---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 72
titulo: "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**"
sequencia: 78 de 98
bytes_do_corpo: 21107
md5_do_corpo: 2d2772f349b02f7335f266cca7b65be7
gerado_por: 06-validacao/geradores/gen-camada-ia.py
nota: fatia GERADA — o corpo abaixo é byte a byte o trecho do canônico; edite o canônico, nunca esta fatia. Canônico inteiro em https://ds.seed.eng.br/01-canonicos/seed-componentes.md
---
## 72. 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 é `auto` — **há 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çamentos** — `main.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**.**

---

