Tokens de Cor
Design System · Arrow DS · Dimensão 01 Cor
Versão: 1.0 · Status: Validado
Âncora base: #081128 (primitive.midnight.900)
Depende de:
Usado por: Dimensão 02 Tipografia, todos os componentes de UI
Princípios da Dimensão
Cor comunica intenção antes de comunicar estética.
Em um produto denso como a Effecti prazos, valores, status de processo a cor não decora. Ela informa: este campo tem erro, esta ação é destrutiva, este prazo está crítico. Antes de qualquer palavra, a cor já tomou uma decisão semântica.
Escalas LCH perceptual calibradas, não arbitrárias.
As 9 famílias de cor foram construídas com progressão uniforme em LCH (Lightness–Chroma–Hue), não em espaço sRGB. O resultado é uma escala onde cada stop parece visualmente equidistante sem os saltos bruscos ou aglomerações que surgem em escalas HSL. As âncoras vêm do BrandBook; os demais stops são derivados matematicamente.
Dois níveis obrigatórios primitivos para construir, semânticos para usar.
Nenhum valor hexadecimal ou primitivo entra diretamente no código de produto. Todo componente referencia um token semântico nomeado por intenção (color.action.primary, color.feedback.error). Primitivos existem para construir os semânticos e para nada mais.
Fundação Famílias Cromáticas
O sistema é composto por 9 famílias cromáticas, cada uma com 11 stops (0 a 900). As âncoras de cada família são os valores do BrandBook; os demais stops são escalas LCH derivadas.
| Família | Âncora | Stop âncora | Papel no sistema | |
|---|---|---|---|---|
| Midnight Neutral | #081128 | 900 | Neutro base superfícies, conteúdo, bordas | |
| Blizzard Blue | #A7EAFB | 200 | CTA principal, ação, acento de marca | |
| Gulf Blue | #121D59 | 800 | Institucional, informação, marca profunda | |
| Merino Beige | #F1EDE1 | 100 | Superfície quente, fundo editorial | |
| Bloom Red | #D2082D | 500 | Erro, destruição, prazo crítico | |
| Orange Sunset | #E56307 | 500 | Premium, destaque comercial | |
| Mint Green | #349E06 | 500 | Sucesso, confirmação, habilitado | |
| Petal Pink | #C40795 | 500 | Badge, notificação, elemento de destaque | |
| Butter Yellow | #ECCE24 | 400 / 500 | Aviso, atenção, alerta não crítico |
Regra
As famílias Gulf, Merino, Pink e Yellow têm uso restrito — Gulf e Merino são institucionais, Pink e Yellow são reservados para feedback específico. O Midnight e o Blizzard são as famílias de trabalho do sistema.
Primitivos
Primitivos são os valores brutos das escalas o vocabulário cromático do sistema. Eles existem para serem mapeados nos tokens semânticos, nunca para aparecer diretamente em componentes.
Midnight Neutral
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.midnight.0 | Branco absoluto, superfície base light | ||
primitive.midnight.50 | Superfície sutil, fundo de input | ||
primitive.midnight.100 | Superfície elevada, hover neutro | ||
primitive.midnight.200 | Borda padrão, overlay | ||
primitive.midnight.300 | Borda forte, conteúdo desabilitado | ||
primitive.midnight.400 | |||
primitive.midnight.500 | Conteúdo terciário | ||
primitive.midnight.600 | Conteúdo secundário | ||
primitive.midnight.700 | |||
primitive.midnight.800 | |||
primitive.midnight.900 | Conteúdo primário, superfície invertida |
Blizzard Blue
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.blizzard.50 | |||
primitive.blizzard.100 | Superfície de ação, hover de ação | ||
primitive.blizzard.200 | Ação sutil, focus ring, brand | ||
primitive.blizzard.300 | |||
primitive.blizzard.400 | CTA em dark mode | ||
primitive.blizzard.500 | CTA light mode, borda de acento, conteúdo acento | ||
primitive.blizzard.600 | Hover de ação | ||
primitive.blizzard.700 | Pressed de ação | ||
primitive.blizzard.800 | Ação sutil em dark | ||
primitive.blizzard.900 | Superfície de ação em dark |
Gulf Blue
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.gulf.50 | |||
primitive.gulf.100 | |||
primitive.gulf.200 | |||
primitive.gulf.300 | |||
primitive.gulf.400 | |||
primitive.gulf.500 | |||
primitive.gulf.600 | |||
primitive.gulf.700 | |||
primitive.gulf.800 | Brand institucional | ||
primitive.gulf.900 |
Merino Beige
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.merino.50 | Superfície quente (surface.warm) | ||
primitive.merino.100 | Brand editorial | ||
primitive.merino.200 | |||
primitive.merino.300 | |||
primitive.merino.400 | |||
primitive.merino.500 | |||
primitive.merino.600 | |||
primitive.merino.700 | |||
primitive.merino.800 | |||
primitive.merino.900 |
Bloom Red
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.red.50 | Hover de erro | ||
primitive.red.100 | Superfície de erro | ||
primitive.red.200 | |||
primitive.red.300 | |||
primitive.red.400 | Erro em dark mode | ||
primitive.red.500 | Erro, borda de erro | ||
primitive.red.600 | Hover de erro | ||
primitive.red.700 | Conteúdo de erro, texto sobre superfície de erro | ||
primitive.red.800 | |||
primitive.red.900 | Superfície de erro em dark |
Orange Sunset
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.orange.50 | |||
primitive.orange.100 | Superfície premium | ||
primitive.orange.200 | |||
primitive.orange.300 | |||
primitive.orange.400 | Premium em dark | ||
primitive.orange.500 | Premium | ||
primitive.orange.600 | Hover premium | ||
primitive.orange.700 | Conteúdo premium | ||
primitive.orange.800 | |||
primitive.orange.900 | Superfície premium em dark |
Mint Green
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.green.50 | |||
primitive.green.100 | Superfície de sucesso | ||
primitive.green.200 | |||
primitive.green.300 | |||
primitive.green.400 | Sucesso em dark | ||
primitive.green.500 | Sucesso | ||
primitive.green.600 | Hover sucesso | ||
primitive.green.700 | Conteúdo sucesso | ||
primitive.green.800 | |||
primitive.green.900 | Superfície sucesso em dark |
Petal Pink
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.pink.50 | |||
primitive.pink.100 | Superfície de badge | ||
primitive.pink.200 | Focus ring de erro | ||
primitive.pink.300 | |||
primitive.pink.400 | Badge em dark | ||
primitive.pink.500 | Badge | ||
primitive.pink.600 | Hover badge | ||
primitive.pink.700 | Conteúdo badge | ||
primitive.pink.800 | |||
primitive.pink.900 | Superfície badge em dark |
Butter Yellow
| Token | Hex | Uso semântico | |
|---|---|---|---|
primitive.yellow.50 | |||
primitive.yellow.100 | Superfície de aviso | ||
primitive.yellow.200 | |||
primitive.yellow.300 | |||
primitive.yellow.400 | Aviso em dark | ||
primitive.yellow.500 | Aviso ⚠ não passa AA sozinho | ||
primitive.yellow.600 | Hover aviso | ||
primitive.yellow.700 | Conteúdo aviso | ||
primitive.yellow.800 | |||
primitive.yellow.900 | Superfície aviso em dark |
css
:root {
/* Midnight Neutral */
--primitive-midnight-0: #FFFFFF;
--primitive-midnight-50: #F8F8F9;
--primitive-midnight-100: #EDEEF0;
--primitive-midnight-200: #DCDCE1;
--primitive-midnight-300: #BFC0C8;
--primitive-midnight-400: #9B9DA9;
--primitive-midnight-500: #737686;
--primitive-midnight-600: #505468;
--primitive-midnight-700: #33384E;
--primitive-midnight-800: #1B2339;
--primitive-midnight-900: #081128;
/* Blizzard Blue */
--primitive-blizzard-50: #EAF9FD;
--primitive-blizzard-100: #D1F4FD;
--primitive-blizzard-200: #A7EAFB;
--primitive-blizzard-300: #4FD1EC;
--primitive-blizzard-400: #00B2D7;
--primitive-blizzard-500: #0092BE;
--primitive-blizzard-600: #007198;
--primitive-blizzard-700: #005677;
--primitive-blizzard-800: #003C55;
--primitive-blizzard-900: #002738;
/* Gulf Blue */
--primitive-gulf-50: #F7F6FB;
--primitive-gulf-100: #E9E7F2;
--primitive-gulf-200: #D5D2E7;
--primitive-gulf-300: #B7B2D4;
--primitive-gulf-400: #918BB9;
--primitive-gulf-500: #6B679E;
--primitive-gulf-600: #494783;
--primitive-gulf-700: #2B2E6B;
--primitive-gulf-800: #121D59;
--primitive-gulf-900: #051244;
/* Merino Beige */
--primitive-merino-50: #FEFCF7;
--primitive-merino-100: #F1EDE1;
--primitive-merino-200: #DCD4BA;
--primitive-merino-300: #C0B691;
--primitive-merino-400: #A4996C;
--primitive-merino-500: #877C4C;
--primitive-merino-600: #6A6135;
--primitive-merino-700: #4E4721;
--primitive-merino-800: #363112;
--primitive-merino-900: #242007;
/* Bloom Red */
--primitive-red-50: #FFF3F1;
--primitive-red-100: #FFE2DE;
--primitive-red-200: #FFC6BF;
--primitive-red-300: #FF9D94;
--primitive-red-400: #FB6965;
--primitive-red-500: #D2082D;
--primitive-red-600: #AC001B;
--primitive-red-700: #87000F;
--primitive-red-800: #640003;
--primitive-red-900: #430000;
/* Orange Sunset */
--primitive-orange-50: #FFF4EC;
--primitive-orange-100: #FFE5D5;
--primitive-orange-200: #FFCBAE;
--primitive-orange-300: #FCA779;
--primitive-orange-400: #ED8143;
--primitive-orange-500: #E56307;
--primitive-orange-600: #BB4900;
--primitive-orange-700: #923400;
--primitive-orange-800: #692200;
--primitive-orange-900: #441500;
/* Mint Green */
--primitive-green-50: #F2F9ED;
--primitive-green-100: #E0F0D7;
--primitive-green-200: #C2E0B1;
--primitive-green-300: #97C97E;
--primitive-green-400: #66AF47;
--primitive-green-500: #349E06;
--primitive-green-600: #137C00;
--primitive-green-700: #005E00;
--primitive-green-800: #004200;
--primitive-green-900: #092800;
/* Petal Pink */
--primitive-pink-50: #FFF3FA;
--primitive-pink-100: #FFE3F4;
--primitive-pink-200: #FBC9E6;
--primitive-pink-300: #F5A1D5;
--primitive-pink-400: #EA6ABE;
--primitive-pink-500: #C40795;
--primitive-pink-600: #A10078;
--primitive-pink-700: #7E005C;
--primitive-pink-800: #5D0043;
--primitive-pink-900: #3D002C;
/* Butter Yellow */
--primitive-yellow-50: #FDF9EF;
--primitive-yellow-100: #F9F0D8;
--primitive-yellow-200: #F6E4AF;
--primitive-yellow-300: #F2D97C;
--primitive-yellow-400: #ECCE24;
--primitive-yellow-500: #B09707;
--primitive-yellow-600: #8C7900;
--primitive-yellow-700: #6F6000;
--primitive-yellow-800: #544800;
--primitive-yellow-900: #3F3607;
}Regra
Primitivos nunca entram no código de produto diretamente. Todo componente referencia apenas tokens semânticos. Usar
#0092BE em vez de color.action.primary é proibido. Tokens Semânticos
Estrutura de cada token
Tokens de cor seguem o padrão de intenção sobre valor:
color.{categoria}.{papel}
└── color (valor hexadecimal via alias do primitivo)
Exemplo:
color.action.primary → var(--primitive-blizzard-500)
color.feedback.error → var(--primitive-red-500)
color.surface.base → var(--primitive-midnight-0)Categoria: Surface
Papel: Camadas de fundo e estrutura visual. Define a hierarquia de profundidade da interface do mais claro (base) ao mais denso (overlay e inverted).
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.surface.base` | `midnight.0` (#FFF) | `midnight.900` | Fundo de página, base de modal |
| `color.surface.subtle` | `midnight.50` | `midnight.800` | Input, área de conteúdo secundário |
| `color.surface.raised` | `midnight.100` | `midnight.700` | Card elevado, hover neutro |
| `color.surface.overlay` | `midnight.200` | `midnight.600` | Overlay leve, divisor visual |
| `color.surface.inverted` | `midnight.900` | `midnight.0` | Tooltip dark, banner invertido |
| `color.surface.warm` | `merino.50` | `midnight.800` | Fundo editorial, seção institucional |
css
--color-surface-base: var(--primitive-midnight-0);
--color-surface-subtle: var(--primitive-midnight-50);
--color-surface-raised: var(--primitive-midnight-100);
--color-surface-overlay: var(--primitive-midnight-200);
--color-surface-inverted: var(--primitive-midnight-900);
--color-surface-warm: var(--primitive-merino-50);Boas práticas Surface
surface.baseé o padrão absoluto de fundo ponto de partida de qualquer telasurface.subtlepara inputs, áreas de preenchimento, fundos de seção secundáriasurface.raisedpara cards, dropdowns, qualquer elemento que precise de elevação visualsurface.invertedé exclusivo para componentes que flutuam sobre o fundo claro (tooltip, snackbar dark)surface.warmé reservado para páginas editoriais, onboarding, institucional nunca em UI operacional densa- Nunca empilhar mais de 3 níveis de surface em sequência direta a hierarquia perde contraste
Combinações recomendadas
color.surface.base → fundo de toda tela de produto
color.surface.subtle → fundo de input, área de tabela zerada
color.surface.raised → card de pregão, dropdown de filtro
color.surface.warm → página de onboarding, empty state editorial
color.surface.inverted → tooltip, snackbar de confirmaçãoCategoria: Content
Papel: Cor de texto e ícones. Hierarquiza a informação do texto principal ao desabilitado sem depender de tamanho ou peso.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.content.primary` | `midnight.900` | `midnight.50` | Títulos, dados em destaque, texto principal |
| `color.content.secondary` | `midnight.600` | `midnight.200` | Texto corrido, descrições, parágrafos |
| `color.content.tertiary` | `midnight.500` | `midnight.300` | Labels, metadados, texto de suporte |
| `color.content.disabled` | `midnight.300` | `midnight.600` | Texto desabilitado (não passa AA intencional) |
| `color.content.inverted` | `midnight.0` | `midnight.900` | Texto sobre superfície invertida |
| `color.content.accent` | `blizzard.500` | `blizzard.400` | Link, ação textual, acento de destaque |
css
--color-content-primary: var(--primitive-midnight-900);
--color-content-secondary: var(--primitive-midnight-600);
--color-content-tertiary: var(--primitive-midnight-500);
--color-content-disabled: var(--primitive-midnight-300);
--color-content-inverted: var(--primitive-midnight-0);
--color-content-accent: var(--primitive-blizzard-500);Boas práticas Content
content.primarypara todo texto que carrega informação crítica números, títulos, dados de processocontent.secondarypara texto corrido e descrições nunca usarprimaryem parágrafos longoscontent.tertiarytem contraste de 4.1:1 emsurface.baseuso restrito a texto auxiliar e labels pequenoscontent.disabledreprova intencionalmente no WCAG sinaliza que o elemento não está disponívelcontent.accentexclusivo para elementos clicáveis ou de ênfase editorial nunca usar em texto estático
Combinações recomendadas
content.primary + type.heading.* → título de seção, número de pregão
content.secondary + type.body.* → descrição do objeto, texto de suporte
content.tertiary + type.label.* → label de campo, metadado de card
content.accent + type.body.md → link inline, ação textual
content.inverted + surface.inverted → texto em tooltip darkCategoria: Border
Papel: Delimitação de elementos inputs, cards, divisores, highlight de seleção. Separa sem ocupar espaço visual excessivo.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.border.default` | `midnight.200` | `midnight.700` | Input idle, card, divisor, tabela |
| `color.border.strong` | `midnight.300` | `midnight.600` | Input hover, separador com mais peso |
| `color.border.accent` | `blizzard.500` | `blizzard.400` | Input focus, elemento selecionado, destaque de ação |
| `color.border.error` | `red.500` | `red.400` | Input com erro de validação |
css
--color-border-default: var(--primitive-midnight-200);
--color-border-strong: var(--primitive-midnight-300);
--color-border-accent: var(--primitive-blizzard-500);
--color-border-error: var(--primitive-red-500);Boas práticas Border
border.defaulté o estado idle de todo input e card nunca usar valor brutoborder.accentexclusivo para estado de foco ou seleção nunca usar decorativamenteborder.errorsempre acompanhafeedback.errorestate.focus-ring-errorno mesmo input- Nunca usar
border.strongem estado de foco ele não tem contraste suficiente para sinalizar seleção
Combinações recomendadas
border.default + surface.base → input idle, card neutro
border.accent + state.focus-ring → input em foco
border.error + feedback.error → campo de formulário com erro
border.strong + content.tertiary → divisor de seção com pesoCategoria: Action
Papel: CTA principal e seus estados interativos. O Blizzard Blue é a cor de ação do sistema botões primários, links de navegação, checkboxes ativos.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.action.primary` | `blizzard.500` | `blizzard.400` | Botão primário (default), ícone ativo |
| `color.action.hover` | `blizzard.600` | `blizzard.300` | Botão primário em hover |
| `color.action.pressed` | `blizzard.700` | `blizzard.500` | Botão primário em pressed |
| `color.action.subtle` | `blizzard.200` | `blizzard.800` | Ação secundária, chip de filtro ativo |
| `color.action.surface` | `blizzard.100` | `blizzard.900` | Fundo de área de ação, banner CTA |
| `color.action.disabled` | `midnight.200` | `midnight.700` | Botão desabilitado |
css
--color-action-primary: var(--primitive-blizzard-500);
--color-action-hover: var(--primitive-blizzard-600);
--color-action-pressed: var(--primitive-blizzard-700);
--color-action-subtle: var(--primitive-blizzard-200);
--color-action-surface: var(--primitive-blizzard-100);
--color-action-disabled: var(--primitive-midnight-200);Boas práticas Action
- A progressão
primary → hover → pressedé obrigatória nunca criar estados intermediários fora da escala action.subtleé para ações secundárias e filtros nunca para CTAs que precisam de destaqueaction.disabledsubstituiaction.primaryem botões desabilitados junto comcontent.disabledno texto- Em dark mode, o CTA sobe um stop (
blizzard.400) para manter o contraste WCAG de 4.5:1 sobresurface.basedark
Combinações recomendadas
action.primary + content.inverted → botão primário (texto branco sobre azul)
action.hover + content.inverted → botão primário em hover
action.subtle + content.accent → botão ghost / outline com fill sutil
action.disabled + content.disabled → botão desabilitado
action.surface + border.accent → banner de chamada para açãoCategoria: Feedback Erro
Papel: Erros de validação, ações destrutivas, prazos críticos. A cor mais importante do sistema de feedback deve ser reservada estritamente para estados negativos.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.feedback.error` | `red.500` | `red.400` | Ícone de erro, indicador de campo inválido |
| `color.feedback.error-hover` | `red.600` | Estado hover em elemento destrutivo | |
| `color.feedback.error-surface` | `red.100` | `red.900` | Fundo de toast de erro, área de alerta |
| `color.feedback.error-border` | `red.500` | `red.400` | Borda de input com erro |
| `color.feedback.error-content` | `red.700` | `red.200` | Texto de mensagem de erro |
css
--color-feedback-error: var(--primitive-red-500);
--color-feedback-error-hover: var(--primitive-red-600);
--color-feedback-error-surface: var(--primitive-red-100);
--color-feedback-error-border: var(--primitive-red-500);
--color-feedback-error-content: var(--primitive-red-700);Boas práticas Erro
feedback.errorefeedback.error-bordersempre aparecem juntos em inputs inválidosfeedback.error-contentsobrefeedback.error-surfacegarante contraste para a mensagem de erro abaixo do campo- Nunca usar vermelho para ênfase decorativa ou chamada de atenção não relacionada a erro isso deprecia o sinal
- Em formulários, o trio
border.error + feedback.error-surface + feedback.error-contenté o padrão de validação
Categoria: Feedback Sucesso
Papel: Confirmação de ação, habilitação de fornecedor, processo concluído com sucesso.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.feedback.success` | `green.500` | `green.400` | Ícone de sucesso, indicador de status positivo |
| `color.feedback.success-surface` | `green.100` | `green.900` | Fundo de toast de sucesso |
| `color.feedback.success-border` | `green.500` | `green.400` | Borda de elemento com status positivo |
| `color.feedback.success-content` | `green.700` | `green.200` | Texto de mensagem de sucesso |
css
--color-feedback-success: var(--primitive-green-500);
--color-feedback-success-surface: var(--primitive-green-100);
--color-feedback-success-border: var(--primitive-green-500);
--color-feedback-success-content: var(--primitive-green-700);Boas práticas Sucesso
- Reservado para confirmações reais proposta enviada, documento aprovado, fornecedor habilitado
- Nunca usar verde para progresso parcial ou estados neutros isso confunde com confirmação total
Categoria: Feedback Aviso
Papel: Alertas de atenção, prazos próximos, informações que precisam de revisão. Diferente do erro a ação ainda é possível.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.feedback.warning` | `yellow.500` | `yellow.400` | Ícone de aviso ⚠ sempre acompanhado de ícone |
| `color.feedback.warning-surface` | `yellow.100` | `yellow.900` | Fundo de banner de aviso |
| `color.feedback.warning-border` | `yellow.500` | `yellow.400` | Borda de elemento em atenção |
| `color.feedback.warning-content` | `yellow.700` | `yellow.200` | Texto de mensagem de aviso |
css
--color-feedback-warning: var(--primitive-yellow-500);
--color-feedback-warning-surface: var(--primitive-yellow-100);
--color-feedback-warning-border: var(--primitive-yellow-500);
--color-feedback-warning-content: var(--primitive-yellow-700);Boas práticas Aviso
feedback.warning(yellow.500) tem ratio 3.8:1 sobresurface.basenão passa AA em texto solo- Obrigatório sempre usar acompanhado de ícone de aviso para garantir acessibilidade
feedback.warning-content(yellow.700) passa AA e pode ser usado em texto sobrefeedback.warning-surface- Nunca usar amarelo como cor de destaque positivo no contexto da Effecti, amarelo significa atenção
Categoria: Feedback Premium
Papel: Recursos, funcionalidades ou planos premium. Diferencia conteúdo exclusivo do fluxo padrão.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.feedback.premium` | `orange.500` | `orange.400` | Ícone de premium, tag de recurso exclusivo |
| `color.feedback.premium-surface` | `orange.100` | `orange.900` | Fundo de card premium, banner de upgrade |
| `color.feedback.premium-border` | `orange.500` | `orange.400` | Borda de card premium |
| `color.feedback.premium-content` | `orange.700` | `orange.200` | Texto de label premium |
css
--color-feedback-premium: var(--primitive-orange-500);
--color-feedback-premium-surface: var(--primitive-orange-100);
--color-feedback-premium-border: var(--primitive-orange-500);
--color-feedback-premium-content: var(--primitive-orange-700);Boas práticas Premium
feedback.premium(orange.500) tem ratio 3.2:1 não passa AA em texto solo, assim como warning- Usar sempre com ícone ou em contexto onde o rótulo "Premium" já está visível
- Nunca usar laranja para alertas ou erros a família Orange Sunset é exclusiva do premium
Categoria: Feedback Badge
Papel: Notificações, contadores, badges de destaque. A cor mais vibrante do sistema uso muito restrito.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.feedback.badge` | `pink.500` | `pink.400` | Ponto de notificação, contador de badge |
| `color.feedback.badge-surface` | `pink.100` | `pink.900` | Fundo de badge de notificação |
| `color.feedback.badge-border` | `pink.500` | `pink.400` | |
| `color.feedback.badge-content` | `pink.700` | `pink.200` | Número dentro do badge |
css
--color-feedback-badge: var(--primitive-pink-500);
--color-feedback-badge-surface: var(--primitive-pink-100);
--color-feedback-badge-border: var(--primitive-pink-500);
--color-feedback-badge-content: var(--primitive-pink-700);Boas práticas Badge
- Exclusivo para elementos de notificação contadores, pontos de alerta não lido
- É a cor mais saturada do sistema usar com extrema parcimônia
- Nunca substituir
feedback.errorporfeedback.badgepapéis distintos, não intercambiáveis
Categoria: States
Papel: Estados interativos transientes hover, pressed, focus, disabled. Não comunicam semântica de conteúdo, comunicam interatividade.
| Token | Light Mode | Dark Mode | Uso |
|---|---|---|---|
| `color.state.hover-neutral` | `midnight.100` | `midnight.800` | Hover em linha de tabela, item de menu, chip |
| `color.state.hover-accent` | `blizzard.100` | `blizzard.900` | Hover em item de ação secundária |
| `color.state.hover-error` | `red.50` | Hover em elemento com estado de erro | |
| `color.state.pressed-accent` | `blizzard.700` | Pressed em botão de ação | |
| `color.state.focus-ring` | `blizzard.200` | `blizzard.400` | Anel de foco padrão (todos os elementos interativos) |
| `color.state.focus-ring-error` | `pink.200` | Anel de foco em campo com erro | |
| `color.state.disabled-surface` | `midnight.50` | `midnight.800` | Fundo de elemento desabilitado |
| `color.state.disabled-content` | `midnight.300` | `midnight.600` | Texto/ícone de elemento desabilitado |
css
--color-state-hover-neutral: var(--primitive-midnight-100);
--color-state-hover-accent: var(--primitive-blizzard-100);
--color-state-hover-error: var(--primitive-red-50);
--color-state-pressed-accent: var(--primitive-blizzard-700);
--color-state-focus-ring: var(--primitive-blizzard-200);
--color-state-focus-ring-error: var(--primitive-pink-200);
--color-state-disabled-surface: var(--primitive-midnight-50);
--color-state-disabled-content: var(--primitive-midnight-300);Boas práticas States
state.focus-ringé obrigatório em todos os elementos interativos nunca remover o outline de focostate.focus-ring-errorsubstitui o ring padrão quando o campo está em estado de errostate.hover-neutralé o hover padrão para qualquer elemento de lista ou tabela não usarsurface.raisedpara hover- O par
disabled-surface + disabled-contenté sempre usado junto nunca desabilitar apenas cor de texto
Categoria: Brand
Papel: Tokens institucionais de marca. Para uso em peças de comunicação, onboarding, páginas de marketing nunca em UI funcional operacional.
| Token | Valor | Uso |
|---|---|---|
| `color.brand.midnight` | `midnight.900` | Cor primária de marca fundos, logotipo |
| `color.brand.blizzard` | `blizzard.200` | Cor de acento de marca highlights, gradientes |
| `color.brand.gulf` | `gulf.800` | Cor institucional secundária |
| `color.brand.merino` | `merino.100` | Cor de fundo editorial da marca |
css
--color-brand-midnight: var(--primitive-midnight-900);
--color-brand-blizzard: var(--primitive-blizzard-200);
--color-brand-gulf: var(--primitive-gulf-800);
--color-brand-merino: var(--primitive-merino-100);Regras Globais do Sistema
Hierarquia de camadas
Primitivos → vocabulário bruto (nunca no produto)
Semânticos → intenção (único nível permitido em componentes)
Estados → interatividade transiente (hover, focus, disabled)
Dark Mode → inversão semântica (mesmos tokens, primitivos remapeados)Acessibilidade pares WCAG validados
| Par | Ratio | Nível | Restrição |
|---|---|---|---|
| `content.primary` / `surface.base` | 19.2:1 | AAA ✓ | |
| `content.secondary` / `surface.base` | 7.2:1 | AAA ✓ | |
| `content.tertiary` / `surface.base` | 4.1:1 | AA ✓ | Uso restrito a texto auxiliar |
| `content.disabled` / `surface.base` | 2.4:1 | reprovado | Intencional sinaliza indisponibilidade |
| `action.primary` / `surface.base` | 4.6:1 | AA ✓ | |
| `feedback.error` / `surface.base` | 5.9:1 | AA ✓ | |
| `feedback.success` / `surface.base` | 5.1:1 | AA ✓ | |
| `feedback.warning` / `surface.base` | 3.8:1 | AA* | **Sempre com ícone** |
| `feedback.badge` / `surface.base` | 5.4:1 | AA ✓ | |
| `feedback.premium` / `surface.base` | 3.2:1 | AA* | **Sempre com ícone** |
Regra crítica
feedback.warning e feedback.premium não passam WCAG AA em texto solo. Qualquer uso desses tokens em conteúdo textual exige acompanhamento de ícone ou rótulo visível que identifique o estado independentemente da cor. Dark Mode lógica de inversão
O dark mode não é uma inversão simples de cor. Cada token é remapeado individualmente para manter contraste e hierarquia:
- Superfícies invertem a escala Midnight (0→900, 50→800, etc.)
- Conteúdo inverte a hierarquia (900→50, 600→200, 500→300)
- CTAs e feedback sobem um stop na escala para compensar o fundo escuro (
blizzard.500→blizzard.400) - Superfícies de feedback caem para os stops mais escuros (100→900) para não criar ruído luminoso
css
[data-theme="dark"],
@media (prefers-color-scheme: dark) {
:root {
--color-surface-base: var(--primitive-midnight-900);
--color-surface-subtle: var(--primitive-midnight-800);
--color-surface-raised: var(--primitive-midnight-700);
--color-surface-overlay: var(--primitive-midnight-600);
--color-surface-inverted: var(--primitive-midnight-0);
--color-surface-warm: var(--primitive-midnight-800);
--color-content-primary: var(--primitive-midnight-50);
--color-content-secondary: var(--primitive-midnight-200);
--color-content-tertiary: var(--primitive-midnight-300);
--color-content-disabled: var(--primitive-midnight-600);
--color-content-inverted: var(--primitive-midnight-900);
--color-content-accent: var(--primitive-blizzard-400);
--color-border-default: var(--primitive-midnight-700);
--color-border-strong: var(--primitive-midnight-600);
--color-border-accent: var(--primitive-blizzard-400);
--color-border-error: var(--primitive-red-400);
--color-action-primary: var(--primitive-blizzard-400);
--color-action-hover: var(--primitive-blizzard-300);
--color-action-pressed: var(--primitive-blizzard-500);
--color-action-subtle: var(--primitive-blizzard-800);
--color-action-surface: var(--primitive-blizzard-900);
--color-action-disabled: var(--primitive-midnight-700);
--color-feedback-error: var(--primitive-red-400);
--color-feedback-error-surface: var(--primitive-red-900);
--color-feedback-error-content: var(--primitive-red-200);
--color-feedback-success: var(--primitive-green-400);
--color-feedback-success-surface: var(--primitive-green-900);
--color-feedback-success-content: var(--primitive-green-200);
--color-feedback-warning: var(--primitive-yellow-400);
--color-feedback-warning-surface: var(--primitive-yellow-900);
--color-feedback-warning-content: var(--primitive-yellow-200);
--color-feedback-premium: var(--primitive-orange-400);
--color-feedback-premium-surface: var(--primitive-orange-900);
--color-feedback-premium-content: var(--primitive-orange-200);
--color-feedback-badge: var(--primitive-pink-400);
--color-feedback-badge-surface: var(--primitive-pink-900);
--color-feedback-badge-content: var(--primitive-pink-200);
--color-state-hover-neutral: var(--primitive-midnight-800);
--color-state-hover-accent: var(--primitive-blizzard-900);
--color-state-focus-ring: var(--primitive-blizzard-400);
--color-state-disabled-surface: var(--primitive-midnight-800);
--color-state-disabled-content: var(--primitive-midnight-600);
}
}O que nunca fazer
| Proibido | Alternativa correta |
|---|---|
| Usar hex direto no componente (`#0092BE`) | Usar `color.action.primary` |
| Usar token primitivo no componente (`--primitive-blizzard-500`) | Usar `color.action.primary` |
| Usar `feedback.warning` ou `feedback.premium` em texto sem ícone | Adicionar ícone ou usar o token `-content` com `-surface` |
| Usar `content.disabled` intencionalmente para texto legível | `content.tertiary` como mínimo para texto lido |
| Usar `brand.*` em UI operacional | Usar os tokens funcionais equivalentes |
| Criar estado de hover com valor arbitrário | Usar `state.hover-neutral` ou `state.hover-accent` |
| Usar `feedback.error` como cor de destaque decorativo | Reservado para estados negativos reais |
| Remover o `state.focus-ring` de elementos interativos | Obrigatório para acessibilidade de teclado |
Integração com Dimensão 02 Tipografia
| Token tipográfico | Token de cor recomendado | Contexto |
|---|---|---|
| `type.display.*` | `color.content.primary` | Título de alto impacto |
| `type.heading.*` | `color.content.primary` | Título de seção, modal, card |
| `type.body.md/lg` | `color.content.secondary` | Texto corrido, descrições |
| `type.body.sm/xs` | `color.content.secondary` | Texto de suporte, disclaimers |
| `type.label.*` | `color.content.tertiary` | Labels, metadados, tags |
| `type.label.*` | `color.content.primary` | Label ativo ou selecionado |
| `type.code.*` | `color.content.primary` | Dado técnico em destaque |
| qualquer tipo | `color.content.accent` | Link, ação textual, chamada de atenção |
| qualquer tipo | `color.feedback.error-content` | Mensagem de validação de erro |
| qualquer tipo | `color.feedback.warning-content` | Mensagem de aviso (sobre surface de aviso) |
Decisões Estratégicas Registradas
Estas decisões foram tomadas, discutidas e validadas. Nenhuma pode ser revertida sem discussão explícita.
Escalas LCH em vez de HSL
As 9 famílias foram construídas em espaço LCH (Lightness–Chroma–Hue), não HSL. O motivo é perceptual: escalas HSL têm brilho percebido inconsistente entre stops o que parece "meio claro" em azul parece "muito escuro" em amarelo. LCH garante que cada stop parece visualmente equidistante em qualquer família.
Dois amarelos âncora 400 e 500 hue fixo
O amarelo tem o problema mais crítico de contraste em WCAG: o stop de melhor saturação (400, #ECCE24) reprova como texto, e o stop que passa AA (500, #B09707) é mais escuro e menos vibrante. O sistema mantém os dois stops âncora com hue fixo em 93.6°, e documenta explicitamente que warning nunca aparece solo em texto.
Blizzard Blue como único CTA Gulf Blue apenas institucional
O BrandBook Effecti tem dois azuis: Blizzard (claro, vibrante) e Gulf (escuro, institucional). A decisão foi segmentar: Blizzard é o CTA e acento de UI, Gulf é restrito a brand e institucional. Misturar os dois azuis em UI cria ambiguidade semântica o usuário não sabe o que é clicável.
Dark Mode por data-attribute com fallback em prefers-color-scheme
O dark mode é ativado por [data-theme="dark"] com fallback automático em @media (prefers-color-scheme: dark). Esta arquitetura permite que o produto respeite a preferência do sistema mas ofereça override manual padrão esperado em produtos B2B.
content.disabled reprova WCAG intencionalmente
O token de conteúdo desabilitado (ratio 2.4:1) não passa AA. Essa falha é intencional: um elemento desabilitado deve ser visivelmente inacessível o baixo contraste comunica que ele não pode ser usado. A WCAG excepciona explicitamente componentes desabilitados do critério de contraste (1.4.3).
Merino Beige fora da paleta operacional
A família Merino é restrita a surface.warm, brand.merino e peças institucionais. Em UI operacional, o quente compete com os sinais de feedback (warning/premium) e dilui a hierarquia semântica.
Exemplos de Uso
Card de pregão — tokens em combinação
surface · content · border · action · feedback em conjunto
Pregão Eletrônico · 0045/2026Habilitado
Fornecimento de material de escritório para a administração pública federal
UASG 153042 · Ministério da Educação
Valor estimado
R$ 284.750,00
Estados de feedback — os 5 tipos
color.feedback.* — erro · sucesso · aviso · premium · badge
Prazo encerrado — documentação inválida
Fornecedor habilitado com sucesso
⚠ Prazo de habilitação encerra em 2 dias
Recurso disponível no plano Premium
3 novas notificações não lidas
Hierarquia de superfícies
color.surface.* — base → subtle → raised → inverted → warm
color.surface.basecolor.surface.subtlecolor.surface.raisedcolor.surface.invertedcolor.surface.warmEstados de input
border · feedback.error · state.focus-ring — aplicados em campos
00.000.000/0001-00
12.345.678/0001-90
12.345.678/000X-90
CNPJ inválido — verifique os dígitos
Arquivos de Output Dimensão 01
| Arquivo | Formato | Conteúdo |
|---|---|---|
| `effecti_tokens_color.css` | CSS | Custom Properties primitivos + semânticos + dark mode |
| `effecti_tokens_color.dart` | Dart | `EffectiPrimitives`, `EffectiColors`, `EffectiColorsDark` |
| `effecti_color_palette_v1.svg` | SVG | Visualização das 9 famílias para validação no Figma |
Effecti Programa de Governança de Design System · Dimensão 01 · v1.0