---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 48
titulo: "Painel — grade, lentes, frescor, edição direta e mapa — **`estável`** (v0.62) · **validado pelo Rafael em 2026-08-13** · PN1–PN54 · pattern F6 · **cinco camadas de validação verdes: `suite-painel.mjs` 133/133 · `render-painel.mjs` 37/37 · `render-edicao.mjs` 142/142 · `render-contraste.mjs` 6/6 · `contraste-painel.py` 70/70** · preview **v0.6** · **BLOCO 6C FECHADO**"
sequencia: 50 de 98
bytes_do_corpo: 94352
md5_do_corpo: 0fa2e5828c247b0f1e92e42147f02f1f
gerado_por: 06-validacao/geradores/gen-camada-ia.py
nota: fatia GERADA — o corpo abaixo é byte a byte o trecho do canônico; edite o canônico, nunca esta fatia. Canônico inteiro em https://ds.seed.eng.br/01-canonicos/seed-componentes.md
---
## 48. Painel — grade, lentes, frescor, edição direta e mapa — **`estável`** (v0.62) · **validado pelo Rafael em 2026-08-13** · PN1–PN54 · pattern F6 · **cinco camadas de validação verdes: `suite-painel.mjs` 133/133 · `render-painel.mjs` 37/37 · `render-edicao.mjs` 142/142 · `render-contraste.mjs` 6/6 · `contraste-painel.py` 70/70** · preview **v0.6** · **BLOCO 6C FECHADO**

> **⚠ FRONTEIRA DA PROMOÇÃO, e ela é dura.** O que este `estável` cobre são os **contratos** PN1–PN54: grade, lentes, frescor, blocos de dado, edição direta, mapa. **A camada visual (§48.3) é PROPOSTA**, não canônico.
>
> **A ressalva se pagou em menos de 24 horas, e o registro disso é útil.** A promoção foi escrita em 2026-08-13 excluindo três decisões de marca; na mesma noite o Rafael retirou o azul (*"eu tinha aceitado para podermos parar com os testes"*) e a **âncora escura virou turquesa vivo**. Duas das três decisões mudaram de valor ou saíram — e **nada** do `estável` precisou ser tocado. Se o azul tivesse entrado no canônico no dia anterior, isto seria errata em `marca-seed.md`, nos três gêmeos de token, no sistema de e-mail (`estável`) e nos 40 HTML do repositório.
>
> **Estado atual das decisões de marca:** **S3** revisto — a âncora é `turquesa-400` #11B0A0, não mais `azul-800`. **S4 RETIRADO** — a ação volta à família da marca, e o conflito com o §3.5 de `marca-seed.md` **deixa de existir**: nada a superseder na marca. **S6** (tinta da família) segue **PROPOSTA**, como camada alternável pelo botão "Tinta". Ver §48.8 e a pendência **PN-P1** do §48.9, que encolheu na mesma proporção. *Quem consumir este §48 hoje para escrever código usa a régua de ação do `marca-seed.md` §3.5 — que é, desde esta rodada, a MESMA do preview.*

> **Natureza:** pattern de **COMPOSIÇÃO** do F6, como o §33, o §46 e o §47 — **nenhum componente
> novo nasce aqui**. Consome o shell (§46), tabela (§40), lista de dados (§43), toolbar (§42),
> tabs (§34), os gráficos da Fase 5 e os estados de espera do Bloco 3.
>
> **Este bloco cumpre uma fronteira declarada há duas fases.** O **DF6** do `seed-dataviz.md`
> (Fase 5, `estável` desde 2026-08-09) escreveu: *"dashboard/layout de painel = F6 — a F5 entrega
> a peça, não o painel"*. É esta seção.
>
> **O QUE ESTE BLOCO ENTREGA, EM TRÊS RODADAS.** O 6C foi produzido em três rodadas, e o
> registro da ordem importa porque cada uma nasceu de um gate do Rafael sobre a anterior.
> **Rodada 1 (2026-08-12):** a grade, o comutador de visualização com pré-requisitos de dado, a
> gramática do frescor, a variante equipe × cliente, o consumo do movimento (PN1–PN12) e os
> quatro blocos de dado que não são gráfico (PN13–PN20). **Rodada 2 (2026-08-13, manhã):** o
> supersede do PN3 para **oito lentes** e a **camada visual** PN21. **Rodada 3 (2026-08-13,
> tarde e noite):** a **edição direta** (PN22–PN41), os **contratos que o gate produziu**
> (PN46–PN50) e a **lente mapa em dois modos** (PN51–PN54). **Preview e gate visual são únicos,
> no fim.**
>
> **Escopo do produto, decidido em briefing antes da pesquisa (2026-08-12):** o ERP atende
> **quatro setores** — Admin, Engenharia, Comercial e Qualidade — com áreas dentro deles; **a
> estrutura de setores e áreas e o desenho do workflow são do PROJETO DO ERP**, declarados fora
> deste bloco pelo Rafael. O painel serve **dois públicos**: a equipe (prioritário) e o cliente,
> que terá área própria com produtos e serviços contratados, arquivos e contratos, monitoramento
> de usina e um sistema de **indicação de leads com acompanhamento de status**. O painel é
> **fixo** — o que varia é a **forma de exibir a mesma informação**, no padrão do ClickUp. O
> painel precisa **poder** mostrar informação em tempo real. Referências visuais: ClickUp
> (comutador) e a plataforma do `estudo-viver-de-ia.md` (KPI, ranking, progresso, camada visual)
> — ambas já estudadas e ancoradas; nenhuma referência externa nova.
>
> **A DISTINÇÃO QUE DEFINE O TAMANHO DO BLOCO, e ela não estava clara no briefing.** O que o
> Rafael descreveu **não é painel configurável — é comutador de visualização**. *Configurável* é
> o usuário arrastar blocos e escolher o que aparece: caro, e explicitamente descartado.
> *Comutador* é **a mesma informação em formatos diferentes**, com a tela permanecendo fixa.
> Separar as duas coisas cortou o custo do bloco pela metade e é a razão de o PN1 e o PN3
> coexistirem sem conflito.
>
> **Base (3 rodadas encadeadas, 2026-08-12):** **R1 canon interno** — **DF6** (esta fronteira) e
> **DM10** (tempo real é produto); a **Régua de Espera** do Bloco 3 em três regimes compostos
> (ação · carga inicial · refresh sobre conteúdo, com delay de 1s e permanência mínima); os
> **dois regimes de live region** do §1.13 (discreto × contínuo, uma por componente); o §46
> inteiro (SH2 landmarks nomeados, SH5 ativo que sobrevive ao grayscale); o **DP12** (destino
> externo × interno); o §40 (densidade compacta medida em 33px); e a **§6b do
> `estudo-viver-de-ia.md`** — a auditoria que mostrou que a "camada de movimento" **não era
> lacuna de token** (existem 4 durações + 4 easings + `prefers-reduced-motion` desde os
> primitivos) e sim **de consumo**. **R2 mercado** — comutador de visualização no ClickUp, Notion
> e Linear: as lentes mostram os mesmos itens com filtro e layout próprios sobre a mesma fonte;
> trocar de lente não altera os itens; e a adequação da lente **depende do dado**. **R3 normas** —
> **WCAG 2.2.2 (nível A)**: informação que se atualiza sozinha, começa automaticamente e é
> apresentada em paralelo com outro conteúdo exige mecanismo para **pausar, parar, esconder ou
> controlar a frequência**; painel com intervalo escolhível (30s / 5min / manual) satisfaz pelo
> controle de frequência. **Base adicional da rodada 3 (edição direta):** **WCAG 2.2, SC 2.5.7
> Dragging Movements (AA)** — toda funcionalidade que usa arrasto tem de ter **caminho de
> ponteiro único** alternativo; e a documentação do ClickUp sobre gantt × timeline (ver PN3c).
> Consolidados aprovados pelo Rafael em 2026-08-12 e 2026-08-13.

### 48.1 Decisões estruturais · PN1–PN12

| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| **PN1** | **O painel é uma GRADE de 12 colunas**, com blocos de largura declarada (4, 6, 8 ou 12). **Layout fixo por tela**, definido no projeto do ERP | Painel configurável — arrastar, redimensionar, escolher o que aparece — foi **descartado pelo Rafael** e é várias vezes mais caro: o DS deixaria de desenhar a tela para desenhar as peças mais a grade que as recebe. Grade declarada dá liberdade de composição sem arrasto | Painel arrastável · larguras livres em pixel (impede reflow previsível a 360px) |
| **PN2** | **Todo bloco do painel é `<section>` com cabeçalho próprio e nome acessível. Um bloco = uma pergunta respondida** | Painel é uma página com muitas regiões; sem nome, o leitor de tela entrega uma pilha de conteúdo sem estrutura. Herda o **SH2** do §46. A regra "uma pergunta" é o que impede o bloco-depósito | Bloco sem título · dois assuntos no mesmo bloco |
| **PN3** | **COMUTADOR DE VISUALIZAÇÃO — OITO lentes** *(SUPERSEDE 2026-08-13; 1ª redação: cinco)*: `lista` · `tabela` · `kanban` · `gantt` · `tempo` (linha do tempo por responsável) · `calendario` · `carga` (carga de trabalho) · `mapa`. **Os oito nomes entre acentos graves são os identificadores canônicos** — o atributo `data-lente` do preview usa exatamente estes | É o que o Rafael pediu, no padrão do ClickUp. **A tela é fixa; o que troca é a lente.** *O supersede tem duas causas, ambas de 2026-08-13:* **(a)** a documentação do ClickUp provou que gantt e linha do tempo são lentes DIFERENTES (ver PN3c) — a 1ª redação as tratava como sinônimos; **(b)** decisão do Rafael: *os templates estruturais nascem AGORA, e a alocação de pessoa precisa estar prevista mesmo que o ERP não a use de imediato* — o que supersede a proposta anterior de deixar linha do tempo e carga de trabalho "para depois". O **mapa** entra como lente porque OS tem endereço e usina tem coordenada, e o §4d (DP) já entrega malha IBGE e projeção: ver a mesma lista de OS num mapa é o mesmo dado noutra forma. No modo cliente, o mapa herda o **PN10/DP12**: só as usinas do próprio cliente | Painel configurável · lente única por tela · adiar a alocação de pessoa (o template nasceria sem o lugar dela e obrigaria redesenho — a mesma razão da ordem lote 1 → lote 2) · tratar como lentes o que é tipo de conteúdo ou tela própria no ClickUp (formulário, documento, whiteboard, mapa mental, chat) ou integração de produto (incorporações) · o rótulo **"quadro"** como nome canônico (ver **S2** em §48.8) |
| **PN3b** | **A LENTE DESENHA A FORMA QUE O NOME PROMETE.** Linha do tempo é **barra posicionada e dimensionada por data**, sobre escala de datas. Calendário é **grade de mês** — sete colunas iguais, primeiro dia da semana calculado, evento no seu dia. Kanban é **coluna por estado**. Nenhuma delas pode ser uma lista com outro rótulo | **Achado no gate visual do Rafael.** O preview v0.1 renderizava "linha do tempo" e "calendário" como **listas** — passava em todo teste de comportamento e **mentia para o olho**. É a mesma classe do **botão morto** que o projeto já proíbe: *"responder significa DEMONSTRAR, não explicar"* (§A.3 do ESTADO_ATUAL, emendado no marco v1.7). *Guardas permanentes:* `PN3b-01…08` na suíte e `R5b-01…08` no render, este último medindo **geometria** — barras em posições e larguras distintas, dentro da faixa, e as sete colunas do calendário com a **mesma largura** | Lente que só troca o rótulo · lente "em breve" (é botão morto com outro nome) |
| **PN3c** | **GANTT ≠ LINHA DO TEMPO — são perguntas diferentes sobre as mesmas tarefas.** **Gantt** responde *"o que trava o quê"*: uma faixa por TAREFA, barra posicionada e dimensionada por data, e **as dependências DESENHADAS** — conector do fim da predecessora ao início da dependente. **Linha do tempo** responde *"quem está ocupado quando"*: uma faixa por RESPONSÁVEL, com as tarefas da pessoa empilhadas dentro da faixa dela (sub-linhas quando se sobrepõem). Gantt sem dependência desenhada não é gantt | Fonte: documentação oficial do ClickUp (Gantt = tarefas conectadas, sequenciamento, caminho crítico, reagendar cadeias; Timeline = cronograma linear por recurso, para roadmap e gestão de alocação). *Registro de origem:* o preview v0.2 implementava um gantt sem dependências com o rótulo de linha do tempo — a distinção veio de pergunta do Rafael (*"tem o gantt e tem a linha do tempo, existe diferença"*) e foi respondida pela fonte, não por dedução | Tratar como sinônimos (o defeito de origem) · gantt sem conector de dependência (é linha do tempo de tarefa com o nome errado) |
| **PN4** | **O DADO habilita a lente, não a tela.** Pré-requisitos declarados: `lista` e `tabela` não exigem nada · `kanban` exige campo de estado com valores finitos em **todos** os itens · `gantt` exige **ao menos uma** ordem com início E fim · `tempo` exige ao menos uma agendada **E** alguém com responsável · `calendario` exige ao menos uma com data · `carga` exige responsável · `mapa` exige coordenada ou endereço geocodificável em **todos**. **Lente sem pré-requisito não é oferecida** — nunca oferecida-e-vazia; e o motivo da ausência é dito com o nome do campo que falta | Responde a dúvida do Rafael (*"as telas serão montadas dizendo que é permitido, a não ser que o sistema consiga entender sozinho"*) **sem as duas saídas ruins**. Regra estável, sem lista de exceções para manter. *O quantificador "ao menos uma" é SUPERSEDE de 2026-08-13 — ver **PN47** e **S8** em §48.8:* a 1ª redação exigia o dado em TODOS os itens e uma única ordem sem data derrubava o gantt inteiro | Marcação manual por tela (vira lista viva de manutenção, e lista de exceções apodrece) · inferência mágica sem regra escrita (falha em silêncio) · oferecer a lente e mostrar vazio (o usuário conclui que não há dado, quando o que falta é campo) |
| **PN5** | **A lente NUNCA altera o conjunto.** Filtro e ordenação **viajam** com a troca de lente; o que muda é a forma | Se a lente filtrar, o usuário perde o rastro do que sumiu e passa a desconfiar do painel. É o que a evidência de mercado descreve: trocar de visualização não muda os itens, só como aparecem | Filtro embutido na lente · lente que esconde item sem pré-requisito (esconder é filtrar) |
| **PN6** | **A lente ativa é estado de navegação:** `aria-current`, marca visual que **sobrevive ao grayscale**, e **uma lente padrão declarada por tela** | Herda o **SH5** do §46 sem alteração. A lente padrão existe para que a tela abra resolvida, não perguntando | Só cor de fundo (morre em cinza) · última lente usada como padrão global (o mesmo usuário quer kanban numa tela e calendário noutra) |
| **PN7** | **GRAMÁTICA DO FRESCOR.** Todo bloco com dado que se atualiza declara três coisas: **momento da última leitura** · **estado atual** (atualizado / atualizando / falhou) · **idade do dado quando ela importa** | O **DM10** e o **DF6** já declararam que tempo real, websocket e persistência são **produto**. O DS declara a **gramática**, nunca o transporte — mesma precisão de fronteira que o §47 fez com a camada GEO. Sem isso, *"está gerando 0 kW"* e *"não sei o que está gerando"* viram a mesma tela — e num painel de usina essa diferença é a diferença entre chamar o técnico e não chamar | Indicador global de "ao vivo" no topo do painel (não diz **qual** bloco está velho) · dado velho sem marca · esconder o valor enquanto atualiza (pisca e perde a referência) |
| **PN8** | **CONTROLE DE FREQUÊNCIA OBRIGATÓRIO em painel que se atualiza sozinho** — intervalo escolhível, com opção **manual** | **WCAG 2.2.2, nível A**: informação que se atualiza automaticamente e é apresentada em paralelo com outro conteúdo exige mecanismo para pausar, parar, esconder **ou controlar a frequência**. Um painel com intervalo escolhível satisfaz pela frequência. **Painel em tempo real sem isso não é AA — não é nem A** | Atualização fixa e não interrompível · pausar sem retomar (o usuário fica com dado velho sem saber) |
| **PN9** | **Atualização automática NÃO move o foco, NÃO reordena o que está sendo lido e NÃO fala sozinha.** Só o que o usuário pediu para acompanhar anuncia; o resto atualiza em silêncio, com o frescor do PN7 dando a evidência visual. **O painel tem UMA live region** (`role="status"`, `aria-live="polite"`), e todo anúncio — de edição, de filtro, de zoom, de fallback de mapa — sai por ela | Um painel que anuncia cada mudança em live region é **inutilizável** com leitor de tela. Herda os dois regimes do §1.13: o discreto (o nó visível é a live region) serve ao bloco acompanhado; o contínuo, com debounce e marcos, ao resto. *A regra da região única foi reafirmada na rodada 3:* o rótulo do zoom (`"15 d na tela"`) é **estado visível**, não anúncio — quem anuncia a mudança é a região única | Toda atualização em `aria-live` · reordenar a lista enquanto o usuário lê · rolar automaticamente ao chegar dado novo · uma live region por controle (duas regiões competindo produzem fala sobreposta) |
| **PN10** | **Variante EQUIPE × CLIENTE declarada, com UM contrato só.** O painel do cliente vê **apenas o que é dele**; identificação de terceiros nunca aparece — **inclusive dentro de agregados** | Herda a estrutura do **DP12** (destino externo × interno). Área do cliente com produtos contratados, arquivos, contratos, monitoramento e indicação de leads é **o mesmo painel com escopo diferente**, não um segundo produto. A ressalva do agregado é a que costuma vazar: "você está entre os 3 maiores clientes" revela o tamanho dos outros | Dois painéis (divergem em seis meses) · mesmo painel sem escopo declarado (vazamento por omissão) |
| **PN11** | **CONSUMO DO MOVIMENTO declarado por papel:** registro **produtivo** para o que serve à tarefa (troca de lente, abrir e fechar bloco, hover) · registro **expressivo** só para momento significativo (entrada de bloco novo, confirmação de ação). **Atualização de dado NÃO anima** | Fecha a lacuna nº 5 do censo do `estudo-viver-de-ia.md` — que a **auditoria da Fase 5 provou não ser lacuna de token**: existem 4 durações, 4 easings e o bloco `prefers-reduced-motion` desde os primitivos (errata E-EST1). O que faltava era **declarar o consumo**, e é isto. Dado que pisca a cada leitura é ruído: chama atenção para o que não mudou de importância | Animar a troca de valor · registro expressivo em interação de tarefa (300–400ms numa troca de lente parece o sistema travando) |
| **PN12** | **Densidade: compacta por padrão no ERP, confortável no painel do cliente** | O §40 já mediu a compacta em **33px** e o gate do Bloco 6 a aprovou. Equipe treinada ganha com densidade — mais informação por tela, menos rolagem; cliente eventual perde, porque densidade exige familiaridade | Densidade única para os dois públicos |

### 48.2 Blocos de dado que não são gráfico · PN13–PN20

> **Escrito em 2026-08-12.** Estes quatro blocos — KPI, ranking, progresso e timeline — são os
> **buracos vermelhos** que o censo de lacunas do `estudo-viver-de-ia.md` (§6) encontrou e que a
> **auditoria de impacto** do marco da Fase 5 (§6b daquele arquivo) classificou como **aditivos**:
> nenhum exige supersede em algo `estável`. O achado estrutural do censo foi que os buracos **não
> eram gráficos** — eram **componentes de dado que não são gráficos**, uma classe intermediária
> sem dono entre o Bloco 6 (dados) e o DG (gráficos core). É esta seção.
>
> **Três dos quatro são INVÓLUCRO, não desenho** — e isso está medido, não suposto: o **DG16** já
> especifica a gramática do cartão-KPI, e o **DG15** mais o **DG17** já especificam a barra de
> ranking e o caso de uso dela. O DS **promove o que já existe**; inventa só onde havia vazio de
> verdade (timeline).
>
> **Base adicional deste lote (R2/R3, 2026-08-12):** APG do W3C sobre propriedades de faixa
> (`aria-valuenow`, `aria-valuemin`, `aria-valuemax`, `aria-valuetext`); documentação do MDN sobre
> o papel `progressbar` e o efeito dele sobre os descendentes; a distinção normativa entre
> `progress` (conclusão de tarefa) e `meter` (quantidade escalar em faixa conhecida); e a
> orientação de anunciar progresso em **marcos**, não a cada ponto percentual.

| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| **PN13** | **KPI — o número é o PROTAGONISTA.** Valor em `fs-h2` peso 800 · rótulo em micro-caps mono · variação em **badge-pílula suave** (fundo `feedback-*-bg`, texto `feedback-*-text`). Vive **fora de `<figure>`**: é bloco autônomo do painel, não gráfico | **O DG16 já escreveu esta gramática e está `estável` desde 2026-08-10.** O 6C **promove, não inventa** — a auditoria de impacto da Fase 5 já havia mostrado que a lacuna era "menos vazia do que parecia". Reescrever produziria duas fontes da mesma regra, que é o problema que o DS existe para matar (DF7) | Recriar a gramática aqui (deriva garantida) · KPI dentro de `<figure>` (obrigaria o fallback textual do DG1 para um número que **já é** texto) |
| **PN14** | **O KPI declara o PERÍODO e a BASE de comparação.** *"R$ 486k · +12% vs. mês anterior"* — nunca "+12%" solto | Variação sem base é número sem significado: +12% contra o mês passado, contra o ano passado e contra a meta são três afirmações diferentes. É o irmão do **MK15** do §47 (número declara fonte e data) — mesma regra, outro contexto. E a seta de variação nunca vai sozinha: a escada de mecanismos do §1.12 exige sinal **mais** texto, senão morre em escala de cinza | Variação sem referência · seta colorida como único sinal · comparação implícita ("o usuário sabe qual é") |
| **PN14b** | **A COR DA VARIAÇÃO VEM DO SENTIDO DO INDICADOR, NUNCA DO SINAL.** Cada KPI declara a polaridade — *maior é melhor* (geração, usinas em operação) ou *menor é melhor* (chamados abertos, tempo de resposta, perdas) —, e a pílula é positiva quando a variação **melhora** o indicador. A **seta** carrega o sinal; a **cor** carrega o juízo | **Achado na inspeção do render, não previsto na spec.** O preview saiu com *"-3 chamados abertos"* em vermelho, porque eu havia pintado pelo sinal da variação. **Reduzir chamados é bom.** Sem a polaridade declarada, todo indicador em que menos é melhor sai pintado ao contrário — e num painel de O&M isso é a maioria deles: falhas, chamados, tempo de parada, perdas. *Efeito colateral bom:* separar seta (sinal) de cor (juízo) dá **dois mecanismos** onde antes havia um, o que é a escada do §1.12 de graça | Pintar pelo sinal da variação (o defeito) · omitir a seta e deixar só a cor (morre em escala de cinza) |
| **PN15** | **RANKING — lista ordenada com barra embutida:** índice em mono · rótulo · **barra fina em pílula completa** (`rx` = metade da altura) · valor numérico à direita. **A barra é proporcional ao MAIOR VALOR DA LISTA, e a base é declarada** | O **DG15** já define a pílula da barra fina e o **DG17** já nomeia o caso de uso: *"ranking de usinas com a usina em foco destacada"*. Faltava a **lista que hospeda**, não a barra. A base proporcional precisa ser dita porque duas listas lado a lado com bases diferentes enganam quem compara, e ninguém percebe | Barra proporcional a um teto arbitrário ou a 100% (achata o ranking inteiro quando os valores são próximos) · ranking sem o valor numérico (a barra sozinha não se lê, e a lista vira decoração) |
| **PN16** | **O ranking mostra quem está bem E quem não está, no MESMO bloco:** contador de exceção no cabeçalho, **sempre com prescrição** | Padrão medido no `estudo-viver-de-ia.md` (§3.7 e §3.12): o card de ranking traz *"4 sem acesso"* no canto, e a exceção vem sempre com o próximo passo ao lado. **Dado + diagnóstico + próximo passo, nunca dado sozinho.** Num painel de O&M, "as 5 usinas que mais geraram" sem "as 3 que não reportaram" é meia informação | Ranking só dos melhores (esconde justamente o que o gestor precisa ver) · exceção sem prescrição (produz ansiedade sem ação) |
| **PN17** | **PROGRESSO DE CONCLUSÃO usa `progressbar` — e isso NÃO contraria o DM4** | O **DM4** escolheu `role="meter"` para o medidor e **descartou explicitamente `progressbar`**. São semânticas opostas, com fonte normativa: **`progress` indica conclusão de tarefa** (*"você completou 30%"*); **`meter` indica quantidade escalar dentro de faixa conhecida** (*"2GB de 10GB usados"*). O DM4 decidiu sobre medidor de valor; este bloco decide sobre progresso de tarefa. **O registro explícito é obrigatório** — sem ele, parece exceção silenciosa, e foi exatamente isso que a auditoria de impacto da Fase 5 mandou evitar | `meter` para progresso (semântica errada: obra 40% concluída não é "40 de 100 unidades usadas") · adotar `progressbar` sem declarar a distinção (a exceção silenciosa que a auditoria antecipou) |
| **PN18** | **NADA SEMÂNTICO VIVE DENTRO DO `progressbar`.** Rótulo, fração e porcentagem ficam **fora**, associados por `aria-labelledby`. Progresso indeterminado **OMITE** `aria-valuenow` | Armadilha documentada no MDN: o navegador aplica **`role="presentation"` a todos os descendentes** de um `progressbar`, porque a API de acessibilidade não representa elementos semânticos dentro dele. Um título ou uma fração colocados na barra **deixam de existir** para o leitor de tela — e o desenvolvedor não tem como perceber, porque a tela continua certa. Sobre o indeterminado, o APG é explícito: se o valor é desconhecido, **omita** `aria-valuenow` | Fração ou rótulo dentro da barra · `aria-valuenow="0"` para indeterminado (afirma "0%", que é falso e diferente de "não sei") |
| **PN19** | **Progresso anuncia em MARCOS — 25 / 50 / 75 / 100% — nunca a cada ponto** | Anunciar cada ponto percentual sobrecarrega o usuário de leitor de tela a ponto de inutilizar a tela. Herda o **regime contínuo** de live region do §1.13, que já prevê debounce e marcos, e é a mesma cadência que o **MK19** do §47 adotou para o vídeo. **A conclusão é o marco que nunca se omite** — é o único que sempre importa | Anunciar cada atualização · omitir a conclusão · anunciar progresso que o usuário não pediu para acompanhar (herda o PN9) |
| **PN20** | **TIMELINE — lista ordenada no tempo, MAIS RECENTE PRIMEIRO**, com data em mono, marcador de evento e agrupamento por período. **Cada entrada é ENDEREÇÁVEL** | Território limpo: nada no DS tocava histórico ordenado no tempo, e o ERP precisa dele para histórico de obra, de manutenção e de comissionamento. **Mais recente primeiro** porque num painel o que importa é o que mudou por último. **Endereçável** pelo mesmo motivo do **MK18** (case em vídeo): um evento de histórico precisa de link próprio para ser citado num laudo, num e-mail ou numa conversa com o cliente | Timeline como decoração vertical sem semântica de lista (leitor de tela recebe uma pilha de texto) · ordem cronológica direta (útil em narrativa, não em painel) · entrada sem endereço (não dá para referenciar) |

*Registro de honestidade:* o KPI, o ranking e o progresso **já tinham gramática escrita** no DG15,
DG16 e DG17 — esta seção entrega o **invólucro**. Só a **timeline** é desenho novo. Dizer isso
importa porque a impressão de que um bloco "criou quatro componentes" é falsa, e quem ler daqui a
um ano precisa saber onde procurar a regra de origem.

### 48.3 Camada visual · PN21a–PN21h

> **Origem:** pedido explícito do Rafael em 2026-08-13 — *as técnicas do `estudo-viver-de-ia.md`
> estavam entendidas e não estavam refletidas no resultado*. Todos os valores abaixo são os
> **medidos** na §9.4 e na §2 daquele estudo ou medidos no gate desta rodada, nunca impressão de
> olho. A adaptação preserva as leis SEED: **paleta 2018 intocada** (a monocromia navy do estudo,
> catalogada lá como **D1**, segue rejeitada), gráfico com anatomia acessível (**D2**), regra do
> dourado e variante `-stroke` continuam valendo por cima.

| # | Regra | Porquê / número medido | Descartado |
|---|---|---|---|
| **PN21a** | **Sombra premium multicamada COM ANEL:** duas difusas + anel de 1px na mesma declaração (`0 0 0 1px`) | Receita §9.4-3 do estudo. O anel é o que separa o cartão do fundo quando a difusa é sutil; sem ele o cartão flutua sem contorno e a borda tem de voltar como traço, que é o que o DS quer evitar | Borda de 1px como único separador · sombra de uma camada (lê como carimbo) |
| **PN21b** | **VÉU RADIAL DE LUZ é a única forma de gradiente — nunca gradiente de cor. O teto de alfa é POR SUBSTRATO, não único:** sobre superfície **clara**, ≤ .07 · em camada `::before` de substrato **escuro**, ≤ .16 | *Emenda medida no gate de 2026-08-13.* Sobre o `cinza-900` da marca, véu de acento a .04 move o pixel **5 níveis de 255** e a .09 move **12** — invisível no monitor do usuário; a **.16 move 21**, que é o mínimo perceptível ali. Sobre superfície clara o teto continua baixo, porque o que se acumula lá é **sujeira, não luz** | Teto único de alfa para os dois substratos (a 1ª redação; deixava o escuro sem nenhuma luz visível) · gradiente de cor |
| **PN21b-2** | **O véu de ACENTO (turquesa) pertence ao substrato ESCURO. Sobre superfície clara o véu é NEUTRO** — cinza da marca a 3% | Medido no gate: véu de acento sobre claro **desvia um canal só** — turquesa a 7% tira 16 níveis de R contra 5 de G — e o olho lê *tinta por cima*, não profundidade. O véu do estudo é quase-neutro (desvio R+10 G+9 B+8); o do claro passou a cinza a 3% (desvio uniforme R+6 G+6 B+6) e a área encolheu | Véu turquesa sobre a página clara (a hipótese testada e reprovada) |
| **PN21b-3** | **O SUBSTRATO DA PÁGINA É ESCURO e a "página clara" é um VÉU BRANCO TRANSLÚCIDO por cima** (.995 → .985 → .965 ao longo da altura) | §9.4-1 do estudo, medido no código da plataforma (.96 → .84 → .58): a página clara é **literalmente iluminada sobre escuro**, e é daí que vem a profundidade. **As duas redações anteriores fizeram o inverso** — página clara chapada com véu escuro por cima — e é por isso que a tela lia sombria em vez de viva | Página clara opaca com véu escuro por cima (as duas redações reprovadas) |
| **PN21c** | **UM hero escuro por página**, com anatomia fixa: micro-rótulo mono → saudação ciente da hora → data viva em mono caps → apoio → **UMA linha de ação** (exceção com prescrição + botão da solução ao lado) | §3.2 do estudo, relido no gate. **A redação anterior empilhava CINCO camadas** (stats E exceção E prescrição E controles) e o hero media **456px contra 268px** do da plataforma. Os stats saíram por serem **os mesmos números dos KPIs logo abaixo** — dado repetido na mesma dobra. **Controle de painel vive em régua CLARA, fora do escuro editorial** | Dois blocos escuros competindo na mesma página · stats no hero repetindo KPI · seletor de frequência dentro do hero |
| **PN21d** | **MONO como camada semântica obrigatória:** todo dado, medição, data, contagem e rótulo de KPI em JetBrains Mono; micro-rótulo = caps + tracking largo + corpo pequeno + cor secundária | Lei dos tokens v1.1 (dado de medição = mono), aqui **promovida a obrigação** do painel. É também a base da amplitude tipográfica: o número gigante só se lê como número porque o rótulo ao lado é micro | Dado em Montserrat · micro-rótulo sem caps/tracking |
| **PN21e** | **INSIGHT-COMO-TÍTULO em todo gráfico do painel** (A1 do estudo) — o título é a conclusão, com **itálico marcando o sujeito** (B2), **no máximo um por título** | O título que descreve o eixo ("OS por estado") obriga o leitor a concluir sozinho; o título que conclui ("*Em campo* concentra 6 das 14 ordens") entrega a leitura. O limite de um itálico existe porque dois sujeitos marcados no mesmo título anulam a marcação | Título descritivo de eixo · dois ou mais itálicos por título |
| **PN21f** | **Tipografia consome a escala canônica:** `fs-display-fluid` (clamp 40→64px) + `ls-display` no hero; `fs-caption` no micro-rótulo. **Amplitude hero/micro-rótulo = 6,1×** | *Defeito medido:* a 1ª redação usou 1,7rem (27px) no hero e **desperdiçou a escala** — o DS já tinha o display fluido e o tracking negativo, e o hero não os consumia. Amplitude é o que faz a hierarquia existir sem borda nem cor | Tamanho digitado em rem no hero · amplitude achatada |
| **PN21g** | **Glow do acento turquesa JAMAIS sobre superfície de dado.** Destaque de ação usa **sombra projetada**, não glow | *Emenda do gate:* com a ação virando **pílula branca** sobre o escuro (ver **S4**), o glow turquesa perdeu o portador — brilho de acento atrás de um botão branco vira **halo sujo**. O destaque passou a sombra projetada. A proibição que importa (glow nunca sobre KPI, gráfico, tabela, mapa) continua medida na suíte | Glow sobre gráfico ou KPI (vira ruído sobre dado) · glow atrás de pílula branca |
| **PN21h** | **Movimento consome os 8 tokens dos primitivos** (PN11): nenhuma duração ou easing solto em `transition`; `prefers-reduced-motion` desliga transform e transição do cartão | O DS já tinha os tokens desde os primitivos; o que faltava era o consumo. Duração literal em CSS é o caminho por onde a camada de movimento deriva sem ninguém perceber | `transition: .2s ease` (valor solto) |

**Fronteira desta camada:** a camada visual inteira **vale no preview e não é canônica**. Depois
da inversão do hero (abaixo), restou **uma** decisão de marca em aberto — a **tinta da família**
(**S6**), que vive como camada alternável pelo botão "Tinta". O tom da âncora (**S3**) e a régua
de ação (**S4 retirado**) deixaram de ser conflito: a ação voltou para a família turquesa, que é
onde o `marca-seed.md` §3.5 sempre a colocou. Ver **PN-P1** em §48.9.

> ## SUPERSEDE DA ÂNCORA — o azul sai, entra o turquesa vivo (2026-08-13, noite)
>
> **Origem, nas palavras do Rafael:** *"a questão do azul eu tinha aceitado para podermos parar
> com os testes, pois não estava acertando. Retome as cores da SEED. Aquela caixa no topo que está
> azul quero que use um turquesa com cor viva, não pode ser escura nem cinza, senão fica muito
> escuro e parece velório."* E a instrução de método que destravou a solução: *"veja como o estudo
> do Viver de IA soluciona isso."*
>
> **A RESPOSTA ESTAVA NO ESTUDO, e eu não a tinha lido assim.** `estudo-viver-de-ia.md` **§9.2**
> (medição do código da plataforma): `--primary: 173 100% 46%` = **#00EBCF**. A primária deles
> **não é o navy dos prints** — é um **turquesa vivo**, a **1,1° de matiz** do nosso
> `turquesa-300` e a 0,9° do `turquesa-600`. O navy é *superfície de tema escuro*; o acento é
> turquesa. A §9.2 diz textualmente: *"o sistema é superfície quase-preta + acento turquesa — que
> é, essencialmente, o território do nosso dark mode."*
>
> **O erro de leitura que isso expôs:** nas duas rodadas anteriores eu copiei a **superfície**
> deles (escuro) e deixei o nosso turquesa como enfeite. Para uma marca cujo primitivo é turquesa,
> é o inverso do certo. **A inversão: o turquesa é a SUPERFÍCIE de ênfase, e a tinta é escura da
> própria família.** E o "vivo" que o Rafael pedia não depende de escuro — vem de três mecanismos
> que o próprio §8 do estudo nomeia: **P1** (varredura de 4–6 pontos de luminância dentro do
> próprio matiz), **P2** (sombra em rampa + anel) e **P4** (uma âncora por página contra branco).
> Os três funcionam sobre superfície clara.
>
> **O diagnóstico era luminância, não matiz** — e é isso que explica o "velório":
>
> | | `azul-800` (antes) | `turquesa-400` (agora) |
> |---|---:|---:|
> | Luminância | **6,03%** | **33,71%** — 5,6× mais claro |
> | Croma | 0,380 | **0,624** — +64% |
> | Tinta que carrega | branco 9,52 | `turquesa-900` **4,99** |
>
> Um hero a 6% de luminância é quase preto, e nenhuma quantidade de croma corrige isso.
>
> **Três consequências que a medição obrigou, e nenhuma era previsível de olho:**
>
> **(a) A luz inverteu de canto.** Com tinta branca, a luz apagava o texto e tinha sido empurrada
> para a metade vazia do hero. Com tinta escura a luz **ajuda** — 5,75 no ponto de luz contra 4,99
> na base —, então ela volta para o canto onde o texto vive. **E não existe poço:** descer um
> degrau para `turquesa-500` derrubaria a tinta a **4,20** e reprovaria. O `turquesa-400` é o
> **piso** da varredura, não o meio dela. Véu de `turquesa-300` a .35 → **ΔL 5,84 pontos**, dentro
> da faixa de 4–6 que o P1 mede, com croma preservado em 0,553.
>
> **(b) O anel virou obrigatório.** A base contra a página branca mede **2,71** e reprova o piso
> de fronteira de 3,0. Anel `turquesa-600` na mesma declaração da sombra (padrão PN21a) = **4,60**.
>
> **(c) A tinta é ÚNICA, e a hierarquia deixa de usar cor.** Baixar a tinta escura por opacidade
> reprova: **3,91** a .85 e **2,99** a .70. Dentro do hero há uma tinta só, e a hierarquia vem de
> **corpo e peso** — que é literalmente o que o estudo §2.1 diz: *"o contraste vem de forma e
> peso, não de matiz"*. Por consequência, **o itálico do sujeito perdeu a cor**: sobre o turquesa
> vivo nenhuma cor da paleta passa AA (branco 2,71 · `amarelo-200` 1,90 · `turquesa-100` 3,36), e
> a marcação passa a **itálico + peso 800** na mesma tinta — mecanismo que, ao contrário da cor,
> sobrevive ao grayscale. O amarelo **sai** do hero.
>
> **Ganho de estrutura que não estava no pedido: o hero passou a ter UMA face.** `turquesa-400`
> mede **6,86** contra a página escura e **5,61** contra o cartão escuro; a tinta segue em 4,99
> nos dois temas. Antes, `azul-800` media **1,41** contra a página escura e obrigava a subir para
> `azul-700` — duas composições para manter em sincronia. **A classe de defeito "camada sem
> variante de tema" ficou impossível aqui, por construção**, e não por disciplina.
>
> **A ação dentro do hero desceu um degrau, por decisão do Rafael no gate seguinte** (*"baixa pra
> 800"*): pílula `turquesa-800` #005048 — texto branco **9,37**, fronteira **3,45** contra a base
> e **3,98** contra o ponto de luz. É troca de **margem por matiz**: o 900 dava 4,99 de fronteira
> (66% de folga sobre o piso) e o 800 dá 3,45 (15%), e em troca a pílula lê turquesa em vez de
> quase-preta. **O 800 é o piso: `turquesa-700` mede 2,33 e reprova.** A pílula **branca** nunca
> foi opção — 2,71.

### 48.4 Edição direta · PN22–PN41

> **Escrita em 2026-08-13, rodada 3.** Esta seção existe porque o painel do ERP **não é só
> leitura**: o gestor reagenda uma OS arrastando a barra, reatribui puxando o cartão para outra
> faixa, muda o estado soltando na coluna. Sem contrato, cada tela implementaria o arrasto de um
> jeito e o teclado de nenhum.
>
> **A regra que unifica cinco lentes é uma só (PN33): ONDE O ITEM CAI É O VALOR DO CAMPO.**
> Coluna do kanban = estado · faixa do tempo e da carga = responsável · dia do calendário = data ·
> posição no gantt = datas. O que é **derivado** nunca se arrasta (PN22) e o mapa é **leitura**
> (PN39).
>
> **Norma que governa a seção: WCAG 2.2, SC 2.5.7 Dragging Movements (AA)** — toda funcionalidade
> que use movimento de arrasto tem de oferecer **caminho de ponteiro único** alternativo. É por
> isso que o PN23 não é conveniência: é conformidade.

| # | Decisão | Porquê / número medido | Descartado |
|---|---|---|---|
| **PN22** | **O DERIVADO NUNCA SE ARRASTA.** Carga de trabalho, ranking, KPI e barra de status são **resultado de cálculo**: não têm campo de destino, e por isso não têm alça | Arrastar uma barra de carga significaria *"trabalhe menos"* — o gesto não tem para onde escrever. Oferecer a alça e ignorar o gesto é a classe do **botão morto**. *Guarda:* `E-15` mede que nenhuma barra da carga é arrastável | Alça em bloco derivado · alça que não faz nada (botão morto) |
| **PN23** | **CAMINHO DE PONTEIRO ÚNICO PARA TUDO QUE SE ARRASTA.** Menu **"Mover sem arrastar"** aplica a MESMA mutação, com o mesmo desfazer; criar tem **botão explícito**, sem depender de passar o mouse | **SC 2.5.7 (AA).** Além da norma: em toque real, arrastar dentro de faixa rolável compete com o gesto de rolagem — o caminho alternativo é o que faz a tela funcionar no celular. *Guardas:* `E-22`, `E-23`, `I-17`, `I-19` | Arrasto como caminho único (reprova AA) · alternativa que aplica mutação diferente (duas verdades) |
| **PN24** | **CONTRATO DE TECLADO ÚNICO, IGUAL EM TODA LENTE:** **Enter/Espaço** pega o item e o anúncio **ensina o contrato** (*"setas movem, Enter solta, Esc cancela"*) · **setas anunciam o DESTINO antes de confirmar** · **Enter** solta aplicando a mesma mutação do arrasto · **Esc** cancela sem aplicar | Arrasto sem teclado exclui quem não usa ponteiro. O anúncio que **ensina** existe porque um contrato de teclado que ninguém descobre é um contrato que não existe. Anunciar o destino **antes** de confirmar é o que torna o gesto reversível sem custo. *Guardas:* `E-18…E-21` | Teclado diferente por lente · mover sem anunciar destino (o usuário confirma no escuro) |
| **PN25** | **O ÍMÃ É A UNIDADE DA ESCALA:** modo hora → passo de 1 hora · dia, semana e mês → passo de 1 dia. **Datas inteiras, sem hora residual** | Precisão maior que a escala é **precisão inventada**: arrastar num gantt de mês não pode gravar 14h37. *Guardas:* `E-07` (datas inteiras), `F-19` (em escala de hora o arrasto move horas) | Ímã no pixel · granularidade fixa independente da escala |
| **PN26** | **A CASCATA DE DEPENDÊNCIA É MOSTRADA EM FANTASMA ANTES DE SOLTAR e DECLARADA EM NÚMERO no anúncio** | Mover uma ordem que trava outras três muda quatro datas. Se o usuário só descobre depois, o desfazer vira obrigatório em vez de opcional. O número no anúncio é o que dá ao usuário de leitor de tela a mesma informação que o fantasma dá ao olho. *Guarda:* `E-08` | Aplicar cascata em silêncio · mostrar cascata só depois de soltar |
| **PN27** | **MUTAÇÃO OTIMISTA:** o gesto aplica na hora, na tela; confirmação e conflito de servidor são **produto** (fronteira do DM10) | Esperar o servidor a cada arrasto torna o gesto inutilizável. O DS entrega o contrato de tela: aplicar, anunciar, oferecer desfazer. Compõe com o **PN30** (refresh adiado) | Aguardar confirmação para desenhar · aplicar sem desfazer |
| **PN28** | **DESFAZER DE 8 SEGUNDOS, com contagem visível, cobrindo TAMBÉM criação e exclusão. O anúncio diz o RESULTADO, não o percurso** | *"OS-2288 reagendada para 17/08→19/08"* é resultado; *"arrastada 3 colunas"* é percurso, e percurso não se verifica. **O desfazer que não cobre criação é meia verdade** — foi o defeito que apareceu ao ligar a linha de criação. *Guardas:* `E-02…E-05`, `E-29`, `G-14`, `G-15`, `E-41` (o lote em massa volta inteiro) | Toast sem contagem (o usuário não sabe quanto tempo tem) · desfazer só de edição · anúncio de percurso |
| **PN29** | **ITEM TRAVADO NÃO GANHA ALÇA E DIZ O MOTIVO**, com `aria-disabled` e caminho alternativo | Alça que existe e não obedece é botão morto. Motivo invisível transforma trava em bug aos olhos de quem usa — *foi literalmente o relato do gate* (ver **PN46**). *Guarda:* `E-17b` | Alça inerte · trava silenciosa |
| **PN30** | **REFRESH PEDIDO DURANTE EDIÇÃO É ADIADO, NUNCA SILENCIOSO** — o item sob edição é imune, e o adiamento é dito | Sobrescrever o que o usuário está arrastando é perder trabalho sem aviso. Compõe com o **PN9**: adiar é decisão de tela, não de transporte. *Guarda:* `E-26` | Aplicar refresh sobre item em edição · descartar o refresh sem avisar |
| **PN31** | **A ALÇA TEM ALVO DE TOQUE PRÓPRIO (≥44px de área efetiva) e a faixa ROLA sob o ponteiro perto das bordas** (autoscroll, margem de 48px) | Alvo de 44px é regra do DS desde o §1. O autoscroll existe porque reagendar de 15/08 para 30/09 exige sair da janela visível — sem ele, o gesto é impossível sem soltar e rolar. *Guarda de origem:* o link endereçável da timeline media **14px** de altura e só o render pegou | Alça de 14px · faixa que não rola durante o arrasto |
| **PN32** | **ORDENAÇÃO ATIVA DESLIGA O ARRASTO DE REORDENAR, E DIZ POR QUÊ** | Arrastar para reordenar sob ordenação automática produz um resultado que o próprio sistema desfaz no próximo redesenho. Desligar **e explicar** é honesto; desligar em silêncio é bug percebido. *Guardas:* `E-24`, `E-25` (o gesto de fato não muda nada) | Permitir os dois (o sistema desfaz o gesto) · desligar sem motivo visível |
| **PN33** | **ONDE O ITEM CAI É O VALOR DO CAMPO.** Coluna do kanban = `estado` · faixa do tempo e da carga = `resp` · dia do calendário = `data` · posição e largura no gantt = `inicio`/`fim` | É a regra que unifica cinco lentes com **um** motor de arrasto. Sem ela, cada lente teria semântica própria de soltura e o contrato de teclado do PN24 não poderia ser único. *Guardas:* `E-01`, `E-11`, `E-13` | Semântica de soltura por lente · zona de soltura sem campo declarado |
| **PN34** | **CRIAR NO VAZIO, COM O CONTEXTO JÁ PREENCHIDO:** nascer na coluna do kanban já traz o estado daquela coluna; clicar num dia vazio do calendário cria **naquela data** | O contexto do gesto **é** informação; pedir de novo num formulário em branco desperdiça o que o usuário já disse. *Guardas:* `E-28`, `E-30` | Criar sempre em branco · criar sem herdar a zona |
| **PN34b** | **O RESULTADO TEM DE SER VISTO:** o que acabou de mudar é **realçado por 1.600ms** e **trazido ao campo de visão** (vertical e horizontalmente) | **Relato literal do gate.** Um item criado ou agendado fora do enquadramento faz o usuário concluir que **nada aconteceu** — e o sistema estava correto. *Lição de método permanente:* o que nasce fora do campo de visão é lido como "não funcionou". *Guardas:* `I-07`, `I-08` | Aplicar sem realçar · realçar sem rolar até o item |
| **PN35** | **MOVER ≠ REDIMENSIONAR:** punhos nas pontas mudam **só a borda arrastada**; o gesto mexe em **`left`/`width`, NUNCA em `transform`**; a borda oposta não se move | *Defeito do gate:* ao esticar, a barra inteira se deslocava. Causa: `transform` translada o elemento todo. **Regra:** redimensionamento é geometria de caixa, não transformação. E o anúncio distingue os dois gestos, senão o usuário de leitor de tela não sabe qual aconteceu. *Guardas:* `E-09`, `E-10`, `H-06…H-09` (nenhum `transform` no gesto; a largura cresce **durante** o gesto) | `transform` no redimensionamento · punho que move a barra · anúncio idêntico para mover e esticar |
| **PN35b** | **A MESMA ETAPA PODE TER VÁRIOS PERÍODOS NA MESMA LINHA.** Modelo: **segmento `-1`** é o principal (`inicio`/`fim`, lido por calendário, vencimentos e carga) e **`0..n`** são adicionais, que existem só no eixo do tempo. O gesto age sobre o **segmento tocado**, não sobre a ordem inteira | Pergunta do Rafael no gate: *"posso trabalhar na mesma linha/etapa em mais de um período?"* — e a resposta do domínio é sim: manutenção que para no fim de semana e retoma na segunda é **uma etapa, dois períodos**. As duas alternativas eram piores: recusar o gesto (o dado real não cabe) ou criar outra ordem (duplica a etapa e mente na contagem). *Guardas:* `J-01…J-08` — o extra se identifica no rótulo (*"período 2"*), move-se sozinho, e o menu dele oferece **remover o período**, não excluir a ordem | Recusar o segundo período · criar ordem nova (o conjunto cresceria mentindo) · mover o extra arrastando o principal |
| **PN36** | **DEPENDÊNCIA É LISTA, não campo único.** Criada **puxando do nó** até a barra da predecessora; **removida com gesto deliberado** (duplo clique ou botão direito); **ciclo é recusado e explicado**; ligar uma terceira predecessora **acrescenta**, não substitui | Uma ordem pode depender de várias — o campo escalar é o defeito de modelagem que aparece na primeira obra real; o helper aceita o formato antigo para não quebrar dado herdado. **Clique simples removia por acidente** ao passar sobre o fio: ação destrutiva não mora em alvo invisível que cruza a área. *Guardas:* `E-31…E-33`, `I-12` (clique simples NÃO remove), `I-21…I-24` (duas predecessoras no dado, cada uma com fio próprio) | `dep` escalar · remoção por clique simples · substituir a predecessora ao ligar outra · aceitar ciclo |
| **PN37** | **A LENTE TABELA É PLANILHA:** setas navegam entre células, **Enter** abre editor **na própria célula**, e a **alça copia o valor para as células abaixo** | O ERP tem preenchimento repetitivo (mesmo responsável para dez OS). Sem planilha, isso são dez formulários. Herda o §40; a alça é o gesto que o usuário já conhece de fora. *Guardas:* `E-34…E-38` | Editar só em formulário · setas que rolam a página em vez de navegar células |
| **PN38** | **SELEÇÃO E AÇÕES EM MASSA:** a barra de ações **só aparece com seleção**, a ação muda todas de uma vez e o **desfazer reverte o lote inteiro** | Herda o §41 (seleção) e o §42 (toolbar). A barra que existe vazia ocupa espaço e não responde. O desfazer parcial é pior que nenhum: deixa o conjunto num estado que o usuário não pediu. *Guardas:* `E-39…E-41` | Barra sempre visível · desfazer item por item depois de uma ação em massa |
| **PN39** | **O MAPA É LEITURA: o pin NÃO se arrasta.** A localização vem do cadastro da usina, não do gesto | Mover o pin significaria mudar a coordenada da usina — que é cadastro, não agendamento. Arrastar ali seria editar o cadastro por acidente. *Guarda:* `E-16` | Pin arrastável · mapa como editor de cadastro |
| **PN40** | **FILTRO É DA VISÃO, NÃO DA LENTE:** chips removíveis para o que está ativo · **contagem honesta** (*"5 de 14 · 9 ocultas"*) · vazio que **explica que é filtro** e diz quantas existem · **o mesmo recorte em qualquer lente** · limpar devolve o conjunto inteiro | Contagem que não diz o que ficou de fora faz o usuário concluir que o dado desapareceu. O recorte igual em toda lente é o **PN5** aplicado ao filtro. *Defeito medido:* criar ou excluir mexe no **tamanho** do conjunto e a contagem continuava dizendo "14 ordens" — **contagem que não acompanha a mutação é contagem que mente**. *Guardas:* `F-01…F-07`, `I-16`, `I-26` (criar fora do filtro ativo **limpa o filtro e diz por quê**, em vez de criar no vazio) | Filtro por lente · contagem só do que sobrou · vazio genérico ("nada aqui") |
| **PN41** | **A ESCALA É DENSIDADE, NÃO RECORTE:** hora · dia · semana · mês mudam a largura por unidade e a granularidade dos rótulos — **o conjunto desenhado é o mesmo**. Fins de semana marcados; **linha do HOJE única** | Zoom que troca o intervalo **esconde dado**; zoom que troca a densidade só aproxima o olho. *Guardas:* `F-08…F-11`, `F-22`, `H-01…H-05` (cada escala tem **uma coluna por unidade**, alinhada à borda da unidade — mês começa no dia 1) | Escala que muda o intervalo · escala que só troca o cabeçalho (a mesma classe do PN3b) |
| **PN41b** | **ESCALA DE HORA**, com a unidade da faixa **parametrizada**: 24 unidades por dia no modo hora, 1 nos demais | *Pedido do gate:* a manutenção de campo tem janela (*"a equipe entra 8h e sai meio-dia"*) e sem hora o gantt não responde a pergunta que o cliente faz. O ímã acompanha (**PN25**) | Gantt só em dias (não responde à pergunta do campo) · hora fixa com dia derivado |
| **PN41c** | **A JANELA ABRE NO HOJE**, não no início da faixa | Faixa rolável de 60 dias abre no dia 1 e o usuário rola até achar hoje — em toda troca de escala. *Guarda:* `F-18` | Abrir no início da faixa |
| **PN41d** | **O ZOOM SE DECLARA EM UNIDADES VISÍVEIS, não em pixels:** *"8 h na tela"*, *"15 d na tela"*; o px por unidade é **derivado da largura disponível**. No fim do curso o botão **desabilita**, não vira clique morto | É a pergunta que o usuário faz de verdade (*"quero ver as 8 horas do turno"*, *"quero a semana inteira"*). Derivar o px da largura é o que faz o mesmo ajuste funcionar em **1180px e em 390px** — px fixo por unidade quebra num dos dois. *Guardas:* `F-21…F-26`; o `F-25` mede que **a quantidade prometida no rótulo é a que de fato cabe na tela** | Px fixo por unidade · zoom em porcentagem (não responde à pergunta) · botão de zoom que continua clicável no fim do curso |
| **PN41e** | **PANORÂMICA EM MODO EXPLÍCITO:** dois botões — **Criar** × **✋ Mover** — mais atalhos que sempre valem (segurar espaço, Shift+arrasto, botão do meio). Só o **fundo** faz panorâmica; barra, punho e nó continuam sendo edição; limiar de **4px** antes de virar panorâmica | **Dois gestos disputavam o mesmo pixel:** arrastar no vazio criava período (PN49) e também deveria deslocar a janela. Em vez de adivinhar a intenção, o modo é explícito, como em ferramenta de desenho — seta cria, mão navega. *Lição de método permanente: dois gestos não podem dividir o mesmo pixel.* *Guardas:* `F-27…F-29` (a panorâmica **não rouba** o gesto de edição da barra) | Adivinhar a intenção pelo contexto · panorâmica em qualquer ponto (mataria a criação) · modo implícito por tecla apenas (não há tecla no toque) |

### 48.5 Gantt profissional · PN42–PN45 — **RESERVADO, produção no bloco 6D**

**Estes quatro códigos estão reservados e deliberadamente vazios.** Não são omissão: são o
escopo do **bloco 6D**, separado deste por decisão de tamanho — o 6C entrega o gantt que reagenda
e encadeia; o 6D entrega o gantt que **planeja**.

| # | Escopo reservado |
|---|---|
| **PN42** | Os quatro tipos de dependência (**FS**, **SS**, **FF**, **SF**) mais **folga/lag** — hoje o preview implementa apenas fim→início |
| **PN43** | **Caminho crítico** e folga calculada |
| **PN44** | **Linha de base** (baseline) e comparação plano × realizado |
| **PN45** | **Marco** como losango sem duração |

*Por que reservar em vez de renumerar:* as cinco camadas de validação e o preview v0.6 já citam
`PN46`…`PN54` nos comentários e nas guardas. Renumerar para fechar o vão exigiria reescrever os
quatro artefatos executáveis e invalidaria as âncoras MD5 recém-calculadas, trocando um vão
documentado por um risco de deriva. **O vão é intencional e está declarado aqui.**

### 48.6 Contratos que o gate de 2026-08-13 produziu · PN46–PN50

> Estas cinco decisões **não estavam previstas**: nasceram do gate visual do Rafael sobre o
> preview em uso real. Cada uma tem o relato de origem registrado, porque o relato é a evidência.

| # | Decisão | Porquê / relato de origem | Descartado |
|---|---|---|---|
| **PN46** | **A POLÍTICA DE TRAVA É DO DOMÍNIO, NÃO DO DESIGN SYSTEM.** O DS entrega o **contrato** (travado + motivo visível + `aria-disabled` + caminho alternativo); a **regra** vem de fora, como parâmetro | *Relato:* **"a coluna Concluída não move"** — lido como defeito. E era, no sentido que importa: *"concluída não move"* estava **soldado no DS**, que passou a legislar sobre workflow. Uma empresa quer travar concluídas; outra quer reabrir. **O preview expõe as duas políticas (botão "Travar concluídas") para exercer os dois lados** — é assim que se prova que o contrato funciona ligado E desligado. *Guardas:* `E-17a` (sem política, nada trava — o DS não inventa regra de negócio), `E-17b` (com política, o travado não ganha alça e **diz** o motivo) | Regra de workflow dentro do DS · política sem os dois lados testados (metade do contrato sem prova) |
| **PN47** | **PRÉ-REQUISITO DE LENTE PASSA DE "TODOS TÊM O DADO" PARA "ALGUÉM TEM O DADO", e quem não tem vai para a GAVETA DE NÃO AGENDADOS** — visível, contada e arrastável de volta para o tempo. **No gantt, toda ordem tem LINHA; o que falta é a barra** | *Relato:* uma **única** ordem sem data derrubava o gantt inteiro — a lente sumia e o usuário não sabia por quê. A gaveta resolve os dois lados: a lente aparece e desenha quem tem, e o que falta fica **à vista em vez de escondido**. Dar linha a quem não tem data é o que permite **agendar arrastando na própria linha** (ver **S8**). *Guardas:* `F-12…F-14`, `I-01`, `I-02` | Exigir o dado em todos (o defeito) · esconder o não agendado (o usuário conclui que não existe) · lente vazia |
| **PN48** | **RÉGUA DE TEMPO EM DOIS NÍVEIS — contexto em cima, unidade embaixo — com UMA COLUNA POR UNIDADE, alinhada à linha de grade** | *Relato/medida:* a régua antiga espalhava N rótulos por interpolação; em escala de hora dava para ver *"12/08 19h"* a cada 6 horas e **nenhuma coluna dizia que hora era**. Régua e faixa deixaram de medir o mesmo. Dois níveis é o que permite **ler** a coluna em vez de adivinhar: hora↔dia · dia↔mês/ano · semana↔mês · mês↔trimestre. *Guardas:* `G-01…G-05`, `H-01…H-03` | Rótulos por interpolação · um nível só · régua com granularidade diferente da faixa |
| **PN49** | **CRIAR PERÍODO ARRASTANDO NA FAIXA VAZIA**, com **semente visível seguindo o ponteiro**, **rascunho desenhado durante o arrasto**, e **clique sem arrastar também criando**. **O convite aparece onde o gesto age** e promete exatamente o que vai acontecer | *Relato:* a linha vazia não convidava a nada, e onde convidava, o gesto não agia. **Lição de método permanente: convite que aparece onde o gesto não age é pior que convite nenhum.** A dica é específica por linha: linha **sem data** promete *agendar*; linha **já agendada** promete *outro período* (PN35b); a **linha de criação** no fim do gantt promete *criar*. *Guardas:* `G-06…G-10`, `I-09…I-11`, `I-13…I-18` (a faixa da linha de criação é marcada **sempre**, não só no hover) | Faixa vazia sem convite · convite genérico igual em toda linha · convite em zona inerte |
| **PN50** | **MENU DE CONTEXTO (botão direito) EM TODO ITEM + CARTÃO DE EDIÇÃO por clique**, com o menu levando o **foco para a primeira ação** e oferecendo abrir, duplicar, desagendar, concluir e excluir — **excluir reversível, e dizendo isso** | Arrasto cobre data, responsável e estado; o resto precisa de porta. O menu é o mesmo em todas as lentes, senão o usuário reaprende a cada troca. **O cartão de edição aqui é a versão mínima e é o gancho declarado do §49** (painel de detalhe): existe para exercer o contrato, não para especificá-lo. *Guardas:* `G-11…G-17` | Menu diferente por lente · menu que abre sem levar o foco (teclado fica órfão) · excluir irreversível |

### 48.7 Lente mapa · PN51–PN54

> **A lente mapa tem duas perguntas diferentes por trás**, e é isso que produz os dois modos:
> *"onde estão as ordens?"* (leitura, laudo, impresso) e *"como eu chego lá?"* (navegação em
> campo). Guia de ligação para o produto em `mapa-base-lovable.md` *(a âncora deste guia MUDOU DE CAMINHO em 2026-08-13 — era `validacao/`, passou à raiz: a pasta `validacao/` é declarada no `LEIA-ME.md` dela como a dos artefatos EXECUTÁVEIS, e este é documentação de entrega ao produto; ver §19-b do MANIFESTO v4.0)*. **Recomendação
> aprovada pelo Rafael:** MapLibre GL + provedor de tiles; Google apenas para geocodificação, se
> necessário.

| # | Decisão | Porquê / número medido | Descartado |
|---|---|---|---|
| **PN51** | **DOIS MODOS DECLARADOS: `cobertura` (PADRÃO) e `operacao`.** Cobertura é a **malha IBGE do §4d** — projetada, imprimível, sem rede. Operação é **mapa base navegável** com tiles | O modo é do **contexto**, não da preferência: laudo, e-mail e papel são cobertura; ir até a usina é operação. Cobertura é padrão porque é a que **sempre funciona** e porque é a que entra em documento. *Guardas:* `M-01`, `M-02` | Um modo só (nenhum dos dois serve os dois casos) · operação como padrão (quebra em papel e sem rede) |
| **PN52** | **O ESTILO DO MAPA BASE CONSOME TOKENS, e o MARCADOR É PEÇA DO DS** — a mesma forma no mapa base e na lista textual | Mapa com a paleta do fornecedor é o único lugar da tela onde a identidade não se aplica, e é justo o que o cliente fotografa. Marcador próprio garante que o mesmo símbolo apareça nos dois modos e na alternativa textual. *Guardas:* `M-09`, `M-10` (cada usina carrega **coordenada geográfica** além da posição projetada) | Estilo default do fornecedor · marcador do fornecedor · símbolo diferente entre mapa e lista |
| **PN53** | **FALLBACK OBRIGATÓRIO E DECLARADO:** sem biblioteca, sem chave, sem rede ou em impressão, o modo operação **cai para a cobertura** e **DIZ o que aconteceu**. **Nenhuma chave de API vive no artefato** — a fonte de tiles vem da configuração do ambiente | **Equipe em campo com sinal ruim é o caso normal, não a exceção.** O mapa não fica em branco nem mente: cai para a cobertura oficial e anuncia. A chave fora do artefato é requisito de segurança e de LGPD, não conveniência. *Guardas:* `M-04`, `M-05` (o fallback **diz** o que aconteceu, em vez de mostrar retângulo vazio), `M-07`, `M-08` | Retângulo vazio · fallback silencioso · chave embutida no HTML |
| **PN54** | **ALTERNATIVA TEXTUAL SEMPRE PRESENTE, NOS DOIS MODOS, COMO CONTEÚDO** — lista de usinas com marcador, nome, município/UF e contagem de OS ativas; **nunca só `aria-label`** | **Mapa interativo não é navegável por leitor de tela** — e a lista não é enfeite de acessibilidade: é a forma mais rápida de ler o mesmo dado para qualquer pessoa, e a única que sobrevive ao copiar-e-colar num e-mail. *Guardas:* `M-03`, `M-06` | `aria-label` descrevendo o mapa · alternativa só no modo cobertura · alternativa escondida atrás de botão |

### 48.8 Supersedes formais desta rodada

**Regra do projeto:** todo contrato substituído recebe supersede formal, com o número que o
motivou — nunca nota solta. Estes dez são os desta rodada.

| # | O que dizia | O que passa a dizer | Número que motivou |
|---|---|---|---|
| **S1** | **PN3, 1ª redação:** cinco lentes (lista · tabela · quadro · linha do tempo · calendário) | **Oito lentes**, com `gantt` e `tempo` separados e `carga` e `mapa` acrescentados | A documentação do ClickUp separa gantt (tarefas conectadas) de timeline (recurso), e o Rafael decidiu que o template estrutural nasce com o lugar da alocação de pessoa |
| **S2** | O rótulo **"quadro"** como nome da lente kanban | **`kanban`** é o identificador canônico; "quadro" fica como sinônimo de fala, não de código | Os artefatos usam `data-lente="kanban"`; manter dois nomes para a mesma lente é a porta da deriva |
| **S3** *(revisto na mesma data — ver S11-b abaixo)* | **Tom do escuro estrutural: `cinza-900`** (croma 0,063) | ~~**`azul-800` #004C61**~~ **SUPERSEDIDO NA MESMA NOITE por `turquesa-400` #11B0A0** (croma 0,624, L 33,71%) — a âncora deixou de ser escura. O texto abaixo preserva a cadeia de medições que levou ao azul, porque ela documenta quatro tentativas reprovadas que não devem ser repetidas: ~~**`azul-800` #004C61** (croma 0,380, L 6,03%), com luz em `azul-700` #006783 e poço em `azul-900` #003241. **No tema escuro o hero SOBE para `azul-700`** | Cadeia de quatro medições no mesmo gate: **(a)** o hero SEED já era quase 3× mais claro que o do estudo (L 9,12% × 3,25%) e lia mais morto, porque tinha **metade do croma** (0,087 × 0,175) — *escuro dessaturado lê como fumaça, escuro saturado lê como tinta*; **(b)** `turquesa-900` #00352F (croma 0,208) resolveu o croma sem navy alheio, branco em 13,55; **(c)** *"precisamos usar uma cor mais clara"* → `turquesa-800` (L 6,21%, croma 0,314), teto da luz em `turquesa-600` porque acima disso (500 = 3,22) o branco reprovaria; **(d)** *"essa cor é muito escura e deixa tudo preto e branco; o deles usa um azul"* → a escala turquesa esbarra num teto (no 700 o micro-rótulo cai a **4,11**), e o **azul-800 entrega 21% mais croma na mesma luminância**. No tema escuro, `azul-800` media **1,41** contra a página e **1,24** contra o cartão — deixava de ancorar; `azul-700` dá 2,65 e 2,19 com branco em 6,43, e `azul-600` separaria melhor (3,69) mas derrubaria o branco a 4,61. **Regra que fica: no escuro, elevação é LUZ, não sombra** |
| **S4** ⚠ **RETIRADO em 2026-08-13, na mesma data em que nasceu** | **`marca-seed.md` §3.5:** *"ação primária é sempre família turquesa/verde — nunca azul"* — **e esta regra PERMANECE VIGENTE, intocada** | **O supersede foi RETIRADO.** Com a âncora virando turquesa vivo (S11), a ação voltou à família da marca e **não há mais nada a superseder em `marca-seed.md`**: a régua vigente é `turquesa-600` #098475 + branco = **4,60**, e o #098475 é o hex que o próprio §3.5 nomeia. O texto abaixo fica como **registro histórico da tentativa**, não como contrato: ~~**A ação não tem cor própria: ela usa o ESCURO ESTRUTURAL.** Primária sobre claro = `azul-800` + branco (**9,52**) · primária **dentro** do escuro = pílula **branca** + `azul-900` (**13,70**) · secundária no escuro = ghost translúcido + branco (9,52) · secundária sobre claro = outline `azul-800` (9,52) · terciária = link com seta (4,60). **No tema escuro a ação SOBE na escala: `azul-400`** (superfície 5,71 · texto `azul-900` 5,56). **O turquesa continua no sistema como ACENTO** — itálico do sujeito, séries de dataviz, pontos de estado —, o que muda é que ele deixa de carregar a ação | Gate do Rafael com o print da plataforma: *"a cor do botão tem que seguir o mesmo padrão da caixa grande"*. **Tentativa reprovada pela medição, registrada para não se repetir:** baixar a primária do escuro para `azul-500` deixaria o botão menos "neon" (superfície 4,24) mas o texto cai para **4,13**, abaixo do piso de 4,5 — e **nenhum** tom escuro da paleta salva (`azul-900` 4,13 · `cinza-900` 4,17 · `turquesa-900` 4,08 · branco por cima 3,32). `azul-400` é o degrau **mais baixo** que sustenta texto pequeno no escuro. **⚠ Este supersede vale no PRODUTO DIGITAL e é decisão de MARCA: exige registro do Rafael em `marca-seed.md` antes de ser canônico** |
| **S5** | *"Ordem concluída não move"* como regra do DS | **PN46:** o DS entrega o contrato de trava; a política é parâmetro do domínio | Relato do gate *"a coluna Concluída não move"* leu como defeito uma regra de workflow embutida no DS |
| **S6** | **Tinta neutra:** `text-primary` e `text-secondary` na família cinza | **PROPOSTA, não canônico:** tinta da família do escuro estrutural — `text-primary` **#0B3330** (× branco **13,72**) · `text-secondary` **#2F5A54** (× branco **7,75**) · bordas e superfícies esverdeadas; no escuro **#DDECE8 / #A3C4BE / #0F1F1C / #16302C** | O estudo (§2.1) usa tinta *da mesma família do escuro estrutural*, medida em croma **0,192** e saturação 83% contra **0,063** e 31% da nossa. Como texto e bordas ocupam a maior parte da área, tinta neutra faz a tela **inteira** ler cinza mesmo com o hero colorido — foi o que o gate apontou. **Vive como camada alternável no preview (botão "Tinta"), não no canônico: muda o DS inteiro** (ERP, e-mail, documentos, site) e depende de decisão de marca. *Defeito medido a registrar:* a 1ª versão desta camada foi escrita **sem variante de tema** e no escuro impunha tinta clara sobre cartão escuro — o painel virava ilegível. **Regra permanente: toda sobrescrita de token semântico precisa das DUAS faces; um bloco só é meia implementação** |
| **S7** | **Largura da faixa de tempo em px fixo por dia** | **PN41d:** a faixa é **função da escala e da largura disponível** — declara-se quantas unidades devem caber, e o px por unidade é derivado | O mesmo ajuste tinha de funcionar em 1180px e em 390px; px fixo por unidade quebra num dos dois. Guarda `F-25` mede que a quantidade prometida no rótulo é a que cabe de fato |
| **S8** | **PN4:** o gantt exige início E fim em **todos** os itens | **PN47/`PN4-03e`:** o gantt exige **ao menos uma** ordem agendada, **dá LINHA a quem não tem data** (a barra é que não existe) e manda o resto para a gaveta | Uma única ordem sem data derrubava a lente inteira. *Consequência de projeto, não só de tolerância:* dar linha a quem não tem data é o que torna possível **agendar arrastando na própria linha** (PN49) |
| **S9** | Gesto em linha já ocupada = recusar, ou criar ordem nova | **PN35b/`I-06`:** gesto em linha ocupada **acrescenta um PERÍODO** à mesma etapa, sem criar ordem | Pergunta do Rafael (*"posso trabalhar na mesma linha/etapa em mais de um período?"*) contra o dado real da manutenção que para e retoma. Guarda `J-05` mede que o conjunto **não cresce** (14 → 14) |
| **S11** | **Âncora ESCURA** — a caixa de ênfase da página é escura, com texto claro; a ação usa o escuro estrutural (S3+S4) | **ÂNCORA CROMÁTICA:** `turquesa-400` #11B0A0 com **tinta única** `turquesa-900`, **anel** `turquesa-600` e **véu de luz** `turquesa-300` a .35 no canto do texto (ΔL 5,84). A ação volta à família: primária sobre claro **`turquesa-600` + branco 4,60** · dentro do hero **pílula `turquesa-800` + branco 9,37** (fronteira 3,45) · secundária sobre claro outline **`turquesa-700` 6,32** · no tema escuro a ação sobe para **`turquesa-400` + `turquesa-900`** (superfície 5,61 · texto 4,99) | *"Parece velório"* + a instrução de olhar o estudo. **§9.2 do `estudo-viver-de-ia.md`:** a primária da plataforma é **#00EBCF**, turquesa vivo a 1,1° do nosso `turquesa-300` — o navy é superfície, o acento é turquesa. Nós vínhamos copiando a superfície e deixando o turquesa como enfeite. Diagnóstico medido: **luminância**, não matiz — 6,03% × 33,71%. Reprovações que fecham as alternativas: `turquesa-500` derruba a tinta a 4,20 · pílula branca 2,71 · `turquesa-700` como pílula 2,33 · itálico em qualquer cor da paleta reprova (branco 2,71 · amarelo-200 1,90 · turquesa-100 3,36) |
| **S11-b** | **PN21c:** *"UM hero ESCURO por página"*; e a face escura do hero como composição própria | **UMA ÂNCORA DE ÊNFASE por página** — a palavra "escuro" sai do contrato, porque era descrição de implementação, não invariante. E a **face escura desaparece**: o mesmo par serve os dois temas | O tom mudou **cinco vezes em dois dias** (`cinza-900` → `turquesa-900` → `turquesa-800` → `azul-800` → `turquesa-400`), sempre com a guarda exigindo o valor da vez. O invariante real nunca foi a escuridão: é **uma âncora cromática da marca por página**. Ganho medido: `turquesa-400` mede 6,86 × página escura e 5,61 × cartão escuro, contra 1,41 do `azul-800` — **duas composições viraram uma**, e a classe "camada sem variante de tema" ficou impossível aqui por construção |
| **S12** | Fronteira de 3,0 exigida de **toda** pílula que pousa no hero | **COMPONENTE × CONTEÚDO.** A fronteira de 3,0 (SC 1.4.11) é exigida de **pílula interativa** (`btn-solucao`, `btn-ghost-hero`); o **chip de status é ISENTO**, com o motivo escrito no CSS | Erro meu de enquadramento, corrigido no gate: eu havia reprovado o chip branco a **2,71** pelo mesmo critério da ação. O 1.4.11 alcança *"informação visual necessária para IDENTIFICAR COMPONENTES e seus estados"* — o chip é **conteúdo** (rótulo de status, não focável, não acionável), e dele a norma exige o **texto** pelo 1.4.3, medido em **6,58**. E o estudo §2.4 fecha por outro lado: *"hierarquia por PREENCHIMENTO, não por forma"* — todo anel que passasse dos dois lados obrigaria a escurecer o chip, e o `turquesa-900` (4,99) ficaria **mais escuro que o próprio botão** (800), invertendo a hierarquia; o anel semântico, que seria o correto, **reprova** (`feedback-danger-text` 2,65). *Guardas:* `PN21-05e` (pílula interativa só com fill medido), `PN21-05f` (**o chip não é interativo — é o que sustenta a isenção; no dia em que virar botão, a suíte reprova**), `PN21-05g` (a isenção está declarada no artefato, não só aqui) |
| **S10** | **PN21g, 1ª redação:** glow do acento turquesa em elemento de destaque de ação | **Sombra projetada** no destaque de ação; o glow sai. A proibição que importa — **glow jamais sobre superfície de dado** — permanece | Com a ação virando **pílula branca** sobre o escuro (S4), o glow turquesa perdeu o portador: brilho de acento atrás de botão branco vira **halo sujo** |

### 48.9 Fronteiras declaradas e pendências

**Fora deste bloco, e a maior parte por decisão explícita do Rafael:** quais blocos existem em
cada tela e como o workflow se organiza (**projeto do ERP**) · a estrutura de **setores e áreas**
— Admin, Engenharia, Comercial, Qualidade — declarada pelo Rafael como desenho do ERP · qual
perfil vê o quê (**regra de negócio**) · quais KPIs cada tela mostra, o que entra na timeline e
como o progresso é calculado (**projeto do ERP**) · cálculo e agregação de indicador
(**produto**) · **transporte de tempo real**, websocket, persistência e resolução de conflito de
edição concorrente (**produto — Lovable/Supabase**, fronteira do DM10) · BI exploratório ad-hoc
(**fora de escopo desde o DF6**, revisável) · **geocodificação de endereço** e contratação de
provedor de tiles (**produto**).

**Ainda sem dono declarado, e não entram por decisão:** os itens 🟡 do censo do
`estudo-viver-de-ia.md` — **comparação com referência fora de gráfico** (semântica órfã desde o
supersede do DM8), **agenda/sessão/vaga**, **hero de identidade + stats** e
**documento-cerimônia**. Entrar sem consumidor real repetiria o erro que o §7 daquele estudo
mandou evitar.

**PENDÊNCIAS ABERTAS, nomeadas para não se perderem:**

| # | Pendência | Bloqueia |
|---|---|---|
| **PN-P1** *(encolheu em 2026-08-13)* | **Restou UMA decisão de marca e meia.** A **S6** (tinta da família — `text-primary` #0B3330 × branco 13,72, `text-secondary` #2F5A54 × branco 7,75, bordas e superfícies esverdeadas) segue **proposta**, como camada alternável pelo botão "Tinta". A **S11** (âncora `turquesa-400` + régua de ação na família) precisa de **registro** em `marca-seed.md` e nos **gêmeos de token v1.8 → v1.9**, mas **não precisa de decisão** — ela é convergente com o §3.5 vigente, e por isso é a meia. **O S4 saiu da pendência: não há conflito de marca a resolver** | A S6 bloqueia o canônico inteiro (ERP, e-mail, documentos, site) porque muda tinta, bordas e superfícies. A S11 bloqueia só a propagação dos 40 HTML (PN-P7). **Segue sendo o próximo bloco** |
| **PN-P2** | **PN42–PN45** (dependências FS/SS/FF/SF com lag · caminho crítico · linha de base · marco) | **FECHADA em 2026-08-16 pelo §58** (GT1–GT16). Os quatro números seguem reservados e vazios nesta numeração de propósito — renumerar invalidaria âncoras MD5 de cinco artefatos executáveis que já citam PN46–PN54. O conteúdo vive no §58, e a fronteira está declarada lá: o §48 tem a lente temporal (PN47/PN48/PN49), o §58 acrescenta a camada de RELAÇÃO entre itens |
| **PN-P3** | **§49 Painel de detalhe** — modal, gaveta lateral e página cheia, servindo o sistema inteiro. Hoje existe só a versão mínima do **PN50** | Bloco próprio |
| **PN-P4** | **MAPA NACIONAL.** A malha canônica cobre só **MG/ES/BA** (1.348 municípios, IBGE 2025, Albers). Um espelho de terceiro com as 27 UFs foi testado (`raw.githubusercontent`, `giuliano-macedo/geodata-br-states`) e **não declara edição**. Duas saídas: usar com a pendência registrada, ou o Rafael fornece o shapefile oficial. **Falta também a regra de escala** (município → UF → país) | Atendimento fora de MG/ES/BA na lente mapa |
| **PN-P5** | **SH-P1**, aberta desde o 6A: nenhum token de borda semântico passava 3:1 contra `surface-raised` no tema claro. **✅ FECHADA em 2026-08-14 (gêmeos v1.12):** nasce `--seed-border-interactive` (`cinza-500` promovido, ≥3,0 nas seis superfícies dos dois temas); o shell consome desde o preview v0.3. Registro completo no §46.2 e no `seed-tokens.md` v1.12 §3 | — (fechada; resta só o retroativo do artefato do §47, classe PN-P7) |
| **PN-P6** | **Três medidas de composição da camada visual sem guarda automatizada:** massa escura **≤32%** da primeira dobra · hero **≤35%** da altura · página lê branca (luminância média **≥248**). São decisões declaradas e medidas por inspeção, **não** por script — nenhuma das cinco camadas as verifica hoje | Nada; é dívida de instrumento. Candidata natural a uma sexta camada de composição |
| **PN-P7** | **Retroativos nos outros 40 HTML do repositório** (camada visual e régua de ação) | Chat separado, a pedido do Rafael |

### 48.10 Os testes

1. **Nenhum par de cor novo** — o painel compõe peças já medidas; a medição do bloco confere os
   pares **em uso**, e a lição do §46 e do §47 vale: compor pares medidos separadamente **não
   garante** que a combinação passe.
2. **Escada de mecanismos:** lente ativa por `aria-current` + marca visual + peso, nunca só cor;
   variação de KPI por seta (sinal) + cor (juízo), nunca cor sozinha (PN14b).
3. **Grayscale:** lente ativa, estado de frescor e severidade permanecem legíveis (DF4).
4. **Regra do um:** uma lente ativa por bloco · **uma pergunta por bloco** · **UMA live region no
   painel inteiro** (PN9/§1.13) · um itálico por título-insight (PN21e) · **um hero escuro por
   página** (PN21c).
5. **Landmarks e nomes:** todo bloco é `section` nomeada; nenhum nome repetido no painel.
6. **Frescor e norma:** todo bloco que se atualiza declara última leitura e estado; **existe
   controle de frequência com opção manual** (PN8, WCAG 2.2.2 nível A); atualização não move
   foco nem anuncia sem pedido (PN9).
7. **Escopo do cliente:** no modo cliente, **nenhum identificador de terceiro** aparece — nem em
   agregado. Teste documental além de visual, como o de procedência do §47.
8. **Blocos de dado:** nenhum KPI sem período e base de comparação (PN14) · barra de ranking com
   base proporcional declarada e valor numérico à vista (PN15) · **nada semântico dentro do
   `progressbar`** e `aria-valuenow` omitido quando indeterminado (PN18) · toda entrada de
   timeline endereçável (PN20).
9. **Edição direta:** todo gesto de arrasto tem **caminho de ponteiro único** (PN23, SC 2.5.7) ·
   contrato de teclado idêntico em toda lente (PN24) · **nada derivado tem alça** (PN22) · ímã na
   unidade da escala (PN25) · **nenhum `transform` no redimensionamento** (PN35) · desfazer de 8s
   cobrindo criação e exclusão (PN28) · o item mutado é **realçado e trazido à vista** (PN34b).
10. **Contagem honesta:** a contagem acompanha filtro **e** mutação — criar ou excluir muda o
    total exibido no mesmo instante (PN40).
11. **Mapa:** dois modos declarados, cobertura como padrão (PN51) · estilo por token e marcador
    do DS (PN52) · **fallback que diz o que aconteceu** e nenhuma chave no artefato (PN53) ·
    **alternativa textual como conteúdo nos dois modos** (PN54).
12. **Convite e gesto no mesmo lugar:** toda zona que convida a um gesto executa aquele gesto, e
    a promessa da dica é a ação que acontece (PN49) · **dois gestos nunca dividem o mesmo pixel**
    (PN41e) · ação destrutiva não mora em alvo invisível que cruza a área (PN36).

### 48.11 Estado da validação

*(Estado: **`estável`**. **Gate visual do Rafael APROVADO em 2026-08-13 sobre o preview v0.6** — o quarto e último gate do bloco, depois das quatro camadas automatizadas. Com ele o **bloco 6C FECHA** e a Fase 6 vai a 3/3 blocos concluídos (6A §46 Shell · 6B §47 Página institucional · 6C §48 Painel). **A promoção é dos contratos PN1–PN54; as decisões de marca S3, S4 e S6 seguem proposta — ver a ressalva no cabeçalho do §48 e a pendência PN-P1 em §48.9.** Este bloco é o primeiro do projeto validado em **cinco** camadas, e a quinta (`render-contraste.mjs`) nasceu de um defeito que as outras quatro não podiam ver.)*

**Rodada 1 — 2026-08-12, preview v0.1 → v0.2.** `suite-painel.mjs` **67 PASS · 0 FAIL** — *prova
de que as guardas são reais:* contra um preview com 5 defeitos deliberados (lente desabilitada em
vez de oculta, frequência sem opção manual, pílula pintada pelo sinal, `aria-valuemin` ausente,
base proporcional não declarada) ela **reprova em 6**; `render-painel.mjs` **17 PASS · 0 FAIL**;
`contraste-painel.py` **44 PASS · 0 FAIL** após as correções que a própria medição exigiu. **O
gate visual reprovou o v0.1 e produziu o PN3b** — as lentes "linha do tempo" e "calendário"
desenhavam listas. Preview a **v0.2**, suíte a **75**, render a **25**; contra a versão em que as
duas lentes voltam a ser lista, a suíte **reprova em 6**.

**Rodada 2 — 2026-08-13, preview v0.3.** Oito lentes (S1) e camada visual (PN21).
`suite-painel.mjs` v2 **107 PASS · 0 FAIL**; *prova:* contra um preview com **4 defeitos
plantados** — gantt sem dependências, véu a 35%, dois heros, `transition` com duração solta — ela
**reprova exatamente nos 4**. `render-painel.mjs` v2 **37 PASS · 0 FAIL**, medindo em Chrome real
3 conectores de dependência com extensão em pixels, 5 faixas de responsável com **sub-linhas de
sobreposição em tops distintos**, marca de capacidade no mesmo x, excedente com largura real,
contorno do mapa com bbox medido e 5 pontos dentro do viewBox. `contraste-painel.py` v2 **70 PASS
· 0 FAIL**, incluindo os pares do hero escuro (branco × `cinza-900` = 13,86; itálico
`turquesa-300` = 7,57; botão-solução = 5,11).

**Rodada 3 — 2026-08-13, preview v0.5 → v0.6. Cinco camadas, todas verdes, todas re-executadas
contra o artefato final:**

| Camada | Ferramenta | Placar | O que ela mede |
|---|---|---|---|
| `suite-painel.mjs` v4 | Node + jsdom | **133 PASS · 0 FAIL** | Estrutura, ARIA, tokens, classes fantasma, referências fantasma, higiene |
| `render-painel.mjs` v3 | Chrome headless | **37 PASS · 0 FAIL** | Colapso da grade em 3 larguras, geometria das oito lentes, frescor vivo |
| `render-edicao.mjs` v1 | Chrome headless | **142 PASS · 0 FAIL** | Os 33 contratos de edição direta, filtro, escala, mapa e criação — gesto por gesto, com pixels |
| `render-contraste.mjs` v1 | Chrome headless | **6 PASS · 0 FAIL** | Contraste de **composição** renderizada nos dois temas (368 textos medidos), não de par de token |
| `contraste-painel.py` v2 | Python | **70 PASS · 0 FAIL** | Pares declarados, calculados fora do navegador |

**Camada nova desta rodada, e a razão dela:** o `render-contraste.mjs` nasceu de uma lição
medida — **contraste de TOKEN não substitui contraste de COMPOSIÇÃO**. Os pares do
`contraste-painel.py` estavam todos verdes enquanto, no tema escuro, a ação primária em
`azul-800` media **1,48** de superfície contra o cartão (sumia) e a secundária tinha **texto**
`azul-800` sobre cartão escuro (1,48 — ilegível). Nenhum par de token estava errado; a
**combinação** estava. A camada varre todo texto sobre superfície opaca nos dois temas e reporta o
pior caso: hoje **5,56** em `button`.

**Rodada 4 — 2026-08-13 (noite), preview v0.6 → v0.7 → v0.8. A inversão do hero.** Cinco
camadas re-executadas contra o v0.8 final: `suite-painel.mjs` **139 PASS · 0 FAIL** (era 133;
entram `NV-01`, `PN21-05c/05d/05e/05f/05g`) · `render-painel.mjs` **37 · 0** ·
`render-edicao.mjs` **142 · 0** · `render-contraste.mjs` **6 · 0** · `contraste-painel.py`
**78 · 0** (era 70; entram `PC-H5b`, `PC-H6`…`PC-H11`). **Nenhum artefato canônico foi
tocado** — cinco arquivos de preview e validação, e nenhum dos 40 HTML do repositório.

> **DEFEITO REAL DA RODADA, e quem o pegou foi a quinta camada: TOKEN FANTASMA.** Na primeira
> execução após a inversão, o `render-contraste.mjs` reprovou **15 textos com razão
> 1,0–1,26**, incluindo **branco sobre branco**. Causa: o molde passou a consumir
> `turquesa-400/600/700` e a lista `PRIMITIVOS` do `gen-painel.py` **ainda era a da era do
> azul** — e **variável CSS indefinida é valor inválido, então o fundo simplesmente não
> pintou**. É a classe **NV-01** do §47 (nascida quando a command palette abriu
> transparente), que tinha detector na suíte de navegação e **faltava nesta**. Corrigido na
> causa e **detector criado aqui**: `NV-01` — todo `var(--seed-*)` consumido tem definição no
> bloco de tokens. Pega na suíte jsdom, antes de qualquer render. *Lição de método: guarda
> genérica criada num bloco não se propaga sozinha para os outros — quando uma classe de
> defeito ganha detector, o detector precisa ser levado para toda suíte que possa sofrer dela.*

**Errata E-6C-01 (2026-08-13, achado na conferência de ambiente): título e selo declaravam
versões diferentes.** O `<title>` do preview dizia *"preview v0.3"* e o selo na tela dizia
*"preview v0.5"* — duas declarações de versão no mesmo arquivo, discordando. A guarda `HIG-03`
passava verde porque media apenas **presença** de versão no título. **O defeito importa porque o
título da aba é o primeiro sinal de arquivo fresco** — três relatos de *"não funciona"* nesta
sessão foram cache, e um título que mente cega justamente o instrumento usado para detectar cache.
*Correção estrutural, não sintomática:* a versão passa a ter **fonte única** (constante
`VERSAO_PREVIEW` no `gen-painel.py`), consumida por dois marcadores do molde
(`@@VERSAO_TITULO@@` no título, `@@VERSAO@@` no selo, este com data e hora) — divergir deixa de
ser possível por construção. Preview bumpado a **v0.6** porque o artefato corrigido tem de ser
distinguível do defeituoso **na tela**. *Guarda de regressão permanente, creditada ao Rafael:*
**`HIG-06` — título e selo declaram a MESMA versão**; contra um artefato com a versão do título
plantada de volta em v0.3, a suíte **reprova em exatamente 1**, e a mensagem nomeia os dois
valores.

**Nota de determinismo, para quem for reconferir hashes:** o selo carimba **data e hora de
geração**, então regenerar o preview produz um MD5 diferente **sem nenhuma mudança de
comportamento** — conferido: a cadeia
`malha-projetada.json → gen-mapa-lente.py → mapa-lente.json → gen-painel.py + painel-template.html + seed-tokens.css → seed-painel-preview.html`
reproduz **209.288 bytes e 3.730 linhas idênticas, com um único diff: a linha do selo**. Para o
preview, **a âncora é o arquivo entregue, não a receita**.

> **Registro de defeitos e lições — rodada 2 (2026-08-13). Todos viraram guarda ou nota de método.**
> **(1) RDP em anel fechado come o fecho.** A simplificação Ramer–Douglas–Peucker do contorno
> externo do mapa, aplicada ao anel inteiro, ancorava o primeiro e o último vértice **no mesmo
> ponto** e degenerava o fecho. Conserto no `gen-mapa-lente.py` v2.2: dividir o anel em duas
> metades, simplificar cada uma e recosturar. *Classe:* algoritmo de polilinha aplicado a
> polígono sem tratar a topologia.
> **(2) Token fantasma evitado antes do build.** O hero usou `--seed-tq-300`, que **não existe**
> — o primitivo é `--seed-turquesa-300`. Pego por conferência de nome contra o CSS canônico antes
> da geração (classe NV-01 do §47: nome de token digitado de memória).
> **(3) Instrumento calibrado no dado quebra com o dado.** O `R4-02` do render v1 exigia a menor
> barra do ranking entre 30% e 50% — faixa que descrevia os dados ilustrativos antigos, não a
> propriedade. Com dados novos (58/486 = 11,9%) reprovou sem haver defeito. Recalibrado para a
> propriedade: largura renderizada ≈ razão do próprio dado. *Mesma família da lição do 6A
> (instrumento errado invalida a medição), variante temporal.*
> **(4) Dado de exercício precisa conter o caso que a guarda mede.** O `R7-03` (sub-linhas de
> sobreposição) reprovava porque **nenhuma pessoa tinha duas OS sobrepostas** — o mecanismo
> existia e a suíte estrutural passava, mas a geometria não tinha o que mostrar. A OS-2301 foi
> movida para colidir com a OS-2296 do mesmo responsável. *Regra: todo comportamento especificado
> precisa de pelo menos um exemplar no dado ilustrativo.*
> **(5) `--single-process` do pacote `@sparticuz/chromium` trava element-screenshot.** Os args
> padrão do pacote (feitos para Lambda) deadlockam o Chrome em `element.screenshot()` sequencial.
> Args enxutos (`--no-sandbox`) resolvem. Nota de ambiente para qualquer captura futura.

> **Duas correções que a medição impôs, e as duas são reaproveitáveis fora deste bloco.**
> **(1) A regra do dourado vale fora do dataviz.** O ponto de "dado antigo" do frescor usava
> `feedback-warning-solid` (`#F9B11C`) e media **1,85** contra o cartão no tema claro. A **regra
> do dourado** da §3c veta o dourado como *fill solitário* — e um ponto de 8px é exatamente isso.
> Passou a consumir `feedback-warning-text`: **9,84** no claro, **10,09** no escuro. A regra
> nasceu no dataviz e se aplica a **qualquer** preenchimento pequeno e isolado.
> **(2) Barra fina de dado consome a variante `-stroke`.** O preenchimento cheio `chart-cat-1`
> media **2,97** contra o trilho no claro — reprovava 3:1 por 0,03. A variante `chart-cat-1-stroke`
> existe exatamente para *"linha fina e marcador pequeno, o pior caso do 1.4.11"* e mede **4,23**.
> Vale para a barra do ranking (PN15) e para a de progresso (PN17).
>
> **A correção do PN3b expôs um segundo defeito, de raiz diferente.** Ao desenhar o calendário
> de verdade, os eventos caíram **um dia antes** e a grade saiu com sete larguras diferentes.
> Causa: `new Date("2026-08-12")` interpreta a string como **UTC** e desloca no fuso do
> navegador. A primeira tentativa de conserto foi **somar um dia** — remendo sobre o sintoma, que
> teria quebrado em qualquer fuso diferente. O conserto real é **decompor a data em números** e
> fazer a aritmética em UTC puro; e as colunas exigem `minmax(0, 1fr)`, senão o conteúdo do dia
> empurra a coluna. *Classe de defeito:* **remendo sobre sintoma em vez de causa** — sobrevive ao
> teste na máquina de quem escreveu e falha na de quem usa.
>
> **E um defeito de alvo de toque que só o render pegou:** o link de cada evento da timeline —
> justamente o que torna a entrada **endereçável** (PN20) — media **14px** de altura. Alvo de
> toque ≥44px vale para ele como para qualquer controle.

> **LIÇÕES MEDIDAS NA RODADA 3 (2026-08-13). Catorze, e nenhuma é sobre o componente — todas são
> sobre COMO se descobre que algo está errado.** Registradas aqui porque valem para qualquer
> bloco futuro.
> **(1) Instrumento calibrado no dado quebra com o dado** — faixa fixa em vez de propriedade
> (reincidência da lição 3 da rodada 2; virou regra).
> **(2) Feições que se tocam, simplificadas em separado, deixam de se tocar.** No mapa, a
> simplificação independente de cada fronteira abria vão entre municípios vizinhos. Conserto:
> RDP com **nós de junção preservados**; vão medido **4,9px → 0,000px**.
> **(3) Filtro pela grandeza errada.** Contar vértices **não mede extensão**: a divisa BA–ES tem
> **6 arestas** e desaparecia num filtro de complexidade.
> **(4) Classe CSS derivada de rótulo humano quebra em silêncio.** `"Em campo"` virava
> `.st-Emcampo`, que nunca existiu no CSS. **Detector permanente criado** (`PN21-04d`/`PN21-04e`):
> toda chave de estado emitida pelo script tem regra CSS correspondente, e a classe **não** é
> derivada do rótulo.
> **(5) Referência órfã mata o script inteiro.** `getElementById` para id inexistente derruba
> tudo abaixo dele, e a tela fica parada sem erro visível. Detectores **`REF-01`/`REF-02`**: todo
> `getElementById` e todo `querySelector` de id fixo no script têm alvo existente no documento.
> **(6) Camada de sobrescrita de token sem variante de tema é meia implementação.** A camada de
> tinta (S6) nasceu só com a face clara; no escuro o painel inteiro ficou ilegível.
> **(7) Contraste de TOKEN não substitui contraste de COMPOSIÇÃO** — o `render-contraste.mjs`
> nasceu disso.
> **(8) O que nasce fora do campo de visão é lido como "não funcionou"** → PN34b (realce +
> rolagem até o item mutado).
> **(9) Convite que aparece onde o gesto não age é pior que convite nenhum** → PN49.
> **(10) Ação destrutiva não pode morar em alvo invisível que cruza a área** → PN36 (o fio de
> dependência apagava por acidente ao clique simples).
> **(11) Dois gestos não podem dividir o mesmo pixel** — nó de dependência × punho; criar ×
> panorâmica → **modo explícito** (PN41e).
> **(12) `viewBox` e área têm de medir o mesmo**, senão a camada esticada desalinha tudo (o fim
> do conector não coincidia com a barra dependente; guarda `I-20`).
> **(13) Todo comportamento especificado precisa de um exemplar no dado ilustrativo** (a lição 4
> da rodada 2, confirmada duas vezes: sub-linhas de sobreposição e ordem com duas predecessoras).
> **(14) Defeitos do INSTRUMENTO têm o mesmo peso que defeitos do artefato.** Quatro medidos:
> coordenada de viewport em vez de rect da área · medir **durante** transição CSS · escolher ponto
> de clique sem verificar o que está sob ele · medir no sentido em que o navegador **já está no
> fim do curso**. Uma suíte errada reprova artefato bom e aprova artefato ruim — a auditoria do
> instrumento é parte da validação, não etapa opcional.

> **Nota de método da rodada 3, registrada por ordem do Rafael:** duas vezes nesta sessão um lote
> de edições imprimiu "OK" **sem que o arquivo tivesse sido salvo** — o `write` fica no fim do
> script e o abort intermediário deixava tudo no meio. **Regra permanente: se um lote de edições
> abortar, RE-EXECUTAR O LOTE INTEIRO; "OK" impresso não significa arquivo salvo, e só a leitura
> de volta por MD5 significa.**
---

> **PROMOÇÃO A `estável` — 2026-08-16.** As seções §49 a §55 foram promovidas em bloco pelo Rafael
> ("aprovo") após o gate visual sobre as seis telas do projeto. **O gate encontrou dois defeitos
> reais que as cinco camadas automatizadas atravessaram**, e os dois viraram guarda permanente
> antes da promoção: (a) no regime MODAL a lista de fundo acompanhava a navegação entre irmãos —
> verbatim, *"está mexendo as duas janelas… era pra mexer só a que abriu sobreposta"* —, o que
> gerou o **PD19**; (b) a topbar não degradava por CONTÊINER, só por viewport, e no estreitamento
> o rótulo da marca quebrava em duas linhas e a busca empurrava o avatar. Guardas novas: `SNC-01`
> a `SNC-03`, `TOP-01` a `TOP-04`. **Nenhuma seção é promovida sem que o defeito que o gate achou
> tenha virado teste** — é a regra que o projeto pratica desde a Fase 6.

