Componentes
46. Shell de aplicação
seed-componentes.md v1.63 · §46seção 48 de 9946-shell-de-aplicacao-estavel-v0-50-sh1-sh19.md · MD5 68a26f20Título completo no canon: Shell de aplicação — estável (v0.50) · SH1–SH19 · pattern F6 · suíte suite-shell.mjs 68/68 ✓ · render 18/0 · contraste 32/0 (na estreia; em 2026-09-15, com o SH19: 84/0 · 54/0 · 55/0) · gate visual aprovado 2026-08-11 — FECHA O BLOCO 6A
Natureza: pattern de COMPOSIÇÃO do F6, não componente novo — consome menu/dropdown (§35), tabs (§34), breadcrumb (§36), command palette ⌘K (§39), drawer (§31), avatar (§32), badge (§21), lista (§28), central de notificações (§33) e o botão (§1). Nenhum componente nasce aqui. É a mesma natureza do §33, o primeiro pattern F6 do sistema, e a fronteira que o Bloco 5 declarou desde 2026-08-06: "sidebar/topbar é shell do F6, consome este bloco".
PRINCÍPIO-MÃE, decidido com o Rafael em 2026-08-11: CONTRATO POR REGIÃO, COMPOSIÇÃO LIVRE. As cinco regiões são especificadas até o último detalhe; qual delas o produto liga, e o que coloca dentro, é decisão do projeto do ERP — não do Design System. Racional dele, adotado: engessar a composição limita em vez de ajudar, e não gera problema de padronização — o que carrega a identidade é cor, tipografia, traço, densidade e comportamento do item ativo, não o arranjo das caixas. O que o DS não abre mão: cada região se comporta igual em toda composição (SH14) e acessibilidade não é opcional em arranjo nenhum (SH2, SH5, SH7, SH8).
Escopo do produto, decidido em briefing antes da pesquisa: o ERP é web, responsivo, desktop-prioritário, usado pela equipe — escritório como uso principal, campo como uso real. O menu muda por perfil. A navegação é por ÁREA DO NEGÓCIO (processo), não por ferramenta. O app nativo do cliente é fronteira declarada: quando existir, o DS entrega tokens e componentes, nunca layout de navegação, porque brigar com a convenção do iOS e do Android é perder. O site institucional é o bloco 6B, e nasce mobile-first.
Base (3 rodadas encadeadas, 2026-08-11): R1 canon interno — o §33 como molde de pattern F6; o Bloco 5 inteiro como insumo (o shell não inventa, arruma); MN1 (as quatro saídas semânticas) e MN6 (comando indisponível fica visível), que o SH6 precisa distinguir; DW1 (os dois regimes do drawer) e CN6 (o precedente de standard); a escala de sobreposição 60<65<70<75<80; o §40 (densidade compacta medida em 33px). R2 mercado e stack — componente Sidebar oficial do shadcn/ui, que é o consumidor real do Lovable, com
SidebarProvidere os três modosoffcanvas/icon/none; blocos de sidebar colapsável comCollapsibledo Radix e threading porborder-l; prática consolidada de SaaS enterprise (topo para contexto global, lateral para navegação primária, porque as duas camadas fazem trabalhos diferentes e param de disputar espaço); SAP Fiori launchpad shell bar (logo, back, título, busca corporativa, notificações, Me Area). R3 normas e fora-do-circuito — ARIA11/W3C sobre landmark repetido exigindo nome único; MDN sobrerole="navigation";aria-current="page"como critério AAA de baixo custo; o corpus de acessibilidade de SPA (foco preso na navegação após troca de rota é o defeito nº 1, e o alvo do foco não pode ser landmark, link nem botão); Material Design navigation rail (3–7 destinos, posicionado abaixo da top bar). Consolidado aprovado pelo Rafael em 2026-08-11.REFERÊNCIA DE ARQUITETURA, e o que dela foi herdado. O Rafael apresentou um layout de referência (
preview-clientes-v2.html, 58.741 B, md569f00537763e14ef907d2f8130c26a92) no padrão de um produto de mercado, com instrução explícita: "apenas ideia para entender o layout de construção". Regra que sai daqui e vale para todo bloco futuro: de um layout de referência herda-se ESTRUTURA e COMPORTAMENTO; cor, tipografia e forma vêm do DS, sempre. Herdado: o rail como camada acima da sidebar · a sidebar ser contextual ao rail · árvore de quatro níveis com fio de conexão · busca fixa e centralizada com o atalho impresso dentro · seletor de contexto no topo à esquerda · contadores no fim da linha · ações que aparecem no hover · densidade compacta. Descartado por não ser do sistema: rail preto puro#000000(a superfície mais escura do DS é#0B1419), verde de sucesso#2DBA7C(o do DS é turquesa), gradiente terminando em#D94B7D, badge rosa, e neutros deslocados (#9AA8B0onde o DS tem#90A6B3;#CBD3D8onde tem#ACBECA) — a mesma deriva de hex digitado que custou as erratas E4 e E16 na Fase 5.
46.1 Decisões SH1–SH15 e SH19 (SH17 e SH18 vivem em 46.4 e 46.5)#
O contrato de montagem de tela (ex-SH16) é LEI DO SISTEMA e vive no
seed-composicao.md§1 (CP1) — canvassurface-subtle, peçasurface-raised+radius-lg+ par sombra+anel, calhasp-3, nada encosta em nada. A exceção nomeada do rail foi SUPERSEDIDA no gate de 2026-08-15 ("um bloco montado como os outros, todos independentes, igual o ClickUp"): o rail é peça sobre o canvas como as demais — radius-lg, calha nos quatro lados, sem borda (a própria cor é a fronteira: 5,82/8,62 claro · 2,70/1,82 escuro contra o canvas). Registro completo no CP1 doseed-composicao.mdv1.4. O shell é a primeira instância do contrato, não a dona dele (supersede SUP-1, 2026-08-14; fecha a errata E-CF-03 — o cabeçalho desta seção dizia "SH1–SH14" com a tabela terminando em SH15).
| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| SH1 | Cinco regiões nomeadas: rail · topbar · sidebar contextual · conteúdo · painel lateral. Obrigatórias: conteúdo + ao menos uma região de navegação. As demais o produto liga conforme a tarefa | Composição é escolha de tarefa, não de identidade. O §33 já opera assim: não obriga ninguém a ter central de notificações — diz que, se tiver, é assim | Composição fixa em N arranjos canônicos (engessa arquitetura de produto de dentro do DS) · nenhuma região obrigatória (tela sem navegação nem landmark é beco sem saída) |
| SH2 | Toda região de navegação é landmark com NOME ACESSÍVEL ÚNICO, e o nome não contém a palavra "navegação" — o leitor de tela já anuncia o papel. Nomes canônicos: "Áreas" (rail) · "Seções" (sidebar) · "Trilha" (breadcrumb) · "Conta" (menu do avatar) | ARIA11/W3C: landmark repetido exige nome único e significativo. O shell tem três a quatro nav simultâneos — sem nome, o usuário de leitor de tela recebe uma lista de navegações idênticas e não tem critério para escolher |
nav anônimo · nome contendo "navegação" (redundância verbosa) · nomes iguais em regiões diferentes |
| SH3 | RAIL — contrato: destinos de topo · 3 a 12 · largura 80px · ícone do set §45 + rótulo sempre visível NO ESTADO PADRÃO, ≤9 caracteres por palavra (o estado recolhido só ícone é o SH19 — opção do usuário no desktop, nunca padrão; supersede parcial SH-P14, 2026-09-15) · um ativo por vez · ordem estável · altura total, à esquerda da topbar | O Material limita a 3–7, mas calibrado para tablet, com o rail substituindo a barra inferior; num ERP de desktop o rail é a espinha do produto. Teto de 12 declarado como calibrado aqui, NÃO derivado de norma. Largura e limite de caracteres são MEDIDOS (conta de agosto, medir-rail.mjs — instrumento GASTO desde a errata E-CF-06 do §46.2, 2026-09-12: a conta viva é a do mede-rotulo-rail.mjs, 11 px com o tracking do papel micro; a remoção do arquivo é tabela de remoção): Montserrat 9px caixa-alta media 7,01px por caractere; um rail de 64px tem 52px úteis e comporta 7 caracteres — três dos seis rótulos de exemplo transbordavam. 80px dão 68px úteis = 9 caracteres. O rail cedeu de 64 para 80px porque "Comercial" (9) é nome legítimo de área de ERP — quem tem de caber é o negócio. Rótulo truncado não é rótulo, logo o limite recai sobre a palavra. Altura total porque o rail é o nível MAIS ALTO de navegação — ficar dentro da moldura da topbar contradiz a hierarquia que ele representa |
Rail só com ícone como PADRÃO (rótulo em tooltip não é descoberto — NN/g, Icon Usability, 27/07/2014: "icon labels should be visible at all times"; o §45 mede glifos a 24px, não a 24px sem contexto). Supersede parcial SH-P14 (2026-09-15, veredito dele "V-SH14.1 modo recolhido: b"): como OPÇÃO do usuário no desktop — nunca padrão, nunca resposta a tela estreita — o só-ícone é o estado recolhido do SH19; é a exceção que a própria fonte admite para "applications used every day" (NN/g, Left-Side Vertical Navigation on Desktop, 16/05/2021); o ERP é aplicação de uso diário pela equipe, e quem liga o recolhido já aprendeu os ícones. Levantamento datado de sete sistemas no MANIFESTO §227.4. · rail abaixo da topbar (a posição que o Material recomenda, semanticamente errada aqui) · teto de 7 (herdaria calibração de outro contexto — o erro da errata E7) |
| SH4 | SIDEBAR — contrato: árvore de até 4 níveis, contextual à região acima. Quatro travas: (a) um ramo aberto por vez · (b) o ramo do item ativo abre sozinho ao carregar · (c) em modo estreito, níveis 2+ abrem em flyout · (d) quinto nível vira tabs §34 dentro da tela | O teto de 2 níveis foi proposto e derrubado pelo Rafael com contraexemplo (Financeiro → Faturamento → Faturas emitidas), e a referência confirma 4 na prática. As travas existem porque profundidade sem elas vira parede de 60 linhas. O flyout é disclosure de links, nunca role="menu" — distinção que o MN1 pagou caro para estabelecer |
Árvore livre sem travas · nível 3 como navegação secundária dentro da página (solução de Fiori e Carbon; cai porque explorar é ver a estrutura sem entrar nela, e navegação secundária só aparece depois de já ter chegado) |
| SH5 | Item ativo: aria-current="page" + marca que SOBREVIVE AO GRAYSCALE, por região: na sidebar, barra lateral de 3px mais peso tipográfico; no rail, a pílula clara (turquesa-100 sobre o gradiente escuro) mais peso — nunca só fundo colorido de mesma luminância |
Indicar o item atual exige as duas coisas: destaque visual e aria-current no link. E o DF4 faz do grayscale gate estrutural do sistema — fundo colorido sozinho morre em cinza e em mono impresso. Supersede SH-P10 (2026-09-13, veredito dele "b-tirar-do-rail", MANIFESTO §209): até então o rail também levava a barra; medido, a pílula clara sobre o rail escuro é luminância (fronteira 5,31/7,87, SH15-b) e sobrevive ao cinza sozinha — a barra, desenhada para a sidebar (onde o ativo é só um fundo quase igual ao papel), lia como resíduo ao lado da pílula. A barra saiu dos 8 moldes com rail; suite-shell SH5-04 e suite-composicao PX-01/PX-02 provam a ausência |
Só fundo colorido · só aria-current (invisível para quem enxerga) · negrito sozinho (some em densidade compacta) · barra no rail (redundante com a pílula; supersedida) |
| SH6 | Navegação por perfil OMITE o item; ação indisponível MOSTRA com motivo | O MN6 decidiu que comando indisponível fica visível, com motivo, porque "menu é inventário de comandos". Navegação é outra coisa: mostrar "Faturamento" a quem não pode entrar não ajuda ninguém e revela a estrutura interna da empresa. A distinção preserva o MN6 no domínio dele | Item bloqueado na sidebar (ruído permanente + vazamento organizacional) · omitir também na ação (o usuário não entende por que a operação falhou) |
| SH7 | Troca de rota move o foco para o CONTEÚDO (tabindex="-1", nunca o landmark em si), com live region persistente anunciando a tela |
É o defeito nº 1 de aplicação de página única: o foco fica preso na navegação, o conteúdo troca e o usuário de leitor de tela não sabe. O alvo do foco não pode ser landmark, link nem botão — as três quebram por evidência documentada. O DS já tem o protocolo de live region no §1.13 | Não fazer nada (o comportamento padrão, e é o defeito) · focar o main como landmark (lê o conteúdo inteiro) · focar o primeiro link (some do fluxo de tabulação ao receber tabindex="-1") |
| SH8 | Skip link como PRIMEIRO elemento focável, visível ao receber foco | WCAG 2.4.1. Num ERP com dezenas de itens de menu, tabular por toda a navegação a cada tela é inviável — e o SH4 permite quatro níveis | Skip link permanentemente oculto (existe e não funciona) |
| SH9 | BUSCA fixa e centralizada na topbar, com o ATALHO IMPRESSO DENTRO DO CAMPO. Ela abre a command palette §39 — é a mesma busca, com dois caminhos de entrada. Escopo: navega, não consulta dado | Supersede da decisão anterior deste consolidado, que tirava o campo e deixava só o atalho. O campo torna o atalho descoberto por quem lê, em vez de decorado por quem foi treinado — e a referência do Rafael mostrou isso antes de a spec ser escrita. Busca de registro depende de índice no ERP: é produto, não DS | Só o atalho (aposta em treinamento) · campo que não abre o §39 (dois mecanismos de busca, duas fontes de verdade) · busca de registro no shell (fronteira de produto) |
| SH10 | TOPBAR — contrato de três zonas: identidade e contexto à esquerda · busca ao centro · ações globais e conta à direita. Slots nomeados; o produto escolhe o que entra. O título da tela vive no CONTEÚDO, não na topbar | Prática consolidada de produto enterprise: topo para contexto global, lateral para navegação primária — assim as duas camadas param de disputar o mesmo espaço. O Fiori põe o título na shell bar e paga com uma barra que faz duas coisas | Título na topbar (duplica o h1 do conteúdo e cria duas fontes de verdade sobre onde o usuário está) · topbar com conteúdo livre (vira depósito) |
| SH11 | Seletor de contexto existe, no topo à esquerda | Estava reservado e desligado por falta de decisão de produto; a referência do Rafael decide que existe | Seletor dentro da sidebar (some quando a sidebar some) · nascer sem ele (redesenho depois) |
| SH12 | Em tela estreita, rail e sidebar colapsam num ÚNICO drawer §31 em regime MODAL | O CN6 escolheu standard porque o caso é consultar sem sair da tela. Navegação é o oposto: você escolhe e sai. Em tela estreita o drawer cobre o conteúdo — página interativa atrás seria mentira semântica, e o APG só admite aria-modal quando o fundo está de fato bloqueado |
Drawer standard (incoerente com a tarefa) · rail persistente no celular (come 64 dos 360px) · sidebar espremida (não vira app, vira ERP ruim no celular) |
| SH13 | PAINEL LATERAL de detalhe: drawer §31 em regime STANDARD — inspecionar um registro sem sair da lista | Aqui o caso é consulta lado a lado: ler → navegar à fonte → comparar. É o caso central que criou o regime standard no DW1 e que o CN6 já exerceu | Modal (perde o contexto da lista, que é justamente o que motivou o painel) · navegação para tela cheia (perde a posição de rolagem e a seleção) |
| SH15 | CHROME NÃO SEGUE O TEMA. A superfície do rail e a tinta sobre ela são fixas nos dois temas — desde a CP-P3 (2026-08-14) a superfície é o gradiente --seed-rail-background (turquesa-700 → turquesa-800, CP20 adotado no gate G2) com tinta branca, e o item ativo é a pílula clara turquesa-100 com tinta turquesa-900 (SH15-b) |
Achado da medição, não do desenho. O rail consumia surface-inverse, que significa "o oposto do tema": no escuro ele virava uma barra clara (#F2F6F9) dentro de uma interface escura, e o rótulo sobre o item ativo media 1,48. O rail não quer ser o oposto do tema — quer ser estruturalmente escuro nos dois, como o chrome de aplicação que ele é. É o simétrico do DG12 da Fase 5 (tinta sobre dado não segue o tema, porque o objeto contrastado é claro nos dois modos). Medido no estado atual: branco sobre os dois extremos do gradiente 6,32/9,37 · pílula 5,31/7,87 de fronteira · tinta da pílula 11,37. (Errata E-CF-05 fechada na v0.66: esta linha ainda descrevia o valor da era cinza-900 — "e o item ativo usa #006C62 fixo" — duas gerações atrás do artefato: a E-CF-04 consolidou o parágrafo do §46.2 e esqueceu esta linha. A REGRA nunca mudou; o VALOR mudou duas vezes: cinza-900 → turquesa-700 (v6.3) → gradiente (CP-P3).) |
surface-inverse (inverte por definição — era o defeito) · rail claro no claro e escuro no escuro (perde a âncora visual que faz o chrome ser reconhecível entre temas) |
| SH14 | Uma região NUNCA faz o trabalho de outra. Se rail e sidebar coexistem, o rail é destino de topo e a sidebar é contexto | Duas navegações com o mesmo papel deixam o usuário de leitor de tela sem critério de escolha — quebra o SH2 por dentro. É a trava que permite a composição ser livre sem virar deriva | Sidebar como segundo rail · rail com itens de contexto |
| SH19 | **ESTADOS DO RAIL (2026-09-15, SH-P14): o rail tem DOIS estados, declarados no atributo data-rail do contêiner app (o mesmo elemento que nomeia o contêiner do SH12): expandido — o PADRÃO do SH3, 80 px, ícone 20 + rótulo visível, como TODA tela nasce — e recolhido — 56 px (item sp-12 = 48 + calha sp-1 = 4 de cada lado), item 48 × 48, ícone 24 px (IC4 "navegação"), rótulo FORA DA VISTA e NO DOM (clip de 1 px, nunca display:none: o nome acessível do destino não muda) que reaparece como tooltip em :hover e :focus-visible (§23: X1 é o rótulo · X3 Esc fecha sem mover o foco, corredor hoverable, carência de fechamento dur-expressive · X6 par surface-inverse/text-inverse, raio 6, a 8 px do alvo; o do PRIMEIRO destino desce para não cobrir o seletor de contexto — interseção 0 px², medida). Gatilho: um BOTÃO no próprio rail, na BASE (.alterna-rail, 48 × 44, a 8 px da base, último focável do rail — a ordem de Tab dos destinos não muda; aria-expanded = "o rail está expandido"; nome acessível "Recolher áreas"/"Expandir áreas"; ícones Lucide chevrons-left/chevrons-right, NM4 ②). Quem LEMBRA o estado é o PRODUTO: preferência do usuário, GLOBAL (nunca por tela), nasce expandido — as telas de referência não persistem nada (§46.5, porta do ERP). O recolhido NÃO existe abaixo do limiar do SH12 nem no toque (§23 X2): dentro do drawer o rail volta a 80 px com rótulos e o botão some. Emitido pelo módulo único shell_bloco.py nas onze telas; a régua CP-13 aceita 80 ou 56 conforme o atributo. |
Pergunta dele no gate do Grupo 2 (MANIFESTO §226.5): "o Rail pode ser minimizado pra a esquerda aparecendo apenas o icone e escondendo o nome? as telas devem ser responsivas." Estudo SH-P14 (§227.4): cinco de sete sistemas lidos têm o modo recolhido, quatro "só ícone" a 48 px com rótulo em tooltip, todos como ESCOLHA do usuário, nenhum como padrão em desktop largo nem no celular; +24 px de conteúdo medidos a 1440/1280/1024/900. Veredito dele, verbatim (2026-09-15, MANIFESTO §229): "V-SH14.1 modo recolhido: b · V-SH14.2 gatilho: a · V-SH14.3 posição do botão: a · V-SH14.4 quem lembra: a · veto: nenhum" — b = só o recolhido (V1 + V2, sem o expandido de 220 px); a = botão; a = base; a = preferência do usuário, global, nasce expandido. A "responsividade" da pergunta já tem dono (SH12): o recolhido é opção de desktop, não resposta a largura. |
Expandido de 220 px com rótulo em linha (a sidebar de 280 px JÁ é a expansão do rail — SH14; custaria 140 px de conteúdo: a 1024 a tabela do exemplo quebra) · gatilho por largura da janela (Fluent Auto: colidiria com o degrau único do SH12 a 860 e criaria um segundo limiar) · sobrevoo que expande (Carbon: abre sem querer, briga com 1.4.13 e com o toque) · recolhido como padrão ou como resposta a tela estreita (NN/g 2014; aí o certo é o drawer) · display:none no rótulo (apaga o nome acessível) · title como nome (X1) · persistir nas telas de referência (fronteira de produto, CN4) |
46.2 Anatomia, tokens e fronteiras#
Rail: largura 80px (SH3 — medido: 68px úteis = 9 caracteres; "Comercial" cabe); superfície
fixa nos dois temas (SH15 — o rail NÃO consome surface-inverse, que foi o defeito medido a
1,48), hoje o gradiente da rampa da marca via semântico próprio --seed-rail-background
(turquesa-700 #006C62 → turquesa-800 #005048; CP20 do seed-composicao.md, adotado no gate
G2 de 2026-08-14 e executado na CP-P3 — extremos medidos 6,32/9,37, tinta passa nos dois, nunca
na média); hover e pressionado do item consomem os overlays de chrome do SUP-6
(--seed-chrome-overlay-hover/-active, medidos em composição: 4,88/6,82 e 4,68/6,50);
ícone 24px do §45 + rótulo em micro-caps; item ativo pela regra do SH5; alvo de toque ≥44px.
(Errata E-CF-04 fechada na v0.65: este parágrafo dizia 64px, surface-inverse e implicava
cinza-900. Atualizado de novo na v0.66 pela CP-P3: a redação "gradiente admitido — adoção
pendente de gate visual" ficou falsa após o gate.)
Topbar: altura 60px; surface-raised com borda inferior border-subtle; z-index 60 (a
mesma faixa de chrome da escala 60<65<70<75<80 fixada no Bloco 4). Sidebar: largura 280px,
surface-page; indentação progressiva com fio de conexão em border-subtle; contador opcional
no fim da linha em mono; linha na densidade compacta do §40 (33px medidos), com alvo real de
toque garantido pela linha inteira, como no §28. Conteúdo: main com tabindex="-1" para o
SH7. Painel lateral: §31 integral em standard, z-index 65.
Colapso em tela estreita (SH12) — o número, fixado em 2026-09-15 (SH-P13): o limiar é 860 px de
CONTÊINER app (@container app (max-width: 860px)), nunca de janela — regra de reflow responde ao espaço
da aplicação (D4/CP27; a mesma tela dentro de um painel estreito colapsa igual). Vive no molde do shell desde
2026-08-14 (render conferido a 840/420/360, MANIFESTO §30) e desde a SH-P13 é EMITIDO pelo módulo único
shell_bloco.py para as onze telas com casca. Abaixo dele: rail e sidebar (nav "Seções") somem; o botão ☰
(.abre-nav, 44 × 44, PRIMEIRO item da zona esquerda da topbar, SH10; aria-haspopup="dialog") abre um
<dialog class="nav-drawer"> MODAL (showModal(), §31 DW3) de 300 px, máx. 88 % da janela, encostado à
esquerda, com superfície surface-page, sombra shadow-overlay + anel e o ::backdrop do §30; rail e sidebar
são MOVIDOS para dentro (não copiados: cópia duplica id e deixa botão sem ouvinte) e devolvidos ao fechar
(botão Fechar ou Esc); o foco entra no drawer e volta ao ☰ ao fechar. O painel .escopo de quadro/detalhe/gantt
não entra — se ele é a sidebar do shell ou painel de conteúdo é a SH-P12. Medido em 2026-09-15 nas onze
telas (Chrome, mede-casca.mjs): colapsa a ≤ 884 px de janela (884 − 24 px de calha = 860 de contêiner) e volta
a 885; a 390 e 768 px, 44 de 44 (tela × tema) com rail oculto, scrollWidth = janela, drawer modal com nav
"Áreas" (+ "Seções" onde há sidebar); a 1024 e 1366, 44 de 44 com rail de 80 px. Linha de base antes do conserto:
oito das dez telas transformavam o rail numa FAIXA horizontal de 74 px a 390 px — a forma que o SH12 descartou
por outro caminho — e duas (quadro, gantt) mantinham a coluna de 80 px com 274 px para o conteúdo; a 768 px as
dez mantinham o rail. O número 860 não deriva de norma: é o degrau em que rail (80) + sidebar (280) + calhas
deixariam menos de ~480 px ao conteúdo — calibrado no shell e aprovado em render; quem o mudar remede as onze.
Estado recolhido do rail (SH19) — fixado em 2026-09-15 (SH-P14, veredito dele em MANIFESTO §229): o contêiner app declara data-rail="expandido" (nascimento) ou data-rail="recolhido". Recolhido: rail 56 px = item sp-12 (48) + sp-1 (4) de cada lado (padding 8px sp-1, overflow: visible — o tooltip sai pela direita; custo declarado: nesse estado o rail não rola, e 12 destinos × 50 px + botão pedem ≥ 668 px de altura); item 48 × 48, ícone 24 px; o span do rótulo fica no DOM com clip de 1 px e, em :hover/:focus-visible, vira o tooltip do §23 (papel rotulo em caixa de sentença, surface-inverse/text-inverse — 13,86 claro · 12,75 escuro, medidos por token e no pixel —, radius-3, shadow-overlay, z-index 80, a sp-2 do item; no escuro com borda border-default); o tooltip do PRIMEIRO destino nasce com o topo a sp-2 abaixo do item (4 px abaixo da base da topbar), porque centrado cobriria o seletor de contexto — medido: interseção 0 px² com a topbar e com #b-contexto nos seis destinos, nos dois temas. Botão .alterna-rail: último filho do nav.rail, 48 × 44, margin-top: auto (8 px da base), transparente sobre o rail com sobrevoo/pressionado pelos overlays de chrome (SUP-6, como o item não ativo); type="button", aria-expanded (true de nascimento), nome "Recolher áreas"/"Expandir áreas"; dois SVG no DOM (Lucide chevrons-left/chevrons-right), o aria-expanded escolhe qual aparece; alterna_rail() troca o atributo e o nome — e NÃO grava nada. Dentro do dialog.nav-drawer (fora do .app) o seletor do estado não alcança: o rail volta a 80 px com rótulos e o botão fica oculto (medido a 390 e 768 com o atributo ligado, 44 de 44). Medido em 2026-09-15 nas onze telas (render-shell.mjs R5–R9, mede-rail.mjs): padrão → recolhido = rail 80 → 56, item 72 × 58 → 48 × 48, ícone 20 → 24, conteúdo +24 px em toda largura com rail visível; o único pixel novo em repouso é o glifo do botão na base do rail (64–73 px diferentes por tela × tema, caixa x 46–57).
Nenhum par de cor novo — mas compor pares medidos separadamente não garante que a
combinação passe, e o contraste-shell.py provou isso: a primeira execução deu 22 PASS ·
8 FAIL. Correções, todas por medição: o rail deixou de consumir surface-inverse (SH15) · o
contador e o placeholder saíram de text-muted (3,38 e 3,11 no claro) para text-secondary
(6,55 e 6,03) · o item ativo da sidebar deixou de ser texto de marca (4,23) e passou a texto
primário com barra em text-brand — a cor não carrega o estado, quem carrega é a barra e o
peso (SH5) · a sigla do seletor de contexto saiu de branco sobre surface-brand (2,71) para
branco sobre surface-brand-deep (6,32). Placar final: 32 PASS · 0 FAIL.
PENDÊNCIA SH-P1 — buraco na camada semântica, achado por este bloco. Nenhum token semântico de borda passa 3:1 contra
surface-raisedno tema claro:border-defaultmede 1,49 eborder-strong2,53. O campo de busca precisa de contorno que o identifique como componente (1.4.11), e a única saída medida foi consumir o primitivocinza-500(3,38 no claro · 4,50 no escuro). Isso é empréstimo declarado, não regra nova — e viola a lei "componente consome semântico". A correção certa é um token semântico novo na camada 2, e ela não pertence a este bloco: mexer nos três gêmeos por causa do shell seria decidir a camada de tokens dentro de um pattern. Fecha quando a camada 2 for editada por outro motivo, pela regra GI2.✅ FECHADA em 2026-08-14, pela via prevista (gatilho GI2 + decisão do Rafael: "vamos resolver logo"): a camada 2 foi editada pela CP-P3 (gêmeos v1.11) e, na mesma janela, os gêmeos v1.12 promovem o empréstimo a semântico —
--seed-border-interactive=cinza-500#788F9Dnos dois temas, medido contra as seis superfícies onde borda de componente aparece (3,38/3,38/3,11 claro · 4,50/5,51/5,05 escuro, todos ≥3,0), slot dark declarado (coincidência medida, não invariância). O campo de busca do shell consome o semântico desde o preview v0.3 — nenhum primitivo é mais consumido por exceção no §46. Alternativa descartada com número:cinza-600também passa (3,21–4,74), mas mudaria a cor RENDERIZADA que o gate visual já aprovou, sem motivo — a pendência pedia promoção de expressão, não de valor. A metade "separação de peça" já havia fechado no CP17 (par sombra+anel).
Errata E-CF-06 (2026-09-12, F10.4 /
MA-P6) — a conta do SH3 envelheceu, e o rótulo ativo vazava da pílula. O SH3 diz "Montserrat 9px caixa-alta mede 7,01px por caractere; 68px úteis = 9 caracteres": era verdade em agosto, quando o rótulo tinha 9 px. Na v1.14 dos gêmeos o papelmicropassou a 11 px e o rótulo do rail o consome desde então — medido em 2026-09-12 (Chrome real,mede-rotulo-rail.mjs): "COMERCIAL" a 600 = 68,94 px e a 800 = 69,52 px sem tracking; com o.02emlocal (0,22 px × 9) o ativo media 71,5 px dentro de um item de 72 px com 2 px de padding — a caixa de linha ia de x=18 a x=89,5 e a pílula acabava em x=88. Era isso que a régua de contraste rasterizado (F10.3) acusou comoMA-P6: um pixel do "L" final, cobertura total, fora da pílula, turquesa-900 sobre o gradiente do rail = 2,08. Conserto no gerador (gen-shell.pyv0.9, molde): a sobrescrita local de tracking sai e o rótulo consome o tracking do próprio papel (--seed-txt-micro-ls, −0,2 px) — o ativo cai para 67,7 px e cabe nos 68 úteis;max-width: 72pxno span como rede (excesso simétrico peloalign-items: center, nunca só pela direita). O contrato SH3 (rail 80 px · item 72 px · ≤ 9 caracteres por palavra) não muda; muda a conta que o justifica: a 11 px, 9 caracteres cabem nos 68 px úteis só com o tracking do papel (−0,2 px), não com tracking positivo. Depois do conserto:render-shell.mjs34 · 0 (o R2 voltou a medir "nenhum rótulo transborda" de verdade — com o span preso em 68 px ele passava enquanto o texto vazava do span) e a régua RC devolve o shell sem texto abaixo do piso nos dois temas.Pendência
SH-P9(2026-09-12) — peso 800 sem face 800. O shell e o painel declaramfont-weight: 800(rótulo ativo do rail, KPI, botão da solução, sujeito do hero) e os moldes só carregam Montserrat 400/500/600/700 (03-assets/fontes/montserrat/não tem ExtraBold): o navegador sintetiza o 800 a partir do 700 — medido: 700 e 800 têm o mesmo avanço (69,52 px), o que um ExtraBold real não teria. A guarda TP1 (guarda-tipografia-viva.mjs) não vê, porque mede se as faces DECLARADAS carregam, não se os pesos PEDIDOS têm face. Duas saídas, para o gate: (a) trazer o ExtraBold para o acervo e declará-lo nos moldes — muda o render de todo texto 800 e re-mede o rail (o rótulo cresce); (b) baixar os 800 para 700 nos moldes — o SH5 pede "mais peso" que o 600, e o 700 cumpre. Custo medido de (a): um arquivo TTF novo (licença OFL, a mesma), 2 moldes, e a régua RC nas duas telas; de (b): 2 moldes e asuite-shell.mjs(SH5-05 exige 800 no ativo). Dono: sessão, com o veredito dele. ✅ FECHADA em 2026-09-14 — por APLICAÇÃO da sessão, exposta a veto (MANIFESTO §223.4): não houve gate, porque a marca §4.1/§4.3 já decide (o sistema usa 400/500/600/700; 800 e 900 são display de marketing) e a mudança não altera um pixel — perguntar seria pedir só a concordância dele. Aplicado: os quatro papéis passam a declarar 700 nos dois moldes (e asuite-shellSH5-05, asuite-painelPN13-03/AC-09). Errata do enunciado, medida antes de aplicar: o navegador NÃO sintetiza o 800 — o Chrome só engrossa por síntese quando a face casada pesa menos de 600; com a face 700 carregada, "800" rende a própria 700 sem alteração: as capturas inteiras das duas telas nos dois temas saíram pixel-idênticas entre o estado anterior e o 700 declarado (0 px diferentes,mede-sh-p9.mjs), e a régua RC devolveu o mesmo placar (4 PASS · 0 FAIL). Logo (b) não muda um pixel: torna a declaração verdadeira. A alternativa (a) — o ExtraBold real da mesma linhagem (instância wght=800 da variável v9.000, medida byte a byte igual aos cinco TTF da casa) — foi renderizada nos dois temas: o rótulo "COMERCIAL" a 11 px passaria a medir 68,375 px (−0,375 px além dos 68 úteis do SH3; a RC ainda passava, 11,27 no pior pixel) e o H1 de toda tela (titulo-tela, 800) engrossaria em todas as telas; descartada porque a marca §4.1/§4.3 reserva 800/900 ao display de marketing — o sistema usa 400/500/600/700. O censo achou o mesmo800sem face em mais 24 moldes, no token--seed-txt-titulo-tela-weighte no KPI em JetBrains Mono (que só tem 400/500/700): pendência própria, com a TP1-d medindo "peso pedido tem face".✅
SH-P10FECHADA em 2026-09-13 — veredito dele, verbatim: "SH-P10: b-tirar-do-rail" (MANIFESTO §209). Aplicado: a barra saiu do rail nos 8 moldes (a da sidebar ficou), SH5 reescrito por região, suítes invertidas para provar a ausência. O registro do achado, como estava: a barra vertical do item ativo do rail: ele a viu como erro; é a marca do SH5. Verbatim dele, na aprovação do shell com material (MANIFESTO §207): "A Rail está com o menu Comercial selecionado, repare no canto esquerdo que tem uma barcação (barra vertical) essa barra nao deveria estar ali, acho que ela vem de outra estruta e é aplicada ali de maneira errada. verifique por favor." Medido: é o::beforede.rail-item[aria-current="page"]— barra branca de 3 px,left: -4px, do topo 8 px à base 8 px do item, encostada na borda interna do rail; não vem de outra estrutura: é a regra SH5 desta seção ("barra lateral de 3px mais peso tipográfico, nunca só fundo colorido"), aplicada ao rail desde o Bloco 6A, invisível até 2026-08-15 (vivia emleft: -8px, fora da caixa) e trazida para dentro pelo probe de pixel daquele dia; o gate de 2026-08-15/16 aprovou o shell com ela visível. A mesma barra existe nas outras sete telas com rail (.rail-item.ativo::beforenos moldes de chat, detalhe, gantt, lista, quadro, referência e tabela) e asuite-composicao.mjssonda o PIXEL dela (PX-01/PX-02); asuite-shell.mjsexige a regra (SH5-04). Por que ela lê como resíduo agora: com o material, a pílula clara ganhou volume e a barra ficou separada dela por 4 px de metal — e a pílula clara sobre o rail escuro já sobrevive ao cinza sozinha (é luminância: fronteira 5,31/7,87, SH15-b), com o peso 800 como segundo mecanismo; a barra foi desenhada para a sidebar, onde o ativo é só um fundo quase igual ao papel, e replicada no rail por simetria do SH5. É decisão registrada, logo supersede é dele. Duas saídas, renderizadas em cor e em cinza (folha SH-P10): (a) manter — nada muda; (b) tirar a barra do rail (a da sidebar fica) — o SH5 ganha a redação "no rail, a pílula clara é a marca que sobrevive ao cinza; a barra é da sidebar"; custo medido: 8 moldes (shell + 7 telas), SH5-04 dasuite-shell, as sondas PX-01/PX-02 dasuite-composicao(que passam a provar a AUSÊNCIA da barra fora da pílula), regeneração byte-idêntica das 8 telas e re-gate por captura — meia sessão. Dono: ele (veredito), depois a sessão. Nada foi mexido até o veredito.
Fora do shell, declarado: que menus existem e o que há dentro deles (projeto do ERP) · qual perfil vê o quê (regra de negócio) · persistência do estado da sidebar e do estado do rail (SH19: preferência do usuário, global, nasce expandido — V-SH14.4 = a; a tela de referência nunca persiste) (produto — Lovable/Supabase, mesma fronteira do CN4) · busca de registro (produto) · dashboard e composição de painel (bloco 6C) · site institucional (bloco 6B) · app nativo do cliente (fora do DS: tokens e componentes sim, layout de navegação não) · o que o slot de IA da topbar abre (sub-bloco próprio da F6 — o slot existe, o destino não é especificado aqui).
Consequência declarada da navegação por PROCESSO: como o mesmo objeto é alcançável por mais de um caminho, o breadcrumb §36 deixa de ser decoração e passa a responder por qual caminho eu cheguei — é ele que desambigua, não a sidebar.
46.3 Os 7 testes#
- Nenhum par de cor novo; todos herdados e medidos.
- Item ativo nunca depende só de cor (e, no estado recolhido do SH19, o rótulo nunca sai do DOM:
titlenão é nome,display:nonenão é clip —suite-shellSH3-04) — na sidebar barra + peso, no rail pílula clara + peso, sempre comaria-current(SH5; SH-P10). - Grayscale: rail, sidebar e ativo permanecem legíveis (DF4 como gate estrutural).
- Regra do um: um item ativo por região; uma região por papel (SH14).
- Landmarks: três a quatro
navsimultâneos, todos com nome único, nenhum contendo a palavra "navegação" (SH2). - Troca de rota: foco no conteúdo e anúncio na live region, sem foco em landmark, link ou botão (SH7); skip link é o primeiro focável (SH8).
- 360px: rail e sidebar colapsam em drawer modal único; nada transborda; alvos ≥44px (SH12) — e, desde a
SH-P14(SH19), comdata-rail="recolhido"ligado o drawer traz o rail a 80 px com TODOS os rótulos visíveis e o botão de alternar oculto (o recolhido não sobrevive ao colapso;render-shellR9). Até aSH-P13(2026-09-15) só atela-shellcumpria; desde então as onze telas com casca, medidas a 390/768 nos dois temas (44 de 44).
(SH-P14, 2026-09-15 — as quatro camadas remedidas com o SH19: suite-shell.mjs 84 · 0 (SH3-04 e SH3-07 reescritos com o sinal certo; seção SH19 com 12 asserts; cobaia do HEAD reprova 13), render-shell.mjs 54 · 0 (R5 geometria dos dois estados · R6 conteúdo +24 px por viewport · R7 tooltip por teclado sem cobrir topbar/seletor e Esc · R8 nascimento expandido sem persistência · R9 drawer com rótulos), contraste-shell.py 55 · 0 (SH-R9/R10, o par do tooltip por tema), RC rasterizada 22 de 22 telas × tema e, na cobaia com o tooltip aberto (shell-rail-recolhido-cobaia.html, autofocus no 1.º destino), o tooltip medido no pixel a 13,86 / 12,75; CP-13 11 de 11 aceitando 80 (padrão) ou 56 (recolhido declarado) — cobaia negativa a 58 px reprova por uma linha (57 cai na tolerância declarada de 1 px da régua).)
(Estado: estável desde 2026-08-11, por "aprovo" explícito do Rafael após o gate visual
sobre o preview v0.1. Quatro camadas cumpridas: suite-shell.mjs 68 PASS · 0 FAIL —
prova de que as guardas são reais: contra um preview com 5 defeitos deliberados, reprova em
8; render-shell.mjs em Chrome real 18 PASS · 0 FAIL; contraste-shell.py 32 PASS ·
0 FAIL após as correções que a própria medição exigiu; e o gate visual humano. Pendência que
o bloco levou consigo: SH-P1, que é da camada de tokens, não do shell — fechada em
2026-08-14 pelos gêmeos v1.12 (border-interactive; fechamento completo na própria
pendência, acima).)
46.4 SH17 — no PRODUTO, toda tela de aplicação vive dentro do shell; o gabarito é o conteúdo (F11.1, 2026-09-14)#
Por que esta regra nasce agora. Em 2026-09-14 a sessão do ERP construiu a tela "Configurar funil" seguindo o gabarito A18 (§86) — e a tela saiu sem shell: só uma barra superior, sem rail, sem sidebar. Ele reprovou de imediato, verbatim: "tem certeza que as telas sao assim? o quadro aprovado do ERP tem uma rail a esquerda, etc. to achando essa tela muito simplória". Medido depois (MANIFESTO §219): a tela de referência do A18 é publicada SEM a casca (raiz
tela, CP28 doseed-composicao.md— "arquétipo que roda SEM shell"), o §86 não cita o §46 uma vez, e nada no canon dizia com todas as letras o que todo mundo da casa sabia: no produto, a casca é o shell e o gabarito é o que vai dentro. Um agente de fora leu o gabarito como decisão de produto. Esta subseção fecha o buraco — e a página/telas/da vitrine passa a mostrar, por gabarito, se a referência traz a casca e onde ele vive no produto (lido desta tabela e medido no disco pelo gerador).
| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| SH17 | No produto (ERP e apps internos), TODA tela de aplicação vive dentro do shell §46: o shell é a CASCA (rail · topbar · sidebar · conteúdo, pelo princípio-mãe "contrato por região, composição livre") e o gabarito A1–A20 é o CONTEÚDO da região conteudo. A tela de referência de um gabarito pode ser publicada SEM a casca (raiz tela, CP28) para medir o conteúdo isolado — isso é decisão de BANCADA, nunca de produto. Fora do shell só o que não é tela de aplicação: autenticação (A19 — antes de haver sessão), página pública/institucional (A5, §47 — raiz pagina) e o documento quando EXPORTADO (A13 em PDF/impresso; na leitura dentro do app ele vive no shell). Quem constrói uma tela começa pelo §46 e só então abre o gabarito do conteúdo. |
O §46 diz que "qual região o produto liga é decisão do ERP" — e é; mas se o shell existe nunca foi pergunta: o ERP o decidiu no briefing de 2026-08-11 e todas as telas aprovadas com rail (quadro, lista, tabela, detalhe, gantt, chat, referência) o provam. Faltava a frase, e a ausência custou uma tela errada e duas rodadas de gate. | Escrever a casca dentro de cada gabarito (duplicaria o shell 16 vezes — o CP28 nasceu justamente para NÃO fazer isso); deixar como estava (o primeiro consumidor de fora errou, e a regra da casa diz que erro do criador é o aviso de que o acervo ensina errado). |
Os 16 gabaritos publicados, medidos no disco em 2026-09-14 (coluna "rail funcional" medida em 2026-09-15). A coluna
"referência traz a casca" é MEDIDA no HTML (class="rail" e class="topbar" presentes); a coluna "rail funcional
(medido)" também é medida — sim = o rail é o landmark do SH2, <nav class="rail" aria-label="Áreas">, com um
aria-current="page", main com id e tabindex="-1" e skip link (é o que o CP-13 do conferir-peca.py prova);
não = rail ilustrativo (role="img"), que existiu nas dez telas com casca até a SH-P11 (2026-09-15) — quem
copiava a casca de uma tela que não a tela-shell copiava casca de mentira; — = a referência não traz rail. A
coluna "no produto" é a decisão do SH17. O gerador da vitrine lê esta tabela pelo nome da tela, remede a casca E o
rail no disco e ABORTA se o medido divergir do escrito — a tabela nunca envelhece em silêncio. Desde a SH-P11 as
onze telas com casca emitem a MESMA casca do módulo único 06-validacao/ferramentas/shell_bloco.py (rail, skip
link, altura da topbar, foco do conteúdo — e, desde a SH-P13, o colapso do SH12: botão ☰, drawer modal e a regra de 860 px): copiar a casca de qualquer uma delas é copiar a do shell.
| gabarito | tela de referência | referência traz a casca? (medido) | no produto | por quê | rail funcional (medido) |
|---|---|---|---|---|---|
| A1 | tela-shell |
sim (é a casca) | é o shell | — | sim |
| A2 | tela-referencia · tela-lista |
sim | dentro do shell | tela de aplicação | sim |
| A3 | tela-tabela |
sim | dentro do shell | tela de aplicação | sim |
| A4 | tela-painel |
não (raiz conteudo) |
dentro do shell | o painel É a região de conteúdo do shell (§48; CP3: "o canvas do shell") — a referência mostra só a região | — |
| A5 | tela-site |
não (raiz pagina) |
FORA — página pública | não é aplicação (§47) | — |
| A7 | tela-quadro |
sim | dentro do shell | tela de aplicação — foi o quadro aprovado que ele citou ("tem uma rail a esquerda") | sim |
| A8 | tela-detalhe |
sim | dentro do shell | tela de aplicação | sim |
| A11 | tela-gantt |
sim | dentro do shell | tela de aplicação | sim |
| A13 | tela-documento |
não (raiz tela) |
dentro do shell na leitura; FORA quando exportado | ler um documento é uma tela do app; o PDF/impresso não tem chrome (C25 do §88) | — |
| A14 | tela-atividade |
sim | dentro do shell | tela de aplicação | sim |
| A17 | tela-busca |
sim | dentro do shell | tela de aplicação | sim |
| A18 | tela-configuracoes |
não (raiz tela) |
dentro do shell | configurações é ROTA do app (CF-01, §86); a navegação lateral das seções ocupa a região sidebar do shell (papel de contexto, SH14). Foi esta a tela que o ERP leu como "sem casca" |
— |
| A19 | tela-autenticacao |
não (raiz tela) |
FORA — antes da sessão | não há app antes de entrar | — |
| A20 | tela-onboarding |
sim | dentro do shell | o primeiro uso já é o app | sim |
| A23 | tela-chat |
sim | dentro do shell | tela de aplicação | sim |
Aplicado sem pergunta — exposto a veto (regra da casa): as três linhas que decidem o que o canon não dizia — A4 painel, A13 documento e A18 configurações dentro do shell — são aplicação do briefing do §46 e da reprovação dele de 2026-09-14, não decisão nova. Confirmadas por ele em 2026-09-14 (gate F11.1, verbatim: "V-F11.1 tabela SH17: confirmo · V-F11.2 login: aprovo · veto: nenhum", MANIFESTO §220.1) — desde então as três linhas são decisão dele, não aplicação da sessão.
46.5 SH18 — toda tela publicada declara o próprio arquétipo no <html> (V-LC11, 2026-09-15)#
Por que esta regra nasce. A LC-11 (MANIFESTO §223.5) deu à ficha de conformidade o item CP-13, que mede no navegador se uma tela de aplicação tem o shell deste §46 (rail de 80 px, topbar de 60 px,
maincom foco e id, skip link). O que a régua não sabe sozinha é se uma tela DEVE ter shell: pelo SH17, login, site e onboarding vivem fora dele. Ela lia a raiz de consulta do CP27 (appmede ·paginanão se aplica) e, quando a raiz eratelaouconteudo— gabarito publicado sem a casca —, dizia NÃO MEDI e pedia--arquetipoa quem roda. Uma IA que só recebe o HTML não tem como declarar. Veredito dele em 2026-09-15 (MANIFESTO §224.1), verbatim: "V-LC11 data-arquetipo: sim".
| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| SH18 | Toda tela publicada — referência da casa ou tela de consumidor (ERP, apps) — declara no <html> o atributo data-arquetipo com UM valor da lista fechada: aplicacao (tela de aplicação: o shell §46 é obrigatório e o CP-13 o mede) · autenticacao (antes da sessão, A19: sem shell) · pagina (página pública, A5/§47: sem shell) · bancada (referência publicada SEM a casca para medir o conteúdo isolado — raiz tela/conteudo, CP28: o shell não se aplica AO ARQUIVO; a coluna "no produto" do SH17 continua valendo para o gabarito) · documento (documento exportado, PDF/impresso: sem chrome, C25 do §88). O atributo declara o que ESTE HTML é; o SH17 declara onde o GABARITO vive no produto. |
Fato no artefato, não heurística — o mesmo princípio do CP27 (raiz de consulta declarada). Com o atributo, a régua mede sozinha e serve a qualquer IA sem instrução; valor fora da lista é FAIL no CP-13 (declaração errada é defeito do artefato); --arquetipo na linha de comando continua como sobrescrita explícita e sai impresso como tal, dizendo o que o artefato declarava |
Ficar com --arquetipo manual: custo zero agora, e cada consumidor teria de saber declarar. Adivinhar pela forma (contar class="rail"): régua que infere o tipo erra no primeiro caso misto |
Os 16 moldes declaram (2026-09-15): aplicacao — shell, tela-referencia, tela-lista, tela-tabela,
tela-quadro, tela-detalhe, tela-gantt, tela-atividade, tela-busca, tela-onboarding, tela-chat (as onze
com "referência traz a casca: sim" no SH17 — dez delas com casca ainda ilustrativa, SH-P11, e por isso reprovadas
pelo CP-13 até a SH-P11 fechar: é a verdade, não um defeito da declaração) · bancada — painel,
tela-configuracoes, tela-documento (as três publicadas sem a casca) · autenticacao — tela-autenticacao ·
pagina — site. O shell do ERP declara aplicacao (src/routes/__root.tsx). Casca ilustrativa não existe mais como categoria (SH-P11, 2026-09-15, MANIFESTO §225.5): referência que mostra o shell traz o shell REAL emitido pelo módulo shell_bloco.py (rail nav[aria-label="Áreas"], skip link, main#conteudo[tabindex="-1"]); referência que NÃO traz a casca declara bancada — é o que a fila chamava de "o CP-13 aceita casca ilustrativa como não se aplica declarado".
Porta do ERP para o ESTADO DO RAIL (SH19,
SH-P14, 2026-09-15 — é aqui que o V-SH14.4 = a vive). O DS entrega os dois estados, o contrato do atributo e o comportamento do botão; o ERP implementa: (1) o contêinerappdo shell declaradata-rail="expandido"ou"recolhido"— e nasceexpandidopara todo usuário; (2) o botão.alterna-railna base do rail (o mesmo do módulo:aria-expanded, "Recolher áreas"/"Expandir áreas", chevrons do Lucide) chamaalterna_rail(); (3) a preferência é do USUÁRIO e GLOBAL — gravada por usuário (Supabase, mesma fronteira do CN4 e da persistência da sidebar), nunca por tela nem por dispositivo/sessão: recolher numa tela e achar expandido na seguinte é o defeito que oIsPaneOpenglobal do Fluent evita; ao entrar, o shell lê a preferência e aplica o atributo ANTES do primeiro desenho (sem salto de 24 px); (4) abaixo do limiar do SH12 e no toque o estado não se aplica (o drawer traz o rail com rótulos) e a preferência fica guardada para o desktop; (5) o tooltip do recolhido segue o §23 como o módulo o emite (posição do 1.º destino, Esc, carência). Verbatim dele: "V-SH14.1 modo recolhido: b · V-SH14.2 gatilho: a · V-SH14.3 posição do botão: a · V-SH14.4 quem lembra: a · veto: nenhum".
Tinta de marca no shell (V-CT9 = a, MANIFESTO §224.1): item ativo, contador ou rótulo que use tinta de marca sobre
surface-subtleousurface-brand-subtle(sidebar, pílula, badge) usatext-brand-strong— a regra mora no §73.5; o censo da CT-P9 (208 de 208 HTML) não achou ocorrência viva nas telas.
Também cita o §46: tela-atividade, tela-busca, tela-chat, tela-detalhe, tela-gantt, tela-lista, tela-onboarding, tela-quadro, tela-referencia, tela-tabela.