OmniRoute — Design System & Visual Identity (Português (Brasil))
1. Objetivo
Seção intitulada “1. Objetivo”O site de marketing (viral.omniroute.online, why.omniroute.online, omniroute.online) e o dashboard do produto devem parecer um único produto. O site já adotou sua paleta do dashboard — seu css/tokens.css inclusive diz “A paleta espelha o dashboard do OmniRoute (src/app/globals.css)”. Portanto, ambos já estão cerca de 80% alinhados no nível das cores. O que falta no dashboard:
- O papel de parede quadriculado de papel milimetrado que o site utiliza em todas as páginas.
- Alguns tokens de design compartilhados que o site possui, mas o dashboard não (escala de raios, gradiente da marca,
surface-2, fonte mono). - Consistência no nível dos componentes — vários componentes do dashboard ignoram os tokens do tema e usam valores hex/rgba codificados diretamente.
Este documento apresenta a análise e o plano.
2. Princípios
Seção intitulada “2. Princípios”- Fonte única da verdade =
src/app/globals.css. O site espelha o dashboard, nunca o contrário. Novos tokens são adicionados primeiro aoglobals.css. - Tokens, nunca literais. Os componentes consomem tokens semânticos (
bg-surface,text-primary,border-border), nunca valores#hexbrutos. - Sutil, não chamativo. A grade é um papel de parede discreto que fica atrás do conteúdo — ela jamais deve reduzir o contraste do texto ou competir com a interface.
- Ciente do tema. Tudo funciona tanto no modo
.dark(a aparência característica do produto) quanto no modo claro. - Implementação cirúrgica. Primeiro, entregue a grade + os tokens (baixo risco, alta visibilidade); depois, faça a limpeza dos componentes em etapas.
3. Estado atual — o que já está alinhado e o que não está
Seção intitulada “3. Estado atual — o que já está alinhado e o que não está”3.1 Cores — já unificadas ✅
Seção intitulada “3.1 Cores — já unificadas ✅”Todas as cores da marca e superfícies já correspondem às do site em valor (apenas os nomes diferem — o dashboard usa o prefixo --color-). Verificado em src/app/globals.css:30-128:
| Conceito | Token do site (tokens.css) |
Token do dashboard (globals.css) |
Correspondência |
|---|---|---|---|
| primária | --primary #e54d5e |
--color-primary #e54d5e |
✅ |
| primária-hover | --primary-hover #c93d4e |
--color-primary-hover #c93d4e |
✅ |
| destaque | --accent #6366f1 |
--color-accent #6366f1 |
✅ |
| destaque-2 | --accent-2 #8b5cf6 |
--color-accent-hover #8b5cf6 |
✅ (renomeado) |
| destaque-3 | --accent-3 #a855f7 |
--color-accent-light #a855f7 |
✅ (renomeado) |
| sucesso / aviso / erro | #22c55e / #f59e0b / #ef4444 |
idênticos | ✅ |
| luzes de status | #ff5f56 / #ffbd2e / #27c93f |
idênticas | ✅ |
| fundo / superfície / borda escuros | #0b0e14 / #161b22 / rgba(255,255,255,.08) |
idênticos | ✅ |
| fundo / superfície / texto claros | #f9f9fb / #fff / #1a1a2e |
idênticos | ✅ |
Conclusão: não há nenhuma migração de cores a ser feita. A identidade já é compartilhada; estamos concluindo sua implementação, não a reconstruindo.
3.2 Lacunas — o que falta no dashboard
Seção intitulada “3.2 Lacunas — o que falta no dashboard”| Lacuna | O site possui | Dashboard | Ação |
|---|---|---|---|
| Papel de parede quadriculado | Papel milimetrado em body::before, --grid-line, --grid-size 32px, --section-alt |
✅ adicionado (Fase 1) | Parte A |
| Escala de raio | --radius 14px, --radius-sm 9px |
--radius 14px adicionado; -sm + redirecionamento dos componentes pendentes |
Parte B / Fase 2 |
| Gradiente da marca | --grad-brand 135deg primary→accent-3 |
✅ token adicionado (Fase 1); utilizado na Fase 2 | Parte B |
| Superfície aninhada | --surface-2 #1c2230 |
✅ adicionado (Fase 1) | Parte B |
| Fonte monoespaçada | --font-mono (pilha ui-monospace) |
pendente (Fase 4, com os consumidores) | Parte B |
text-muted (escuro) |
#8b8b9e |
#a1a1aa (zinc-400) |
reconciliar — Parte B |
3.3 Mecânica de temas (para não quebrarmos nada)
Seção intitulada “3.3 Mecânica de temas (para não quebrarmos nada)”- Tailwind v4, CSS-first (sem
tailwind.config.*). Os tokens são definidos em:root/.darke disponibilizados aos utilitários por meio de@theme inline(globals.css:130-179). - Modo escuro via classe
.darkem<html>(@custom-variant darkemglobals.css:22), alternado por uma store Zustand personalizada (src/store/themeStore.ts), tema padrão =system(src/shared/constants/appConfig.ts:11). O site usahtml[data-theme="light"]em vez disso — os mecanismos são diferentes, mas nunca se encontram (origens separadas), portanto não há conflito. Mantemos o mecanismo.darkdo dashboard. - Existe uma substituição da cor primária em tempo de execução (
themeStore.ts:85-97, predefinições emCOLOR_THEMES) — os usuários podem trocar--color-primary. Qualquer novo token (gradiente etc.) que faça referência a--color-primaryherda essas substituições sem nenhum esforço adicional. ✅ - Nomes de raio reservados do Tailwind v4:
--radius-sm/md/lg/...são a base dos utilitáriosrounded-*. Redefini-los altera retroativamente todos osrounded-*existentes (por exemplo,rounded-smé usado em 12 arquivos). Portanto, o valor do raio pequeno e o redirecionamento dos componentes foram deliberadamente adiados para a Fase 2, quando os consumidores serão alterados em conjunto.
4. Parte A — O fundo de grade quadriculada (solicitação principal) — IMPLEMENTADO (Fase 1)
Seção intitulada “4. Parte A — O fundo de grade quadriculada (solicitação principal) — IMPLEMENTADO (Fase 1)”4.1 O que é
Seção intitulada “4.1 O que é”A receita exata do site (_mono_repo/omnirouteSite/css/base.css): um pseudo-elemento fixo, ocupando toda a viewport, que desenha dois gradientes de linhas de 1px e fica em z-index:-1 atrás de todo o conteúdo.
body::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background-image: linear-gradient(to right, var(--grid-line) 1px, transparent 1px), linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px); background-size: var(--grid-size) var(--grid-size);}Por que isso funciona mesmo que body tenha um background-color opaco: um ::before com z-index:-1 é renderizado acima do fundo do próprio elemento, mas abaixo do conteúdo dele que está no fluxo. Portanto, --color-bg é o preenchimento base, a grade é sobreposta a ele e o aplicativo é renderizado acima da grade.
4.2 Precedente já existente na base de código
Seção intitulada “4.2 Precedente já existente na base de código”src/app/landing/page.tsx:16-26 já implementa essa mesma grade por página — mas com linhas vermelhas (#E54D5E, opacidade 0.06) a cada 50px, além de orbes animados. Portanto, o padrão já foi validado no produto; este trabalho o promove a um papel de parede global e adaptado ao tema.
4.3 Tokens adicionados (em globals.css)
Seção intitulada “4.3 Tokens adicionados (em globals.css)”:root { /* claro — opacidade da grade aumentada em relação aos 0.045 do site para que o papel de parede seja realmente visível no dashboard denso (cards/interface cobrem a maior parte da viewport) */ --grid-line: rgba(0, 0, 0, 0.07); --grid-size: 32px; --section-alt: rgba(0, 0, 0, 0.022);}.dark { /* escuro — aumentada em relação a 0.035 pelo mesmo motivo */ --grid-line: rgba(255, 255, 255, 0.06); --section-alt: rgba(255, 255, 255, 0.018);}4.4 O único bloqueio — removido
Seção intitulada “4.4 O único bloqueio — removido”A grade é global por definição (ela cobre o painel, auth/login, páginas de erro — todas as rotas — de uma só vez). Exatamente um elemento a ocultava dentro do painel:
-
src/shared/components/layouts/DashboardLayout.tsx— o wrapper externo desenhava umbg-bgopaco. Tudo abaixo dele já é transparente (<main>, o contêiner de rolagem e o elemento internomax-w-7xl), portanto, removerbg-bgpermite que a grade do body apareça através da área de conteúdo (o--color-bgdo body continua sendo o preenchimento base).<div className="flex h-dvh min-h-0 w-full overflow-hidden bg-bg"><div className="flex h-dvh min-h-0 w-full overflow-hidden">
4.5 Interação com a interface (barra lateral / cabeçalho)
Seção intitulada “4.5 Interação com a interface (barra lateral / cabeçalho)”Header(Header.tsx:207,bg-bg) eSidebar(Sidebar.tsx:430,bg-sidebar) permanecem opacos → a grade aparece somente na área de conteúdo, emoldurada por uma interface sólida. É um padrão visual discreto e corresponde à maneira como o site separa a interface da área de trabalho (decisão D3 = sólida).
4.6 Páginas de login / autenticação / erro
Seção intitulada “4.6 Páginas de login / autenticação / erro”Essas páginas são renderizadas diretamente sob <body> (sem a interface do painel), portanto, a grade global deve aparecer atrás delas automaticamente. Fase 5 — CONCLUÍDA: os wrappers independentes de tela cheia eram, de fato, opacos (min-h-screen … bg-bg, em que bg-bg é o mesmo preenchimento sólido de <body>), o que ocultava a grade em todas as telas fora do dashboard — não apenas no login. Agora, todos eles são transparentes para que o papel de parede compartilhado apareça: login, forgot-password, callback, maintenance, offline, status, terms, privacy, onboarding e ErrorPageScaffold (abrange 400/401). Isso conclui a D4 (ampliada de apenas login para todas as telas independentes). Protegido por tests/unit/design-grid-background.test.ts.
4.7 Landing page
Seção intitulada “4.7 Landing page”landing/page.tsx mantém seu fundo animado mais elaborado (orbes + vinheta) — sua própria apresentação de marketing (decisão D5 = manter como está).
5. Parte B — Unificação de tokens
Seção intitulada “5. Parte B — Unificação de tokens”A Fase 1 adiciona os tokens de identidade inertes e sem colisões (--surface-2/--color-surface-2, --grad-brand, --radius). A Fase 2 integra a escala de raios ao Tailwind e redireciona os componentes; a Fase 4 adiciona --font-mono e seus consumidores.
| Token | Motivo | Fase |
|---|---|---|
--radius / --radius-sm |
Uma escala de raios (14/9) em vez de valores ad hoc de 6/8/12 | 1 (valor) / 2 (integrar + redirecionar) |
--grad-brand |
Gradiente da marca para CTAs primários (vermelho→violeta), igual ao site | 1 (token) / 2 (Button) |
--surface-2 |
Painéis aninhados / cabeçalhos de tabela / linhas recuadas | 1 |
--font-mono |
Blocos de código, terminal, IDs, endpoints | 4 |
reconciliar --text-muted |
Escolher um único valor para site↔painel (#a1a1aa recomendado) |
2 |
D2 (text-muted): site #8b8b9e vs. dashboard #a1a1aa. Recomenda-se manter o #a1a1aa do dashboard e atualizar o site para corresponder. Alteração cosmética.
6. Parte C — Padronização de componentes (Fases 2–4)
Seção intitulada “6. Parte C — Padronização de componentes (Fases 2–4)”Componentes personalizados (sem shadcn/Radix), Tailwind v4, tokens semânticos majoritariamente adotados (195 arquivos importam o barrel compartilhado). O trabalho consiste em remover os desvios. Local: src/shared/components/.
| # | Item | Arquivo(s) | Problema → Objetivo | Fase |
|---|---|---|---|---|
| C1 | Alinhamento dos raios | Button.tsx:14-18, Card.tsx:39, Modal.tsx, Input.tsx, Select.tsx |
mistura de 6/8/12px → --radius/--radius-sm (14/9) |
2 |
| C2 | Gradiente do Button + variante accent |
Button.tsx:5-12 |
primário é vermelho→vermelho chapado; alinhar a --grad-brand; adicionar a variante accent ausente. ~195 importadores — maior visibilidade |
2 |
| C3 | Tabelas | DataTable.tsx:122-176, logTableStyles.ts, globals.css:405-414 |
100% de rgba hardcoded inline + variáveis inexistentes; migrar para tokens e descontinuar estilos divergentes | 3 |
| C4 | Centralizar cores de status | flow/edgeStyles.ts, TokenHealthBadge.tsx, DegradationBadge.tsx, ProviderCascadeNode.tsx, Badge.tsx + 5 helpers |
mais de 6 cópias dos mesmos valores hex → um único módulo baseado em --color-success/warning/error |
3 |
| C5 | Borda do Card | Card.tsx:39 |
border-white/5 → marca /8 |
2 |
| C6 | Reconciliar anel de foco ✅ CONCLUÍDO | globals.css --focus-ring (accent) vs. ring-primary/30 dos controles de formulário |
unificado em accent (violeta) para corresponder ao anel global + diferenciar do anel vermelho de erro; o erro permanece vermelho | 4 |
| C7 | Adicionar Checkbox + Textarea |
<input>/<textarea> brutos com accentColor:#6366f1 inline |
primitivas orientadas por tokens | 4 |
| C8 | Varredura de hex hardcoded | ConsoleLogViewer.tsx:240, ComboLiveStudio.tsx:306, pontos do Modal, ~14 arquivos de gráficos |
literais → tokens | 4 |
| C9 | cn() → clsx + tailwind-merge |
src/shared/utils/cn.ts |
classes conflitantes se acumulam; necessário para sobrescritas de C1 | 2 |
Já alinhados à marca (orientados por tokens, precisam apenas de raio): Badge, Toggle, SegmentedControl, Input, Select.
7. Plano de rollout
Seção intitulada “7. Plano de rollout”- Fase 1 — Grid + tokens de identidade (ESTE PR). Grid no
globals.css+ tokens--surface-2/--grad-brand/--radius; wallpaper embody::before; remover o bloqueadorbg-bg; teste de proteção estático. Baixo risco, reversível em um único commit. - Fase 2 — Primitivos (C1, C2, C5) — CONCLUÍDA neste PR. Utilitários semânticos de raio
rounded-card(14px) /rounded-control(9px) adicionados via@theme(nomes personalizados, portanto os padrõesrounded-sm/md/lg/xlpermanecem intactos — sem impacto em 400 arquivos); Card/Modal → 14px, Button/Input/Select → 9px; Button primário →--grad-brand(vermelho→violeta) + nova varianteaccent; bordas de Card → o tokenborder-border(0.08). Adiado:cn()→tailwind-merge (C9) precisa de novas dependências; a varredura pontual derounded-lg(326 arquivos) foi mantida como está, pois os primitivos cobrem a maior parte da superfície. - Fase 3 — Cores de status + tabelas (C3, C4) — CONCLUÍDA neste PR. ✅ C4 (
src/shared/constants/statusColors.ts—STATUS_HEXcomo fonte única;flow/edgeStyles.ts+TokenHealthBadgeredirecionados, fiéis/mesmo valor hexadecimal). ✅ Token--font-mono. ✅ C3 (DataTable) — substituídos todos os rgba inline + os fallbacks inativosvar(--bg-table-header)/var(--text-secondary)por um conjunto de tokens--table-*(--table-header-bg/-row-zebra/-row-hover/-cell-border/-row-selected), cujos valores no tema escuro são exatamente iguais aos antigos rgba codificados diretamente (tema escuro idêntico byte a byte) e cujos valores no tema claro corrigem o tema claro que antes era sempre escuro. Borda do cabeçalho →--color-border, texto secundário →--color-text-muted. Requer uma revisão visual antes do merge. (Não alterados:logTableStyles.tse as regras legadas.ant-tabledo Ant — separados, com prioridade menor.) - Fase 4 — Limpeza (C6, C7, C9 concluídos; C8 pendente). ✅ C9
cn()→twMerge(clsx(...))(clsx + tailwind-merge adicionados como dependências) — agora oclassNamede quem chama substitui corretamente uma classe conflitante do primitivo, em vez de empilhá-la. ✅ C7 novos primitivosCheckbox+Textarea(orientados por tokens, exportados pelo barrel; aditivos — a adoção dos 32 checkboxes brutos / 41 textareas brutas pode ocorrer de forma incremental). ✅ C6 conciliação do anel de foco — os controles de formulário (Input/Select/Textarea/Toggle/Checkbox) agora usam o anel de accent (violeta) no foco para corresponder ao--focus-ringglobal e evitar conflito com o anel vermelho de erro; o estado vermelho de erro permanece inalterado. ⏳ A varredura de valores hexadecimais da C8 NÃO é um localizar/substituir indiscriminado — ocorrências confirmadas como intencionais e que devem permanecer:ConsoleLogViewer.tsx:240(terminal sempre escuro), popover deTokenHealthBadge, traços SVG do ReactFlow. Migrar apenas valores hexadecimais que realmente devam responder ao tema.
Em cada fase: npm run lint + npm run typecheck:core + uma revisão visual.
8. Decisões em aberto (recomendações)
Seção intitulada “8. Decisões em aberto (recomendações)”- D1 — Button primário: manter vermelho→vermelho ou mudar para vermelho→violeta
--grad-brand? Recomendação: vermelho→violeta (Fase 2). - D2 — Cor das linhas do grid: neutra (estilo do site) — escolhida — em vez de vermelho da marca. Tamanho 32px (reduzido em ~30% em relação aos 46px originais após feedback do responsável — células de 46px pareciam grandes demais no layout do dashboard).
- D3 — Vivacidade do chrome: sidebar/header sólidos — escolhido.
- D4 — Grid de autenticação/login: ✅ CONCLUÍDO (Fase 5) —
bg-bgopaco removido de todos os wrappers independentes de tela cheia (não apenas do login), para que o grid apareça em todas as telas. Consulte §4.6. - D5 — Landing page: manter a splash animada como está. Escolhido.
- D6 — Raio 14/9 em todo o produto: Recomendação: sim (Fase 2).
- D7 — Fase 1 enviada primeiro: Escolhido.
- D8 — Largura do layout (Fase 5): o contêiner de conteúdo do dashboard estava limitado a
max-w-7xl(1280px), ficando centralizado com amplas margens laterais vazias em monitores grandes. ✅ CONCLUÍDO — aumentado para ummax-w-[3840px]fluido (4K real): agora o conteúdo acompanha a viewport até ~4K e só é centralizado além desse ponto (DashboardLayout.tsx). Páginas deliberadamente estreitas continuam estreitas por design (ProviderOnboardingWizardmax-w-5xl,Rtk/CavemanContextPageClientmax-w-6xl). - D9 — Tabelas de dados opacas (Fase 6): com a área de conteúdo do dashboard agora transparente (para que o wallpaper de grid apareça através dela, Fase 5), tabelas de dados cujo contêiner não era uma superfície opaca deixavam o grid vazar por suas linhas pares transparentes / zebra de baixa opacidade. ✅ CONCLUÍDO — agora toda tabela sem card aplica
bg-surface(ou, no caso do primitivo<DataTable>,background: var(--color-surface)em seu contêiner de rolagem). Corrigidos:DataTable(primitivo),ProxyLogger/RequestLoggerV2(o tombg-black/5 dark:bg-black/20de seus<Card>estava prevalecendo sobre obg-surfacedo Card via tailwind-merge → ~95% transparente),BatchListTab/FilesListTab/CacheEntriesTab/ReasoningCacheTab/cache page/FreePoolTab/ModelMappingTable/HeaderTable, além das duas “tabelas” em CSS grid nas visualizações de cache (bg-surface/35→bg-surface). As tabelas que já estavam dentro de um<Card>/Modal foram verificadas como opacas e deliberadamente mantidas intactas (bg-surfaceseria redundante e não teria efeito ali). O grid em si não precisou de nenhuma alteração — obody::beforedo dashboard é idêntico byte a byte ao do site (--grid-size: 32px); qualquer “grid maior” visto em uma instância em execução é um build antigo anterior ao#4143, não o código atual. Protegido portests/unit/design-grid-background.test.ts(bloco da Fase 6).
9. Fora do escopo / riscos
Seção intitulada “9. Fora do escopo / riscos”- Nenhuma alteração na paleta — as cores já correspondem; adicionamos apenas os tokens ausentes. Risco zero de alterar as cores do produto.
- Nenhuma alteração no mecanismo de temas — manter
.dark+ store Zustand. - A mudança de raio (Fase 2) é abrangente — afeta todos os cards/botões/inputs; inspecione visualmente telas densas (tabelas, modais) antes do merge.
- As tabelas (C3) concentram a maior quantidade de estilos hardcoded e a maior superfície de regressão — isole-as em seu próprio PR.
10. Índice de referências
Seção intitulada “10. Índice de referências”| Área | Caminho |
|---|---|
| Tokens do dashboard | src/app/globals.css (:root, .dark, @theme inline, body, body::before) |
| Store de tema | src/store/themeStore.ts, src/shared/components/ThemeProvider.tsx, src/shared/constants/appConfig.ts:9-11 |
| Estrutura do painel (grid desbloqueado aqui) | src/shared/components/layouts/DashboardLayout.tsx |
| Chrome | src/shared/components/Header.tsx:207, src/shared/components/Sidebar.tsx:430 |
| Precedente do grid | src/app/landing/page.tsx:16-26 |
| Primitivos | src/shared/components/{Button,Card,Input,Select,Badge,Modal,Toggle,SegmentedControl,Loading,Tooltip,DataTable}.tsx |
| Fontes de cores de status | flow/edgeStyles.ts, TokenHealthBadge.tsx, DegradationBadge.tsx, logTableStyles.ts |
Utilitário cn |
src/shared/utils/cn.ts |
| Teste de proteção da Fase 1 | tests/unit/design-grid-background.test.ts |
| Referência do site | _mono_repo/omnirouteSite/css/tokens.css, css/base.css |
HagiCode
HagiCode é um ambiente de programação com agentes, fluxos estruturados, execução multiagente e visualizações Hero Dungeon.
Transforme ideias em software útil com um fluxo de trabalho com agentes mais inteligente, rápido e agradável.

- SmartFluxos estruturados transformam intenções em um caminho executável da ideia à entrega.
- EfficientFluxos multiagente mantêm pesquisa, implementação e revisão em andamento simultaneamente.
- FunO Hero Dungeon torna longas sessões de programação mais visuais e colaborativas.