Comece aqui

Marca e Design System

Uma luz só, e ela é âmbar.

Tokens, fundações, componentes e diretrizes para que tudo que a Sunny publica pareça vir da mesma empresa: site, landings de produto, Sunshine, slides, propostas comerciais e posts.

/

Este guia não substitui as fontes da verdade: ele organiza e aponta para elas. Os valores exatos vivem em tokens/tokens.json; o logo, a paleta e as fontes originais vivem no Drive. Ver Fontes da verdade.

O que é

A marca vigente é a V4 NewBrand26, no ar desde 17 de março de 2026. Ela tem quatro camadas, e cada uma tem um lugar só.

Tokens

Os valores: cor, tipo, espaçamento, radius, sombra. Vivem em tokens/ em três camadas: primitivo, semântico e de componente.

Fundações

As regras de uso de cada valor: cores, tipografia, espaçamento, radius, elevação e logo.

Componentes

Button, badge, card, input e nav item, com variantes, estados, anatomia e acessibilidade.

Padrões e governança

Acessibilidade, voz, como contribuir, versionamento e quem procurar. Decisões ficam em registro append-only.

O que não cobre

  • UI interna dos produtos. Cada produto tem seu design system de componentes e consome os tokens daqui. O brand define a linguagem, não o componente de tabela.
  • Copy de produto e conteúdo de marketing. A voz dá o tom, não o texto.
  • Ícones customizados e ilustração. Ainda sem padrão. Ver decisões pendentes.

Navegação rápida

!

Não use #FFDE59, Plus Jakarta Sans ou "inglês-first" como atributos atuais. São da V3, que saiu do ar em 17/03/2026. As explorações Convergence, Aurora e Radiance, de fevereiro de 2026, não foram adotadas e não valem como referência.

Comece aqui

Princípios

Quatro ideias que desempatam qualquer dúvida de marca. Quando duas regras parecerem entrar em conflito, decida por estas, nesta ordem.

Dark é a fundação, não um tema

Tudo nasce sobre bg.base. O claro existe para papel, slide e e-mail. Por isso este guia abre no escuro e o tema claro é um botão, não o padrão.

Uma luz só

O âmbar é a única cor de destaque. Se dois elementos na mesma tela pedem âmbar, um deles não merece.

Semântico antes de valor

Sempre text.accent, nunca #FFB61F. É o que faz tema, ajuste de marca e acessibilidade funcionarem de uma vez.

Acessível por padrão

WCAG 2.1 AA é critério de entrada, não polimento. Par de cor que falha não entra no token, componente sem foco visível não entra no índice.

As três camadas

A regra que sustenta o princípio 3. Código e Figma usam semânticos e de componente. Primitivo direto só dentro do arquivo de tokens. É o que permite trocar o tema, ou ajustar o âmbar, em um lugar só.

primitivo    color.amber.500      = #FFB61F
semântico    color.accent.default = {color.amber.500}
componente   button.primary.bg    = {color.accent.default}

Em CSS, var(--sunny-button-primary-bg) resolve para var(--sunny-color-accent-default), que resolve para var(--sunny-color-amber-500).

Status honesto em cada token

Todo token carrega $extensions.sunny.status. Este guia repete o selo em cada valor, porque saber de onde veio o número muda o que você pode fazer com ele.

SeloO que significaO que você pode fazer
medidoLido do código do site ou dos arquivos oficiais do DriveUsar sem pensar
derivadoCalculado a partir de valores medidosUsar, e avisar se ficar estranho na tela
propostaNão existe no site aindaNão usar em produção sem abrir uma decisão

Comece aqui

Por onde começar

O caminho mais curto entre a sua dúvida e a resposta, por perfil.

Dev
  • Precisa de cor, espaçamento ou fonte: use a variável de tokens/tokens.css. Os nomes antigos do site continuam funcionando pelo bloco de compatibilidade.
  • Vai montar botão, badge, card, input ou nav item: siga a página do componente.
  • Vai mostrar comando, ID ou log: type.code, fonte mono.
Marketing e vendas
  • Logo: regras e versões. Arquivos no Drive, pasta _Sunny-NewBrand26.
  • Slides e propostas: fundo bg.base, títulos em Bricolage Grotesque, corpo em Inter, âmbar só em destaque.
  • Texto: voz. Direto, técnico, brasileiro, sem travessão.
Produto e design
  • Tela nova: comece pelos semânticos e pelos componentes existentes. Cor de estado é status.*, nunca âmbar.
  • Cor, fonte ou componente novo: abra uma decisão antes de desenhar.
Todos
  • "Existe X?": este guia, depois o repositório do site.
  • "Quem decide?": quem procurar.
  • "Isso ainda vale?": confira o selo do token e a maturidade do componente.

Consumir os tokens

O site importa o tokens.css desde 15/09/2026 e ainda usa os nomes antigos pelo bloco de compatibilidade. O plano de adoção está em versionamento.

# regenera o tokens.css a partir do tokens.json
$ node tokens/build.mjs

# falha se um par obrigatório não atinge WCAG AA
$ node tokens/check-contrast.mjs
✓ 14 pares verificados, 0 falhas

Sem dependências. Node 18 ou mais recente.

Fundações

Cores

Um âmbar, uma escala de neutros e quatro estados. Nada além disso. Os hex desta página são lidos do tokens.css em tempo de carregamento, então não têm como divergir da fonte.

Âmbar, a cor da marca

Como ler a escala: 50 a 200 são brilhos e fundos claros; 300 a 500 são os tons de marca; 600 a 900 são estados pressionados, texto e contraste.

amber.50medido
amber.100medido
amber.200medido
amber.300medido
amber.400medido
amber.500medido
amber.600medido
amber.700medido
amber.800derivado
amber.900medido
TokenUso
amber.300Amarelo claro oficial. Texto de destaque suave
amber.400Amarelo oficial. Hover do botão primário, severidade média
amber.500Âmbar oficial. CTAs, destaques, foco, símbolo do logo
amber.800Único âmbar aprovado como texto sobre branco. Entra automaticamente no tema claro
amber.900Escuro oficial. Texto sobre âmbar

Neutros

neutral.0medido
neutral.50medido
neutral.100medido
neutral.200derivado
neutral.300medido
neutral.400medido
neutral.500medido
neutral.600medido
neutral.700medido
neutral.800medido
neutral.900medido
neutral.950medido
TokenUso
neutral.100Texto principal sobre escuro
neutral.300"SYSTEMS" no wordmark
neutral.400Texto secundário
neutral.500Só decorativo. Não passa AA como texto sobre escuro
neutral.600"SUNNY" no wordmark, bordas fortes, texto secundário no claro
neutral.800Card sobre escuro
neutral.900Fundo principal
neutral.950Fundo de terminal
!

Card (neutral.800) sobre fundo (neutral.900) tem contraste de 1.1:1. A separação de superfície depende da borda border.subtle, não da cor. Ela não pode ser removida. Um ajuste do 800 está nas pendências.

Feedback

Três tons por estado: 300 para texto sobre escuro, 500 para ícone e borda, 700 para texto sobre claro. O 500 de cada estado é medido; os 300 e 700 são derivados e precisam de validação visual.

Estado300 texto sobre escuro500 ícone e borda700 texto sobre claroDe onde veio
error Formulários de lead e --sev-crit
success --sev-ok e "copiado" no DevXOS
warning --sev-high e topologia do RootPilot
info --sev-low
/

Por que warning é laranja e não âmbar. O âmbar é a cor da marca e aparece em todo CTA. Se aviso também fosse âmbar, um alerta de custo no Sunshine pareceria um botão. O laranja já é a severidade alta no ScopeWard, então não é cor nova.

Aliases de severidade

Para ScopeWard e RootPilot: severity.critical → error.500, severity.high → warning.500, severity.medium → amber.400, severity.low → info.500, severity.ok → success.500.

Semânticos

Estes são os nomes que você escreve no código. Eles mudam sozinhos quando o tema muda.

TokenAponta paraUso
bg.baseneutral.900Fundo da página
bg.cardneutral.800Cards
bg.elevatedneutral.700Popovers, superfícies sobre card
bg.terminalneutral.950Mockups de terminal
bg.headeralpha.ink-92Header ao rolar, com blur
text.primaryneutral.100Texto corrido e títulos
text.secondaryneutral.400Descrições, legendas
text.accentamber.500Destaque em âmbar
text.accent-softamber.300Destaque suave
text.on-accentamber.900Texto sobre botão e badge sólido
border.subtlealpha.white-4Borda de card em repouso
border.defaultalpha.white-8Borda de card em hover, inputs
border.strongneutral.600Seletor de idioma
accent.defaultamber.500CTAs
accent.hoveramber.400Hover
accent.activeamber.600Pressionado
accent.softalpha.amber-10Fundo de badge
accent.glowalpha.amber-7Glow do hero
focus.ringamber.500Outline 2px, offset 2px

Tema claro

O escuro é a fundação. O claro existe para documentos, slides e e-mail, e entra com <html data-theme="light">. Use o botão Tema claro no topo desta página para ver a troca acontecer nos exemplos.

TokenEscuroClaro
bg.baseneutral.900neutral.0
bg.cardneutral.800neutral.50
text.primaryneutral.100neutral.900
text.secondaryneutral.400neutral.600
text.accentamber.500amber.800
status.*.textfeedback.*.300feedback.*.700

A troca de text.accent para amber.800 no claro é obrigatória: âmbar 500 sobre branco tem 1.8:1 e não serve para texto. Ver acessibilidade.

Transparências

TokenValorUso
alpha.white-4rgba(255,255,255,0.04)Borda de card
alpha.white-8rgba(255,255,255,0.08)Borda em hover
alpha.amber-7rgba(255,182,31,0.07)Glow radial do hero
alpha.amber-10rgba(255,182,31,0.10)Fundo de badge
alpha.amber-15rgba(255,182,31,0.15)Linha divisória, drop-shadow da ilustração
alpha.amber-30rgba(255,182,31,0.30)Glow forte
alpha.ink-92rgba(26,26,29,0.92)Header ao rolar

Faça e evite

Faça

  • Use text.accent para âmbar em texto. Ele muda de tom sozinho no tema claro.
  • Use status.* para estado. Nunca âmbar para erro ou sucesso.
  • Use border.subtle para separar card de fundo.

Evite

  • Hex direto no CSS ou no Figma. Sempre variável.
  • Âmbar 500 como texto sobre branco, ou branco como texto sobre âmbar.
  • neutral.500 e neutral.600 como texto sobre escuro.
  • Criar um quinto tom de amarelo. A história da marca já teve quatro.

Pendências

  • Validar visualmente os tons 300 e 700 de feedback.
  • Decidir se bg.card sobe para algo como #1F2426, para separar de bg.base sem depender de borda.
  • O site importa o tokens.css desde 15/09/2026, mas ainda usa os nomes antigos e tem hex escritos direto no CSS. Ver o passo 3 em versionamento.

Fundações

Tipografia

Três famílias, cada uma com um trabalho. Bricolage Grotesque tem personalidade e fica melhor grande. Inter é neutra e segura o corpo. JetBrains Mono é para qualquer coisa que o leitor possa copiar.

Famílias

PapelFamíliaPesosCarregamento
Display, títulos, wordmarkBricolage Grotesque400, 500, 700Google Fonts, eixo opsz 12 a 96
Corpo, UI, navegaçãoInter400, 500, 600, 700Google Fonts
Código, comandos, IDs, logsJetBrains Mono400, 500, 600Google Fonts

Import único, como o site faz hoje:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" />

Fallbacks: sans-serif para as duas primeiras, ui-monospace, monospace para a mono. Os arquivos .ttf e .otf estão em Fonts/ na pasta _Sunny-NewBrand26 do Drive, para slides e documentos offline.

Estilos semânticos

Use estes, não os primitivos. Cada um vira um conjunto de variáveis --sunny-type-<nome>-<propriedade>. A amostra à direita é renderizada com o próprio token.

displayfluid-display · 700 · 1.08
Do produto à operação
heading-1fluid-lg · 700 · 1.2
Título de produto
heading-2fluid-md · 700 · 1.2
Título de CTA
heading-3fluid-sm · 700 · 1.2
Título de seção
heading-422px · 600 · 1.2
Título de bloco
heading-520px · 600 · 1.2
Título de card
body-lg18px · 400 · 1.75
Lead e descrição do hero
body16px · 400 · 1.6
Corpo padrão de texto
body-sm15px · 400 · 1.6
Botões e texto denso
label14px · 500 · 1.6
Navegação e rótulo de campo
caption13px · 400 · 1.6
Legenda e metadado
overline12px · 600 · 0.08em
Solution Provider
code14px · 400 · mono
rootpilot query --since 24h

Exemplo de uso:

.hero h1 {
  font-family: var(--sunny-type-display-family);
  font-size: var(--sunny-type-display-size);
  font-weight: var(--sunny-type-display-weight);
  line-height: var(--sunny-type-display-line-height);
  letter-spacing: var(--sunny-type-display-letter-spacing);
}

Primitivos

Tamanhos em rem sobre raiz de 16px. Os títulos são fluidos com clamp e não trocam por breakpoint.

TokenValorOnde aparece no site
size.120.75remBadge, cookie, rodapé
size.130.8125remBotão pequeno do header, legendas
size.140.875remNavegação, labels
size.150.9375remBotões
size.161remCorpo
size.181.125remDescrição do hero
size.201.25remTítulo de card
size.221.375remTítulo de bloco
size.fluid-smclamp(1.75rem, 3vw, 2.5rem)Título de seção
size.fluid-mdclamp(2rem, 4vw, 3.25rem)Título de CTA
size.fluid-lgclamp(2.25rem, 4vw, 3.5rem)Título de produto
size.fluid-displayclamp(2.75rem, 5.5vw, 4.25rem)h1 do hero

Entrelinha e espaçamento de letras

Entrelinha

tight 1.08 display · snug 1.2 títulos · normal 1.6 corpo · relaxed 1.75 descrições longas

Espaçamento de letras

tight -0.02em display · snug -0.01em títulos · wide 0.08em overline e badge · wider 0.14em rótulos em caixa alta

Slides e documentos

A escala da doc anterior do site (display 40px, h1 28px, body 12px, caption 9px) era para slides de 16:9 e continua válida só nesse contexto. Em web, use a tabela acima. Em slides: display e títulos em Bricolage Grotesque, corpo em Inter, nunca abaixo de 11px.

Faça e evite

Faça

  • Um display por página. Ele é o ponto de luz tipográfico.
  • Mono para qualquer texto copiável: comando, ID, trecho de log.
  • Mínimo de 16px para corpo em web.

Evite

  • Bricolage Grotesque em corpo de texto ou abaixo de 20px.
  • Mais de dois pesos na mesma tela além do display.
  • Caixa alta fora de overline e do wordmark.
  • Recriar o wordmark com texto. Use o arquivo do logo.

Fundações

Espaço, radius e elevação

Base de 4px, radius contido, e sombra só quando há profundidade real. Card em repouso não tem sombra: a separação é por borda.

Espaçamento

Base de 4px. O nome do token é o múltiplo. Toda medida de layout é múltiplo de 4; valores quebrados só em ajuste óptico de ícone, e com comentário.

space.14px
space.28px
space.312px
space.416px
space.624px
space.832px
space.1248px
space.1664px
space.section100px
TokenUso típico
space.1Gap mínimo, entre ícone e texto pequeno
space.2Gap padrão, padding de badge
space.3Padding de input, gap de linha
space.4Padding interno de card pequeno
space.6Padding de card, gap de grid
space.8Padding de card grande, gap de navegação
space.12Separação de blocos
space.16Gap do grid do hero
space.sectionPadding vertical de seção

O Omnibus da ClickBus usa base 8. A Sunny usa base 4 porque o site já é assim e porque 12px aparece muito em UI densa de produto. Os múltiplos de 8 continuam sendo os preferidos para layout.

Radius

A marca é contida: botão com 4px, card com 12px. Não usar 16px ou mais fora de pill.

radius.sm2px · tags, barras
radius.md4px · botões, inputs
radius.lg8px · painéis, código
radius.xl12px · cards
radius.full999px · badges, pills
!

Isso diferencia a V4 do Sunshine app, que usa arredondamento generoso. É uma decisão a revisitar quando o Sunshine adotar estes tokens.

Elevação

Duas famílias: glow em âmbar para destaque, elevation em preto para profundidade. Glow é raro: um por viewport, no elemento que merece o olhar.

shadow.glow-smDots de status, ícones ativos
shadow.glow-mdDestaque do hero
shadow.elevation-mdCards flutuantes, dropdowns
shadow.elevation-lgModais, mockups de tela

Glass

Receita única: fundo bg.header ou alpha.white-4, backdrop-filter: blur(var(--sunny-blur-card)), borda border.subtle. Texto sobre glass é sempre text.primary, nunca text.secondary, porque o fundo varia.

TokenValorUso
blur.header20pxHeader ao rolar, sobre bg.header
blur.card24pxCards translúcidos sobre glow

Ver o glass aplicado no componente Card.

Movimento

TokenValorUso
motion.duration.fast0.15sTransform em hover de botão
motion.duration.base0.2sCor, borda, opacidade
motion.duration.slow0.3sHeader, cards, revelações
motion.easing.defaulteaseTudo
×

Regra: particle network no hero, tilt 3D em cards, contadores animados, parallax e shimmer desligam sob prefers-reduced-motion: reduce, e todo efeito novo precisa da mesma cláusula.

!

Estado real em 14/10/2026: o site cumpre a regra quase toda desde o website#10. Uma regra global no style.css encurta animações e transições dos seis CSS, e cada efeito de effects.ts sai cedo. Faltam três efeitos em JavaScript sem guarda: o contador do gauge do ScopeWard e a rotação automática dos carrosséis do ScopeWard e do RootPilot.

Breakpoints

TokenValorO que muda
breakpoint.md768pxMenu vira mobile, grids viram uma coluna
breakpoint.lg1024pxGrids de quatro viram dois
breakpoint.container1200pxLargura máxima do conteúdo

Ícones

Têm página própria: Ícones. A proposta de Lucide em todos os produtos está na decisão 0008.

Fundações

Ícones

Proposta

Dois tipos de ícone. O de interface é Lucide, em 16, 20 ou 24px, com a cor herdada de currentColor. O de marca é o sol, nas três versões de ícone.

?

Depende da decisão 0008. Até ela ser aceita, este é o conjunto para site, landing e chrome, e os produtos seguem como estão. Hoje o site usa SVG inline desenhado à mão, sem biblioteca, e o Sunshine app usa Lucide.

Tamanhos

16px · denso
20px · padrão
24px · destaque

Traço 1.5px, pontas e junções arredondadas, fill: none. O Lucide vem com traço 2px: passe 1.5 explicitamente. Acima de 128px, ícone de conceito vira ilustração, e Lucide não vai para o hero.

Marca

Icon Color
Icon Color · escuro
Icon Positive
Icon Positive · claro
Icon Negative
Icon Negative · escuro
Icon Negative sobre âmbar
Icon Negative · âmbar

O sol não ganha versão em traço e não entra na galeria de interface.

Interface

menu
search
x
check
plus
list-filter

Ação

download
copy
share-2
pencil

Status

A cor vem de color.status.*.icon. Nunca âmbar para erro, aviso ou sucesso.

circle-check
triangle-alert
circle-x
info

Produto

activity
terminal
shield
cloud
lock

É o recorte usado no guia, com o nome de cada ícone no Lucide. Precisou de outro, use o do Lucide com as mesmas regras.

Faça e evite

Faça

  • Um traço só, 1.5px, com pontas arredondadas e cor herdada.
  • Ícone sem texto com aria-label no controle. Ícone ao lado de texto com aria-hidden="true".
  • Status na cor semântica, não no âmbar.

Evite

  • Baixar pacote de ícones de outro cliente ou de banco de imagens.
  • Juntar dois ícones para inventar um terceiro.
  • Rotacionar, preencher, esticar ou gerar com IA.

Fundações

Assets digitais

Proposta

Favicon, avatar e ícone de canal usam só o sol, porque o nome já está no contexto da aba ou do perfil. O Open Graph usa o lockup horizontal, porque o card de um link não carrega o nome sozinho.

Favicon 32Icon Color sobre bg.base. No ar como favicon-32.png. Abaixo de 22px de altura, nunca o horizontal.
Avatar socialIcon Color sobre bg.base, sem wordmark. Quadrado com cantos suaves. Se a plataforma corta em círculo, o sol cabe inteiro nele.
Open Graph 1200×630Logo Hor White sobre bg.base. O do site tem acentos errados e precisa ser gerado de novo.
Capa do canal da Sunny Systems no YouTube: logo à esquerda e foto de um rosto à direita
Capa do YouTube16:9, Logo Hor White sobre foto escura. A atual tem 2903×1633; o YouTube recomenda 2560×1440, com área segura de 1546×423. Ícone do canal: Icon Color.
!

Não gerar favicon, Open Graph, avatar ou capa com IA. Todo arquivo parte de assets/v4/. Sobre âmbar, Icon Negative ou Positive, nunca Color.

Depende da decisão 0009. O arquivo-fonte da capa do YouTube não foi localizado no Drive.

Componentes

Índice e maturidade

O que existe, onde está implementado e o quanto dá para confiar. Estes são os componentes da camada de marca: o que aparece em site, landings, slides e no chrome dos produtos. Componente interno de produto fica no produto.

ComponenteCategoriaMaturidadeImplementado emTokens
ButtonAtomStableSite, cinco landingsbutton.*
BadgeAtomStableSite, cinco landingsbadge.*
CardMoleculeStableSite, cinco landingscard.*
InputAtomBetaLandings RootPilot e Soberaniainput.*
Nav itemAtomStableHeader do sitenav.*
HeaderOrganismStableSite, cinco landingsheader.*
StatMoleculeStableSite, cinco landingsSem token próprio
Terminal mockupMoleculeBetaScopeWard, DevXOS, Sunshineterminal.*
Toast, Alert, Modal, TabelaProposta sem códigocolor.status.*

Stable em produção com valores medidos. Beta implementado em um lugar, pode mudar. Proposta só documentado.

Regras comuns

  • Só tokens semânticos e de componente. Nenhum hex.
  • Todo estado interativo tem default, hover, focus-visible, active e disabled.
  • Foco é sempre focus.outline com focus.offset.
  • Alvo de toque mínimo de 44 por 44px em mobile.
  • Transições usam motion.duration.*; nada anima sob prefers-reduced-motion.
  • Texto vem de props ou i18n, nunca fixo no componente.

Critérios para entrar no índice

Variantes e estados

Default, hover, focus, active e disabled, todos desenhados.

Anatomia com medidas

Padding, gap, altura e radius em px, ligados a tokens.

Acessibilidade

Teclado, ARIA, contraste medido e alvo de toque.

Código

Implementado em pelo menos um produto, ou marcado como "sem código".

Detalhe completo em como contribuir.

Componentes · Atom

Button

Stable

Ação principal ou secundária. Um primário por bloco; o resto é secundário ou link. Implementado em website/src/style.css como .btn-primary e .btn-secondary.

Playground

button.*
Variante
Tamanho
Estado e layout
HTML
<button class="btn-primary" type="button">Falar com a Sunny</button>

Variantes

VarianteQuandoFundoTextoBorda
PrimaryA ação que queremos que aconteçabutton.primary.bgbutton.primary.fgnenhuma
SecondaryAção alternativa ao lado do primáriotransparentebutton.secondary.fg1.5px âmbar

Sem variante destrutiva na camada de marca. Produto que precisar usa color.status.error.* e documenta no próprio DS.

Estados

accent.default
accent.hover + translateY(-1px)
focus.outline 2px, offset 2px
accent.active, sem translate
opacidade 0.5 proposta
borda e texto accent.default
fundo âmbar, texto text.on-accent
focus.outline
opacidade 0.5 proposta
!

Disabled e active são proposta. O site não os define hoje. O que está na tela acima é o comportamento que este guia propõe, não o que existe em produção.

Tamanhos

TamanhoAltura aprox.PaddingFonte
Default48px14px 32pxbody-sm, 15px, 600
Small40px10px 24pxcaption, 13px, 600

Small só no header e em contextos densos. Alvo de 44px em mobile: o Default já cumpre; o Small precisa de padding extra abaixo de breakpoint.md.

Anatomia

32px 32px 48px

Altura: 48px default, 40px small  ·  Padding: 14px 32px  ·  Radius: radius.md, 4px  ·  Gap ícone e texto: space.2, 8px

  • Display inline-flex, align-items: center.
  • Radius radius.md. Não usar pill em botão.
  • Ícone, quando houver, 16px, à esquerda do texto, em currentColor.
  • Largura mínima natural. fullWidth só em mobile abaixo de breakpoint.md.
  • Transição: fundo em motion.duration.base, transform em motion.duration.fast.

Uso

<a class="btn-primary" href="#contato">Falar com a Sunny</a>
<a class="btn-secondary" href="#pilares">Conheça nossos pilares</a>
.btn-primary {
  background: var(--sunny-button-primary-bg);
  color: var(--sunny-button-primary-fg);
  padding: var(--sunny-button-padding-y) var(--sunny-button-padding-x);
  border-radius: var(--sunny-button-radius);
  font-size: var(--sunny-button-font-size);
  font-weight: var(--sunny-button-font-weight);
}
.btn-primary:hover { background: var(--sunny-button-primary-bg-hover); }

Acessibilidade

Teclado
TabMove o foco para o próximo botão
Shift + TabMove o foco para o anterior
EnterAtiva o botão focado
SpaceAtiva o botão focado
Semântica e ARIA
  • Navegação é <a>, ação na página é <button type="button">. Nunca div clicável.
  • Ícone sozinho exige aria-label.
  • aria-disabled="true" em vez de disabled quando o botão precisa continuar focável para explicar por que está inativo.

Contraste medido

ParContrasteMínimo
Texto sobre primary7.9:14.5passa
Texto sobre primary em hover8.6:14.5passa
Secondary sobre fundo9.9:14.5passa

Checklist

  • Texto diz o que acontece: "Falar com a Sunny", não "Enviar" ou "Clique aqui"
  • Indicador de foco visível, 2px âmbar com offset 2px
  • Ícone sempre acompanhado de texto ou aria-label
  • Estado disabled comunicado visualmente e via ARIA
  • Alvo mínimo de toque 44 por 44px em mobile
  • Responde a Enter e Space

Componentes · Atom

Badge

Stable

Rótulo curto acima de um título ou ao lado de um item: categoria, novidade, status neutro. Não é botão e não é filtro. Implementado como .badge.

Solution ProviderAccent, padrão
Ativostatus.success proposta
Degradadostatus.warning proposta
Fora do arstatus.error proposta
Em análisestatus.info proposta
×

A versão com fundo âmbar sólido e texto escuro, descrita na doc anterior do site, não está em uso e sai.

Anatomia

Solution Provider 16px 16px 6px ↕

Tipo: type.overline, Inter 600, 12px, caixa alta, letter-spacing 0.08em, line-height 1  ·  Padding: 6px 16px  ·  Radius: radius.full

  • Display inline-flex. Com ícone: 12px à esquerda, gap space.1.
  • Sem borda. Sem sombra. Sem hover: badge não é interativo.

Uso

<span class="badge">Solution Provider</span>
<span class="badge badge-success">Ativo</span>

Acessibilidade

  • Contraste medido: âmbar sobre badge sobre card, 9.4:1
  • Caixa alta é feita por CSS. O HTML fica em caixa normal, para o leitor de tela ler palavras e não letras
  • Status nunca só por cor: o texto diz o estado
  • Badge decorativo que repete o título recebe aria-hidden="true"

Componentes · Molecule

Card

Stable

Superfície que agrupa título, texto e, às vezes, uma ação sobre um mesmo assunto. Um card é um bloco de leitura, não um botão gigante. Implementado como .pillar-card, .service-card e .product-card.

Playground

card.*
Tipo
Superfície

Passe o mouse no card para ver o hover dos tipos interativos.

Observabilidade

O RootPilot lê métricas, logs e custos da sua stack e responde perguntas de engenharia em um só lugar.

HTML
<article class="pillar-card">
  <h3>Observabilidade</h3>
  <p>O RootPilot lê métricas, logs e custos…</p>
</article>

Tipos

TipoInteraçãoUso
EstáticoNenhumaPilares, serviços
Com açãoUm link ou botão dentroProduto com "Saiba mais"
Inteiramente clicável BetaO card todo é um <a>Lista de produtos no menu

Anatomia

  • Fundo card.bg. Borda card.border, 1px branco a 4%. Radius card.radius, 12px.
  • Padding card.padding, 32px, em .service-card e .product-card. Em mobile, space.6, 24px.
  • O .pillar-card usa 48px 32px, medido. Diverge do token e ainda não foi decidido se o token sobe ou se o card desce.
  • Ordem interna: ícone ou glifo 40px, título type.heading-5, texto type.body em text.secondary, ação.
  • Gap entre título e texto space.3; entre texto e ação space.6.
  • Sem sombra em repouso.
  • Faixa de acento de 3px no topo: existe, medida em 14/09/2026. O .pillar-card usa um dos três amarelos por posição; o .product-card usa --accent, injetado inline por produto. A documentação anterior afirmava que a faixa não existia, e estava errada.

Estados

EstadoMudança
DefaultBorda border.subtle
Hover, só nos clicáveistranslateY(-4px) e borda âmbar a 12% no .pillar-card, medido. A documentação anterior dizia -2px e branco 8%, e estava errada
Focus-visible, só nos clicáveisfocus.outline no card inteiro
Tilt 3DEfeito do site. Desliga com reduced motion e não é obrigatório

Glass

Sobre glow ou imagem, o card vira glass: fundo alpha.white-4, backdrop-filter: blur(var(--sunny-card-blur)), mesma borda. Texto sempre text.primary, porque o fundo varia. Ative o controle no playground acima para ver.

Grid

Quatro colunas em desktop, duas abaixo de breakpoint.lg, uma abaixo de breakpoint.md. Gap space.6. Cards da mesma linha têm a mesma altura.

Acessibilidade

  • Título do card é heading real, na hierarquia da página
  • Card inteiramente clicável é um único <a> com o título como texto principal. Nada interativo dentro dele
  • Contraste medido: texto principal sobre card 12.3:1, secundário sobre card 5.1:1
!

A separação entre card e fundo é 1.1:1 por cor. A borda é o único limite visual, então ela não pode ser removida.

Componentes · Atom

Input

Beta

Campo de texto de uma linha com rótulo acima e mensagem de erro abaixo. Implementado em sovereign.css e rootpilot.css como .lead-field. Único formulário do site: captação de lead.

Playground

input.*
Estado

O campo é real: clique nele para ver o foco de verdade, com a borda âmbar.

HTML
<div class="lead-field">
  <label for="email">E-mail corporativo</label>
  <input id="email" name="email" type="email"
         autocomplete="email" placeholder="voce@empresa.com.br" required />
</div>

Anatomia

ParteEspecificação
Rótuloinput.label: JetBrains Mono 600, 0.7rem, caixa alta, letter-spacing 0.12em, text.secondary. 6px acima do campo
CampoFundo input.bg, borda 1px border.default, radius radius.md, padding 12px 14px, texto branco 0.95rem em Inter
Placeholdertext.secondary com opacidade 0.65
Erroinput.error.fg, 12px, abaixo do campo, aparece só com .invalid
/

Dois valores medidos fogem da escala: padding horizontal 14px e fonte 0.95rem. Proposta: 16px e font.size.15. Muda quase nada na tela e alinha com o botão.

Estados

EstadoMudança
DefaultComo na anatomia
HoverFundo input.bg-hover, branco a 5.5%
FocusBorda accent.default, fundo input.bg-focus, âmbar a 4%. O site remove o outline nativo; a borda âmbar faz o papel de foco
InvalidBorda status.error.border, fundo status.error.bg, mensagem visível
Disabled propostaOpacidade 0.5, cursor: not-allowed

Variantes

Só texto de uma linha hoje: nome, e-mail, empresa, telefone. Textarea, select e checkbox são proposta. O checkbox de consentimento do formulário já existe como .lead-check, com foco visível por focus.outline na caixa.

Acessibilidade

  • <label for> sempre, mesmo com placeholder. Placeholder não é rótulo
  • autocomplete correto em cada campo: name, email, organization, tel
  • Inválido: aria-invalid="true" e aria-describedby apontando para a mensagem
  • A mensagem diz o que fazer, não só "inválido"
  • Erro nunca só por cor: a borda vermelha vem com texto
  • Foco: a borda âmbar dá 9.9:1 sobre o fundo e substitui o outline. Se o fundo mudar, voltar ao focus.outline

Contraste medido

ParContrasteSituação
Texto branco sobre campo17:1passa
Placeholder a 65% de neutral.400< 4.5:1Aceitável: placeholder não é conteúdo, o rótulo é
Rótulo mono 0.7rem11pxNo limite. Não reduzir mais

Componentes · Atom

Nav item

Stable

Link de navegação principal no header. Também cobre o seletor de idioma. Implementado como .nav a e .lang-toggle.

Exemplo

nav.*

"Produtos" está no estado ativo e "Serviços" no estado hover, forçados para a vitrine.

Anatomia

  • type.label: Inter 500, 14px. Cor nav.link.fg.
  • Gap entre itens nav.gap, 32px.
  • Sublinhado animado: pseudo-elemento de 2px em accent.default, 4px abaixo do texto, cresce de 0 a 100% da largura em motion.duration.base.

Estados

EstadoMudança
Defaulttext.primary, sublinhado 0
Hovernav.link.fg-hover, âmbar, sublinhado 100%
Focus-visiblefocus.outline
Ativo propostaSublinhado 100%, aria-current="page". O site não marca o ativo hoje

Seletor de idioma

Pill com borda border.strong, texto type.overline sem caixa alta forçada, ícone de globo 14px. Hover: borda e texto âmbar. É um <button> com aria-label dizendo o idioma de destino: "Switch to English" quando em pt-BR.

Mobile

Abaixo de breakpoint.md, o header vira um botão hambúrguer com aria-expanded e o menu abre em painel com bg.header e blur. Itens ficam em coluna, type.body-lg, com alvo de 44px.

Acessibilidade

  • <nav aria-label="Principal"> envolvendo a lista
  • Links são <a href> reais; troca de idioma é <button>
  • Contraste medido: link sobre header 13.0:1
  • Skip-link antes do header, visível ao receber foco, com fundo âmbar
!

A borda do seletor de idioma tem 1.5:1. É aceitável porque o botão tem texto. Não reutilizar essa borda como único limite de um controle sem texto.

Componentes · Organism

Header

Stable

Barra fixa do site. Logo à esquerda, navegação com o CTA, e à direita o seletor de idioma e, no mobile, o botão de menu. Transparente no topo, opaca e com blur depois de rolar.

Estado rolado

header.*
Sunny Systems

Anatomia

  • position: fixed no topo, z-index: 100. Padding vertical space.4 (16px), conteúdo em container de 1200px com space.6 (24px) nas laterais. Perto de 73px de altura, calculado.
  • Logo: Logo Hor White, 28px de altura, link para a home. No rodapé, 22px. Hoje é PNG; o SVG está em assets/v4/.
  • Navegação: itens de Nav item com nav.gap (32px). O CTA é .btn-primary compacto, padding 10px 24px e 0.813rem, dentro do <nav>.
  • Ações: seletor de idioma e, abaixo de 768px, o botão de menu, com gap space.4.

Estados

EstadoFundoBorda inferiorQuando
TopoTransparenteNenhumascrollY até 50px
Roladoheader.bg-scrolled + header.blurheader.border-bottom, âmbar 8%Acima de 50px, classe .scrolled
Menu abertoPainel em tela cheia, ink a 98% com blur 20pxMobile, aria-expanded="true"

Fundo e blur fazem transição em motion.duration.slow; a borda entra sem transição. O ink a 98% do painel mobile não tem token.

Mobile

Abaixo de breakpoint.md (768px), hambúrguer de três barras de 24×2px que vira X ao abrir. O painel ocupa a tela, com itens em coluna, gap de 32px e texto de 20px. Clicar em um link fecha o menu.

Acessibilidade

  • Skip-link "Pular para o conteúdo" antes do header, para #main-content. Desce para 16px do topo no foco, fundo amber.500, texto amber.900.
  • <header role="banner"> e <nav aria-label="Navegação principal">.
  • Logo com alt="Sunny Systems". O link da home ainda não tem aria-label; o padrão de Logo pede "Sunny Systems, página inicial".
  • O Logo Hor White passa sobre o header nos dois estados. O Hor Color some no escuro.
  • O CTA é o único botão primário da barra.
!

O botão de menu ainda não tem: aria-controls, fechar com Esc, levar o foco para o menu e devolver ao botão, travar a rolagem do fundo. São pendências, não opções.

Pendências

  • Trocar o PNG do logo pelo SVG.
  • Os atributos width do logo no HTML (180 e 140) não batem com a largura renderizada, perto de 107 e 84px.
  • A home não marca o item ativo da navegação com aria-current.
  • Confirmar no navegador se o backdrop-filter do estado rolado prende o painel mobile à altura do header.

Componentes · Molecule

Stat

Stable

Número de destaque com rótulo curto, em uma faixa âmbar. Um stat não é um gráfico: é um número que o leitor guarda.

59
checks de governança
7
eixos auditados
5 min
de MTTR típico em incidente

Vitrine com o rótulo já corrigido para text.on-accent sólido. O site usa amber.900 a 65% ou 70%, que falha AA. Ver Acessibilidade.

Anatomia

  • Faixa: color.amber.500 com gradiente animado até amber.600. Padding vertical de 80px, 60px no mobile.
  • Número: Bricolage Grotesque 700, line-height 1, text.on-accent.
  • Rótulo: Inter 500, space.2 abaixo do número.
HomeLandings
Númeroclamp(2.25rem, 4vw, 3.5rem)clamp(1.8rem, 3.5vw, 2.75rem), -0.02em
Rótulo14px, alpha 65%0.8rem, alpha 70%
LayoutFlex centralizado, gap space.16Grid de 4 colunas, gap space.8
Até 768pxUma coluna, gap 32pxDuas colunas, gap de 16 ou 24px conforme a landing

As landings não concordam entre si nos breakpoints. Alinhar é pendência.

Estados

Nenhum. O stat não é interativo. Na home e no RootPilot o número conta de 0 até o valor em 1,8s quando aparece na tela, uma vez só, e não conta sob prefers-reduced-motion: reduce.

Regras

  • Número com unidade e contexto: "5 min de MTTR típico em incidente", não "5". Nunca abreviar como "48.2k".
  • Faixa âmbar, texto escuro. Número e rótulo em text.on-accent.
  • A variante com número âmbar sobre fundo escuro não existe no código. Se for desejada, entra como proposta.

Acessibilidade

  • Número: 7.9:1 sobre amber.500 e 6.3:1 sobre amber.600. Passa.
  • Rótulo falha AA. A 65% dá 3.5:1 e 3.2:1; a 70%, 4.0:1 e 3.5:1. Texto de 13 a 14px pede 4.5:1. Correção: text.on-accent sólido.
  • O título da faixa da home está fixo em inglês, "The Sunny Facts", inclusive no aria-label. Deve vir do i18n.

Componentes · Molecule

Terminal mockup

Beta

Janela falsa que emoldura uma saída de terminal ou um relatório. Serve para dizer “isto é output real de ferramenta”, não para ser interativo: nenhum dos três dots faz nada.

$ scopeward audit
# 80 checks, 0 falhas
Neutra, padrão
$ sunshine report
# custo por nó, 30d
Quente medido
×

Os três dots não são as cores da janela do macOS. Eram, nas três landings, e o amarelo do macOS era um quinto amarelo na tela. Passaram a vir da paleta da marca na decisão 0007.

Os três dots

São posicionais, não semânticos: esquerda, meio e direita de um chrome de janela. Fecham nada, avisam nada, confirmam nada.

TokenValorVem de
terminal.dot-close#FF5D5Dcolor.feedback.error.500
terminal.dot-min#FFB61Fcolor.amber.500
terminal.dot-max#6FCF97color.feedback.success.500

Reusar as cores de feedback aqui não contraria a regra da decisão 0004 de que âmbar nunca significa estado. Essa regra vale para o que comunica estado ao usuário; o dot do meio não comunica nada. O proibido continua sendo o inverso — âmbar dizendo “atenção” numa mensagem real.

Anatomia

Barra: padding 11px space.4, borda inferior 1px branco 5%  ·  Dots: terminal.dot-size (11px), radius.full, gap 7px  ·  Corpo: JetBrains Mono 0.8rem (12,8px), line-height 1.75, padding space.6, medido no ScopeWard  ·  Janela: radius.lg, borda color.alpha.white-6, sombra shadow.elevation.lg

  • A variante quente não é decoração: terminal.bg-warm é um preto com âmbar dentro, e trocá-lo pelo neutro muda a página de forma perceptível (ΔE 5.2 no corpo, 7.6 na barra).
  • Use a neutra por padrão. A quente só onde o fundo da página já é quente — hoje, só o Sunshine.

Uso

<div class="term">
  <div class="term-bar" aria-hidden="true">
    <span class="term-dot"></span>
    <span class="term-dot"></span>
    <span class="term-dot"></span>
  </div>
  <pre class="term-body">$ scopeward audit</pre>
</div>

Acessibilidade

  • Os três dots são decorativos: aria-hidden="true" na barra. Um leitor de tela não deve anunciar “vermelho amarelo verde” antes do conteúdo
  • Contraste medido do texto primário sobre o corpo: 14.2:1 na neutra, 14.1:1 na quente. Os dois passam AAA
  • Barra e corpo se separam por 1.09:1 (neutra) e 1.04:1 (quente) — por isso a borda inferior da barra é obrigatória: é ela que dá o limite, não a diferença de fundo
  • O corpo é texto de verdade, nunca imagem de texto. Saída longa rola no corpo, não na janela

Padrões

Acessibilidade

WCAG 2.1 nível AA em tudo que a Sunny publica. Não é polimento: par de cor que falha não vira token, componente sem foco visível não entra no índice.

Contraste mínimo

NívelTexto normalTexto grandeComponentes e ícones
AA, obrigatório4.5:13:13:1
AAA, desejável em títulos7:14.5:1

Texto grande é 24px, ou 19px em bold.

Checagem automática

node tokens/check-contrast.mjs lê os tokens semânticos e falha o PR se um par obrigatório não atinge o mínimo. Resultado em setembro de 2026: todos passam.

ParContrasteMínimo
Texto principal sobre fundo13.0:14.5
Texto principal sobre card12.3:14.5
Texto secundário sobre fundo5.4:14.5
Texto secundário sobre card5.1:14.5
Texto âmbar sobre fundo9.9:14.5
Texto sobre botão primário7.9:14.5
Texto sobre botão primário em hover8.6:14.5
Badge sobre card9.4:14.5
Link sobre header13.0:14.5
Anel de foco sobre fundo9.9:13
Feedback: texto sobre fundo7.5 a 11.2:14.5
Feedback: ícone sobre fundo5.8 a 9.1:13
Tema claro: amber.800 sobre branco6.2:14.5
Tema claro: feedback 700 sobre branco5.0 a 6.3:14.5
!

O texto secundário sobre card está perto do limite, em 5.1:1. Qualquer clareamento do card ou escurecimento do cinza quebra o par.

Pares proibidos

Medidos e reprovados. Não usar como texto.

ParContraste
Âmbar 500 sobre branco1.8:1
Branco sobre âmbar 5001.8:1
Neutral 500 sobre fundo escuro2.6:1
Neutral 600 sobre fundo escuro1.5:1

Em fundo claro, âmbar em texto é sempre amber.800. Sobre botão âmbar, texto é sempre amber.900.

Limites conhecidos

  • Card sobre fundo tem 1.1:1. A borda border.subtle é o único limite visual e não pode ser removida.
  • Borda do seletor de idioma tem 1.5:1. Aceitável porque o botão tem texto. Não reutilizar em controle sem texto.
  • Placeholder de input fica abaixo de 4.5:1. Aceitável porque placeholder não é conteúdo; o rótulo é.

Checklist geral

Vale para qualquer página, slide exportado para web ou e-mail.

  • Contraste de texto e ícone conforme a tabela
  • Navegação completa por teclado, na ordem visual
  • Foco sempre visível: focus.outline 2px âmbar, offset 2px
  • Skip-link antes do header
  • Todo controle com rótulo; ícone sem texto com aria-label
  • Estado nunca só por cor: ícone ou texto junto
  • Formulário com label for, autocomplete, aria-invalid e aria-describedby
  • Imagem informativa com alt que descreve; decorativa com alt=""
  • Logo com alt="Sunny Systems"
  • <html lang> correto e atualizado ao trocar idioma
  • Um h1 por página, hierarquia sem pulos
  • prefers-reduced-motion desliga partículas, tilt, parallax, shimmer e contadores
  • Zoom a 200% sem perda de conteúdo
  • Reflow a 320px sem scroll horizontal
  • Alvo de toque de 44px em mobile
  • Vídeo e GIF de demo com descrição textual ao lado

Faça e evite

Faça

  • HTML semântico
  • <button> para ação e <a> para navegação
  • aria-expanded no menu mobile
  • aria-current="page" no item ativo
  • aria-live="polite" no retorno do formulário

Evite

  • div clicável
  • Esconder conteúdo só com opacidade
  • Comunicar erro só com borda vermelha
  • Animação sem alternativa
  • Texto em imagem sem equivalente em HTML

Padrões

Voz

Como a Sunny Systems escreve. Vale para site, landings, propostas, e-mails, posts e mensagens de produto.

Princípios

Direto

Vai ao ponto. Frases curtas. O leitor é ocupado.

Técnico mas acessível

Fala com CTO e com CFO na mesma frase. Sigla sempre com explicação na primeira vez.

Confiante sem arrogância

Mostra expertise com fato e número, não com superlativo.

Brasileiro

Português do Brasil natural. Sem tradução literal de inglês, sem "performar", sem "endereçar problema".

Idioma

pt-BR é o idioma primário. Inglês é a versão alternativa do site e de materiais para parceiros globais. Termos técnicos consagrados ficam em inglês: observability, FinOps, platform engineering, on-premises. Não traduzir "deploy" nem "pipeline". Traduzir "monitoring" para monitoramento e "cost" para custo.

Evite e prefira

EvitePrefira
Travessão em texto corridoDois-pontos, vírgula ou nova frase
"Soluções inovadoras"O que a solução faz, em verbo
"De ponta a ponta"Lista do que está incluso
"Somos os melhores""X% de economia em Y dias"
"Alavancar", "endereçar", "performar""Usar", "resolver", "rodar"
Voz passiva"Implementamos", "entregamos", "medimos"
Ponto de exclamaçãoPonto final
Emoji em texto institucionalNenhum

Exemplos

Ruim

"Oferecemos soluções inovadoras de ponta a ponta para modernização de infraestrutura."

Bom

"Migramos sua infraestrutura para a nuvem, do planejamento ao go-live, com foco em disponibilidade e custo."

Ruim

"Nossa plataforma alavanca IA para endereçar os desafios de observabilidade."

Bom

"O RootPilot lê métricas, logs e custos da sua stack e responde perguntas de engenharia em um só lugar."

Nomes

  • Sunny Systems, sempre com S maiúsculo nos dois, nunca "Sunny" sozinho em texto institucional. "Sunny" sozinho só em conversa informal e no wordmark.
  • Produtos: RootPilot, ScopeWard, DevXOS, Sunshine, Soberania de IA. Grafia fixa, sem espaço, sem hífen.
  • Tagline: "Seu parceiro estratégico em tecnologia, do produto à operação." Em inglês: "Your strategic partner in technology, from product to operations."

Microcopy de produto

  • Botão diz o que acontece: "Falar com a Sunny", não "Enviar"
  • Erro diz o que fazer: "Digite um e-mail válido", não "Campo inválido"
  • Estado vazio diz o próximo passo, em uma frase
  • Número sempre com unidade e período: "R$ 48,2 mil este mês", não "48.2k"

Governança

Como contribuir

Fluxo para mudar ou adicionar algo na marca: token, componente, regra ou asset. Sem SLA de revisão nem reunião fixa.

Fluxo

  1. Já existe? Procure neste guia e no tokens.json. Se existe, use como está. Não sobrescreva com estilo local.
  2. É ajuste ou é novidade? Ajuste de valor medido errado, texto ou exemplo: abra PR direto. Cor, fonte, componente, regra ou mudança visual grande: abra uma decisão primeiro, com contexto, opções e recomendação.
  3. Faça no token, não no CSS. Se a mudança é de valor, ela entra em tokens.json, roda o build e o check de contraste, e o tokens.css gerado vai junto no PR.
  4. PR para main com um approval de alguém com contexto de marca. Mudança visível para usuário avisa no PR o que muda na tela e onde.
  5. Registre. Mudança que altera decisão anterior ganha uma nova decisão, nunca edita a antiga.

Critérios de entrada

Token novo
  • Tem uso em pelo menos dois lugares, ou é semântico obrigatório para tema
  • Passa no check de contraste nos pares em que será usado
  • Tem status honesto: medido, derivado ou proposta
Componente novo
  • Variantes, estados, anatomia com medidas e API ou classes
  • Seção de acessibilidade: teclado, ARIA, contraste, alvo de toque
  • Só tokens semânticos ou de componente
  • Implementado em pelo menos um produto, ou marcado como "sem código"

Regra nova entra se resolve uma dúvida que apareceu de verdade. Regra preventiva vira ruído.

Checklist do PR

  • node tokens/build.mjs rodou e tokens.css está atualizado
  • node tokens/check-contrast.mjs passa
  • Nenhum hex novo fora de tokens.json
  • Texto em pt-BR, sem travessão em prosa
  • Se muda visual: screenshot ou link antes e depois
  • Se muda decisão: arquivo novo em decisoes/
  • CHANGELOG.md dos tokens atualizado, se tocou em token

O que fica fora deste repositório

  • Componentes internos de produto: tabelas, gráficos, drawers do Sunshine. Ficam no produto, consumindo tokens daqui.
  • Copy final de marketing.
  • Configuração de build dos sites.

Governança

Versionamento e adoção

O pacote tokens/ segue Semantic Versioning. A versão fica em tokens/CHANGELOG.md. Hoje: 0.2.0.

Semver dos tokens

NívelQuandoExemplo
MAJORToken removido ou renomeado, valor de marca trocado, tema padrão alteradoaccent.default deixa de ser amber.500
MINORToken novo, tema novo, alias novo, componente novocolor.status.* adicionado
PATCHCorreção de valor medido errado, doc, exemplo, comentáriospace.section de 96 para 100px

Mudança de status de um token, de proposta para medido, é PATCH se o valor não mudou e MINOR se mudou.

Maturidade

Stable

Em produção em pelo menos um produto, valores medidos.

Beta

Documentado e implementado em um lugar, pode mudar.

Proposta

Só documentado, sem código.

Deprecated

Sai na próxima MAJOR. O substituto está indicado.

Breaking change

Nunca sem alternativa. Token renomeado mantém o nome antigo como alias por uma MAJOR inteira, no bloco de compatibilidade do tokens.css. Mudança visual grande é avisada no PR antes de mergear, não só no changelog.

Plano de adoção pelo site

A migração é em três passos, sem big bang. Os passos 1 e 2 estão feitos desde o website#14, em 15/09/2026. O passo 3 está em andamento.

  1. Copiar (feito) o tokens.css para o site e importar antes do style.css. O bloco de compatibilidade garante que --color-amber, --space-lg e os demais nomes atuais continuem funcionando. Nada muda na tela.
  2. Remover (feito) os :root duplicados de style.css e dos seis CSS de produto. Os --sev-* do ScopeWard passam a vir do tokens.css.
  3. Trocar (em andamento) gradualmente os nomes antigos pelos semânticos novos, arquivo por arquivo, e apagar o bloco de compatibilidade na MAJOR seguinte.

Depois do passo 1, este repositório é a origem. O site consome uma versão fixa e atualiza por PR.

/

Esta página já está no passo 1: ela importa o tokens.css deste repositório e não define nenhum valor de cor próprio. Todo hex que você vê aqui é lido do arquivo em tempo de carregamento.

Sunshine e outros produtos

Mesmo caminho, com um passo extra: mapear os tokens OKLCH do Sunshine app para os semânticos daqui. O radius contido da V4 é a diferença mais visível e pede uma decisão antes da adoção.

Governança

Quem procurar

Direcione a dúvida por assunto. Assíncrono, por PR ou issue no repositório.

Dúvida sobreProcure
Decisão de marca, aprovação de mudança visual, prioridadeFabio Trentini, mantenedor do repositório
Tokens, build, contraste, adoção pelo site@sunnysystems/engineers
Arquivos de logo, fontes e paleta no DriveFabio Trentini
Voz e copyA definir
Design system do Sunshine appTime do Sunshine

Este quadro reflete setembro de 2026, quando há um mantenedor. Ao entrar mais gente, atualize aqui e no CODEOWNERS no mesmo PR.

Perguntas frequentes

Posso usar #FFB61F direto no CSS?

Não. Use var(--sunny-color-accent-default) ou o alias --color-amber. Hex direto quebra tema e auditoria.

Preciso de uma cor que não existe.

Abra uma decisão em docs/decisoes/ com o caso de uso. Quase sempre a resposta é um semântico novo apontando para um primitivo que já existe.

O site ainda não usa o tokens.css. Onde eu mudo uma cor hoje?

No tokens.json daqui, e depois espelha no style.css do site no mesmo dia. Depois da adoção, só aqui.

Qual logo uso em slide escuro?

Logo Hor White. Em slide claro, Logo Hor Color. Ver logo.

As propostas Convergence, Aurora e Radiance valem?

Não como referência. São explorações não adotadas, de fevereiro de 2026. Ver a decisão 0002.

Quero mostrar um comando de instalação.

type.code, JetBrains Mono, sobre bg.terminal.

Referência

Decisões

Registro append-only de decisões de marca. Uma decisão nunca é editada depois de aceita. Se muda, entra uma nova que substitui a anterior e aponta para ela.

Formato: NNNN-titulo-curto.md com as seções Status, Contexto, Decisão, Consequências e Alternativas. Status possíveis: Proposta, Aceita, Substituída por NNNN, Rejeitada.

NºTítuloStatus
0001Adoção da NewBrand26 como marca vigenteAceita
0002Destino das explorações de fevereiro de 2026Proposta
0003Tokens em três camadas como fonte da verdadeProposta
0004Cores de feedback e severidadeProposta
0005Cor de acento por produtoProposta
0006Posicionamento e site-betaProposta
0007Chrome do terminal e superfície escura quenteProposta
0008Lucide como biblioteca de íconesProposta
0009Assets digitais saem dos arquivos oficiaisProposta

O que está em aberto agora

0002 · Explorações de fevereiro

Convergence, Aurora e Radiance não foram adotadas. A recomendação é arquivar, com a porta aberta para trazer só o sistema de glow do Radiance como token de sombra.

0005 · Cor de acento por produto

Site em produção usa âmbar para tudo. Site-beta usa um dos três amarelos por página. Decks comerciais usam paletas próprias. O mesmo produto aparece com cor diferente dependendo de onde está.

0006 · Posicionamento

Existem duas taglines em código: a do site no ar e a do site-beta. Precisa de decisão do mantenedor antes de qualquer outra coisa.

0008 · Ícones

Lucide em todos os produtos, traço 1.5px. A decisão está escrita e espera aceite; até lá, a página de ícones é proposta.

0009 · Assets digitais

Favicon, avatar e ícone de canal com o sol, Open Graph com o lockup, nada gerado com IA. O avatar sai de pendência solta e vira regra proposta.

/

Decisão 0001, aceita de fato em 17/03/2026 e registrada só em 14/09/2026: a marca passou seis meses no ar sem constar no repositório. É por isso que a governança existe.

Referência

História da marca

Quatro identidades em cinco anos. Saber o que ficou para trás evita trazer de volta um amarelo aposentado.

2021

V1 — Identidade original

Logo "SUNNY☀SYSTEMS" com símbolo de sol de raios integrado entre as palavras. Space Grotesk e Tajawal. Amarelo #FFC700 com azul royal e cinzas. Mascote robô Sunny e grafismos de losangos em dissolução.

2023

V2 — Branding 2.0

O símbolo do sol foi isolado e ampliado, virando ícone independente. O amarelo evoluiu para #F8D347, mais quente. Paleta expandida para 12 cores em pares light e dark.

2024 a 2025

V3 — Site Framer

Dark premium em Framer. Plus Jakarta Sans e Geologica, amarelo #FFDE59 sobre #171E20, ilustração isométrica wireframe, inglês-first. Saiu do ar em 17/03/2026. Nada daqui vale como referência atual.

fev 2026

Explorações não adotadas

Convergence, Aurora e Radiance. Partiam de premissas que a marca lançada não seguiu: amarelo #FFDE59, hierarquia por opacidade de branco, arredondamento generoso, inglês-first. Ficam em docs/propostas/ como registro do processo.

março 2026 · vigente

V4 — NewBrand26

Sol em semicírculo de faixas horizontais, sem raios. Wordmark SUNNY SYSTEMS. Âmbar #FFB61F sobre #1A1A1D. Bricolage Grotesque, Inter e JetBrains Mono. Tom de voz brasileiro, pt-BR primário. No ar desde 17/03/2026.

O que sobreviveu às quatro versões

O sol e o amarelo. Tudo o mais mudou: a fonte, a forma do símbolo, o tom do amarelo, o idioma. Por isso a regra de não criar um quinto tom.

Referência

Fontes da verdade

Em caso de divergência, a fonte da verdade vence, nesta ordem.

#O queOndeObservação
1Tokenstokens/tokens.jsontokens.css é gerado a partir dele
2Logo, paleta e fontes originaisDrive _Sunny-NewBrand26.ai, .svg, .pdf, PNG, .ttf
3Implementação de referênciawebsite/src/style.cssImporta o tokens.css desde o website#14, em 15/09/2026. Ainda usa os nomes antigos pelo bloco de compatibilidade
4Decisõesdocs/decisoes/Append-only
5Históriadocs/historia-da-marca.mdV1 a V4 e explorações
/

Estado em setembro de 2026: os tokens deste repositório foram medidos no site, então hoje os dois batem. A partir da adoção do tokens.css pelo site, este repositório passa a ser a origem. Plano em versionamento.

Links

Para agentes e LLMs

O mesmo conteúdo desta página existe em markdown, gerado das mesmas fontes. Um agente que precise escrever código ou texto na marca deve ler isso em vez de raspar o HTML.

ArquivoO que éTamanho
/llms.txtÍndice no formato llmstxt.org, com as regras duras e os pares de cor proibidos inline. Para quem vai ler um arquivo só e decidir o que buscar depois6 KB
/llms-full.txtTudo em um arquivo: regras, tabela dos 276 tokens com valor resolvido e status, as quatro fundações, os cinco componentes, padrões, governança, as seis decisões e a história131 KB
/tokens.cssAs custom properties prontas para importar, com tema claro e aliases de compatibilidade26 KB

Os dois primeiros são gerados por node site/build.mjs a partir de tokens/tokens.json e de docs/. Não há cópia escrita à mão: se um valor muda no token, ele muda nos três arquivos no mesmo comando.

/

No llms-full.txt os aliases já vêm resolvidos: button.primary.bg aparece como #FFB61F junto com o token para o qual aponta. O agente não precisa seguir a cadeia de três camadas para saber a cor final.

Os cinco produtos

RootPilot, ScopeWard, DevXOS, Sunshine e Soberania de IA. Grafia fixa, sem espaço, sem hífen. Nenhum tem cor própria hoje: ver decisão 0005.