Ir ao conteúdo
SEED engenhariaDesign System

Componentes

60. Escolha segmentada e múltipla

estávelseed-componentes.md v1.43 · §60seção 66 de 9860-escolha-segmentada-e-multipla-estavel-sg1-sg14.md · MD5 2d07c038

Título completo no canon: 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 radiogroupradiogroup 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 sistemaHighlight / 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, operadorradiogroup 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, selectou 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-01aPN6-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?"
BancadaSEED Design System v2 · banco-escolha (§60 · escolha segmentada e múltipla) — preview v0.4abrir em página própria ↗

Também cita o §60: banco-edicao-linha, banco-identidade, banco-prioridade.

Esc