Conformidade com a especificação v2.5 e prova de critérios de aceite
Duas verificações independentes: (1) o layout e o design usam exclusivamente o design system "Calm 2026 × IBCS"; (2) toda US da especificação tem Gherkin e uma tela onde os cenários podem ser exercidos.
1 · Layout e design vs. regras inegociáveis do DS
Verificação item a item das 10 regras do prompt + Seção 12 e 19 da especificação. Evidência = onde conferir.
| Regra | Veredito | Evidência |
|---|---|---|
| 1 · Só o DS anexado | conforme | As 16 telas carregam tokens.css + _ds_bundle.js e compõem com AppTopbar, AppSidebar, AppBottomBar, SpecKpiCard, DataTable, ChartFrame, ErrState, EmptyState, SampleSeal, StaleSeal, QuotaChip e as classes rps-* do product-spec.css. |
| 2 · Sem Tailwind, hex ou biblioteca de chart | conforme | Varredura automática: 0 hex hardcoded nas 16 telas; nenhuma dependência externa; todos os gráficos são SVG/flex próprios (linhas, barras, heatmap, radar, banda P25–P75). |
| 2 · Sem px hardcoded | conforme com nota | 254 valores convertidos em tokens (bordas, tipografia, espaçamentos, raios). Restam apenas: geometria de layout (min-width de coluna de grade, max-width de diálogo, altura de skeleton, coordenadas de SVG) e alturas de controles compactos (24/26/30/36/38 px) — os mesmos valores que o próprio product-spec.css do DS usa. |
| 3 · Nada inventado | conforme | Nenhum token, componente ou dado novo: onde a spec não define valor visual, a decisão foi reusar a classe rps-* equivalente do DS. |
| 4 · Hierarquia de cor | conforme | PRIMARY --calm-primary em ações e foco; neutros na estrutura; --calm-tertiary (IBCS) exclusivo para dado interno — coluna e chip “meu canal”, tr.is-internal, KPI .internal, radar e banda do KPI-45. Semânticas apenas em status; âmbar só nos estados de atenção previstos. |
| 5 · Tipografia | conforme | Inter na interface e JetBrains Mono em todo número (classe .tnums e --font-mono nos KPI cards, células td.r e selos). Escala usada apenas via --text-display/hero/h1…micro. |
| 6 · Grid 8pt e raios | conforme | Espaçamentos só por --space-*; raios por --radius-xs…2xl (chips 6, inputs 10, botões 14, cards 24, diálogos 32, pills full). Nenhum canto vivo — barras de dado usam --data-mark-radius (2px, token IBCS). |
| 7 · Dark mode independente | conforme | Nenhuma cor literal: o tema [data-theme=dark] do tokens.css recalibra tudo, incluindo --data-ink e a moldura do dado. Controle único Sistema · Claro · Escuro em Configurações → Aparência (padrão: Sistema), persistido em localStorage, aplicado a todas as telas e sincronizado entre abas pelo RITheme do DS — sem controle flutuante no chrome. |
| 8 · Semântica IBCS nos gráficos | conforme | Actual em --data-ac sólido, ano anterior em --data-py, dado interno em --calm-tertiary, referência tracejada com --bw-medium; área de plotagem sem sombra e sem fundo colorido (tokens --data-region-*). |
| 9 · Motion e mobile-first | conforme | Transições apenas com --duration-* e --ease-default; prefers-reduced-motion herdado do tokens.css (inclui o shimmer do skeleton). Breakpoint 767 px: sidebar → AppBottomBar de 5 itens; tokens de tipo sobem para 14 px mínimo. |
| Marca (logo) | conforme | Marca (mira + barras) ao lado do wordmark em toda topbar e em todo cabeçalho próprio, herdando currentColor — logo funciona em tema claro e escuro sem cor literal. |
| 12.1 · Seletor de workspace | conforme com nota | Implementado no menu do avatar em /niches e como seletor canônico em Configurações → Equipe. Nota: o AppTopbar do DS não tem espaço para o seletor — a alternativa foi o menu do avatar, sem recriar a topbar. Recursos exibem “criado por {membro}”. |
| 12.2 · Nav lateral colapsável | conforme | Botão “Recolher” do AppSidebar ligado em todas as 12 telas do produto (estado por tela); em ≤ 767 px a nav vira AppBottomBar de 5 itens. |
| 12.6 · Toast de erro persistente | conforme | Erro não desaparece sozinho: variante com código ERR-08, “Tentar novamente” e fechar (exercível em /niches). Sucesso continua em 4 s. |
| 12.8 · Tabela → cards em mobile | conforme | Comparativo tem alternância Tabela / Cards por canal com seletor de métrica (14 KPIs), “meu canal” destacado em azul terciário; abaixo de 767 px os cards são o formato padrão. |
| T6 · Benchmark do meu porte | conforme | Painel KPI-40 no detalhe do meu canal com a faixa 10k–100k destacada, demais faixas visíveis, ERR-17 na faixa 1M+ e leitura comparando meus números ao normal do porte. |
| 10 · Componentes reutilizados | conforme | Topbar, nav, KPI card com rodapé obrigatório, tabela com td.r e tr.is-internal, chips, botões e selos vêm do DS — nenhum foi recriado. |
| 12.3 · KPI card completo | conforme | Todo card traz valor em mono, rótulo, delta colorido, tooltip “como calculamos” com a fórmula da Seção 17/18 e rodapé amostra · data · origem A|B; estados n.a., amostra insuficiente e “coletando — dia x/N”. |
| 12.4 · Tabelas | conforme | Cabeçalho fixo, ordenação asc→desc→padrão por clique e teclado, números à direita em mono, paginação de 25 (DataTable do DS). |
| 12.5 · Gráficos acessíveis | conforme | Toda moldura ChartFrame tem título, unidade no eixo, pontos focáveis por teclado com <title> e botão “ver como tabela”; nenhum gráfico é desenhado sem dados — no lugar entra EMPTY-03. |
| 12.6/12.7 · Toasts e skeletons | conforme | Sucesso em 4 s com os textos literais (“'{objeto}' salvo.”, “Link copiado.”, “Senha alterada”); decisões sempre em modal ou inline. Skeleton em toda tela de dados — spinner de página inteira só na coleta (EMPTY-02). |
| 19 · Regras transversais | conforme | Números em pt-BR (1.234.567 · 12,5%), datas DD/MM/AAAA HH:mm, “≈” em inscritos e derivados com tooltip do arredondamento, selo de procedência em toda tela de dados, degradação para cache com selo de data. |
| 26.5 · Conformidade YouTube API | conforme | Rodapé de conformidade nas 12 telas do produto, na autenticação, na landing, no relatório público e no 404: “Dados: YouTube · Este produto usa os Serviços de API do YouTube” + Termos do YouTube + Política de Privacidade do Google + Limites dos dados. Atribuição sempre visível (fora dos estados do protótipo). MOD-03 com a retenção corrigida de 30 dias; nenhuma tela oferece download de vídeo ou thumbnail. |
| 26.1 · Autoria no workspace | conforme | Nichos e relatórios exibem “criado por {membro}”; seletor de workspace no menu do avatar e em Configurações → Equipe; plano em modo leitura para member. |
| 7.x · Acessibilidade | conforme com nota | Navegação por teclado, foco visível por --shadow-focus, aria-sort/aria-selected/aria-modal, alternativa em tabela para todo gráfico e rótulo em todo ícone. Nota: auditoria APCA numérica e teste com leitor de tela real ficam para a fase de implementação em código. |
2 · Prova: toda US tem Gherkin e tela
Extração automática do documento: 72 histórias (47 US + 25 TS), 195 cenários, 72 com bloco Funcionalidade: — nenhuma história sem critérios de aceite. Clique numa linha para ver os cenários literais.
Validação inline por campo (e-mail, senha ≥8 com letra e número, confirmação, termos com foco no checkbox), botão desabilitado com senha fraca, ERR-10 com links Entrar/Recuperar senha, ERR-11 no 3º reenvio.
Texto literal “Enviamos um link para {e-mail}. O link vale por 60 minutos.”, reenvio bloqueado por 60 s, ERR-11, tela de link expirado com ERR-12 + “Solicitar novo link”, aviso “Confirme seu e-mail para continuar.”
ERR-15 sem revelar o campo, ERR-16 com contagem 15:00 ao vivo e senha desabilitada, EMPTY-08 em ?login-expired, MOD-10 (em /niches) preservando o destino.
Resposta neutra “Se este e-mail existir…”, redefinição com aviso de encerramento das outras sessões e toast “Senha alterada”, ERR-12 no link reusado.
Chips de keywords com ERR-90, MOD-01 com custo em buscas, EMPTY-02 com etapas nomeadas, retomada do passo salvo, “Pular por enquanto” → EMPTY-01, falha com ERR-03 + estorno declarado.
CTA por plano com pró-rata declarada, ciclo mensal/anual, chip “teste do Pro termina em 3 dias”, ERR-09 simulável com “Tentar outro cartão”; queda para Free dispara MOD-08 em Configurações → Plano.
MOD-07 com data de fim, MOD-08 com contador {selecionados}/{limite} e primário desabilitado, banner de inadimplência com graça de 7 dias, estado Free pós-downgrade.
Troca de senha com “Senha incorreta.” e toast, troca de e-mail com aviso ao endereço antigo, exportar JSON em 24 h, MOD-09 em 2 passos (EXCLUIR + senha, ESC bloqueado no passo 2).
ERR-01 10/10 com “Ver planos”/“Gerenciar itens”, ERR-13 com “Abrir nicho existente”, status parcial com EMPTY-06 e “Tentar completar” respeitando ERR-14.
Cards TAM/SAM/SOM/KPI-42 com tooltip “como calculamos”, histograma com ≈ e barra “ocultos”, Top 10, outliers 90 d, ERR-17 no estado de amostra insuficiente, selo de cache ERR-03.
Ordenação asc→desc→padrão via DataTable, inscritos “oculto” com nota no tooltip, linha clicável para /channels/:id, “+ watchlist” virando “na watchlist ✓”.
Resolução por URL/@handle sem consumir busca, MOD-04 para nome livre, ERR-04 com os 3 formatos clicáveis, coluna “meu canal” primeira e em azul terciário.
KPIs 08–19 + 20–25 em colunas com base/data/origem no tooltip, ERR-01 + MOD-11 no Starter, células “coletando — dia 2/7”, composição persistida em localStorage.
Painel KPI-09/10 com “2,5 vídeos/semana” e interpretação textual de σ; canal com poucos uploads mostra a frequência e ERR-17 no lugar da consistência (estado “Meu canal”: 18 uploads).
Até 20 vídeos com score ≥ 3 ordenados desc, título/canal/views/score e link externo em nova aba; estado “Nenhum vídeo fora da curva nos últimos 90 dias — desempenho homogêneo.”
Card KPI-11 com “base: 50 vídeos” no rodapé e tooltip informando os 2 vídeos com likes indisponíveis.
“primeiro histórico amanhã” no canal novo, Δ7d/Δ30d, linha ERR-05 com “Remover” (MOD-03) e “Manter histórico”, ERR-01 sem afetar canais existentes.
10 termos com demanda relativa 0–100, oferta e gap, aviso metodológico fixo, “ver vídeos” por termo, ERR-02 antes de qualquer consumo, EMPTY-05 com sugestões.
Linha “Duração top 25% (KPI-19)” com mediana 11:40 e mix Shorts (KPI-18) rotulado como heurística por duração; exclusão de durações inválidas declarada no tooltip.
TAM/SAM/SOM rotulados “piso observado” com fórmula da Seção 18 e tamanho da amostra; SOM traz cenários P25/mediana/P75 e a regra de indisponibilidade com < 5 entrantes.
Card com HHI 1.560 classificado “moderado” e C4 70%; tooltip explica que a base é views (sempre disponível) e não inscritos.
12 barras de vídeos por mês, Δ +20% do último trimestre e nota “amostra, não censo” no rodapé do gráfico.
Colunas pareadas com TAM, SAM, SOM, C4, HHI, engajamento médio, ritmo, nº de canais e mediana de inscritos; “Maior valor” apenas descritivo; nicho em coleta desabilitado com a nota; MOD-11 no Starter.
Tabela ordenável por Gap (padrão desc) com tooltip da fórmula gap = demanda ÷ oferta renormalizado (Seção 18.5).
Salvar a partir do painel/comparativo, detalhe com valores congelados e data, “Gerar versão atual” criando novo relatório sem sobrescrever.
Faixas 0–1k · 1k–10k · 10k–100k · 100k–1M · 1M+ com contagem e barra própria “ocultos”.
Linha KPI-24 (Origem B) com participação por canal; canal com < 30 snapshots exibe EMPTY-03 “coletando — dia 2/7” em vez de valor.
Total + 20 amostrados por relevância com likes e data, “Atualizar amostra” respeitando cache de 7 dias, ERR-06 como estado informativo.
Tabela canal × mês com inscritos no fim do mês, Δ absoluto e Δ %, linha do meu canal destacada e exportação CSV.
MOD-05 com expiração 7/30/90 e botão copiar, MOD-06 de revogação, página /r/:token sem dados de conta e ERR-07 quando expirado.
Heatmap 7 × 8 no fuso do usuário com valor absoluto no tooltip de cada célula, ao lado do KPI-28 (resultado por dia).
Toggles inline por canal e tipo, sino com os alertas de 7 dias, digest e descadastro geridos em Configurações → Notificações (envio é backend).
- TS-01Provisionar e restringir a chave da APIbackend — sem tela2 cenários
Provisionamento e restrição da chave — sem superfície de interface.
- TS-02Segredo fora do clientebackend — sem tela2 cenários
Nenhuma chamada à API do YouTube nem chave no front: as telas consomem apenas dados de exemplo locais.
Chip “{usado}/{limite} buscas hoje” na topbar (fonte: GET /me/limits) com estados de atenção e esgotado.
Selo de cache no estado “Cache (ERR-03)” exibindo data/hora do dado salvo.
Textos “snapshot diário às 05:15”, “primeiro histórico amanhã” e canal 404 como ERR-05 na linha.
- TS-06Batching universalbackend — sem tela2 cenários
Batching de chamadas — sem superfície de interface.
- TS-07Mapeamento de erros da YouTube APIreflexo na interface4 cenários
Nenhuma mensagem em inglês nas telas: todo erro sai como ERR-xx do catálogo em pt-BR literal.
- TS-08Retry com backoff e jitterreflexo na interface3 cenários
ERR-08 previsto no catálogo com “Tentar novamente” (toast persistente); retries são backend.
- TS-09Normalização de payloadsbackend — sem tela2 cenários
Tipos, fusos e hiddenSubscriberCount → NULL; efeito visível é o “oculto” na tabela.
- TS-10Snapshots imutáveisbackend — sem tela2 cenários
Imutabilidade dos snapshots — sem superfície de interface.
Todo KPI card traz amostra, computed_at e selo de origem A/B; Origem B sem histórico vira “coletando — dia x/N”.
- TS-12Deduplicação de entidadesbackend — sem tela1 cenários
Deduplicação de canais entre nichos.
Selo de amostra com “· truncada” no nicho Violão fingerstyle.
ERR-02 exibido antes de qualquer consumo, com renovação à meia-noite.
- TS-15Observabilidadebackend — sem tela2 cenários
Observabilidade e projeção de cota — rota administrativa fora do escopo do produto.
Prefixo “≈” em inscritos e derivados com tooltip do arredondamento; canais ocultos fora dos KPIs de inscritos.
Durações exibidas em mm:ss; vídeos sem duração válida declarados como excluídos no tooltip do KPI-19.
- TS-18Auth do app e RLSbackend — sem tela2 cenários
RLS por usuário/workspace.
Estados trialing/active/past_due/canceled refletidos na aba Plano; webhooks são backend.
Barras de uso vs. limite lidas de /me/limits — nenhum limite hardcoded na interface.
Ação “Exportar CSV” com nome de arquivo rivalindex_{tipo}_{AAAA-MM-DD}.csv; gate de plano por MOD-11.
Página pública sem dados de conta e estado ERR-07 para token expirado/revogado.
Toggles de digest diário/semanal e nota do descadastro de 1 clique sem login.
Barra de progresso com as etapas nomeadas da Seção 5.3 e estado de falha com o ERR correspondente.
MOD-09 declara purga em até 30 dias e revogação imediata dos links públicos.
6 linhas (cadência, duração, melhor dia, formato, temas quentes, vocabulário) cada uma com link ao KPI-fonte e linguagem descritiva.
Radar com views P38 · frequência P75 · engajamento P81 · VPS P88 e leitura literal por eixo; sem “meu canal” definido, o botão “Definir como meu canal” assume o papel do estado vazio.
Aba “Em alta agora” com selo “atualizado há 3 h (máx. 6 h)”, canais da amostra destacados em azul terciário e tooltip da aproximação por categoria.
Pedidos agrupados por termo com contagem, exemplo real e link “ver origem”; base de 412 comentários amostrados declarada.
Toggle “Digest semanal de insights (segunda 08:00 no seu fuso · Starter+)” com nota do descadastro de 1 clique.
Playlists ordenadas por nº de itens com marcação “série”; estado “Este canal não mantém playlists públicas.” no canal sem playlists.
Ordem por atenção necessária (quedas → removidos → hiatos → picos/marcos), explicador de salto expansível, vazio “Nada exige sua atenção hoje.”, seção “Coletando linha de base (dia x/28)”.
Agendamento semanal/mensal com dia, hora no fuso do dono e até 5 destinatários, selo “enviado automaticamente” na lista, aviso de retry no dia seguinte; MOD-11 fora do plano.
Item “vídeo removido” com título, canal e última contagem conhecida, declarando que o motivo não é observável; sem falso positivo por 5xx (regra do backend citada).
Benchmark por faixa com ERR-17 na faixa 1M+ (1 de 5) e demais faixas visíveis; emergentes listando os critérios cumpridos por canal, incl. caso de inscritos ocultos.
Views do vídeo de 2 dias contra a banda P25–P75 dos últimos 10, leitura “dentro do seu normal”, coleta 6/6 h declarada no subtítulo.
Convite de uso único válido por 7 dias com assento reservado como pendente e ERR-01 “assentos: 5/5”; aba Equipe só existe no Business.
Estado “Membro (leitura)”: plano em modo leitura com “Gerenciado por {owner}” e sem botões de upgrade/cancelamento/reembolso; limites descritos como do workspace.
MOD-14b “Remover {nome} do workspace?” com “Ela perde o acesso na hora. Tudo o que ela criou permanece no workspace.” e nota de que o owner não pode sair.
Botão só dentro da janela de 7 dias, MOD-15 com valor e volta ao Free, texto “Reembolsos após 7 dias: fale com o suporte” fora da janela.
3 · Catálogos ERR · MOD · EMPTY
Cobertura dos catálogos das Seções 8, 9 e 10 — onde cada código pode ser exercido no protótipo.
Erros (ERR)
19/19 no catálogo · 17 exercíveis- ERR-01Niches · Watchlist · Compare · Settings (assentos)
- ERR-02Keywords · estado “Sem buscas”
- ERR-03NichePanel (selo de cache) · Onboarding (falha) · EMPTY-07 em Niches
- ERR-04Compare · exemplos clicáveis
- ERR-05Channel (banner) · Watchlist (linha)
- ERR-06Channel · painel de comentários
- ERR-07PublicReport · link expirado
- ERR-08catálogo do DS · toast persistente com “Tentar novamente”
- ERR-09Plans · simulação de recusa
- ERR-10 … 12Auth · signup, verify, link expirado
- ERR-13Niches · nicho duplicado
- ERR-14Niches · MOD-12 com recoleta recente
- ERR-15 · 16Auth · login e bloqueio com contagem
- ERR-17NichePanel · cards e faixa 1M+ do benchmark
- ERR-90todos os formulários · inline por campo
- ERR-99catálogo do DS · trace_id + “Voltar aos nichos”
Modais (MOD)
16/16- MOD-01Onboarding · custo em buscas
- MOD-02Niches · arquivar
- MOD-03Watchlist · com aviso de purga em 30 dias
- MOD-04Compare · busca por nome
- MOD-05 · 06Compare e Reports · gerar e revogar link
- MOD-07Settings · cancelar assinatura
- MOD-08Settings · contador e primário desabilitado
- MOD-09Settings · 2 passos, EXCLUIR + senha
- MOD-10Niches · sessão expirada preservando destino
- MOD-11Compare · CompareNiches · Reports
- MOD-12Niches e NichePanel · recoleta
- MOD-13Niches · reativar nicho
- MOD-14 · 14bSettings · sessão e membro
- MOD-15Settings · reembolso
Estados vazios (EMPTY)
10/10- EMPTY-01Niches · sem nichos
- EMPTY-02Onboarding e NichePanel · coleta com etapas
- EMPTY-03Channel · Compare · histórico insuficiente
- EMPTY-04Watchlist · vazia
- EMPTY-05Keywords · sem resultados + sugestões
- EMPTY-06Niches e NichePanel · coleta parcial
- EMPTY-07Niches · cota do dia esgotada
- EMPTY-08Auth · sessão expirada no login
- EMPTY-09Reports · sem relatórios
- EMPTY-10Compare · sem canais
4 · Pendências declaradas
O que esta implementação de front-end deliberadamente não resolve — coerente com a Seção 26.6 da especificação. Nada aqui é defeito silencioso.
- andaime
Seletor “Estados do protótipo” em cada tela
Existe para você exercer carregando, vazio, erro, parcial e completo sem backend. Deve ser removido na implementação em código — não faz parte do produto.
- backend
8 das 25 TS não têm superfície de interface
TS-01, TS-02, TS-06, TS-09, TS-10, TS-12, TS-15 e TS-18 — chave da API, segredo, batching, normalização, snapshots imutáveis, deduplicação, observabilidade e RLS — são verificáveis em código e teste, não em tela. A auditoria marca cada uma como “backend — sem tela” em vez de fingir cobertura.
- dados
Números de exemplo, não dados reais
Todos os valores seguem os exemplos numéricos da Seção 17 (mediana 22 k views, ER 7,0%, HHI 1.560, TAM 46,2 M) e são coerentes entre telas — nenhum número redondo irreal.
- a11y
Verificação APCA e leitor de tela
Os pares de cor vêm dos tokens já calibrados para os alvos APCA do DS, mas a medição numérica por par e o teste com leitor de tela real pertencem à fase de implementação.
- e-mail
15 templates de e-mail da Seção 25.9 + 26.4 — entregues
Produzidos como entrega separada: um HTML send-ready por e-mail, em tabelas com estilo inline, na paleta do design system. Galeria e regras aplicadas em Emails.dc.html. Resta apenas trocar placeholders, domínio e endereço postal.
- jurídico
Termos, Privacidade e página “Limites dos dados” completa
O rodapé já traz a atribuição obrigatória do YouTube e a seção de transparência da landing cobre a Seção 22.2; o texto jurídico integral é pendência declarada na Seção 26.6.