Ir ao conteúdo
SEED engenhariaDesign System

Componentes

72. SH1 — COLISÃO, COBERTURA, CORTE e VAZAMENTO

seed-componentes.md v1.43 · §72seção 78 de 9872-sh1-colisao-cobertura-corte-e-vazamento-regra.md · MD5 2d2772f3

Título completo no canon: SH1 — COLISÃO, COBERTURA, CORTE e VAZAMENTO · regra transversal (2026-08-19, sétima e oitava partes) · validacao/guarda-colisao.mjs · FECHA a SH-P3

Escrito em 2026-08-19. Fecha a pendência SH-P3, aberta havia quatro partes, que dizia: "nenhum instrumento mede COLISÃO — sobreposição de elementos irmãos dentro de uma barra que não estoura o documento. O SH-P2 foi achado por captura e olho, não por guarda."

72.1 Por que a guarda de reflow não bastava#

A suite-reflow.mjs (contrato BT7) mede se o documento estoura na largura. Mas conteúdo pode encavalar sem estourar largura nenhuma: a barra continua com 1440px, o documento não tem rolagem horizontal, e dois irmãos dentro dela estão um em cima do outro. Guarda que mede o continente não mede o conteúdo.

72.2 A base normativa — e aqui, ao contrário do HV1, ela é direta#

fonte formulação
Understanding da SC 1.4.12 Text Spacing "Overlapping text is a failure" · "Text Cut Off — the bottom portion of the words is cut off ... making that text unreadable"
F104, falha técnica da WCAG 2.2 "part of the content clips and is unreadable when the user overrides the spacing of the text"
SC 1.4.10 Reflow "no loss of content or functionality" — e isenta explicitamente "parts of the content which require two-dimensional layout", sendo tabela de dados o exemplo canônico da própria norma

Consequência de alcance: colisão não é questão de gosto nem de conveniência de layout. É perda de conteúdo, e perda de conteúdo é falha normativa. Por isso SH1 reprova, não "acha".

72.3 O contrato#

# Cláusula Régua
SH1-a Irmãos em fluxo não se sobrepõem dois filhos do mesmo pai, ambos visíveis e em fluxo normal, com caixas de LINHA que se cruzam em área > 1px²
SH1-b Texto visível não fica coberto elementFromPoint no centro do nó de texto tem de devolver ele mesmo, um ancestral ou um descendente. Terceiro que pinta → FAIL; terceiro transparente[achado]
SH1-c Texto não é cortado em silêncio conteúdo que transborda a caixa no eixo que esconde, com um nó de texto de fato passando do recorte. text-overflow: ellipsis é ISENTO e CONTADO
SH1-d O conteúdo não vaza da própria caixa o retângulo de um nó de texto excede a caixa de padding do elemento por mais de 1px, e esse elemento tem FRONTEIRA VISÍVEL (borda, fundo pintado, ou é controle interativo). Nasce em 2026-08-19, oitava parte

Por que a SH1-d precisou nascer, e por que ela não é uma variação da SH1-c: o Rafael anexou um recorte a 390px com duas setas vermelhas sobre os botões "Anterior" e "Próximo" do tela-gantt e escreveu — "o nome dentro do botão estoura para fora, isso tem solução?" Nenhuma das três cláusulas anteriores pegava aquilo: não é colisão entre irmãos, não é texto coberto, e não é texto cortado, porque o overflow é visible e o texto fica perfeitamente legível — só está do lado de fora da caixa que deveria contê-lo. A SH1-c mede o que o recorte ESCONDE; a SH1-d mede o que a caixa NÃO SEGURA. São defeitos opostos com a mesma causa — conteúdo maior que a caixa — e um instrumento que só olhasse overflow:hidden seria estruturalmente cego para metade do problema. A fronteira visível é o corte que dá sentido à cláusula: texto que passa da caixa de um div transparente é layout normal e ninguém vê; texto que atravessa a borda de um botão salta aos olhos.

72.3-a A causa do defeito fundador: duas regras boas que, juntas, produzem uma ruim#

Medido no tela-gantt a 390px: caixa de conteúdo 50×42, texto 56×14 → vaza 6px. E a 1440px sob o espaçamento da SC 1.4.12: caixa 49×42, texto 67×14 → vaza 6px à esquerda e 12px à direita. O defeito existia nas duas larguras — ele viu na estreita.

A causa é uma armadilha clássica de flexbox, e vale escrita porque vai reaparecer:

  1. display:flex dá ao item flex-shrink: 1 por padrão — o item pode encolher;
  2. o min-width: auto, que normalmente protege o item de encolher abaixo do próprio conteúdo, foi substituído por min-width: 44px, que é o piso de ALVO da SC 2.5.8;
  3. com 44px valendo como mínimo e o encolhimento ligado, a caixa fica menor que o texto; e como overflow é visible e "Anterior" é palavra única sem ponto de quebra, o texto sai por fora.

A lição: o piso de alvo, escrito como min-width, desligou sem querer a proteção que o flexbox dava de graça. Duas regras corretas, cada uma defensável, produziram um defeito na interseção. Nenhuma revisão de uma regra por vez encontraria isso — só a medição do resultado.

O conserto, em duas linhas: flex-wrap: wrap no pai (se a linha não couber, os botões descem) e flex: 0 0 auto nos botões (nunca encolhem abaixo do conteúdo). O alvo de 44×44 segue garantido por min-width/min-height.

alternativa descartada motivo
overflow-wrap: anywhere quebraria "Anterior" no meio da palavra — resolve a geometria e piora a leitura
rótulo curto no mobile ("Ant." / "Próx.") degrada o nome acessível e o entendimento
font-size menor fura a escala tipográfica e o piso de legibilidade
overflow: hidden no botão transformaria vazamento em CORTE — o defeito oposto e pior, e a própria SH1-c reprovaria. Esconder o sintoma no eixo errado não é conserto

Dois espaçamentos, e o placar separa os dois: padrao (o artefato como é) e 1412 (o override da SC 1.4.12: line-height: 1.5, letter-spacing: .12em, word-spacing: .16em, 2em depois de parágrafo, todos !important porque o usuário os aplica por folha de usuário). Antes desta guarda, nenhum instrumento do acervo media essa dimensão.

72.4 SETE defeitos de instrumento numerados (mais dois sem número), todos de FALSO POSITIVO, todos com fixture#

A primeira execução acusou 398 colisões, 122 textos cobertos e 304 textos cortados. Depois de sete consertos de régua — nenhum de artefato — o acervo saiu com 0 · 0 · 0 · 0 a 1440px. Falso positivo de guarda nova quase nunca é bug de código: é a régua medindo uma COISA DIFERENTE da que o contrato nomeia.

# defeito o que produzia, MEDIDO o conserto
caixa de inline multilinha getBoundingClientRect() de um inline devolve a união das linhas; dois <strong> em linhas diferentes têm uniões que se cruzam sem nada se sobrepor. 106 falsos strong × strong getClientRects(): uma caixa por linha, e a comparação é linha contra linha
34º <details> FECHADO tem retângulo e não tem pixel a tabela equivalente do banco-dataviz-dm, que existe para leitor de tela, saía 5× por passe como "th coberto por figure.seed-chart" Element.checkVisibility({checkOpacity, checkVisibilityCSS, contentVisibilityAuto}) + closest('details:not([open]))
35º elementFromPoint é HIT-TEST DE PONTEIRO, não teste de pintura o kbd do "Ctrl K", que é pointer-events:none desenhado por cima, saía 12× como coberto pelo botão texto sob pointer-events: none[n/a] nomeado
36º a técnica de leitor de tela É uma caixa de 1px com overflow:hidden SH1-c acusou 304 cortes, sendo 172 span.vh + 20 .visually-hidden + 12 .sr + 12 label.vlibras + 8 caption.vh recorteDeLeitor(): lado ≤2px, clip: rect(0 0 0 0) ou clip-path que zera
37º conteúdo ROLADO PARA FORA de overflow:auto tem retângulo dentro da janela e está recortado a célula #1208 do banco-dados em y=778, checkVisibility true, e o elementFromPoint devolvia a paginação. A captura mostrou: .seed-tablewrap é overflow-y:auto com clientHeight 420 e scrollHeight 465 — a linha está fora da vista, não coberta o retângulo do texto tem de estar dentro da caixa de todos os ancestrais que recortam
38º o eixo que ESCONDE tem de ser o eixo que TRANSBORDA o #quadro do tela-quadro é overflow: auto/hidden com excesso em X, onde o valor é autohá rolagem, o usuário alcança tudo — e reprovava por causa do hidden em Y medir o excesso por eixo, só onde aquele eixo esconde
39º clientWidth e clientHeight de elemento INLINE não-substituído valem ZERO a SH1-d acusou 168 vazamentos na primeira execução, e o censo mostrou 124 code + 24 kbd + 16 span.kbd + 4 span — todos inline com fundo e borda (os chips de código e as teclas de atalho desta casa). Com caixa de 0×0, qualquer texto "vaza" para o inline, a caixa certa é o próprio getBoundingClientRect() descontadas as bordas
40º opacity: 0 NÃO tira o elemento do hit-test visibility:hidden e display:none saem do elementFromPoint; opacity:0 não — o elemento continua ganhando o hit-test e simplesmente não pinta. E a função pinta() olhava cor de fundo, imagem e borda, não opacidade. Caso medido: o div#toast do banco-icones.html (position:fixed; bottom:16px; opacity:0, visível só 1,8s depois de um clique que a medição nunca dá) produziu 2 FAIL de SH1-b — mas só a 390×844; a 390×900, a altura canônica desta casa, a mesma caixa invisível cai 56px abaixo e o defeito não aparece opacidade acumulada pela cadeia de ancestrais (opacity compõe: pai a 0 zera filho a 1); se a efetiva é 0, sai [achado]"atrapalha o ponteiro, não a leitura", exatamente o tratamento que a guarda já dava ao fundo transparente
enfeite ≠ texto o section.hero do seed-design-system acusava 100px cortados em X, e o que transborda ali é o grafismo SH1-c exige que um nó de texto passe do recorte; se nenhum passa, sai [achado] enfeite transbordando

O 40º ensina uma coisa que os outros seis não ensinavam, e ela é sobre COMO se mede duas vezes. Ele só apareceu porque a segunda medição do acervo a 390px foi rodada com altura 844 em vez das 900 que todos os instrumentos desta casa usam. Rodar o mesmo comando duas vezes não é medir duas vezes — é obter o mesmo número duas vezes. Medir duas vezes é variar uma dimensão e ver se a conclusão sobrevive. A divergência bruta foi 8 FAIL a 390×844 contra 6 FAIL a 390×900, e a explicação da diferença era defeito de instrumento, não diferença de artefato. Depois do conserto as duas alturas concordam em 198 PASS · 6 FAIL, e a 844 sai com 2 [achado] a mais — o toast invisível, agora classificado pelo que ele é.

72.5 DECLARAÇÃO COM SAÍDA VERIFICADA — o mecanismo que distingue defeito de desenho#

Duas situações do acervo são legítimas e, para uma guarda que só olha pixel, idênticas a defeito:

  1. o painel de chat do tela-chat SOBREPÕE a tabela de propósito. O contrato CH3 do §55 diz, com estas palavras: "o painel é PEÇA e SOBREPÕE: ele não empurra o miolo, a tela de trabalho não pode refluir toda vez que alguém pergunta alguma coisa" — e há um botão que o recolhe.
  2. a régua do tela-gantt é RECORTADA por overflow:hidden e acompanha, por sincronização, a área de plotagem, que o usuário rola.

A saída não foi afrouxar a régua nem escrever uma lista de exceções à mão — lista escrita à mão mede a lista, não o acervo. Foi exigir que o artefato declare, e que a declaração nomeie a saída:

atributo contrato o que a guarda VERIFICA
data-sobrepoe="declarado:<id>" "eu cubro isto de propósito, e #<id> recolhe" que #<id> exista, esteja visível, seja focável e não esteja desabilitado
data-recorte="sincronizado:<id>" "eu recorto, e #<id> rola para revelar" que #<id> exista, esteja visível, role de fato no eixo que esconde e seja alcançável por teclado (tabindex ≥ 0)

Declaração sem saída verificável NÃO isenta: reprova, com esse motivo. É o oposto de aceitar um comentário no código — comentário não tem como ser medido, e um id tem. É o mesmo princípio que a CT1 usa com justify-content: space-* e a SH1-a usa com margem negativa: guarda não discute decisão declarada — mas a decisão tem de estar declarada em algo que a máquina leia.

72.6 O que a execução tocou, e o placar#

# arquivo mudança por quê
1 tela-chat-template.html <aside class="chat peca" data-sobrepoe="declarado:b-recolher"> a sobreposição é o contrato CH3, e o #b-recolher é a saída
2 tela-gantt-template.html <div class="gt-plot" data-recorte="sincronizado:gtArea"> a régua acompanha #gtArea, que é overflow:auto e tabindex="0"
3 tela-chat-template.html · tela-gantt-template.html .conteudo passa de overflow-x: hidden a overflow-x: auto a 390px o miolo tinha 366px de caixa e 416px de conteúdo, e o rótulo "Valor" ficava 22px fora, inalcançável. A SC 1.4.10 ISENTA tabela de dados da exigência de caber em uma coluna — logo a solução que a norma PRESCREVE é deixar rolar. Alternativa descartada: encolher a tabela abaixo da largura mínima das colunas — medido, isso produz corte DENTRO das células, a mesma perda com outro nome
4 seed-design-system.html .ig-post e .ig-story passam de overflow: hidden a auto sob o espaçamento da SC 1.4.12, a cópia do story passava 57px do recorte e a do post 26px. auto porque estes cartões ILUSTRAM peça de 1080×1080 e 1080×1920: a proporção é a informação, e crescer a caixa mentiria sobre o formato da plataforma. No espaçamento padrão nada muda — não há excesso, logo não há barra
5 seed-design-system.html .feature-tile recebe overflow-wrap: anywhere a 390px a caixa tinha 106px e o conteúdo 121px, e "Subestações MT" saía 15px fora. Alternativa descartada: overflow: auto, que poria barra de rolagem dentro de um cartão de 106px — pior de ler que a palavra quebrada

| 6 | tela-gantt-template.html | .gt-nav ganha flex-wrap: wrap e os botões flex: 0 0 auto | SH1-d: os rótulos "Anterior" e "Próximo" vazavam 6px da borda a 390px e até 12px a 1440px sob o espaçamento da norma |

PLACAR a 1440px, com as QUATRO cláusulas: 204 PASS · 0 FAIL · 0 [n/a] — 51 arquivos × 2 temas × 2 espaçamentos · 96.000 pares de irmãos comparados · 9.826 nós de texto testados por hit-test · 9.456 caixas com fronteira visível · 0 colisões · 0 textos cobertos · 0 textos cortados · 0 textos vazando · 40 [achado], todos nomeados. A 390px: 198 PASS · 6 FAIL — os 6 são a pendência SH-P8, e SH1-d sai ZERO nas duas larguras. Este placar de 390px foi confirmado em duas alturas de janela, 900 e 844, e as duas dão o mesmo número depois do conserto do 40º defeito: 198 · 6. Os 6 são 2 de SH1-b no banco-navegacao (só no espaçamento padrao: o botão de rolagem da faixa de abas cobre a aba "Equipamentos") e 4 de SH1-c no tela-tabela (nos dois espaçamentos: main.conteudo tem caixa de 366px e conteúdo de 810px, e o rótulo "Responsável" passa 6px do recorte no espaçamento padrão e 35px sob o da norma).

72.7 Pendências#

# Pendência Por que fica
SH-P8 A 390px sobram 6 FAIL, em 2 arquivos e 2 classes de causa, medidos e confirmados nas alturas 900 e 844: (a) banco-navegacao, 2 FAIL de SH1-b só no espaçamento padrao — o button.seed-tabscroll da faixa de abas cobre o rótulo "Equipamentos" do button.seed-tab#tab-equip no ponto (353,382); (b) tela-tabela, 4 FAIL de SH1-c nos dois espaçamentosmain.conteudo tem caixa de 366×786 e conteúdo de 810×786, e o nó de texto "Responsável" passa 6px do recorte no padrão e 35px sob o espaçamento da SC 1.4.12 É trabalho de layout móvel, não de instrumento — e é o tipo de conserto que muda composição aprovada em gate. ⚠ No tela-tabela o conserto óbvio já foi tentado e REVERTIDO: pôr overflow-x:auto no main.conteudo viola a cláusula RF-02 da suite-container ("região focável e nomeada") e a BT7-teclado da suite-reflow ("região que rola e NÃO se alcança sem mouse"). O conserto certo é o mesmo que o tela-chat recebeu — envelope role="region" tabindex="0" com nome em volta da tabela — e ali exige composição, porque a tabela do tela-tabela não é um bloco isolado
SH-P4 sobreposição entre elementos que não são irmãos só é vista pela SH1-b, e só onde há texto no ponto testado geometria entre não-irmãos exige comparar árvore inteira contra árvore inteira
SH-P5 a SH1-b testa um ponto por nó de texto — o centro texto coberto pela metade, com o centro livre, passa
SH-P6 a largura de 320px da SC 1.4.10 não entra ainda é a largura em que a norma exige que nada se perca
SH-P7 a guarda verifica que a saída declarada existe e é operável, não que ela revele aquele conteúdo provar isso exige clicar na saída e re-medir — é o próximo degrau de rigor





*Estrutura da Fase 3 (7 blocos, reescopada em 2026-07-31 — ver seed-ds-roadmap.md): 1 — Botões ✅ v0.5 (+full-width v0.7) · 2 — Formulários ✅ 13/13 (v0.14) · 3 — Feedback e status ✅ 11/11 (v0.24) · 4 — Superfícies ✅ 7/7 (v0.32: §26–§32) · 5 — Navegação (+ ⌘K) · 6 — Dados (+ pendências: densidade ERP→mobile; barra composta EUI; selecionar-tudo indeterminate §10) · 7 — Iconografia ✅ 1/1 (§45 estável v0.47 — set canônico de 28 glifos). Pattern F6: §33 Central de Notificações ✅ estável (v0.34). Bloco 5 — Navegação ✅ FECHADO 6/6 (v0.41). Bloco 6 — Dados ✅ FECHADO 5/5 (v0.45): §40 tabela · §41 seleção · §42 toolbar · §43 lista de dados · §44 guia de integração. Componente futuro fora dos blocos: editor rich-text (F6). Fase 6 (patterns de produto e marketing), aberta em 2026-08-11: bloco 6A — §46 Shell de aplicação ✅ estável (FECHADO) → bloco 6B — §47 Página institucional ✅ estável (FECHADO 2026-08-12, MK1–MK22 em dois lotes, preview e gate únicos) → bloco 6C — §48 Painel: grade, lentes, frescor, edição direta e mapa ✅ estável (FECHADO 2026-08-13 — FASE 6 a 3/3), com PN1–PN54; oito lentes, camada visual PN21a–h, edição direta PN22–PN41 sob o SC 2.5.7, contratos do gate PN46–PN50, mapa em dois modos PN51–PN54; PN42–PN45 reservados ao 6D; dez supersedes formais em §48.8 e sete pendências em §48.9; preview v0.8 com cinco camadas verdes: 139 · 37 · 142 · 6 · 78 + gate visual do Rafael; INVERSÃO DO HERO em 2026-08-13: a âncora passa de azul-800 a turquesa-400 #11B0A0, a ação volta à família da marca e o S4 é RETIRADO — o conflito com o §3.5 de marca-seed.md deixa de existir. Segue proposta apenas a tinta da família (S6): pendência PN-P1). O preview e o gate visual do 6C são únicos, no fim. Patterns F6 já estável: §33 Central de Notificações. Fase 7 (cobertura, aberta em 2026-08-15 a partir do mapa-cobertura-ds.md): F7.1 fundação ✅ (seed-composicao.md v2.0: sete tipos de bloco, CP25–CP31, 23 gabaritos, renomeação bancada×tela) → F7.2 TELAS DE DADO — §50 agrupamento de linhas · §51 personalização de colunas · §52 árvore · §53 filtro composto, mais as extensões DT9–DT12, SL6–SL8, TD6 e LD6, todas em rascunho até o gate visual; gabaritos tela-tabela.html (A3) e tela-lista.html (A2). F7.3 REGISTRO — §49 Detalhe de registro (PD1–PD18, gabarito A8 tela-detalhe.html, fecha a PN-P3) e §55 Chat (CH1–CH14, arquétipo A23) — primeira spec do projeto escrita a partir de LEITURA VISUAL do produto de referência (§13 do estudo-clickup-completo.md, dispositivos C41–C49) em vez de extração de valores. As sete fases e o inventário de cobertura vivem no mapa-cobertura-ds.md. F7.5 COBERTURA DE CONTROLES: §59 valor de domínio · §60 escolha segmentada e múltipla (estável) · §61 data, intervalo e hora · §62 seletor de pessoa (bancada banco-pessoa.html, 44 · 0 · 1) · §63 prioridade e escalas ordinais · §64 bancada e tema — BT1–BT6, transversais.


Esc