[
  {
    "chave": "CS-174",
    "territorio": "frontend",
    "titulo": "O PAPEL E' O CHAO, E O CARTAO GANHA A BORDA QUE O §2.2 EXIGE — criterio 1. MEDIDO HOJE, ⛔ nao suposto: `grep -rl FDFBF6 src/` da' **0 ficheiros** e o fundo de ecra e' `--md-sys-color-surface: #FAF9FD` (`src/estilo/tokens.css:70`), servido em `tokens.css:228` e em `src/app/raiz.module.css:56` (`surface-container-lowest`). ⟹ Os tres tokens do papel (`papel #FDFBF6` · `papelPainel #F7F5EE` · `papelDivisoria #E2DFD6`) sao trabalho por fazer. 🩸 E A BORDA ⛔ NAO E' ENFEITE: o §2.2 mede **1,03 de contraste** entre `#FFFFFF` e `#FDFBF6` ⟹ SEM BORDA O CARTAO DESAPARECE NO PAPEL. Medido em `base.module.css` no bloco `.cartao`: ha' `border-radius`, `background`, `box-shadow` e ⛔ **NENHUM `border:`**. ⚠️ O cartao CONTINUA `#FFFFFF` (`surface-container-lowest`) — ⛔ nao se pinta de papel: e' branco SOBRE papel, e e' dai' que vem a leitura de caderneta (§2.2). ⚠️ A `papelDivisoria` da' **1,34** sobre papel ⟹ e' DECORATIVA, como a `outlineVariant` (§2.5.4): ⛔ nunca fronteira que carregue sentido sozinha. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca em `componentes/molde`, em `ListaDensa`, nos blocos, nos estados, na casca nem em pagina nenhuma de `src/app/**` fora da raiz — o fundo entra pelo token e pela raiz, e as 34 paginas herdam-no. ⛔ Nao se reabre estilo (regras 78 a 86).",
    "escopo_paths": [
      "frontend/src/estilo/tokens.css",
      "frontend/src/componentes/base/base.module.css",
      "frontend/src/componentes/base/Cartao.tsx",
      "frontend/src/app/raiz.module.css",
      "frontend/src/app/layout.tsx",
      "frontend/e2e/tokens-servidos.spec.ts"
    ],
    "aceites": [
      "cd frontend && grep -q -- '--md-sys-color-papel: #FDFBF6' src/estilo/tokens.css && grep -q -- '--md-sys-color-papel-painel: #F7F5EE' src/estilo/tokens.css && grep -q -- '--md-sys-color-papel-divisoria: #E2DFD6' src/estilo/tokens.css",
      "cd frontend && grep -qE 'background:\\s*var\\(--md-sys-color-papel\\)' src/estilo/tokens.css",
      "cd frontend && sed -n '/^\\.cartao {/,/^}/p' src/componentes/base/base.module.css | grep -qE '^\\s*border:' && sed -n '/^\\.cartao {/,/^}/p' src/componentes/base/base.module.css | grep -qE 'background:\\s*var\\(--md-sys-color-surface-container-lowest\\)'",
      "cd frontend && grep -q -- '--md-sys-color-papel: #FDFBF6' src/estilo/tokens.css && test $(grep -rhoE '#[0-9a-fA-F]{6}' --include='*.module.css' --include='*.tsx' src/ | wc -l) -eq 0",
      "cd frontend && npx playwright test e2e/tokens-servidos.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": []
  },
  {
    "chave": "CS-175",
    "territorio": "frontend",
    "titulo": "AS TRES PECAS NOVAS ENCAIXAM NA PALETA **ANTES** DO NORMALIZADOR E ENTRAM MONO: `pecas.ts` passa de **39** para **42** — criterios 4, 5 e 6. 🩸 O NUMERO QUE OBRIGA A ESTE CARD, medido peca a peca em `_produto/design/exports/desenhos/`: `ex-lupa` traz **14 cores**, `nu-unidade` **11**, `ac-exportar` **21** — contra **2** em `ex-check`, que e' uma das 39 que ja' entraram. E o normalizador do repo ASSUME MONO: a regra N4 (`scripts/normalizar-icones.mjs:126`) tira o `fill` de todo o caminho ESCURO e anexa o recorte BRANCO ao ultimo escuro que o precede. ⟹ PASSADAS COMO ESTAO, SAEM BORRAO. ⟹ O ENCAIXE DE COR VEM ANTES, e ⛔ nao depois. 🩸 E O ENCAIXE ENTRA NO PRODUTO, ⛔ NAO FICA NA FABRICA: `bin/encaixarcores.py` (44 linhas) faz exactamente isto e vive em `/srv/fab`, onde a regra 296 proibe escrever ⟹ o passo e' PORTADO para `frontend/scripts/`. ⛔ Nao se chama nada de `/srv/fab` a partir do produto. ⚠️ ⛔ NAO INVENTA COR NENHUMA: aproxima cada `fill` a' mais PERTO da paleta que lhe dao — azul `#144777` · areia quente · branco (regra 98). ⚠️ E O NORMALIZADOR CONTINUA IDEMPOTENTE (o proprio ficheiro o declara, linha 17): correr duas vezes devolve **byte a byte** o mesmo. Isso e' aceite, ⛔ nao promessa. ⛔ ZERO DE ENSAIO E ZERO RECUSADAS: os prefixos `svg-` `v3-` `traco-` ja' estao em `PREFIXOS_DE_ENSAIO` e ⛔ nao entram; `exports/recusados/` tem **18 SVG** medidos (o texto da demanda diz 22 — a contagem certa e' 18) e ⛔ nenhuma entra. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca em `Icone.tsx` (e' o CS-177 que mapeia nome⟶peca), ⛔ nao toca nas 4 pecas de ELENCO (sao multicor e tem caminho proprio, CS-176), ⛔ nao desenha peca nenhuma (regra 306) e ⛔ nao encomenda nada.",
    "escopo_paths": [
      "frontend/scripts/normalizar-icones.mjs",
      "frontend/scripts/encaixar-cores.mjs",
      "frontend/src/assets/icones",
      "frontend/e2e/icones.spec.ts"
    ],
    "aceites": [
      "cd frontend && test -f scripts/encaixar-cores.mjs && ! grep -rq '/srv/fab' scripts/",
      "cd frontend && test $(ls src/assets/icones/*.svg | wc -l) -ge 42 && for p in ex-lupa nu-unidade ac-exportar; do test -f src/assets/icones/$p.svg || exit 1; done",
      "cd frontend && test $(grep -cE \"^\\s*'[a-z]+-[a-z-]+':\" src/assets/icones/pecas.ts) -ge 42 && grep -q \"'ex-lupa'\" src/assets/icones/pecas.ts && grep -q \"'nu-unidade'\" src/assets/icones/pecas.ts && grep -q \"'ac-exportar'\" src/assets/icones/pecas.ts",
      "cd frontend && test $(ls src/assets/icones/*.svg | wc -l) -ge 42 && ! grep -rlq c2pa src/assets/icones/ && test $(grep -l 'fill=\"currentColor\"' src/assets/icones/*.svg | wc -l) -ge 42",
      "cd frontend && test $(ls src/assets/icones/*.svg | wc -l) -ge 42 && ! grep -rhoE 'rgb\\([0-9]+, ?[0-9]+, ?[0-9]+\\)' src/assets/icones/*.svg | grep -q .",
      "cd frontend && test $(ls src/assets/icones/*.svg | wc -l) -ge 42 && ! grep -q 'M00L20480L20482048L02048L00z' src/assets/icones/*.svg",
      "cd frontend && test $(ls src/assets/icones/*.svg | wc -l) -ge 42 && test $(ls src/assets/icones/ | grep -cE '^(svg-|v3-|traco-)') -eq 0",
      "cd frontend && rm -rf /tmp/n1 /tmp/n2 && node scripts/normalizar-icones.mjs src/assets/icones /tmp/n1 && node scripts/normalizar-icones.mjs /tmp/n1 /tmp/n2 && diff -r /tmp/n1 /tmp/n2",
      "cd frontend && npx playwright test e2e/icones.spec.ts --reporter=line",
      "cd frontend && rm -f e2e/capturas/d48-icones-24px.png && CAPTURAS=1 npx playwright test e2e/icones.spec.ts --reporter=line && test -f e2e/capturas/d48-icones-24px.png",
      "cd frontend && npx next build"
    ],
    "depende_de": []
  },
  {
    "chave": "CS-176",
    "territorio": "frontend",
    "titulo": "AS QUATRO PECAS DE ELENCO ENTRAM POR CAMINHO MULTICOR PROPRIO — ⛔ NAO PELO NORMALIZADOR MONO (criterio 4, parte do elenco). 🩸 PORQUE E' CAMINHO PROPRIO, MEDIDO: `elenco-chefe` traz **7 cores**, `elenco-especialista` **3**, `heroi-entrada` **3**, `aula-topo` **3**. O normalizador mono tira o `fill` do caminho escuro e anexa o recorte BRANCO ⟹ PASSADAS POR ELE PERDIAM A AREIA. As quatro sao de TRES cores por desenho (azul `#144777` · areia · branco) e cada cor entra POR TOKEN, ⛔ nunca cozida. ⚠️ ESTAS QUATRO ⛔ NAO SAO ICONES e ⛔ NAO entram em `pecas.ts` nem em `NomeDeIcone`: sao IMAGEM (§10.3) e vivem em `src/assets/elenco/`. ⛔ Nao se misturam com o lote dos 42. 🩸 SO' HA' DOIS RETRATOS — a chefe e o especialista (§16.4-A.3, a' letra) — e quem ⛔ nao tem retrato leva MONOGRAMA, que o produto ja' sabe fazer (`src/componentes/base/monograma.ts`). ⛔ NAO SE CORTA UMA PECA DE CORPO INTEIRO NUM CIRCULO DE 34px: isso ⛔ nao e' retrato, e' borrao — esta' escrito no §16.4-A.3 e e' trava. ⚠️ O `heroi-entrada` e o `aula-topo` ⛔ NAO sao retratos: um e' figura recortada sobre `primaryContainer` (entrada) e o outro PREENCHE um rectangulo e sangra (topo do cartao de aula, 16:9, cantos de cima 12dp) — e ai' o fundo E' conteudo (regra 104). ⛔ O QUE ESTE CARD ⛔ NAO FAZ: 🩸 ⛔ NAO SE DESENHA PECA NOVA DE ELENCO — ordem do dono, a' letra, no texto da demanda. ⛔ Nao toca em `src/assets/icones`, ⛔ nao toca no normalizador mono, ⛔ nao poe imagem em lista densa, em estado, em bloco, em ranking nem em dialogo (§10.3: imagem e' CONTEUDO, ⛔ nao papel de parede). E toda a imagem leva `alt` que descreve o que la' esta'.",
    "escopo_paths": [
      "frontend/scripts/elenco-multicor.mjs",
      "frontend/src/assets/elenco",
      "frontend/src/componentes/elenco",
      "frontend/e2e/elenco.spec.ts"
    ],
    "aceites": [
      "cd frontend && for p in elenco-chefe elenco-especialista heroi-entrada aula-topo; do test -f src/assets/elenco/$p.svg || exit 1; done",
      "cd frontend && test -d src/assets/elenco && test $(ls src/assets/elenco/*.svg | wc -l) -ge 4 && ! grep -rlq c2pa src/assets/elenco/",
      "cd frontend && test -d src/assets/elenco && test $(ls src/assets/elenco/*.svg | wc -l) -ge 4 && ! grep -rhoE 'rgb\\([0-9]+, ?[0-9]+, ?[0-9]+\\)' src/assets/elenco/*.svg | grep -q .",
      "cd frontend && test $(grep -l 'var(--md-sys-color-' src/assets/elenco/*.svg | wc -l) -ge 4",
      "cd frontend && test -d src/assets/elenco && test $(ls src/assets/elenco/*.svg | wc -l) -ge 4 && ! grep -qE \"'(elenco-chefe|elenco-especialista|heroi-entrada|aula-topo)'\" src/assets/icones/pecas.ts",
      "cd frontend && test -d src/componentes/elenco && grep -rq monograma src/componentes/elenco",
      "cd frontend && test $(grep -rhoE 'alt=' src/componentes/elenco | wc -l) -ge 1",
      "cd frontend && npx playwright test e2e/elenco.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": []
  },
  {
    "chave": "CS-177",
    "territorio": "frontend",
    "titulo": "ICONE EM CADA PORTA DA BARRA, A 18dp, E A BARRA EM DOIS ANDARES — criterios 2 e 3, e paga o criterio 2 da demanda 47 que ⛔ NAO foi cumprido. 🩸 MEDIDO POR MIM EM `lib/navegacao.ts`, expandindo porta×papel (⛔ nao contando o array): sao **16 portas** e **28 pares porta-papel** — SECRETARIA **12** · COORDENADOR **4** · ESPECIALISTA **6** · MEDICO **6** — para **12** nomes de icone. E AS COLISOES DENTRO DO MESMO MENU: SECRETARIA `description` **2x** (Questoes, Protocolos) · ESPECIALISTA `star` **2x** (Avaliacoes, Artigos) **e** `description` **3x** (Questoes, Protocolos, Publicar artigo) ⟹ **5 das 6 portas do especialista com desenho repetido**. 🩸 E O QUE ESTE CARD PODE FECHAR, E O QUE ⛔ NAO PODE — medido, e dito antes de alguem o descobrir no QA: `SEM_PECA` tem **4** nomes (`domain`, `bar_chart`, `school`, `groups`, `Icone.tsx:174`) e `PECA_DE` encomenda-lhes 4 chaves que o lote ⛔ NAO TEM (`un-upa`, `ex-relatorio`, `ex-formacao`, `ex-turma`). Das 42 aprovadas, as unicas ⛔ NAO atribuidas e ⛔ nao clinicas sao **tres**: `nu-unidade`, `ex-lupa` e `ac-exportar` — todas as outras livres sao `nu-*` e `s-*`, que sao MARCAS DE NUCLEO e a regra 100 proibe em porta («o simbolo clinico marca A MATERIA, ⛔ nunca uma porta»; esta' escrito no proprio `navegacao.ts:290`). ⟹ ESTE CARD FECHA O QUE E' ALCANCAVEL: `domain` passa a `nu-unidade` e `SEM_PECA` cai de **4 para 3**; `ex-lupa` veste a BUSCA da barra, que o §11 nomeia a' letra como indo sem icone. ⟹ `SEM_PECA = []` e «ZERO COLISAO» EXIGEM ~6 PECAS QUE ⛔ NAO EXISTEM e que SO' O ESTUDIO desenha — ver a OBSERVACAO do enquadramento. A falta fica **ESCRITA e CONTADA** em `SEM_PECA`, que e' o mecanismo que a regra 294 fixou, ⛔ nao disfarcada num `undefined`. ⚠️ A BARRA USA 18dp e os SETE que ⛔ nao se leem a esse tamanho ⛔ NAO servem aqui (§11, nominal): `ex-cronometro` · `nu-cirurgia` · `cp-crm` · `cp-identificacao` · `nu-paliativos` · `nu-psiquiatria` · `s-neuro`. Os restantes 32 leem-se a 18dp — a trava e' NOMINAL e ⛔ nao geral. ⚠️ DOIS ANDARES EM TODAS AS LARGURAS, REFLUIDA (regras 303 §2 e 304): busca e avisos em cima, a accao que cada perfil mais usa a' direita. ⛔ NENHUMA CASCA DE APP DE TELEMOVEL — as tres portas que a justificam vivem no CS-120, que ⛔ nao esta' no `main`. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao acrescenta porta nenhuma, ⛔ nao mexe em `papeis` de porta nenhuma (e' permissao, e e' do dono), ⛔ nao toca `lib/moldes.ts`, ⛔ nao toca pagina nenhuma de `src/app/**`, ⛔ nao aceita `icone: undefined` (o CS-153 fechou o tipo e ⛔ nao se desfaz) e ⛔ nao desenha peca a' mao: `PrimitivasTemporarias.tsx` SAI do caminho das portas que ja' tem peca. === 🩸 O QUE O DEV ⛔ NAO TEM DE ADIVINHAR, porque eu medi e escolhi: (1) `domain` ⟶ `nu-unidade` (a UPA e' UNIDADE, ⛔ nao simbolo clinico — e' o unico `nu-*` que a regra 100 deixa numa porta). (2) `ex-lupa` ⟶ a BUSCA do andar de cima, que o §11 nomeia a' letra como indo sem icone. (3) `ac-exportar` ⟶ **«Publicar artigo»** (`/especialista/artigos`), que e' o acto de por um artigo PARA FORA ⟹ fecha UMA das colisoes de `description` do especialista, e e' a unica das 42 aprovadas que carrega esse sentido sem ser marca de nucleo. ⟹ Fica `description` 2x na SECRETARIA e `star` 2x + `description` 2x no ESPECIALISTA. === A GUARDA QUE ESTE CARD ESCREVE E QUE FICA NO REPO: `scripts/conferir-portas.mjs` expande porta×papel (⛔ nao conta o array) e sai com 1 se os icones REPETIDOS dentro de um mesmo menu passarem de **3**, ou se alguma porta trouxer um dos SETE que ⛔ nao se leem a 18px. HOJE mede **4** ⟹ o aceite falha hoje e passa com o remap. ⚠️ O numero **3** ⛔ NAO e' o alvo do dono (ele quer 0): e' o PISO alcancavel sem peca nova, e a diferenca esta' na OBSERVACAO O-A do enquadramento.",
    "escopo_paths": [
      "frontend/src/lib/navegacao.ts",
      "frontend/src/componentes/base/Icone.tsx",
      "frontend/src/componentes/casca",
      "frontend/scripts/conferir-portas.mjs",
      "frontend/e2e/navegacao.spec.ts",
      "frontend/e2e/casca.spec.ts"
    ],
    "aceites": [
      "cd frontend && grep -q \"domain: 'nu-unidade'\" src/componentes/base/Icone.tsx",
      "cd frontend && test $(sed -n '/^export const SEM_PECA/p' src/componentes/base/Icone.tsx | grep -o \"'\" | wc -l) -le 6",
      "cd frontend && grep -qE \"search: 'ex-lupa'\" src/componentes/base/Icone.tsx && grep -rq search src/componentes/casca/",
      "cd frontend && node scripts/conferir-portas.mjs",
      "cd frontend && grep -qE '^\\.(barraAndar|andarUm|andarDois|doisAndares)' src/componentes/casca/casca.module.css",
      "cd frontend && ! grep -q 'icone: undefined' src/lib/navegacao.ts",
      "cd frontend && npx playwright test e2e/casca.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/navegacao.spec.ts --reporter=line",
      "cd frontend && rm -f e2e/capturas/d48-barra-*.png && CAPTURAS=1 npx playwright test e2e/casca.spec.ts --reporter=line && test $(ls e2e/capturas/d48-barra-*.png | wc -l) -ge 4",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-175"
    ]
  },
  {
    "chave": "CS-178",
    "territorio": "frontend",
    "titulo": "O VOCABULARIO DO BLOCO SUBSTITUI O EMPRESTADO: os quatro estados com FORMA propria, o MEDIDOR contavel, e o VAZIO e o A-CARREGAR saidos da GRELHA 5×5 — criterios 9 e 10. 🩸 MEDIDO: `src/componentes/base/estados.tsx` serve `<Icone nome=\"inbox\" tamanho={48} />` (linha 77) e `<Icone nome=\"progress_activity\" tamanho={48} />` (linha 110) — um CAIXOTE a dizer «vazio» e uma peca emprestada a dizer «a carregar». O §16.4-A.2 manda exactamente trocar isto pela GRELHA 5×5: o vazio e' **a grelha por encher**, o a-carregar e' **a mesma grelha a encher-se**. ⟹ «Um caixote ou uma lupa a dizer vazio sao vocabulario de fora»: o estado passa a falar a lingua do produto — *ainda ⛔ nao contou nada*. 🩸 E A REGRA DE CONSTRUCAO ⛔ NAO SE INVENTA, e' o §16.1 e e' DETERMINISTA: celula **4** · passo **5** (folga 1) · meio-passo **2,5** · raio **28%** da celula; a grelha 5×5 enche exactamente **24** ⟹ ⛔ nenhum numero solto, ⛔ nenhum hex solto. PASSO INTEIRO = contagem (blocos separados); MEIO-PASSO = um gesto (blocos tocam-se, juntas redondas). 🩸 OS QUATRO ESTADOS COM FORMA PROPRIA, ⛔ NAO SO' COR (§16.4.1): validado **visto** · a' espera **ponteiros** · ⛔ nao validado **barra** · por vir **bloco vazado**. Isto cumpre sozinho a trava do §2.5.3 («cor ⛔ nunca e' sinal unico»). 🩸 O MEDIDOR: A BARRA LISA CAI (§16.4.2). A carga conta-se em BLOCOS — **um por hora** — e nas listas em **decimos**. «Uma barra lisa diz mais ou menos dois tercos; dez blocos dizem faltam-lhe seis horas e quarenta, e contam-se com o dedo.» E O TOTAL EM TABULAR FICA **AO LADO**, ⛔ NUNCA EM VEZ: o numero e' o resultado, os blocos sao a prova. ⚠️ ZERO `<progress>` E ZERO `role=\"progressbar\"` a representar minutos validados ou carga. MEDIDO: ha' **UM SO'** no produto, `componentes/leitor/LeitorDeGravacao.tsx:475`, e e' TEMPO DE VIDEO ⟹ **FICA**, e esta' fora desta cerca de proposito. 🩸 BLOCO PERDIDO E' **VAZADO** — ⛔ NAO VERMELHO e ⛔ NAO RISCADO. Errar ⛔ NAO TIRA PONTOS (regra 56) e ⛔ nao ha' castigo na cara deste produto. ⚠️ OS SEIS ESTADOS CONTINUAM TODOS, e o PARCIAL ⛔ nao regride — e' «o mais importante deste produto» (§8.6): validado + a' espera + perdido ao mesmo tempo, o total em tabular ao lado, e a LINHA que explica a diferenca entre o que se assistiu e o que contou. Os outros quatro (erro, sem permissao, sucesso, e o corpo do vazio) ⛔ nao perdem nada: `warning`, `lock` e `check` a 48dp FICAM. ⚠️ Cada bloco tem NOME ACESSIVEL PROPRIO e e' percorrivel por teclado (§7.2.4): um medico com leitor de ecra tem de saber QUAL bloco perdeu. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `ListaDensa` nem os moldes (CS-179), ⛔ nao toca pagina nenhuma de `src/app/**`, ⛔ nao poe faixa em lado nenhum (CS-183), ⛔ nao mexe no leitor de video, ⛔ nao acrescenta movimento (CS-185) e ⛔ nao inventa estado novo.",
    "escopo_paths": [
      "frontend/src/componentes/base/estados.tsx",
      "frontend/src/componentes/base/FitaDeBlocos.tsx",
      "frontend/src/componentes/fita",
      "frontend/src/componentes/base/base.module.css",
      "frontend/e2e/estados.spec.ts",
      "frontend/e2e/fita-blocos.spec.ts"
    ],
    "aceites": [
      "cd frontend && ! grep -qE 'nome=\"(inbox|progress_activity)\" tamanho=\\{48\\}' src/componentes/base/estados.tsx",
      "cd frontend && grep -qE 'grelha|Grelha' src/componentes/base/estados.tsx",
      "cd frontend && grep -qE 'grelha|Grelha' src/componentes/base/estados.tsx && for n in warning lock check; do grep -q \"nome=\\\"$n\\\"\" src/componentes/base/estados.tsx || exit 1; done",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx && ! grep -rqE '<progress|role=\"progressbar\"' src/componentes/base/ src/componentes/fita/",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx && test $(grep -rcE 'role=\"progressbar\"' src/ | grep -v ':0' | wc -l) -eq 1 && grep -q 'role=\"progressbar\"' src/componentes/leitor/LeitorDeGravacao.tsx",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx && grep -qE 'tabular-nums|tabular' src/componentes/base/FitaDeBlocos.tsx src/componentes/base/base.module.css",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx && ! sed -n '/^\\.bloco/,/^}/p' src/componentes/base/base.module.css | grep -qE 'error|#BA1A1A|vermelho'",
      "cd frontend && grep -q visto src/componentes/base/FitaDeBlocos.tsx && grep -q ponteiros src/componentes/base/FitaDeBlocos.tsx && grep -q vazado src/componentes/base/FitaDeBlocos.tsx && grep -rqE 'nomeAcessivel|aria-label' src/componentes/base/FitaDeBlocos.tsx",
      "cd frontend && npx playwright test e2e/estados.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/fita-blocos.spec.ts --reporter=line",
      "cd frontend && rm -f e2e/capturas/d48-estados-*.png && CAPTURAS=1 npx playwright test e2e/estados.spec.ts --reporter=line && test $(ls e2e/capturas/d48-estados-*.png | wc -l) -ge 6",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-174"
    ]
  },
  {
    "chave": "CS-179",
    "territorio": "frontend",
    "titulo": "A GRAMATICA (b) ENTRA NOS COMPONENTES: a LISTA DENSA passa a REGUA de ponta a ponta e os TRES MOLDES passam a expressar as duas gramaticas do §15.1 — criterio 7, primeira metade. 🩸 PORQUE ESTE CARD VEM ANTES DAS PAGINAS: os tres moldes foram construidos e aprovados no CS-171 **antes de o papel e a regua existirem**. Vestir 34 paginas num molde que ainda fala a gramatica (a) era vesti-las duas vezes. 🩸 O §15.1 FOI CORRIGIDO PELA REGRA 308 E TEM **DUAS** GRAMATICAS VALIDAS, ⛔ nao uma, e ⛔ nao ha' uma terceira: **(a)** cartao branco de canto arredondado, sombra suave, separado por espaco — para conteudo que se **escolhe** (aula, curso, nucleo); **(b)** faixa cheia em `primary` e REGUA de ponta a ponta — para o **registo** e para listas densas que se **leem**. ⟹ ⛔ NAO BATE quem embrulhe o registo num cartao a flutuar, e ⛔ NAO BATE canto recto. ⚠️ A LISTA DENSA E' O INSTRUMENTO DO COORDENADOR, que varre oitenta nomes: a ORDEM DAS COLUNAS e' a MESMA em todo o produto — [avatar da UPA] | nome + CRM | numero tabular a' direita | ETIQUETA DE ESTADO SEMPRE NA ULTIMA COLUNA (§5.4). E' isto que a torna varrivel A UM METRO: o olho desce UMA coluna. ⛔ Sem zebra; rato = camada 8% e ⛔ NAO levanta a linha. ⚠️ E O NUMERO QUE ESTE CARD SERVE: a regua vale nas **12** paginas que usam `ListaDensa` — e e' por isso que ela se conserta UMA vez aqui, no componente, e ⛔ nao doze vezes nas paginas. ⚠️ O MEDIDOR EM DECIMOS nas listas vem do CS-178 e aqui so' se CONSOME: ⛔ nao se redesenha bloco. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca pagina nenhuma de `src/app/**` (sao os CS-180 a CS-183), ⛔ nao toca `lib/moldes.ts` (o manifesto esta' certo e e' a REGUA da conferencia), ⛔ nao toca a casca, ⛔ nao acrescenta movimento e ⛔ nao reabre estilo.",
    "escopo_paths": [
      "frontend/src/componentes/base/ListaDensa.tsx",
      "frontend/src/componentes/molde",
      "frontend/src/componentes/base/base.module.css",
      "frontend/e2e/moldes.spec.ts",
      "frontend/e2e/lista-regua.spec.ts"
    ],
    "aceites": [
      "cd frontend && grep -qE 'regua|Regua' src/componentes/base/ListaDensa.tsx src/componentes/base/base.module.css",
      "cd frontend && ! sed -n '/^\\.lista {/,/^}/p' src/componentes/base/base.module.css | grep -qE 'border-radius'",
      "cd frontend && grep -qE 'regua|Regua' src/componentes/base/ListaDensa.tsx src/componentes/base/base.module.css && ! grep -qE 'nth-child\\(odd\\)|nth-child\\(even\\)' src/componentes/base/base.module.css",
      "cd frontend && grep -q papel src/componentes/molde/molde.module.css",
      "cd frontend && npx playwright test e2e/lista-regua.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/moldes.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/moldes-classificacao.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-178"
    ]
  },
  {
    "chave": "CS-180",
    "territorio": "frontend",
    "titulo": "AS 12 PAGINAS DA SECRETARIA VESTEM O MOLDE DO MANIFESTO — criterio 7, e e' «o maior numero desta demanda». 🩸 MEDIDO HOJE: `lib/moldes.ts:73` classifica as **34** paginas uma a uma (**16** LISTA · **9** FICHA · **9** FORMULARIO) e `grep -rlE 'MoldeLista|MoldeFicha|MoldeFormulario' src/app` da' **ZERO paginas**. ⟹ O molde esta' ESCRITO e ⛔ NAO esta' VESTIDO. ⟹ ESTE CARD VESTE ESTAS 12, e o molde de cada uma e' o que o MANIFESTO diz — ⛔ nao o que parecer ao dev: 206 ⚠️ `lib/moldes.ts` E' A REGUA E ⛔ NAO SE TOCA (esta' FORA desta cerca de proposito): a conferencia e' ficheiro a ficheiro contra ele, e `e2e/moldes-classificacao.spec.ts` continua a passar. Uma pagina que mude de molde e' uma pagina que mente sobre o manifesto. ⚠️ E A LISTA DE AULAS TEM DOIS MODOS QUE ⛔ NUNCA VIGORAM AO MESMO TEMPO (regra 295, decisao do dono): tocar num chip de nota FAZ AS ABAS DESAPARECEREM; tocar em «Data» TRA-LAS DE VOLTA. ⟹ O molde ⛔ nao pode por as abas e os chips de nota no ecra ao mesmo tempo, e a troca entre modos tem de ser OBVIA ao olhar. E a aba **«Permanentes»** fica ao lado de «Todas · Agendadas · Ao vivo · Encerradas» (regra 292) — ⛔ nao se deriva de data, deriva-se do TIPO. ⚠️ A GRAMATICA E' A DO §15.1 e vem pronta do CS-179: **(a)** cartao para o que se ESCOLHE, **(b)** regua para o que se LE'. ⛔ Nao se inventa a terceira. 🩸 E A TRAVA 14 DO CRITERIO, QUE REPROVA O CARD: ⛔ ZERO simbolos da casa (`⛔` `⟹` `🩸`) em TEXTO QUE O UTILIZADOR LE'. Medido 05/10: um `⛔` tinha entrado na prosa do certificado. ⟹ Em comentario e em codigo valem; em prosa de ecra, ⛔ nunca. 🩸 E A TRAVA QUE TORNA ISTO SEGURO, E E' O QUE DISPENSA MEXER NUM UNICO ENSAIO: ⛔ NENHUM `data-teste` SE PERDE NEM SE RENOMEIA. O `playwright.config.ts` di-lo a' letra — «os testes casam por `data-teste` e ⛔ NUNCA por texto de etiqueta» ⟹ vestir o molde e' MUDANCA DE ESTRUTURA, ⛔ nao de contrato, e os e2e/upas.spec.ts e2e/nucleos.spec.ts e2e/especialidades.spec.ts e2e/aulas.spec.ts e2e/relatorios-upas.spec.ts e2e/permanente-secretaria.spec.ts `data-teste` medidos hoje nestas paginas tem de continuar todos la'. ⟹ E' por isso que `e2e/` esta' FORA desta cerca: se um ensaio precisasse de ser emendado, o molde tinha partido o contrato — e isso ⛔ nao e' vestir, e' reescrever. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `componentes/molde` nem `base/**` (vem do CS-179), ⛔ nao toca `lib/moldes.ts`, ⛔ nao toca nenhuma pagina fora desta cerca, ⛔ nao muda regra de negocio, ⛔ nao acrescenta ecra nenhum e ⛔ nao reabre estilo. ⚠️ E A TRAVA 14 (⛔ ZERO simbolos da casa em texto de utilizador) PROVA-SE NO **RENDERIZADO**, no CS-185 (`e2e/simbolos.spec.ts`), e ⛔ nao por `grep` — medido por mim: o `grep` de no de texto JSX acusa **2 falsos positivos** que sao COMENTARIOS a falar de JSX (`especialista/avaliacoes/page.tsx:246` e `gravacao/[aulaId]/page.tsx:286`). ⟹ Um aceite que acusa comentario trava o dev por nada. A regra vale igual — ⛔ nenhum `⛔` `⟹` `🩸` em prosa de ecra — e quem a furar e' apanhado no ensaio que le' o que o utilizador le'.",
    "escopo_paths": [
      "frontend/src/app/secretaria"
    ],
    "aceites": [
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/secretaria | wc -l) -eq 12",
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/secretaria | wc -l) -eq 12 && test $(grep -rhoE 'data-teste=\"[^\"]+\"' src/app/secretaria | sort -u | wc -l) -ge 206",
      "cd frontend && npx playwright test e2e/moldes-classificacao.spec.ts e2e/moldes.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/upas.spec.ts e2e/nucleos.spec.ts e2e/especialidades.spec.ts e2e/aulas.spec.ts e2e/relatorios-upas.spec.ts e2e/permanente-secretaria.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-179"
    ]
  },
  {
    "chave": "CS-181",
    "territorio": "frontend",
    "titulo": "AS 8 PAGINAS DE FORMACAO E ACERVO VESTEM O MOLDE DO MANIFESTO — criterio 7, e e' «o maior numero desta demanda». 🩸 MEDIDO HOJE: `lib/moldes.ts:73` classifica as **34** paginas uma a uma (**16** LISTA · **9** FICHA · **9** FORMULARIO) e `grep -rlE 'MoldeLista|MoldeFicha|MoldeFormulario' src/app` da' **ZERO paginas**. ⟹ O molde esta' ESCRITO e ⛔ NAO esta' VESTIDO. ⟹ ESTE CARD VESTE ESTAS 8, e o molde de cada uma e' o que o MANIFESTO diz — ⛔ nao o que parecer ao dev: 147 ⚠️ `lib/moldes.ts` E' A REGUA E ⛔ NAO SE TOCA (esta' FORA desta cerca de proposito): a conferencia e' ficheiro a ficheiro contra ele, e `e2e/moldes-classificacao.spec.ts` continua a passar. Uma pagina que mude de molde e' uma pagina que mente sobre o manifesto. ⚠️ O CARTAO DE AULA E' GRAMATICA (a) e a sua anatomia esta' lida da referencia (§5.3): imagem 16:9 que sangra ⟶ ponto + PALAVRA de estado ⟶ titulo ⟶ 2-3 linhas ⟶ divisoria ⟶ metadados com icone de 18dp ⟶ avatar+nome da UPA ⟶ numero tabular e LINK DE TEXTO COM CHEVRON (⛔ nao um botao cheio dentro do cartao). ⚠️ SEM IMAGEM O CARTAO ⛔ NAO PARTE: cai para `surfaceContainerHighest` com o icone da materia (regra 96.3). ⚠️ A GRAMATICA E' A DO §15.1 e vem pronta do CS-179: **(a)** cartao para o que se ESCOLHE, **(b)** regua para o que se LE'. ⛔ Nao se inventa a terceira. 🩸 E A TRAVA 14 DO CRITERIO, QUE REPROVA O CARD: ⛔ ZERO simbolos da casa (`⛔` `⟹` `🩸`) em TEXTO QUE O UTILIZADOR LE'. Medido 05/10: um `⛔` tinha entrado na prosa do certificado. ⟹ Em comentario e em codigo valem; em prosa de ecra, ⛔ nunca. 🩸 E A TRAVA QUE TORNA ISTO SEGURO, E E' O QUE DISPENSA MEXER NUM UNICO ENSAIO: ⛔ NENHUM `data-teste` SE PERDE NEM SE RENOMEIA. O `playwright.config.ts` di-lo a' letra — «os testes casam por `data-teste` e ⛔ NUNCA por texto de etiqueta» ⟹ vestir o molde e' MUDANCA DE ESTRUTURA, ⛔ nao de contrato, e os e2e/calendario.spec.ts e2e/artigos.spec.ts e2e/cursos.spec.ts e2e/protocolos.spec.ts e2e/protocolo-ficha.spec.ts e2e/presencas.spec.ts e2e/aulas-medico.spec.ts `data-teste` medidos hoje nestas paginas tem de continuar todos la'. ⟹ E' por isso que `e2e/` esta' FORA desta cerca: se um ensaio precisasse de ser emendado, o molde tinha partido o contrato — e isso ⛔ nao e' vestir, e' reescrever. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `componentes/molde` nem `base/**` (vem do CS-179), ⛔ nao toca `lib/moldes.ts`, ⛔ nao toca nenhuma pagina fora desta cerca, ⛔ nao muda regra de negocio, ⛔ nao acrescenta ecra nenhum e ⛔ nao reabre estilo. ⚠️ E A TRAVA 14 (⛔ ZERO simbolos da casa em texto de utilizador) PROVA-SE NO **RENDERIZADO**, no CS-185 (`e2e/simbolos.spec.ts`), e ⛔ nao por `grep` — medido por mim: o `grep` de no de texto JSX acusa **2 falsos positivos** que sao COMENTARIOS a falar de JSX (`especialista/avaliacoes/page.tsx:246` e `gravacao/[aulaId]/page.tsx:286`). ⟹ Um aceite que acusa comentario trava o dev por nada. A regra vale igual — ⛔ nenhum `⛔` `⟹` `🩸` em prosa de ecra — e quem a furar e' apanhado no ensaio que le' o que o utilizador le'.",
    "escopo_paths": [
      "frontend/src/app/artigos",
      "frontend/src/app/aulas",
      "frontend/src/app/calendario",
      "frontend/src/app/cursos",
      "frontend/src/app/protocolos"
    ],
    "aceites": [
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/artigos src/app/aulas src/app/calendario src/app/cursos src/app/protocolos | wc -l) -eq 8",
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/artigos src/app/aulas src/app/calendario src/app/cursos src/app/protocolos | wc -l) -eq 8 && test $(grep -rhoE 'data-teste=\"[^\"]+\"' src/app/artigos src/app/aulas src/app/calendario src/app/cursos src/app/protocolos | sort -u | wc -l) -ge 147",
      "cd frontend && npx playwright test e2e/moldes-classificacao.spec.ts e2e/moldes.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/calendario.spec.ts e2e/artigos.spec.ts e2e/cursos.spec.ts e2e/protocolos.spec.ts e2e/protocolo-ficha.spec.ts e2e/presencas.spec.ts e2e/aulas-medico.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-179"
    ]
  },
  {
    "chave": "CS-182",
    "territorio": "frontend",
    "titulo": "AS 12 PAGINAS DE PESSOAS, ENTRADA E ESPECIALISTA VESTEM O MOLDE DO MANIFESTO — criterio 7, e e' «o maior numero desta demanda». 🩸 MEDIDO HOJE: `lib/moldes.ts:73` classifica as **34** paginas uma a uma (**16** LISTA · **9** FICHA · **9** FORMULARIO) e `grep -rlE 'MoldeLista|MoldeFicha|MoldeFormulario' src/app` da' **ZERO paginas**. ⟹ O molde esta' ESCRITO e ⛔ NAO esta' VESTIDO. ⟹ ESTE CARD VESTE ESTAS 12, e o molde de cada uma e' o que o MANIFESTO diz — ⛔ nao o que parecer ao dev: 196 ⚠️ `lib/moldes.ts` E' A REGUA E ⛔ NAO SE TOCA (esta' FORA desta cerca de proposito): a conferencia e' ficheiro a ficheiro contra ele, e `e2e/moldes-classificacao.spec.ts` continua a passar. Uma pagina que mude de molde e' uma pagina que mente sobre o manifesto. ⚠️ ACEITAR MEDICO, CONFIRMAR PRESENCA E APROVAR CERTIFICADO SAO **PAGINAS**, ⛔ NAO DIALOGOS (§5.7, lido da propria referencia): o dialogo serve so' para confirmar um acto curto e destrutivo. ⟹ `/coordenador/pedidos/[id]` e' FICHA e ⛔ nao vira modal. ⚠️ A FOTO DO MEDICO SEGUE O NOME (regra 134): onde o nome aparece, a foto aparece — e um ecra que esconda o nome ⛔ nao ganha foto. E o medico pode ⛔ NAO ter foto: todo o ecra sabe viver sem ela. ⚠️ A GRAMATICA E' A DO §15.1 e vem pronta do CS-179: **(a)** cartao para o que se ESCOLHE, **(b)** regua para o que se LE'. ⛔ Nao se inventa a terceira. 🩸 E A TRAVA 14 DO CRITERIO, QUE REPROVA O CARD: ⛔ ZERO simbolos da casa (`⛔` `⟹` `🩸`) em TEXTO QUE O UTILIZADOR LE'. Medido 05/10: um `⛔` tinha entrado na prosa do certificado. ⟹ Em comentario e em codigo valem; em prosa de ecra, ⛔ nunca. 🩸 E A TRAVA QUE TORNA ISTO SEGURO, E E' O QUE DISPENSA MEXER NUM UNICO ENSAIO: ⛔ NENHUM `data-teste` SE PERDE NEM SE RENOMEIA. O `playwright.config.ts` di-lo a' letra — «os testes casam por `data-teste` e ⛔ NUNCA por texto de etiqueta» ⟹ vestir o molde e' MUDANCA DE ESTRUTURA, ⛔ nao de contrato, e os e2e/coordenador.spec.ts e2e/perfil.spec.ts e2e/questoes.spec.ts e2e/cadastro.spec.ts e2e/entrada.spec.ts e2e/raiz.spec.ts e2e/sistema.spec.ts e2e/avaliacao-especialista.spec.ts `data-teste` medidos hoje nestas paginas tem de continuar todos la'. ⟹ E' por isso que `e2e/` esta' FORA desta cerca: se um ensaio precisasse de ser emendado, o molde tinha partido o contrato — e isso ⛔ nao e' vestir, e' reescrever. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `componentes/molde` nem `base/**` (vem do CS-179), ⛔ nao toca `lib/moldes.ts`, ⛔ nao toca nenhuma pagina fora desta cerca, ⛔ nao muda regra de negocio, ⛔ nao acrescenta ecra nenhum e ⛔ nao reabre estilo. ⚠️ E A TRAVA 14 (⛔ ZERO simbolos da casa em texto de utilizador) PROVA-SE NO **RENDERIZADO**, no CS-185 (`e2e/simbolos.spec.ts`), e ⛔ nao por `grep` — medido por mim: o `grep` de no de texto JSX acusa **2 falsos positivos** que sao COMENTARIOS a falar de JSX (`especialista/avaliacoes/page.tsx:246` e `gravacao/[aulaId]/page.tsx:286`). ⟹ Um aceite que acusa comentario trava o dev por nada. A regra vale igual — ⛔ nenhum `⛔` `⟹` `🩸` em prosa de ecra — e quem a furar e' apanhado no ensaio que le' o que o utilizador le'.",
    "escopo_paths": [
      "frontend/src/app/coordenador",
      "frontend/src/app/especialista",
      "frontend/src/app/perfil",
      "frontend/src/app/cadastro",
      "frontend/src/app/entrar",
      "frontend/src/app/page.tsx",
      "frontend/src/app/sistema"
    ],
    "aceites": [
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/coordenador src/app/especialista src/app/perfil src/app/cadastro src/app/entrar src/app/page.tsx src/app/sistema | wc -l) -eq 12",
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/coordenador src/app/especialista src/app/perfil src/app/cadastro src/app/entrar src/app/page.tsx src/app/sistema | wc -l) -eq 12 && test $(grep -rhoE 'data-teste=\"[^\"]+\"' src/app/coordenador src/app/especialista src/app/perfil src/app/cadastro src/app/entrar src/app/page.tsx src/app/sistema | sort -u | wc -l) -ge 196",
      "cd frontend && npx playwright test e2e/moldes-classificacao.spec.ts e2e/moldes.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/coordenador.spec.ts e2e/perfil.spec.ts e2e/questoes.spec.ts e2e/cadastro.spec.ts e2e/entrada.spec.ts e2e/raiz.spec.ts e2e/sistema.spec.ts e2e/avaliacao-especialista.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-179"
    ]
  },
  {
    "chave": "CS-183",
    "territorio": "frontend",
    "titulo": "AS 2 PAGINAS DO REGISTO — E A FAIXA VESTEM O MOLDE DO MANIFESTO — criterio 7, e e' «o maior numero desta demanda». 🩸 MEDIDO HOJE: `lib/moldes.ts:73` classifica as **34** paginas uma a uma (**16** LISTA · **9** FICHA · **9** FORMULARIO) e `grep -rlE 'MoldeLista|MoldeFicha|MoldeFormulario' src/app` da' **ZERO paginas**. ⟹ O molde esta' ESCRITO e ⛔ NAO esta' VESTIDO. ⟹ ESTE CARD VESTE ESTAS 2, e o molde de cada uma e' o que o MANIFESTO diz — ⛔ nao o que parecer ao dev: 27 ⚠️ `lib/moldes.ts` E' A REGUA E ⛔ NAO SE TOCA (esta' FORA desta cerca de proposito): a conferencia e' ficheiro a ficheiro contra ele, e `e2e/moldes-classificacao.spec.ts` continua a passar. Uma pagina que mude de molde e' uma pagina que mente sobre o manifesto. 🩸 E ESTE CARD TRAZ A FAIXA DO REGISTO (criterio 8), porque e' AQUI que o registo existe HOJE e ⛔ em mais lado nenhum: a sala ao vivo abre com FAIXA DE PONTA A PONTA em `primary`, o NUMERO GRANDE em `tabular-nums` e a FITA DE BLOCOS por cima dela. E' a gramatica **(b)** do §15.1 e a trava 5 do §16.6. ⟹ ⛔ NENHUMA FAIXA INVENTADA em pagina que o ranking ainda ⛔ nao trouxe: a folha do mes e a carga obrigatoria ⛔ NAO EXISTEM (medido: ⛔ nenhum model de obrigatoriedade, ⛔ nenhuma pagina de percurso — nascem no CS-120, que ⛔ nao esta' no `main`). Para essas o §16 fica escrito como TRAVA. ⚠️ A fita que esta faixa mostra vem PRONTA do CS-178 e aqui so' se consome: ⛔ nao se redesenha bloco e ⛔ nao se duplica a conta — «a conta aparece UMA vez por ecra» (§16.6.2). ⚠️ E O `role=\"progressbar\"` DO LEITOR FICA (`LeitorDeGravacao.tsx:475`): e' tempo de VIDEO, ⛔ nao minutos validados. ⛔ Nao se troca por blocos. ⚠️ A GRAMATICA E' A DO §15.1 e vem pronta do CS-179: **(a)** cartao para o que se ESCOLHE, **(b)** regua para o que se LE'. ⛔ Nao se inventa a terceira. 🩸 E A TRAVA 14 DO CRITERIO, QUE REPROVA O CARD: ⛔ ZERO simbolos da casa (`⛔` `⟹` `🩸`) em TEXTO QUE O UTILIZADOR LE'. Medido 05/10: um `⛔` tinha entrado na prosa do certificado. ⟹ Em comentario e em codigo valem; em prosa de ecra, ⛔ nunca. 🩸 E A TRAVA QUE TORNA ISTO SEGURO, E E' O QUE DISPENSA MEXER NUM UNICO ENSAIO: ⛔ NENHUM `data-teste` SE PERDE NEM SE RENOMEIA. O `playwright.config.ts` di-lo a' letra — «os testes casam por `data-teste` e ⛔ NUNCA por texto de etiqueta» ⟹ vestir o molde e' MUDANCA DE ESTRUTURA, ⛔ nao de contrato, e os e2e/ao-vivo.spec.ts e2e/gravacao.spec.ts e2e/alcance.spec.ts e2e/permanente-leitor.spec.ts `data-teste` medidos hoje nestas paginas tem de continuar todos la'. ⟹ E' por isso que `e2e/` esta' FORA desta cerca: se um ensaio precisasse de ser emendado, o molde tinha partido o contrato — e isso ⛔ nao e' vestir, e' reescrever. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `componentes/molde` nem `base/**` (vem do CS-179), ⛔ nao toca `lib/moldes.ts`, ⛔ nao toca nenhuma pagina fora desta cerca, ⛔ nao muda regra de negocio, ⛔ nao acrescenta ecra nenhum e ⛔ nao reabre estilo. ⚠️ E A TRAVA 14 (⛔ ZERO simbolos da casa em texto de utilizador) PROVA-SE NO **RENDERIZADO**, no CS-185 (`e2e/simbolos.spec.ts`), e ⛔ nao por `grep` — medido por mim: o `grep` de no de texto JSX acusa **2 falsos positivos** que sao COMENTARIOS a falar de JSX (`especialista/avaliacoes/page.tsx:246` e `gravacao/[aulaId]/page.tsx:286`). ⟹ Um aceite que acusa comentario trava o dev por nada. A regra vale igual — ⛔ nenhum `⛔` `⟹` `🩸` em prosa de ecra — e quem a furar e' apanhado no ensaio que le' o que o utilizador le'.",
    "escopo_paths": [
      "frontend/src/app/ao-vivo",
      "frontend/src/app/gravacao"
    ],
    "aceites": [
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/ao-vivo src/app/gravacao | wc -l) -eq 2",
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app/ao-vivo src/app/gravacao | wc -l) -eq 2 && test $(grep -rhoE 'data-teste=\"[^\"]+\"' src/app/ao-vivo src/app/gravacao | sort -u | wc -l) -ge 27",
      "cd frontend && grep -qE '^\\.faixaDoRegisto' src/app/ao-vivo/ao-vivo.module.css && sed -n '/^\\.faixaDoRegisto/,/^}/p' src/app/ao-vivo/ao-vivo.module.css | grep -qE 'var\\(--md-sys-color-primary\\)' && grep -q tabular src/app/ao-vivo/ao-vivo.module.css",
      "cd frontend && rm -f e2e/capturas/d48-faixa-*.png && CAPTURAS=1 npx playwright test e2e/ao-vivo.spec.ts --reporter=line && test $(ls e2e/capturas/d48-faixa-*.png | wc -l) -ge 1",
      "cd frontend && npx playwright test e2e/moldes-classificacao.spec.ts e2e/moldes.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/ao-vivo.spec.ts e2e/gravacao.spec.ts e2e/alcance.spec.ts e2e/permanente-leitor.spec.ts --reporter=line",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-179"
    ]
  },
  {
    "chave": "CS-184",
    "territorio": "frontend",
    "titulo": "A ASSINATURA: AS ONZE LETRAS CONSTRUIDAS, E INTER ABAIXO DE ~120px — criterios 12 e 13. 🩸 MEDIDO: `src/componentes/marca` ⛔ NAO EXISTE e ⛔ nao ha' letra construida em parte nenhuma do produto. A tipografia ja' esta' certa (Inter em `estilo/letra.css`, ⛔ zero serifa) ⟹ o que falta e' A ASSINATURA. 🩸 E ⛔ NAO E' DESENHO NOVO — e' a MESMA REGRA que ele aceitou, e e' DETERMINISTA (§16.1, §16.3): as letras desenham-se na grelha em MEIO-PASSO (celula 4 · passo 5 · meio-passo 2,5 · raio 28%), e por isso tem as mesmas juntas redondas do visto e ⛔ nao parecem pixels. CAPACITA e SALVADOR tem **oito letras cada**; empilhadas alinham a' largura exacta. Estao feitas **onze** letras — so' as que estas duas palavras pedem. ⟹ Gera-se da regra, em codigo, como o monograma: ⛔ nenhuma geometria a' mao de agente, e por isso a regra 306 ⛔ NAO trava isto (ver D9 do enquadramento). ⚠️ O «i» de Capac**i**ta leva o BLOCO no lugar do pingo, NA COR DA MARCA — ⛔ nao no verde: o verde ficou reservado ao sinal, porque solto numa palavra lia-se como pixel perdido (medido 05/10). 🩸 A FRONTEIRA DOS ~120px E' TRAVA, E ⛔ NAO SE DISCUTE (§16.3): abaixo de ~120px as letras construidas FECHAM-SE e deixam de se ler ⟹ ai' e' **Inter**. ASSINATURA GRANDE (entrada, folha grande) = letras construidas; ASSINATURA PEQUENA (barra, rodape) = Inter. ⟹ ZERO letra construida abaixo de ~120px, e prova-se em DUAS capturas. ⚠️ E A CONTA APARECE **UMA** VEZ POR ECRA (§16.6.2): duas = ⛔ NAO BATE. 🩸 A PECA-FONTE FICA VERSIONADA NO REPO, em `src/componentes/marca/` — ⛔ NAO num link e ⛔ NAO em `/srv/fab/obra/.tmp-agentes/`, que e' o que o criterio 12 proibe. ⚠️ O criterio nomeia `_produto/design/identidade/`, que esta' FORA do worktree e a cerca do dev ⛔ nao alcanca (ver a OBSERVACAO O-B do enquadramento): o repo cumpre o PORQUE da exigencia — regua que vive num link morre — e cumpre-o melhor, porque e' versionado. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca o CERTIFICADO (⛔ NAO EXISTE — medido: 24 models no `schema.prisma` e ⛔ nenhum `Certificado`; o §16.4-A.5 fica como TRAVA escrita para o dia em que nascer, D1), ⛔ nao desenha alfabeto que estas duas palavras ⛔ nao pedem, ⛔ nao toca `letra.css` nem a escala de tipografia, e ⛔ nao reabre estilo.",
    "escopo_paths": [
      "frontend/src/componentes/marca",
      "frontend/src/app/page.tsx",
      "frontend/src/componentes/casca",
      "frontend/e2e/marca.spec.ts"
    ],
    "aceites": [
      "cd frontend && test -d src/componentes/marca && grep -rqE 'celula|passo|meio-passo|raio' src/componentes/marca",
      "cd frontend && test $(grep -rhoE \"'[A-Z]'\" src/componentes/marca | sort -u | wc -l) -ge 11",
      "cd frontend && grep -rqE '120' src/componentes/marca",
      "cd frontend && grep -q 'marca' src/app/page.tsx",
      "cd frontend && npx playwright test e2e/marca.spec.ts --reporter=line",
      "cd frontend && rm -f e2e/capturas/d48-marca-*.png && CAPTURAS=1 npx playwright test e2e/marca.spec.ts --reporter=line && test $(ls e2e/capturas/d48-marca-*.png | wc -l) -ge 2",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-177",
      "CS-182"
    ]
  },
  {
    "chave": "CS-185",
    "territorio": "frontend",
    "titulo": "UM SO' MOVIMENTO EM TODO O PRODUTO: o bloco validado salta e o total conta ate' ao novo numero — criterio 11, e e' o ULTIMO card porque conta o produto INTEIRO. 🩸 MEDIDO POR MIM, E CORRIJO O TEXTO DA DEMANDA: sao **3** `@keyframes` em **3** ficheiros, ⛔ nao 4 em 4 — `rodar` (`componentes/base/base.module.css:109`), `abrir` (`app/ao-vivo/ao-vivo.module.css:171`) e `entrar` (`app/cadastro/cadastro.module.css:324`). O quarto que o texto conta e' uma MENCAO DENTRO DE UM COMENTARIO (`base.module.css:876`), e um comentario ⛔ nao anima nada. E `transition:` da' **17**, que e' o numero do texto. ⟹ PRONTO = **o movimento do bloco, e ⛔ nenhum que ⛔ nao responda a um acto** (§16.4-A.4): o bloco que acabou de ser validado da' um salto curto e o total CONTA ate' ao novo numero. ⛔ Nada mais se mexe — ⛔ nao ha' seccoes a deslizar a' entrada, ⛔ nao ha' cartoes a saltar ao passar o rato. *Isso e' o tell de pagina gerada.* ⚠️ `abrir` E `entrar` SAO EXACTAMENTE ISSO — opacidade e `translateY` a' entrada do ecra, ⛔ respondendo a acto nenhum ⟹ SAEM. O `rodar` do `Botao` fica SE e SO' SE servir o estado «A TRABALHAR» de um botao que a pessoa acabou de premir (§5.1: rotulo FICA NO SITIO, largura ⛔ NAO MUDA, indicador de 18dp) — e' acto, ⛔ nao enfeite; e a peca do «a carregar» e' marca ESTATICA, como o proprio `base.module.css:876` ja' declara. 🩸 `prefers-reduced-motion: reduce` LEVA TUDO A **0ms** COM O MESMO PIXEL FINAL, e prova-se nas DUAS capturas (§9, regra 84): ⛔ nenhum movimento residual, ⛔ nenhuma animacao «suavizada». Zero. ⚠️ E AS CURVAS E DURACOES SAO AS DO M3 E ⛔ NAO SE INVENTAM (regra 84): `standard` cubic-bezier(0.2,0,0,1) · short-2 100ms · short-4 200ms · medium-2 300ms. ⛔ PROIBIDO, e vem da regra 84: ⛔ parallax · ⛔ carrossel automatico · ⛔ brilho de esqueleto («trai o prefers-reduced-motion») · ⛔ ressalto e mola · ⛔ snackbar a confirmar o que ja' se ve' no ecra. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao redesenha o bloco (vem do CS-178), ⛔ nao toca a faixa, ⛔ nao muda molde nenhum, ⛔ nao toca o leitor de video e ⛔ nao reabre estilo.",
    "escopo_paths": [
      "frontend/src/componentes/base/base.module.css",
      "frontend/src/app/ao-vivo/ao-vivo.module.css",
      "frontend/src/app/cadastro/cadastro.module.css",
      "frontend/src/componentes/fita",
      "frontend/e2e/movimento.spec.ts",
      "frontend/e2e/simbolos.spec.ts"
    ],
    "aceites": [
      "cd frontend && test $(grep -rhc '^@keyframes' src/ --include='*.css' | awk '{s+=$1} END{print s+0}') -le 2",
      "cd frontend && ! grep -q '^@keyframes abrir' src/app/ao-vivo/ao-vivo.module.css && ! grep -q '^@keyframes entrar' src/app/cadastro/cadastro.module.css",
      "cd frontend && grep -rqE '^@keyframes (salto|contar|bloco)' src/componentes/base/base.module.css src/componentes/fita",
      "cd frontend && grep -rq 'prefers-reduced-motion' src/componentes/base/base.module.css",
      "cd frontend && test $(grep -rlE 'Molde(Lista|Ficha|Formulario)' --include='page.tsx' src/app | wc -l) -eq 34",
      "cd frontend && npx playwright test e2e/simbolos.spec.ts --reporter=line",
      "cd frontend && npx playwright test e2e/movimento.spec.ts --reporter=line",
      "cd frontend && rm -f e2e/capturas/d48-movimento-*.png && CAPTURAS=1 npx playwright test e2e/movimento.spec.ts --reporter=line && test $(ls e2e/capturas/d48-movimento-*.png | wc -l) -ge 2",
      "cd frontend && npx next build"
    ],
    "depende_de": [
      "CS-180",
      "CS-181",
      "CS-182",
      "CS-183"
    ]
  }
]