Fundações
Cor
--brand é a ação, --ia é o agente, --positive é o sucesso. Nenhum componente sabe qual tema está no ar — ele pede bg-surface e recebe a superfície do tema vestido. Troque o tema no topo desta página e todas as amostras abaixo mudam, porque elas leem o valor real no navegador.Papéis, não matizes
A distância é o canon
No Claro, marca e IA ficam a 120° de matiz (verde e violeta). Com a marca em azul, o violeta cairia pra 41° e os dois fundos suaves (#dbeafe e #ede9fe) virariam a mesma cor no olho. Por isso o tema Azul clínico leva a IA pro fúcsia, que devolve 72° e continua lendo como “roxo de IA”.
O troco, assumido
Branco sobre o fúcsia dá 4,71 contra 5,70 do violeta: passa o AA com menos folga. Vale, porque cor de IA que não se distingue da ação não cumpre função nenhuma, por melhor que seja o contraste dela.
| O que NÃO anda com a marca | Por quê |
|---|---|
| --positive | Sucesso é verde em qualquer tema. É o desfecho que fecha a conta — “compareceu” não pode virar azul num app azul. |
| --tick-read | O ✓✓ de lida é convenção do WhatsApp, não roupa da clínica. Se andasse com o tema, um app verde diria “lida” em verde e o sinal perderia o significado. |
| O verde do logotipo (#16a34a) | Constante congelada no SVG. Logotipo que troca de cor com o tema deixa de ser logotipo. |
| O verde do WhatsApp (#25D366) | Marca de terceiro: vive no glifo do canal e na textura do chat. |
Os cinco temas
NuncaAs peles são do APP. A identidade é o verde.
Os três temas escuros existem para o modo escuro do aplicativo, e para mais nada. Landing page, apresentação, proposta, e-mail, post, anúncio, impresso, papelaria, slide, vídeo, ícone de loja — qualquer material da Hiperclini que não seja a tela do produto usa o tema Claro, que é a identidade da marca: o verde sobre superfície branca.
A mesma trava vale pro Azul clínico: ele é uma preferência que a CLÍNICA escolhe dentro do produto, não uma variante da marca Hiperclini. Peça de marketing em azul (ou em grafite, verde profundo, ardósia) está falando a língua de um cliente específico, ou de nenhuma — não a nossa.
O seletor no topo desta página é ferramenta de conferência: ele existe pra você ver como um componente se comporta vestido de cada pele. Escolher um escuro aqui não autoriza usá-lo fora do app.
| Slug | Nome na UI | O que a pessoa ganha | Aparência |
|---|---|---|---|
| data-theme="light" | Claro | O padrão da casa, para sala clara. | light |
| data-theme="azure" | Azul clínico | Claro, com o azul que muita clínica prefere. | light |
| data-theme="graphite" | Grafite | Escuro neutro, contraste alto. | dark |
| data-theme="forest" | Verde profundo | Escuro com um fundo esverdeado. | dark |
| data-theme="slate" | Ardósia | Escuro suave, sem preto — cansa menos de dia. | dark |
Comparação lado a lado
Claro · data-theme="light"
Ocupação
esta semana
Azul clínico · data-theme="azure"
Ocupação
esta semana
Grafite · data-theme="graphite"
Ocupação
esta semana
Verde profundo · data-theme="forest"
Ocupação
esta semana
Ardósia · data-theme="slate"
Ocupação
esta semana
Armadilha já pagaTema aninhado precisa se bastar
globals.css declara até o que repete o valor do claro, como --accent-dark e --ia-accent-dark. A variante dark: do Tailwind tem o mesmo cuidado embutido (um :not() que desarma a variante dentro de uma ilha clara).Marca ◊ a cor da ação
IA ◊ a cor do agente
Sim
O que o agente escreveu, sugeriu ou classificou vem em roxo, com Sparkles.
Não
Um dado que a recepção digitou não é território de IA. Roxo aqui mente sobre a origem do dado.
Neutros ◊ a escala “ink”
Armadilha já pagaA ilha ink-950 é escura nos CINCO temas
bg-ink-950 é a superfície de contraste máximo — dock, tooltip, bloco de código, painel do split de acesso. Dentro dela, texto relativo (text-ink-100) some: no tema escuro o ink-100 já é quase preto. Use tinta fixa (branco) ou --accent-dark. E note que no escuro a ilha SOBE um degrau (#26262c, não quase-preto): preto sobre preto não é ilha, é buraco.Semânticas ◊ base · strong · soft
A regra do -strong, medida ao vivo
O -strong é o tom 700 no claro e o 300 no escuro: a direção inverte, a regra não. E a segunda amostra é o teste: no tema Claro o tom BASE sobre o -soft desaba pra ~2,2:1 e reprova — nos temas escuros ele passa, porque lá a base já é um tom claro. É por isso que a regra é “texto usa -strong”, e não “use o que parecer legível no tema em que eu estou desenhando”.
A gramática do escuro
Elevação vira tom, não sombra
Sombra preta não desenha sobre fundo escuro: o que sobe fica mais claro (--surface-2) com um fio de luz na borda (0 0 0 1px rgb(255 255 255 / 0.04)).
O tom -strong clareia
No claro ele é o 700 (escurece); no escuro é o 300. A regra do canon continua: texto SEMPRE no -strong.
Botão colorido inverte a tinta
O fundo clareia pro tom 400 e o texto vira o 950 da família (--brand-fg, --ia-fg, --warning-fg). Nunca text-white num botão.
Véu de tinta não escurece o escuro
--scrim no claro é preto a 40%; no escuro sobe pra 65% e o --veu da película deixa de ser a superfície e passa a ser o fundo — recuar no escuro é afundar no preto, não clarear.
Tokens de propósito único
| Token | O que é | Por que não usa a família |
|---|---|---|
| --tick-read | O ✓✓ azul de mensagem lida. | É recibo do WhatsApp. No Azul clínico ele fica AINDA mais fundo (blue-800), pra não sumir na bolha azul-clara nem virar a tinta da marca. |
| --agora / --agora-soft / --agora-strong | O fio do horário corrente na grade da agenda, e a etiqueta da hora. | Rosa, não vermelho: nos temas escuros --negative e --agora seriam o mesmo vermelho e o fio sumiria dentro do cartão de “faltou”. E “agora” não é erro — é posição do relógio. |
| --hatch | O triplet RGB da hachura de fora-do-expediente (o alpha fica no consumidor). | Risco preto não desenha sobre fundo escuro: nos temas escuros vira 255 255 255. |
| --scrim / --scrim-suave / --scrim-tenue | Os três véus: diálogo e gaveta · busca com desfoque · captura de clique de fora. | Carregam a própria transparência porque no escuro não basta trocar a cor — é o preto puro que passa a fazer o trabalho. |
| --veu | A cor de “para onde a tela recua” no foco em camadas. | No claro é a superfície (o conteúdo se dissolve no branco); no escuro é o fundo. |
| --surface-hoje / --surface-hoje-hover | A coluna de HOJE na agenda. | É color-mix de --brand-muted com --surface, resolvido no uso. Opaca de propósito: cabeçalho e faixa “dia todo” ficam grudados no topo, e tinta transparente deixaria os compromissos passarem por baixo. |
| --evt-fundo-l/c · --evt-texto-l/c · --evt-borda-l/c | A receita OKLCH da cor de um compromisso. | O banco guarda o NOME da cor; a tinta é conta do tema. OKLCH porque amarelo e azul no mesmo lightness pesam igual na tela — em HSL o amarelo salta. |
.evt {
background: oklch(var(--evt-fundo-l) calc(var(--evt-fundo-c) * var(--evt-k, 1)) var(--evt-h));
color: oklch(var(--evt-texto-l) calc(var(--evt-texto-c) * var(--evt-k, 1)) var(--evt-h));
border-color: oklch(var(--evt-borda-l) calc(var(--evt-borda-c) * var(--evt-k, 1)) var(--evt-h));
}
/* A FORMA é o ESTADO e sobrevive à cor escolhida:
.evt-listrado agendado — tinta pela metade, ainda é promessa
.evt-vazado faltou — o buraco na agenda precisa se ver vazado
.evt-check compareceu — o carimbo cabe num cartão de 15 min porque é um caractere */Status da jornada
Armadilha já pagaO tema Azul revelou uma inversão de dois anos
--brand e --positive são o MESMO verde — e isso escondia que a agenda pintava “Compareceu” com a MARCA e “Confirmado” com o SUCESSO, invertido em relação ao que o canon sempre disse. O Azul clínico separou os dois e o erro apareceu. Corrigido: compareceu é verde em qualquer tema (é o desfecho que vale dinheiro) e confirmado veste a marca.Como o tema chega na tela
const tema = await temaDoEspelho(); // cookie hc-tema (espelho de user_settings)
<html data-theme={tema === TEMA_PADRAO ? undefined : tema}>| Peça | Onde | Nota |
|---|---|---|
| A verdade | user_settings.theme | É da conta: entrar noutro computador já traz o tema junto. |
| O espelho | cookie hc-tema (__Host- em produção) | O servidor precisa da resposta antes de qualquer query. O prefixo __Host- impede um subdomínio irmão de plantar um espelho falso. |
| A pintura | atributo data-theme no <html> | O tema padrão NÃO carimba o atributo — :root já é o claro. |
| Os nativos | color-scheme: light | dark | Select, campo de data e barra de rolagem seguem a UI em vez do SO. Era o que pintava controles escuros por cima do app claro. |
| A moldura do celular | TEMA_BG (meta theme-color) | Meta tag não lê CSS var — é o único espelho manual do --bg, e há teste comparando os dois. |
Regras de cor
Nunca hex solto no componente
Sempre a classe utilitária (bg-brand, text-fg-muted, border-border). O teste tokens.test.ts varre src/ e reprova cor literal fora das exceções declaradas.
Cor nova é decisão de design system
Não do componente. Cor nova entra por globals.css, nos CINCO temas, e aparece aqui.
Texto semântico usa o -strong
text-warning-strong, text-negative-strong… O tom base fica pra dot, fundo e borda.
Tinta sobre botão colorido vem do -fg
text-brand-fg, text-ia-fg. Nunca text-white: no escuro o botão clareia e o branco deixa de ler.
A variante dark: é exceção, não ferramenta
Quase tudo troca pelo token. dark: existe pro caso pontual que INVERTE (uma pílula escura no claro tem que ficar clara no escuro).
Sombra colorida é token próprio
As sombras utilitárias têm tinta por tema, e a var é opaca: compor cor na utility (shadow-sm shadow-brand/20) deixa de funcionar em silêncio. Ver --shadow-glow-ia.
NotaDébitos congelados