Revisão de Engenharia UI — Design Systems Temáticos (produtos/design/*.json)
Escopo: 22 arquivos de design system (20 originais + par Meridian dia/noite). Última correção de consumo (console 0.3.7): semantic em foundations.colors.semantic ou palette.semantic; Schema A e Bugatti passaram a expor o bloco; Highlander ganhou borderRadius.none.
Lente aplicada: craft principles de design-principles (grid, contraste, elevação, consistência) + frontend-design (identidade visual ousada, tipografia, atmosfera) — este segundo é o mais aderente, já que os 20 arquivos são sistemas de marca maximalistas, não dashboards enterprise.
Sumário executivo
O maior risco aqui não é estético — cada tema, isoladamente, tem uma identidade visual forte e bem pensada (paleta, tipografia e motion coerentes com o universo ficcional escolhido). O problema é de engenharia de tokens: os 20 arquivos foram gerados em pelo menos três gerações de schema incompatíveis entre si, várias delas com referências a variáveis CSS que nunca são definidas. Se algum pipeline (build de tema, gerador de CSS custom properties, seletor de tema no produto) espera uma forma única de JSON, ele quebra ou falha silenciosamente em 13+ dos 20 arquivos. Antes de qualquer refinamento visual, isso precisa ser consolidado.
1. Três schemas incompatíveis coexistindo
| Schema | Arquivos | Estrutura |
|---|---|---|
| A — legado/simples (6) | ancient-rome, cyberpunk-brazil, interstellar, samurai-zen, the-alchemist, deep-sea | metadata + foundations.colors.{palette,gradients} + foundations.typography.fontFamilies + components.{hero,apex-card,specs-table,technical-card} + iconography.icons + animations.keyframes.<nome> |
| B — expandido (13) | star-wars, matrix, mandalorian, lord-of-rings, o-hobbit, house-of-the-dragon, avatar, avatar-a-lenda-de-aang, path-of-the-ronin, the-vikings, conan-o-barbaro, highlander, the-good-the-bad-and-the-ugly | metadata + foundations.colors.{palette,semantic,themes} + typography completa (sizes/weights/lineHeights/letterSpacing) + borderRadius + shadows + navigationExperience + components.{button,card,...} + iconography.essential + animations.<nome>.keyframes |
| C — outlier total (1) | bugatti-brouillard | Sem metadata, sem foundations. Usa designSystem{name,version,keywords}, color_palette (com objetos {hex, usage} em vez de string), typography.fonts/typography.weights com nomenclatura própria (noble, majestic, monumental) |
Três schemas para 20 arquivos significa que qualquer parser único (ex.: um script que lê foundations.colors.palette para gerar CSS variables) processa corretamente só 13 dos 20 temas. Os 6 do Schema A perdem semantic, borderRadius, shadows, button/card variants e navigationExperience — não é que estejam “errados”, é que representam uma geração anterior do produto que nunca foi migrada. O Bugatti é ilegível para qualquer consumidor dos outros 19: color_palette.primary.brouillard_green.hex não tem nenhuma relação estrutural com foundations.colors.palette.*.
Recomendação (P0): definir um schema único (idealmente o B, que é o mais completo) e migrar os 6 arquivos legados + o Bugatti para ele. Vale formalizar como JSON Schema e validar os 20 arquivos em CI antes de qualquer novo tema ser adicionado.
2. Referências a variáveis CSS nunca definidas
Isso é o achado mais sério e mais fácil de corrigir. No Schema B, praticamente todo componente (card, button, apex-card) referencia var(--spacing-4) até var(--spacing-12) — mas nenhum dos 20 arquivos define uma escala de spacing em foundations. É um token fantasma repetido dezenas de vezes (lord-of-rings, o-hobbit, house-of-the-dragon, star-wars, matrix, mandalorian, conan, vikings, ronin, highlander, good-bad-ugly, avatar/Pandora — todos usam var(--spacing-N) sem que exista fonte).
Dois arquivos também referenciam var(--radius-none) / var(--radius-md) em componentes (avatar.json, highlander.json) sem que foundations.borderRadius exista naquele arquivo — outro token fantasma, desta vez pontual.
Além disso, a convenção de nome da variável (como o path do JSON vira --var) muda arquivo a arquivo e às vezes dentro do mesmo arquivo: var(--foundations-colors-palette-earth-clay-burnt) (Schema A, path completo), var(--color-factions-rebel-alliance-pilot-orange) (Star Wars, encurtado), var(--color-palette-semantic-background-primary) (Ronin), var(--color-semantic-background-glass) (Star Wars, outro card do mesmo arquivo), var(--color-palette-earth-shire-green) (O Hobbit). São pelo menos 4 convenções distintas de geração de nome de variável para o mesmo tipo de token — sinal de que os arquivos foram gerados por prompts/gerações diferentes sem um gerador de CSS variables centralizado.
Recomendação (P0): adicionar foundations.spacing (escala em grid de 4px, como o próprio design-principles recomenda) a todos os arquivos do Schema B, e padronizar uma única função determinística de “JSON path → CSS var name” usada por todos os temas.
3. Ausência total de prefers-reduced-motion
Os 20 temas são ricos em motion contínuo — digitalRain (20s loop), mistDrift (60s loop), neonFlicker, hologramFlicker, glow pulsante em quase todo apex-card. Nenhum dos 20 arquivos define uma variante ou flag para prefers-reduced-motion. Para um produto com esse volume de animação decorativa contínua, isso é um gap de acessibilidade real (WCAG 2.3.3), não cosmético — vale adicionar um bloco padrão (animations.reducedMotion ou equivalente) ao schema unificado.
4. Contraste: risco sistêmico nos tokens muted/faint
Praticamente todo arquivo do Schema B define foreground.muted e foreground.faint como a própria cor de texto principal com opacidade reduzida sobre fundo escuro (padrão rgba(fg, 0.4-0.6) e rgba(fg, 0.15-0.2)). Testei com a fórmula de luminância relativa do WCAG no tema Matrix, que é representativo do padrão:
foreground.muted—rgba(0,255,65,0.4)sobre#000000→ contraste 2.92:1 (reprovado; mínimo AA é 4.5:1 para texto normal, 3:1 para texto grande)foreground.faint—rgba(0,255,65,0.15)sobre#000000→ contraste 1.28:1 (praticamente ilegível)
O mesmo padrão de fórmula se repete em Star Wars, Mandaloriano, Senhor dos Anéis, O Hobbit, House of the Dragon, Vikings, Conan, Ronin, Highlander e Sad Hill — não testei os 13 individualmente, mas a estrutura do token é idêntica, então o risco é sistêmico e não um caso isolado. Vale checar caso a caso onde muted/faint é usado como cor de texto real (ex.: tabs.inactive.color em avatar.json, que usa exatamente foreground.muted) versus onde é puramente decorativo.
Curiosamente, avatar.json (Pandora) é o único dos 20 arquivos com um bloco explícito de acessibilidade (designPrinciples.accessibility: { focusRing, minTouchTarget: "44px" }) — e é também um dos que usa foreground.muted como cor de texto funcional em tabs, sem que o próprio contraste tenha sido validado contra a intenção declarada.
Em contrapartida, os botões e cards com texto sólido sobre cor sólida que testei (ex.: botão “bounty” do Sad Hill, #C69C2D com texto #1A1310 → 7.15:1; botão “air” do Avatar-Aang, #87CEEB com texto #2D3436 → 7.28:1) passam com folga — o problema está concentrado nos tokens de opacidade, não no sistema de cor como um todo.
Recomendação (P1): rodar um checker de contraste (ex. wcag-contrast ou polished) sobre todos os pares foreground/background realmente usados em texto, e subir a opacidade mínima de muted/faint ou trocar por cores sólidas mais claras.
5. Inconsistências de conteúdo/metadata
- Localização Brasil contraditória:
avatar.jsondeclaratargetMarket: "Global | Brazil"mas não tem o blocobrazilianMarket.localizationque 7 outros arquivos têm (Star Wars, Matrix, Mandaloriano, House of the Dragon, Conan, Sad Hill, Avatar-Aang). Jástar-wars.json, que declaratargetMarket: "Global"(sem menção a Brasil), tem o bloco. A presença do bloco não é confiável como indicador do mercado real do tema. - Versionamento sem semântica clara: os 6 arquivos do Schema A (os mais simples, sem
semantic/shadows/navigationExperience) estão todos em1.1.0, enquanto vários arquivos do Schema B, muito mais completos, estão em1.0.0. O número de versão não reflete maturidade nem completude do schema — não dá para usá-lo para decidir o que precisa de migração. - Colisão de nome de tema:
design-system-avatar.json(Avatar/Pandora, filme de 2009) edesign-system-avatar-a-lenda-de-aang.json(Avatar: A Lenda de Aang) — o primeiro nome de arquivo é genérico demais e ambíguo com o segundo; se há uma UI de seleção de tema por slug, vale renomear o primeiro para algo comodesign-system-avatar-pandora.json. - Redundância de catálogo: Senhor dos Anéis e O Hobbit competem pelo mesmo imaginário visual (pergaminho, ouro, élfico/dwarf) — não é um bug técnico, mas se o catálogo de temas for exposto ao usuário final, os dois podem parecer variações do mesmo tema em vez de produtos distintos.
6. Avaliação de craft (lente frontend-design)
Nos pontos fortes, os temas cumprem bem o que o skill de frontend design pede: cada um comita a uma direção ousada e específica (tipografia de display incomum — Cinzel Decorative, Bilbo Swash Caps, Zhi Mang Xing —, paleta com cor dominante clara + acento nítido, motion com propósito narrativo em vez de genérico). Isso é o oposto do “AI slop” que o skill quer evitar, e é o maior acerto do conjunto.
Dois pontos valem atenção fina: (1) vários apex-card aplicam backgroundImage de textura direto sobre uma cor de fundo semi-transparente (rgba(0,0,0,0.8) etc.) — funciona, mas em telas menores ou com pouca luz ambiente essas texturas competem com o texto; vale garantir overlay/scrim suficiente em todos os casos, não só nos que já têm backdropFilter: blur. (2) não existe nenhum token de z-index em nenhum dos 20 arquivos, apesar de vários já preverem modal, tooltip, toast, hud e cursores customizados simultâneos (ex. avatar.json) — sem uma escala de camadas, a ordem de empilhamento fica a critério de quem implementa cada componente, o que tende a gerar sobreposição incorreta conforme mais temas ganham modais/toasts.
Prioridades
P0 (bloqueia consumo confiável dos arquivos): unificar os três schemas em um só; adicionar foundations.spacing a todos os arquivos do Schema B; corrigir as duas referências órfãs a --radius-* em avatar.json e highlander.json; padronizar a convenção de nome de CSS variable.
P1 (qualidade/acessibilidade antes de produção): validar contraste de muted/faint em todos os temas onde são usados como texto funcional; adicionar z-index scale; adicionar suporte a prefers-reduced-motion.
P2 (higiene de catálogo): resolver a ambiguidade de nome entre os dois arquivos “avatar”; decidir um critério único para quando incluir brazilianMarket; alinhar versionamento à completude real do schema.