---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 60
titulo: "Escolha segmentada e múltipla — **`estável`, SG1–SG14 e SG6-b** (F7.5, 2026-08-16) · **validado pelo Rafael em 2026-08-16** na v0.3 · **RE-GATE OBSERVADO em 2026-08-17 na v0.4: a BT-P1 FECHA — insumo nomeado, ver §64.10.1** · fecha C3 e C12 · bancada `banco-escolha.html` **v0.4** · quatro camadas verdes: `suite-escolha` **238 · 0 · 29 [n/a]** em cinco alvos · `suite-painel` **146 · 0** · `contraste-painel` **78 · 0** · `suite-container` **66 · 0** · **SEM PENDÊNCIA ABERTA — dez fechadas em 2026-08-16**"
sequencia: 66 de 98
bytes_do_corpo: 41456
md5_do_corpo: 2d07c038849905fcd3685f5063f62981
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
---
## 60. Escolha segmentada e múltipla — **`estável`, SG1–SG14 e SG6-b** (F7.5, 2026-08-16) · **validado pelo Rafael em 2026-08-16** na v0.3 · **RE-GATE OBSERVADO em 2026-08-17 na v0.4: a BT-P1 FECHA — insumo nomeado, ver §64.10.1** · fecha C3 e C12 · bancada `banco-escolha.html` **v0.4** · quatro camadas verdes: `suite-escolha` **238 · 0 · 29 [n/a]** em cinco alvos · `suite-painel` **146 · 0** · `contraste-painel` **78 · 0** · `suite-container` **66 · 0** · **SEM PENDÊNCIA ABERTA — dez fechadas em 2026-08-16**

> **Rodada zero.** Os dois itens **TÊM** leitura visual, e ela é recente: **C114** (§14) — segmentação
> por estado como **par de pílulas com contagem**, `1 On-line · 7 Off-line`, adjacentes, a ativa com
> fundo, *não é filtro em barra, é recorte binário do mesmo conjunto* · **C63** — escopo como filtro
> na sidebar, com contagem · **C74** — cada widget tem toolbar própria, com **chips de filtro
> removíveis**. Não é preciso navegar.
>
> **E esta seção tem uma particularidade: ela chega DEPOIS dos consumidores.** O §48 já usa
> segmentação para trocar de lente, o §56 usa um interruptor "só comentários", o §53 usa chips de
> filtro. Os três funcionam — e nenhum tinha spec. *É o inverso do §54, que existiu como artefato
> sem seção; aqui a seção chega para nomear o que três artefatos já fazem, e a primeira coisa que
> ela faz é medir se eles fazem a mesma coisa.*
>
> **Base (3 rodadas, 2026-08-16). E o achado da R1 é uma DIVERGÊNCIA DE CANON.** Cinco fontes de
> peso dão **quatro semânticas diferentes** para o mesmo componente:
> **(a)** o **Primer** diz explicitamente para **não** tratar como `radiogroup` — *radiogroup requer
> um botão de salvar* —, usa botões com Tab entre eles e **setas que não movem foco**;
> **(b)** o **useUI** manda `role="radiogroup"` + `role="radio"` + `aria-checked`, com **um único tab
> stop** e setas movendo dentro — *"o grupo é um radiogroup, não um tablist: não há painéis aqui, e
> prometer painéis enganaria a tecnologia assistiva"*;
> **(c)** o **Workday** usa **toggle button** com estado pressionado;
> **(d)** o **eBay** usa botões comuns no tab order com **`aria-current`**, avisando que *segmented
> buttons não são substitutos de abas e não operam como abas*.
> O **React Aria** confirma a fronteira útil: se a escolha **troca a vista do mesmo conteúdo**, use
> grupo de alternância ou radiogroup; se **troca o conteúdo**, use abas.
>
> **R3 normas:** o estado selecionado precisa se distinguir **por mais que cor** — diferença de
> valor claro/escuro é o que sobrevive à deficiência de visão de cores.

### 60.1 A decisão que a divergência obriga: TRÊS SAÍDAS, com régua

Não há "o jeito certo" no canon. Há três problemas diferentes que a mesma forma visual serve, e a
semântica tem de seguir o **problema**, não a aparência.

| Se o controle… | Então é… | Semântica |
|---|---|---|
| **troca a VISTA do mesmo conteúdo**, com 2 a 5 opções mutuamente exclusivas, aplicando na hora | **segmentado** (SG1) | `role="radiogroup"` + `role="radio"` + `aria-checked`, **um tab stop** e setas dentro |
| **liga e desliga um recorte** do mesmo conjunto (binário) | **interruptor de recorte** (SG2) | um `<button>` com `aria-pressed` |
| **troca o CONTEÚDO** e tem painel associado | **abas** (§34) | `tablist`/`tab`/`tabpanel` — e **não** é este componente |

> **A régua em uma frase: pergunte o que muda.** Muda a **forma de ver** o mesmo dado → segmentado.
> Muda **quanto** do mesmo dado aparece → interruptor. Muda **o dado** → abas.
>
> **Por que descartamos a saída do Primer** (botões com Tab entre eles): num quadro com quatro
> lentes, quatro tab stops custam quatro pressionamentos para atravessar um controle só — e o
> próprio canon avisa que *um controle de quatro opções não deve custar quatro pressionamentos para
> ser ultrapassado*. **Por que descartamos `aria-current`** (eBay): ele diz "este é o atual" sem
> dizer que os outros são **escolhas**; `aria-checked` num radiogroup diz as duas coisas.
>
> **O alerta do Primer, porém, entra como contrato (SG4):** radiogroup em formulário sugere que a
> escolha só vale ao salvar. Aqui **a escolha aplica na hora**, e isso precisa estar dito no nome do
> grupo — não implícito.

### 60.2 Os contratos

| # | Contrato | O que ele descarta, e por quê |
|---|---|---|
| **SG1** | **Segmentado é `radiogroup` com um único tab stop** e setas movendo dentro (roving). **`<input type="radio">` nativo satisfaz o contrato** e é a forma PREFERIDA quando cabe — o roving, as setas e o `checked` vêm de graça do HTML; `role="radio"` + `aria-checked` + roving em JS é a forma para quando o nativo não cabe | Um tab stop por segmento. Quatro opções custariam quatro pressionamentos para atravessar |
| **SG2** | **Recorte binário é um `<button>` com `aria-pressed`**, não um segmentado de duas opções | Segmentar "com/sem". Ligar e desligar é um controle, não uma escolha entre dois |
| **SG3** | **Nunca `tablist` sem painel.** Se não há painel, o papel promete o que não existe | `role="tablist"` por parecer aba |
| **SG4** | **O nome do grupo diz o que a escolha faz** ("Ver como", "Filtrar por") **e que ela aplica na hora** | Grupo sem nome. Sem ele, o leitor de tela anuncia as opções sem contexto — e o alerta do Primer sobre "salvar" fica de pé |
| **SG5** | **REVISTO 2026-08-16 · o teto é de APERTO MEDIDO, não de contagem.** O segmentado cabe enquanto a fileira, em toda largura de uso, **não vazar, não cortar e não reduzir nenhum alvo abaixo de 44px** — quebrar em mais de uma linha é permitido quando as opções são de mesma natureza. Passado esse ponto, `select`. O grupo precisa oferecer **Home e End**, que é o que impede a fileira longa de custar N setas | **DESCARTADO: o teto fixo de 5.** Ele foi violado pelo primeiro consumidor — as oito lentes do §48, `estável` e aprovadas em gate **três dias antes de o contrato existir** —, e mantê-lo exigiria converter pixel aprovado em `select` por uma regra que nasceu depois dele. Medido: 8 opções em 390/768/1180/1440px = 4/2/1/1 linhas, alvo mínimo 62×44px, sem vazar nem cortar |
| **SG6** | **REVISTO 2026-08-16 · o selecionado se distingue por diferença de VALOR MEDIDA ≥ 3,00** entre os dois fundos, não por matiz. O peso é reforço **opcional** | **DESCARTADO: exigir mudança de `font-weight`.** Ela altera a largura do texto e faz a fileira **refluir a cada seleção** — custo de layout real. Medido: 4,60 (lentes) e 4,57 (operador), ambos acima do piso 3,00 do SC 1.4.11 |
| **SG6-b** | **NOVO 2026-08-16 · e ele é a razão de o SG6 não ter sido simplesmente relaxado.** A separação tem de sobreviver a **`forced-colors: active`**, onde o agente de usuário SUBSTITUI `background-color` e `border-color`. O meio é **cor de sistema** — `Highlight` / `HighlightText` para o selecionado, `ButtonFace` / `ButtonText` para o repouso, com `forced-color-adjust: none` | **DESCARTADO: confiar no fundo da marca.** Medido antes do conserto: a separação cai de **4,60 para 1,00** e o selecionado fica **indistinguível** do repouso. Depois: **19,04**. *O SG6 original estava certo pelo motivo errado — dizia "não só cor" pensando em daltonismo, e quem cobra a fatura é o alto contraste* |
| **SG7** | **Contagem por segmento é opcional e, quando existe, conta o CONJUNTO — não muda com o filtro aplicado** | Contador que acompanha o próprio recorte. Herda o **CM11**: número que muda ao filtrar deixa de ser referência |
| **SG8** | **Segmento com ícone e rótulo visível usa SÓ o rótulo no nome acessível**; ícone sozinho exige nome próprio | Concatenar ícone e texto no nome |
| **SG9** | **Multi-select produz CHIPS REMOVÍVEIS**, cada um com nome que diz o que remove | Lista de marcados escondida atrás do gatilho. O chip é o que torna o filtro visível — e removível de um clique |
| **SG10** | **O chip de filtro é do §22, com o X interno em alvo de 44px** | Reinventar o chip |
| **SG11** | **Acima de um teto declarado, os chips colapsam em "+N"**, e o "+N" abre a lista completa | Vazar a linha. Herda o comportamento de excedente do §32 |
| **SG12** | **Remover um chip anuncia o que saiu e quantos restam** em live region | Remoção silenciosa |
| **SG13** | **"Limpar tudo" existe quando há dois ou mais chips**, e é a última ação da fileira | Limpar com um chip só: aí o próprio X já é o limpar |
| **SG14** | **Multi-select não fecha a lista ao escolher**; escolha única fecha | Fechar a cada marcação. Quem escolhe vários teria de reabrir a cada item |

### 60.3 Os consumidores — AUDITADOS (SG-P1, fechada em 2026-08-16)

Esta subseção nasceu, na v0.81, como uma lista de **três consumidores a verificar**. O que segue a
substitui: é o resultado medido. **Instrumento:** `validacao/suite-escolha.mjs` (nova nesta edição),
Chromium headless a 1440×900, sobre os quatro arquétipos que hoje têm controle de escolha.
**Placar: 52 PASS · 22 FAIL · 21 [n/a].** Decomposição por arquivo em §60.5.

A auditoria achou **seis controles em quatro arquivos** — não três em três. E a tabela original
errava em dois pontos, corrigidos aqui: apontava o **§53 para `tela-tabela.html`** quando o
construtor FC1–FC6 vive em **`tela-lista.html`**, e **não listava** os dois controles do
`tela-painel.html` que não têm marcação de "atual" visível ao instrumento antigo.

| # | Controle | Arquivo | Seção · estado | Forma medida hoje | Veredito |
|---|---|---|---|---|---|
| 1 | **Lentes** (8) | `tela-painel.html` | §48 · `estável`, gate 2026-08-13 | `role="group"` + 8 `<button>` + `aria-current="page"` · 8 tab stops · 44,00px · raio 9999px | **DIVERGE do SG1** |
| 2 | **Escala de tempo** (4) | `tela-painel.html` | §48 PN41 · `estável` | `role="group"` + 4 `<button aria-pressed>`, exclusivos | **DIVERGE — 3ª forma** |
| 3 | **Gesto no vazio** (2) | `tela-painel.html` | §48 · `estável` | 2 `<button aria-pressed>`, exclusivos | **DIVERGE do SG2** |
| 4 | **Operador do grupo / do subgrupo** (2 cada) | `tela-lista.html` | §53 FC3 · `estável` | `role="radiogroup"` + `<input type="radio">` nativos · 32,00px · raio 0px | **CONFORME ao SG1** |
| 5 | **Chips de filtro** (3) | `tela-tabela.html` | §42/§53 · `estável` | `<span class="chip">` + `<button class="x">` de **24×24px** | **6 FAIL** |
| 6 | **"Só comentários"** | `tela-detalhe.html` | §56 · `estável` | `<button aria-pressed>` | **CONFORME ao SG2** ✅ |

#### O achado central: o acervo já resolvia a mesma pergunta de TRÊS jeitos

A divergência de canon que a R1 achou **fora** da casa — Primer × useUI × Workday × eBay, quatro
semânticas para o mesmo componente — **já estava reproduzida dentro da casa**, e ninguém tinha
medido. Para a mesma pergunta *"escolha exclusiva que aplica na hora"*, o acervo responde:

* **`tela-painel.html`, lentes** — fileira de `<button>` com `aria-current="page"`. É a saída do
  **eBay**, e é exatamente a que o §60.1 descarta por escrito. Pior: o token `page` é de
  **navegação entre páginas**; nem dentro do padrão eBay ele caberia aqui, onde nada navega.
  Custo medido: **8 tab stops** para atravessar um controle só.
* **`tela-lista.html`, operador** — `radiogroup` com rádios **nativos**. É a saída do **useUI**, e é
  a que o §60.1 escolheu. Um tab stop, setas movendo dentro, tudo de graça pelo HTML.
* **`tela-painel.html`, escala de tempo e gesto no vazio** — fileira de `aria-pressed` **mutuamente
  exclusivos**. Não é nenhuma das quatro saídas do canon: a exclusividade existe só no script. A
  tecnologia assistiva anuncia *quatro interruptores independentes*, não *uma escolha entre quatro*.
  É a forma mais silenciosa das três, porque cada botão isolado passa em qualquer guarda de ARIA.

> **É por isso que a SG-P1 vinha antes da SG-P2.** A bancada `banco-escolha.html` produzida antes
> desta medição teria nascido como a **quarta** variação do mesmo controle, e o §60 teria
> documentado uma convergência que não existe. *Spec que chega depois do uso começa por auditar o
> uso* — a regra estava escrita; esta é a primeira vez que ela paga.

#### E a exclusividade precisa ser PROVADA, não inferida

A guarda que acha o item 2 nasceu com **falso positivo**: "fileira de `aria-pressed` com exatamente
um ligado" também descreve uma barra de interruptores **independentes** em que só um está ligado por
acaso — foi o que a barra de controles do preview de `tela-chat.html` e `tela-shell.html` fez. Uma
guarda que acusa o inocente é pior que guarda nenhuma. A versão final **prova por clique**: liga
outra opção e mede se a primeira desligou sozinha. Com a prova, os dois falsos positivos caem e os
dois achados reais ficam de pé. **Regra: exclusividade é comportamento, e comportamento se mede
agindo — nunca se lê da marcação.**

### 60.4 Números — o que a SG-P1 já mediu, e o que segue a medir

Método do §55: a spec nasceu só com relações; a auditoria trouxe os primeiros números. **Estes são
medidos, não escolhidos** — são o retrato do acervo hoje, e a bancada da SG-P2 é que decide quais
viram canon.

| Medida | `tela-painel.html` (lentes) | `tela-lista.html` (operador) |
|---|---|---|
| Altura do segmento | **44,00px** | **32,00px** |
| Raio | **9999px** (pílula) | **0px** (reto) |
| Peso, repouso → selecionado | 600 → **600** (não muda) | 700 → **700** (não muda) |
| Fundo, repouso → selecionado | `#ffffff` → `#098475` | transparente → `#098475` |
| **Separação de VALOR entre os dois fundos** | **4,60** | **4,57** |
| Texto sobre o selecionado | **4,60** (piso 4,50) | — |

> **Duas geometrias para a mesma família:** pílula de 44px e retângulo de 32px. Nenhuma das duas é
> errada isoladamente; as duas juntas são a prova de que não havia canon. A escolha é da SG-P2.

Alvo do X, medido: **24×24px** no chip (`tela-tabela.html`) e **32×32px** na condição
(`tela-lista.html`). Piso do SG10: **44px**. Detalhe do defeito em §60.6.

**Seguem a medir na bancada:** espessura e cor da fronteira do grupo · hover e foco · teto de chips
antes do `"+N"` · e todos os pares **nos dois temas** — nada acima foi medido no tema escuro.

### 60.5 Placar da SG-P1, por suíte

Placar agregado sem decomposição não é auditável (regra da v8.7).

| Arquivo | PASS | FAIL | `[n/a]` | O que os `[n/a]` querem dizer |
|---|---:|---:|---:|---|
| `tela-painel.html` | 16 | **9** | 5 | não tem chip removível — contrato declarado inaplicável, não pulado |
| `tela-lista.html` | 20 | **7** | 3 | não tem fileira de chips |
| `tela-tabela.html` | 8 | **6** | 4 | não tem controle segmentado |
| `tela-detalhe.html` | 8 | **0** | 9 | só tem interruptor; **único arquivo limpo** |
| **Agregado** | **52** | **22** | **21** | + 15 medidas |

Rodam também, com zero achado, `tela-quadro.html` · `tela-gantt.html` · `tela-chat.html` ·
`tela-shell.html` · `banco-dominio.html`: **achado negativo é achado** — nenhum destes tem controle
de escolha, e isso agora está medido em vez de suposto.

### 60.6 Supersede formal — o que a auditoria muda, e o que ela cobra do gate

#### (a) CORRIGIDO sem gate — fato, não decisão

**SUPERSEDE §60.3 (v0.81) → §60.3 (v0.82).** A tabela de consumidores da v0.81 dizia
*"Chips de filtro (§53, filtro composto) — `tela-tabela.html`"*. **Está errado:** o construtor
FC1–FC6 do §53 vive em **`tela-lista.html`** (`fieldset` + `legend` + `radiogroup`, FC3), e os chips
de `tela-tabela.html` são da toolbar do §42. A v0.81 também listava **três** consumidores; são
**seis**. *Motivo do erro: a tabela foi escrita a partir da memória da seção, não de uma busca no
acervo. É a lição da v7.0 outra vez — reconstrução de memória é inferior ao arquivo real.*

#### (b) DEFEITO MEDIDO, conserto pendente de autorização

**SG10 · o alvo de 44px do X do chip existe no código e não cobre o botão.** `tela-tabela.html`
declara `.chip .x::before { position:absolute; width:44px; height:44px }` — a intenção certa. Mas
`.chip .x` é `position:static`: o absoluto ancora no primeiro ancestral posicionado, que é `<html>`.
**O alvo de 44px está no canto da página.** Alvo real do botão: **24×24px**, contra piso 44px.
Conserto: uma declaração — `.chip .x { position: relative }`. O X da condição em `tela-lista.html`
mede **32×32px** e não tem nem a tentativa.

> **Esta é a família de defeito mais cara do projeto: o que PARECE resolvido.** Uma leitura do CSS
> vê "44px" e passa. Só a medição do retângulo real acusa. **Regra nova: alvo estendido por
> pseudo-elemento absoluto só conta se o instrumento provar que o elemento-dono é posicionado.** A
> guarda `SG10` da `suite-escolha.mjs` já nomeia a âncora do `::before` na mensagem de FAIL.

**SG12 · a remoção anuncia o que saiu e não quantos restam.** Medido:
`"Filtro removido: Frente: Subestação MT."` — sem o número. *E a própria suíte tropeçou aqui:*
a primeira versão lia a **primeira** live region do DOM e pegava o contador `"Mostrando 12 de 148"`,
que é outro dispositivo (TD1). Veredito sobre o texto errado. A versão final lê **a região que
mudou**. *Guarda que depende de qual elemento vem primeiro no DOM não é guarda, é sorte.*

**SG13 · "Limpar filtros" persiste com um chip só** — medido descendo a fileira até 1.
**SG11 · não há teto nem `"+N"`** em nenhum dos dois arquivos: a fileira vaza.

#### (c) A PRÓPRIA SPEC ERRA — dois contratos que a medição derruba

**SG5 (teto de 5 opções) contra o §48 (oito lentes).** O §48 é `estável` e passou pelo gate do
Rafael em 2026-08-13 com **oito** lentes. O SG5 foi escrito em 2026-08-16 sem olhar para ele. **Não
é o artefato que está fora do contrato: é o contrato que nasceu sem consultar o consumidor.**
O motivo do SG5 é *"não espremer sete opções numa fileira apertada"* — e o painel não espreme:
`.lentes` é `flex-wrap: wrap`, e o PN4 **esconde** a lente que o conjunto de dados não sustenta, de
modo que o número visível é menor que oito na maioria dos casos. A régua útil não é a **contagem**,
é o **aperto**. Proposta à decisão do gate, com a alternativa descartada nomeada:

> **SG5 revisto (proposta):** *o teto não é de contagem, é de aperto medido.* Segmentado cabe
> enquanto a fileira couber em **uma linha sem reduzir o alvo abaixo de 44px**; passado isso,
> `select` — **ou** quebra em duas linhas quando as opções são de mesma natureza e a quebra não
> muda o significado. **Descartado:** manter o teto fixo em 5, que exigiria converter as oito lentes
> em `select` e desfazer pixel aprovado em gate por uma regra que nasceu depois dele.

**SG6 ("fundo E peso") contra 2 de 2 dos segmentados.** Nenhum dos dois muda o peso ao selecionar
(600→600 e 700→700). O **motivo** do SG6 é *"diferença de valor é o que sobrevive à deficiência de
visão de cores e à escala de cinza"* — e a medição diz que **o fundo sozinho já entrega**: **4,60**
e **4,57** de separação de luminância, contra piso **3,00** do SC 1.4.11. *Contrato violado por 100%
dos seus consumidores é contrato mais estrito que o problema que ele resolve.*

> **SG6 revisto (proposta):** *o selecionado se distingue por diferença de VALOR medida ≥ 3,00
> entre os dois fundos — não por matiz.* O peso é reforço **opcional**. **Descartado:** exigir a
> mudança de peso, porque `font-weight` altera a largura do texto e a fileira **reflui a cada
> seleção** — os segmentos mudariam de tamanho ao serem escolhidos, o que é custo de layout real em
> troca de um sinal que a medição mostra já existir.

#### (d) A DECISÃO DO GATE — tomada em 2026-08-16

Os controles divergentes estão em seções `estável`, e convertê-los muda **comportamento de teclado
aprovado** (de 8 tab stops para 1) e **marcação anunciada** — a mesma forma do **CP-P5**, que só
andou com o *"conserta"* explícito. **O Rafael autorizou:** converter os três controles do §48
(SG-P4/SG-P5) e consertar os cinco defeitos dos removíveis (SG-P7). O **SG-P6** ele delegou
("analise e tome a melhor decisão"), e o que segue registra a decisão tomada e **por que ela é o
oposto da que eu tinha proposto**.

#### (e) SG-P6 · A MEDIÇÃO DERRUBOU A PROPOSTA — e essa é a lição da edição

Em §60.6(c) eu propus **relaxar o SG6**: o fundo sozinho media **4,60** e **4,57** de separação de
valor contra piso **3,00**, logo o `e PESO` seria mais estrito que o problema. O argumento estava
correto **dentro do modo que eu tinha medido**. Antes de aplicar, medi os outros:

| Modo | Fundo, repouso → selecionado | Separação | Veredito |
|---|---|---:|---|
| normal | `#ffffff` → `#098475` | **4,60** | passa |
| escuro | `#ffffff` → `#098475` | **4,60** | passa |
| **`forced-colors: active`** | `#ffffff` → **`#ffffff`** | **1,00** | **o selecionado SOME** |

Sob alto contraste do sistema o agente de usuário **substitui** `background-color` e
`border-color`. A distinção inteira do selecionado evaporava — nos três controles do painel e nos
dois operadores da lista. **O SG6 estava certo pelo motivo errado:** o texto dizia *"não só cor"*
pensando em deficiência de visão de cores e escala de cinza, e quem cobrava a fatura era um modo
que ninguém tinha medido.

Mas o remédio também não era o que o contrato dizia. `font-weight` sobreviveria ao modo, sim — só
que ao custo de a fileira **refluir a cada seleção**. O meio certo são as **cores de sistema**, que
são as únicas preservadas: `Highlight` / `HighlightText` é exatamente o par que o sistema reserva
para *"isto está selecionado"*. Depois do conserto a separação mede **19,04**.

> **Regra nova, e ela corrige uma que eu tinha acabado de escrever.** Em §60.6(c) escrevi:
> *"contrato violado por 100% dos seus consumidores é suspeito de ser mais estrito que o problema"*.
> Continua verdade — mas **a suspeita não é veredito**. Antes de relaxar, **meça o modo em que o
> contrato ganha a vida**. Um contrato pode estar certo pelo motivo errado, e relaxá-lo pelo motivo
> declarado destrói a proteção real. *Irmã direta da regra da v9.8 — antes de declarar uma fronteira
> decorativa, meça se existe outro sinal — aplicada na direção oposta.*

O **SG5**, esse sim, cedeu — e com número: as oito lentes cabem em 390, 768, 1180 e 1440px, em
4/2/1/1 linhas, alvo mínimo **62×44px**, sem vazar e sem cortar. **E a SG5 revista achou defeito
que a antiga não alcançava:** o segmento do operador do §53 media **62×32px**, abaixo do piso de
44. A guarda SG10 não o via porque só cobria o X de chip e de condição. *Contrato reescrito para
medir o problema certo acha o que o contrato anterior não alcançava.*

#### (f) DUAS GUARDAS APONTAVAM PARA O LADO ERRADO

**`PN6-01` (`suite-painel.mjs`) AFIRMAVA o defeito.** Ela dizia, e passava:
*"a lente ativa usa aria-current"*. É por isso que cinco camadas de validação atravessaram o caso:
**a guarda não estava cega — estava apontada para o lado errado.** Superseded por seis guardas
(`PN6-01a`…`PN6-01f`) que testam o **problema** (radiogroup · role=radio · um tab stop · nenhum
`aria-current` sobrando · nome que diz "aplica na hora" · nenhuma LEITURA órfã de `aria-current`
no script) em vez da forma. Nasce também a `PN6-03`, do SG6-b.

**E o instrumento novo errou duas vezes, das duas em família conhecida.** A `suite-escolha.mjs`
casava as passadas extra (aperto por largura · forced-colors) com os grupos da passada principal
**por posição no array** — e consultas diferentes produzem ordens diferentes: o operador nativo do
§53 nem aparecia na segunda consulta, e o índice escorregou, atribuindo a um grupo a medida de
outro. E o detector do `"+N"` procurava `[class*=mais-n]`, um nome que a guarda inventou e que não
batia com o `chips-mais` do artefato — **guarda que procura um seletor que ninguém combinou
reprova o conserto correto**. Consertos: casar por **chave estável**, e procurar o **contrato**
(`aria-expanded` na fileira) em vez do nome.

> **Regra nova: guarda que casa dois conjuntos por índice não é guarda, é coincidência.** Irmã da
> regra da v9.4 (*guarda que depende da ordem de execução das outras não é guarda, é sequência*) e
> da v8.9 (*o gate abriu o arquivo errado*): as três são a mesma doença — **veredito correto sobre
> o objeto errado**.

#### (g) O QUE FOI EXECUTADO — e onde

Tudo no **molde e no gerador**, nunca no HTML gerado: artefato editado à mão volta atrás no
próximo `gen-*`.

| Arquivo | O que mudou |
|---|---|
| `validacao/painel-template.html` | Os QUATRO grupos viram `radiogroup`; **um** helper de roving (`marcar` + `rovingTeclado`) substitui três mecanismos; `@media (forced-colors: active)`; anel de foco do `[role=radio]`; `lenteAtual()` passa a ler `aria-checked` |
| `validacao/gen-painel.py` | Selo do preview **v0.10 → v0.11** |
| `validacao/suite-painel.mjs` | `PN6-01` superseded por 6 guardas · `PN6-02`/`AC-01` com o seletor novo · **`PN6-03`** (forced-colors) |
| `validacao/tela-tabela-template.html` | `.chip .x{position:relative}` + `::before` centrado · `"+N"` com `TETO_CHIPS` declarado · anúncio com contagem · `"Limpar"` com piso de 2 |
| `validacao/tela-lista-template.html` | X da condição a 44px com dono posicionado · segmento do operador a **44px** · `@media (forced-colors)` · anúncio com contagem |
| `validacao/gen-tela-lista.py` | Nome do radiogroup ganha *"— aplica na hora"* (SG4) · selo **0.1 → 0.2** |
| `validacao/gen-tela-tabela.py` | Selo **0.1 → 0.2** |
| `validacao/suite-escolha.mjs` | Guarda `SG2/SG1` prova exclusividade **por clique** · SG5 e SG6 revistos · SG6-b · passadas extra por chave |

**Cinco camadas, depois do conserto:** `suite-escolha` **88 · 0 · 21 [n/a]** (4 arquétipos) ·
`suite-painel` **146 · 0** · `contraste-painel` **78 · 0** · `suite-container` **66 · 0** (2 telas).
*Falta o gate visual do Rafael — a única camada que mede se o controle é OPERÁVEL, e não só
conforme.*

### 60.7 A promoção, e os TRÊS níveis de prova

O gate visual do Rafael saiu em 2026-08-16 sobre os três previews: **"verificado, tudo ok"**. Antes
de escrever `estável`, uma pergunta que o projeto ainda não tinha feito a si mesmo: **quais destes
contratos têm PROVA, e quais têm só texto?**

A resposta obrigou a distinguir **três níveis de evidência**, e a distinção fica registrada porque
eles não valem o mesmo:

| Nível | O que significa | Contratos |
|---|---|---|
| **1 · Consumidor em produção** | O contrato é exercido por artefato que já estava em uso, e a medição o confirmou. É o nível mais forte: ninguém construiu o caso para o contrato passar | SG1 · SG2 · SG4 · SG5 · SG6 · SG6-b · SG8 · SG9 · SG10 · SG11 · SG12 · SG13 |
| **2 · Bancada** | O contrato é exercido por artefato que **nós construímos para prová-lo**. Vale — mas é mais fraco, porque quem escreve o teste e quem escreve o caso são o mesmo | **SG7** · **SG14** |
| **3 · Ausência de violação** | O contrato é uma **proibição**, e a guarda informa que ninguém a viola | **SG3** (zero `tablist` no acervo) |

> **Proibição sem instrumento é só uma frase.** O SG3 existia desde a v0.81 e **nada o media**. Agora
> há guarda, e ela mede a cada rodada em vez de supor. *Passar por ausência é veredito mais fraco que
> passar por instância, e a diferença fica dita.*

#### O SG8 nunca tinha sido testado — e estava violado

*"Segmento com ícone e rótulo visível usa SÓ o rótulo no nome acessível."* O contrato existia desde a
v0.81; nenhum consumidor parecia exercê-lo, então nenhuma guarda foi escrita. Ao escrever a guarda
**para poder promover**, ela achou o caso: o botão **`✋ Mover`** do "Gesto no vazio" levava o glifo
num nó de texto, e o nome acessível saía `"✋ Mover"` — o leitor de tela anunciava *"mão levantada
Mover"*. Conserto: `<span aria-hidden="true">✋</span>`.

> **Regra: contrato sem guarda é contrato sem prova — mesmo quando existe consumidor.** A SG-P1 mediu
> se os consumidores **concordavam entre si**; não mediu se cada contrato **tinha instrumento**. São
> perguntas diferentes, e a segunda só foi feita na hora de promover. *Auditoria de concordância não
> substitui auditoria de cobertura.*

### 60.8 A bancada — e por que o escopo dela é estreito

A `banco-escolha.html` nasce **por último**, e isso é decisão, não atraso. Quando o §60 foi escrito
(v0.81), quatro artefatos já usavam controles de escolha sem spec; a SG-P1 mandou **auditar antes de
produzir**, e a auditoria achou o acervo resolvendo a mesma pergunta de **três jeitos
incompatíveis**. *Produzir a bancada primeiro teria criado a quarta variação, e o §60 teria
documentado uma convergência que não existia.*

Com onze contratos já provados por consumidor real, o que sobrava para a bancada era estreito:

1. **Provar o SG7 e o SG14**, os dois sem instância no acervo.
2. **Fechar a última divergência de geometria** — o raio.
3. Servir de **referência única do mecanismo de roving** (antes eram três mecanismos).

**Placar: 137 PASS · 0 FAIL · 0 `[n/a]`.** É o único artefato do acervo em que **nenhum contrato sai
`[n/a]`** — o que é o próprio critério de uma bancada estar completa.

#### SG-P9 · o raio, e por que ele vai a gate em vez de eu decidir

A SG-P1 mediu duas geometrias para a mesma família. A **altura convergiu em 44px** (o §53 media 32 e
subiu na SG-P7). O **raio não**: **9999px** (pílula, §48) contra **6px** no item e **8px** no grupo
(reto, §53).

A bancada põe os dois **lado a lado, com o mesmo conteúdo**, e acrescenta uma **terceira fileira
estreita de propósito** — porque o SG5 revisto permite o segmentado **quebrar em linhas**, e é na
quebra que os dois se comportam diferente: o arredondamento total do **grupo** tem de envolver duas
linhas; o reto não tem esse problema.

> **Isto está na bancada para ser OLHADO, não afirmado.** Eu poderia escrever "a pílula fica estranha
> quebrando" — seria opinião com cara de medição. Pôr as duas quebrando lado a lado é medição que o
> olho faz, e o olho é do Rafael. *É o formato que ele mesmo pediu no §49: "me mostre visualmente a
> diferença, é mais fácil para eu decidir".*

### 60.9 SG-P9 fechada — e o que a decisão descobriu

**Decisão do gate, 2026-08-16:** *"pilula contra reto, escolho reto"*. O segmento passa a **6px**, o
valor que já vinha do §53. A família de escolha do SEED fica com **uma geometria**: altura **44px**
(convergida na SG-P7) e raio **6px**.

A regra escrita é **específica** — `.lentes [role="radio"]`, `.escala-ctrl [role="radio"]`,
`.mapa-modos [role="radio"]` —, e não uma troca no `button` genérico do preview.

> **O gate decidiu sobre o SEGMENTADO, não sobre todos os botões do painel.** Trocar o raio genérico
> teria sido mais limpo de escrever e teria mudado dezenas de controles que ninguém avaliou.
> *Alargar a decisão para além do que foi decidido é a forma silenciosa de decidir sozinho.*

#### SG-P10 · aplicar o raio revelou o que o raio escondia

Com o raio igualado, ficou visível que os dois **não desenham a mesma coisa**:

| | `tela-painel.html` (hoje) | `banco-escolha.html` (bancada) |
|---|---|---|
| Fronteira | **uma por segmento** — oito bordas | **uma por grupo** — segmentos sem borda |
| Fundo do grupo | nenhum (fileira nua) | `surface-subtle`, com 3px de respiro |
| Espaçamento | `gap: 6px` entre botões soltos | `gap: 4px` dentro de um contêiner |
| Leitura | oito botões que por acaso estão juntos | **um controle** com oito posições |

Altura igual, raio igual, **anatomia diferente**. É a mesma família de divergência que a SG-P1 achou
e que esta seção inteira passou fechando — só que **uma camada acima**: não no valor, na estrutura.

> **Regra nova: divergência de VALOR esconde divergência de ESTRUTURA.** Igualar o número não iguala
> a coisa. Quando dois artefatos convergem em todas as medidas e ainda parecem diferentes, o que
> resta é anatomia — e anatomia não aparece em placar de contraste, alvo ou raio, porque nenhuma
> guarda mede *"isto lê como um controle ou como oito?"*.

A leitura de conjunto importa: **um controle com oito posições** e **oito botões que por acaso estão
juntos** dizem coisas diferentes ao olho, mesmo com a semântica de `radiogroup` correta nos dois.
Mas mudar a anatomia do §48 altera pixel aprovado em gate, e a decisão é dele.

### 60.10 SG-P10 fechada — a anatomia converge, e três defeitos aparecem no caminho

**Decisão do gate, 2026-08-16: B.** O grupo carrega **uma** fronteira; os segmentos perdem a
própria. O painel, a lista e a bancada passam a desenhar a mesma coisa:

| | Antes | Agora (canon) |
|---|---|---|
| Fronteira | uma por segmento (painel) · `overflow:hidden` com rótulos colados (lista) | **uma por grupo**, nos três |
| Fundo do grupo | nenhum · nenhum | `surface-subtle`, 3px de respiro |
| Segmento | borda e fundo próprios | borda **transparente**, fundo transparente |
| Largura do grupo | `flex` — esticava até o fim da linha | **`inline-flex`** — encolhe para o conteúdo |

> **O operador do §53 tinha uma TERCEIRA anatomia** — contêiner com `overflow:hidden`, `gap:0` e
> rótulos colados de borda a borda. Ele já tinha *um* contêiner, e por isso quase passou.
> *Ter algum contêiner não é convergir; convergir é adotar A MESMA anatomia.*

**Por que `inline-flex`:** com a fronteira do grupo visível, `display:flex` (nível de bloco) esticava
o contêiner até o fim da linha e deixava fundo vazio à direita do último segmento — a fronteira
passava a delimitar a **linha**, não o **controle**. Com `flex-wrap`, a largura disponível segue
sendo o limite, e a quebra medida na SG5 não muda.

#### Os três defeitos que apareceram ao aplicar — e todos foram pegos por guarda

**(1) `AC-08` · token em vez de px.** Eu digitei `8px` e `6px`, e existem
`--seed-radius-md` e `--seed-radius-3` com esses valores. A guarda de higiene é de **classe**: não
interessa que o número esteja certo, interessa que o componente consuma a camada de token — senão a
escala muda e o segmentado não acompanha. Mesma família do GI2.

**(2) Regressão de ESPECIFICIDADE, e ela é silenciosa.** A regra nova
`.lentes [role="radio"] { background: transparent }` tem peso **0,2,0** — o **mesmo** de
`[role="radio"][aria-checked="true"] { background: action-primary }`. Empate resolve por ordem, e a
nova era posterior: **o selecionado perdeu o fundo e ficou idêntico ao repouso.** O placar acusou
separação de **1,00** contra piso **3,00**.

> **Regra nova: regra escrita DEPOIS, com o MESMO peso, desfaz a anterior em silêncio.** Não há erro
> de sintaxe, não há aviso, e a cor certa continua escrita no arquivo — só não vence. *Só a medição
> do valor EFETIVO mostra; ler o CSS mostraria as duas regras, ambas corretas.*

**(3) Sexto defeito do instrumento: `transparent` lido como PRETO.** Com o segmento em
`background: transparent`, o `getComputedStyle().backgroundColor` devolve `rgba(0,0,0,0)` — e a
leitura ingênua disso é preto. A guarda do SG6 passou a comparar `#000000` com `#000000` e reprovou
um artefato correto.

> **Regra nova: quando o contrato é sobre o valor PERCEBIDO, a guarda mede o valor EFETIVO.** O que o
> usuário vê não é o fundo declarado: é o fundo composto com o que aparece por baixo. A guarda agora
> **sobe pelos ancestrais compondo o alfa**, que é o que o olho faz. *Mesma família do `textContent`
> tratado como nome acessível (v10.2) — ler o valor declarado quando o contrato é sobre o percebido é
> medir outra coisa com o nome certo.*

### 60.11 Pendências

**Nenhuma.** As dez pendências do §60 fecharam em 2026-08-16.

| # | Pendência | Como fechou |
|---|---|---|
| **SG-P1** | Auditar os consumidores existentes | 6 controles em 4 arquivos; instrumento permanente |
| **SG-P2** | Bancada `banco-escolha.html` | 137 · 0 · 0 — SG7 e SG14 provados |
| **SG-P3** | Excedente em tela estreita | **Respondida por medição:** não há excedente |
| **SG-P4** | Converter as lentes do §48 | 8 tab stops → 1 |
| **SG-P5** | Escala, gesto e modo do mapa | um helper de roving para os quatro |
| **SG-P6** | Revisar SG5 e SG6 | SG5 cede com número; SG6 **não** cede — vira SG6-b |
| **SG-P7** | Alvos, anúncios, teto e piso | 24→44px · 32→44px · `"+N"` · contagem · piso de 2 |
| **SG-P8** | Gate visual dos três previews | *"verificado, tudo ok"* |
| **SG-P9** | Raio do segmentado | *"escolho reto"* — 6px |
| **SG-P10** | Anatomia do grupo | *"B com certeza"* — fronteira por grupo |

> **Gate pendente:** os previews mudaram depois do gate da SG-P8 — `tela-painel` **v0.14**,
> `tela-lista` **v0.3**, `banco-escolha` **v0.2**. As mudanças foram **autorizadas** (SG-P9 e SG-P10),
> mas *autorização não é verificação*: o olho ainda não viu o resultado montado. Fica como
> conferência de abertura da próxima sessão, não como pendência do §60.
>
> **Atualização 2026-08-16:** a `banco-escolha` está hoje na **v0.4** — barra de controles fixa (BT1),
> seletor de largura (BT2) e conserto da contagem no tema escuro, que media **1,00** e passou a medir
> **4,60 / 7,39**. O re-gate destas versões é a **BT-P1**, no §64.6, para não haver duas listas
> disputando a mesma pendência.



| # | Pendência | Estado | Nota |
|---|---|---|---|
| **SG-P1** | Auditar os consumidores existentes | ✅ **FECHADA** | 6 controles em 4 arquivos |
| **SG-P2** | Bancada `banco-escolha.html` | ✅ **FECHADA** | 137 · 0 · 0 — SG7 e SG14 provados |
| **SG-P3** | Excedente em tela estreita | ✅ **RESPONDIDA por medição** | Não há excedente: quebra em linhas mantendo 62×44px |
| **SG-P4** | Converter as lentes do §48 | ✅ **FECHADA** | 8 tab stops → 1 |
| **SG-P5** | Converter escala, gesto e modo do mapa | ✅ **FECHADA** | um helper de roving para os quatro |
| **SG-P6** | Revisar SG5 e SG6 | ✅ **FECHADA** | SG5 cede com número; SG6 **não** cede — vira SG6-b |
| **SG-P7** | Alvos, anúncios, teto e piso dos removíveis | ✅ **FECHADA** | 24→44px · 32→44px · `"+N"` · contagem · piso de 2 |
| **SG-P8** | Gate visual dos três previews | ✅ **FECHADA** | *"verificado, tudo ok"* |
> **Gate pendente:** os previews mudaram depois do gate da SG-P8 — `tela-painel` **v0.14**,
> `tela-lista` **v0.3**, `banco-escolha` **v0.2**. As mudanças foram **autorizadas** (SG-P9 e SG-P10),
> mas *autorização não é verificação*: o olho ainda não viu o resultado montado. Fica como
> conferência de abertura da próxima sessão, não como pendência do §60.
>
> **Atualização 2026-08-16:** a `banco-escolha` está hoje na **v0.4** — barra de controles fixa (BT1),
> seletor de largura (BT2) e conserto da contagem no tema escuro, que media **1,00** e passou a medir
> **4,60 / 7,39**. O re-gate destas versões é a **BT-P1**, no §64.6, para não haver duas listas
> disputando a mesma pendência.



| # | Pendência | Estado | Nota |
|---|---|---|---|
| **SG-P1** | Auditar os consumidores existentes | ✅ **FECHADA** | 6 controles em 4 arquivos |
| **SG-P2** | Bancada `banco-escolha.html` | ✅ **FECHADA** | 137 · 0 · 0 — SG7 e SG14 provados |
| **SG-P3** | Excedente em tela estreita | ✅ **RESPONDIDA por medição** | Não há excedente: quebra em linhas mantendo 62×44px |
| **SG-P4** | Converter as lentes do §48 | ✅ **FECHADA** | 8 tab stops → 1 |
| **SG-P5** | Converter escala, gesto e modo do mapa | ✅ **FECHADA** | um helper de roving para os quatro |
| **SG-P6** | Revisar SG5 e SG6 | ✅ **FECHADA** | SG5 cede com número; SG6 **não** cede — vira SG6-b |
| **SG-P7** | Alvos, anúncios, teto e piso dos removíveis | ✅ **FECHADA** | 24→44px · 32→44px · `"+N"` · contagem · piso de 2 |
| **SG-P8** | Gate visual dos três previews | ✅ **FECHADA** | *"verificado, tudo ok"* |
| **SG-P9** | RAIO do segmentado | ✅ **FECHADA** | *"escolho reto"* — 6px. A pílula fica na bancada marcada como `superseded`, porque **decisão sem a evidência ao lado vira folclore em três meses** |
| **SG-P10** | **ANATOMIA do grupo: fronteira por segmento ou fronteira por grupo** | **ABERTA — única do §60** | Descoberta ao aplicar a SG-P9: raio e altura iguais, estrutura diferente. O painel desenha oito botões com borda própria; a bancada desenha um contêiner com segmentos sem borda. Decisão de gate — altera pixel aprovado, e nenhuma guarda existente mede "isto lê como um controle ou como oito?" |



