# SEED engenharia — Data Visualization v0.22

> **Estado:** **FASE 5 CONCLUÍDA.** Os seis sub-blocos — **DF** (fundamento), **DT** (tokens de
> dado), **DG** (gráficos core), **DM** (monitoramento), **DI** (impresso e integração) e **DP**
> (mapas) — são todos **`estável`**. DF e DT foram promovidos em 2026-08-09 após o "aprovo" do Rafael no gate do
> preview `seed-dataviz-tokens-preview.html` v0.2; **DG foi promovido no mesmo dia**, após o gate
> do `seed-dataviz-graficos-preview.html` v0.5 — e **recebeu em 2026-08-10 o redesenho
> DG14–DG17** ("gráfico de produto, não de relatório"), aprovado em gate visual sobre o preview
> **v1.2** e formalizado nesta versão. O sub-bloco **DM (monitoramento)** teve o preview **v0.7**
> aprovado no mesmo gate de 2026-08-10 ("acredito que agora esteja tudo ok"); a spec foi escrita
> na v0.5 e o DM é **`estável` desde 2026-08-11**, por "aprovo" explícito do Rafael sobre o lote
> de formalização. O sub-bloco **DI** (impresso/PDF + integração da stack) entra nesta versão
> em **duas partes, ambas agora `estável`**: **DI-a** (DI1–DI2, DI4–DI19) e **DI-b** (DI3 — o
> veredito do gatilho da textura no papel), fechado em 2026-08-11 por prova impressa física.
> O sub-bloco **DP** (mapas de atuação MG-ES-BA) — o **último** dos seis — é **`estável` desde
> 2026-08-11**, por aprovação do Rafael no gate visual sobre o preview
> `seed-dataviz-dp-preview.html` (§4d, DP1–DP14). **COM ELE, A FASE 5 ESTÁ FECHADA:** os seis
> sub-blocos DF · DT · DG · DM · DI · DP são todos `estável`, e o marco **v1.6** é disparado.
>
> **O gate do DG levou o preview da v0.1 à v0.5; o gate do redesenho + DM levou de novo, da v0.6
> à v1.2 (gráficos) e da v0.1 à v0.7 (monitoramento).** Os números não são sinal de
> desorganização — são o registro de que a régua foi corrigida enquanto era aplicada. Os achados
> que mais mudaram o resultado vieram do OLHO do Rafael, não da automação: o colapso das séries
> em escala de cinza no modo escuro (DG13), o ar de "relatório antigo" do contorno universal
> (→DG14), a paleta que "parecia escalas da mesma cor" (→categórica estendida v1.5) e as bandas
> do medidor indistintas mesmo acima do piso do instrumento (→DM3/DM11).
> **Data:** 2026-08-09 · **Editado:** 2026-08-11 (v0.5 lote de formalização · v0.6 promoção do
> DM a `estável` + P6 fechada + erratas E1–E6 medidas · v0.7 as seis erratas CORRIGIDAS nos
> previews, que passam a v1.3/v0.8 · v0.8 gate visual aprovado nesses previews ·
> v0.9 sub-bloco DI escrito, com SUPERSEDE do gatilho do DG13 medido ·
> **v0.10 lote de produção do DI-a: vocabulário de textura estendido a 6, oito erratas
> E9–E16, preview do DG a v1.4 e a guarda de textura que faltava** · v0.11 DI4 medido e suíte do
> DI · v0.12 DI-b fechado por prova impressa e supersede da regra do piso · v0.13 supersede do
> DM8 · **v0.14 spec do sub-bloco DP — mapas — em §4d** · **v0.15 medição do DP: dois tokens novos, erratas E19/E20 e DP-P1 fechada** · **v0.19 malha real do IBGE · v0.20 gate visual do preview v0.4 aprovado, DP sem pendências** · **v0.16 gate visual: a dimensão largura da matriz de render nunca havia sido exercida** · **v0.17 a camada de RENDER é executada pela primeira vez no DP e acha uma violação do DG12**) · **Fase:** 5
> **Escopo desta versão:** as 7 decisões de fundamento (DF1–DF7, §2) · o registro do sub-bloco DT
> (§3), cujos VALORES vivem no `seed-tokens.md` **v1.5** §3c — este arquivo referencia, nunca
> duplica (DF7) · as **13 decisões originais do DG mais o redesenho DG14–DG17** (§4), cobrindo
> sete tipos de gráfico (barra, empilhada, agrupada, linha, área, pizza, dispersão), os três
> estados e os formatos novos gated em 2026-08-10 · e a **spec do sub-bloco DM** (§4b, DM1–DM11:
> bullet graph, sparkline, gráfico do alerta ET5) · e a **spec do sub-bloco DI** (§4c,
> DI1–DI19: destino do impresso, supersede do gatilho da textura, folha de estilo de
> impressão, CMYK e formato de arquivo, guia de integração da stack, reescrita do
> `contraste-dg.py` e o slot ET5). E a **spec do sub-bloco DP** (§4d, DP1–DP14: mapa como gráfico, consumidor técnico,
os três estados do território, fronteira, malha, piso, projeção, fonte e simplificação da
geometria, marcador, LGPD, impresso e o coropleto documentado). **Com o DP escrito, os seis
sub-blocos da Fase 5 existem;** falta apenas o gate visual do DP para fechar a fase.

---

## 0. Contexto para quem nunca viu a conversa que gerou este arquivo

A **SEED engenharia** é um HUB de engenharia elétrica que atua em Minas Gerais, Espírito
Santo e Bahia desde 2016. Cinco pilares: energia solar fotovoltaica, subestações de média
tensão, grupos geradores (GMG), projetos elétricos e consultorias. Ferramenta proprietária:
o **Diagnóstico 360°**. A produção da empresa é pesada em **gráficos, tabelas e relatórios
complexos** (monitoramento de usinas, faturas de energia, laudos, relatórios de O&M) — foi
por esse perfil que o roadmap classificou a dataviz como **prioridade elevada**.

O **Design System v2 (DS v2)** é o sistema canônico permanente que serve todos os outputs
da empresa. Fases já concluídas: 1 (tokens, `seed-tokens.md` v1.4) · 2 (marca,
`marca-seed.md` v5.0) · 3 (44 componentes em 7 blocos, `seed-componentes.md` v0.47) ·
4 (sistema de e-mail, `seed-email.md` v0.11). **Este arquivo abre a Fase 5** e é o
**9º arquivo canônico** do Project Knowledge.

**Convenção de leitura.** Decisões têm código de duas letras + número (`DF1`, `DG3`). Toda
decisão traz **racional** e **alternativas descartadas** — regra do projeto: decisão sem
alternativa descartada registrada não é decisão, é preferência. Substituição de conteúdo é
**supersede formal**, nunca nota solta. Nada é promovido a `estável` sem "aprovo" explícito
do Rafael após gate visual.

### Estrutura da fase (aprovada pelo Rafael em 2026-08-09)

| # | Sub-bloco | Escopo | Estado |
|---|---|---|---|
| DF | Fundamento | As 7 decisões estruturais deste arquivo | **`estável`** (2026-08-09) |
| DT | Tokens de dado | Escalas v1.3: sequencial · divergente · gauge · strokes | **`estável`** (2026-08-09) |
| DG | Gráficos core | 7 tipos + 3 estados; 13 decisões + redesenho DG14–DG17 (§4) | **`estável`** (2026-08-09; redesenho gated 2026-08-10, formalizado na v0.5) |
| DM | Monitoramento | Bullet graph/medidor · sparklines (tabelas §40 do ERP) · gráfico do alerta de geração (fecha o slot ET5) — DM1–DM11 (§4b) | **`estável`** (2026-08-11) |
| DP | Mapas | Diretriz MG-ES-BA (usinas/obras) | não escrito |
| DI | Impresso/PDF + integração | Grayscale/hachura para laudo e O&M (ponte para a F7) · guia de integração da stack — DI1–DI19 (§4c) | **`estável`** (2026-08-11) — DI-a e DI-b, o segundo fechado por prova impressa física |

Ordem de produção: DF → DT → DG → DM → **DI** → DP. **A ordem declarada originalmente punha
DP antes do DI; foi invertida pelo Rafael em 2026-08-11, com racional registrado: o DI tinha
pendências represadas desde o DT e desbloqueia o ERP, enquanto o DP não desbloqueia nada.**
Concluídos: DF, DT, DG, DM e **DI inteiro**. Resta o **DP** para fechar o marco da Fase 5.

---

## 1. A tese: cor de dado não é cor de UI

A regra-mãe do `seed-componentes.md` é "componente consome semântico, nunca hex" — e o
semântico de UI carrega **intenção de interface** (`action-primary`, `feedback-danger`).
Uma série de gráfico não tem intenção de interface: a série 2 de um gráfico de barras não é
"ação" nem "erro" — é a **segunda categoria de um dado**. Ela consome uma escala com
semântica própria (`chart-cat-2`), cujas leis são outras: ordem fixa, diferenciação
perceptual entre vizinhas, comportamento sob grayscale, isenções normativas específicas
(WCAG 1.4.11 isenta heatmap; nenhum componente de UI tem isenção equivalente).

Hospedar essas leis dentro do arquivo de componentes criaria a mesma contaminação de
regra-mãe que o e-mail teria criado (EM0 do `seed-email.md`) — por isso este arquivo
existe (DF1).

**O que a dataviz herda das fases anteriores — e o que não herda:**

| Herda-se | Não se herda |
|---|---|
| Cadeia de 3 camadas (primitivo → semântico de dado → consumo) | Semânticos de UI (`action-*`, `feedback-*`) como cor de série |
| Escada de mecanismos do §1.12 (cor nunca é o único portador) | — |
| Taxonomia de severidade T1–T5 (faixas de gauge referenciam feedback) | Severidade paralela nova |
| Método dos 7 testes + grayscale (aqui promovido a gate estrutural, DF4) | — |
| Tabela de dados semântica EC3/§40 (é o fallback textual canônico) | — |
| Régua de validação em camadas (jsdom + render + contraste + gate humano) | A régua da F4 (motor Word não é o alvo aqui) |

---

## 2. Decisões de fundamento — DF1–DF7 (consolidado aprovado em 2026-08-09)

### DF1 — Por que arquivo canônico próprio

**Decisão:** a dataviz vive em `seed-dataviz.md`, 9º arquivo canônico. O PK passa de 8
para 9 arquivos.

**Racional:** cor de dado não é cor de UI (§1) — regra-mãe própria em conflito direto com
a do `seed-componentes.md`, que além disso já tem 341 KB. Precedente duplo do projeto:
EM0 (e-mail virou canônico próprio pela mesma classe de conflito) e NM5 (iconografia
declarou que expansão de domínio gera arquivo próprio por supersede formal).

**Alternativas descartadas:**
- *Seções novas no `seed-componentes.md`* — contamina a regra-mãe "componente consome
  semântico"; todo leitor futuro passaria a duvidar dela.
- *Fatiar entre `seed-tokens.md` e `seed-componentes.md`* — fragmenta a fonte de verdade
  do domínio; ninguém saberia onde a lei mora.

### DF2 — Canônico agnóstico; consumidor canônico web = shadcn Chart sobre Recharts v3

**Decisão:** este arquivo especifica **anatomia e regras** de forma agnóstica de
biblioteca. O consumidor canônico web é o componente **Chart do shadcn/ui**, construído
sobre **Recharts v3**, consumindo a cadeia `--seed-chart-*` → aliases `--chart-N` do
shadcn — o mesmo padrão GI1 que o Bloco 6 formalizou para os componentes.

**Racional (fatos da rodada de mercado, 2026-08-09):** o shadcn/ui mantém componente
Chart oficial sobre Recharts, com theming nativo por CSS variables, e declara
explicitamente que não embrulha o Recharts — sem lock-in de abstração; upgrade segue o
caminho oficial da lib. Detalhe técnico que o guia de integração (DI) deve gravar: na
migração para Recharts v3, a referência de token mudou para `var(--chart-N)` direto,
**sem** o wrapper `hsl()` antigo. A stack real dos produtos (Lovable = Vite + React +
Tailwind + shadcn) já contém tudo isso.

**Alternativas descartadas:**
- *Especificar EM Recharts* — acopla o canônico à biblioteca; o canônico deve sobreviver
  à troca de lib.
- *D3 puro* — poder máximo que os tipos core não exigem; custo de manutenção real.
- *Chart.js* — fora da stack shadcn/Lovable; obrigaria ponte de theming paralela.

### DF3 — Régua de acessibilidade da fase (4 pisos, todos medidos)

**Decisão:** todo entregável da F5 passa por quatro pisos:

1. **1.4.1 (uso de cor):** cor nunca é o único portador — série se distingue também por
   forma de marcador, espessura ou tracejado; estado (positivo/negativo) também por
   posição, seta ou rótulo. É a escada de mecanismos do §1.12 aplicada ao dado.
2. **1.4.11 (contraste não-textual):** **3:1 medido por script** para elemento de dado
   contra o fundo e para séries/fatias adjacentes entre si (ou borda separadora).
   **Isenção declarada para a escala sequencial/heatmap** — a própria norma isenta
   situações onde mudar a cor muda o significado, com heatmap como exemplo nomeado.
   A isenção tem condições de acompanhamento e gatilho de revisão registrados no
   `seed-tokens.md` v1.4 §3c.
3. **1.4.3 (texto):** rótulo, eixo e legenda ≥4.5:1 — pares aprovados na §3c.
4. **1.1.1 (alternativa):** todo gráfico tem fallback textual — tabela de dados
   semântica (herda EC3 do e-mail e o §40 da web) ou sumário textual do achado.

**Alternativas descartadas:** confiar na percepção sem medir (a errata do rodapé do
e-mail provou o perigo: 4.37 parecia bom e reprovava) · exigir 3:1 dentro da rampa
sequencial (impossível numa escala contínua — a norma mesma isenta).

### DF4 — Grayscale é gate estrutural, não só teste

**Decisão:** todo gráfico canônico deve permanecer **legível em preto-e-branco**. O
preview de cada sub-bloco carrega um modo grayscale acionável, e o gate visual do Rafael
inclui a prova P&B.

**Racional:** serve dois senhores de uma vez — o "aperto de olhos" do método §1.12 e o
impresso da F7 (laudo e relatório de O&M saem em P&B); o sub-bloco DI herda gráficos que
já degradam bem em vez de retrofitar.

**Alternativa descartada:** tratar impresso como retrofit no DI — produziria uma fase
inteira de gráficos web que não degradam.

### DF5 — Régua de validação: 4 camadas

| Camada | O que mede aqui |
|---|---|
| **Estática/jsdom** | Estrutura do SVG, ARIA (role, título/descrição acessível), presença do fallback textual, tokens fantasma |
| **Render (Chrome headless)** | **Volta a protagonista**: geometria real — colisão de rótulos, overflow de legenda a 360px, recorte, cor renderizada |
| **Contraste por script** | `contraste-dataviz.py` sobre as escalas v1.3 e os pares de cada gráfico |
| **Gate visual (Rafael)** | Percepção: grayscale, zoom, "isso conta a história certa?" — não-opcional |

**Racional:** diferente da F4 (Chrome headless não provava nada sobre o motor Word),
gráfico é SVG no navegador — exatamente o território da `suite-render.mjs`, a camada que
pegou os 2 bugs reais do Bloco 6 antes do gate. A lição permanente do projeto se mantém:
suite valida comportamento, geometria é render, percepção é o olho humano.

**Alternativas descartadas:** herdar a régua da F4 (alvo errado) · pular a camada de
render (histórico contra).

### DF6 — Fronteiras declaradas

- **Dashboard/layout de painel = F6.** O shell consome os gráficos daqui; a F5 entrega a
  peça, não o painel.
- **Tempo real, websocket, persistência = produto** (Lovable/Supabase), fora do DS.
- **BI exploratório ad-hoc = fora de escopo** (revisável).
- **Gráfico em e-mail = PNG @2x gerado e hospedado no R2** — o runtime de e-mail não roda
  JS; herda EM5 (SVG proibido) e EM11 (caminho imutável). É assim que o slot do alerta de
  geração (ET5) será servido quando o DM o preencher.

**Racional:** fronteira não-declarada vira expectativa quebrada — lição de todas as fases.
**Alternativas descartadas:** incluir dashboard na F5 (duplicaria o shell da F6) · SVG no
e-mail (proibido pela EM5).

### DF7 — Tokens de dado têm UMA fonte

**Decisão:** os valores das escalas vivem no `seed-tokens.md` (v1.4, §3c) — que é editado
na F5 e, pela regra GI2, fechou na mesma edição a errata aberta do §5 (par info). Este
arquivo **referencia** a §3c e registra as **regras de consumo**; nunca duplica hex.

**Racional:** paleta duplicada = deriva garantida (mesmo racional do EM1 do e-mail — que
resolve por *resolução* porque aquele runtime não tem variável; aqui o runtime tem, então
a resposta é *referência*).

**Alternativa descartada:** tabela espelhada aqui — o problema que o DS existe para matar.

---

## 3. Sub-bloco DT — tokens de dado (registro; valores na §3c do `seed-tokens.md` v1.5)

> **Nota da v0.5:** a §3c ganhou em 2026-08-11 a **categórica ESTENDIDA v1.5** (supersede da
> categórica v1.0 e da restrição "nenhum hex novo"): 2 matizes exclusivos de dado (magenta,
> violeta), sequência de 5 famílias, `cat-1` → turquesa-500, regra do dourado, cinza fora da
> categórica. Os VALORES e medições estão lá (DF7); as **leis de consumo** estão aqui, na
> §4.6. Tudo do DT original (sequencial, no-data, divergente, gauge, strokes) permanece
> `estável` e intocado.

**O que o DT entregou (2026-08-09):**

- **Sequencial** `chart-seq-1…7` — rampa turquesa em 7 classes, **escala final 100→900
  light / 800→100 dark**. A escala decidiu-se NO GATE: a proposta original (50→800)
  foi reprovada pelo Rafael porque os stops 50/100 **liam como cinza** em tela —
  ambíguos com "sem dado" — e a opção A (deslocar um stop) foi aprovada sobre preview
  comparativo em 2026-08-09. Supersede formal e medições na §3c do `seed-tokens.md`.
  Isenção 1.4.11 declarada com condições de acompanhamento (rótulo/tooltip/tabela ·
  fronteira por `chart-grid` · legenda com limites) e gatilho de revisão.
- **Sem dado** `chart-no-data` — nasce do mesmo achado do gate: cinza (100/800) agora é
  EXCLUSIVO de "sem medição" em gráfico SEED, **sempre com hachura diagonal** (a
  distinção "gerou pouco × não reportou" nunca depende de cor — 1.4.1, grayscale e
  impresso de graça). Legenda ganha o item "sem medição" quando houver célula no-data.
- **Divergente** `chart-div-neg-3…pos-3` — vermelho↔cinza↔turquesa, alinhada por
  construção ao par `chart-positive/negative` da v1.0 (os stops ±2 SÃO turquesa-500 e
  vermelho-500). Posições plenas passam 3:1 medido nos dois modos; **regra da zona-zero**
  declarada (±1/zero aproximam o fundo por semântica — dado que precisa se distinguir
  nunca as usa sozinho).
- **Gauge** `gauge-track/value/range-*` — faixas **referenciam a taxonomia de feedback**
  (nenhuma severidade paralela, lei do Bloco 3).
- **Stroke da categórica** `cat-N-stroke` — variante para traço fino (linha ≤3px,
  marcador pequeno), nascida de remedição que reprovou cat-1/2/5 no pior caso; o fill
  v1.0 fica intocado. Regra de consumo: linha/sparkline = stroke; barra/área/fatia = fill.

**Os dois achados de medição do lote (registro de método):** o script reprovou a proposta
original em dois pontos antes de qualquer spec — gauge warning light (dourado-500, 2.35
contra a trilha → corrigido para dourado-600, 3.25) e gauge critical dark (vermelho-400,
2.38 → corrigido para vermelho-300, 3.26). Nenhum hex novo foi criado em toda a entrega:
só stops existentes das rampas §2.1.

**Validação executada:** `contraste-dataviz.py` (camada de contraste da F5) — errata §5
resolvida com número (azul-700=5.79 confirmado; par semântico real azul-800=8.57 AAA),
escalas medidas nos dois modos, gauge e strokes com todos os gates PASS após a iteração 2.

**Preview do gate:** `seed-dataviz-tokens-preview.html` v0.2 — escala A com o bloco
comparativo da proposta rejeitada (memória visual do achado), no-data hachurado demonstrado
no heatmap, barra divergente, gauge com as 3 faixas, fill×stroke em traço fino, e o **modo
grayscale acionável** (DF4). Nenhum botão morto.

**Balanço FECHADO do ciclo de gate do DT:** 1 defeito real encontrado pelo olho do
Rafael (a escala-cinza — invisível às três camadas automatizadas, que mediam razões e não
percepção de hue) → 1 correção estrutural (escala A) + 1 token novo (`no-data`). O padrão
das fases anteriores se repete: a automação é o piso, o olho é o juiz.

**Veredito do gate (2026-08-09):** "aprovo" explícito do Rafael sobre o preview v0.2
completo, em segunda rodada — a primeira rodada tinha aprovado só a escala A sobre o
preview comparativo, e o veredito do preview inteiro ficou pendente até esta data. Com o
aprovo, **DF e DT passam a `estável`** e este arquivo vai a v0.3. Registro de método: o
projeto distingue "aprovo de item" (a escala) de "aprovo de gate" (o preview completo) —
só o segundo promove, e a distinção existe porque um item corrigido pode quebrar outro
ponto da mesma tela.

**Reprodução independente da validação na janela da promoção (2026-08-09):**
`contraste-dataviz.py` foi re-executado sobre os mesmos hex e reproduziu **29 PASS · 3
FAIL**, sendo os 3 FAILs exatamente os documentados — `cat-1` (2.71), `cat-2` (1.85) e
`cat-5` (2.53) do **fill** em traço fino, que são a própria razão de existir da variante
`cat-N-stroke`. Nenhum número da §3c divergiu. Fato, não inferência: os valores da §3c
foram cruzados linha a linha contra os hex efetivamente gravados nos gêmeos —
**26/26 batem, 0 divergências**.

---

## 4. Sub-bloco DG — gráficos core (13 decisões + redesenho DG14–DG17; `estável` em 2026-08-09)

> **O que é o DG.** O sub-bloco que especifica os **sete tipos de gráfico** que a SEED usa no
> dia a dia — barra, barra empilhada, barra agrupada, linha, área, pizza e dispersão — mais os
> três estados (carregando, vazio, erro). Não especifica painel (isso é F6), gauge nem sparkline
> (DM), mapa (DP) nem impresso (DI).
>
> **Consolidado aprovado pelo Rafael em 2026-08-09**, após três rodadas encadeadas de pesquisa
> (R1 canon interno · R2 mercado e stack · R3 normas e fora-do-circuito) e **duas emendas feitas
> durante a produção**: a barra empilhada foi puxada para dentro do escopo a pedido do Rafael
> (o caso real: consumo por posto tarifário), e o DG13 nasceu do gate visual.
>
> **Artefatos:** `seed-dataviz-graficos-preview.html` — **v1.2** (82.126 B, md5
> `8d1930598b9d124d3807fc80f70b0fbf`) é o artefato do gate de 2026-08-10, reanexado e conferido
> por MD5 em 2026-08-11 (P6); a **v1.3** corrige as erratas E4/E5/E6 e **aguarda gate** ·
> `validacao/suite-dataviz-dg.mjs` — **163 PASS · 0 FAIL, RE-EXECUTADA em 2026-08-11 contra o
> artefato reanexado** (o placar do gate deixou de ser reprodução e passou a ser execução) ·
> `validacao/contraste-dg.py` ⚠ **desatualizado** (ainda mede DG11 e a paleta antiga —
> atualizar na próxima edição) · `validacao/render-dg.mjs` (6 cenários, puppeteer).

### 4.1 Anatomia e acesso

**DG1 — invólucro canônico obrigatório.** Todo gráfico SEED é um `<figure>` com cinco partes:
**(a)** título visível em `figcaption`; **(b)** descrição curta que identifica o gráfico e diz onde
está a longa; **(c)** **fallback textual sempre presente** — tabela semântica (herda §40 do
`seed-componentes.md`: `caption`, `th scope`, numérico em mono à direita, célula vazia como `—`)
ou sumário do achado, dentro de `<details>` quando ocupar espaço; **(d)** legenda; **(e)** a área
do gráfico, com `role="img"` e `aria-labelledby` apontando para (a) e (b). Sem as cinco, não é
gráfico canônico.

*Racional:* o W3C classifica gráfico como **imagem complexa** e exige alternativa textual em duas
partes — curta que identifica, longa que representa a informação essencial. E a auditoria pública
do shadcn Charts (2024) reprovou a biblioteca em 1.1.1 (os gráficos testados não entregam
alternativa textual: o leitor de tela recebe só rótulos de eixo e, às vezes, o tooltip) e em 1.3.1
(a legenda não tem relação codificada com o gráfico). *Alternativa descartada:* tratar o
`accessibilityLayer` do Recharts como cumprimento do 1.1.1 — há evidência pública em contrário.

**DG2 — teclado: um único tab-stop, depois setas.** O gráfico inteiro é **um** ponto de parada na
tabulação; dentro dele, `←` `→` percorrem os pontos e `Home`/`End` vão aos extremos, com cada
movimento anunciado em região `aria-live`. Nenhum ponto de dado é focável individualmente.

*Racional:* é o padrão do APG e a posição oficial da própria biblioteca — se cada elemento virasse
tab-stop, quem não se importa com o gráfico teria de tabular por todos os pontos.
**Risco declarado e NÃO resolvido:** em modo de navegação, JAWS e NVDA interceptam as setas antes
da página; o Recharts contorna com `role="application"`, e o VoiceOver não tem equivalente. Por
isso **o teclado é enriquecimento, não o caminho de acesso** — quem garante o acesso é o fallback
textual do DG1.

### 4.2 Escolha do tipo e honestidade do eixo

**DG3 — uma pergunta por gráfico.** Barra = comparar categorias · barra empilhada = total **e**
composição · barra agrupada = comparar um subgrupo entre categorias · linha = tendência no tempo ·
área = tendência **com magnitude** · pizza = parte-do-todo num instante · dispersão = correlação
entre duas variáveis. Gráfico que responde duas perguntas vira dois gráficos.

**DG4 — eixo zero é regra dura ASSIMÉTRICA.** Barra e área **sempre** partem do zero, sem exceção.
Linha **pode** truncar, sob três condições cumulativas: eixo rotulado, valor mínimo explícito e
**marca visual de truncamento**.

*Racional:* é geometria, não estilo — comprimento e área codificam o valor diretamente, então
truncar mente; a linha codifica por posição e inclinação, então truncar acima de zero não quebra a
leitura. *Alternativa descartada:* proibir truncamento em linha — cegaria justamente o que a SEED
mais precisa ver (PR de usina e tensão de rede variam pouco e importam muito). *Também descartada:*
permitir truncamento em barra — desonesto por construção.

**DG5 — pizza com oito travas.** Só parte-do-todo somando 100% · **máximo 5 fatias**, resto em
"Outros" nomeado · nunca 3D, nunca fatia explodida · maior fatia às 12h, sentido horário ·
**valor sempre rotulado**, sem depender de legenda ou hover · fatias adjacentes com menos de
**5 pontos percentuais** de diferença → vira barra ordenada · dado ordinal ou sequencial → vira
barra empilhada · valor negativo → nunca pizza. Donut é variante permitida quando o centro carrega
o número.

*Racional:* limite cognitivo documentado de 5–6 itens comparados simultaneamente; a regra dos 5
p.p. para distinção visual; e o corte semântico do dado ordinal. *Alternativa descartada:* banir
pizza — o público de proposta e laudo lê pizza, e banir empurraria o consumidor para fora do DS,
o que é pior do que usá-la com regra.

**DG5-b — rótulo dentro da fatia é condicional, e a condição é medida.** A tinta do rótulo interno
é escolhida pelo maior contraste contra o **fill**; se nenhuma opção atingir 4,5, o rótulo vai para
**fora, com linha-guia**. ~~Medido na §3c: sobre `cat-1` a tinta escura dá 5,11 e sobre `cat-2` dá
7,48 (ambas entram); sobre `cat-3` nenhuma tinta atinge 4,5 (branco 3,32 · escura 4,17), logo a
fatia `cat-3` sempre leva rótulo externo.~~

> **REMEDIÇÃO da v0.5 (paleta categórica estendida v1.5) — a regra não muda; a tabela de
> resultados sim.** Tinta escura (`cinza-900`) sobre os fills light novos: `cat-1` **4,30**
> (reprova o piso 4,5 — na paleta antiga dava 5,11) · `cat-2` 7,48 ✓ · `cat-3` 3,40 ✗ ·
> `cat-4` 4,17 ✗ · `cat-5` 3,43 ✗ · `cat-6` 1,46 ✗, **mas branco sobre `cat-6` mede 9,52 ✓**.
> Resultado vigente: **rótulo interno só em `cat-2` (tinta escura) e `cat-6` (tinta branca)**;
> todas as demais fatias levam rótulo externo com linha-guia. **Errata aberta contra o preview
> v1.2:** a pizza aprovada no gate mostra o rótulo "45%" interno sobre `cat-1` a 4,30 —
> defeito latente que a formalização encontrou; corrigir quando o preview for editado. A
> regra provou funcionar exatamente como desenhada: condicional e medida, ela absorve a troca
> de paleta sem supersede.

### 4.3 Empilhada e agrupada (DG10)

**DG10-a — uso.** Empilhada só quando **total e composição importam juntos**. Se só a composição
importa, é pizza com regras (DG5). Se importa comparar **um subgrupo específico** entre categorias,
é **agrupada** — que entra como variante irmã, não como alternativa de gosto.
*Racional:* só o segmento da base fica sobre a linha de zero comum; os de cima flutuam.

**DG10-b — máximo 4 segmentos**, resto em "Outros" nomeado. ~~*Aperto deliberado sobre os 5 do
mercado, por motivo interno:* acima de 4, a categórica SEED começa a parear matizes da mesma
família (dois dourados, duas turquesas), e segmento preenchido não carrega tracejado para
desambiguar — o teto é fato de paleta, não preferência.~~

> **Nota da v0.5 — o RACIONAL foi supersedido; o TETO permanece.** Com a categórica estendida
> v1.5, as posições 1–5 são famílias todas distintas — o "fato de paleta" que sustentava o
> teto deixou de existir. O teto de 4 **continua vigente** porque nenhum gate o reavaliou
> (mudar limite aprovado sem gate seria decisão inventada); os motivos remanescentes são os
> do mercado (limite cognitivo de comparação em pilha). **Pendência registrada no §5:**
> reavaliar o teto (4→5) quando um caso real do ERP pedir 5 segmentos, com preview e gate.

**DG10-c — ordem de empilhamento fixa**, idêntica em todos os gráficos da mesma família, com o
segmento mais importante na **base**; toda barra contém os mesmos componentes (se uma barra tem um
componente que a outra não tem, a comparação quebra).

**DG10-d — SUPERSEDIDO pelo DG11.** Ver §5.

**DG10-e — legenda permitida na empilhada**, exceção explícita ao DG7: com 4 segmentos o rótulo
direto não cabe dentro da faixa. O fallback textual leva uma coluna por segmento **mais coluna
Total**. Na agrupada, o total **não** é exibido — ela responde outra pergunta.

### 4.4 Fronteira, tinta e textura — as três regras que a medição criou

> As três nasceram **durante a validação**, não do consolidado. São o registro de que a camada
> automatizada e o gate humano acharam o que a pesquisa não anteciparia.

**DG11 — SUPERSEDIDO pelo DG14 (§4.6) em 2026-08-10.** ~~Toda superfície de área opaca leva
contorno de 1px em `cinza-900`.~~ O contorno universal viveu um dia: aprovado no gate de
2026-08-09, foi reprovado pelo OLHO do Rafael no gate seguinte ("ar de relatório antigo",
crítica de estética de produto sobre o preview v0.6+). O problema que o DG11 resolvia —
fill que reprova 3:1 sozinho contra o fundo — foi re-resolvido pela raiz: a categórica
estendida v1.5 tem **todos os fills ≥3,22 contra o fundo** (única exceção: dourado, com regra
própria), o que dispensa a fronteira desenhada. O texto original permanece abaixo como
registro do racional:

*Racional medido (histórico):* o fill categórico v1.0 reprovava 1.4.11 sozinho contra o fundo
claro — `cat-1` 2,71 · `cat-2` 1,85 · `cat-5` 2,53. *Alternativa descartada com número:*
contorno na variante `-stroke` da própria série — `cat-2-stroke` contra `cat-1` media **1,28**,
não separava vizinho. O `cinza-900` foi a única cor testada que atingia ≥3 contra todos os
fills nos dois modos (mínimo 4,17). A cadeia completa de supersedes está no §6:
**DG10-d → DG11 → DG14**.

**DG12 — tinta sobre dado não segue o tema.** Rótulo interno ~~e contorno~~ usa o primitivo
`cinza-900` em light **e** em dark. É exceção declarada à regra "componente consome semântico".
*(Emenda da v0.5: "e contorno" morreu junto com o DG11/DG14 — sobrou o rótulo interno como
único consumidor da regra nos gráficos core. A regra em si permanece viva e testada na suite.)*

*Racional:* a regra existe para que o tema funcione — mas o objeto contrastado aqui é o **fill
categórico**, que é claro nos dois modos (`cat-2` é literalmente o mesmo hex). Uma tinta que
inverte com o tema erra em um dos lados por construção.

> **Exceção declarada ao DG12, nascida no DM (2026-08-10):** no medidor, a tinta da **marca de
> meta** ACOMPANHA a superfície (`cinza-900` no light, `cinza-100` no dark). Motivo medido: as
> bandas do medidor **invertem com o tema** (DM3 — cinza claro no light, cinza escuro no dark),
> então o objeto contrastado não é claro nos dois modos como o fill categórico; a tinta fixa
> erraria no dark por construção. Pior caso medido: 7,07 (light) · 3,93 (dark), ambos ≥3.
> O DG12 vale onde o objeto é estável entre temas; onde o objeto inverte, a tinta inverte junto.

**DG13 — textura por série.** *(Gatilho supersedido pelo DI2 — ver emenda da v0.9 ao fim
desta seção. O vocabulário abaixo permanece vivo e foi ESTENDIDO na v0.10.)*

**Vocabulário — 6 posições, uma por série do teto:**

| Série | Textura |
|---|---|
| 1 | sólida (ausência de textura é o próprio sinal) |
| 2 | pontilhada |
| 3 | quadriculada |
| 4 | linhas horizontais |
| **5** | **linhas verticais** *(novo na v0.10)* |
| **6** | **diagonal a 135°** *(novo na v0.10)* |

A **hachura diagonal a 45° não entra no vocabulário** — fica reservada ao `chart-no-data`,
estendendo a exclusividade que a §3c deu ao cinza de "sem medição". A legenda repete a
textura sob o **mesmo** gatilho, senão os quadradinhos mentem sobre o gráfico. Gráfico de
série única não leva textura.

> **Emenda da v0.10 — a lacuna das posições 5 e 6.** O vocabulário nasceu com **quatro**
> texturas enquanto o teto de séries sempre foi **seis**. A lacuna era invisível porque o
> gatilho antigo (escuro ∩ grayscale) nunca foi exercido contra um gráfico de 5 ou 6 séries:
> o único que existe no preview — a pizza de 5 — estava sem textura nenhuma, o que é a
> errata **E11**. Com o DI2, gráficos de 4+ séries passam a texturizar também no claro, e a
> falta apareceu. *Racional das duas escolhas, aprovadas no gate de 2026-08-11:* **linhas
> verticais** para a 5, porque é a rotação de 90° da textura 4 e nenhuma das duas se
> confunde com as demais; **diagonal a 135°** para a 6, distinta da diagonal a 45° do
> `chart-no-data` **por direção**, o que preserva a exclusividade que faz "sem medição"
> nunca ser lido como categoria. *Alternativas descartadas:* diagonal a 45° com espaçamento
> diferente — a distinção viraria densidade, frágil no papel e pior ainda em fotocópia,
> exatamente onde o no-data mais precisa ser inconfundível; pontos maiores para a 5 — lê
> como a textura 2 vista de perto.

*Origem — gate visual do Rafael:* ele ligou grayscale no modo escuro e disse que "parece tudo
igual". Estava certo.

*Racional, com a correção de instrumento que o gate forçou:* a primeira medição usou **razão de
contraste WCAG** entre as séries convertidas para cinza e reprovava também o modo claro
(`cat-1` × `cat-3` = 1,22) — o que teria levado a texturizar tudo. Razão de contraste é a métrica
**errada** aqui: foi calibrada para texto sobre fundo, não para faixas grandes adjacentes separadas
por contorno. A métrica que discrimina faixa é o **espalhamento de claridade** do cinza resultante:

⚠ **Tabela histórica — três séries da categórica v1.0.** O veredito "a cor basta no claro" vale
somente até **três** séries; com a categórica v1.5 e seis posições ele é falso, e o gatilho foi
supersedido pelo **DI2** (§4c.2). A tabela permanece como registro do racional que criou o DG13.

| Modo | `cat-1` | `cat-2` | `cat-3` | menor distância | veredito |
|---|---:|---:|---:|---:|---|
| Claro | 62% | 75% | 55% | **7 pontos** | a cor basta; textura seria ruído |
| Escuro | 75% | 75% | 71% | **0 pontos** | textura obrigatória |

O colapso é da **rampa escura**, não do grayscale em si — por isso a textura é remédio local, e o
gatilho é a interseção, não o "ou". O piso de **6 pontos** está no `contraste-dg.py` declarado como
**calibrado pelo gate, não derivado de norma**, para que ninguém o cite um dia como se fosse WCAG.

> **Emenda da v0.5 — o piso vale só onde foi medido.** No gate do DM (2026-08-10), as bandas do
> medidor distavam **9/8/17 pontos** de claridade — acima do piso de 6 — e o Rafael **não as
> distinguia** ("não consegui perceber a diferença de tonalidade"). O piso foi calibrado em UM
> contexto (barras altas adjacentes, modo claro) e **não transfere** para faixas finas
> empilhadas dentro de um medidor. Regra decorrente: o piso de 6 pontos decide apenas no
> contexto em que foi calibrado; **fora dele, quem decide é o gate** — e cada decisão do gate
> vira número novo, declarado no contexto novo (foi assim que nasceu o DM11). A remedição da
> categórica v1.5 (claridades dark 75/75/71/71/67, vizinhas a 0–4 pontos) confirma: o DG13
> permanece obrigatório com a paleta nova.

> **Emenda da v0.9 — SUPERSEDE do gatilho pelo DI2 (§4c.2).** A remedição da v0.5 acima
> conferiu apenas o **modo escuro** da paleta nova; o modo claro seguiu sendo citado pelos
> **7 pontos** da tabela histórica, que são de **três** séries. Medido em 2026-08-11 no
> sub-bloco DI, com as **seis** posições da v1.5 em modo claro: `cat-1 × cat-4` = **1 ponto**
> e `cat-3 × cat-5` = **1 ponto** (claridades 56/75/49/55/50/27). O claro é seguro **até três
> séries** e colapsa a partir da quarta. O gatilho passa de "escuro ∩ grayscale" para
> **`grayscale ∩ (escuro OU ≥4 séries)`**. O vocabulário de textura, a exclusividade da
> diagonal a 45° para o `chart-no-data`, a repetição na legenda sob o mesmo gatilho e a
> isenção do gráfico de série única permanecem intactos. *Fato de método:* o defeito
> sobreviveu porque o `contraste-dg.py` percorre só `cat1/cat2/cat3` — o detector estava
> recortado exatamente onde o defeito não mora (correção no DI18).

### 4.5 Estados e forma (DG6, DG7, DG8)

**DG6 — os três estados herdam o Bloco 3 com moldura de gráfico.** **Skeleton:** espelha a moldura
real (eixos, base e o mesmo número de barras — S2), shimmer E→D 1,8 s desligado em
`prefers-reduced-motion` (S3), `aria-busy` com o conteúdo visual em `aria-hidden` (S6), timeout de
15 s que vira erro (S5). **Vazio:** pelos 5 tipos do Z1 — zero-resultados **não recebe CTA de
criação**, a ação oferecida mexe no filtro, que é a causa; título de até 5 palavras sem ponto
final e uma ação só (Z2). **Erro:** alerta §15 em `role="alert"`, **no lugar** do gráfico, com
recuperação ("tentar novamente").

**DG6-b — "sem dado" NÃO é estado vazio.** Série ou célula sem medição usa `chart-no-data`
**sempre hachurado**, com o item "sem medição" na legenda e `—` na tabela; o gráfico continua
existindo com as demais séries. A distinção "gerou pouco × não reportou" nunca depende de cor.

**DG7 — rótulo direto vence legenda** até três séries em linha e área; legenda é recurso, não
default. Exceção declarada: DG10-e. *Racional:* a legenda obriga ida-e-volta do olho **e** — pela
auditoria citada no DG1 — sequer tem relação codificada com o gráfico; é elo fraco perceptual e
programático. *(Inferência declarada, não medida.)*

**DG8 — mobile 360 px.** Barra vertical com mais de 5 categorias **vira barra horizontal**; rótulo
de eixo rotacionado é proibido (só o título do eixo pode girar). O container exige altura mínima
declarada — o Chart do shadcn não é responsivo sem ela.

**DG9 — fronteiras.** Gauge e sparkline = **DM** · mapas = **DP** · impresso = **DI** · painel =
**F6**. **Fora da v1 do DG**, registrados: empilhada 100%, waterfall, boxplot, combo de eixo duplo.

### 4.6 Redesenho "gráfico de produto" — DG14–DG17 + duas leis transversais (gate de 2026-08-10)

> **Origem.** Sobre o DG recém-promovido, o Rafael abriu um segundo ciclo com uma crítica de
> ESTÉTICA, não de conformidade: o resultado estava tecnicamente correto e visualmente datado —
> "gráfico de relatório", não "gráfico de produto" (referência apresentada: dashboards no
> padrão do site Viver de IA — cantos suaves, zero contorno, curvas orgânicas, cor limpa).
> O ciclo levou o preview `seed-dataviz-graficos-preview.html` da v0.6 à **v1.2**, com gate
> visual completo (matriz tema × grayscale × viewport cruzada) e "aprovo" em 2026-08-10.
> Nenhuma decisão de CONFORMIDADE do DG1–DG10 mudou; o que mudou foi a camada de desenho —
> e uma decisão de conformidade (DG11) caiu porque a causa raiz dela foi removida.

**DG14 — zero contorno em superfície de dado; fronteira por espaço negativo (SUPERSEDE do
DG11).** Barra, segmento de pilha, fatia e área **não levam contorno**. Na empilhada e na
pizza, segmentos adjacentes separam-se por **vão de 2px** — tecnicamente um `stroke` na cor
do cartão (`surface-raised`), que funciona como espaço negativo: a fronteira é **geometria,
não contraste**, então funciona idêntica em light, dark, grayscale e impresso. *Condição
estrutural que tornou isso possível:* todos os fills da categórica estendida v1.5 passam
3:1 sozinhos contra o fundo (mínimo 3,22; exceção declarada do dourado com regra própria na
§3c) — o `cat-1` mudou de stop exatamente para isso. *Alternativas descartadas:* manter o
contorno só no light (dois desenhos por tema, deriva garantida) · contorno em cor mais suave
(resolve a estética, devolve o problema de contraste que criou o DG11).

**DG15 — geometria orgânica.** Todo retângulo de dado nasce com **canto arredondado `rx=3`**
("nenhum retângulo de dado sai de fábrica com canto vivo"); barra fina de ranking usa
**pílula completa** (`rx` = metade da altura). Linha de tendência usa **curva monótona**
(interpolação Fritsch–Carlson) a 2px — *nunca* spline genérica (Catmull-Rom/natural), que
inventa picos acima dos dados reais e mente sobre máximos; a curva monótona nunca ultrapassa
os valores medidos. Área sob a linha usa **gradiente vertical 22% → 0** da cor da série.
*Racional:* é a gramática visual consolidada de produto (shadcn charts, Tremor, dashboards
modernos); a restrição monótona é o que a torna compatível com a honestidade de eixo do DG4.

**DG15b — guarda do raio consistente (defeito achado pelo OLHO, não pela regex).** Dentro do
mesmo SVG, retângulos da mesma altura usam o mesmo raio. A primeira verificação automatizada
das pílulas casou só 3 de 7 barras (regex fraca); o Rafael apontou a inconsistência no
preview. A suite ganhou o teste DG15b (raio ↔ altura por classe de elemento), permanente.

**DG16 — palco mínimo.** Máximo **3 gridlines** hairline por gráfico; **sem linha de eixo
desenhada** (os rótulos flutuam); o **número é o protagonista** do cartão-KPI (`fs-h2`, peso
800) com rótulo em micro-caps mono; variação em **badge-pílula suave** (fundo
`feedback-*-bg`, texto `feedback-*-text`); ponto de status **sempre com rótulo textual** ao
lado (cor nunca sozinha — 1.4.1, mesma lei de sempre).

**DG17 — destaque × contexto.** Gráfico de série única **pode** realçar 1 categoria em cor
com as demais em `cinza-200` — o cinza aqui é "contexto", não "sem dado" (o no-data continua
exclusivo do hachurado; a distinção é a hachura, testada na suite). Uso canônico: ranking de
usinas com a usina em foco destacada.

**Lei transversal 1 — hierarquia de traço (3 pesos + `non-scaling-stroke`).** DADO = 2px
(linha de tendência, sparkline) · ESTRUTURA = 1px (gridline, trilha; a marca de meta do
medidor usa 1,5px como exceção registrada — precisa vencer a banda atrás dela) · APOIO =
0,5px (linha-guia de rótulo, tick). E **todo SVG de gráfico usa `vector-effect:
non-scaling-stroke`** nos traços. *Racional medido:* os viewBox da suíte de previews escalam
de **0,66× a 12,4×** na tela real — o mesmo `stroke-width="1"` renderizava entre meio pixel
e doze; sem o atributo, a hierarquia de peso é destruída pelo layout responsivo.

**Lei transversal 2 — consumo da categórica estendida (os VALORES estão na §3c; as leis são
estas).** (a) Sequência de entrada fixa: turquesa → dourado → magenta → azul → violeta →
azul-800. (b) **Até 5 séries, as famílias de matiz são todas distintas** — nenhum gráfico
multi-série pareia dois tons da mesma família. (c) A **6ª posição é a única exceção**
(azul-800: mesma família da cat-4, a 28 pontos de claridade no light), e **6 séries é o teto
absoluto** da categórica — acima disso, o gráfico se reestrutura (agrupamento "Outros",
facetas, destaque×contexto DG17). (d) Dourado (`cat-2`): permitido em área grande com rótulo
direto; **vetado como fill solitário sem rótulo** — gráfico de série única nunca nasce em
`cat-2`. (e) Magenta e violeta são exclusivos de dado: aparecerem em UI é defeito, e a suite
não os aceita fora de contexto `chart-*`.

> **Ordem 2↔3 — decisão de gate com racional registrado:** a sequência proposta era
> turquesa → magenta → dourado; o Rafael inverteu para turquesa → **dourado** → magenta
> porque turquesa e magenta são ambos tons médios saturados (56 e 49% de claridade) e liam
> parecidos como vizinhos de pilha — o dourado (75%) entre eles separa por PESO, não só por
> matiz. É a mesma lógica do espalhamento de claridade do DG13, aplicada na ordenação.

---

## 4b. Sub-bloco DM — monitoramento (DM1–DM11, **`estável`** em 2026-08-11)

> **O que é o DM.** O sub-bloco dos objetos de MONITORAMENTO — os que respondem "como está
> AGORA?" em vez de "como se comparam?": o **medidor** (KPI contra meta e faixas), a
> **sparkline** (tendência em espaço mínimo, célula de tabela §40 do ERP) e o **gráfico do
> alerta de geração** (fecha o slot ET5 do `seed-email.md`). Consolidado aprovado pelo Rafael
> em 2026-08-10 após as 3 rodadas de pesquisa do método (R1 canon · R2 mercado/stack ·
> R3 normas — Stephen Few *Bullet Graph Design Specification*, Tufte *Beautiful Evidence*
> sobre sparklines, ARIA `meter` pattern, WAI-ARIA 1.2); preview iterado v0.1 → **v0.7** com
> gate visual completo (matriz cruzada) e fechamento "acredito que agora esteja tudo ok".
>
> **Artefatos:** `seed-dataviz-monitoramento-preview.html` **v0.7** (30.166 B, md5
> `f146c84a3d140a892d1de87ee37d334c`) — reanexado e conferido por MD5 em 2026-08-11, fechando a
> pendência P6; a **v0.8** corrige as erratas E1–E4 e E6 e **aguarda gate** · `validacao/gen-dm.py` (gerador dos fragmentos SVG do preview) ·
> `validacao/render-dm.mjs` (puppeteer, com a guarda de `getBBox`) ·
> `validacao/suite-dataviz-dm.mjs` **v2** — placar oficial contra o artefato do gate:
> **85 PASS · 0 FAIL · 6 FAIL DOCUMENTADO** (as erratas E1–E6 do §5).
>
> **Promovido a `estável` em 2026-08-11**, por "aprovo" explícito do Rafael sobre o lote de
> formalização. O que o "aprovo" cobre: a **spec** (DM1–DM11), os tokens v1.5 que ela consome e a
> suite. O que ele **não** cobre, e por isso permanece aberto no §5: as seis erratas medidas no
> artefato depois do gate. Nenhuma delas altera decisão — a spec é a fonte, o preview é a
> evidência dela, e onde os dois divergem quem manda é a spec.

**DM1 — o medidor canônico é o BULLET GRAPH; gauge circular é exceção declarada.** O medidor
SEED é horizontal, linear, compacto — o bullet graph de Stephen Few. O gauge circular
(velocímetro) só entra como exceção declarada: peça ÚNICA em tela de exibição (TV de sala de
monitoramento), nunca em lista ou comparação. *Racional:* comprimento sobre linha de base é a
codificação perceptual mais precisa (Cleveland–McGill); ângulo é das piores. E o caso real da
SEED é COMPARAR muitas usinas — bullets empilham em lista com rótulos alinhados; velocímetros
não. Um bullet ocupa ~1/8 da área do gauge circular equivalente. *Alternativa descartada:*
gauge circular como padrão (é o clichê de dashboard que o mercado abandonou; Few o desenhou
o bullet exatamente para substituí-lo).

**DM2 — anatomia do medidor: seis partes.** (a) rótulo da métrica; (b) unidade; (c) **barra
de valor** (a medida); (d) **marca de meta** — traço perpendicular de 1,5px (exceção
registrada da hierarquia de traço: precisa vencer visualmente a banda atrás); (e) **bandas de
faixa** ao fundo — máximo **3** (Few: mais de 3 faixas vira arco-íris); (f) eixo numérico com
os limiares rotulados. *Alternativa descartada:* bandas sem eixo numérico — a faixa sem
número obriga o leitor a adivinhar os limiares.

**DM3 — papéis invertidos: banda é intensidade de cinza; a BARRA carrega a severidade.**
Formalizado como supersede na §3c do `seed-tokens.md` v1.5 (os hex não mudam; muda quem os
consome). Bandas: `cinza-100/200/300` no light, **invertendo** para `cinza-800/700/600` no
dark (distâncias de claridade 9/10/19 e 9/8/17 pontos, medidas). Barra de valor: assume
`gauge-range-ok/warning/critical` conforme a faixa em que o valor cai. *Racional medido:* as
três faixas coloridas originais distavam **1 ponto** de claridade no light e **0** no dark —
diferiam quase só por matiz, ilegível para daltônico e em grayscale; Few manda codificar
faixa em INTENSIDADE. *Alternativas descartadas:* texturizar as 3 bandas coloridas (ruído em
objeto pequeno) · mudar os hex (supersede caro sem necessidade). *Geometria:* barra de valor
com **12px de altura sobre banda de 18px** — engrossada no gate (era 8px) para dominar
sobre a banda mesmo com textura DM11 ativa.

**DM4 — acesso do medidor: `role="meter"` com nome e valor em português.** O elemento do
medidor leva `role="meter"` + `aria-valuenow/min/max` + **`aria-valuetext`** com a leitura
humana ("PR 83,1% — dentro do esperado"). Rótulo e valor visíveis ficam **FORA** do elemento
com o role — descendentes de `meter` são apresentacionais para leitores de tela, texto dentro
dele desaparece. No produto React, via **`useMeter` do React Aria**. *Alternativas
descartadas:* `<meter>` nativo (VoiceOver o anuncia como barra de progresso — semântica
errada) · `role="progressbar"` (progresso implica conclusão; medidor mede estado).

**DM5 — sparkline: tendência, nunca valor.** Sem eixo, sem grade, sem legenda, sem rótulo
interno; **série única**; traço 2px (`cat-N-stroke`, hierarquia de traço); **marcador só no
ponto final** (o valor "agora"). A sparkline responde "subiu ou desceu?" — quem responde
"quanto?" é o número na célula vizinha. *Racional:* é a definição de Tufte (word-like
graphic); qualquer adorno a transforma num gráfico de linha ruim.

**DM6 — sparkline em tabela é decorativa POR CONTRATO.** Na célula de tendência da tabela
§40 do ERP: `aria-hidden="true"` na sparkline, e a célula vizinha **obrigatoriamente** carrega
valor atual + variação em texto. **Sem par numérico, a sparkline não entra.** *Racional:*
uma micro-linha por linha de tabela é inaudível por construção; fingir que ela é acessível
(title, aria-label por ponto) é pior que declará-la decorativa e garantir o dado em texto —
o mesmo raciocínio do fallback do DG1, aplicado ao micro-formato.

**DM7 — rótulo textual de estado SEMPRE visível.** Todo medidor exibe a palavra do estado
("dentro do esperado" · "atenção" · "crítico") na coluna à direita, na cor
`gauge-range-*` correspondente + texto. Cor nunca é o único portador (1.4.1); em grayscale
e no impresso, a palavra é o que sobrevive. Nasceu como defeito no gate (v0.4 do preview o
omitia) e virou regra com teste.

**DM8 — gráfico do alerta de geração (fecha o slot ET5 da F4).** Barra **agrupada**
esperado × medido (herda DG10 inteiro), renderizada a **PNG @2x, largura fixa 560px**,
hospedada no R2 (`/email/v1/`), com `alt` que declara o desvio em texto ("geração 18% abaixo
do esperado nos últimos 7 dias"). E-mail não roda SVG nem JS (leis do `seed-email.md`); o
PNG estático com alt textual é o único formato que sobrevive aos clientes. A emenda de
referência no `seed-email.md` dispara quando o PNG existir no R2.

> **SUPERSEDE do DM8 na v0.13 (2026-08-11) — o e-mail de alerta NÃO leva gráfico.** Decisão do
> Rafael no gate de produção do asset, e o racional dele derruba o desenho original: **um alerta
> não pode carregar dado que não é do destinatário.** O PNG hospedado no R2 é um arquivo único,
> servido a todos os disparos — logo, os números nele são ilustrativos. O cliente cujo desvio é
> de 6% receberia um e-mail com uma imagem mostrando 18%, contradizendo o texto ao lado. Quem vê
> isso não conclui "a imagem é genérica"; conclui que **o sistema erra** — e um alerta existe
> justamente para ser confiável.
>
> **Regra vigente:** o e-mail de alerta leva **símbolo de alerta**, não gráfico. O dado real vive
> no sistema, onde o cliente entra para ver o que está acontecendo. *O e-mail avisa; o sistema
> mostra.*
>
> **O slot ET5 sai do escopo da dataviz e volta para o `seed-email.md`, sem regra nova:** o
> **EC5** já determina que ícones raster são produzidos **sob demanda**, como par glifo×cor
> rasterizado do SVG normalizado quando um template o pede, em `/email/v1/icones/`. Um template
> de alerta pedindo glifo de alerta é exatamente o caso previsto. O DM8 tinha contornado essa
> lei ao especificar um PNG de conteúdo; a correção reconduz o slot à regra que já existia.
>
> *Alternativa descartada:* gráfico gerado por usina no envio, com renderização server-side. Não
> é rejeitada por mérito — é **fora do Design System**. O DM10 já pôs comportamento dependente de
> dado vivo no domínio do produto (Lovable/Supabase). Se um dia se decidir mandar gráfico real ou
> outra informação no e-mail, isso é programação de sistema, não spec de DS.
>
> *Consequência material:* o PNG `seed-email-et5-grafico@2x.png` (1120×520, 28.441 B) chegou a
> ser produzido e **foi descartado sem subir ao R2**. Fica registrado que existiu, para que
> ninguém o encontre num diretório de trabalho e o suba supondo que faltava propagar. O
> **DI19** — que decidiu o caminho `/email/v1/` para o asset do ET5 — **permanece válido quanto
> ao caminho** e muda de objeto: quando o glifo de alerta for rasterizado pelo EC5, vai para
> `/email/v1/icones/`.

**DM9 — estados herdam o DG6 com uma adição.** Skeleton/vazio/erro do medidor e da sparkline
seguem o DG6 (moldura real, Z1/Z2, alerta §15). Adição própria: **medidor sem leitura usa
`chart-no-data` hachurado na barra de valor** — "sem medição" NÃO desenha barra em zero, que
mentiria (zero é um valor legítimo de geração).

**DM10 — fronteiras do DM.** Atualização em tempo real/websocket = comportamento de
**produto** (Lovable/Supabase), não do DS · composição de painel/grid de medidores = **F6** ·
comportamento no impresso = **DI**. O DM entrega o objeto; quem orquestra é outro bloco.

**DM11 — textura nas bandas do medidor, no MESMO gatilho do DG13 (escuro + grayscale).**
Vocabulário próprio, por banda: **esperado = sólido · atenção = pontilhado · crítico =
quadriculado**; a diagonal 45° permanece exclusiva do no-data (lei da §3c). A legenda do
medidor repete a textura sob o mesmo gatilho. *Origem — gate visual de 2026-08-10:* com o
DM3 aplicado, as bandas cinza mediam 9/8/17 pontos de espalhamento — ACIMA do piso de 6 do
`contraste-dg.py` — e o Rafael ainda assim não as distinguia no escuro+grayscale. É o caso
que provou que **o piso não transfere de contexto** (emenda registrada no DG13): faixa fina
empilhada exige mais que barra alta adjacente. A textura entra como remédio no mesmo
gatilho conservador do DG13; no claro, o espalhamento medido basta.

### Registro de produção do DM (defeitos que viraram guarda)

Quatro defeitos de produção foram encontrados e corrigidos ANTES do gate final — três pela
suíte, um só pelo render real:

1. **Variáveis CSS órfãs** — o preview consumia `var(--seed-gauge-range-*)` sem declará-las
   no bloco de tokens embutido (herança silenciosa de um preview anterior). Guarda: teste de
   variáveis órfãs (toda `var()` consumida existe declarada) — permanente na suíte.
2. **DM7 não implementado** — a spec exigia o rótulo de estado e o preview v0.4 não o
   desenhava. Guarda: teste de presença do rótulo por medidor.
3. **Overflow silencioso de viewBox** — o rótulo "83,1%" estourava o viewBox em 9px e era
   CORTADO no render; **jsdom não detecta** (não faz layout), só `getBBox()` em navegador
   real vê. Guarda: o `render-dm.mjs` mede `getBBox()` de todo texto contra o viewBox —
   requisito permanente da camada de render do DM (mesma família do aprendizado
   puppeteer-vs-CLI do §5).
4. **Acentos perdidos** no HTML gerado pelo `gen-dm.py` (encoding). Guarda: verificação de
   round-trip UTF-8 no gerador.

**Exceção ao DG12 usada pelo DM:** registrada na emenda do próprio DG12 (§4.4) — a tinta da
marca de meta acompanha a superfície porque as bandas invertem com o tema (7,07 / 3,93
medidos).

## 4c. Sub-bloco DI — impresso/PDF + integração da stack (DI1–DI19)

> **Estado: o sub-bloco DI está COMPLETO — `estável` em 2026-08-11.** Foi produzido em duas
> partes, por decisão de método: **DI-a** (DI1–DI2, DI4–DI19) fechou pelo "aprovo" do Rafael
> sobre o consolidado, e **DI-b** (DI3 — o veredito do gatilho da textura no papel) ficou
> deliberadamente aberto até haver **prova impressa física**, porque não se responde por
> análise. A prova foi executada e o DI-b fechou no mesmo dia (§4c.3): o impresso **não** entra
> no gatilho, e a medição produziu um supersede da própria regra do piso de claridade, que
> passa a ser calibrada por **forma** e não por meio.
>
> **Base:** 4 rodadas encadeadas (R1 canon interno: §5 e §4.4 deste arquivo, §3c do
> `seed-tokens.md`, §44/GI1–GI5 do `seed-componentes.md` · R2 mercado/stack: fornecedor
> gráfico real da SEED, doc oficial do shadcn Chart sobre Recharts v3, `print-color-adjust`
> no MDN e no comportamento real dos navegadores · R3 normas: Lei 6.496/77 e Resolução
> CONFEA 1.137/2023, Resoluções e Orientação Técnica 4 do CONARQ, políticas PAdES da
> ICP-Brasil sob a IN 34/2025, ISO 12647-2:2013 · R4, disparada porque impresso é domínio
> novo para este projeto: comportamento de meio-tom e linha mínima em impressora laser).
>
> **Siglas usadas aqui, explicadas na primeira ocorrência.** **CTP** = *computer-to-plate*,
> o processo pelo qual a gráfica grava a chapa de impressão direto do arquivo digital.
> **TVI** = *tone value increase*, o nome normativo do "ganho de ponto" (a mancha de tinta
> que engorda o ponto impresso em relação ao arquivo). **PAdES** = *PDF Advanced Electronic
> Signatures*, o padrão de assinatura digital embutida em PDF adotado pela ICP-Brasil.
> **ART** = Anotação de Responsabilidade Técnica, o documento que vincula legalmente o
> engenheiro ao serviço.

### 4c.0 O achado que reabriu o DG13 — remedição de 2026-08-11

A pendência que este sub-bloco herdou do §5 dizia que o modo claro tinha **7 pontos** de
espalhamento de claridade, acima do piso de 6, e que a dúvida era apenas se o papel
justificaria baixar esse piso. **A remedição mostrou que a premissa estava velha:** os 7
pontos foram medidos na **categórica v1.0, com três séries**. A categórica ESTENDIDA v1.5
tem seis, e as seis nunca foram medidas juntas neste instrumento.

Medição com a mesma função do `contraste-dg.py` (claridade = luminância relativa em
codificação gama, em pontos percentuais), modo **claro**, que é o modo que vai ao papel:

| Série | Token | Hex light | Claridade |
|---|---|---|---:|
| cat-1 | turquesa-500 | `#00A192` | 56% |
| cat-2 | dourado-300 | `#F9B11C` | 75% |
| cat-3 | magenta (exclusivo de dado) | `#CD518B` | 49% |
| cat-4 | azul-500 | `#0099C1` | 55% |
| cat-5 | violeta (exclusivo de dado) | `#966AC8` | 50% |
| cat-6 | azul-800 | `#004C61` | 27% |

**Piores pares, em qualquer adjacência:** `cat-1 × cat-4` = **1 ponto** · `cat-3 × cat-5` =
**1 ponto** · `cat-4 × cat-5` = **5 pontos**. Com três séries (`cat-1/2/3`) o pior par é
**7**, e a medição antiga estava correta na data em que foi feita.

**Conclusão que o número obriga:** o modo claro **não** é seguro em escala de cinza. Ele é
seguro **até três séries**. A partir da quarta, o claro colapsa como o escuro sempre
colapsou — e isso é um fato de tela, anterior a qualquer discussão sobre papel.

**Por que ninguém tinha visto.** O `contraste-dg.py` percorre apenas `cat1`, `cat2` e
`cat3` — exatamente o trio que passa. O detector estava recortado no lugar onde o defeito
não mora. Isso reclassifica a pendência **P8** do `MANIFESTO.md`: atualizar aquele script
não é higiene de manutenção, é restaurar a única guarda automatizada capaz de flagrar esta
classe de erro. A correção está no **DI18**.

### 4c.1 DI1 — Dois destinos de impressão; só um é escopo do DI

| Destino | O que sai por ele | Escopo |
|---|---|---|
| **(a) Laser colorida de escritório** | Laudo, relatório de O&M, proposta impressa, qualquer PDF gerado pelo ERP e mandado para a impressora | **DI** |
| **(b) Offset da gráfica** | Colateral físico da marca | **Fase 7** |

*Fato apurado sobre o fornecedor real (Zap Gráfica, o parceiro da SEED):* o fluxo dela é
CTP e **exige PDF/X-1a**, com todos os elementos convertidos em CMYK — arquivos entregues
em RGB podem ter a cor alterada ou simplesmente não impressa. A gráfica também **declara
variação de ±10% na cor, para mais ou para menos, dentro do mesmo lote de produção**.

*Consequência declarada:* essa tolerância é incompatível com qualquer informação codificada
por diferença fina de cor — mas é **irrelevante para o laudo**, que nunca passa pelo CTP da
gráfica. É por isso que o DI trata os dois destinos como problemas diferentes em vez de
buscar um pipeline único.

*Alternativa descartada:* adotar CMYK como saída única de todo impresso da empresa.
Obrigaria conversão de cor em todo laudo gerado pelo ERP, com perda de gama e sem nenhum
ganho, já que o destino real daqueles PDFs é uma impressora de escritório.

### 4c.2 DI2 — SUPERSEDE do gatilho do DG13: o gatilho é função do número de séries

**Regra antiga (DG13, §4.4):** textura por série apenas na interseção **escuro ∩ grayscale**.

**Regra vigente:** textura por série quando **`grayscale ∩ (escuro OU ≥4 séries)`**.

*Racional medido:* §4c.0. O DG13 nasceu correto sobre a evidência que tinha — três séries,
7 pontos de folga no claro. A categórica v1.5 dobrou o número de posições sem que o gatilho
fosse remedido, e nos pares `cat-1 × cat-4` e `cat-3 × cat-5` a folga caiu para **1 ponto**.
O que muda não é o meio (tela × papel): é a **densidade da paleta em uso**.

*O que permanece intocado:* o vocabulário de textura do DG13 (série 1 sólida · 2 pontilhada
· 3 quadriculada · 4 linhas horizontais), a exclusividade da **diagonal a 45° para o
`chart-no-data`**, a obrigação de a legenda repetir a textura sob o **mesmo** gatilho, e a
isenção do gráfico de série única.

*Alternativas descartadas:*
- **Manter o DG13 como está e apenas somar o modo de impressão.** Fecharia a pergunta do
  papel deixando aberto um colapso de tela já medido — a definição de verde enganoso.
- **Texturizar sempre, em todo modo.** O gate visual de 2026-08-09 já reprovou esse desenho
  ("ligar textura onde a cor já resolve" é ruído), e a regra de 3 séries continua verdadeira.
- **Baixar o piso de 6 para 1 ponto.** Trocaria um limiar calibrado por gate humano por um
  número escolhido para caber na paleta — inverteria a ordem entre instrumento e evidência.

### 4c.3 DI3 — O impresso NÃO entra no gatilho da textura, porque não precisa (DI-b FECHADO)

> **Estado: FECHADO em 2026-08-11**, por prova impressa física executada pelo Rafael. Esta
> seção substitui integralmente a redação anterior, que declarava o veredito ABERTO e previa
> que o papel exigiria piso próprio de claridade. **A previsão estava errada, e o modo pelo
> qual ela errou é o achado mais valioso do sub-bloco** — ver a correção da regra do piso no
> fim desta seção.

**Veredito.** O modo de impressão **não** é acrescentado ao gatilho do DI2. O gatilho permanece
`grayscale ∩ (escuro OU ≥4 séries)`, exatamente como o DI2 o escreveu, e cobre o impresso sem
uma palavra nova.

**Como a medição chegou a isso, por eliminação:**

| Condição de impressão | O que a prova mostrou | Consequência |
|---|---|---|
| **Em cor** | As 6 séries se distinguem bem, sem textura | A cor basta. Textura aqui seria ruído — o mesmo argumento que derrubou o DG11 |
| **Em escala de cinza (driver mono)** | Sem textura, 4 das 6 séries se distinguem; **2 pares colapsam** | Impressão mono **é grayscale por definição**, e o gatilho do DI2 já dispara ali com 6 séries |
| **Em escala de cinza, com textura** | As **6 texturas se distinguem bem** | O vocabulário estendido a 6 posições (§4.4) sobrevive ao papel |
| **Régua de traço** | As quatro espessuras (2 · 1,5 · 1 · 0,5px) saíram distintas, nenhuma sumiu nem engordou | **Não há piso de traço próprio para papel.** A hierarquia vale igual no impresso — ver DI6 |

*Alternativa descartada:* acrescentar "impresso" como terceira condição do gatilho. Seria
**redundante e pior**: criaria duas regras dizendo a mesma coisa, e regra duplicada é
precisamente o que deriva quando uma das duas é editada e a outra não — a classe de defeito das
erratas E12/E14/E16 desta mesma fase.

**O item 1 da folha era um CONTROLE, não um caso de uso.** Ele mostra 6 séries sem textura em
cinza, situação que a regra vigente **já proíbe**. Ele falhou como previsto. A prova não pediu
regra nova: **validou a regra existente no meio em que ela nunca havia sido testada.**

#### Os dois pares que colapsaram são exatamente os dois pares previstos

| Par identificado a olho, na folha impressa em cinza | Séries | Claridade medida em TELA | Espalhamento |
|---|---|---|---:|
| "Fora de ponta" ≈ "Bombeamento" | `cat-1` × `cat-4` | 56% × 55% | **1 ponto** |
| "Reservado" ≈ "Iluminação" | `cat-3` × `cat-5` | 49% × 50% | **1 ponto** |

**Nenhum falso positivo, nenhum falso negativo.** Os outros 13 pares tinham folga na medição e
foram todos distinguidos. O instrumento — espalhamento de claridade em pontos percentuais,
calibrado em tela — **previu o comportamento do papel com precisão de par a par.**

#### SUPERSEDE da regra do piso: ele é calibrado por FORMA, não por MEIO

A regra vigente até aqui, nascida da emenda da v0.5 e do DM11, dizia: *"o piso de 6 pontos
decide apenas no contexto em que foi calibrado — barras altas adjacentes, modo claro, em tela;
fora dali quem decide é o gate"*. Ela foi escrita depois que as bandas do medidor mediram 9, 8
e 17 pontos, todas acima do piso, e ainda assim eram indistinguíveis. A leitura natural foi que
**meio novo exige calibração nova**, e foi por isso que o DI3 nasceu prevendo piso próprio para
o papel.

**A prova impressa mostra que a variável nunca foi o meio — foi a FORMA.** Compare os dois
episódios:

| Episódio | Forma | Meio | O instrumento… |
|---|---|---|---|
| DM11 | bandas finas dentro de um medidor, com barra de valor por cima | tela | **errou** (9/8/17 pontos e ainda assim indistintas) |
| DI3 | **barras altas adjacentes** — a forma em que o piso foi calibrado | **papel** | **acertou par a par** |

Forma diferente, mesmo meio → erra. Mesma forma, meio diferente → acerta.

**Regra vigente, mais precisa e mais útil que a anterior:** o piso de claridade é calibrado por
**forma de apresentação** e vale para aquela forma **em qualquer meio**. Mudar de tela para
papel não invalida o número; mudar de barra alta adjacente para banda fina de medidor invalida.
Ao encontrar uma forma nova — banda, fatia fina, célula de heatmap, faixa de sparkline — o piso
tem de ser recalibrado por gate **mesmo que o meio seja o de sempre**.

*Por que isso importa mais que o veredito:* a regra anterior mandava recalibrar a cada meio
novo, o que é caro e, como se vê, desnecessário. A nova manda recalibrar a cada **forma** nova,
que é onde o risco realmente mora — e explica os **dois** episódios em vez de um só.

#### Fronteira: a folha de prova mede sobrevivência, não adequação

Crítica do Rafael no gate, registrada porque é correta e limita o instrumento: a régua do item 6
mostra as espessuras **isoladas**, com rótulos que só significam algo para quem já conhece a
hierarquia. Uma régua abstrata responde *"a impressora consegue depositar esta linha?"* — e
**não** responde *"esta espessura é adequada aqui?"*. A segunda pergunta exige as espessuras
**aplicadas no gráfico** (linha de série, linha de meta, eixo, grade). A folha v0.1 responde a
primeira, que era o que o DI6 precisava; se a segunda pergunta for feita algum dia, a folha
precisa ser refeita.

*Achado colateral:* o piso de **0,5px não tem consumidor** hoje — a grade do preview do DG está
toda em 1px. É um valor que existe na lei e não é exercido, e valor não exercido deriva.
A verificar quando a **Fase 6** montar painéis, onde grade fina em gráfico pequeno é o caso
natural para ele.

### 4c.4 DI4 — Nenhuma informação de gráfico pode viver em `background-color` de CSS

**Fato apurado, não inferência:** a propriedade `print-color-adjust: exact` é uma **dica** ao
navegador, e a preferência do usuário no diálogo de impressão ("Gráficos de plano de fundo",
"Background graphics") **tem precedência** — nenhuma folha de estilo a sobrepõe. Um laudo
impresso por alguém que nunca abriu "Mais configurações" sai com todo `background` ausente.

**Regra dura que sai daí:** toda superfície que carrega dado é elemento de **conteúdo** do
SVG — `<rect>`, `<path>`, `<circle>` com atributo `fill` —, nunca um `<div>` pintado por
`background-color`. Vale para barra, área, fatia, banda de medidor, célula de heatmap e o
`chart-no-data`. O `print-color-adjust: exact` continua declarado na folha de impressão,
como reforço, e nunca como garantia.

> **A inferência foi MEDIDA e virou fato — gate de impressão de 2026-08-11.** A v0.1 do preview
> do DI trazia esta regra como inferência não medida. A v0.2 montou uma matriz de quatro células
> — `background-color` × `fill` de SVG, cruzados com `print-color-adjust: exact` × `economy` — e
> o Rafael a imprimiu no Chrome, destino "Salvar como PDF", A4, nas duas posições da opção
> "Gráficos de segundo plano".
>
> | Célula | O que é | Opção MARCADA | Opção DESMARCADA |
> |---|---|---|---|
> | A | CSS `background` · `exact` | sobreviveu | sobreviveu |
> | B | SVG `fill` · `exact` | sobreviveu | sobreviveu |
> | C | CSS `background` · `economy` | sobreviveu | **SUMIU** |
> | D | SVG `fill` · `economy` | sobreviveu | sobreviveu |
>
> **C sumiu e D sobreviveu sob condição idêntica** — mesma cor, mesma área, mesma célula da
> matriz, única diferença sendo *como* a superfície é pintada. O DI4 está provado como escrito.
>
> **Segundo achado, não previsto:** a célula A sobreviveu, isto é, o Chrome honrou
> `print-color-adjust: exact` mesmo contra a preferência desmarcada. Existem portanto **duas
> camadas de proteção, e elas não valem o mesmo**: a dica de CSS, que funcionou aqui, e a
> natureza estrutural do SVG, que não depende de navegador. **A regra dura do DS continua sendo
> a segunda**, porque a primeira é documentadamente uma dica.
>
> **Fronteira da medição, declarada:** um navegador (Chrome), um destino ("Salvar como PDF").
> Não medido em Firefox nem em driver de impressora física, e o Firefox tem histórico de divergir
> neste ponto. Vale como **fato para o Chrome** e forte indício para o resto.
>
> *Erro de método registrado, porque é instrutivo:* a v0.1 do preview tinha só **duas** células e
> **não isolava a variável** — a folha de impressão declara `exact` num seletor universal, que
> protegia os dois braços do próprio teste. A primeira rodada devolveu "os dois sobreviveram",
> resultado verdadeiro que respondia **outra pergunta**. Só a matriz de quatro, com o controle
> sobrescrevendo para `economy` por especificidade de classe, isolou o que interessava.

### 4c.5 DI5 — O `<figure>` do gráfico nunca se parte entre páginas

`break-inside: avoid` aplicado ao `<figure>` inteiro, não a partes dele. Motivo: o DG1 define
o gráfico como um conjunto de cinco partes (título em `figcaption`, descrição curta, fallback
textual, legenda e a área de dado com `role="img"`). Se a paginação separa a legenda da área
de dado, o leitor perde a chave de leitura na virada da folha — e o fallback textual, que
existe para ser a alternativa acessível, vira um parágrafo órfão sem referente visível.

### 4c.6 DI6 — Traço no papel: o piso é do papel, não da tela

A escala já está resolvida: `vector-effect: non-scaling-stroke` é obrigatório em todo SVG de
gráfico (lei transversal do §4.6), e sem ele o mesmo `stroke-width=1` renderizaria entre meio
pixel e doze, porque os viewBox do sistema escalam de 0,66× a 12,4×.

O que **não** está resolvido é o piso físico. A hierarquia canônica é **dado 2px · estrutura
1px · apoio 0,5px · marca de meta 1,5px**. O candidato a falhar no papel é o apoio de 0,5px:
a referência de ordem de grandeza levantada na R4 é que uma impressora laser não deposita
linha abaixo de aproximadamente três a quatro vezes o seu ponto nominal, o que aproxima o
apoio do limite mesmo em equipamentos de resolução alta. **Número declarado como referência
de literatura, não como medição da SEED** — a régua de traço da folha do DI3 é que produz o
número nosso.

### 4c.7 DI7 — O Design System não converte para CMYK

Os hex canônicos permanecem **RGB**. A conversão para CMYK é responsabilidade do fluxo da
gráfica, na Fase 7, com prova de cor contratada.

*Racional:* criar uma tabela CMYK aqui criaria um **segundo lugar onde a cor mora**, contra o
DF7 ("tokens de dado têm UMA fonte"), e o consumidor real desse valor não existe hoje — o
laudo, que é o impresso que a empresa de fato produz, sai por impressora de escritório, que
recebe RGB e converte sozinha.

*Alternativa descartada:* gêmeo CMYK dos tokens. Levaria a unidade `seed-tokens.md` +
`.json` + `.css` a **quatro** arquivos que precisam mudar juntos, quadruplicando a superfície
que o `paridade-tokens.py` precisa guardar, para servir um consumidor hipotético.

**Duas regras do fornecedor ficam registradas desde já, para a F7 não redescobri-las:** o
preto de texto deve ser **K 100% puro** (a gráfica não se responsabiliza por material enviado
com preto composto, que causa decalque e variação); e o preto de área grande, quando se quer
um preto profundo, é **C 50% M 50% Y 40% K 100%**.

### 4c.8 DI8 — PDF/A não é adotado; o laudo sai em PDF comum, assinável em PAdES

**Pesquisa normativa fechada, com o resultado negativo declarado:** não existe exigência de
formato de arquivo para laudo técnico de engenharia no arcabouço CONFEA/CREA. A Lei
6.496/77 e a Resolução CONFEA 1.137/2023 tratam da ART, do acervo técnico e da validade da
assinatura eletrônica — nunca do formato do documento. O **PDF/A** (ISO 19005) é
recomendação do **CONARQ** para preservação de longo prazo, dirigida aos órgãos e entidades
do Sistema Nacional de Arquivos, isto é, ao setor público; a SEED não integra o SINAR.

**E há um conflito técnico real, que é o argumento decisivo:** a Orientação Técnica 4 da
Câmara Técnica de Documentos Eletrônicos do CONARQ registra que **o PDF/A-1 admite apenas
assinatura digital simples**. Isso colide frontalmente com o padrão **PAdES** da ICP-Brasil
— cujas políticas foram republicadas pela Instrução Normativa 34/2025 do ITI, nas variantes
AD-RB, AD-RT, AD-RC e AD-RA —, que é justamente o que confere validade jurídica plena a um
laudo assinado. Adotar PDF/A-1 seria trocar validade jurídica por conformidade de
arquivamento que ninguém exige.

**Decisão:** PDF comum, com assinatura PAdES quando o laudo exigir responsabilidade técnica
formal.

*Gatilho de revisão declarado:* se um contrato, cliente ou órgão exigir PDF/A por escrito,
reavaliar com **PDF/A-2 ou PDF/A-3**, que admitem assinatura avançada — **nunca PDF/A-1**.

### 4c.9 DI9 — Fotocópia e fax: sem regra própria, com gatilho declarado

Evidência de campo do Rafael: fotocópia de laudo é rara a ponto de ele não lembrar da última
vez. A rede de proteção para esse caso **já existe e é herdada**, sem custo novo: o fallback
textual obrigatório do DG1, o rótulo textual de estado sempre visível do DM7 e a hachura
diagonal exclusiva do `chart-no-data`. Nenhuma regra nova é criada.

*Gatilho:* se a fotocópia passar a ocorrer com regularidade em algum fluxo (concessionária,
cartório, cliente), o caso entra com medição própria — e a fotocópia em preto e branco é, por
construção, um caso de grayscale, portanto já coberto pelo gatilho do DI2 a partir de quatro
séries.

### 4c.10 DI10 — Fronteira com a Fase 7 (colateral físico)

O **DI** entrega o comportamento da **dataviz** no papel: gatilho de textura, folha de estilo
de impressão, paginação do `<figure>`, piso de traço e a decisão de formato do arquivo. A
**Fase 7** entrega tudo o mais que o papel exige da marca: formato, gramatura, acabamento,
capa, papelaria e a conversão de cor para o fluxo da gráfica (DI7). Linha declarada para não
ser invadida em nenhuma direção.

### 4c.11 Guia de integração da stack — DI11–DI17

Consumidor real e imediato: o **ERP em Lovable** (Vite + React + TypeScript + Tailwind +
shadcn/ui + Supabase). O guia é o documento colável lá; **este arquivo permanece agnóstico
de biblioteca** (DF2), e o guia é a ponte, nunca a lei.

**DI11 — A cadeia tem quatro saltos, não três.** O padrão **GI1** do §44 do
`seed-componentes.md` formalizou a cadeia de três camadas para componentes de UI
(primitivos → semânticos `--seed-*` → aliases shadcn). Para gráfico existe **um salto a
mais**, e ele é fácil de errar:

```
--seed-chart-cat-N   (token SEED, dono do valor)
      ↓
--chart-N            (alias que o shadcn Chart espera encontrar no CSS)
      ↓
chartConfig[chave].color = "var(--chart-N)"
      ↓
fill="var(--color-chave)"   ← o que o componente Recharts realmente consome
```

*Fato da documentação oficial:* o `fill` **não** referencia `--chart-N`. Ele referencia
`var(--color-CHAVE)`, uma variável que o `ChartContainer` gera em tempo de execução a partir
do `chartConfig`. Pular o terceiro salto produz gráfico sem cor, sem erro no console.

**DI12 — Sintaxe do Recharts v3.** `var(--chart-1)`, **nunca** `hsl(var(--chart-1))`. A forma
com `hsl()` era o padrão do Recharts v2 e pressupunha tokens gravados como triplas de canal;
os tokens SEED são **hex**, e o embrulho em `hsl()` produziria valor inválido — que em CSS
significa cor ausente, e não erro.

**DI13 — O tema vem do `[data-theme]`, não do `chartConfig`.** O `chartConfig` aceita um
objeto `theme: { light, dark }` como alternativa às variáveis CSS. **Descartado:** duplicaria
a cor dentro do TypeScript, criando uma segunda fonte de verdade dentro do produto e furando
o DF7 e o GI1. Trocar o `data-theme` continua resolvendo o tema inteiro de uma vez.

**DI14 — `accessibilityLayer` é obrigatório e insuficiente.** A prop existe e entrega acesso
por teclado e suporte a leitor de tela; deve ser ligada em todo gráfico. Ela **não** entrega
alternativa textual (WCAG 1.1.1) nem relação codificada entre legenda e dado (1.3.1) — que
são exatamente as duas reprovações da auditoria pública do shadcn Charts. **O invólucro
`<figure>` de cinco partes do DG1 permanece obrigatório por cima da prop.** Sem ele, o
produto herda a falha da biblioteca, e o guia de integração deixa de ser guia para virar
veículo do defeito.

**DI15 — `ChartContainer` sempre com altura.** Ou `height`, ou `min-h-*`, ou `aspect-*`. Sem
uma delas o `ResponsiveContainer` não consegue medir no primeiro render e o gráfico não
aparece. Item de verificação do guia, não recomendação.

**DI16 — Aliases de `--chart-1` a `--chart-6`.** O shadcn distribui cinco por padrão; o teto
SEED é **seis** (DG). Acima disso o gráfico se reestrutura — agregação em "Outros", facetas,
ou o par destaque × contexto do DG17 — e nunca ganha uma sétima cor.

**DI17 — Contrato Lovable.** O guia entrega: um bloco único colável em `globals.css`
(Tailwind v4, via `@theme`) com os seis aliases apontando para os tokens SEED nos dois temas;
um `chartConfig` de exemplo; e o wrapper `<figure>` do DG1 como componente em
`src/components/seed/`, conforme o GI5 do §44.

### 4c.12 DI18 — Reescrita do `contraste-dg.py` (fecha a pendência P8 do MANIFESTO)

O script vigente mede duas coisas mortas — o **DG11** (contorno em `cinza-900`, supersedido
pelo DG14) e a paleta categórica anterior à v1.5 — e, pior, percorre apenas três séries. A
reescrita mede:

1. Ausência de contorno e o vão de 2px do **DG14**.
2. As **seis** séries da categórica v1.5, contra os fundos de referência declarados.
3. O gatilho do **DI2**, por varredura de **todos** os pares em cada número de séries de 2 a
   6, nos dois modos — reprovando quando um par cai abaixo do piso sem que a textura esteja
   prevista.

**O placar vai mudar, e é para mudar.** O verde atual é produto do recorte, não da saúde da
paleta. Isso reafirma a régua do §7 do MANIFESTO: verde só é bom sinal quando não há errata
aberta; havendo, a suíte parou de medir.

### 4c.13 DI19 — O gráfico do alerta de geração (ET5) entra em `/email/v1/`

O **DM8** especificou o gráfico do e-mail de alerta de geração e declarou que o slot fecha
quando o PNG em resolução dobrada existir no bucket R2, sob
`assets.seed.eng.br/email/v1/`. O caminho `/email/v1/` é **imutável por decisão** — arte nova
vai para `/v2/`.

**Decisão:** o PNG do ET5 nasce em **`/email/v1/`**, com nome novo.

*Racional:* a imutabilidade do `/v1/` existe para impedir que um arquivo seja **substituído**
no mesmo caminho sem ninguém perceber — a classe de defeito da §1 do `MANIFESTO.md`, em que
uma propagação afirmada e nunca lida de volta sobrescreveu um artefato. **Acrescentar** um
arquivo com nome inédito não expõe nenhum consumidor existente a troca silenciosa. Além
disso, o slot do ET5 está declarado desde a Fase 4 e nunca foi preenchido: ele já pertence
ao `/v1/` conceitualmente.

*Alternativa descartada:* abrir `/email/v2/` só para este asset. Faria o `seed-email.md`
passar a citar dois caminhos-base para a mesma geração de arte, dobrando a superfície de
confusão para economizar uma regra que não estava sendo violada.

*Consequência:* a produção deste PNG fecha, no mesmo movimento, a pendência **P4-b** do
`MANIFESTO.md` — os seis PNGs do bucket que seguem sem âncora passam a ser medidos e
ancorados junto com o novo.

---

## 4d. Sub-bloco DP — mapas de atuação MG-ES-BA (DP1–DP14)

> **Estado:** **`estável` desde 2026-08-11, e SEM PENDÊNCIAS ABERTAS desde o mesmo dia.** O
> consolidado de decisões foi aprovado pelo Rafael ("aprovo" explícito sobre DP1–DP14) e a
> promoção veio depois do **gate visual** sobre o preview. As seis pendências nominais que o
> sub-bloco abriu — **DP-P1 a DP-P6** — **fecharam todas**: as três primeiras por medição de
> contraste e de forma; as três últimas quando a **malha oficial do IBGE, edição 2025**, entrou
> no lugar da malha sintética. O gate visual sobre o preview **v0.4**, já com a geografia real,
> foi aprovado em 2026-08-11. *Fronteira honesta do que o gate cobriu, registrada porque a diferença importa:* o
> Rafael inspecionou visualmente o preview **v0.2** e respondeu os cinco pontos do protocolo
> (formas legíveis em escala de cinza · fronteira visível no tema escuro · malha completa
> ilegível a 360px · impressão correta · malha sintética aceita). A **v0.3** difere da v0.2 em
> **um único ponto** — a tinta da contagem de agrupamento, corrigida pelo DG12 —, verificada por
> medição de contraste e por inspeção de captura de render, e aprovada por ele sobre esse
> relato. **DP** = sub-bloco de **mapas** da Fase 5; é o
> último dos seis (DF · DT · DG · DM · DI · DP) e o seu fechamento dispara o marco da fase.
>
> **Por que este sub-bloco tem insumo que nenhum outro teve.** DF, DT, DG, DM e DI operam
> sobre geometria que o Design System inventa (uma barra tem a altura que o dado mandar).
> O DP opera sobre **geometria geográfica real**: o contorno de Minas Gerais não é decisão
> de design, é um dado externo, com fonte, licença, data de publicação e erro declarado.
> Isso põe no sub-bloco duas classes de decisão que os outros não tiveram — **de onde vem a
> forma** (DP8, DP9) e **como ela é achatada num plano** (DP7).

### 4d.0 Escopo, decidido em briefing com o Rafael antes de qualquer pesquisa

As seis perguntas de escopo foram feitas e respondidas em 2026-08-11, antes da primeira
rodada de pesquisa, exatamente porque nenhuma delas é derivável do canônico — todas dependem
do uso real da empresa. **Fato (respostas do Rafael), não inferência:**

| # | Pergunta | Resposta |
|---|---|---|
| a | Obras como **pontos** ou municípios pintados por intensidade (**coropleto**)? | **Pontos.** O coropleto fica **escrito** na spec como caminho pronto, sem ser implementado agora |
| b | Onde o mapa aparece? | **Nos três destinos**: laudo/proposta impressa, ERP (tela) e site institucional |
| c | Zoom/pan/tooltip ou figura fixa? | **Figura fixa** como norma; tooltip permitido no ERP como enriquecimento |
| d | Quantos níveis geográficos? | Estado + **município** + ponto. O Rafael recusou o recorte de dois níveis: *"eu tenho que ter todos os municípios"* — o território do estado nunca aparece recortado, e a seleção incide sobre a **linha de fronteira**, não sobre o território |
| e | Carrega dado de cliente identificável? | Sim no ERP; **não** em peça externa — vira regra dura (DP12) |
| f | Fonte de malha já em uso na empresa? | Não há. Decisão livre (DP8) |

**Glossário mínimo, porque o vocabulário de cartografia não aparece em nenhum outro arquivo
deste sistema:**

- **Malha** — o arquivo com as coordenadas que desenham os contornos (estados, municípios).
- **Coropleto** — mapa em que cada região é preenchida com uma cor que representa um número.
- **Marcador** — o símbolo que marca um ponto (uma obra) sobre o mapa.
- **Projeção** — a regra matemática que achata a superfície curva da Terra num plano. Toda
  projeção deforma alguma coisa; escolher a projeção é escolher **o que** deformar.
- **Simplificação** — reduzir o número de pontos de um contorno para o arquivo caber na web,
  aceitando perda de detalhe.
- **TopoJSON / GeoJSON** — formatos de arquivo de geometria. TopoJSON é a variante compacta,
  que armazena fronteiras compartilhadas uma única vez em vez de duas.
- **SIRGAS 2000** — o sistema geodésico de referência oficial brasileiro; define a partir de
  que modelo da Terra as coordenadas são medidas.

**O DP entrega DIRETRIZ DE MAPA.** Não orquestra tela (isso é Fase 6), não implementa
comportamento dependente de dado vivo (isso é produto — Lovable/Supabase, mesma fronteira do
DM10), e não vira SIG/GIS: não faz análise espacial, não calcula rota, não mede distância.

---

### 4d.1 DP1 — Um mapa é um gráfico: herda o DG1 inteiro, e o fallback textual é o mapa

**Decisão:** todo mapa SEED é um `<figure>` com as **cinco partes do DG1** (§4.1): título em
`figcaption`, descrição curta, **fallback textual sempre presente**, legenda, e a área com
`role="img"` + `aria-labelledby`. O fallback textual de um mapa é uma **tabela município →
obras**, com as colunas: Município · UF · Tipo de solução · Quantidade. Em destino interno
acrescenta-se a coluna de identificação permitida pelo DP12; em destino externo, nunca.

**Racional:** o W3C classifica gráfico como imagem complexa e exige alternativa textual em
duas partes, e a orientação específica para mapas vai além do que vale para um gráfico comum
— ela pede, além da tabela, **navegação alternativa por lista de localidades**, porque num
mapa a informação é *onde*, e "onde" não se lê por varredura de eixo. Num mapa da SEED a
lista de municípios **é** o mapa para quem não o enxerga. E é também o que sobra quando o
laudo é lido em preto e branco, ou quando o PDF é aberto num leitor que não renderiza SVG.

**Alternativa descartada:** `alt` textual curto como cumprimento do 1.1.1. Insuficiente para
imagem complexa — a mesma razão já registrada no DG1, agravada aqui: um `alt` que diz "mapa
de atuação da SEED em MG, ES e BA" identifica o objeto e **não entrega nenhum dado**.

---

### 4d.2 DP2 — Consumidor técnico: SVG projetado sobre `d3-geo`; mapa de tiles é VETADO

**Decisão:** o mapa canônico da SEED é **SVG projetado**, gerado por `d3-geo` +
`topojson-client`. O invólucro `react-simple-maps` é **permitido** (é um wrapper fino sobre
exatamente essas duas dependências, com API declarativa), mas o que o Design System exige é a
camada de baixo — para que a diretriz sobreviva ao abandono do wrapper. **Mapa de tiles
(Leaflet, MapLibre, Google Maps, Mapbox) é vetado dentro do escopo do DS.**

**Racional do veto, com três motivos independentes:**
1. **Identidade.** Tile traz base cartográfica de terceiro, com estética própria — ruas,
   pontos de interesse, tipografia alheia. O mapa deixa de ser uma peça SEED e passa a ser
   uma captura de tela do produto de outra empresa com uns pinos por cima.
2. **Impressão.** Tile é imagem raster carregada por rede. Num PDF de laudo vira mancha, e
   sob a regra do **DI4** (§4c.4) nada disso é superfície de dado protegida.
3. **Custo de render.** A abordagem de tiles paga custo de performance na renderização
   durante pan e zoom, ao contrário do SVG — e nós nem usamos pan e zoom (DP13).

**Alternativa descartada:** D3 puro sem wrapper — é o que o DF2 já descartou para os
gráficos core ("poder máximo que os tipos core não exigem"). Aqui a decisão é diferente
**por um motivo declarado**: mapa **não tem** equivalente ao shadcn Chart, então a camada
`d3-geo` é obrigatória de qualquer forma; o que é opcional é o wrapper acima dela.

> **EMENDA FORMAL AO DF2 (§2), nascida neste sub-bloco.** O DF2 declara o consumidor canônico
> web como **shadcn Chart sobre Recharts v3**. **Recharts não desenha mapa** — não há
> componente geográfico na biblioteca. O DF2 permanece vigente para os sete tipos core, o
> monitoramento e o que vier deles; **a família mapa consome outra cadeia**, declarada neste
> DP2. Isso não é supersede do DF2: é o preenchimento de uma lacuna que ele tinha sem saber,
> porque foi escrito quando mapa ainda não era escopo. Registro no §6.

---

### 4d.3 DP3 — Num mapa existem TRÊS cinzas, e cada um precisa de papel declarado

Esta é a decisão mais importante do sub-bloco, porque é onde a regra com mais reincidências
do projeto — **posição categórica nunca serve de neutro** (erratas E3, E14, E15) — tem a
maior superfície de erro. Num gráfico de barras existem duas coisas cinzas ("sem dado" e
"contexto"). **Num mapa existem três**, e as três parecem a mesma mancha:

| Estado do território | Significado | Tinta |
|---|---|---|
| **Contexto** | não é objeto de medição (o resto do estado) | **`chart-geo-base`** — token próprio, novo na v1.8 dos gêmeos |
| **Sem medição** | é objeto de medição e **não temos o dado** | `chart-no-data` + hachura diagonal a 45° em `chart-no-data-hatch`, **obrigatória** |
| **Com dado** | medido | escala **sequencial** (§3c) — no coropleto do DP14 |

**Regra dura:** nenhum dos três consome `cat-N`. Nunca. Território não é série.

**Racional do caso perigoso — o do meio.** Sem a hachura, "não medimos aqui" e "aqui não
interessa" viram a mesma mancha cinza, e a diferença entre as duas afirmações, num laudo de
engenharia, é a diferença entre lacuna declarada e território fora do escopo. É exatamente a
estrutura do erro da errata **E3**, transposta para outra forma: um papel de desenho existindo
sem token próprio e tomando emprestado o de outro papel. A hachura a 45° permanece
**exclusiva** do `chart-no-data` (§4.4), e a tinta dela é o `chart-no-data-hatch` (v1.7 dos
gêmeos), nunca `chart-axis` e nunca `cat-N-stroke`.

> **DP-P1 FECHADA na v0.15, por medição.** O instrumento é o `contraste-dp.py` v1, que extrai
> os hex do `seed-tokens.css` canônico em vez de digitá-los (lição das erratas E4/E16).
> **Veredito:** nasce o token **`chart-geo-base`** (`#F2F6F9` light / `#141D23` dark), com papel
> próprio, na v1.8 dos três gêmeos. **Por que token novo se o valor já existe** (é idêntico ao
> `surface-subtle` vigente): o que muda não é a cor, é a responsabilidade de mantê-la — mesmo
> racional que criou o `chart-no-data-hatch` na v1.7 depois da errata **E3**, que provou que
> papel de desenho sem token próprio acaba tomando emprestado o de outro papel.
> *Alternativa descartada:* consumir `surface-subtle` diretamente — repetiria a estrutura da E3
> num papel novo. Medições completas na §3c do `seed-tokens.md` v1.8.

---

### 4d.4 DP4 — Fronteira no mapa: PRECISÃO DE ESCOPO do DG14, não supersede

**Decisão:** o **DG14** (§4.6) determina que superfície de dado não leva contorno, e resolve
a separação entre vizinhos por **vão de 2px na cor do cartão** — espaço negativo, fronteira
por geometria e não por contraste. Isso **não se aplica ao território**, porque território é
**contíguo**: não existe vão entre Governador Valadares e Alpercata sem que se invente um. No
mapa vale o **princípio** da condição (b) da §3c do `seed-tokens.md`, já `estável` desde o
sub-bloco DT e escrita junto com a isenção do WCAG 1.4.11 para heatmap — *a fronteira entre
regiões é desenhada, nunca deixada por conta da diferença de cor*. **A tinta, porém, não é a
que aquela condição nomeia.** Ver a errata **E19** logo abaixo: a fronteira do mapa consome
**`chart-geo-boundary`** (`#788F9D` light / `#90A6B3` dark, token novo na v1.8), não
`chart-grid`.

> **ERRATA E19 — contra a redação original do DP4 na v0.14 (nascida e corrigida no mesmo dia).**
> A v0.14 mandava a fronteira consumir `chart-grid`, por leitura direta da condição (b) da §3c.
> A medição do `contraste-dp.py` derrubou: **`chart-grid` e `chart-no-data` têm o MESMO HEX nos
> dois temas** — `#E3EBF0` no light e `#38464F` no dark. Sobre um município sem medição a
> fronteira mede **1,00** contra o preenchimento: ela desaparece. Contra o território de
> contexto ela mede **1,11**, também muito abaixo do piso de 3:1.
> *Por que o defeito nunca apareceu no heatmap, que é o consumidor para o qual a condição (b)
> foi escrita:* lá a célula sem medição é hachurada e as vizinhas são sequenciais saturadas, de
> modo que a fronteira nunca precisa separar dois cinzas. **Num mapa, onde metade do território
> pode ser "sem medição", separar dois cinzas é o caso normal.**
> *Candidatas medidas contra o território de contexto no light:* `chart-grid` **1,11** ·
> `border-default` **1,37** · `border-strong` **2,33** · a tinta adotada **3,11** — única a
> passar. No dark a adotada mede **6,74**.
> *Por que não emprestar `chart-axis`, que tem o mesmo valor:* **no tema escuro `chart-axis` é o
> mesmo hex do `chart-no-data-hatch`** (`#90A6B3`). Emprestar faria a linha da fronteira e a
> tinta da hachura de "sem medição" serem o mesmo token por acidente — literalmente a estrutura
> da errata E3, num arquivo que a registra três vezes.
> **Classe de defeito:** *regra herdada de outro consumidor sem remedir o novo contexto.* É
> parente da E7 (herdar um número medido antes de um supersede de paleta).

**Consequência:** o DG14 permanece intacto e **ganha escopo declarado** — vale onde a
superfície de dado é **separável por espaço negativo** (barra, segmento de pilha, fatia,
área). Onde a geometria é contígua (mapa, heatmap), a fronteira é desenhada e consome
`chart-grid`.

> **E19-b — EXCEÇÃO DECLARADA POR VEREDITO (2026-08-24, gate F7.7-P1, saída (a):
> *"aceito sua sugestao, A"*).** O porte da camada de validação revelou o que a E19
> não havia medido: no tema claro a tinta adotada mede **2,80 sobre o sem-medição**
> (`chart-no-data`/`surface-sunken`, #E3EBF0) — abaixo do piso 3,0 que ela cumpre
> sobre o contexto (3,11). A razão é do PAR, não da tinta: o mesmo ci-500 sobre um
> fundo um degrau mais escuro rende menos. **A casa decidiu ACEITAR como exceção
> declarada**, porque a hachura já é o segundo separador da região (a SC 1.4.11 só
> cobra o par quando ele é o ÚNICO identificador) — mesma lógica da isenção do
> heatmap na §3c. O mesmo veredito cobre o `cat-2-stroke × sunken` (2,89), cujo
> segundo portador é a FORMA (E20). *Alternativas medidas e descartadas no gate:*
> **ci-600** passa todos os pares (4,37/3,93) mas **colide em valor com a tinta da
> hachura** (#617683) — a estrutura E3 que esta própria errata usou para recusar o
> `chart-axis`; **ci-700** passa com folga (6,03/5,43) sem colisão, mas dobra o
> peso do traço num desenho aprovado — recusada pelo custo visual. No tema ESCURO
> nada disso se aplica (a adotada mede 3,84–7,35). A exceção vive como código no
> `contraste-dp.py` (categoria própria `[exceção]`, com o número IMPRESSO a cada
> execução para a decisão poder ser re-julgada); placar do sub-bloco: **27 PASS ·
> 0 FAIL · 3 exceções por veredito**.
>
> **Fronteira honesta do alcance, medida na prova visual de 2026-08-24:** HOJE o par não é
> consumido por artefato nenhum — o único mapa com sem-medição é a demo do coropleto, e ela
> **não desenha fronteira** (pendência nova **DP-P7**). O par passa a ser real no momento em
> que o coropleto for ligado com dado real, porque aí o DP4 obriga a fronteira. Ou seja: a
> exceção não perdoa uma dívida existente — ela **DESTRAVA o conserto do DP-P7**, que sem ela
> nasceria com dois FAIL. Provado no navegador real, lupa 12× por captura em escala 1:1: com
> 2,80 a fronteira SEPARA os municípios sem medição e mantém a discrição que a E19 escolheu.

**Alternativa descartada, com o racional que a derruba:** erodir cada polígono para fabricar
o vão de 2px, que seria a leitura literal do DG14. É geometricamente possível e foi
considerada. Cai por dois defeitos medíveis: (i) em municípios estreitos a erosão de 2px por
lado consome a própria área, e o polígono some ou vira filete; (ii) onde não há vizinho — na
borda externa do estado — a erosão abre uma canaleta clara contra o fundo, **inventando uma
fronteira que não existe**. Um mapa que desenha limite onde não há limite é pior que um mapa
sem contorno.

**Fato vs. inferência:** que a §3c exige a fronteira desenhada é **fato** (texto vigente e
`estável`). Que a tinta dela no mapa é o `chart-geo-boundary` e não o `chart-grid` também é
**fato medido** desde a v0.15 (E19). O que permanece **não medido** é a largura mínima de
renderização da variante malha completa — pendência DP-P2, que é geometria e não cor.

---

### 4d.5 DP5 — Duas variantes de malha, e a segunda tem trava de largura

**Decisão:** o território do estado aparece **sempre inteiro**, sem recorte. O que varia é
**quais fronteiras municipais são desenhadas**:

- **Variante BASE** — padrão nos três destinos. Silhueta completa do estado; fronteira
  desenhada **apenas nos municípios com obra**. Traço: **estrutura, 1px**, em `chart-grid`.
- **Variante MALHA COMPLETA** — todas as fronteiras municipais desenhadas em **apoio, 0,5px**.
  Permitida **somente no ERP** e **acima de uma largura mínima de renderização a medir**.
  **Vetada** a 360px e em figura pequena de papel.

**Racional:** MG tem 853 municípios, BA 417 e ES 78 — **1.348 polígonos**. Desenhar 1.348
fronteiras numa figura que precisa caber num A4 de proposta e num celular de 360px não
informa: vira uma textura cinza uniforme, e o marcador da obra — que é o dado — se perde
dentro dela. A fronteira só ajuda quem já sabe qual município procurar, e o leitor de uma
proposta não sabe. **A variante base inverte isso:** a linha aparece onde há informação, e
por isso a linha *é* informação.

**Achado colateral que esta decisão resolve:** o §4c.3 registrou que o piso de **0,5px não
tem consumidor** — a grade do preview do DG está toda em 1px — e que "valor que existe na lei
sem ser exercido deriva", deixando a verificação para a Fase 6. **A fronteira municipal da
variante completa é o primeiro consumidor real do 0,5px.**

**Fronteira do instrumento, herdada do DI6 e registrada de propósito:** a folha de prova
impressa mediu **sobrevivência** da linha de 0,5px (a impressora consegue depositá-la?), não
**adequação** dela aplicada num desenho. A largura mínima da variante completa é medição de
adequação e é **pendência nominal DP-P2**.

**Alternativa descartada:** malha municipal completa e permanente em todos os destinos —
pedida no briefing e revista na mesma conversa. Cai por legibilidade, não por peso de arquivo:
mesmo simplificada e leve, ela piora o mapa nos três destinos, e piora mais no menor deles.

---

### 4d.6 DP6 — O piso de claridade NÃO se herda para polígono de município

**Decisão:** o piso de **6 pontos percentuais de espalhamento de claridade** — o número que
decide quando duas superfícies adjacentes se distinguem — **não vale para polígono de
município**, e não será herdado. Fica declarado como **calibração pendente**, a pagar quando
o coropleto (DP14) existir com dado real.

**Racional, que é aplicação direta da regra vigente e não decisão nova:** o supersede de
2026-08-11 (§4c.3 e §6) estabeleceu que **o piso é calibrado por FORMA de apresentação e vale
para aquela forma em qualquer meio** — e que forma nova exige recalibração por gate mesmo no
meio de sempre. Polígono de município é forma nova por três atributos simultâneos, nenhum
deles presente na forma em que o piso foi calibrado (barras altas adjacentes): é
**irregular**, tem **área muito variável** (dois vizinhos podem diferir em uma ordem de
grandeza) e tem **vizinhança imprevisível** (um município pode tocar dois ou onze outros).

**Por que não calibrar agora:** calibrar piso exige medir contra caso real. Sem dado por
município, o caso seria inventado — e um piso calibrado contra exemplo inventado é pior que
piso ausente, porque parece medição. Precedente direto: o `contraste-dg.py` v1 media três das
seis séries, dava verde, e **o verde impediu a procura por dois sub-blocos**.

**Pendência nominal DP-P3.**

---

### 4d.7 DP7 — Projeção: cônica EQUIVALENTE. Mercator é vetado

**Decisão:** o mapa SEED usa **projeção cônica equivalente (Albers)** — em `d3-geo`,
`geoConicEqualArea` com paralelos padrão calculados para o recorte MG-ES-BA. Datum de
referência: **SIRGAS 2000**, que é o que a malha de origem já traz (DP8). **Mercator, em
qualquer variante, é vetado.**

**Racional:** um coropleto compara áreas pintadas; se a projeção deforma área, o polígono
**mente sobre o dado antes de qualquer cor entrar**. A orientação técnica é explícita: ao
mapear valores num coropleto, usa-se projeção equivalente para que as áreas fiquem corretas
umas em relação às outras. A projeção de Albers é cônica equivalente com dois paralelos
padrão e é a usada no Brasil pelo IBGE; a referência técnica do próprio IBGE recomenda, para
cálculo de área no país inteiro, os parâmetros **longitude de origem -54°, latitude de origem
-12°, paralelos padrão -2° e -22°**.

**Racional do veto ao Mercator, com o número que o decide:** Mercator é o padrão de fato de
todo tutorial de mapa em React e de toda biblioteca de tiles, e deforma área em função da
latitude. Nosso recorte vai de aproximadamente **-8°** (norte da Bahia) a **-22°** (sul de
Minas). A deformação seria **sistemática e direcional**, inflando a Bahia contra Minas — num
mapa de atuação, isso é mentira visual da empresa sobre si mesma, e ela cresce justamente no
estado onde a SEED tem a operação mais recente.

**Fronteira declarada:** os parâmetros do IBGE citados acima são calibrados para o **Brasil
inteiro**. Para o recorte MG-ES-BA os paralelos padrão devem ser **recalculados**, por script,
com o valor resultante declarado no arquivo canônico e no asset. **Pendência nominal DP-P4.**

**Alternativa descartada:** projeção Policônica, usada pelo IBGE no mapeamento oficial em
escala geográfica. Cai porque não é equivalente nem conforme — só se aproxima disso perto do
meridiano central — e o DP precisa da propriedade de área preservada de forma garantida,
não aproximada.

---

### 4d.8 DP8 — Malha: IBGE, com o ANO declarado, versionada como asset do DS

**Decisão:** a fonte da geometria é a **Malha Municipal Digital (MMD) do IBGE**, publicada em
Shapefile e agrupada por estado, com **SIRGAS 2000** e codificação **UTF-8**. É convertida por
script para **TopoJSON** e versionada como **asset do próprio Design System** — não como
dependência de runtime instalada no ERP.

**Duas advertências do próprio IBGE entram no canônico, porque num laudo de engenharia elas
importam mais que a estética:**
1. Os limites da MMD devem ser entendidos como **aproximados**, e o IBGE se isenta de
   responsabilidade por usos que não sejam a compilação de dados estatísticos.
2. O IBGE **não tem atribuição legal** para definição e demarcação de limites territoriais.

**Consequência dura, que precisa estar escrita e não apenas sabida:** o mapa da SEED **não
serve como peça de definição de limite territorial**. Serve para localizar obra e comunicar
atuação. Se um dia um documento da empresa precisar afirmar de que município é um ponto para
efeito legal ou regulatório, a fonte é a documentação do imóvel e da concessionária — não este
mapa.

**Terceira consequência, operacional:** a MMD é **republicada anualmente**, e municípios
mudam de limite entre publicações. O asset **declara o ano no nome do arquivo e no
MANIFESTO**. Sem isso, dois mapas da empresa produzidos com seis meses de diferença podem
discordar sem que ninguém saiba por quê — a classe de defeito "artefato que mente sobre si
mesmo" já custou uma nota permanente no §3.1 do `MANIFESTO.md`.

**Alternativas descartadas:**
- *Pacote npm de malha brasileira.* O desenho poderia mudar numa atualização de dependência,
  sem pedido e sem gate — exatamente o risco que o **DF7** existe para evitar (tokens de dado
  têm uma fonte). Malha é geometria de dado; o argumento é o mesmo.
- *Base comercial editável (mapas de município vendidos como objeto de PowerPoint).* Existem e
  custam por estado. Caem porque devolvem geometria **digitada/desenhada** no lugar de
  geometria **calculada**, contra a regra de método do projeto, e porque a licença de
  redistribuição num PDF de cliente teria de ser auditada peça a peça.
- *Serviço de mapa hospedado (Google/Mapbox).* Já vetado no DP2 por identidade e impressão;
  soma-se aqui o custo por carregamento e a dependência de rede num documento que precisa
  funcionar off-line.

---

### 4d.9 DP9 — Simplificação por script, tolerância declarada, dois níveis de asset

**Decisão:** a malha é **simplificada por script** (algoritmo de Visvalingam, via `mapshaper`),
com **tolerância declarada no arquivo**, e o asset é publicado em **dois níveis de resolução**:

- **Nível FIGURA** — para o laudo, a proposta e o site; otimizado para larguras pequenas e
  para impressão a 300 dpi.
- **Nível ERP** — mais detalhado, para telas grandes e para a variante malha completa (DP5).

**Racional:** a malha municipal cheia dos três estados é inviável na web por peso, e
simplificar "no olho" produz um desenho que ninguém consegue reproduzir. Regra herdada e não
negociável do projeto: **geometria é calculada por script, nunca digitada**, e o script leva
asserção que falha se qualquer rótulo estourar o `viewBox` — o defeito de 9px do DM nasceu
exatamente da ausência dessa asserção.

**Pendência nominal DP-P5:** *qual* tolerância. Isso é **gate, não pesquisa** — a medição é
ver o desenho quebrar: o valor certo é o maior que ainda preserva a silhueta reconhecível do
estado e a identidade dos municípios de fronteira recortada.

**Alternativa descartada:** um único nível de asset servindo os três destinos. Cai porque os
requisitos são opostos — o que sobrevive a 300 dpi no papel é pesado demais para o site, e o
que é leve o bastante para o site perde detalhe visível na impressão.

---

### 4d.10 DP10 — Marcador: cor até 3 categorias, FORMA acima disso. Textura não se aplica

**Decisão (REESCRITA na v0.15 pela medição — ver errata E20):** a categoria de um marcador
(tipo de solução: fotovoltaico, subestação, GMG, projeto elétrico, consultoria) é codificada
pela **FORMA**, sempre; a **cor é redundância**, nunca o portador. Vocabulário de três
posições, e o teto é **3 categorias por mapa**:

| Posição | Forma |
|---|---|
| 1 | círculo |
| 2 | quadrado |
| 3 | triângulo |

**Teto de 3 categorias por mapa.** Acima disso, o mapa se reestrutura: um mapa por tipo de
solução (facetas), ou destaque × contexto no padrão do **DG17**.

**Paleta do marcador: `cat-1` (turquesa) · `cat-3` (magenta) · `cat-4` (azul).** O dourado
(`cat-2`) **fica de fora, e isso não é regra nova**: a regra do dourado da §3c já o veta como
*fill solitário sem rótulo direto*, e um marcador de mapa é precisamente um preenchimento
pequeno e solitário. Medido: `cat-2` contra o território mede **1,54–1,85** no light.

**O marcador leva contorno na variante `cat-N-stroke`.** Não é ornamento: o *fill* sozinho
reprova o piso de 3:1 contra o território no light — `cat-1` mede **2,97** e `cat-4` **3,05**.
Com o contorno: **4,23 · 5,23 · 3,05**. A variante `cat-N-stroke` existe no sistema exatamente
para isto, e a descrição dela nos gêmeos já nomeia o caso: *"traço fino (linha ≤3px, marcador
pequeno — o pior caso do 1.4.11)"*. **Isto não contraria o DG14**, que trata de superfícies
adjacentes separáveis por espaço negativo; o marcador é objeto solto sobre o território.

> **ERRATA E20 — contra a redação original do DP10 na v0.14.** A v0.14 dizia *"cor até 3
> categorias; acima de 3, forma"*, e **descartava explicitamente** a redundância cor+forma desde
> a primeira categoria, alegando ruído. **A medição inverte a decisão.** Espalhamento de
> claridade entre os marcadores, que é a métrica certa para distinguir superfícies (§4.4):
>
> | Par | Light | Dark |
> |---|---:|---:|
> | `cat-1` × `cat-3` | 6,8 pontos | **3,6** |
> | `cat-1` × `cat-4` | **0,9** | **3,7** |
> | `cat-3` × `cat-4` | 6,0 pontos | **0,2** |
>
> Piso de 6 pontos (calibrado pelo gate, **não** derivado de norma). **No tema escuro as três
> cores colapsam** — 0,2 a 3,7 pontos —, e mesmo no light o par `cat-1 × cat-4` mede **0,9**.
> Como o mapa vai obrigatoriamente para impressão (mono é grayscale por definição) e para o ERP
> (que tem tema escuro), **não existe cenário em que a cor sustente a categoria sozinha**.
> Logo a forma não é o plano B: é o portador. *A alternativa que a v0.14 descartou por "ruído"
> era a correta, e o que a derrubou foi eu ter raciocinado em vez de medir* — o mesmo erro
> registrado no §7 da v0.11 ("não diagnostique por raciocínio: meça").
> **Consequência sobre o gatilho:** em mapa não há gatilho condicional de forma como há para a
> textura (DI2). A forma é **permanente** a partir da 2ª categoria; com uma única categoria o
> marcador é círculo e não há o que distinguir.

**Racional, e este é o único ponto do DP que inventa vocabulário em vez de herdar.** O
**DI2** (§4c.2) manda texturizar por série quando `grayscale ∩ (escuro OU ≥4 séries)`. A
regra é boa e permanece vigente — **mas o veículo dela não existe aqui**. Textura precisa de
área para ser lida: quadriculado, pontilhado ou linhas verticais dentro de um marcador de
8–12px não produzem padrão, produzem sujeira, e em impressão a laser ou fotocópia produzem um
borrão. O DI2 não é contrariado; ele é **atendido por outro vocabulário**, porque a forma de
apresentação mudou — que é precisamente a lógica do supersede da regra do piso (§4c.3): o
instrumento vale para a **forma** em que foi calibrado.

**Consequência que é melhor descobrir agora:** o teto útil de categorias num mapa é **3**, e
não os 6 da categórica estendida. Um mapa da SEED não consegue mostrar os cinco pilares da
empresa como cinco marcadores distintos e continuar legível em escala de cinza. Isso é
restrição real e está declarada.

**Alternativas descartadas:**
- *Reduzir a hachura proporcionalmente ao tamanho do marcador.* É a mesma armadilha já
  rejeitada na extensão do vocabulário de textura (§4.4): a distinção viraria **densidade**,
  frágil no papel e pior ainda em fotocópia.
- *Losango, estrela e cruz como 4ª, 5ª e 6ª formas.* Caem porque perdem identidade a 8–12px:
  losango lê como quadrado girado e estrela lê como mancha. Círculo, quadrado e triângulo
  diferem em **número de vértices**, que é o atributo que sobrevive à redução.
- ~~*Cor + forma redundantes desde a 1ª categoria.*~~ **Esta alternativa foi descartada na v0.14
  e READMITIDA na v0.15 como a decisão vigente** — a medição mostrou que a premissa do descarte
  ("com uma ou duas categorias a cor resolve sozinha nos dois temas") é falsa: no dark os pares
  medem 0,2 a 3,7 pontos de claridade. Registro mantido à vista de propósito, porque descarte
  errado que some do arquivo volta a ser proposto.
- *Codificar a categoria pelo TAMANHO do marcador.* Cai porque tamanho já tem dono declarado
  (magnitude, ver regra de tamanho abaixo), e um atributo com dois donos é a estrutura do
  defeito que o DM3 corrigiu no medidor.

**Regra de tamanho:** o marcador tem **um papel de tamanho por vez**. Se o tamanho carrega
magnitude (potência instalada, por exemplo), ele não carrega também contagem de agrupamento
(DP11) no mesmo mapa. **Alvo de toque:** no ERP, a área clicável do marcador é de no mínimo
**44×44px**, independentemente do tamanho desenhado — o marcador visual pode ter 12px com área
de toque invisível maior.

---

### 4d.11 DP11 — Agrupamento, colisão e o halo

**Decisão:** município com **mais de uma obra** exibe **um marcador com contagem numérica**,
não vários pinos sobrepostos. O marcador leva **halo na cor do fundo do território** —
o mesmo mecanismo de espaço negativo do DG14.

**Racional:** pinos empilhados em município pequeno viram uma mancha cuja área não significa
nada, e a contagem que o leitor tentaria fazer visualmente estaria errada. O halo é legítimo
aqui — e não contraria o DG14 — porque o marcador é um objeto **solto sobre** o território,
não uma superfície adjacente a outra superfície de dado: existe espaço para o vão, que é
exatamente a condição que o DP4 declarou faltar entre municípios.

**A contagem exata vive no fallback textual do DP1.** O número no marcador é conveniência de
leitura; a tabela é a fonte.

---

### 4d.12 DP12 — LGPD: destino externo e destino interno são mapas diferentes

**Decisão:**

- **Destino externo** (site institucional, proposta comercial, material de marketing, qualquer
  peça que sai da empresa): o marcador comunica **município + tipo de solução + faixa de
  porte**. **Nunca** nome de cliente, **nunca** número de unidade consumidora (UC), **nunca**
  endereço, **nunca** razão social.
- **Destino interno** (ERP, atrás de autenticação): identificação permitida. A
  responsabilidade passa a ser do controle de acesso, não do desenho.

**Racional:** um pino rotulado com o nome do cliente num mapa de atuação exibido a um
**terceiro** expõe a carteira da empresa a quem não deveria vê-la, e o dado é pessoal
identificável quando o cliente é pessoa física ou produtor rural — o que é o caso comum na
carteira de irrigantes. Aqui a questão é de conformidade antes de ser de design, e o custo de
errar não é estético.

**Regra de fechamento, sem a qual a anterior não vale nada:** o **fallback textual do DP1
obedece à mesma separação**. Não adianta omitir o nome no mapa e vazá-lo na tabela ao lado —
e a tabela é justamente a parte que é copiada, exportada e colada em outro documento.

---

### 4d.13 DP13 — Impresso e interação

**Impresso — herança direta do sub-bloco DI, sem regra nova:**
- **DI4:** nenhuma informação do mapa pode viver em `background-color` de CSS. Território,
  fronteira e marcador são `<path>`/`<rect>`/`<circle>` com `fill`/`stroke` de SVG. Medido no
  DI: sob impressão econômica, o `background` de CSS **some** e o `fill` de SVG sobrevive.
- **DI5:** `break-inside: avoid` no `<figure>` inteiro — o mapa e a sua legenda nunca se
  partem entre páginas. Proteger o bloco **atômico**, nunca o contêiner que o agrupa (E18).
- **`@page` declara a orientação.** Um mapa dos três estados é mais alto que largo; se a
  figura pedir paisagem, a orientação vai em CSS. Precedente registrado: uma rodada de prova
  saiu em paisagem por opção herdada do driver e gerou 11 páginas no lugar de 6.
- **`vector-effect: non-scaling-stroke`** aplicado por **seletor universal** (`.plot svg *`),
  nunca em `<g>` — a propriedade **não é herdada** em SVG 2 (errata E17). Num mapa isso é
  crítico: o `viewBox` de um mapa escala muito mais que o de um gráfico de barras, e sem o
  atributo a hierarquia de traço de 1px e 0,5px do DP5 é destruída pelo layout responsivo.

**Interação:**
- **Figura fixa é a norma.** O mapa completo não depende de nenhuma interação para ser lido.
- **Tooltip** é permitido no ERP como **enriquecimento** e **nunca** como portador único de
  informação. Mesma lei do DG1: tooltip não existe no papel, e o que só vive nele não existe
  no laudo.
- **Zoom e pan estão FORA do escopo do DP.** São comportamento de tela, logo produto — mesma
  fronteira que já separou tempo real e websocket no DM10.
- **Teclado:** herda o **DG2** — o mapa inteiro é **um** tab-stop. O caminho de acesso real é
  a lista/tabela de municípios do DP1, não a navegação por marcadores.

---

### 4d.14 DP14 — O coropleto fica ESCRITO, não implementado

**Decisão:** o coropleto (mapa com municípios preenchidos por intensidade de cor) **não é
implementado neste sub-bloco**, mas fica especificado ao ponto de quem o implementar não
precisar tomar nenhuma decisão nova de design. O que já está decidido e vale quando ele for
ligado:

| Questão | Já decidido em |
|---|---|
| Escala de cor | **§3c do `seed-tokens.md`** — sequencial `chart-seq-1…7`, 100→900 no light e 800→100 no dark. A §3c já nomeia "mapa coroplético" como consumidor desde o DT |
| Condições obrigatórias da isenção 1.4.11 | §3c: (a) valor acessível por rótulo, tooltip ou tabela-fallback · (b) fronteira por `chart-grid` · (c) legenda com os limites numéricos das classes |
| Fronteira entre polígonos | **DP4** |
| Papel dos três estados do território | **DP3** |
| Projeção equivalente | **DP7** |
| Malha municipal completa e simplificação | **DP8**, **DP9** |
| Piso de claridade | **DP6** — pendente de calibração por gate |

**Racional de não implementar agora:** o coropleto pinta um **número por município**. A
empresa não tem hoje esse número organizado para os 1.348 municípios dos três estados, e um
coropleto sem dado real pinta ar. Implementá-lo agora custaria a calibração de piso do DP6 —
que só pode ser feita contra caso real — para produzir um artefato que ninguém consegue
alimentar.

**Alternativa descartada:** entregar ponto e coropleto em camadas sobrepostas desde já.
Cai por custo desproporcional: o marcador teria de ser legível por cima de **sete** tons de
fundo diferentes nos dois temas, o que é o pior caso de contraste do sistema inteiro, e
obrigaria a resolver dois problemas novos ao mesmo tempo — sem que o dado do coropleto
exista.

---

### 4d.14b DP15 — Ilhas oceânicas saem do DESENHO, nunca do dado

**Decisão (2026-08-11, aprovada pelo Rafael):** o arquipélago de **Trindade e
Martim Vaz**, administrativamente parte do município de **Vitória (ES)** e a cerca
de 1.100 km da costa, é **recortado do desenho** do mapa. O município de Vitória
permanece no mapa, na tabela e em qualquer agregação — o que sai é somente a
geometria das ilhas.

**Medição que motivou:** com as ilhas, a extensão de longitude do recorte vai a
**22,20°**; sem elas, a **13,70°**. São **8,5° de oceano vazio** — cerca de 40% da
largura da figura sem informação nenhuma, com os três estados espremidos no canto.
A variante malha completa do DP5 deixaria de funcionar e a leitura a 360px ficaria
inviável. **5 anéis removidos, 901 vértices, nenhum município removido.**

*Regra operacional:* o corte é por longitude declarada (**-35°**), valor que cai no
vazio entre o litoral continental do ES (≈ -39,7°) e o arquipélago (≈ -29,5°) — não
há ambiguidade possível.

*Alternativa descartada:* **inset com quebra de escala**, no padrão que os atlas usam
para Alasca e Havaí. Exigiria um componente novo — moldura, escala própria, marca de
descontinuidade — que o DP não especifica. Fica registrada como caminho.

**A exclusão é DECLARADA no asset e no preview, nunca silenciosa.** O espelho de
GitHub que serviu de fonte provisória fazia exatamente o mesmo corte **sem dizer**,
e isso só apareceu porque a extensão foi medida. *Fronteira já escrita no DP8 e que
sustenta esta decisão:* este mapa não é peça de definição de limite territorial.

---

### 4d.15 Matriz de render do DP — uma dimensão a mais

A matriz de render se **cruza, não se amostra** (regra da fase). O DP acrescenta uma dimensão
que nenhum sub-bloco anterior teve: **largura de renderização**, porque um mapa legível a
1200px pode ser ilegível a 360px e a malha exige simplificação diferente em cada faixa.

| Dimensão | Valores |
|---|---|
| Tema | claro · escuro |
| Grayscale | não · sim |
| **Largura** | **360 · 768 · 1200** |
| Impressão | tela · impresso (A4, com orientação declarada) |

O par que historicamente esconde defeito é **escuro × grayscale** (foi ali que morava o
colapso de séries do DG13). No DP, o par novo a vigiar é **360px × malha completa** — que o
DP5 já veta, e o teste existe para provar que o veto é real e não decorativo.

> **REGRA NOVA, nascida do gate visual de 2026-08-11 e mais geral que o DP: simular uma
> dimensão da matriz só vale se a simulação dirigir as MESMAS regras que a realidade dirige.**
> O preview v0.1 tinha um controle de largura que mudava o `max-width` do contêiner, enquanto as
> regras responsivas de layout respondiam à largura da **janela**. As duas coisas nunca se
> encontravam: ao escolher "360", as duas figuras do DP5 continuavam lado a lado, com cerca de
> **170px cada** — e o que estava na tela não era a célula 360 da matriz, era uma célula que não
> existe. **A dimensão largura nunca havia sido exercida.** Correção no preview v0.2: o contêiner
> vira *container de consulta* (`container-type: inline-size`) e as regras de layout passam a ser
> `@container`, de modo que o controle e a janela real disparem exatamente o mesmo conjunto de
> regras. Guardas permanentes `LARG-01` a `LARG-05` na `suite-dataviz-dp.mjs`; *prova de que são
> reais:* contra o preview v0.1, reprovam em **3**.
>
> *Classe de defeito:* **instrumento ancorado no lugar errado** — a mesma família de "teste
> ancorado no seletor errado" (DG7-03, `contraste-dg.py`, DI6-02), aqui aplicada não ao teste e
> sim ao **simulador**. E o achado é do olho humano: nenhuma das 68 verificações automatizadas
> via, porque jsdom não resolve layout e a suíte conferia a presença da regra, não quem a
> dispara. *Fronteira honesta:* isto é gate visual fazendo o que a automação não faz — o Rafael
> mandou uma captura da tela a 360px e a captura mostrava duas figuras onde deveria haver uma.

---

### 4d.16 Pendências nominais abertas pelo DP

Nenhuma bloqueia a escrita da spec; todas bloqueiam a promoção a `estável`.

| Id | Pendência | Como fecha |
|---|---|---|
| ~~**DP-P1**~~ | ~~Token do território de contexto e contraste contra a fronteira e o marcador~~ | **FECHADA na v0.15, no mesmo dia em que nasceu.** Instrumento: `contraste-dp.py` v1. Resultado: **dois** tokens novos (`chart-geo-base`, `chart-geo-boundary`) na v1.8 dos três gêmeos, mais as erratas **E19** (fronteira não é `chart-grid`) e **E20** (a forma é o portador da categoria, não a cor). *O que o episódio prova:* a pendência foi declarada como "medir na edição" e a medição **mudou duas decisões já aprovadas** — declarar pendência em vez de chutar valor foi o que impediu que as duas entrassem no preview |
| ~~**DP-P2**~~ | ~~Largura mínima de renderização para a variante malha completa~~ | **FECHADA em 2026-08-11, por medição sobre a malha real: a variante malha completa exige ≥ 640px de largura de renderização.** *Instrumento:* a fronteira de 0,5px é constante (`non-scaling-stroke`); o que varia com a largura é o **tamanho do município em pixels**. Medida a menor dimensão de cada um dos 1.348 municípios no viewBox de 640 — p5 **3,33** · mediana **7,42** · p75 **10,75** — e escalada por largura. *Piso declarado, calibrado aqui e **não** derivado de norma:* mediana ≥ **6px** e p5 ≥ **2px**, porque entre duas fronteiras de 0,5px precisa sobrar interior para o olho separar linha-interior-linha. Resultado: **360px** (mediana 4,17 · p5 1,87) e **480px** (5,56 · 2,50) reprovam; **640px** (7,42 · 3,33) passa. O veto do DP5 a 360px, que era inferência, passa a ser **fato medido**. Instrumento em `validacao/medir-dpp2.mjs` |
| ~~**DP-P3**~~ | ~~Piso de claridade para polígono de município~~ | **FECHADA em 2026-08-11 como DECISÃO, não como medição — e a distinção é o ponto.** O piso **não foi calibrado**: foi declarado **não herdável** (§4d.6) e adiado até existir coropleto com dado real. *Racional:* calibrar piso exige medir contra caso real; sem dado por município o caso seria inventado, e piso calibrado contra exemplo inventado é **pior que piso ausente**, porque parece medição. Precedente direto: o `contraste-dg.py` v1 media três das seis séries, dava verde, e **o verde impediu a procura por dois sub-blocos**. A pendência sai da lista do DP e entra como **pré-requisito declarado do DP14** — quem implementar o coropleto calibra o piso por gate antes de ligar |
| ~~**DP-P4**~~ | ~~Paralelos padrão da projeção para o recorte MG-ES-BA~~ | **FECHADA em 2026-08-11.** Calculados por script a partir da extensão real da malha oficial, pela regra de Deetz & Adams (paralelos a 1/6 e 5/6 da faixa de latitude): **-20,52°** e **-10,93°**, origem -15,73° / -44,19°. *Descartados:* os parâmetros que o IBGE recomenda para o Brasil inteiro (origem -54°/-12°, paralelos -2° e -22°) — são calibrados para um recorte 6× maior e jogariam os dois paralelos padrão para fora da área de interesse |
| ~~**DP-P5**~~ | ~~Tolerância de simplificação por nível de asset~~ | **FECHADA em 2026-08-11, e o resultado SUPERSEDIU o DP9** (§6): nível único a **2%**, com piso declarado de erro de área p99 ≤ 2%. Sete tolerâncias varridas e medidas |
| ~~**DP-P6**~~ | ~~Ano da Malha Municipal Digital do IBGE adotado~~ | **FECHADA em 2026-08-11: edição 2025**, baixada do portal oficial pelo Rafael e anexada em três pacotes Shapefile (MG, ES, BA), SIRGAS 2000, UTF-8. *Registro do que foi descartado:* antes disso a malha veio do espelho `tbrugz/geodata-br` no GitHub, porque o domínio do IBGE não é acessível da máquina de execução. As contagens batiam (853 · 78 · 417), mas a medição de vértices expôs a diferença — **143.319 no espelho contra 4.251.625 no oficial**: o espelho já era uma malha ~30× simplificada e não declarava isso |
| ~~**DP-P7**~~ | **A demonstração do coropleto (fig-dp3, "Os três estados do território") não desenha fronteira nenhuma — 1.404 polígonos, ZERO traço (MEDIDO em 2026-08-24, no navegador real, durante a prova visual da E19-b).** O DP4 é explícito em contrário: *"a fronteira entre regiões é desenhada, nunca deixada por conta da diferença de cor"*. Consequência visível na lupa 12×: dois municípios sem medição adjacentes **se fundem numa mancha só** — o leitor não sabe se é um ou três. | **FECHADA em 2026-08-24, veredito dele: "opção B é melhor".** O `gen-dp.py` passou a desenhar fronteira na variante `coropleto` como já fazia na `completa` — **medido depois: 1.348 fronteiras, `#788F9D`, espessura 0,5** (tinta vigente, espessura de apoio). O que tornou o conserto possível sem criar FAIL foi a própria **E19-b**: sem a exceção declarada, cumprir o DP4 aqui produziria dois pares abaixo do piso. Nada regrediu: suíte do DP 82·0, render 22·0, contraste 27·0 com as 3 exceções, escala-figura 93·0, paridade 235·0. *Registro do estado anterior:* não bloqueava nada (o coropleto é DP14 = escrito, não implementado), e por isso não é errata: é a demo que ilustra menos do que a spec manda. Fecha dando fronteira `chart-geo-boundary` (espessura `.5`, a `.fronteira.apoio` da própria bancada) aos polígonos do fig-dp3 — e é EXATAMENTE isso que a **E19-b torna possível sem criar FAIL**: sem a exceção declarada, cumprir o DP4 aqui produziria dois pares abaixo do piso. |

---

## 5. Fronteiras e pendências abertas

- ~~**Gêmeos `seed-tokens.json`/`seed-tokens.css`** a regenerar com a §3c~~ — **ENCERRADO
  em 2026-08-09**, na promoção do DT (o prazo declarado era exatamente este gate). Os dois
  gêmeos foram para **v1.4**. **Achado da execução:** o débito era MAIOR do que o §7.0
  dizia — os gêmeos declaravam `v1.1` e não continham **nenhum** token do pacote mobile
  v1.2 (M1–M3: breakpoints, tipografia fluida `clamp()`, `--seed-fs-field-touch`,
  safe-area). A defasagem era de **duas versões**, não uma. Detalhe no §7.0 do
  `seed-tokens.md` v1.4, com o supersede formal da redação antiga da pendência.
- ~~**DG** não escrito~~ — **ENCERRADO em 2026-08-09** (§4, 13 decisões, `estável`).
- ~~**DM** não escrito~~ — **`estável` desde 2026-08-11** (spec na v0.5 §4b, promoção pelo
  "aprovo" do Rafael sobre o lote de formalização). ~~**DP e DI** não escritos~~ — **o DI foi
  escrito na v0.9** (§4c) e **fechado por inteiro na v0.12**: DI-a e DI-b, ambos `estável` em
  2026-08-11 (o DI-b por prova impressa física — item próprio abaixo). ~~**Resta o DP**~~ — **o DP foi escrito na v0.14** (§4d, DP1–DP14) e é **`estável` desde
  2026-08-11**, por aprovação no gate visual sobre o preview v0.3. Ele abre seis pendências nominais próprias, **DP-P1 a
  DP-P6**, listadas no §4d.16; nenhuma bloqueia a spec e todas bloqueiam a promoção a
  `estável`. **Fechado o DP, a Fase 5 fecha e o marco é disparado** — e o marco tem um item
  obrigatório já decidido: a **auditoria de impacto das lacunas** do §6 do
  `estudo-viver-de-ia.md` (KPI/número-protagonista, ranking com barra embutida, progresso de
  conclusão, timeline e camada de movimento), para dizer, linha a linha, se cada lacuna é
  aditiva ou exige supersede em algo já `estável`.
- ~~**PREVIEWS APROVADOS AUSENTES DO DRIVE**~~ — **FECHADA em 2026-08-11** (pendência P6 do
  MANIFESTO, aberta e fechada no mesmo dia). O Rafael reanexou os dois arquivos da pasta local
  de downloads dos cards; a conferência bateu **2/2**: `seed-dataviz-graficos-preview.html`
  82.126 B `8d1930598b9d124d3807fc80f70b0fbf` e `seed-dataviz-monitoramento-preview.html`
  30.166 B `f146c84a3d140a892d1de87ee37d334c`. As suites foram re-executadas contra os
  artefatos reais (163·0 e 85·0·6). *Registro de método:* a leitura de volta pegou a ausência
  **antes** de qualquer perda — na §1 do MANIFESTO, a mesma classe de defeito só apareceu
  depois de um arquivo ter sido sobrescrito.

### Erratas abertas contra os previews aprovados (E1–E6, medidas em 2026-08-11)

Todas nasceram da execução das suites contra os artefatos REAIS, depois do gate visual. Nenhuma
altera decisão da spec — **onde o preview diverge da spec, quem manda é a spec**; a errata existe
para que a divergência não seja lida um dia como se fosse regra.

> **AS SEIS FORAM CORRIGIDAS em 2026-08-11 (v0.7).** Os previews passam a
> `seed-dataviz-graficos-preview.html` **v1.3** e `seed-dataviz-monitoramento-preview.html`
> **v0.8**, e as suites fecham em **163 PASS · 0 FAIL** e **105 PASS · 0 FAIL · 0 FAIL·DOC**.
> **Gate visual do Rafael em 2026-08-11: aprovado.** As v1.3/v0.8 passam a ser os artefatos
> VIGENTES do DG e do DM; as v1.2/v0.7 seguem ancoradas no MANIFESTO como o registro do que
> sustentou as promoções. As três correções visíveis que motivaram o gate — E1 (medidores expõem
> `role="meter"`), E3 (troca de cor do "esperado" do ET5 e da hachura do no-data) e E5 (rótulo da
> pizza sai de dentro da fatia) — foram vistas e aceitas. As versões v1.2/v0.7 permanecem ancoradas no MANIFESTO
> como os artefatos que sustentaram a promoção do DM.
>
> **Sétimo ponto, achado durante a correção e tratado dentro da E3:** a hachura do `chart-no-data`
> desenhava as linhas em `cat-5-stroke` — a mesma armadilha do ET5, e no lugar mais sensível
> possível, porque "sem medição" é justamente o que nunca pode parecer uma categoria. Passou a
> consumir `chart-axis`. **Regra que sai daqui:** posição categórica nunca serve de neutro. Quando
> um desenho precisa de "referência", "contexto" ou "ausência", ele consome um token com esse
> papel declarado (`chart-no-data`, `chart-grid`, `chart-axis`, ou cinza de contexto do DG17) —
> nunca `cat-N`, porque `cat-N` é uma posição de série e pode mudar de cor em qualquer supersede
> de paleta, como mudou.

| # | Errata (medida) | Onde | Consequência |
|---|---|---|---|
| ~~**E1**~~ ✔ | `role="meter"` **não implementado** no preview do DM — o arquivo só DESCREVE a regra num parágrafo explicativo (0 ocorrências do atributo) | monitoramento v0.7 | O **DM4 não foi validado pelo gate visual**, porque não havia o que ver. A regra permanece na spec e sua implementação real é do produto (`useMeter` do React Aria); o **próximo preview do DM deve implementá-la** para que o gate possa exercê-la com leitor de tela |
| ~~**E2**~~ ✔ | Sparkline a **1,6px**; a hierarquia de traço — declarada em comentário no PRÓPRIO arquivo — manda 2px para dado | monitoramento v0.7 | Traço de dado abaixo do peso canônico, entre "estrutura" (1px) e "dado" (2px). Corrigir para 2px na próxima edição do preview; a spec (§4.6) não muda |
| ~~**E3**~~ ✔ | O "esperado" do gráfico ET5 consome `chart-cat-5` | monitoramento v0.7 | **Consequência não intencional do supersede da categórica:** na v1.0 o `cat-5` era cinza-400 (neutro, correto para uma referência), e na **v1.5 virou violeta**. Referência de comparação não pode carregar cor de categoria viva. O ET5 deve consumir tinta neutra (`chart-no-data` ou `chart-grid`); o `medido` segue em `cat-1`. **Primeira consequência colateral medida do supersede — a classe de risco que qualquer troca de paleta cria** |
| ~~**E4**~~ ✔ | **Deriva de hex primitivo:** 4 dos 17 primitivos embutidos divergem da rampa do §2.1, nos DOIS previews (o bloco de tokens foi copiado entre eles): `cinza-300` `#A9BCC8`→`#ACBECA` · `cinza-50` `#F5F8FA`→`#F2F6F9` · `cinza-800` `#3A4A54`→`#38464F` · `turquesa-300` `#66D2C2`→`#66D1C2`. Somam-se os hex categóricos derivados inline no preview de gráficos (`#4FC3E8`, `#00506F`, `#A8DCEF`, `#FFD166`) | ambos | **Nenhum veredito muda** (remedição completa: espalhamento das bandas 9/10/19 light e 9/8/17 vs 10/8/18 canônico; tinta da meta 7,07 vs 7,24 — deltas ≤1 ponto). Mas prova que o bloco de tokens dos previews foi **digitado, não copiado** do canônico. *Guarda que nasce daqui:* preview novo deve importar o `seed-tokens.css` ou ter o bloco conferido contra a rampa por script |
| ~~**E5**~~ ✔ | Rótulo interno "45%" sobre a fatia `cat-1` da pizza | gráficos v1.2 | Na paleta v1.5 mede **4,30 < 4,5** — o rótulo vai para fora com linha-guia (DG5-b remedido, §4.2). Defeito latente que só apareceu porque a regra é medida, não fixa |
| ~~**E6**~~ ✔ | `<title>` e texto de abertura dizem **"preview v0.1"** nos DOIS arquivos (as versões reais são v1.2 e v0.7); o do DM ainda cita "§3c do `seed-tokens.md` v1.4" | ambos | **A "identificação positiva por leitura" do MANIFESTO §3.1 não funciona nestes dois arquivos** — só o MD5 os identifica. É a mesma família do defeito da §1 (afirmação que não encontra o seu objeto), aqui invertida: o arquivo mente sobre si mesmo. Corrigir rótulo e referência na próxima edição |
- **`contraste-dg.py` desatualizado (pendência P8 do `MANIFESTO.md`):** ainda mede o DG11
  (contorno morto) e a paleta antiga — e, o que só se soube em 2026-08-11, percorre apenas
  três séries, que são justamente as que passam. **Reclassificada de higiene para guarda
  ausente**: era ele quem deveria ter flagrado o colapso do modo claro acima de 3 séries.
  Especificação da reescrita no **DI18** (§4c.12); a execução é lote seguinte, junto do
  preview e da suíte do DI.
- **Aliases `gauge-band-*` nos gêmeos:** só nascem quando o produto consumir o medidor
  (fronteira declarada no supersede DM3 da §3c) — não antecipar.
- **Teto da empilhada (DG10-b):** o racional de paleta caiu com a categórica v1.5; o teto de 4
  permanece por não ter sido reavaliado em gate. Reavaliar (4→5) quando um caso real do ERP
  pedir, com preview e gate.
- ~~**EMENDA DEVIDA ao `seed-tokens.md` §3c** (regra GI2): registrar o colapso de claridade da
  rampa categórica escura~~ — **CUMPRIDA em 2026-08-11**, na edição v1.5 da §3c (o gatilho GI2
  "editar por outro motivo" disparou com a categórica estendida). O registro inclui a remedição
  com a paleta nova (75/75/71/71/67) e a consequência declarada: o DG13 permanece obrigatório.
- ~~**Textura em série preenchida no IMPRESSO (DI):** o DG13 hoje só dispara em escuro +
  grayscale, e o impresso sai do modo **claro**. Pela medição, o claro tem espalhamento
  suficiente (7 pontos)…~~ — **TRATADA em 2026-08-11 (v0.9), e a redação acima continha uma
  ERRATA (E7).** Os "7 pontos" eram da categórica **v1.0, com três séries**. Remedido com as
  **seis** posições da v1.5 em modo claro: pior par **1 ponto** (`cat-1 × cat-4` e
  `cat-3 × cat-5`). O claro **não** tinha margem estreita — tinha margem nenhuma acima de três
  séries. Resultado: **DI2** supersede o gatilho do DG13 (§4c.2), que passa a
  `grayscale ∩ (escuro OU ≥4 séries)`. *O que a errata ensina:* um número medido carrega o
  contexto em que foi medido; ao citá-lo depois de um supersede de paleta, o contexto tem de
  ser reconferido, não herdado. **A pergunta original — se o modo de impressão entra no
  gatilho — segue ABERTA no DI-b**, item abaixo.
- ~~**DI-b — veredito do gatilho da textura no papel (DI3, §4c.3).**~~ — **FECHADO em
  2026-08-11** por prova impressa física (folha de 7 itens, impressa em cor e em escala de cinza
  pelo driver). **Veredito: o impresso NÃO entra no gatilho, porque não precisa** — em cor as 6
  séries se distinguem; em mono, que é grayscale por definição, o DI2 já dispara. Os **dois pares
  que colapsaram a olho são os dois pares previstos pela medição em tela** (`cat-1 × cat-4` e
  `cat-3 × cat-5`, ambos a 1 ponto), sem falso positivo nem falso negativo. **Consequência maior
  que o veredito:** o piso de claridade é calibrado por **FORMA**, não por meio — supersede
  registrado no §4c.3 e no §6.
- **Empilhada 100%, waterfall, boxplot e combo de eixo duplo** ficaram fora da v1 do DG (DG9).
  Entram quando o ERP pedir — a spec é aditiva, nenhuma delas mexe no que foi promovido.
- ~~**Slot ET5 (gráfico do alerta de geração)**~~ — **ENCERRADO na v0.13 por supersede do DM8**
  (§4b): o e-mail de alerta **não leva gráfico**, leva símbolo de alerta. Racional do Rafael: um
  PNG único servido a todos os disparos carrega números que não são do destinatário, e um alerta
  que contradiz o próprio texto destrói a confiança que ele existe para ter. O dado real vive no
  sistema. **O slot volta ao `seed-email.md` sem regra nova** — o EC5 já manda rasterizar ícone
  sob demanda a partir do SVG normalizado, em `/email/v1/icones/`. **Deixa de ser pendência da
  dataviz.**
- **NM5 (ícones):** se a F5 expandir o set de glifos (ex.: ícones de tipo de gráfico),
  dispara o `seed-icones.md` próprio — gatilho registrado, não disparado.
- **Skeleton/empty de gráfico** (herdados do Bloco 3, 2026-08-04): entram no DG.
- ~~**Gauge em grayscale (observado no render de 2026-08-09):** o desenho canônico do gauge
  (DM) deve prever textura/hachura ou rótulo de faixa~~ — **CUMPRIDA na v0.5**: o DM entregou
  as duas previsões — rótulo textual de estado sempre visível (**DM7**) e textura por banda no
  gatilho escuro+grayscale (**DM11**). A prova impressa real continua no DI (o gatilho de
  textura no modo de impressão segue em aberto, item acima da textura no impresso).
- **Guarda nova nascida da promoção do DT — `paridade-tokens.py` (2026-08-09):** a regra
  "o `.md`, o `.json` e o `.css` formam uma unidade; alterar um exige alterar os três"
  existia desde a v1.0 do `seed-tokens.md` **sem nenhum detector**, e por isso os gêmeos
  ficaram duas versões atrás sem que ninguém notasse — ler o `.md` não revela nada sobre o
  conteúdo dos gêmeos. O script mede 3 portões: **G1 não-regressão** (todo token do CSS
  anterior continua existindo, com o mesmo valor), **G2 paridade** (todo token do JSON tem
  contraparte no CSS, salvo isentos declarados), **G3 cobertura** (o inventário nominal da
  §3c e do pacote v1.2 está nos dois gêmeos, em light e dark). Placar na promoção:
  **43 PASS · 0 FAIL**. *Fato relevante de método:* o G1 **reprovou a primeira tentativa de
  regeneração** — ela reescrevia o CSS inteiro a partir do JSON e, no caminho, renomeou
  `--seed-sp-*` para `--seed-space-*`, perdeu o composto `--seed-focus-ring` (que só existe
  no CSS) e serializou sombras/famílias/beziers como estrutura DTCG em vez de valor CSS. A
  entrega passou a ser por **edição cirúrgica** do arquivo anterior. Lição transferível:
  regeneração total a partir de um modelo incompleto perde token em silêncio; preservar
  bytes é mais seguro que reconstruir e conferir.
- **Matriz de render se CRUZA, não se amostra (2026-08-09, achado do gate do DG):** a primeira
  matriz tinha 4 cenários e cobria `claro+grayscale` e `escuro`, mas **nunca a combinação**
  `escuro+grayscale` — que era exatamente onde estava o defeito. Amostrar combinações dá a sensação
  de cobertura sem a cobertura. A matriz passou a 6 cenários cruzando tema × grayscale × largura, e
  o render mede o `fill` **resolvido pelo navegador**, cobrando textura onde deve haver e ausência
  onde não deve.
- **Aprendizado de ferramenta (2026-08-09):** o screenshot via CLI do Chrome
  (`--screenshot --window-size=360,...`) truncou a renderização à direita e simulou um
  overflow que não existia (scrollWidth medido: 360, zero elementos estourando). A
  camada de render da F5 usa **puppeteer** (viewport + `fullPage`), nunca o CLI — vale
  como requisito da futura suite de render do DG.

### Erratas E9–E16 (nascidas na janela do sub-bloco DI, 2026-08-11)

As E1–E6 (subseção acima) foram divergências do PREVIEW em relação à spec. Estas oito são de
natureza mais variada — e três delas são de uma classe nova e desconfortável: **correção
declarada que não foi inteiramente aplicada, ou que foi aplicada sem remedir o que quebrou.**

| # | Errata (medida) | Onde | Estado |
|---|---|---|---|
| **E7** | O §5 afirmava "o claro tem 7 pontos de espalhamento" — número da categórica v1.0 com **três** séries. Com as seis da v1.5 o pior par mede **1 ponto** | este arquivo, §5 | **RESOLVIDA** — motivou o DI2 |
| **E8** | A §3c do `seed-tokens.md` declara o fundo de referência dark como `#1C252B`; o token real é `#1D272D`. *Causa raiz achada depois:* o número foi copiado do **preview**, que embutia o valor errado — não do token | `seed-tokens.md` §3c | aberta; emenda registrada |
| **E9** | `seed-dataviz.md` v0.8 (74.897 B) ficou sem âncora no `MANIFESTO.md`, que ainda ancorava a v0.7 | `MANIFESTO.md` §3.7 | fecha na edição do MANIFESTO deste lote |
| **E10** | As cópias **v1.5** de `seed-tokens.json`/`.css` em `validacao/` não são declaradas em lugar nenhum. Mantidas de propósito pelo Rafael como insumo histórico da execução do `paridade-tokens.py` | `validacao/` | declarar em prosa, como já se faz com o `LEIA-ME` |
| **E11** | **Pizza de 5 séries sem textura alguma.** Violava o DG13 já na redação ANTIGA — o gatilho escuro ∩ grayscale se aplicava a ela e nunca foi implementado. Não é consequência do DI2; o DI2 apenas tornou visível | preview do DG v1.3 | **CORRIGIDA** na v1.4 |
| **E12** | O §6 deste arquivo afirmava, na linha do supersede do gatilho, que *"a suite extrai todos os seletores que ligam textura e exige as duas condições em cada um"*. **A suíte não tinha nenhuma seção de DG13.** 163 verificações, zero sobre a regra que o gate humano criou | §6 · `suite-dataviz-dg.mjs` | **CORRIGIDA** — seção `DG13/DI2` com 11 verificações + `E3/E13` com 2; suíte vai a **176 PASS · 0 FAIL** |
| **E13** | A hachura do `chart-no-data` apontada para `chart-axis` pela E3 mede **2,80** contra o preenchimento — abaixo do piso de 3:1. A E3 trocou um valor certo com semântica errada por um valor errado com semântica certa | `seed-tokens.md` §3c | **RESOLVIDA** — token próprio `chart-no-data-hatch` (v1.7): 3,93 light · 3,84 dark |
| **E14** | **A correção da E3 foi PARCIAL.** Ela trocou a tinta da hachura apenas no *swatch da legenda*; os **dois `<pattern>` SVG** que desenham a hachura de verdade continuaram em `chart-cat-5-stroke` — ou seja, em violeta — desde a v1.5. Quatro ocorrências | preview do DG v1.3 | **CORRIGIDA** na v1.4 |
| **E15** | **Terceira ocorrência da mesma armadilha:** a série "Esperada" do gráfico *medida × esperada* consumia `cat-5-stroke`. É referência, não categoria | preview do DG v1.3 | **CORRIGIDA** na v1.4 — passa a cinza de contexto (linha 4,74 · rótulo 6,55), o mesmo papel que o preview do DM adotou na E3 |
| **E16** | **Deriva de 19 tokens SEMÂNTICOS** no bloco embutido do preview, contra o canônico: `surface-page`/`raised`/`subtle` dark, `text-primary`/`secondary`/`inverse` dark, toda a família `feedback-danger`, `border-*` dark, `chart-grid`, `chart-positive`, `chart-negative`, `chart-no-data`. A E4 achara 4 **primitivos**; ninguém tinha auditado os semânticos | preview do DG v1.3 | **CORRIGIDA** na v1.4, **por script a partir do canônico** — que é literalmente a guarda que a E4 pediu |

| **E17** | **`vector-effect` não é herdada** (SVG 2: *Inherited: no*). Declará-la num `<g>` é inócuo — não alcança os `<path>` filhos. A primeira escrita do preview do DI cometeu isso; o preview do DG sempre fez certo, por seletor universal `.seed-chart__plot svg *`, que atinge cada elemento individualmente | preview do DI v0.1 | **CORRIGIDA** na v0.2 — regra por seletor universal + teste `DI6-04` que reprova qualquer `<g>` carregando o atributo. A lei do §4.6 estava certa; o que faltava era a implementação que a torna verdadeira |

> **A classe de defeito que E14 e E16 expõem, e que vale mais que as erratas em si.** A E3 foi
> declarada corrigida em 2026-08-11 e o arquivo nunca foi lido de volta *no ponto corrigido* —
> conferiu-se o MD5 (que muda com qualquer edição) e o placar da suíte (que não media aquilo).
> É a assinatura exata do defeito da §1 do `MANIFESTO.md`, agora numa variação mais sutil: não
> é "a propagação foi afirmada e não aconteceu", é **"a correção foi afirmada e aconteceu pela
> metade"**. *Regra que fica:* correção de errata é verificada pela **medição do que ela
> prometia consertar**, não pelo fato de o arquivo ter mudado. Se a errata dizia "a hachura não
> pode ser categórica", o teste é varrer TODAS as hachuras — foi o que o `NEU-01` passou a fazer.
>
> **A E16 fecha um ciclo aberto pela E4** e explica a **E8**: a §3c copiou o fundo de referência
> dark do *preview* (`#1C252B`) em vez de copiar do *token* (`#1D272D`). Bloco de token digitado
> à mão não contamina só o artefato — contamina o canônico que o cita.

### Emendas devidas a outros arquivos canônicos

| Arquivo | Emenda | Quando |
|---|---|---|
| `seed-email.md` v0.11 | Referenciar o PNG do gráfico do alerta (ET5) quando existir | Spec pronta (DM8); dispara quando o PNG @2x existir no R2 |
| `seed-componentes.md` v0.47 | Sparkline dentro da tabela §40 (célula de tendência) | **Gatilho cumprido** — gate do DM confirmou (DM5/DM6, §4b). A emenda entra na próxima edição real do `seed-componentes.md` (regra GI2), referenciando o contrato decorativo do DM6 |
| `seed-tokens.md` v1.6 §3c | **ERRATA E8 (medida em 2026-08-11):** a §3c declara o fundo de referência do dark como cartão `surface-raised` **`#1C252B`**; o valor real do token no `seed-tokens.css` é **`#1D272D`**. Corrigir o hex citado | **Nenhum veredito muda** — remedi as 6 séries contra os dois valores e os deltas ficam entre −0,16 e −0,24 (cat-1 8,50→8,31 · cat-6 10,66→10,42), todos com folga enorme sobre o piso de 3:1. Entra na próxima edição do arquivo por outro motivo (regra GI2), como a E3 entrou |
| `seed-componentes.md` v0.47 §44 | O **GI1** descreve a cadeia de 3 camadas para componentes de UI; para **gráfico** há um 4º salto (`--chart-N` → `chartConfig` → `var(--color-CHAVE)`), especificado no **DI11** (§4c.11) | Não é conflito: o GI1 continua correto no seu domínio. A emenda é uma referência cruzada, a entrar na próxima edição real do `seed-componentes.md` (regra GI2) |
| ~~`MANIFESTO.md` v1.1~~ | ~~Linhas deste arquivo, do `seed-tokens.md` e do `contraste-dataviz.py`~~ | **CUMPRIDA em 2026-08-09** — `MANIFESTO.md` **v1.2** ancora os artefatos da F5 (e fecha de quebra a pendência P4, do marco v1.5) |

---

## 6. Supersedes formais

| O que morre | O que passa a valer | Motivo |
|---|---|---|
| **DG10-d** — separar segmentos da pilha com traço de 1px em `surface-page` | **DG11** — contorno de 1px em `cinza-900` em toda superfície de área opaca | O branco mede **1,85** contra `cat-2` (amarelo): praticamente invisível. O `cinza-900` mede ≥4,17 contra todos os fills nos dois modos, e resolve fronteira contra o fundo **e** contra o vizinho — uma regra no lugar de duas. Descartado no caminho: contorno na variante `-stroke` da própria série (`cat-2-stroke` × `cat-1` = 1,28) |
| **Portão de grayscale por razão de contraste WCAG** (1ª versão do `contraste-dg.py`) | **Portão por espalhamento de claridade**, piso de 6 pontos | A razão de contraste foi calibrada para texto sobre fundo e reprovava o modo claro (`cat-1` × `cat-3` = 1,22), onde o gate humano leu bem. A claridade discrimina faixa: claro espalha 20 pontos, escuro 4. O piso está declarado no código como **calibrado pelo gate, não derivado de norma** |
| Gatilho da textura "escuro **OU** grayscale", e depois "só grayscale" | **Interseção escuro + grayscale** (DG13) | Duas leituras erradas da decisão do Rafael, ambas ligavam textura onde a cor já resolve. Guarda permanente: a suite extrai todos os seletores que ligam textura e exige as duas condições em cada um |
| **DG11** — contorno de 1px em `cinza-900` em toda superfície de área opaca | **DG14** — zero contorno; fronteira por vão de 2px na cor do cartão (espaço negativo) | Gate de estética de 2026-08-10 ("ar de relatório antigo"). A causa raiz do DG11 — fill que reprovava 3:1 sozinho — foi removida pela categórica estendida v1.5 (todos os fills ≥3,22; `cat-1` mudou de stop para isso). Cadeia completa: **DG10-d → DG11 → DG14**, cada elo com racional medido |
| A parte "e contorno" do **DG12** | DG12 restrito ao **rótulo interno** | O contorno morreu com o DG14; a regra da tinta fixa permanece viva para o rótulo. Exceção nova declarada: a meta do medidor ACOMPANHA a superfície, porque as bandas invertem com o tema (DM3) — 7,07/3,93 medidos |
| Categórica v1.0 (valores) e a restrição "nenhum hex novo" do DT | **Categórica ESTENDIDA v1.5** (§3c do `seed-tokens.md`) — 2 matizes exclusivos de dado, 5 famílias, `cat-1`→turquesa-500, regra do dourado, cinza fora | Racional medido: 3 matizes livres na marca ⇒ 6 posições sempre repetiam família ("escalas da mesma cor", crítica do gate). Leis de consumo na §4.6 |
| Racional de paleta do **DG10-b** ("acima de 4 pareia matizes") | Teto de 4 permanece; racional passa a ser o cognitivo do mercado | Com a v1.5, as posições 1–5 são famílias distintas — o fato de paleta sumiu. Teto não reavaliado em gate; pendência registrada no §5 |
| Papéis do gauge do DT (banda colorida carrega a severidade) | **DM3** — banda em intensidade de cinza; a barra de valor carrega a severidade | Faixas coloridas distavam 1 ponto (light) / 0 (dark) de claridade; Few manda codificar faixa em intensidade. Nenhum hex muda; supersede formal na §3c v1.5 |
| Piso de 6 pontos como critério geral de espalhamento | **Piso restrito ao contexto de calibração** (barras altas adjacentes, modo claro); fora dele decide o gate | No DM, bandas a 9/8/17 pontos — acima do piso — seguiam indistintas para o Rafael. Emenda no DG13; o DM11 nasceu dessa decisão de gate |
| **DG13** — gatilho da textura na interseção **escuro ∩ grayscale** | **DI2** — `grayscale ∩ (escuro OU ≥4 séries)` | Remedição de 2026-08-11 com as **seis** posições da categórica v1.5 em modo claro: `cat-1 × cat-4` = **1 ponto** e `cat-3 × cat-5` = **1 ponto** de claridade (56/75/49/55/50/27). O "a cor basta no claro" do DG13 valia para **três** séries, medidas na paleta v1.0 — a v1.5 dobrou as posições sem que o gatilho fosse remedido. O que muda é a densidade da paleta, não o meio. *Descartados:* somar só o impresso ao gatilho (deixaria aberto um colapso de tela já medido) · texturizar sempre (reprovado no gate de 2026-08-09) · baixar o piso de 6 para 1 (escolher o limiar para caber na paleta inverte instrumento e evidência) |
| A afirmação do §5 de que **o modo claro tem 7 pontos de espalhamento** (errata **E7**) | O claro tem **1 ponto** no pior par acima de 3 séries | Os 7 pontos são da categórica v1.0 com `cat-1/2/3`, corretos na data. Citar um número medido depois de um supersede de paleta exige reconferir o contexto, não herdá-lo. É a segunda consequência colateral medida do supersede da categórica — a primeira foi a E3 (ET5 em `cat-5`) |
| **DM8** — o e-mail de alerta de geração leva um **gráfico** (barra agrupada esperado × medido, PNG @2x no R2) | **O e-mail de alerta leva SÍMBOLO DE ALERTA, não gráfico.** O slot volta ao `seed-email.md` sob o EC5 (ícone raster sob demanda, `/email/v1/icones/`) | Gate de produção do asset, 2026-08-11. O PNG hospedado é **arquivo único servido a todos os disparos**: os números nele são necessariamente ilustrativos, e o cliente com desvio de 6% receberia imagem mostrando 18%, contradizendo o texto. Quem vê isso conclui que **o sistema erra**, não que a imagem é genérica — e alerta existe para ser confiável. *O e-mail avisa; o sistema mostra.* A correção não abre exceção: **reconduz o slot a uma lei que já existia** e que o DM8 havia contornado ao especificar um PNG de conteúdo. *Descartado:* gráfico gerado por usina no envio — não por mérito, mas por domínio; o DM10 já pôs comportamento dependente de dado vivo no produto (Lovable/Supabase), e isso é programação de sistema, não spec de DS |
| A regra do piso: *"o piso de 6 pontos decide apenas no contexto em que foi calibrado; fora dali quem decide é o gate"* — lida como **meio novo exige calibração nova** | **O piso é calibrado por FORMA de apresentação e vale para aquela forma em qualquer meio.** Forma nova exige recalibração por gate mesmo no meio de sempre | Prova impressa física de 2026-08-11 (§4c.3). O DI3 nasceu prevendo que papel exigiria piso próprio; **não exigiu**. Os dois pares que o Rafael não distinguiu na folha em escala de cinza são **exatamente** os dois que a medição em tela apontava a 1 ponto (`cat-1 × cat-4` e `cat-3 × cat-5`), sem falso positivo nem falso negativo em 15 pares. Comparando com o DM11 — bandas finas de medidor, 9/8/17 pontos, indistinguíveis **na tela** —, a variável discriminante aparece: forma diferente + mesmo meio → o instrumento erra; mesma forma + meio diferente → acerta. *Por que a regra nova é melhor:* a anterior mandava recalibrar a cada meio, o que é caro e desnecessário; a nova manda recalibrar a cada forma, que é onde o risco mora, e explica **os dois** episódios em vez de um. *Descartado:* manter a redação por "contexto", vaga o bastante para caber qualquer coisa e portanto incapaz de prever nada |
| Vocabulário de textura do **DG13 com 4 posições** | **6 posições** — acrescentam-se linhas verticais (série 5) e diagonal a 135° (série 6) | O teto de séries sempre foi 6; o vocabulário parava em 4. A lacuna era invisível porque o gatilho antigo nunca foi exercido contra um gráfico de 5 ou 6 séries — o único que existe estava sem textura nenhuma (errata E11). A 6ª usa 135° e não 45° porque **a diagonal a 45° é exclusiva do `chart-no-data`**, e é a exclusividade que impede "sem medição" de ser lido como categoria. *Descartados:* 45° com espaçamento diferente (a distinção viraria densidade, frágil no papel e em fotocópia) · pontos maiores para a 5 (lê como a textura 2 de perto) |
| A hachura do `chart-no-data` consumindo **`chart-axis`** (redação da errata E3) | **`chart-no-data-hatch`**, token próprio — cinza-600 light / cinza-400 dark (`seed-tokens.md` v1.7 §3c) | `chart-axis` é cinza-500 e mede **2,80** contra o preenchimento cinza-100, abaixo do piso de 3:1 (errata E13). A cadeia inteira do papel: `cat-5-stroke` (v1.0 — cinza-600 por acidente, passava com 3,93) → `chart-axis` (E3 — semântica certa, medição quebrada) → token próprio (3,93 / 3,84). *Descartado:* consumir o primitivo `cinza-700` direto — repetiria a estrutura do erro, que foi um papel de desenho existir sem token próprio e tomar emprestado o de outro papel |
| **DF2** como cobertura completa do consumidor web (shadcn Chart sobre Recharts v3) | DF2 vigente para os tipos core, monitoramento e derivados; **a família MAPA consome `d3-geo` + `topojson-client`** (DP2, §4d.2) | **Recharts não desenha mapa** — não há componente geográfico na biblioteca. Não é supersede do DF2 e sim o preenchimento de uma lacuna que ele tinha sem saber, por ter sido escrito quando mapa não era escopo. *Descartados:* mapa de tiles (Leaflet/MapLibre/Google/Mapbox) — traz base cartográfica de terceiro com estética própria, não imprime, e paga custo de render em pan/zoom que nem usamos · D3 puro sem invólucro — aqui a camada `d3-geo` é obrigatória de qualquer forma, o opcional é o wrapper acima dela |
| **DG14** lido como "nenhuma superfície de dado leva contorno, em qualquer forma" | **DG14 com escopo declarado:** vale onde a superfície é **separável por espaço negativo** (barra, segmento de pilha, fatia, área). Onde a geometria é **contígua** (mapa, heatmap), a fronteira é desenhada e consome `chart-grid` (DP4, §4d.4) | Território é contíguo: não existe vão entre dois municípios sem que se invente um. A regra que cobre o caso **já existia e está `estável` desde o DT** — condição (b) da §3c do `seed-tokens.md`, escrita junto com a isenção do WCAG 1.4.11 para heatmap. Por isso é precisão de escopo, não supersede: nenhuma decisão anterior deixa de valer. *Descartado:* erodir cada polígono para fabricar o vão de 2px — em município estreito a erosão consome a área, e na borda externa do estado ela abre canaleta contra o fundo, **inventando fronteira onde não há** |
| **DI2** aplicado literalmente ao mapa (textura por série quando `grayscale ∩ (escuro OU ≥4 séries)`) | **Em mapa, a distinção de categoria em escala de cinza é por FORMA do marcador** — círculo · quadrado · triângulo — com **teto de 3 categorias** (DP10, §4d.10) | O DI2 permanece vigente; o que muda é o **veículo**. Textura exige área para virar padrão: dentro de um marcador de 8–12px, quadriculado ou pontilhado não produzem padrão, produzem sujeira, e em impressão a laser ou fotocópia produzem borrão. É a mesma lógica do supersede da regra do piso (§4c.3): o instrumento vale para a **forma** em que foi calibrado. *Descartados:* hachura reduzida proporcionalmente ao marcador (a distinção viraria densidade, frágil no papel e pior em fotocópia — armadilha já rejeitada no vocabulário de textura) · losango, estrela e cruz como 4ª–6ª formas (perdem identidade a 8–12px; círculo/quadrado/triângulo diferem em **número de vértices**, atributo que sobrevive à redução) |
| **DP4 da v0.14** — a fronteira de município consome `chart-grid` | **`chart-geo-boundary`**, token próprio novo na v1.8 dos gêmeos (errata **E19**) | Medido em 2026-08-11 pelo `contraste-dp.py`: **`chart-grid` e `chart-no-data` têm o mesmo hex nos dois temas** (`#E3EBF0` / `#38464F`), então a fronteira **desaparece** sobre um município sem medição (razão **1,00**) e mede **1,11** contra o território de contexto. A condição (b) da §3c foi escrita para heatmap, onde a fronteira nunca separa dois cinzas; num mapa, separar dois cinzas é o caso normal. *Descartados:* `border-default` (1,37) · `border-strong` (2,33) · emprestar `chart-axis`, que passa numericamente mas **no dark é o mesmo hex do `chart-no-data-hatch`** — a estrutura exata da errata E3 |
| **DP10 da v0.14** — cor codifica a categoria até 3 marcadores; forma só acima disso | **A FORMA é o portador permanente da categoria; a cor é redundância** (errata **E20**) | Espalhamento de claridade medido entre os marcadores: no **dark** os três pares medem **3,6 · 3,7 · 0,2** pontos, e mesmo no **light** o par `cat-1 × cat-4` mede **0,9** — todos abaixo do piso de 6. Como o mapa vai para impressão (mono é grayscale por definição) e para o ERP (tema escuro), **não existe cenário em que a cor sustente a categoria sozinha**. *Registro desconfortável:* a alternativa correta estava escrita na v0.14 e foi descartada **por raciocínio** ("cria distinção sem informação"), sem medição — o erro que o §7 da v0.11 já havia nomeado |
| **DP9** — a malha é publicada em **DOIS níveis** de resolução (figura e ERP) | **UM único asset**, simplificado a **2%** (Visvalingam com topologia preservada) | Medido em 2026-08-11 sobre a Malha Municipal Digital do IBGE 2025, com instrumento próprio (erro de área por município na projeção real). **A previsão do DP9 era que o nível de papel seria pesado demais para o site — a diferença medida entre os dois níveis é de 192 KB** (710 KB contra 518 KB), porque abaixo de 1% quem domina o arquivo é a quantização, não a contagem de vértices. Dois assets da mesma geometria por 192 KB é uma segunda fonte de verdade em troca de quase nada, exatamente o que o **DF7** existe para impedir. **Piso declarado do nível único: erro de área no p99 ≤ 2%** (medido: **1,78%**), porque é este o nível que hospedará o coropleto do DP14, onde a área desenhada é o que compara os dados. *Descartados com número:* 1% (p99 **4,08%**, pior município **20,5%**) · 0,5% (p99 9,70%) · 0,2% (p99 23,24%) · 0,05% (p99 68,55%, e economiza apenas 208 KB sobre o 1%). *Caso-limite achado pelo instrumento sozinho:* **Santa Cruz de Minas (MG), 3,565 km²**, o menor município de Minas — a 2% erra 4,2%; a 1%, 20,5% |
| *(do DT, inalterado)* nada | — | Sequencial, no-data, divergente, gauge-tokens e strokes v1.3 seguem intocados |

---

## 7. Registro de versões

| Versão | Data | Conteúdo |
|---|---|---|
| **0.22** | 2026-08-24 | **A DP-P7 FECHA no mesmo dia em que nasceu, por veredito ("opção B é melhor"): o coropleto passa a desenhar a fronteira que o DP4 obriga.** O `gen-dp.py` deixou de tratar a variante `coropleto` no ramo dos municípios com obra (que no coropleto é vazio) e passou a desenhar em todos, como a `completa`. Medido depois: 1.348 fronteiras em `#788F9D` a 0,5 de espessura. **A E19-b é o que permitiu o conserto sem FAIL.** Nenhum hex muda, nenhuma decisão de cor muda — muda o que É DESENHADO. |
| **0.21** | 2026-08-24 | **Nasce a E19-b — exceção declarada por veredito na fronteira geográfica sobre o sem-medição.** O porte da camada de validação (F7.7-P1) mediu o que a E19 não tinha medido: no claro a tinta adotada rende 2,80 sobre `chart-no-data`/`surface-sunken` (o par canonizado, sobre o contexto, segue 3,11 PASS). Veredito do Rafael, saída (a): aceitar como exceção declarada — a hachura é o segundo separador (1.4.11 cobra o par só quando ele é o ÚNICO identificador); mesmo veredito para cat-2-stroke × sunken (2,89), cujo segundo portador é a FORMA (E20). Candidatas medidas e descartadas: ci-600 (colide em valor com a hachura — estrutura E3) e ci-700 (dobra o peso do traço). NENHUM hex muda; a exceção vira categoria própria `[exceção]` no `contraste-dp.py`, com número impresso. Placar: 27 PASS · 0 FAIL · 3 exceções. **A prova visual da decisão (mapa real, lupa 12× por captura) achou de carona a pendência DP-P7:** a demo do coropleto não desenha fronteira nenhuma, contra o DP4 — e a E19-b é o que permite consertá-la sem criar FAIL. |
| **0.20** | 2026-08-11 | **GATE VISUAL DO PREVIEW v0.4 APROVADO — o sub-bloco DP fica SEM NENHUMA PENDÊNCIA ABERTA, e com isso a Fase 5 fecha sem ponta solta.** Nenhuma decisão de conteúdo muda: é mudança de estado mais o registro que a aprovação obriga. **As seis pendências nominais do DP, todas fechadas no mesmo dia em que o sub-bloco nasceu:** DP-P1 (token do território e da fronteira — fechou com dois tokens novos e as erratas E19/E20) · DP-P2 (largura mínima da variante malha completa — **medida agora: ≥ 640px**) · DP-P3 (piso de claridade do polígono — **fecha como decisão**, com o piso declarado NÃO herdável e transferido ao DP14) · DP-P4 (paralelos da projeção) · DP-P5 (tolerância de simplificação, que superseiu o DP9) · DP-P6 (edição da Malha Municipal Digital). **Placar final das quatro camadas com a geografia real:** jsdom **82 PASS · 0 FAIL** · render em Chrome real **22 PASS · 0 FAIL** · contraste **27 PASS** com 23 candidatas reprovadas de propósito · **gate visual aprovado**. *Nota de fronteira sobre a DP-P3, para que ninguém a leia como resolvida por decreto:* o piso de claridade para polígono de município **não foi calibrado** — foi declarado como **não herdável** e adiado até existir um coropleto com dado real, porque calibrar contra exemplo inventado produz o verde que impede a procura. A pendência fecha como **decisão**, não como medição, e isso está escrito no §4d.6. |
| **0.19** | 2026-08-11 | **A MALHA REAL DO IBGE ENTRA E FECHA TRÊS PENDÊNCIAS (DP-P4, DP-P5, DP-P6). O preview deixa de usar malha sintética.** Fonte: **Malha Municipal Digital do IBGE, edição 2025**, baixada do portal oficial pelo Rafael em três pacotes Shapefile (MG, ES, BA), SIRGAS 2000, UTF-8 — **1.348 municípios, 4.251.625 vértices, 135,9 MB de GeoJSON bruto**. *Registro de fonte descartada:* antes disso a malha veio do espelho `tbrugz/geodata-br` (GitHub, CC0), porque o domínio do IBGE não é acessível da máquina de execução; as contagens batiam, mas os vértices não — **143.319 contra 4.251.625**. O espelho já era ~30× simplificado e não declarava. **DP15 (novo, §4d.14b):** as ilhas oceânicas de Vitória saem do desenho, não do dado — a extensão de longitude cai de **22,20° para 13,70°**, evitando 40% de figura em oceano vazio. **DP-P4 fechada:** paralelos **-20,52° / -10,93°** calculados da extensão real. **DP-P5 fechada, e o resultado SUPERSEDIU o DP9:** um único asset a 2%, no lugar de dois níveis — a diferença medida entre os níveis era de **192 KB**, e duas fontes da mesma geometria por isso viola o DF7. Piso declarado: **erro de área p99 ≤ 2%** (medido 1,78%). **DP-P6 fechada: edição 2025**, no nome do asset. **Instrumento novo:** erro de área por município medido na projeção real, contra a malha bruta — é a métrica certa porque num coropleto a área desenhada é o que compara os dados. Caso-limite achado sozinho: **Santa Cruz de Minas (MG), 3,565 km²**, erra 4,2% a 2% e 20,5% a 1%. **Preview a v0.4**, com a malha oficial renderizada pela cadeia REAL do DP2 (`d3-geo` + `topojson-client`). Suíte a **82 PASS · 0 FAIL** (era 77) e render **22 PASS · 0 FAIL**. **Três defeitos achados na inspeção das capturas, nenhum visto pela automação:** (1) a tabela do fallback **transbordava 8px a 360px** — corrigida com o contêiner rolável nomeado e focável do Bloco 6; (2) a descrição do DP1 ainda dizia **"malha sintética"** depois da troca — artefato mentindo sobre si mesmo, a classe da errata E6; (3) **dois códigos IBGE digitados de memória apontavam para municípios errados** (Vitória virou Cariacica, Cachoeiro virou São Mateus): o preview ficava correto e dizendo outra coisa. *Regra que sai daqui:* **identificador digitado de cabeça é a mesma classe de defeito que a regra "geometria é calculada, nunca digitada" já cobria** — a seleção passou a ser resolvida por nome contra a própria malha, com asserção. |
| **0.18** | 2026-08-11 | **PROMOÇÃO: o sub-bloco DP passa a `estável` e A FASE 5 ESTÁ FECHADA.** Os seis sub-blocos — DF, DT, DG, DM, DI e DP — são todos `estável`, e o marco **v1.6** é disparado. Nenhuma decisão de conteúdo muda nesta versão: é mudança de ESTADO mais o registro que a promoção obriga. **Placar final das quatro camadas de validação do DP:** jsdom **77 PASS · 0 FAIL** · render em Chrome real **22 PASS · 0 FAIL** · contraste **27 PASS** com 23 candidatas reprovadas de propósito (é a evidência que fundamenta os dois tokens novos) · gate visual **aprovado**. **Fronteira do que o gate cobriu:** o Rafael inspecionou o preview v0.2 e respondeu os cinco pontos do protocolo; a v0.3 difere em um único ponto (a tinta da contagem, corrigida pelo DG12) e foi aprovada sobre relato de medição e de inspeção de captura. Registrado porque *fato e inferência se declaram separados*. **Pendências que o DP leva consigo para a Fase 6, todas declaradas:** DP-P2 (largura mínima da variante malha completa) · DP-P3 (piso de claridade do polígono de município, que só fecha com coropleto de dado real) · DP-P4 (paralelos da projeção para o recorte MG-ES-BA) · DP-P5 (tolerância de simplificação) · DP-P6 (ano da Malha Municipal Digital do IBGE). **O preview usa malha SINTÉTICA declarada** enquanto a DP-P6 não fecha. **Item obrigatório do marco, executado:** a AUDITORIA DE IMPACTO DAS LACUNAS do §6 do `estudo-viver-de-ia.md`, agora na §6b daquele arquivo (v1.3). Veredito: **nenhuma lacuna exige supersede em algo `estável`**; e uma das cinco lacunas vermelhas **não existia** — a "camada de movimento" está nos gêmeos desde a camada de primitivos (errata E-EST1). |
| **0.17** | 2026-08-11 | **A camada de RENDER do sub-bloco DP foi executada — e ela havia sido PULADA em silêncio nos lotes anteriores.** Cobrança do Rafael, correta: *"você precisa rodar o teste e enxergar essas coisas antes de eu testar"*. **Fato registrado sem atenuante:** nos lotes das v0.14–v0.16 eu verifiquei que não havia navegador headless na máquina, **não avisei, e segui** — de modo que a régua de quatro camadas (jsdom · render · contraste · gate humano) rodou com três. O defeito das 360px morava exatamente na camada ausente. Ambiente resolvido com o binário de Chromium empacotado em npm (`@sparticuz/chromium` + `puppeteer-core`), já que o download normal do Chrome não passa pela rede desta máquina. **Nasce a `render-dp.mjs`: 22 PASS · 0 FAIL**, medindo o que jsdom não vê — colapso real da grade em cada largura (R1), equivalência entre o controle de largura e o redimensionamento real da janela (R2, a regra do §4d.15), estouro de viewBox por `getBBox()` em navegador real (R3), espessura RENDERIZADA das fronteiras com o viewBox escalando 0,82× (R4, prova do `non-scaling-stroke`) e ausência de transbordo horizontal (R5). **O defeito que só a inspeção das capturas achou, e que é violação de regra existente:** a contagem de agrupamento do DP11 estava pintada em **branco fixo**. O **DG12** determina há dois sub-blocos que *tinta sobre dado não segue o tema* e consome `cinza-900` nos dois modos, **porque o fill categórico é claro nos dois modos**. Medido: branco contra os fills do tema escuro dá **1,83 · 2,04 · 2,05**; `cinza-900` dá **7,57 · 6,80 · 6,77** no escuro e **4,30 · 3,40 · 4,17** no claro. Preview a **v0.3**, guardas `DP11-02b/c/d` na suíte (**77 PASS · 0 FAIL**, era 74); *prova de que são reais:* contra o preview v0.2, reprovam em **2**. *Classe do defeito:* **regra do sistema não aplicada em consumidor novo** — o DG12 nasceu para rótulo interno de barra e fatia, e o marcador de mapa é rótulo interno também; ninguém fez a ligação. Parente direto da E19, que herdou de outro consumidor sem remedir. **Lição de método, e é a mais cara deste sub-bloco:** *camada de validação indisponível não é camada dispensável — é pendência a declarar.* Pular em silêncio produz o mesmo verde de quando tudo passou. Nenhuma decisão de spec mudou nesta versão. |
| **0.16** | 2026-08-11 | **O gate visual do Rafael achou um defeito que 68 verificações automatizadas não viam — e o defeito era no INSTRUMENTO, não no desenho.** Ele testou os cinco pontos do gate no preview v0.1 e mandou uma captura da tela a 360px: **as duas figuras do DP5 apareciam lado a lado**, com cerca de 170px cada, em vez de empilhadas. Causa medida: o controle de largura da barra mudava o `max-width` do contêiner, enquanto a regra que empilha a grade era uma `@media` ancorada na largura da **janela** — que continuava larga. **Consequência dura: a dimensão "largura" da matriz de render nunca foi exercida de verdade**; o que aparecia na tela ao escolher "360" era uma célula que não existe na matriz. **Regra nova, registrada no §4d.15 e mais geral que o sub-bloco:** *simular uma dimensão da matriz só vale se a simulação dirigir as MESMAS regras que a realidade dirige.* **Correção:** preview a **v0.2**, com o contêiner virando container de consulta (`container-type: inline-size`) e as regras de layout passando a `@container` — assim o controle e a janela real disparam o mesmo conjunto de regras. Guardas novas `LARG-01`…`LARG-05` na suíte; *prova de que são reais:* contra o preview v0.1, reprovam em **3**. **Segunda correção de âncora no mesmo lote:** a verificação `HIG-03` procurava a string literal `preview v0.1` no título — guarda que quebra a cada revisão e que, pior, convida a mentir de volta, que é exatamente a errata **E6**. Passou a exigir que o título declare *alguma* versão e que ela seja **a mesma do `<h1>`**. **Placar da suíte: 74 PASS · 0 FAIL** (era 68). *O que o episódio prova, e é o motivo de o gate visual ser estruturalmente não-opcional:* nenhuma das verificações automatizadas via o defeito, porque jsdom não resolve layout e a suíte conferia a **presença** da regra, não **quem a dispara**. Nenhuma decisão de spec do DP mudou nesta versão. |
| **0.15** | 2026-08-11 | **A medição do DP mudou DUAS decisões que já haviam sido aprovadas no gate — e fechou a pendência DP-P1 no mesmo dia em que ela nasceu.** Nasce o `contraste-dp.py` v1, instrumento do sub-bloco DP, que extrai os hex do `seed-tokens.css` em vez de digitá-los (lição das erratas E4/E16) e mede seis famílias de pares nos dois temas: colisões de valor entre papéis, território × fronteira, território × sem-medição, hachura, marcador × território e marcadores entre si em escala de cinza. **Achado 1, que é um fato do sistema e não do mapa:** `chart-grid` e `chart-no-data` **têm o mesmo hex nos dois temas** (`#E3EBF0` light, `#38464F` dark) — o que torna a condição (b) da §3c (*"fronteira sustentada por `chart-grid`"*) **impossível de cumprir sobre uma célula sem medição**, com razão **1,00**. O defeito é antigo e nunca apareceu porque no heatmap a célula no-data é hachurada e as vizinhas são sequenciais saturadas: a fronteira nunca precisava separar dois cinzas. Num mapa, separar dois cinzas é o caso normal. **Errata E19** e supersede no §6. **Achado 2:** no tema escuro `chart-axis` é o mesmo hex do `chart-no-data-hatch` (`#90A6B3`) — logo emprestar `chart-axis` para a fronteira repetiria a estrutura da **E3**. Daí **dois tokens novos** na v1.8 dos três gêmeos: `chart-geo-base` (território de contexto) e `chart-geo-boundary` (fronteira), ambos com **valor idêntico a tokens existentes de propósito** — o que muda não é a cor, é a responsabilidade de mantê-la. **Achado 3, o mais incômodo:** o **DP10** dizia "cor até 3 categorias, forma acima disso", e **descartava por raciocínio** a redundância cor+forma desde a primeira. A medição inverte: no dark os três pares de marcador medem **3,6 · 3,7 · 0,2** pontos de claridade e no light o par `cat-1 × cat-4` mede **0,9**, todos abaixo do piso de 6. **A forma passa a ser o portador permanente da categoria e a cor vira redundância** (**errata E20**). O dourado sai da paleta de marcador por aplicação da **regra do dourado que já existia** (fill pequeno e solitário), e o marcador ganha contorno em `cat-N-stroke`, cuja própria descrição nos gêmeos nomeia o caso: *"marcador pequeno — o pior caso do 1.4.11"*. **Lição de método, terceira ocorrência registrada:** *não diagnostique por raciocínio, meça* — aqui o raciocínio não errou um diagnóstico, errou uma **decisão de design aprovada**, e o que a pegou foi a pendência ter sido declarada em vez de resolvida por escolha. **Gêmeos a v1.8** (adição pura: nenhum valor anterior muda) e a guarda `paridade-tokens.py` estendida para os dois tokens novos — **52 PASS · 0 FAIL**, e *prova de que a guarda nova é real:* rodada contra o CSS v1.7, reprova em **4**. **Errata E8 CORRIGIDA de passagem** na mesma edição, pela regra GI2: a §3c citava o fundo dark `#1C252B`, e o token é `#1D272D`. **Pendente deste lote:** preview do DP construído **sobre a spec corrigida**, suíte, gate visual e a edição do `MANIFESTO.md`. |
| **0.14** | 2026-08-11 | **Spec do sub-bloco DP — mapas de atuação MG-ES-BA — em §4d, DP1–DP14. Com ela, os SEIS sub-blocos da Fase 5 existem; falta o gate visual do DP para fechar a fase.** Consolidado aprovado pelo Rafael após 3 rodadas encadeadas de pesquisa (R1 canon interno · R2 mercado/stack de mapa em React · R3 normas: IBGE, projeção cartográfica, acessibilidade de mapa). **Escopo decidido em briefing ANTES da pesquisa** — pontos e não coropleto, três destinos (impresso, ERP, site), figura fixa, três níveis geográficos, sem identificação de cliente em peça externa, sem fonte de malha preexistente na empresa. *Registro de método:* a primeira formulação da pergunta (d) foi respondida com uma correção do Rafael — a proposta de dois níveis (estado + ponto) foi recusada com *"eu tenho que ter todos os municípios"*, e a redação da proposta induzia a leitura errada de que municípios sem obra sumiriam do mapa; a decisão final (DP5) mantém o território sempre inteiro e torna seletiva apenas a **linha de fronteira**. **Três achados da R1 mudaram o desenho:** (1) a §3c do `seed-tokens.md` **já nomeia "mapa coroplético"** como consumidor da escala sequencial e **já traz as três condições obrigatórias** da isenção do WCAG 1.4.11 — entre elas *fronteira por `chart-grid`*, o que dispensa o supersede do DG14 que eu previa e o reduz a **precisão de escopo** (DP4); (2) o traço de **0,5px seguia sem consumidor** e a fronteira municipal da variante malha completa é o primeiro (DP5); (3) o **DF2 tem uma lacuna**: declara shadcn Chart sobre Recharts como consumidor canônico web, e **Recharts não desenha mapa** — emenda formal no §6. **Achado da R2/R3:** projeção **equivalente** (Albers) é obrigatória e **Mercator é vetado**, porque nosso recorte vai de ~-8° a ~-22° de latitude e a deformação de área seria sistemática e direcional, inflando a Bahia contra Minas — mentira visual da empresa sobre si mesma. **Achado que inventa vocabulário, o único do sub-bloco:** o **DI2** manda texturizar, mas textura não cabe num marcador de 8–12px; em mapa a distinção em escala de cinza passa a ser por **forma** (círculo/quadrado/triângulo), com **teto de 3 categorias** — menor que o teto de 6 da categórica, e portanto um mapa da SEED **não** consegue mostrar os cinco pilares como cinco marcadores legíveis em mono. **Advertências do IBGE que entram no canônico** (DP8): os limites da Malha Municipal Digital são **aproximados**, o IBGE **não tem atribuição legal** de demarcação, e a malha é **republicada anualmente** — logo o mapa da SEED não serve como peça de definição de limite territorial, e o asset declara o ano. **Matriz de render ganha dimensão nova:** largura de renderização (360 · 768 · 1200), cruzada com tema × grayscale × impressão. **Seis pendências nominais nascem declaradas (DP-P1…DP-P6, §4d.16)**, nenhuma bloqueando a spec e todas bloqueando a promoção a `estável`. **Pendente deste lote:** preview do DP, suíte, gate visual do Rafael e a edição do `MANIFESTO.md` que ancora este arquivo e os artefatos do DP. |
| **0.13** | 2026-08-11 | **SUPERSEDE do DM8: o e-mail de alerta de geração não leva gráfico.** Decisão do Rafael no gate de produção do asset, contra o desenho que eu havia especificado e produzido. **Racional, que é mais forte que o original:** o PNG hospedado no R2 é arquivo único servido a **todos** os disparos, logo os números nele são ilustrativos — o cliente cujo desvio real é de 6% receberia um e-mail com imagem mostrando 18%, contradizendo o texto ao lado. Quem vê isso não conclui "a imagem é genérica", conclui que **o sistema erra**; e um alerta existe precisamente para ser confiável. Regra vigente: **o e-mail avisa, o sistema mostra** — dado real vive onde o cliente entra para ver. **O slot ET5 sai da dataviz e volta ao `seed-email.md` SEM REGRA NOVA:** o **EC5** já determina ícone raster sob demanda, rasterizado do SVG normalizado quando um template o pede, em `/email/v1/icones/`; um template de alerta pedindo glifo de alerta é o caso previsto, e o DM8 havia **contornado** essa lei ao especificar um PNG de conteúdo. *Descartado:* gráfico gerado por usina no envio — não por mérito, mas por domínio, já que o DM10 pôs comportamento dependente de dado vivo no produto. *Registro material:* o PNG `seed-email-et5-grafico@2x.png` (1120×520 @2x, 28.441 B, MD5 `f2ad29b3a8075da85c67f157399711fd`) chegou a ser produzido, com fonte SVG e gerador, e **foi descartado sem subir ao R2** — fica anotado que existiu para que ninguém o ache num diretório de trabalho e o suba supondo propagação pendente. O **DI19** permanece válido quanto ao caminho e muda de objeto. **Lição de método:** a spec do DM8 foi escrita sem perguntar *de quem é o dado que a peça mostra* — a pergunta que o gate fez em dez segundos e que teria evitado a produção inteira. |
| **0.12** | 2026-08-11 | **DI-b FECHADO por prova impressa física. O sub-bloco DI está completo e a Fase 5 fica a um sub-bloco do marco.** (1) Produzida a **folha de prova de 7 itens** (`seed-dataviz-di-prova-impressa.pdf`, A4 retrato com orientação declarada em CSS, 3 páginas, questionário de 6 perguntas na última) e impressa pelo Rafael **duas vezes na mesma impressora física**, em cor e em escala de cinza pelo driver. (2) **Veredito do DI3: o modo de impressão NÃO entra no gatilho da textura, porque não precisa.** Em cor as 6 séries se distinguem — textura ali seria o ruído que derrubou o DG11. Em mono, que **é grayscale por definição**, o gatilho do DI2 já dispara com 6 séries. *Descartado:* acrescentar "impresso" como terceira condição — redundante e pior, porque regra duplicada é o que deriva quando uma das duas é editada e a outra não, a classe de defeito das erratas E12/E14/E16. O item 1 da folha era **controle**, não caso de uso: 6 séries sem textura em cinza é situação que a regra vigente já proíbe, e falhou como previsto. **A prova validou a regra existente no meio em que ela nunca havia sido testada, em vez de pedir regra nova.** (3) **Os dois pares que colapsaram a olho são exatamente os dois previstos:** "Fora de ponta" ≈ "Bombeamento" (`cat-1 × cat-4`, 56% × 55%) e "Reservado" ≈ "Iluminação" (`cat-3 × cat-5`, 49% × 50%), ambos a **1 ponto** — zero falso positivo e zero falso negativo em 15 pares. (4) **SUPERSEDE da regra do piso, e é o achado mais valioso do sub-bloco:** ela dizia que o piso decide só no contexto em que foi calibrado, e foi lida como *meio novo exige calibração nova* — foi por isso que o DI3 nasceu prevendo piso próprio para papel. **A variável nunca foi o meio, foi a FORMA.** No DM11 eram bandas finas de medidor a 9/8/17 pontos, indistinguíveis **na tela**; aqui são barras altas adjacentes, a forma em que o piso foi calibrado, e o instrumento acertou **no papel**. Forma diferente + mesmo meio → erra; mesma forma + meio diferente → acerta. Regra vigente: **o piso é calibrado por forma e vale para aquela forma em qualquer meio**; forma nova (banda, fatia fina, célula de heatmap) exige recalibração por gate mesmo no meio de sempre. (5) **As 6 texturas se distinguem no papel em escala de cinza** — o vocabulário estendido a 6 posições da v0.10 sobrevive ao impresso. (6) **DI6 fechado sem piso próprio:** as quatro espessuras (2 · 1,5 · 1 · 0,5px) saíram distintas na impressão física, nenhuma sumiu nem engordou; a hierarquia de traço vale igual no papel. (7) **Fronteira do instrumento, por crítica do Rafael:** a régua mede **sobrevivência**, não **adequação** — espessura isolada com rótulo abstrato responde "a impressora deposita?" e não "é adequada aqui?"; a segunda pergunta exigiria as espessuras aplicadas no gráfico. *Achado colateral:* o piso de **0,5px não tem consumidor** — a grade do preview do DG está toda em 1px, e valor que existe na lei sem ser exercido deriva; a verificar na Fase 6. **Pendente do lote:** PNG @2x do ET5 e a edição do MANIFESTO que ancora a folha de prova, o preview do DI v0.3, a suíte do DI e este arquivo. |
| **0.11** | 2026-08-11 | **O DI4 sai de inferência para fato medido, e nasce a suíte do sub-bloco DI.** (1) **Gate de impressão do Rafael** (Chrome, "Salvar como PDF", A4): a matriz de quatro células do preview do DI devolveu **C sumiu · D sobreviveu** com "Gráficos de segundo plano" desmarcado — `background-color` de CSS desaparece quando nada o protege, `fill` de SVG sobrevive por ser conteúdo desenhado. Regra do DI4 provada como escrita (§4c.4). *Segundo achado não previsto:* a célula A sobreviveu, ou seja, o Chrome honra `print-color-adjust: exact` mesmo contra a preferência desmarcada — há duas camadas de proteção e **elas não valem o mesmo**; a regra dura do DS continua sendo a estrutural, porque a de CSS é documentadamente uma dica. *Fronteira declarada:* um navegador, um destino; Firefox e driver físico não medidos. (2) **Erro de método registrado:** a v0.1 do preview tinha duas células e não isolava a variável, porque a folha de impressão declara `exact` num seletor universal e protegia os dois braços do próprio teste — a primeira rodada devolveu um resultado verdadeiro que respondia outra pergunta. (3) **Preview do DI chega à v0.3** e a **`suite-dataviz-di.mjs` nasce com 32 verificações**, cobrindo DI4, DI5, DI6, o modo de impressão forçado ao claro, as cinco partes do DG1 no exemplo, o guia de integração e a higiene de tokens; rodada contra a v0.1, reprova em 4 — as guardas são reais. (4) **Errata E17:** `vector-effect` não é herdada (SVG 2 a define como *Inherited: no*), então declará-la num `<g>` é inócuo; o preview do DG sempre aplicou por seletor universal e o do DI copiou o conceito da lei do §4.6 sem copiar a implementação que a torna verdadeira. (5) Dois defeitos de papel achados pelo gate e que nenhuma automação veria: uma `.nota` partindo entre páginas (o `break-inside: avoid` cobria só os blocos longos) e as células do teste com áreas diferentes (o SVG preservava a proporção do viewBox). **Padrão que se repetiu três vezes neste lote e vale como regra:** quando um teste e o comportamento discordam, quase sempre é o teste que está olhando para o lugar errado — aconteceu no `DG7-03`, no `contraste-dg.py` e no `DI6-02`. **Pendente:** PNG @2x do ET5 e a folha de prova do DI-b (o gatilho da textura no papel, que segue ABERTO — o gate de impressão desta versão mediu o DI4, não o DI3). |
| **0.10** | 2026-08-11 | **Lote de produção do DI-a.** Nenhum gráfico novo e nenhum tipo novo: o DI não cria gráfico, cria comportamento. **(1) Vocabulário de textura do DG13 ESTENDIDO de 4 para 6 posições** (linhas verticais na 5, diagonal a 135° na 6 — nunca 45°, que é exclusiva do `chart-no-data`), aprovado no gate de 2026-08-11. A lacuna existia desde sempre e era invisível porque o gatilho antigo nunca foi exercido contra um gráfico de 5 ou 6 séries. **(2) `seed-tokens.md` vai a v1.7** com o token novo `chart-no-data-hatch` (cinza-600 / cinza-400), fechando a errata E13; os três gêmeos foram editados na mesma edição e o `paridade-tokens.py` fecha em **50 PASS · 0 FAIL**. **(3) `contraste-dg.py` reescrito (v2, DI18)**: mede o DG14 em vez do DG11 morto, as **seis** séries da v1.5 em vez de três, e opera o portão do DI2 varrendo todos os pares para 2…6 séries nos dois modos — **38 PASS · 0 FAIL · 20 MITIGADO · 4 ISENTO**. Fecha a pendência P8. **(4) Preview do DG a v1.4** com a E11 corrigida (a pizza de 5 séries passa a texturizar), o gatilho DI2 implementado por atributo `data-series` no `<figure>` — para a condição ficar auditável no DOM e não escondida em JS —, os patterns `tex-s5`/`tex-s6` e a hachura no token novo. **(5) A suíte ganha a seção que o §6 dizia existir e não existia** (errata E12): 11 verificações `TEX-*` + 2 `NEU-*`, levando o placar de 163 a **176 PASS · 0 FAIL**. *Prova de que a guarda é real:* rodada contra o preview v1.3 antigo, ela reprova em 4. **Oito erratas E9–E16** (§5), três delas de uma classe nova — correção declarada que não foi inteiramente aplicada: a **E14** mostra que a E3 trocou a tinta da hachura só no swatch da legenda, deixando os dois `<pattern>` SVG em violeta desde a v1.5; a **E15** acha a terceira ocorrência da mesma armadilha na série "Esperada"; a **E16** mede **19 tokens semânticos** derivados no bloco embutido do preview e os corrige **por script a partir do canônico** — a guarda que a E4 havia pedido — e de quebra explica a **E8**, porque a §3c copiou o fundo de referência dark do preview em vez de copiar do token. **Regra de método que sai do lote: correção de errata se verifica pela medição do que ela prometia consertar, não pelo fato de o arquivo ter mudado.** *Percalço de produção registrado:* a primeira edição do CSS dos tokens usou `replace` de texto e a linha indentada a 2 espaços casou dentro da indentada a 4, dentro do `@media (prefers-color-scheme: dark)`, duplicando uma declaração fora de qualquer seletor; pego na leitura de volta e refeito por regex de linha inteira. Guarda que fica: **edição cirúrgica de CSS por `replace` de texto é insegura quando o mesmo token existe em blocos de indentação diferente** — o casamento tem de ser ancorado na linha. **Pendente:** gate visual do preview v1.4, preview do DI, PNG do ET5 e a edição do MANIFESTO (que fecha E9, E10, P8 e P4-b). |
| **0.9** | 2026-08-11 | **Sub-bloco DI escrito — §4c, DI1–DI19 — em duas partes: DI-a `estável` e DI-b aberto.** Consolidado aprovado pelo Rafael após 4 rodadas encadeadas (a 4ª disparada por regra: impresso é domínio novo para o projeto). **O achado central não estava no roteiro:** ao remedir a premissa represada no §5 ("o claro tem 7 pontos de espalhamento"), descobriu-se que o número era da categórica **v1.0 com três séries**; com as **seis** posições da v1.5 o pior par no modo claro mede **1 ponto** (`cat-1 × cat-4` e `cat-3 × cat-5`; claridades 56/75/49/55/50/27). O modo claro é seguro **até três séries** e colapsa a partir da quarta — fato de **tela**, anterior a qualquer discussão sobre papel. Daí o **DI2**, supersede formal do gatilho do DG13, que passa de "escuro ∩ grayscale" para **`grayscale ∩ (escuro OU ≥4 séries)`**, e a errata **E7** contra a redação anterior do §5. **Por que o defeito sobreviveu dois sub-blocos:** o `contraste-dg.py` percorre apenas `cat1/cat2/cat3` — o detector estava recortado no lugar onde o defeito não mora; a pendência **P8** do `MANIFESTO.md` deixa de ser higiene e passa a ser guarda ausente (reescrita especificada no **DI18**). **Decisões de impresso:** DI1 separa os dois destinos (laser de escritório = escopo; offset da gráfica, que exige PDF/X-1a em CMYK e declara variação de ±10% na cor dentro do mesmo lote = Fase 7) · **DI4** proíbe informação de gráfico em `background-color` de CSS, porque `print-color-adjust: exact` é dica e a preferência do usuário no diálogo de impressão vence — com a inferência complementar (o `fill` de SVG sobrevive por ser conteúdo) **declarada como não medida** e transformada em teste da folha de prova · DI5 `break-inside: avoid` no `<figure>` inteiro · DI6 piso de traço a calibrar no papel · **DI7** o DS não converte para CMYK (evita um segundo lugar onde a cor mora, contra o DF7) · **DI8** PDF/A **não** adotado: nada no arcabouço CONFEA/CREA exige formato, o PDF/A é recomendação do CONARQ para o setor público, e o PDF/A-1 admite apenas assinatura simples — colidiria com o PAdES da ICP-Brasil, que é o que dá validade jurídica ao laudo assinado · DI9 fotocópia sem regra própria, com gatilho · DI10 fronteira com a F7. **Guia da stack (DI11–DI17):** a cadeia tem **quatro** saltos, não três — o `fill` do Recharts consome `var(--color-CHAVE)` gerado pelo `ChartContainer`, nunca `--chart-N` direto; sintaxe v3 sem `hsl()`; tema por `[data-theme]` e não pelo objeto `theme` do `chartConfig`; `accessibilityLayer` obrigatório **e insuficiente** (não cobre 1.1.1 nem 1.3.1 — o invólucro DG1 permanece por cima). **DI19** decide o caminho do PNG do ET5: `/email/v1/`, porque a imutabilidade daquele caminho proíbe **substituir** arte, não **acrescentar** — e fecha a P4-b junto. **DI-b (DI3) fica ABERTO por método:** o veredito do gatilho da textura no papel só sai de prova impressa real, com protocolo de 7 itens fechado no §4c.3. Erratas novas: **E7** (acima) e **E8** (a §3c do `seed-tokens.md` cita o fundo dark `#1C252B`; o token real é `#1D272D` — remedido, deltas ≤0,24, nenhum veredito muda). **Pendente deste lote:** preview do DI, suíte, `contraste-dg.py` reescrito, PNG do ET5 e a folha de prova impressa. |
| **0.8** | 2026-08-11 | **Gate visual aprovado nos previews corrigidos** — as v1.3/v0.8 passam a artefatos VIGENTES do DG e do DM. Mudança de estado apenas; nenhuma decisão de conteúdo. **Fecha a janela de 2026-08-11**, na qual a Fase 5 ganhou: a categórica ESTENDIDA `estável` (tokens v1.6), o redesenho DG14–DG17 formalizado, o sub-bloco DM escrito e promovido, a P6 aberta e fechada no mesmo dia, e as seis erratas achadas e corrigidas. **Próximo sub-bloco: DI** (impresso/PDF + integração da stack), com o `contraste-dg.py` a atualizar antes ou durante — ele ainda mede o DG11 e a paleta anterior à v1.5. |
| **0.7** | 2026-08-11 | **As seis erratas E1–E6 corrigidas nos previews**, que passam a `seed-dataviz-graficos-preview.html` **v1.3** e `seed-dataviz-monitoramento-preview.html` **v0.8** — na entrega, ambos `aguardando gate visual` (aprovado no mesmo dia, v0.8), porque correção de artefato aprovado não se auto-aprova e três das mudanças são visíveis (E1 medidores com `role="meter"`, E3 troca de cor do "esperado" e da hachura, E5 rótulo da pizza sai da fatia). Nenhuma decisão de spec muda nesta versão: as erratas eram divergências do PREVIEW em relação à spec, e a correção fez o artefato alcançar a regra que já existia. **Sétimo ponto achado durante a correção, tratado dentro da E3:** a hachura do `chart-no-data` desenhava as linhas em `cat-5-stroke` — mesma armadilha do ET5, no lugar mais sensível possível, já que "sem medição" é exatamente o que não pode parecer categoria; passou a `chart-axis`. **Regra nova, generalizada a partir daí: posição categórica nunca serve de neutro** — referência, contexto e ausência consomem token com papel declarado (`chart-no-data`, `chart-grid`, `chart-axis`, cinza de contexto do DG17), porque `cat-N` pode trocar de cor em qualquer supersede de paleta, como trocou na v1.5. Validação: DG **163 PASS · 0 FAIL**; DM **105 PASS · 0 FAIL · 0 FAIL DOCUMENTADO** (a suite ganhou v2.1 com dois falsos negativos corrigidos: exigia `aria-valuenow` do medidor SEM leitura, que legitimamente não o tem, e não resolvia o alias novo do "esperado"). |
| **0.6** | 2026-08-11 | **PROMOÇÃO: o sub-bloco DM passa de spec escrita a `estável`**, por "aprovo" explícito do Rafael sobre o lote de formalização. A Fase 5 fica com **DF, DT, DG e DM concluídos**; restam DP e DI. Nenhuma decisão de conteúdo mudou nesta versão — é mudança de ESTADO mais os registros que a promoção obriga. **Pendência P6 FECHADA no mesmo dia em que nasceu:** os dois previews aprovados foram reanexados e conferidos por MD5 **2/2** (gráficos v1.2 `8d1930…0fbf` · monitoramento v0.7 `f146c8…334c`), e as suites passaram de placar reproduzido a placar **executado** contra os artefatos reais — `suite-dataviz-dg.mjs` **163 PASS · 0 FAIL** e `suite-dataviz-dm.mjs` **v2: 85 PASS · 0 FAIL · 6 FAIL DOCUMENTADO**. **Seis erratas E1–E6 medidas** (§5), todas nascidas de rodar a automação contra o artefato depois do gate humano: `role="meter"` ausente no preview do DM (E1 — o DM4 não chegou a ser exercido no gate), sparkline a 1,6px contra os 2px que o próprio arquivo declara (E2), ET5 "esperado" em `cat-5` que a v1.5 transformou em violeta (E3 — **primeira consequência colateral medida de um supersede de paleta**), deriva de 4 primitivos nos dois previews (E4 — nenhum veredito muda, deltas ≤1 ponto, mas prova que o bloco de tokens foi digitado e não copiado), rótulo interno da pizza a 4,30 (E5) e os dois arquivos declarando "v0.1" no próprio título (E6 — a identificação positiva por leitura do MANIFESTO §3.1 não funciona neles). **Lição de método registrada na suite:** a v1 da `suite-dataviz-dm.mjs`, escrita contra uma reconstrução enquanto o artefato estava ausente, produziu 26 FAIL no artefato real — **23 eram premissa da suite** (ela codificava os NOMES da reconstrução como se fossem spec) e só 3 eram desvio genuíno. Suite escrita contra reconstrução testa a reconstrução; a v2 testa a mesma spec pelo COMPORTAMENTO (o alias resolve para cinza? o gatilho exige as duas condições?), não pelo seletor. |
| **0.5** | 2026-08-11 | **Lote de formalização da F5 — o material aprovado nos gates de 2026-08-10 sai da conversa e entra no canônico.** (1) **Redesenho DG14–DG17** (§4.6, "gráfico de produto"): DG14 supersede o DG11 (zero contorno; vão de 2px como espaço negativo; possível porque a categórica v1.5 passa 3:1 sozinha); DG15 geometria orgânica (rx=3 universal, pílula em ranking, curva monótona Fritsch–Carlson 2px, gradiente 22%→0) + guarda DG15b (raio consistente — defeito achado pelo olho do Rafael, não pela regex); DG16 palco mínimo (≤3 gridlines, sem linha de eixo, número protagonista, badge-pílula, ponto de status com rótulo); DG17 destaque×contexto. Duas leis transversais: **hierarquia de traço** (2/1/0,5px + meta 1,5px como exceção + `vector-effect: non-scaling-stroke` obrigatório — viewBox escalam 0,66×–12,4× medidos) e **consumo da categórica estendida** (5 famílias distintas até 5 séries; 6ª posição única exceção; teto 6; regra do dourado; ordem 2↔3 decidida no gate pelo peso do dourado). (2) **Sub-bloco DM escrito por extenso** (§4b, DM1–DM11): bullet graph canônico (Few/Cleveland–McGill), anatomia de 6 partes, DM3 papéis invertidos (supersede na §3c), `role="meter"`+`aria-valuetext` via useMeter (descartados `<meter>` nativo e progressbar), sparkline de Tufte com contrato decorativo DM6, DM7 rótulo de estado sempre visível, DM8 fecha o slot ET5 (PNG @2x 560px no R2), DM9 no-data nunca vira zero, DM11 textura de banda no gatilho do DG13 — com o registro de que o **piso de 6 pontos não transfere de contexto** (bandas a 9/8/17 seguiam indistintas; emenda no DG13). 4 defeitos de produção viraram guarda (variáveis órfãs, DM7 ausente, overflow de viewBox detectável só por `getBBox` em navegador real, acentos). Estado do DM: `aguardando aprovo do lote`. (3) **Emendas**: DG5-b remedido para a paleta v1.5 (interno só em cat-2/cat-6; errata do "45%" latente no preview), DG10-b com racional supersedido e teto mantido, DG12 restrito ao rótulo + exceção do DM. (4) **Achados da formalização**: previews aprovados AUSENTES do Drive (alvos MD5 registrados; pendência P6) · deriva de 5 hex nos previews vs canônico (ancoragem nos stops reais, veredito idêntico) · GI2 do colapso dark CUMPRIDA na §3c v1.5. Suite do DG na versão final: 163 verificações. |
| **0.4** | 2026-08-09 | **Sub-bloco DG (gráficos core) `estável` — 13 decisões, §4 nova.** Sete tipos (barra, empilhada, agrupada, linha, área, pizza, dispersão) mais os três estados herdados do Bloco 3. Consolidado aprovado após 3 rodadas encadeadas de pesquisa, com **duas emendas durante a produção**: a **barra empilhada** foi puxada para dentro do escopo a pedido do Rafael (caso real: consumo por posto tarifário), trazendo junto a **agrupada** como saída obrigatória; e o **DG13 (textura)** nasceu do gate. **Três regras nasceram da medição, não do consolidado:** DG11 (contorno `cinza-900` — o fill categórico reprova sozinho contra o fundo claro), DG12 (tinta sobre dado não segue o tema — o fill é claro nos dois modos) e DG13 (textura na interseção escuro+grayscale). **O gate levou o preview da v0.1 à v0.5**, e os dois achados decisivos foram do olho do Rafael: o colapso das séries em cinza no modo escuro, e o escopo exato do gatilho da textura. **Correção de instrumento registrada:** o portão de grayscale media razão de contraste WCAG e reprovava o modo claro, onde o gate humano lia bem — foi trocado por espalhamento de claridade, com piso declarado como calibrado pelo gate e não derivado de norma. **Validação:** jsdom 147/0 · contraste 32 PASS · 0 FAIL · 14 MITIGADO · 4 ISENTO · render puppeteer 6 cenários (matriz tema × grayscale × largura, agora **cruzada** e não amostrada — a versão anterior não gerava escuro+grayscale, que era exatamente onde o defeito morava). |
| **0.3** | 2026-08-09 | **PROMOÇÃO: DF e DT passam de `rascunho` a `estável`**, após "aprovo" explícito do Rafael no gate visual do preview `seed-dataviz-tokens-preview.html` v0.2 completo (2ª rodada do gate; a 1ª aprovara só a escala A sobre o preview comparativo). Nenhuma decisão de conteúdo mudou nesta versão — a v0.3 é mudança de ESTADO mais os registros que a promoção obriga. Junto: validação reproduzida na janela (29 PASS · 3 FAIL, os 3 documentados do fill em traço fino) e cruzamento §3c×gêmeos (26/26 hex batem). Débito dos gêmeos ENCERRADO — `seed-tokens.json`/`.css` regenerados para v1.4, e a execução revelou que a defasagem era de duas versões (faltava todo o pacote mobile v1.2), não uma; nasceu daí a guarda `paridade-tokens.py`. `MANIFESTO.md` v1.2 ancora os artefatos da F5. |
| **0.2** | 2026-08-09 | **Achado do gate visual do Rafael na escala sequencial:** os stops 50/100 da proposta original liam como cinza — ambíguos com "sem dado". Correção aprovada (opção A sobre preview comparativo): escala desloca para 100→900 (light) / 800→100 (dark), e nasce o token `chart-no-data` (cinza exclusivo de "sem medição", sempre hachurado). Alternativa B descartada (manter 50→800 e resolver só por regra — a leitura-cinza permaneceria). Valores e supersede na §3c do `seed-tokens.md` v1.3. Bug de regressão corrigido no `contraste-dataviz.py` (seção do gauge media os stops rejeitados, não os canônicos). |
| **0.1** | 2026-08-09 | Primeira entrega da Fase 5. Nasce o 9º canônico com o fundamento DF1–DF7 (consolidado aprovado pelo Rafael em 2026-08-09 após 3 rodadas: R1 canon interno · R2 mercado/stack shadcn Chart+Recharts v3 · R3 normas WCAG 1.4.1/1.4.11/1.4.3) e o registro do sub-bloco DT, cujos valores vivem no `seed-tokens.md` v1.3 §3c (DF7: uma fonte). Medição prévia corrigiu 2 propostas de gauge e originou a variante `cat-N-stroke`. Estado: `rascunho`, aguardando gate visual do preview de tokens. |

---

*Arquivo canônico do Design System v2 da SEED engenharia. Produzido por Claude sob direção
de Rafael Sant'Ana. Nada aqui é promovido a `estável` sem aprovação explícita após gate
visual.*
