Ir ao conteúdo
SEED engenhariaDesign System

Componentes

64. Bancada e tema — regras transversais

seed-componentes.md v1.43 · §64seção 70 de 9864-bancada-e-tema-regras-transversais-bt1-bt6-f7-5.md · MD5 1ce4e024

Título completo no canon: Bancada e tema — regras transversais · BT1–BT6 (F7.5, 2026-08-16) · nascidas do gate de 2026-08-16 · valem para TODA bancada e TODA tela

O que esta seção é. As seções anteriores especificam componentes. Esta especifica o suporte onde os componentes são avaliados (a bancada) e a inversão de tema (claro ↔ escuro), que é transversal a todos eles. Ela nasceu de um gate visual em 2026-08-16 no qual o Rafael apontou quatro coisas em quatro capturas de tela — duas de ergonomia da bancada e duas de tema escuro. As quatro viraram contrato, porque defeito que o olho pega e que não vira guarda volta.

Vocabulário, para quem chega sem contexto. Bancada (banco-*.html) = catálogo dos ESTADOS de um componente, feito para avaliar; tela (tela-*.html) = caso de uso montado (lei CP31 do seed-composicao.md). Token primitivo = um degrau da rampa de cor, ex. --seed-turquesa-100; ele é um valor fixo e não muda quando o tema inverte. Token semântico = um papel, ex. --seed-action-primary ou --seed-surface-raised; ele é redefinido no tema escuro. A regra GI2 do projeto ("componente consome SEMÂNTICO, não primitivo") já existia — o que faltava era alguém medir se ela estava sendo cumprida.


64.1 Os contratos#

# Contrato Por quê
BT1 A barra de controles de todo artefato produzido — bancada OU tela — é fixa no topo: position:sticky; top:0, com faixa de fundo própria e sombra de separação Verbatim do gate: "deixe sempre o topo ... sempre travado no topo pra quando rolar a página ele ficar fixo no topo". Bancada é comprida por definição — ela imprime todos os estados. Se o seletor de tema rola para fora, avaliar o tema escuro no meio da página exige subir, trocar, descer e reencontrar o lugar
BT2 Toda bancada oferece seletor de largura de páginaTotal · 1280 · 1024 · 768 · 390px — limitando o max-width do contêiner de conteúdo Avaliar aperto sem redimensionar a janela. Sem isto, "cabe em 390?" vira uma pergunta que só o autor da suíte consegue responder, e o gate humano fica dependente do placar
BT3 O par de estado tem de sobreviver à inversão. Fundo e texto de um mesmo estado medem ≥ 3,00 de contraste nos DOIS temas É a formulação MEDÍVEL do GI2. O defeito real nunca é "usou primitiva": é primitiva de um lado e semântico do outro — o par se separa quando um dos dois inverte e o outro não
BT4 Primitiva de rampa em superfície de marca (herói, trilho, selo) é tolerada — desde que fundo E texto sejam do mesmo par fixo, e o número seja impresso no placar Superfície de marca é justamente aquilo que não deve inverter. Proibir a primitiva ali seria proibir a marca. Mas tolerar em silêncio faz o achado sumir: o placar imprime primitiva só em superfície de marca com o pior par medido
BT5 Atributo de CONTRATO não se traduzdata-theme="dark", não data-tema="escuro" Regra já escrita em §63.7, repetida aqui porque é da mesma fronteira. O idioma do projeto é pt-BR; o gancho do gêmeo de tokens não é escolha nossa
BT6 Medição de tema roda em página recém-carregada, e a suíte declara isso Número que depende de quais guardas rodaram antes não é medição, é resíduo (a prova está em §64.4)
BT7 Nenhuma bancada rola na horizontal a 320px. O que pode rolar é a parte que exige layout bidimensional — tabela de dados, grade de glifos —, e só dentro de uma região focável e rotulada (role="region" + tabindex="0" + aria-label) SC 1.4.10 Reflow (AA). A norma proíbe a página rolar nas duas direções e abre exceção nomeada para "partes do conteúdo que exigem layout bidimensional". Mas região rolável sem foco de teclado não se rola sem mouse, e sem nome a AT anuncia uma região anônima. Nasceu no rito de promoção de 2026-08-17: as quatro bancadas novas transbordavam a 320px, e três delas também a 390 ou 768 — ninguém tinha medido abaixo de 1200

SUPERSEDE FORMAL — o estado de VERIFICAÇÃO do BT1 e do BT2 (acrescentado em 2026-08-20, décima parte)#

Esta subseção define os contratos; ela não os declara verificados. O estado de verificação de cada um, em 2026-08-20, é:

· BT1 — VERIFICADO POR INSTRUMENTO. validacao/guarda-barra-fixa.mjs, de alvo de pasta, mede as quatro cláusulas BT1-a…d em todo .html do diretório: 33 PASS · 0 FAIL · 18 [n/a] a 1440×900 e a 320×900. A especificação completa, o censo dos onze reprovados com número, o conserto canônico e a pasta de prova render-audit/prova-bt1 estão em §74 — que SUPERSEDE qualquer afirmação anterior de que a pendência BT-P2 estivesse fechada. A BT-P2 havia sido declarada fechada em 2026-08-17 sobre uma lista escrita à mão de dez artefatos, num acervo de trinta e quatro; onze reprovavam.

· BT2 — NÃO VERIFICADO. Nenhum instrumento mede se a bancada oferece seletor de largura de página. A guarda-barra-fixa.mjs declara explicitamente não julgar a composição da barra. Fica como pendência BT-P3 (§74.9). Este parágrafo existe para que "BT2 está escrito" nunca volte a ser lido como "BT2 está cumprido" — que é exatamente o erro que a BT-P2 cometeu.


64.2 Os dois defeitos de tema escuro que o gate achou — com número#

Ambos tinham a mesma raiz e nenhum dos dois foi pego por guarda: as suítes rodavam no tema claro.

① O vão do intervalo no calendário ficava BRANCO (banco-data.html). Verbatim: "veja o anexo do calendário, o período de data fica branco". O preenchimento entre a data inicial e a final usava --seed-turquesa-100 — primitiva, #CDF3EC idêntico nos dois temas. No tema escuro o número do dia (texto semântico, que inverteu) sobre essa faixa mediu 1,02. A faixa aparecia como uma cicatriz clara atravessando um calendário escuro.

Conserto: o vão passa a ser derivado de semântico, e por isso inverte junto — color-mix(in srgb, var(--seed-action-primary) 20%, var(--seed-surface-raised)). Medido depois: #cee6e3 → 10,52 no claro e #2c494b → 7,98 no escuro.

② A contagem no segmento selecionado SUMIA (banco-escolha.html). Verbatim: "no outro exemplo, a quantidade de item no menu não aparece". O número usava --seed-turquesa-900 como cor de texto sobre o fundo de ação do segmento selecionado. No escuro o fundo de ação virou justamente aquele tom: #00352F sobre #00352F = 1,00. Não era "pouco contraste": era o mesmo valor exato dos dois lados.

Primeira tentativa, DESCARTADA por medição: véu de text-on-brand a 22% atrás do número. Mediu ~3,0 — ou seja, pior que véu nenhum no tema claro, onde antes havia 4,6. Trocar um problema de escuro por um problema de claro não é conserto. Conserto em vigor: pílula vazadabackground:transparent, border:1px solid currentColor, color:currentColor. Ela herda a cor do texto do segmento, então o par nunca se separa, em nenhum tema. Medido depois: 4,60 no claro e 7,39 no escuro.

A lição comum aos dois: o defeito não é usar primitiva, é parear primitiva com semântico. Um lado inverte, o outro não, e o par se rompe. Onde os dois lados são do mesmo par fixo (superfície de marca), nada se rompe — daí o BT4 tolerar em vez de proibir.


64.3 A guarda GI2, e as três formas erradas antes da certa#

A guarda que nasceu deste achado teve de ser reescrita três vezes na mesma rodada. Fica registrado inteiro porque cada erro é de uma família que já custou caro antes.

Forma 1 — texto, com recorte por posição. A guarda procurava var(--seed-<rampa>-<n>) no CSS e recortava o "corpo do componente" com split('=====').pop() — supondo que o bloco de tokens vinha primeiro e que a última fatia entre réguas de comentário era o componente. Medido: essa fatia é 4.393 de 30.016 bytes em tela-lista.html (15%) e 15.283 de 84.617 em tela-painel.html (18%). A guarda olhava um sétimo do arquivo e declarava "só semânticos" sobre os outros seis — inclusive sobre .rail-item.ativo, que consome --seed-turquesa-100/900. Mesma família do 8º defeito de instrumento: guarda escrita para não olhar onde o defeito mora é pior que guarda nenhuma. Correção: o recorte não é por posição no arquivo, é por seletor — primitiva é legítima onde o token é DEFINIDO (:root, html[data-theme=…], [data-theme=…]) e é consumo em qualquer outro lugar.

Forma 2 — texto, agora enxergando o arquivo inteiro. Reprovou tela-painel.html, que é estável e aprovada pelo olho. Medido por pixel: as seis primitivas do painel pintam o herói, o botão de solução e o selo de versão — superfícies de marca, par fixo dos dois lados, pior par 4,60. Não havia defeito. Uma guarda que condena artefato correto força conserto errado — é tão cara quanto a que não vê o defeito. Correção: a pergunta certa não é "existe primitiva?", é "o par sobrevive à inversão?" — e essa pergunta só se responde MEDINDO nos dois temas (BT3).

Forma 3 — medição, mas com o fundo lido errado. O compositor de fundo subia pelos ancestrais lendo backgroundColor — e é cego a background-image. O trilho lateral das telas é um gradiente; o compositor pulava-o e devolvia o fundo da página. Resultado: texto branco lido como se estivesse sobre #f2f6f9, 1,09 — um defeito gravíssimo que não existe. O trilho é pintado de #005e55, e o número real é 7,55. Correção: o fundo passa a ser lido do PIXEL efetivamente pintado — captura do elemento e cor modal do histograma.

Forma 4, em vigor. Recorte por seletor + medição por pixel nos dois temas + piso 3,00 + o número impresso mesmo quando passa. Placar depois da correção: banco-escolha 238 · 0 · 29, banco-data 31 · 0 · 1, banco-prioridade 18 · 0 · 0.


64.4 Por que a medição roda em página LIMPA (BT6)#

Na forma 3 da guarda, tela-detalhe.html mediu 2,08 no escuro; medida em isolamento, a mesma regra no mesmo arquivo mediu 11,37. A diferença não era do artefato: no topo do laço a suíte clica .linha-abrir para revelar o registro (sem isso o §56 sai como ausente), e a cortina do registro aberto escurece o trilho por baixo.

Nenhum dos dois números é "errado" — eles medem estados diferentes. O erro é a guarda não dizer qual estado ela mede. Por isso a medição de tema abre carga nova, no estado neutro do artefato, e isso está escrito no código junto da medida.


64.5 Veredito sobre as quatro telas estável — achado NEGATIVO, declarado#

A guarda de classe apontou primitiva de rampa em quatro artefatos já estável. Medido por pixel, nos dois temas:

Arquivo Seletor Claro Escuro Veredito
tela-painel.html .hero, .hero-sub, .hero .micro, .hero .data-viva, .hero-nota 4,99 (5,90 no micro) 4,99 superfície de marca — par fixo
tela-painel.html .btn-solucao 9,37 9,37 superfície de marca — par fixo
tela-painel.html .selo-versao 4,60 (pior par do arquivo) 4,60 superfície de marca — par fixo
tela-lista.html · tela-tabela.html · tela-detalhe.html .rail-item.ativo 11,37 11,37 trilho de marca — par fixo

Nenhum defeito. Em todos, fundo e texto são primitivas do mesmo par, e o par não se rompe porque nenhum dos dois lados inverte. As quatro telas seguem estável sem conserto e sem novo gate — e o registro fica aqui para que a próxima leitura da guarda não reabra a mesma pergunta.

Fato × inferência, declarado: os números da tabela são FATO (medidos por pixel, Chromium 1194, viewport 1440×900, data-theme alternado no <html>). A afirmação "superfície de marca não deve inverter" é DECISÃO de projeto, não medição — ela vem do marca-seed.md, e é ela que torna o achado tolerável em vez de defeito.


64.7 O BT7 nasce no rito de promoção — e o que ele diz sobre o seletor de largura#

O BT2 deu à bancada um seletor de largura de página (Total · 1280 · 1024 · 768 · 390). Ele limita o max-width do conteúdo, não o viewport — e é isso que ele deve fazer, porque o que responde é o contêiner (CP27).

Mas ninguém tinha medido o viewport estreito de verdade. No rito de promoção de 2026-08-17, com o navegador aberto em 390 e 320px, as quatro bancadas novas rolaram na horizontal:

Artefato 390px 320px Causa
banco-identidade 37px 107px table.dados do contraexemplo + grade de repeat(7, 44px) = 348px num contêiner de 288
banco-credencial 0 39px seis caixas de 44px + 5 calhas = 304px, e a tabela de contratos
banco-edicao-linha 0 32px grid-template-columns: 180px 1fr — o 1fr não encolhe abaixo do min-content do gatilho
banco-texto-rico 0 36px minmax(340px, 1fr) numa coluna de 288px

As três causas, e o conserto de cada uma:

  1. minmax(Xpx, 1fr) força X mesmo sem X disponível. Conserto: minmax(min(Xpx, 100%), 1fr).
  2. 1fr não encolhe abaixo do conteúdo mínimo. Conserto: minmax(0, 1fr) na coluna e min-width: 0 no filho que trunca.
  3. Grade de largura fixa não reflui. Conserto: repeat(auto-fit, 44px) com teto igual à largura das sete colunas — desenha sete enquanto couber, quebra para menos quando não couber.

E o conserto 3 obrigou a corrigir um contrato: o SI5 dizia que ↓ desce "± o número de colunas", lendo o data-colunas fixo. Com a grade refluindo, esse número passa a mentir — e ele já mentia antes, sempre que o filtro deixava menos de sete ícones visíveis. As colunas passam a ser MEDIDAS pelo offsetTop dos itens visíveis, e o nome acessível do grupo passa a dizer o número real: "2 de 28 glifos do set canônico, 2 por linha". Guarda nova SI-OP3b.

Regra: número de layout que vive em atributo é cópia — e cópia de layout desatualiza no primeiro reflow.

Décimo oitavo defeito de instrumento, na mesma rodada. O script de auditoria de sobreposição varria .cx, .amostra-cx, .cx-amostra — e .cx é cartão na banco-texto-rico e caixinha de dígito na banco-credencial. Pior: ele comparava pai com filho e chamava conter de sobrepor. Resultado: seis achados que não existiam, em todas as larguras. Corrigido: o conjunto é só o cartão, e par em linha de ancestralidade é descartado. Placar final do render de promoção: 40 combinações (4 artefatos × 5 larguras × 2 temas) · 0 achados.

Regra: nome curto de classe é ambíguo entre artefatos — guarda transversal seleciona por ESTRUTURA, não por nome curto. É o mesmo defeito de escopo do 8º, 14º e 17º, agora entrando pelo seletor.

64.8 A varredura FECHA — e o que ela ensinou sobre guarda transversal (2026-08-17, v0.99)#

A validacao/suite-reflow.mjs é a primeira guarda do projeto cujo alvo é a pasta, e não um artefato. Ela saiu de 82 PASS · 10 FAIL · 40 [n/a] em 33 artefatos (v0.98) para 120 PASS · 0 FAIL · 34 [n/a] em 34 artefatos. O relato completo — com a medida e a alternativa descartada de cada conserto — está no validacao/MANIFESTO.md §79. Aqui ficam só as regras que passam a valer para o sistema inteiro.

O contrato BT7 se parte em TRÊS medidas, porque elas falham por motivos diferentes e se consertam de jeitos diferentes:

Guarda Pergunta Critério
BT7-<largura> a página rola na horizontal a 320 e a 390px? SC 1.4.10 Reflow (AA)
BT7-teclado existe caminho de teclado até cada faixa que rola? SC 2.1.1 Teclado
BT7-nome a faixa que exige nome — papel region/group/tablist, ou parada de teclado que só existe para rolar — tem nome acessível? SC 4.1.2 / 1.3.1

Como cada uma mede, e por que a forma anterior estava errada (19º e 20º defeitos de instrumento):

  1. Região rolável se detecta por COMPORTAMENTO, não por classe. A primeira forma procurava .rolavel; o #quadro do Kanban é região rolável, focável e nomeada desde o QD8 e não tem essa classe — saía como [n/a] justamente no artefato que mais exercia o contrato. Agora o critério é overflow-x em auto/scroll e scrollWidth > clientWidth.
  2. Nome acessível se CALCULA, na ordem da especificação accname: aria-labelledbyaria-labeltitle<caption>. Três artefatos (tela-lista com rot-lista, tela-tabela com rot-tab, banco-dados com tbl-title) nomeiam a região por aria-labelledby e eram acusados de anônimos. Falso negativo puro — um leitor de tela anuncia os três corretamente.
  3. Alcance de teclado tem DUAS formas legítimas. Ou a caixa é ela mesma parada de teclado (tabindex >= 0), ou ela contém algo focável — o navegador rola a caixa ao mover o foco para dentro. Exigir a receita role="region" + tabindex="0" reprovava o role="tablist" do banco-navegacao, que é operável por roving tabindex.

Regra que vale daqui para a frente: guarda que pergunta "tem este atributo?" está medindo uma IMPLEMENTAÇÃO, não um CONTRATO. Foi o mesmo erro do 18º defeito (seletor por nome curto de classe), do 19º (região por classe) e do 20º (nome e foco por receita) — três vezes no mesmo dia. Medir comportamento custa mais linhas e é a única forma de a guarda sobreviver a uma reescrita legítima do artefato.

Prova de que as duas guardas novas sabem reprovar (regra do projeto: guarda que nunca reprovou não é guarda). Injeção controlada, revertida em seguida: removido o aria-labelledby de tela-listaBT7-nome FAIL (4·1); removido o tabindex="0" de um <pre> de banco-dataviz-diBT7-teclado FAIL (3·1).

Três armadilhas de CSS que o BT7 expôs, e que valem para qualquer artefato novo:

  • 1fr é minmax(auto, 1fr), e esse auto é o piso min-content. Coluna que precisa encolher abaixo do conteúdo pede minmax(0, 1fr) — enquanto o piso estiver lá, nenhum ajuste de recuo resolve. (Medido no banco-tokens: célula da rampa com piso de 60,81px — 44,81 de texto do hex mais 16 de recuo — cinco delas pedindo 304px num contêiner de 272.)
  • Texto visualmente oculto (.vh) em position:absolute sem ancestral posicionado ancora no body; dentro de uma faixa que rola, ele toma a coordenada rolada e estende o scrollWidth do documento. (Medido: right=479 num viewport de 390, right=385 num de 320 — exatamente os 89px e 65px de excesso das duas telas.) O padrão do sistema passa a ser position:fixed, que não contribui para o scrollWidth em hipótese nenhuma e não muda nada do que a tecnologia assistiva lê.
  • Faixa que não cabe se resolve com flex-wrap, nunca com overflow-x. Trocar um defeito de SC 1.4.10 por um de SC 2.1.1 não é conserto. overflow-x só entra quando o conteúdo exige duas dimensões — e aí vem acompanhado de foco e de nome, que é o que o BT7-teclado e o BT7-nome cobram.

E duas regras de instrumento, vindas de suítes que ninguém rodava:

  • Suíte que MORRE é pior que suíte que reprova. A render-painel.mjs procurava a lente ativa do painel por aria-current="page" depois de as lentes terem virado role="radiogroup" + aria-checked (supersede SG1/SG4 do §48). O querySelector devolvia null, o processo estourava, e tudo que vinha depois deixava de ser medido em silêncio — os blocos R5b (geometria das lentes), R6 (relógio de frescor) e R7 (faixas, carga, mapa) rodaram pela primeira vez depois do conserto, placar 37·0. Contrato superado tem de ser caçado em TODOS os instrumentos, não só naquele que acusou a mudança.
  • Teto de largura obtido por ACASO de layout volta a esticar. A suite-escala-figura, rodada pela primeira vez nesta edição, reprovou o FIG-03 do SVG .gt-conectoras do gantt: ele passava FIG-01 (não amplia) e FIG-02 (não espreme) e não tinha regra de teto — dependia do atributo width em px e do pai com width em px. No dia em que alguém trocar a largura do pai por %, o desenho volta a esticar e as duas guardas que passam continuariam passando. Conserto: max-width:100%, que não muda um pixel hoje (medido: 1284px nas três larguras) e muda o que acontece depois.

64.9 O EM-BT7 nasce, e a BANCADA também é artefato (2026-08-17, v1.00)#

Esta subseção registra três coisas que passam a valer para o sistema inteiro. O relato completo, com a medida e a alternativa descartada de cada uma, está no validacao/MANIFESTO.md §80.


64.9.1 EM-BT7 — o contrato irmão do BT7 para a família de e-mail#

A pendência E-P1 tinha veredito pendente e agora tem veredito: o BT7 vale para e-mail em PARTE — a régua de largura TRANSFERE, o conserto NÃO TRANSFERE.

(Para quem lê sem contexto: E-P1 era a pendência que perguntava se o contrato de reflow BT7 — §64.7, "nenhum artefato rola na horizontal a 320 nem a 390 CSS px", critério SC 1.4.10 da WCAG 2.2 nível AA — se aplica aos 8 artefatos de e-mail do acervo: et-* (transacionais), en-* (newsletter/comercial), ea-* (assinatura) e seed-email-* (base e componentes). A suite-reflow.mjs varre só banco-* e tela-*; os de e-mail nunca tinham sido medidos. Ausência de medição, não aprovação.)

Guarda Pergunta Critério Existe no BT7? Existe no EM-BT7?
EM-BT7-390 / EM-BT7-320 a página rola na horizontal? SC 1.4.10 via EN 301 549 §10.1.4.10 sim sim — mesmos números
BT7-teclado há caminho de teclado até a faixa que rola? SC 2.1.1 sim não — ver abaixo
BT7-nome a faixa que exige nome tem nome acessível? SC 4.1.2 / 1.3.1 sim não — ver abaixo
EM-BT7-outlook [n/a] impresso em toda rodada

Por que a régua transfere. O WCAG2ICT é a ponte oficial do WCAG para fora do navegador: ele aplica a SC 1.4.10 a documentos não-web trocando "viewport" por "a área de exibição efetiva do conteúdo dentro de uma aplicação ou dispositivo" e mantendo os 320 CSS px. A EN 301 549, cláusula 10 (documentos não-web), traz em 10.1.4.10 o mesmo texto, com a exceção nomeada que inclui tabelas de dados. E a técnica canônica de mercado — a fluid hybrid, width:100% + max-width:600px mais ghost tables em condicional mso para o Outlook do Windows — existe justamente para permitir o reflow: os 600px do e-mail são um teto, não um piso.

Por que o conserto NÃO transfere. Os três consertos de CSS da v0.99 — minmax(0,1fr), flex-wrap e .vh em position:fixed — pressupõem grid, flexbox e posicionamento, que o e-mail não tem. E o remédio do BT7 para a exceção (overflow-x:auto + role="region" + tabindex="0") é pior que o defeito aqui: o Outlook do Windows roda o motor do Word, que ignora overflow, e vários clientes removem tabindex e papel ARIA. Trocaria um defeito medido por um não mensurável.

O remédio do EM-BT7 é geometria dentro da @media (max-width:620px) que a casca canônica já tem — recuo e corpo menores na tabela de dados. Medido: levou os três artefatos com tabela de 30px/100px e 23px/93px de excesso a 0px/0px nas duas larguras.

Exceção a piso declarada com a GEOMETRIA que a obriga: três colunas de valor atômico (número+unidade, moeda) mais 14px de recuo de cada lado em cada célula = 84px só de recuo, dentro de uma faixa de 320 − 40 = 280px. Por isso o corpo cai a 12px e o recuo a 6px — só abaixo de 620px, só dentro de [data-tabela-dados]. Acima de 620 nada muda, e o Outlook ignora @media.

TEMPLATE × AMOSTRA — regra nova de medição. Molde com sentinela {{nome}} não se mede como e-mail: {{desvio_pct}}% é um token de 14 caracteres que não quebra e que não existe no e-mail entregue. Medido no et-alerta-geracao: 55px de excesso a 320 com sentinelas, 0px com elas substituídas. Havendo par -amostra, é ele que dá o veredito e o molde sai [n/a] com o número impresso; não havendo, a suíte substitui e declara a substituição.

FRONTEIRA DE AGENTE, declarada e impressa em toda rodada: a guarda mede em Chromium. Ela não mede o Outlook para Windows, onde a largura é a da ghost table de 600px e o reflow não acontece. É o caso da ressalva expressa do WCAG2ICT — "se um tipo de documento não-web e seus agentes de usuário disponíveis não suportam reflow, pode não ser possível a um documento desse tipo satisfazer este critério". Limite do AGENTE, não defeito do artefato. Isso é gate visual humano.

Guarda: validacao/suite-email-reflow.mjs16 PASS · 0 FAIL · 26 [n/a] em 14 artefatos × 2 larguras. Reexecutadas depois do conserto: suite-email 179 · 0 · contraste-email 14 pares, 0 reprovações.


64.9.2 A BANCADA também é artefato, e o instrumento dela também tem contrato#

As quatro bancadas da BT-P1/PS-P4 passaram o rito de promoção inteiro — suíte própria, BT7, render em cinco larguras e dois temas, contraste, escala de figura — com um defeito de acessibilidade dentro: a fronteira do <select> da barra de provas media 1,37 no claro (#C8D6DF sobre #F2F6F9) e 2,61 no escuro (#4D606C sobre #141D23), contra o piso 3,00 da SC 1.4.11.

Nenhuma guarda o via porque todas olhavam o espécime. A causa foi a base-bancada.css consumir --seed-border-default, que não é semântico de fronteira de controle — o próprio gêmeo escreveu isso na v1.12 ao criar o --seed-border-interactive: "nenhum outro semântico de borda passava no claro (default 1.49, strong 2.53)". Alternativa descartada: --seed-border-strong (#90A6B3), que mede 2,53 — continua abaixo do piso.

Regra nova, transversal: a bancada é artefato, e a barra de provas é interface. O que o sistema cobra do componente, cobra do suporte onde ele é avaliado. Mesma família do botão de tema que estava morto em três bancadas (§64.2 / MANIFESTO §72): instrumento que não se mede é instrumento que mente.

E a consequência de método, cumprida: os quatro artefatos mudaram depois de as folhas de captura terem sido geradas. O rito foi reexecutado e as folhas regeradas, para que o gate cubra a versão real — em vez de virar errata depois. "Aprovado" cobre o que foi olhado, não o que estava por perto (§64.7 / MANIFESTO §77.4).


64.9.3 A FOLHA DE CAPTURA vira parte do rito de promoção#

Contrato novo: bancada não vai a gate sem folha de captura. Gate sem folha vira "abre o arquivo e procura", e foi assim que a banco-data v0.1 passou em 25 PASS · 0 FAIL com o calendário inoperante (§61.7) — quem reprovou foi o olho, não o placar.

A folha (validacao/folha-captura.mjsrender-audit/folha-<nome>.html) imprime cada bloco de estado lado a lado nos dois temas, com o tema anotado em cada figura — lei CP31, bancada imprime estados, não fluxo —, e traz no cabeçalho o que a guarda não consegue medir e por isso é o que o olho precisa julgar: legibilidade de forma, densidade, ritmo visual, e se o estado impresso é o estado que o componente realmente tem.

A folha é DESENHO, não instrumento operável: sem button, sem input, sem tabindex (§67.4).

Defeito da própria folha, achado na primeira geração e consertado: o recorte começava atrás da barra fixa do BT1 e comia o título de cada bloco. A altura da barra passou a ser medida, nunca suposta, e a barra é detectada por comportamento (position sticky/fixed encostada no topo), não por nome de classe.


64.9.4 SUPERSEDE FORMAL das pendências do §64.6#

As linhas abaixo supersedem as correspondentes da tabela do §64.6. A tabela antiga fica como histórico; o estado vigente é este.

# Estado em 2026-08-17 (v1.00)
E-P1 FECHADA. Veredito dado com o RITO de três rodadas (R1 WCAG2ICT · R2 fluid hybrid/Outlook · R3 EN 301 549 §10.1.4.10). Nasce o EM-BT7 (§64.9.1). 12 artefatos consertados; suite-email-reflow 16 · 0 · 26.
CD-P2 FECHADA. --seed-field-border vira alias de --seed-border-interactive. Medido: 4,39 → 3,13 no claro, 5,05 → 5,05 no escuro; os dois acima do piso 3,00, margem do claro caindo de 1,39 para 0,13 — consequência medida, registrada. O nome local não foi apagado: são 32 consumos, e trocar 32 lugares sem gate seria o irreversível onde cabia o reversível (§75). As variantes de estado (-hover, -error, -success, -warning) não migram: não têm semântico no gêmeo.
CD-P3 FECHADA. validacao/auditoria-borda-campo.mjs criada e executada em 9 artefatos × 2 temas: 10 PASS · 0 FAIL. O único FAIL de campo era o <select> da barra de provas (§64.9.2), consertado.
BT-P1 · PS-P4 ABERTAS só no gate. O trabalho de preparação acabou: rito completo nas quatro bancadas e folhas de captura entregues.
BT-P3 ABERTA, sem avanço nesta sessão — a fila foi consumida pelos três primeiros itens da ordem, e os defeitos de instrumento 21º/22º/23º custaram o tempo restante. Ausência de trabalho, declarada.
CD-P6 (nova) --seed-surface-sunken (#E3EBF0) mede 2,80 contra --seed-border-interactive — abaixo do piso 3,00. O comentário do gêmeo declara "seis superfícies, todas ≥3"; recontado por comando, o tema claro tem oito, e três ficam abaixo: brand 1,25, brand-deep 1,87 (as duas sob a tolerância do BT4, superfície de marca) e sunken 2,80 (não coberta pelo BT4). Nenhum campo do acervo está sobre ela hoje — foi medido. Alterar token do gêmeo pede rodada própria.
CD-P7 (nova) 93 botões do acervo com borda abaixo de 3,00. Achado, não veredito: a SC 1.4.11 exige 3:1 da informação visual necessária para identificar o componente, e botão tem rótulo, forma e muitas vezes preenchimento. Decidir se a borda dele é identificador necessário é desenho, não medida. Guarda que condena artefato correto força conserto errado (§64.3, forma 2 da GI2).
E-P2 (nova) A tabela de dados de e-mail cabe hoje por geometria. Ganhando uma quarta coluna, não cabe. A técnica que preservaria o significado ao empilhar — rótulo repetido por linha, porque ::before/content não funciona em e-mail — exige marcação nova no componente EC e gate próprio.

64.10 O GATE OBSERVADO das quatro bancadas — BT-P1, PS-P4 e DH-P6 FECHAM (2026-08-17, v1.01)#

O que esta subseção registra, para quem lê sem ter visto a conversa que a gerou. As quatro bancadas do bloco de entrada e seleção — banco-escolha.html (§60), banco-data.html (§61), banco-prioridade.html (§63) e banco-pessoa.html (§62) — esperavam, desde 2026-08-16, a única coisa que nenhuma guarda automatizada entrega: o olho do Rafael Sant'Ana, CEO e decisor único. Bancada, neste sistema, é o artefato HTML que imprime todos os estados de um componente lado a lado para inspeção (lei CP31: bancada imprime estados, não fluxo — ela não é uma tela do produto). Gate é a aprovação humana que autoriza promover uma spec a estável. A pendência do re-gate das três primeiras chamava-se BT-P1; a da banco-pessoa, PS-P4; e a DH-P6 (§61.8) era a mesma pendência dita do lado do §61, para não haver duas listas divergentes.


64.10.1 Por que este gate é OBSERVADO, e não DECLARADO#

A distinção entre gate OBSERVADO e gate DECLARADO existe para tornar errata possível, e nasceu no §78 do validacao/MANIFESTO.md depois de uma rodada em que quatro seções foram promovidas com um "aprovo. siga" que não dizia qual artefato havia sido aberto:

  • gate DECLARADO — o Rafael aprovou e não há registro de qual insumo ele olhou. A promoção vale; o que fica registrado é que uma errata futura é possível sem contradizer o registro.
  • gate OBSERVADO — há registro de que o insumo nomeado do gate foi olhado. Errata aqui seria contradição, não complemento.

Este gate é OBSERVADO. O registro é a própria pergunta que o produziu: a aprovação foi colhida numa escolha de três opções explícitas — "Aprovo — gate OBSERVADO", "Aprovo — gate DECLARADO" e "Ainda não olhei — deixa aberto" — sobre a pergunta "Você já olhou as folhas de captura das quatro bancadas (banco-escolha v0.4, banco-data v0.4, banco-prioridade v0.2, banco-pessoa v0.1) em render-audit/folha-banco-*.html?". Ele escolheu a primeira. O insumo está nomeado por arquivo e por versão, a natureza do gate foi decidida por ele e não por mim, e a alternativa "declarado" estava na mesa e foi recusada.

Fato vs. inferência, declarado: é fato que a opção escolhida nomeia as quatro folhas e as quatro versões, e que a opção "declarado" foi oferecida e não escolhida. É inferência minha que ele abriu as quatro folhas e não três — a granularidade da pergunta foi de conjunto, não de artefato. Quem quiser granularidade por artefato precisa de quatro perguntas, e essa é a lição desta rodada sobre a forma de perguntar.


64.10.2 O placar do rito, REEXECUTADO do zero antes de promover#

Regra aplicada: medição antes da spec — número lembrado não promove nada. Todo o rito foi reexecutado neste contêiner contra os artefatos lidos da pasta no início desta sessão, e não contra os números registrados no §80 do MANIFESTO. Os dois conjuntos coincidem integralmente, o que é a evidência de que os artefatos da pasta são os mesmos que o rito de 2026-08-17 mediu.

Camada de prova banco-escolha v0.4 banco-data v0.4 banco-prioridade v0.2 banco-pessoa v0.1
Suíte própria (jsdom + render) 238 · 0 · 29 em 5 alvos · 138 · 0 · 0 no artefato isolado 31 · 0 · 1 18 · 0 · 0 44 · 0 · 1
BT7 (SC 1.4.10 · não rola a 320/390) via suite-reflow 5 · 0 5 · 0 5 · 0 3 · 0 · 1 [n/a]
Rito de promoção render-promocao (5 larguras × 2 temas) ✅ — agregado 168 · 0 nos quatro
Contraste na composição contraste-composicao (fundo lido do pixel, 2 temas) 2 · 0 2 · 0 2 · 0 2 · 0 — agregado 8 · 0
Fronteira de campo auditoria-borda-campo (piso 3,00 da SC 1.4.11) 2 · 0 2 · 0 2 · 0 2 · 0
Folha de captura (§64.9.3) render-audit/folha-banco-escolha.html …folha-banco-data.html …folha-banco-prioridade.html …folha-banco-pessoa.html

Achado colhido de graça, que alimenta a CD-P7 com número por artefato. A auditoria-borda-campo.mjs emite achado, não veredito, para borda de botão (§64.9.4). Nas quatro bancadas, por tema, ela contou: banco-escolha 15 · banco-data 32 · banco-prioridade 6 · banco-pessoa 255 botões com borda abaixo de 3,00. Fronteira declarada: 55 é a contagem nestes quatro artefatos, não no acervo; o total de acervo registrado na CD-P7 é 93, e a diferença está nos outros artefatos, que não foram remedidos aqui. Nenhum desses 55 é defeito nem aprovação enquanto a CD-P7 não tiver veredito.

Nota de ambiente, para quem reproduzir. A suite-escolha varre cinco alvos (a bancada mais tela-painel, tela-lista, tela-tabela e tela-detalhe). Rodada numa cópia de trabalho que tinha só a bancada, ela devolveu 138 PASS · 4 FAIL — e os quatro FAIL eram arquivo ausente, não defeito de artefato. Isso é um caso do princípio do §64.9.2: alvo que não está lá não é alvo que reprova, e suíte que conta ENOENT como FAIL produz o mesmo mal da suíte que morre — número plausível sobre coisa que não foi medida. Trazidos os quatro alvos por nome, o placar foi a 238 · 0 · 29.


64.10.3 ERRATA DE VERSÃO em três cabeçalhos — o documento declarava versão que o artefato não tem#

Achado desta sessão, por medição, antes de qualquer promoção. Os cabeçalhos das seções §61, §62 e §63 declaravam versões de bancada uma minor acima das que existem:

Seção Versão que o cabeçalho declarava Versão MEDIDA no artefato Corrigido para
§61 · banco-data.html v0.5 v0.4 v0.4
§62 · banco-pessoa.html v0.2 v0.1 v0.1
§63 · banco-prioridade.html v0.3 v0.2 v0.2

Como foi medido, e por que o artefato ganha. Quatro fontes independentes foram conferidas por comando, e três concordam contra uma:

  1. O artefato<title> e o <p class="selo"> de cada bancada. Medido: banco-escolha v0.4, banco-data v0.4, banco-prioridade v0.2, banco-pessoa v0.1.
  2. O gerador — o histórico de versão comentado em validacao/gen-banco-*.py para em v0.4, v0.4, v0.2 e v0.1. Nenhum gerador conhece as versões v0.5 / v0.2 / v0.3 alegadas.
  3. O validacao/MANIFESTO.md — §76 (v0.3 → v0.4), §78, §79 e §80 dizem, em nove ocorrências distintas, banco-escolha v0.4 · banco-data v0.4 · banco-prioridade v0.2 · banco-pessoa v0.1.
  4. O mapa-cobertura-ds.md §11.3 — as mesmas quatro versões.

Os três cabeçalhos eram a única fonte divergente do acervo. Alternativa descartada, com o porquê: subir os artefatos para as versões alegadas (v0.5 / v0.2 / v0.3) foi considerada e recusada — mudança de versão sem mudança de conteúdo é etiqueta, não versão (o §73 diz "mudança de conteúdo sobe a versão", e não o contrário); e, decisivo, as folhas de captura que o Rafael olhou neste gate foram geradas a partir dos artefatos v0.4 / v0.4 / v0.2 / v0.1 — conferido por mtime: as quatro folhas são ~3 s mais novas que os quatro artefatos. Reetiquetar o artefato depois do gate faria o "aprovado" cobrir um número que não existia quando ele olhou, que é exatamente o que a distinção observado/declarado foi criada para impedir.

Causa provável, declarada como inferência e não como fato: os três cabeçalhos foram escritos na sessão da manhã de 2026-08-17 antecipando uma regeração que a sessão da tarde não produziu — e a tarde registra que um mv+rm em lote destruiu quatro cópias de trabalho, retrazidas por nome da pasta, o que devolveria os geradores à versão anterior. Não há evidência direta desse encadeamento; o que é fato é a divergência e sua direção — exatamente +1 minor em cada um dos três.


64.10.4 SUPERSEDE FORMAL — o que passa a valer#

As linhas abaixo supersedem as correspondentes do §64.9.4, do §64.6, do §61.8 e do §62.7. As tabelas antigas ficam como histórico; o estado vigente é este.

# Estado em 2026-08-17 (v1.01)
BT-P1 FECHADA. Re-gate visual OBSERVADO de banco-escolha v0.4, banco-data v0.4 e banco-prioridade v0.2 (§64.10.1). Rito completo reexecutado antes de fechar (§64.10.2). As três specs (§60, §61, §63) permanecem estável, agora com gate observado em vez de declarado.
PS-P4 FECHADA. Gate visual OBSERVADO de banco-pessoa v0.1 (§64.10.1). A spec do §62 permanece estável, agora com gate observado. Não confundir com a PS-P2, que segue ABERTA: C5 (seletor de entidade colorida) e C8 (menção @) são inalcançáveis no modo somente leitura, porque só abrem escrevendo no produto de referência.
DH-P6 FECHADA — era a BT-P1 dita do lado do §61.8. O calendário da banco-data v0.4 opera (31 guardas de operabilidade, medidas) e foi olhado. Fecha a linhagem que a DH-P5 abriu quando o olho reprovou a v0.1 com 25 PASS · 0 FAIL no placar.
Natureza do gate das quatro OBSERVADO, com o insumo nomeado por arquivo e por versão. Isto supersede a nota de rastreabilidade dos cabeçalhos de §61, §62 e §63, que dizia "o gate foi declarado, e não há registro de quais capturas ele abriu" — para estes quatro artefatos nestas quatro versões há registro. A nota continua valendo, sem alteração, para os artefatos que ela cobria e que não entraram neste gate: tela-referencia, tela-painel, tela-quadro, tela-gantt, banco-tokens e banco-dataviz-di, promovidos por gate declarado na manhã de 2026-08-17.
Errata de versão CORRIGIDA nos cabeçalhos de §61, §62 e §63 (§64.10.3): v0.5→v0.4, v0.2→v0.1, v0.3→v0.2. Correção do documento, não do artefato, com as quatro fontes de medição registradas.
Achado de instrumento, SEM conserto suite-escolha conta arquivo ausente como FAIL (4 FAIL medidos numa cópia sem os alvos de tela). Alvo ausente deve declarar [n/a], nunca reprovar — mesma família da regra "suíte que morre é pior que suíte que reprova". Não consertado nesta rodada: o padrão vale para as 21 suítes e pede prova de reprovação própria. Registrado para não voltar como surpresa.


64.11 A GI2 forma 4 vira GUARDA TRANSVERSAL — a BT-P3 fecha na FORMA, e a pasta ganha UM defeito medido (2026-08-17, v1.03)#

O que esta subseção registra, para quem a lê sem ter visto a conversa que a gerou. O contrato GI2 deste sistema diz: componente consome token semântico, nunca primitiva de rampa. Primitiva é um token de cor cru (--seed-turquesa-100); semântico é um token de papel (--seed-text-primary). A diferença que importa é uma só: semântico inverte quando o tema inverte; primitiva não. A guarda que mede isso foi escrita quatro vezes (§64.3), e até hoje rodava em apenas três bancadas. A BT-P3 pedia levá-la às quatro suítes antigas.

64.11.1 SUPERSEDE FORMAL da FORMA da BT-P3 — um instrumento, não quatro cópias#

A BT-P3 pedia, ao pé da letra: "levar a guarda GI2 forma 4 às suítes antigas — suite-painel, suite-container, suite-dominio, suite-icones". Isto é: quatro cópias da mesma guarda de ~130 linhas, uma em cada suíte.

ALTERNATIVA DESCARTADA: as quatro cópias. O motivo não é economia de trabalho — é o achado central da própria sessão que fecha esta pendência. Em 2026-08-17 nasceu a auditoria-consumidor.mjs (§69) exatamente porque cópia colada de bloco canônico DIVERGE do canônico: foi assim que o bloco de assinatura EA ficou com o cargo velho num consumidor por três dias, e nenhum placar viu. Espalhar a mesma guarda por quatro arquivos é cometer, na CAMADA DE INSTRUMENTO, o defeito que a camada de artefato acabou de ganhar guarda para não cometer. E há precedente na casa: todo contrato transversal deste projeto já se resolve com instrumento de alvo de PASTAsuite-reflow.mjs para o BT7, auditoria-borda-campo.mjs para a SC 1.4.11, contraste-composicao.mjs para contraste em composição. O GI2 é do §64, que é a seção dos contratos transversais.

ESCOLHIDO: validacao/guarda-gi2.mjsuma guarda, alvo de PASTA, cobrindo os alvos das quatro suítes antigas e todo o resto do acervo. A BT-P3 fecha com cobertura maior do que pedia: 29 artefatos, contra os 4 alvos que as quatro suítes cobririam.

FRONTEIRA DECLARADA, e ela importa: este instrumento não altera as quatro suítes antigas. Quem rodar suite-painel isolada não verá GI2 no placar dela. A cobertura existe e está no instrumento novo; dizer que as suítes antigas passaram a medir GI2 seria falso. Rode os dois.

64.11.2 O placar, e o que ele mudou no estado do acervo#

15 PASS · 1 FAIL · 35 [n/a] em 29 artefatos — primeira medição de GI2 na pasta inteira.

Os 35 [n/a] não são silêncio: são três categorias declaradas, cada uma com o motivo impresso. 14 de superfície (consumidor de primitiva sem texto próprio) · 5 sem anel (texto sem fundo próprio ou com padding < 2px) · 3 com override de tema (a primitiva inverte a mão). O resto é artefato que não consome primitiva nenhuma.

CONSEQUÊNCIA MATERIAL PARA O ESTADO DO PROJETO, e ela tem de ser dita sem rodeio. Até esta subseção, o registro dizia que o acervo inteiro estava SEM DEFEITO MEDIDO EM ABERTO. Isso deixa de ser verdade. A tela-chat.html tem um defeito medido, reprodutível em três execuções idênticas, e ele é a pendência BT-P6 abaixo. A frase antiga não era mentira: era o alcance da medição de então. Guarda nova encontra defeito antigo — é para isso que ela existe.

64.11.3 BT-P6 (nova) — DEFEITO MEDIDO EM ABERTO na tela-chat.html#

O quê Medida
Seletor .msg--propria .msg__balao — o balão da mensagem própria no chat
Declara background: var(--seed-turquesa-50)primitiva, não inverte · color: var(--seed-text-primary)semântico, inverte
Override de tema para este seletor não existe (medido: zero ocorrências de [data-theme="dark"] para ele)
Medido no tema escuro texto #ddece8 sobre fundo #e8fbf7 = 1,14 · piso 3,00
Reprodutibilidade 3 de 3 execuções, valor idêntico

É exatamente a forma do defeito que o gate do Rafael achou em 2026-08-16 — fundo primitivo de um lado, texto semântico do outro; no escuro o texto clareia e o fundo não, e a mensagem fica branca sobre branca. Os dois casos daquele dia mediram 1,02 e 1,00; este mede 1,14.

Conserto indicado, NÃO executado nesta rodada, e o porquê: trocar --seed-turquesa-50 pelo semântico de superfície equivalente, no validacao/tela-chat-template.html, e regerar por gen-tela-chat.py. Não foi feito aqui por duas razões declaradas: (1) a tela-chat é artefato promovido, e conserto em artefato promovido pede rodada com re-execução da suíte própria, do BT7 e do contraste, mais folha de captura — a fila desta sessão não alcançou; (2) qual semântico entra é escolha com consequência visual no balão, e o §64.9.2 já ensinou que a escolha do token semântico certo é decisão, não substituição mecânica. Ausência de conserto, declarada — não silêncio.

64.11.4 QUATRO consertos de instrumento — e o 24º defeito é NÚMERO QUE VARIA ENTRE EXECUÇÕES#

Levada crua da bancada para a pasta inteira, a guarda devolveu 7 FAIL. Investigados um por um, seis eram falso positivo, e cada um por uma razão diferente e nomeável. Sete consertos errados de uma vez teriam sido o pior estrago já causado nesta pasta.

Conserto O falso positivo, medido A causa A regra
A .fachada do tela-site reprovou a 1,01 é um contentor de vídeo 16/9 sem texto próprio — quem pinta texto ali são os filhos, com cor própria. A guarda leu a cor herdada do contentor contra o pixel dominante dele elemento sem texto próprio não é par texto/fundo. Entra no relatório como consumidor de superfície, não como reprovação
B .seed-empty__icon do banco-feedback (1,91) e o h2 do banco-formfield (2,04) os dois declaram primitiva e têm a regra irmã [data-theme="dark"] para si mesmos — cinza-300cinza-600 e turquesa-600turquesa-300 primitiva com override explícito de tema INVERTE a mão. A premissa da guarda ("primitiva não inverte") não se aplica: condená-los seria condenar a solução
C o h2 devolveu fundo "#aaadaf" — cinza médio que não existe no artefato numa caixa apertada, o pixel dominante é a mistura de texto e fundo pelo antialias o fundo de um texto é o ANEL em volta dele, a moldura externa da captura, onde está o padding
D .tagok do banco-composicao mediu 1,84, depois 2,56, depois 2,95no mesmo artefato, sem tocar nele ele é {color:var(--seed-turquesa-600);font-weight:700}: sem fundo próprio e sem padding. A caixa é apertada em volta dos glifos, então o anel de 2px é o próprio glifo. #cecfd0 é o cinza que o antialias produz misturando #098475 com branco: a guarda media o texto contra si mesmo número que varia entre execuções do mesmo alvo NÃO É MEDIDA — é assinatura de medidor quebrado, e este reprovava três artefatos. Elemento de texto sem fundo próprio ou com padding < 2px sai como [n/a] com o motivo

A regra que o conserto D deixa, e ela é simétrica: guarda que não consegue medir não pode declarar aprovação — e não pode declarar reprovação tampouco. O projeto já tinha metade dessa regra escrita. A outra metade custou três FAIL em artefatos corretos.

E a lição de método: o conserto C parecia suficiente e não era — ele mentia diferente a cada execução, e a única coisa que revelou isso foi rodar a mesma medida três vezes. Medida que não é repetida não está verificada. Repetição entra no rito.

Isto abre a BT-P5 (nova): medir o fundo real de um texto sem anel exige ler o ancestral que pinta, fora do retângulo do elemento — e isso é coordenada relativa a outra captura, que é a família do 22º defeito de instrumento. Pede rodada própria. Hoje são 5 [n/a] declarados por essa causa.

64.11.5 A PROVA DE REPROVAÇÃO — e ela fechou o diagnóstico#

Injetado em banco-superficies.html (que passava) um elemento com a forma exata do defeito — fundo primitivo --seed-turquesa-50 mais texto semântico --seed-text-primary, com padding para ter anel. Resultado: FAIL a 1,14 no escuroo mesmo número da tela-chat. A coincidência não é acaso: ela prova que o mecanismo diagnosticado é o mecanismo real, e não uma coincidência de pixel. Revertido, com MD5 conferido contra o arquivo da pasta.

64.11.6 Estado das pendências desta subseção#

# Estado
BT-P3 FECHADA na FORMA superseder (§64.11.1): um instrumento transversal de alvo de PASTA em vez de quatro cópias, cobrindo 29 artefatos em vez de 4. Fronteira: as quatro suítes antigas seguem sem GI2 no placar delas.
BT-P5 (nova) ABERTA. A medida de par texto/fundo não alcança elemento de texto sem anel (sem fundo próprio ou padding < 2px). Hoje: 5 [n/a] declarados. Alcançar exige ler o ancestral que pinta, fora do retângulo — família do 22º defeito, rodada própria
BT-P6 (nova) ABERTA — DEFEITO MEDIDO. tela-chat.html, .msg--propria .msg__balao, 1,14 no escuro contra piso 3,00, reprodutível 3/3. Conserto indicado e não executado, com o porquê (§64.11.3). O acervo não está mais sem defeito medido em aberto

64.12 CD-P7 — o RITO de três rodadas sobre a borda de BOTÃO, e o veredito PROPOSTO (2026-08-17, v1.04)#

O que esta subseção resolve, para quem a lê sem ter visto a conversa que a gerou. A validacao/auditoria-borda-campo.mjs mediu, no acervo, 93 botões cuja borda fica abaixo do piso 3,00 da SC 1.4.11 (Non-text Contrast) da WCAG 2.2. Ela emitiu [achado], não veredito, de propósito: a SC exige 3:1 da "informação visual necessária para identificar o componente", e botão tem rótulo, forma e muitas vezes preenchimento. Decidir se a borda do botão é identificador necessário é DESENHO, não medida — e por isso a pendência CD-P7 existe e exige RITO de três rodadas mais gate. Nenhum dos 93 é defeito nem aprovação enquanto não houver decisão.

64.12.1 R1 · CANON — o Understanding responde a pergunta DIRETAMENTE#

O texto normativo da SC 1.4.11 é: "The visual presentation of the following have a contrast ratio of at least 3:1 against adjacent color(s): User Interface Components [and] Visual information required to identify user interface components and states, except for inactive components."

E o Understanding SC 1.4.11 do W3C diz, verbatim, o que resolve a CD-P7:

"If a control has visible content (such as text or a sufficiently contrasting icon), which helps users identify the presence of the control, then a border or other indication of the overall boundary of the hit area is not required."

O mesmo documento traz como caso que PASSA: "A button without a visual boundary — the button's text is sufficient to indicate the presence of the control."

Leitura direta: botão com rótulo legível NÃO precisa de borda a 3:1. A borda só se torna "informação visual necessária" quando não há outro identificador — nem rótulo legível, nem ícone com contraste suficiente.

Divergência de canon, registrada porque existe e porque a fronteira do que eu li importa. A issue w3c/wcag#800 foi aberta por David MacDonald com a leitura oposta: "palavras sozinhas não bastam para identificar um controle interativo" — se há fundo ou borda visíveis sugerindo um botão, esses elementos precisariam dos 3:1. A issue foi discutida em 25/06/2019 e fechada pelo PR #813, que é o que produziu o texto do Understanding citado acima. Fronteira do que MEDI: li a abertura da issue e o Understanding vigente; não consegui ler a thread completa nem o PR. Logo: é fato que o texto vigente do Understanding diz que a borda não é obrigatória com rótulo visível, e é inferência minha que o grupo resolveu a favor dessa leitura por meio daquele PR.

64.12.2 R2 · MERCADO — os maduros dão a borda ao TERCIÁRIO e NENHUMA ao fantasma#

Carbon Design System (IBM), especificação de botão, medida na fonte:

Variante Borda Fundo
ghost (fantasma) nenhuma borda declarada, em nenhum estado — nem repouso, nem hover, nem foco, nem ativo transparent
tertiary (terciário) tem borda no repouso, com token próprio ($button-tertiary) transparent

O Carbon não publica o número de contraste dessas bordas — nomeia o token e não declara a razão. Registro isso como limite da fonte, não como omissão minha.

O que o padrão do mercado diz, então: a borda não é obrigatória em botão identificado por rótulo (o ghost prova por existência); e quando ela é o identificador — no tertiary, que tem fundo transparente e portanto nada além da borda para se distinguir da página —, ela ganha token próprio e passa a ser estrutural. Isso é exatamente a fronteira que o Understanding descreve, achada independentemente por um sistema maduro.

64.12.3 R3 · NORMAS — e aqui a pergunta MUDA, com número medido#

EN 301 549 cláusula 9 remete a WCAG 2.1 AA, então a régua da SC 1.4.11 é a mesma. A rodada de normas não contradiz a R1. Mas ela abre um risco diferente, e este é o achado que a CD-P7 não previa.

Em forced-colors (o modo de alto contraste do sistema operacional), o navegador sobrescreve background-color e box-shadow. A orientação canônica de Sarah Higley para o modo é declarar uma moldura transparente de propósito, para que o sistema a torne visível: "make it transparent instead: outline 3px solid transparent", e ela registra que "this trick also works with transparent borders if, for example, your button has a distinct background color but no separately visible borders".

Consequência, e ela inverte o problema. Um botão identificado apenas pelo preenchimento desaparece em forced-colors — porque é justamente o preenchimento que o modo joga fora. Quem sobrevive é quem declarou borda ou outline, mesmo transparente. Ou seja: o risco real não é "borda abaixo de 3,00"; é "nenhuma borda nem outline declarada".

MEDIDO NO ACERVO, por comando, nesta rodada:

Medida Número
Artefatos varridos 29
Artefatos que declaram alguma regra @media (forced-colors: active) 12
Artefatos que, dentro dessa regra, tratam botão 1 — só o tela-painel.html (2 regras)

Vinte e oito de vinte e nove artefatos não têm nenhuma regra de botão para forced-colors. Este número é novo, não estava em pendência nenhuma, e é o que a rodada de normas entregou.

64.12.4 VEREDITO PROPOSTO — três frases, e a decisão é do Rafael#

1 · Os 93 achados NÃO são defeito de SC 1.4.11, com a fronteira escrita: um botão cujo rótulo é legível (texto acima do piso de 4,50 do projeto) ou cujo ícone atinge 3:1 tem identificador suficiente, e a borda dele não é "informação visual necessária". É o que o Understanding diz verbatim e é o que o Carbon pratica no ghost.

2 · A exceção que continua valendo, e ela é estreita: botão cujo único identificador é a borda — fundo transparente, sem ícone, rótulo tipograficamente indistinto do texto corrido em volta — está sob a SC 1.4.11 e a borda dele tem de medir 3,00. É o caso do tertiary do Carbon. Quantos dos 93 caem nessa classe NÃO foi medido nesta rodada — a auditoria-borda-campo conta bordas, não classifica identificadores. Ausência de medição, declarada; se o gate aprovar a fronteira, medir isso é a primeira tarefa da rodada seguinte.

3 · Nasce uma obrigação NOVA, que não é a CD-P7 e é mais barata que ela: todo botão declara outline (ou borda) transparente para sobreviver a forced-colors, porque o modo descarta background-color. Hoje 1 de 29 artefatos tem regra de botão para forced-colors. Isto é conserto mecânico e de baixo risco, e vale para o acervo inteiro.

A pergunta de gate está acumulada no fechamento desta sessão. Enquanto o Rafael não decidir, os 93 continuam [achado]: nem defeito, nem aprovação. Guarda que condena artefato correto força conserto errado — e "conserto" aqui significaria pôr borda a 3:1 em 93 botões que o canon diz não precisarem dela.

64.12.5 Pendências desta subseção#

# Estado
CD-P7 RITO COMPLETO (R1 canon · R2 mercado · R3 normas), veredito PROPOSTO, ABERTA só no GATE. O trabalho de pesquisa acabou; a decisão é de desenho e é do Rafael
CD-P9 (nova) ABERTA — e ela é a que tem número. 28 de 29 artefatos do acervo não têm nenhuma regra de botão em @media (forced-colors: active). Botão identificado só pelo preenchimento desaparece no modo de alto contraste, porque o modo descarta background-color. Conserto: outline transparente declarado. Mecânico, barato, e vale para a pasta inteira
CD-P10 (nova) ABERTA. Quantos dos 93 botões têm a borda como único identificador (fundo transparente · sem ícone · rótulo indistinto) não foi medido: a auditoria-borda-campo conta bordas, não classifica identificadores. É a primeira tarefa se o gate aprovar a fronteira do §64.12.4

64.13 A BT-P6 FECHA na causa, a CD-P7 FECHA por decisão, e nasce a MR-P1 (2026-08-17, v1.05)#

Esta subseção SUPERSEDE o §64.11.3, que descreve a BT-P6 como defeito ABERTO — ele foi escrito antes do conserto. Relato completo no validacao/MANIFESTO.md §85.

64.13.1 BT-P6 — o conserto, e por que ele foi feito no GÊMEO#

O conserto óbvio seria trocar a primitiva por um semântico no artefato. Não havia semântico para trocar. Medido: o tela-chat.html era o único consumo de --seed-turquesa-50 em 29 artefatos, e o gêmeo não tinha token semântico para "superfície de marca sutil" — tinta de marca sem virar surface-brand. O artefato alcançou a primitiva porque era a única coisa disponível.

Regra nova: quando o artefato consome primitiva e é o ÚNICO consumidor dela no acervo, a primeira hipótese não é descuido — é LACUNA DE TOKEN. Consertar o artefato sem olhar o gêmeo empurraria o defeito para o próximo componente que precisasse da mesma coisa.

Passo Feito Medida
1 Nasce --seed-surface-brand-subtle nos três gêmeos claro #E8FBF7 · escuro #1A3833
2 Contra --seed-text-primary 12,79 claro · 10,40 escuro · piso 4,50
3 Molde consome o semântico; seed-turquesa-50 sai da lista NOMES do gerador token injetado e não consumido é peso morto
4 tela-chat.html regerada e remedida guarda-gi2 0·0·2 [n/a] · suite-reflow 3·0·1 · contraste-composicao de 0·2 FAIL para 1·1 — os três FAIL do escuro sumiram

#1A3833 não é valor novo: é o que a camada de tokens já havia escolhido para superfície de marca que assenta na página (--seed-action-secondary-bg no escuro). Alternativas descartadas: reusar --seed-row-selected-bg/--seed-action-secondary-bg (o semântico estaria mentindo — balão não é linha selecionada nem fundo de botão), ou usar --seed-surface-subtle como o balão alheio (apagaria a distinção de tinta entre mensagem própria e alheia, que é desenho aprovado).

64.13.2 CD-P7 ✅ FECHADA por decisão — os 93 não são defeito#

O Rafael questionou a recomendação do §64.12 e a acatou depois da defesa: (1) o Understanding da SC 1.4.11 diz verbatim que borda não é obrigatória em controle com conteúdo visível; (2) consertar destruiria a escala de botão — o que distingue terciário de fantasma é a borda, e a 3:1 em todos o fantasma vira terciário (o Carbon pratica a mesma fronteira: ghost sem borda, tertiary com); (3) o risco real é outro e tem número — 28 de 29 artefatos sem regra de botão para forced-colors (CD-P9).

Fronteira que fica escrita: botão com rótulo legível (acima do piso 4,50) ou ícone a 3:1 tem identificador suficiente e a borda dele não é "informação visual necessária". Exceção estreita mantida: botão cujo único identificador é a borda — e quantos são disso não foi medido (CD-P10).

64.13.3 MR-P1 (nova) — o número que sustenta a regra de branco sobre a marca NUNCA EXISTIU#

Rodando o contraste-composicao.mjs no tela-chat.html — alvo em que ele nunca havia sido apontado — dois textos reprovaram o piso 4,50 da SC 1.4.3 no claro: button "Recolher chat" (12px/600) e div.avatar "RS" (12px/700), ambos #ffffff sobre #11b0a0 = 2,71.

#11B0A0 é --seed-surface-brand. O seed-tokens.md declarava 3,22:1 e concluía "passa AA-large (≥3.0)" — e sobre essa conclusão foi construída a regra "branco sobre surface-brand somente ≥24px ou ≥19px bold", com supersede formal da regra do marca-seed.md v4. Duas medições independentes derrubam o 3,22: cálculo direto pela fórmula da WCAG 2.x = 2,74; leitura por pixel = 2,71. A 2,71, branco sobre a marca reprova até AA-large — não é permitido em nenhum tamanho.

A resposta já estava na casa, no tema escuro do mesmo artefato: #00352F sobre #11B0A0 = 4,99. Medido também #0B3330 = 5,06 e #005048 = 3,45.

DECISÃO DO RAFAEL: recomendação ACATADA — a tinta sobre --seed-surface-brand passa a ser escura (turquesa-900 ou o texto primário), nos dois temas, e não branca em nenhum tamanho. Errata escrita no seed-tokens.md. Execução pendente, e o motivo é explícito: muda todo botão e selo de marca do acervo, a regra antiga está referenciada no marca-seed.md, e quantos casos existem NÃO FOI CONTADO — o instrumento foi apontado até hoje para 6 dos 29 artefatos. Contar vem antes de consertar.

A lição de cobertura, e ela vale para todo eixo declarado limpo neste arquivo: este defeito existia desde que a regra foi escrita, e nenhuma guarda o viu porque nenhuma guarda tinha sido apontada para aquele alvo. Ausência de medição não é aprovação. Antes de declarar um eixo limpo, liste quais alvos cada instrumento cobre e aponte-o para os que faltam. Terceira vez que alargar o alvo de um instrumento existente rende mais que escrever spec nova — as outras duas foram a BT-P4 e a BT-P3.

64.13.4 SI-P4, IL-P2 e PS-P5 — DECIDIDAS, execução pendente#

O Rafael aprovou a unificação e a chamou de inegociável: "unificar é melhor… precisamos manter o mesmo padrão, isso é inegociável."

# Decisão Estado
SI-P4 .sigla§65 EXECUTADA em 2026-08-19 — e eram OITO telas, não quatro. As quatro desta linha mais tela-chat, tela-gantt, tela-quadro e tela-referencia, que nenhuma lista escrita à mão continha e que só apareceram quando a guarda passou a varrer a PASTA. Ver §65.7
IL-P2 ✅ grade do §48 → §67 EXECUTADA em 2026-08-19. Eram sete defeitos, não três — o principal era teclado, não semântica. Ver §67.7
PS-P5 REVOGADA PELA MEDIÇÃO em 2026-08-19 — ver §62.8. O .mini-avatar não é avatar de pessoa: ele carrega o CLIENTE, que é uma ENTIDADE, com as iniciais do cliente, na coluna Cliente de tela-tabela e tela-referencia. A paleta de entidade é a certa para o que ele representa. Em tela-lista ele tinha zero elementos no DOM — folha morta, removida com prova de inércia. Nasce a PS-P6, que é julgamento de PRODUTO
Ponto de cor decorativo (.ent · 12px · aria-hidden · sem glifo) ganha spec própria EXECUTADA em 2026-08-19 — §65.8, contrato SI18. E eram 29 elementos em 7 telas, não 14. Quatro divergências medidas, entre elas um ponto que pintava transparente no tela-lista

64.13.5 Pendências#

# Estado em 2026-08-17 (v1.05)
BT-P6 FECHADA na causa. Supersede o §64.11.3
CD-P7 FECHADA por decisão. Supersede o §64.12.5
MR-P1 (nova) DECIDIDA, execução pendente. Branco sobre --seed-surface-brand mede 2,71 e reprova até AA-large; a tinta passa a ser escura. Contar os casos no acervo é a primeira tarefa
SI-P4 · IL-P2 · PS-P5 · spec do ponto de cor DECIDIDAS, execução pendente (§64.13.4)
CD-P9 · CD-P10 · BT-P5 · AC-P1 · AC-P2 · CD-P6 · E-P2 ABERTAS, sem decisão

64.14 A MR-P1 EXECUTA no gêmeo, nasce e fecha a MR-P2, e o ANEL vaza em elemento pequeno (2026-08-17, v1.06)#

Esta subseção SUPERSEDE o §64.13.3 e a linha da MR-P1 no §64.13.5, que a descrevem como decidida, execução pendente. Relato completo, com placares e provas de reprovação, no validacao/MANIFESTO.md §86.

64.14.1 A causa da MR-P1 era da CAMADA DE TOKEN — terceira vez#

O conserto óbvio seria trocar o branco por tinta escura em cada artefato. Seria conserto de sintoma. Medido: um único token de tinta servia TRÊS fundos de marca com necessidades OPOSTAS, e o gêmeo de JSON descrevia esse token, com essas palavras, como "texto sobre action.primary" — ele declarava para qual fundo havia sido feito, e estava sendo consumido em outros dois.

Fundo Valor branco escura #00352F
marca chapada surface-brand #11B0A0 nos dois temas 2,71 4,99
marca profunda surface-brand-deep claro #006C62 6,32 2,14
marca profunda escuro #005048 9,37 1,45
botão primário action-primary claro #098475 4,60 2,95
botão primário escuro #66D1C2 1,83 7,39

Nenhum valor único satisfaz as três linhas — logo o token acertava o botão primário e errava os outros dois, um defeito em cada tema. Conserto: três tintas, uma por fundo, nos gêmeos v1.15 — text-on-brand (escura nos dois temas), text-on-brand-deep (branca nos dois) e text-on-action-primary (inverte, com os valores que a tinta única tinha, de modo que o botão primário não muda de aparência). Regra vigente e alternativas descartadas: seed-tokens.md §5-b.

64.14.2 MR-P2 (nova, e FECHADA na mesma edição) — a irmã simétrica, no tema escuro#

Medido por pixel no tela-tabela.html, tema escuro: span.qtd "2", span.qtd "1" e button "1" (página corrente do rodapé) mediam #00352f sobre #005048 = 1,45, piso 4,50. Três textos. Ninguém tinha visto porque o contraste-composicao.mjs nunca havia sido apontado para o tela-tabela.html — ele cobria 6 dos 34 artefatos do acervo.

64.14.3 O CENSO da MR-P1, e os denominadores que estavam errados#

Momento Textos sobre a marca chapada Violando
antes, instrumento v0.1 45 15
antes, instrumento v0.2 (alcance maior) 49 17
depois de tudo 49 0

Duas correções de fato, medidas por comando: o acervo tem 34 artefatos banco-*/tela-* (24 + 10), não 29 — o 29 era o alcance de uma cópia de trabalho; e o contraste-composicao.mjs aceita VÁRIOS alvos por invocação (o abertura-proxima-sessao.md dizia que não; a restrição vale para a suite-reflow.mjs). Recontagem da CD-P9: 22 de 34 artefatos não têm nenhuma regra de forced-colors, e os 12 que têm cobrem estado, não fronteira de botão — logo 34 de 34 seguem sem regra genérica de botão.

Quinze das 17 violações vinham do token. Duas eram tinta #fff literal em style=, nas duas galerias de cor do acervo (banco-tokens.html, rótulo da barra de hierarquia 70/20/10; banco-dataviz-tokens.html, rótulo do stop 400 da rampa v0.1 rejeitada) — os dois artefatos não têm gerador e foram editados à mão, com a edição declarada.

64.14.4 25º DEFEITO DE INSTRUMENTO — o ANEL vaza em elemento pequeno e ARREDONDADO#

O anel de 5px nasceu para matar os 29 falsos positivos do span.av (caixa quadrada de 32px). Ele resolveu o quadrado de 32px e não resolveu o círculo de 26px: no tela-tabela.html o span.mini-avatar é um círculo de 26px e o rótulo de duas letras, dilatado em 5px, estoura o círculo pelos quatro cantos. Resultado: seis falsos positivos (1,00 no claro, 1,10 no escuro) sobre pares que medem, pela cor declarada, 5,11 a 9,37.

Conserto de premissa, nos dois instrumentos de contraste: quando o elemento pinta cor de fundo opaca e sem imagem, o fundo atrás do texto dele é essa cor declarada — não há o que amostrar. O pixel continua a régua para elemento que não pinta (captura expandida) e para elemento pintado por gradiente. Alternativa descartada: reduzir a folga de 5px para 2px — a 2px o anel vira o glifo, que é o 24º defeito. Prova nos dois sentidos, no mesmo alvo: o placar do tela-tabela.html foi de 3/7 FAIL para 1/3 — os seis falsos positivos sumiram e os quatro reais (três da MR-P2 a 1,45, um da MR-P1 a 2,71) continuaram reprovando.

Consequência para a PS-P5, e ela evita conserto errado: a decisão de migrar o .mini-avatar para a paleta de pessoa do §62 segue valendo (é token fora do semântico). Mas o componente renderiza corretamente hoje — 5,11 a 9,37 nos dois temas. Não há defeito de contraste no .mini-avatar, e quem abrisse a PS-P5 pelo placar em vez de pelo par declarado teria "consertado" cor que está certa.

64.14.5 BT-P7 (nova, e FECHADA) — token fantasma na BARRA DE PROVAS de seis bancadas#

O validacao/base-bancada.css pinta o estado ligado do alternador com surface-brand + text-on-brand + surface-brand-deep. Seis bancadas consumiam surface-brand e surface-brand-deep e NÃO OS DEFINIAM (banco-credencial, banco-data, banco-edicao-linha, banco-identidade, banco-prioridade, banco-texto-rico): variável indefinida é valor inválido, o fundo não pinta, classe NV-01. Consequência operável: o alternador de tema e o de escala de cinza dessas seis ficavam sem nenhuma marca visual de ligado — na barra que é o instrumento do gate humano (§64.9.2).

Nenhuma guarda tinha visto porque o estado ligado não existe no DOM estático: o aria-pressed nasce false e o manipulador o vira true no clique. Conserto na causa (os dois nomes entram nas listas NOMES dos nove geradores) e guarda nova permanente validacao/guarda-barra-provas.mjs, contrato BP1, alvo de pasta, que CLICA: 9 PASS · 0 FAIL · 15 [n/a], todos medindo 4,99. Prova de reprovação com o caso fundador: apagadas as duas definições, a BP1 reprova com "o FUNDO NAO PINTA".

64.14.6 BC-P1 (nova, e FECHADA pelo pré-voo) — nove bancadas estavam ATRÁS da folha base#

Antes de regerar, cada gerador rodou para destino temporário e a saída foi comparada com o artefato em disco ignorando comentários. Achou duas divergências substantivas, nenhuma desta edição: .vh { position:absolute } onde a folha base diz fixed — e fixed é o conserto do BT7/BT-P4, registrado como feito no §64.6 — e .controles { z-index:50 } onde a folha diz 9000. A regeneração desta edição levou as duas às nove bancadas. Classe AC1 uma camada acima: o AC1 compara bloco canônico em artefato, não folha base em artefato gerado — cobertura de um bloco não é cobertura da família.

64.14.7 DOIS ACHADOS NOVOS, medidos e NÃO consertados — os dois são pergunta de DESENHO#

Apontar o contraste-composicao.mjs para tela-lista e tela-gantt pela primeira vez achou dois casos que não vêm desta edição (a tinta deles não mudou) e que não são de contraste:

# Alvo Medido Diagnóstico
GT-P6 tela-gantt, span "Execução" dentro de button.gt-barra 1,00 claro · 1,12 escuro, contra fundo de página SEGUNDA FORMA do 25º defeito: quem pinta é o ancestral (.gt-barra, position:absolute, 20px de altura) e o rótulo dilatado em 5px estoura a barra na vertical. Par real, pela cor declarada: 4,60 no claro e 7,39 no escuro — passa. Não é defeito de artefato
LS-P6 tela-lista, td "Nenhuma fatura deste cliente no período filtrado." 1,22 nos dois temas a barra de seleção em massa (.massa, position:absolute, z-index:70) cobre a linha de estado vazio. O pixel está certo: ele lê o oclusor. Mas oclusão não é contraste — reportá-la como contraste é erro de categoria

| AD-P1 (nova) | banco-componentes e banco-tokens, botão destrutivo no tema escuro | 2,76 · #ffffff sobre #fc6f6a (action-destructive escuro), piso 4,50 | DEFEITO MEDIDO EM ABERTO, e é a mesma forma da MR-P1 um degrau adiante: no escuro o destrutivo é um vermelho claro e a tinta ali é branca. Falta o token de tinta do destrutivo, exatamente como faltavam as três tintas de marca. Não consertado: é decisão de identidade visual e pede rodada própria + gate |

Nenhum dos dois primeiros foi consertado, e o motivo é a lei da casa: guarda que condena artefato correto força conserto errado; quando a pergunta é de DESENHO e não de medida, emite-se achado, não veredito. O GT-P6 pede conserto de instrumento (generalizar a cor declarada para o ancestral que pinta, parando no primeiro background-image) — registrado como CC-P2. O LS-P6 pede decisão de desenho (a barra de massa pode cobrir a linha de estado vazio?) e vai a gate.

64.14.8 Pendências#

# Estado em 2026-08-17 (v1.06)
MR-P1 FECHADA. Conserto na camada de token, censo em 48 artefatos × 2 temas com 0 violações, guarda nova MR1. Supersede o §64.13.3
MR-P2 (nova) FECHADA na mesma edição. Mesma causa, tema oposto
BT-P7 (nova) FECHADA, com guarda nova BP1 que mede por clique
BC-P1 (nova) FECHADA pelo pré-voo de regeneração
BT-P5 PARCIAL. Fechada no guarda-tinta-marca.mjs pela captura expandida (23 folhas alcançadas onde a pendência previa 5). Aberta no contraste-composicao.mjs
GT-P6 · LS-P6 · CC-P2 (novas) ABERTAS, §64.14.7
AD-P1 (nova) DEFEITO MEDIDO EM ABERTO: branco sobre action-destructive no escuro mede 2,76. Mesma forma da MR-P1, e pede a mesma resposta — token de tinta próprio, rodada e gate
CC-P3 (nova) o contraste-composicao.mjs não conhece a isenção da SC 1.4.3 para componente INATIVO: reprova botão disabled da galeria de estados. 9 achados em banco-componentes. Isenção nomeada pela norma, guarda cega a ela
SI-P4 · IL-P2 · PS-P5 · spec do .ent DECIDIDAS, execução pendente. Ver a correção de premissa da PS-P5 em §64.14.4
CD-P9 ABERTA, denominador recontado: 22 de 34 sem nenhuma regra de forced-colors; 34 de 34 sem regra genérica de botão
CD-P10 · AC-P1 · AC-P2 · CD-P6 · E-P2 · CC-P1 ABERTAS
Gate as nove bancadas regeradas carregam .vh em fixed e z-index 9000, que nunca passaram pelo olho do Rafael. Inertes ao desenho, mas conserto medido não é conserto visto

64.15 A AD-P1 FECHA por pesquisa, a isenção de componente INATIVO entra nas guardas, e o gate vira VISUAL (2026-08-18, v1.07)#

Supersede a linha da AD-P1 no §64.14.7 e no §64.14.8, que a descrevem como defeito medido em aberto. Relato completo no validacao/MANIFESTO.md §87.

64.15.1 A regra de método que muda a forma de perguntar#

Instrução do Rafael, verbatim: "quando for me perguntar alguma coisa, me dê exemplos visuais… me diga qual é o arquivo e o que tenho que ver nele, ou traga o print com a comparação" e "essa é a única solução? ou é a melhor solução? pesquise sempre e aplique a melhor solução, não precisa me perguntar isso."

Leitura operacional, e ela vale para toda pergunta de gate deste projeto:

  1. Pergunta que a MEDIÇÃO responde não é pergunta. Meça e informe.
  2. Pergunta que a PESQUISA responde não é pergunta. Faça o RITO, decida, aplique, registre as alternativas descartadas com número.
  3. O que sobra para o gate é julgamento de APARÊNCIA — e vai com recorte antes/depois por elemento, nos dois temas, mais o arquivo e o que olhar nele. A folha render-audit/gate-mr1/gate-visual.html é o precedente e o molde.

64.15.2 AD-P1 ✅ FECHADA — --seed-text-on-action-destructive#

Nasce a tinta do destrutivo: #FFFFFF no claro (5,19) e #521112 vermelho-900 no escuro (5,26); no hover, 7,18 e 7,21. Antes, branco no escuro media 2,76. A tinta inverte com o tema, como a do botão primário. RITO: o M3 faz assim (on-error inverte); o Carbon faz o oposto (não clareia o fundo de perigo no escuro). Adotado o M3 por coerência com o que esta casa já pratica. Descartados com número: cinza-900 (5,03) e turquesa-900 (4,92). Regra completa no seed-tokens.md §5-c.

Guarda: contrato MR2, no mesmo guarda-tinta-marca.mjs, com a superfície sob exame parametrizada. 22 PASS · 0 FAIL · 74 [n/a], 50 textos sobre o destrutivo, zero violando. Prova de reprovação com o caso fundador: devolvida a tinta literal, reprova 6; revertido, aprova.

64.15.3 CC-P3 ✅ FECHADA — a isenção que a norma nomeia#

A SC 1.4.3 isenta "texto que faz parte de um componente de interface do usuário INATIVO". As duas guardas de contraste não conheciam a isenção e reprovavam 9 botões disabled da galeria de estados. Agora a sonda descarta folha dentro de :disabled/[disabled]/[aria-disabled="true"] e imprime a contagem — isenção que não aparece no placar é a mesma doença da truncagem silenciosa.

64.15.4 A regeneração das nove bancadas: a pergunta virou MEDIDA#

O §64.14.8 mandava a regeneração a gate porque ela levou .vh em fixed e z-index 9000. Medido: excesso horizontal 0 px a 390 e a 320, antes e depois, e diferença pixel a pixel de 0 em 163.800 em três bancadas. A mudança é provadamente invisível e não precisa de olho humano.

64.15.5 TK-P1 (nova) — o rótulo do degrau sobre o degrau#

Na galeria de rampa do banco-tokens.html, 12 rótulos por tema ficam abaixo do piso: vermelho-500 3,38 · cinza-500 3,38 · dourado-500 4,01 · amarelo-500 4,08. A única tinta que resolve os quatro é o preto puro (4,89 · 6,21 · 6,02 · 6,17), que não existe em nenhuma rampa da SEED. Alternativa: mover o rótulo para fora do degrau. Pergunta de DESENHO — achado, não veredito.

64.15.6 Pendências#

# Estado em 2026-08-18 (v1.07)
AD-P1 FECHADA por pesquisa e execução, com guarda MR2
CC-P3 FECHADA nas duas guardas
Gate da regeneração RESPONDIDO por medição (0 pixels de diferença)
LS-P6 · TK-P1 ABERTAS — as duas são de DESENHO e vão a gate com imagem
GT-P6 · CC-P2 · CC-P1 · CD-P9 · CD-P10 · BT-P5 · AC-P1 · AC-P2 · CD-P6 · E-P2 ABERTAS
SI-P4 · IL-P2 · PS-P5 · spec do .ent DECIDIDAS, execução pendente

64.16 O GATE VISUAL REVERTEU a MR-P1, e a reversão melhorou o número (2026-08-18, v1.08)#

Supersede o §64.15.2 e a linha da MR-P1 no §64.14, no ponto em que mandam tinta ESCURA sobre a marca. Relato completo no validacao/MANIFESTO.md §88; regra vigente no seed-tokens.md §5-d.

64.16.1 A forma nova: turquesa-600 com texto BRANCO#

Verbatim do Rafael: "ter o turquesa com o texto Branco dentro no tema claro é algo visualmente bonito… vamos manter o texto branco." Com o branco fixado, a pergunta passou a ser a superfície: branco sobre turquesa-400 mede 2,71; sobre turquesa-600 #098475, 4,60. Escolhida a segunda.

Nascem --seed-surface-brand-strong (#098475, igual nos dois temas) e --seed-text-on-brand-strong (#FFFFFF, igual nos dois temas), gêmeos v1.17. surface-brand continua #11B0A0 e fica reservada para área SEM texto funcional — é a âncora visual, não a superfície de rótulo. Fronteira do controle (SC 1.4.11, piso 3,00) medida: 4,60 no claro, 4,05 na página escura, 3,31 na superfície elevada escura.

Migração: 19 regras em 9 arquivos, por regra CSS; 17 geradores com os nomes novos; 19 artefatos regerados com pré-voo. Depois: zero regras põem texto sobre a chapada. Guarda: contrato MR3, 21 PASS · 0 FAIL · 75 [n/a], 65 textos, duas execuções idênticas.

A referência de mercado foi MEDIDA e reprova: o botão primário do ClickUp usa #12a594 com branco a 12px/500 = 3,07. Referência é prova de prática, não de conformidade.

64.16.2 LS-P6 ✅ FECHADA — o problema era maior que a pergunta#

Medido antes, em 17 larguras de 320 a 1440px: a barra de seleção em massa cobria conteúdo nas 17, com 177 sobreposições somadas. A altura dela varia de 98 a 218px conforme os botões quebram, contra reserva fixa de 72px — reserva por constante teria de ser 230px e erraria em 15 das 17 larguras. Conserto na causa: a barra sai de absolute e entra no fluxo como sticky; abaixo de 768px, onde passa de 218px, deixa de flutuar (static). Depois: 0 sobreposições nas 17, visibilidade idêntica.

64.16.3 TK-P1 ✅ FECHADA — e eram seis degraus, não quatro#

Tinta preta nos degraus médios das seis rampas: vermelho 3,38→4,89 · cinza 3,38→6,21 · dourado 4,01→6,02 · amarelo 4,08→6,17 · turquesa 4,20→6,51 · azul 4,13→6,33. A opacidade dos rótulos saiu, porque reduzia o contraste renderizado sem aparecer na medida da cor declarada. O preto puro entra no acervo só aqui, como tinta de rótulo de galeria.

LIÇÃO DE LEITURA DE PLACAR: a primeira rodada consertou quatro porque a guarda imprimia "CORTADA em 8 de 12" e eu trabalhei sobre os oito visíveis. O corte estava declarado e mesmo assim me pegou. Placar cortado é placar incompleto — quem erra na leitura é o leitor.

64.16.4 SEIS pendências novas, de artefatos que nunca tinham sido medidos#

A pergunta "isso pega em outro lugar?" virou varredura dos 9 artefatos nunca medidos pelo contraste-composicao.mjs. O padrão do TK-P1 é exclusivo do banco-tokens.html (1 de 34). Mas apareceram 8 casos de componente, todos anteriores a esta semana:

# Onde Mede
SU-P1 banco-superficies, descrição de card sobre superfície de ação 1,69 claro · 1,02 escuro (invisível)
CP-P5 banco-composicao escuro, 8× chip de anotação 3,31 — a tinta de marca não clareia
FF-P1 banco-formfield, legenda de grupo sobre superfície de ação 3,02 · 3,81
FB-P1 banco-feedback escuro, badge de contagem 2,76 — é o par da AD-P1, fecha com o token existente
DD-P1 banco-dados claro, 3× badge "Aprovada" 4,28
DI-P1 banco-dataviz-di claro, 2× rótulo "CSS" 4,30

64.16.5 Pendências#

# Estado em 2026-08-18 (v1.08)
MR-P1 FECHADA na forma da opção B. Supersede o §64.15.2
LS-P6 · TK-P1 FECHADAS, as duas por decisão no gate visual
SU-P1 · CP-P5 · FF-P1 · FB-P1 · DD-P1 · DI-P1 (novas) ABERTAS, §64.16.4
GT-P6 · CC-P2 · CC-P1 · CD-P9 · CD-P10 · BT-P5 · AC-P1 · AC-P2 · CD-P6 · E-P2 ABERTAS
SI-P4 · IL-P2 · PS-P5 · spec do .ent DECIDIDAS, execução pendente

64.6 Pendências#

# Pendência Por que fica aberta
BT-P1 RE-gate visual das três bancadas nas versões desta rodada — banco-escolha v0.4, banco-data v0.4, banco-prioridade v0.2 Os consertos foram medidos, não vistos. Quem reprovou a v0.1 do calendário foi o olho, não o placar (§61.7). Nada promove antes
BT-P2 BT1 nas TELAS, não só nas bancadas FECHADA no mesmo dia, por decisão do Rafael. Verbatim: "todo material que você produzir tem que ter a barra fixa, todos você já tem essa opção, só não é fixo". Aplicada e MEDIDA em nove telas (tela-painel, lista, tabela, detalhe, quadro, gantt, shell, chat, referencia) mais banco-dominio: depois de rolar, a barra mede top=0, position=sticky, altura 66px e não é coberta por nenhum elemento em nenhuma das dez. Suítes reexecutadas: painel 146·0 · detalhe 73·0 · quadro 35·0 · gantt 43·0 · shell 72·0 · composição 33·0 · contêiner 66·0 · domínio 28·0. Fica aberto só o tela-site.html, que não estava nesta cópia de trabalho
E-P1 O BT7 vale para os artefatos de E-MAIL? — sem veredito Os 8 artefatos (et-*, en-*, ea-*, seed-email-*) não foram medidos: a suite-reflow.mjs varre só banco-* e tela-*, e a suite-email.mjs não rodou porque os alvos não estavam na cópia de trabalho. Ausência de medição, não aprovação. E-mail tem outra régua — tabela de layout, cliente sem CSS moderno, sem container query —, então estender o filtro por conta própria seria decidir sem rodada. Precisa do RITO de 3 rodadas
BT-P3 Levar a guarda GI2 (forma 4) às suítes antigas — suite-painel, suite-container, suite-dominio, suite-icones Hoje ela roda em suite-escolha, suite-data e suite-prioridade. As antigas usam puppeteer-core. Atualização 2026-08-17: o bloqueio de ambiente CAIU. Elas rodam neste contêiner (suite-container 66·0, render-painel 37·0); bastou um shim local para o @sparticuz/chromium, pacote que existe só para devolver o caminho do binário do Chrome e cujo download real passa de 100 MB. O shim não muda nenhuma medida e vive em node_modules, nunca na pasta. Sobra trabalho de portabilidade, não risco
BT-P4 Levar o BT7 ao resto do sistema — ✅ FECHADA em 2026-08-17 (v0.99) A varredura (validacao/suite-reflow.mjs) cobre hoje 34 artefatos e mede 120 PASS · 0 FAIL · 34 [n/a]. Os SEIS que restavam foram fechados em duas levas. (1) tela-quadro (89px) e tela-gantt (65px) pelo mesmo conserto do .vh: texto visualmente oculto em position:absolute sem ancestral posicionado ancora no body, toma a coordenada rolada dentro de uma faixa que rola e estende o scrollWidth do documento — medido right=479 num viewport de 390 e right=385 num de 320; virou position:fixed, conserto de causa que curou as duas telas de uma vez. (2) Conserto próprio, cada um com a alternativa descartada registrada no validacao/MANIFESTO.md §79.3: tela-referencia (84px · .busca com flex:1; max-width:520px e sem min-width:0, piso de conteúdo medido em 187px → topbar que quebra abaixo de 640px), tela-painel (35px a 320 · .escala-ctrl inline-flex sem quebra, 307px num pai de 224px → flex-wrap), banco-tokens (27px a 390 e 97px a 320 · .type-row sem quebra, e 1fr — que é minmax(auto,1fr), com piso min-content — impedindo a célula da rampa de encolher abaixo de 60,81px num contêiner de 272px → minmax(0,1fr) mais recuo de 4px, folga medida de 1,6px) e banco-dataviz-di (61px · tabela de 4 colunas de dado cruzado dentro de um .nota de 302px, mais quatro <pre> que rolavam sem nenhum caminho de teclado → tabela em role="region" tabindex="0" aria-labelledby e <pre> com tabindex="0" + aria-label). O banco-dataviz-dp (7,5 MB) foi medido: o teto de 3 MB era estimativa ("levaria minutos"), e a medida real é 2,05 s para as duas larguras, com aprovação nos três contratos — teto elevado a 9 MB, ajustável por TETO_MB=<n>. Fronteira declarada: a varredura cobre banco-* e tela-*; os 8 artefatos de e-mail não entram e não têm decisão sobre o BT7 — pendência E-P1, ausência de medição e não aprovação.

64.17 O MEDIDOR ESTAVA ERRADO EM DOIS DE SEIS, e o conserto achou um token FANTASMA que matava o tema escuro (2026-08-18, v1.09)#

Leitor novo: esta seção fecha seis pendências de contraste que vinham da varredura dos 9 artefatos nunca medidos (§64.16 e MANIFESTO §88.8) e acrescenta uma regra de consumo que vale para toda bancada e toda tela. Registro completo, com as provas, no validacao/MANIFESTO.md §89.

CONTRATO NOVO — BT8. VALOR DE RESERVA EM var() É PROIBIDO PARA TOKEN DE COR.

Declaração honesta de estado: a BT8 está ESCRITA e ainda NÃO TEM GUARDA. A guarda é a pendência NV-02. Enquanto ela não existir, a BT8 é regra escrita e não medida — e regra sem instrumento não é contrato cumprido. O caso fundador dela já está medido e está abaixo.

PROIBIDO   color: var(--seed-action-primary-bg, #098475)
CERTO      color: var(--seed-action-primary)

O porquê, medido: o banco-formfield.html consumia --seed-action-primary-bg em 15 lugares. Esse nome não existe no gêmeo — o nome canônico é --seed-action-primary, sem o sufixo -bg. Como havia valor de reserva literal, o navegador pintou assim mesmo, com o turquesa escuro fixo nos dois temas. Consequência: o interruptor, o rádio, a caixa de seleção, o cartão de rádio, o controle deslizante e a área de arrastar arquivo nunca inverteram no tema escuro — seis componentes, e nenhum instrumento tinha visto, porque o defeito se disfarçava de acerto (com o fundo preso no escuro, a tinta branca media 4,60 e passava).

A regra em uma frase: token consumido e não definido tem de NÃO PINTAR. O valor de reserva é anestésico — ele esconde a lacuna em vez de denunciá-la. É a NV-01 vista pelo outro lado. Pendência NV-02: varrer os 34 artefatos atrás de var(--token, <literal>) cujo token não seja declarado. Ainda não rodada.

Assim que a superfície passou a inverter, apareceu o defeito que estava escondido atrás dela: três botões primários do mesmo artefato tinham color:#fff literal e passaram a medir 1,83 no escuro. Migrados para --seed-text-on-action-primary: 4,60 claro · 7,39 escuro.

AS SEIS PENDÊNCIAS, e o que cada uma era de fato

# Onde Era Virou Natureza
SU-P1 p.seed-card__desc · banco-superficies 1,69 · 1,02 7,75 · 8,11 FALSO POSITIVO — 26º defeito de instrumento
FF-P1 legend.seed-field__label · banco-formfield 3,02 · 3,81 13,86 · 14,16 FALSO POSITIVO — 26º defeito
FB-P1 .seed-badge--count · banco-feedback 2,76 escuro 5,19 · 5,26 real — tinta #fff literal sobre superfície que clareia
CP-P5 .tagok · banco-composicao 3,31 escuro 4,60 · 8,31 real — tinta saída da rampa, não do token semântico
DD-P1 .seed-badge.ok · banco-dados 4,28 claro 5,89 real — valor divergente do gêmeo
DI-P1 .amostra.via-css · banco-dataviz-di 4,30 claro 6,51 real — nenhuma tinta da casa passava

Duas nasceram e fecharam junto: CP-P6 (aviso vermelho com hex literal em atributo de estilo, 2,93 no escuro → --seed-feedback-danger-text) e FF-P2/FF-P3 (o token fantasma acima).

O QUE ISSO ENSINA SOBRE CONSUMO DE TINTA — três formas do mesmo erro, todas vistas neste dia

  1. Tinta literal (#fff, #C6393B em style=): não inverte, e some do alcance de qualquer guarda que procure token.
  2. Tinta de RAMPA (var(--seed-turquesa-600)): o degrau é fixo por definição; rampa é primitivo, não semântico. Quem carrega tema é o token semântico — aqui, --seed-text-brand.
  3. Tinta de token INEXISTENTE com reserva: pinta, engana e trava o tema (BT8 acima).

A regra positiva: toda tinta de componente sai de token SEMÂNTICO declarado nos DOIS blocos de tema do artefato. Se o artefato não declara o token, ele passa a declarar — não se inventa reserva.

PRECEDENTE APLICADO SEM RITO NOVO: o par do FB-P1 é o mesmo par que a AD-P1 resolveu com três rodadas em 2026-08-18. Rito não se repete para o mesmo par; repete-se a decisão, citando-a.

GATE: a folha visual desta edição é render-audit/gate-cc-v127/fechamento.html, com recorte antes/depois por elemento nos dois temas. Uma única pergunta aberta, e ela é de escopo de decisão já tomada: se o preto puro #000000 — liberado na TK-P1 para rótulo de galeria de cor — vale também para o rótulo "CSS" da figura de prova de impressão do banco-dataviz-di. As três alternativas da casa foram medidas e nenhuma passa: cinza-900 4,30, turquesa-900 4,20, branco 3,22, contra piso 4,50.

64.18 CONTRASTE FORÇADO — contratos FC1 e FC2, e a BT8 ganha guarda (2026-08-18, v1.10)#

Leitor novo: esta seção fecha a CD-P9 e a CD-P11 nos 34 artefatos do acervo e dá instrumento ao contrato BT8, que na §64.17 nasceu escrito e sem guarda. Registro completo, com as provas nos dois sentidos, no validacao/MANIFESTO.md §90.

CONTRATO NOVO — FC1. TODO CONTROLE TEM FRONTEIRA QUANDO O NAVEGADOR DESCARTA O PREENCHIMENTO.

Em forced-colors: active (o modo de contraste forçado do Windows e do Firefox) o navegador descarta background-color e box-shadow e impõe a paleta do usuário. Botão identificado apenas pelo preenchimento simplesmente desaparece.

CONTRATO NOVO — FC2. O FOCO CONTINUA VISÍVEL NO MESMO MODO. O anel de foco desta casa é --seed-focus-ring, que é box-shadow — e box-shadow é justamente o que o modo joga fora. Sem regra própria, o foco some em 100% dos controles.

A REGRA, e ela é uma só, idêntica nos 34 artefatos:

@media (forced-colors: active) {
  button, [role="button"], input[type="button"], input[type="submit"],
  input[type="reset"], summary, a.seed-btn, a[class*="btn"] {
    border: 1px solid ButtonText !important;
  }
  :focus-visible { outline: 2px solid Highlight !important; outline-offset: 2px !important; }
}

TRÊS DECISÕES DENTRO DELA, com o porquê:

  1. A fronteira vai por border; o outline fica reservado ao FOCO. Alternativa descartada — e ela era o conserto escrito na própria pendência CD-P9: outline: 1px solid transparent. Recusada porque em contraste forçado o outline é o único mecanismo que ainda funciona para indicar foco, e gastá-lo na fronteira deixaria o foco sem sinal. A pesquisa revogou o conserto que já estava escrito.
  2. !important é deliberado. .seed-btn{border:0} tem especificidade maior que um seletor de tipo; medido, sem ele a FC1 continuava reprovando.
  3. A lista de seletores é a MESMA do contrato FC1 na guarda. Regra e régua têm de olhar para o mesmo conjunto, senão uma cobre o que a outra não mede.

ONDE SE ESCREVE — e isto vale para QUALQUER mudança transversal daqui em diante:

tipo de artefato onde escrever por quê
gerado (19 dos 34) no molde (ou no gerador), e regerar com PRÉ-VOO escrever no artefato é desfeito na próxima regeneração
de mão (14 dos 34) no próprio arquivo não há molde
banco-dataviz-dp nos dois, e NÃO regerar o gerador dele não reproduz o artefato — pendência DP-P9

ARMADILHA DE MOLDE, medida: 6 dos 20 moldes passam por str.format() (shell, site, tela-chat, tela-lista, tela-referencia, tela-tabela). Neles toda chave literal { } tem de vir DOBRADA; sem isso o gerador morre com KeyError. Aconteceu nos seis, na primeira tentativa.

A PROVA DE QUE NÃO MUDA NADA FORA DO MODO: validacao/prova-inercia.mjs compara antes/ com a raiz pixel a pixel, nos dois temas, a 1440px e a 390px. Resultado: 0 de 13.176.000 pixels diferentes. Por isso esta mudança não foi a gate: não há o que julgar com o olho.

PLACAR, duas execuções idênticas cada:

antes depois
FC1 — controles ativos sem fronteira 408 de 1.336 0 de 1.336 (68 PASS · 0 FAIL · 24 isentos)
FC2 — controles focados sem outline 100% (o anel é box-shadow) 0 de 386 (68 PASS · 0 FAIL)

PROVA DE REPROVAÇÃO, com o caso fundador de cada cláusula: removido o bloco do tela-tabela.html, a FC1 reprova 22 controles sem fronteira; removido do banco-componentes.html, a FC2 reprova 10 de 12 focados. E note: o primeiro caso fundador que tentei para a FC1 — o banco-componentespassou sem o bloco, porque os botões dele já tinham borda. Caso fundador é o artefato onde o defeito EXISTE, não um qualquer que se tenha à mão.

A BT8 GANHA GUARDA — validacao/guarda-valor-reserva.mjs, contrato NV1. Duas cláusulas: NV1-a reprova var(--x, …) com --x nunca declarado (token FANTASMA); NV1-b emite [achado] para reserva de cor sobre token que existe. Placar do acervo: 10 PASS · 0 FAIL · 0 [achado] · 86 [n/a] — zero fantasmas e zero reservas de cor. Dois fantasmas reais foram achados e consertados na causa: o ponto de presença do banco-pessoa pintava com a superfície de AÇÃO em vez da de SUCESSO (idênticas no claro, #66D1C2 contra #11B0A0 no escuro), e o banco-prioridade consumia --seed-radius-md sem declarar.

Também cita o §64: banco-texto-rico.

Esc