Pular para o conteúdo
Cor da agenda

Fundações

Cor da agenda

As 24 cores do marcador não são 24 hex: são 24 receitas de quatro campos que cada tema resolve na sua tinta. Esta página conta a regra do cartão vivo, a do passado, a do cancelado, e a medida que decide se a paleta está boa.
lib/agenda/cores.tsapp/globals.cssOKLCH24 cores

A receita

O banco guarda o NOME da cor, nunca o código dela. Um hex gravado na linha ficaria fluorescente num tema e ilegível no outro — e a clínica tem cinco temas.
CampoO que ele faz
matizO ângulo OKLCH. É o NOME da cor — mexer nele troca Rubi por outra coisa.
cromaMultiplica a saturação da receita do tema. É o que deixa existir marrom, musgo e cinza numa paleta que, no resto, é de cor cheia.
luzDesloca a luminância desta cor em pontos percentuais, sobre a base do tema. É a peça que separa as cores DEPOIS do lavado.
textoClaro ou escuro por cor. Só o tema claro usa a distinção; nos três escuros o texto claro serve nas 24.

Como a cor chega no cartão

estiloDaCor devolve as quatro medidas como variáveis CSS, e o cartão as veste por style inline. A conta acontece no consumidor, nunca no token.

app/globals.css
.evt {
  background: oklch(
    calc(var(--evt-fundo-l) + var(--evt-dl, 0%))
      calc(var(--evt-fundo-c) * var(--evt-k, 1)) var(--evt-h)
  );
}

Armadilha já pagaO calc mora no consumidor, não no token

Escrever calc() com --evt-dl lá em cima, junto dos tokens do tema, resolve contra a raiz — onde a variável não existe. Sai sempre a base do tema, sem erro e sem aviso. A conta tem que acontecer no elemento que recebeu o style. Mesma armadilha vale pro --evt-tx do texto.

As 24, vivas, passadas e canceladas

Cada fileira: a bolinha da paleta, o cartão de um compromisso futuro, o do mesmo compromisso depois que a hora passou e o dele cancelado. São os componentes de verdade, não uma réplica.
Rubi
Rubi, 14:00
Rubi, 14:00
Rubi, 14:00
Rosa
Rosa, 14:00
Rosa, 14:00
Rosa, 14:00
Salmão
Salmão, 14:00
Salmão, 14:00
Salmão, 14:00
Tomate
Tomate, 14:00
Tomate, 14:00
Tomate, 14:00
Laranja
Laranja, 14:00
Laranja, 14:00
Laranja, 14:00
Tangerina
Tangerina, 14:00
Tangerina, 14:00
Tangerina, 14:00
Âmbar
Âmbar, 14:00
Âmbar, 14:00
Âmbar, 14:00
Ouro
Ouro, 14:00
Ouro, 14:00
Ouro, 14:00
Amarelo
Amarelo, 14:00
Amarelo, 14:00
Amarelo, 14:00
Limão
Limão, 14:00
Limão, 14:00
Limão, 14:00
Abacate
Abacate, 14:00
Abacate, 14:00
Abacate, 14:00
Floresta
Floresta, 14:00
Floresta, 14:00
Floresta, 14:00
Esmeralda
Esmeralda, 14:00
Esmeralda, 14:00
Esmeralda, 14:00
Turquesa
Turquesa, 14:00
Turquesa, 14:00
Turquesa, 14:00
Oceano
Oceano, 14:00
Oceano, 14:00
Oceano, 14:00
Céu
Céu, 14:00
Céu, 14:00
Céu, 14:00
Azul
Azul, 14:00
Azul, 14:00
Azul, 14:00
Anil
Anil, 14:00
Anil, 14:00
Anil, 14:00
Lavanda
Lavanda, 14:00
Lavanda, 14:00
Lavanda, 14:00
Uva
Uva, 14:00
Uva, 14:00
Uva, 14:00
Magenta
Magenta, 14:00
Magenta, 14:00
Magenta, 14:00
Cacau
Cacau, 14:00
Cacau, 14:00
Cacau, 14:00
Musgo
Musgo, 14:00
Musgo, 14:00
Musgo, 14:00
Grafite
Grafite, 14:00
Grafite, 14:00
Grafite, 14:00
A bolinha fica em luminância FIXA de propósito: ela carrega matiz e croma, que são a identidade da cor, e não a luminância, que é decisão de legibilidade do cartão. A mesma receita alimenta a caixinha do profissional, que tem um risquinho em cima precisando de chão previsível.

A mesma paleta nos temas escuros

Graphite · data-theme="graphite"

Rubi
Rubi, 14:00
Rubi, 14:00
Rosa
Rosa, 14:00
Rosa, 14:00
Salmão
Salmão, 14:00
Salmão, 14:00
Tomate
Tomate, 14:00
Tomate, 14:00
Laranja
Laranja, 14:00
Laranja, 14:00
Tangerina
Tangerina, 14:00
Tangerina, 14:00
Âmbar
Âmbar, 14:00
Âmbar, 14:00
Ouro
Ouro, 14:00
Ouro, 14:00

Forest · data-theme="forest"

Rubi
Rubi, 14:00
Rubi, 14:00
Rosa
Rosa, 14:00
Rosa, 14:00
Salmão
Salmão, 14:00
Salmão, 14:00
Tomate
Tomate, 14:00
Tomate, 14:00
Laranja
Laranja, 14:00
Laranja, 14:00
Tangerina
Tangerina, 14:00
Tangerina, 14:00
Âmbar
Âmbar, 14:00
Âmbar, 14:00
Ouro
Ouro, 14:00
Ouro, 14:00

Slate · data-theme="slate"

Rubi
Rubi, 14:00
Rubi, 14:00
Rosa
Rosa, 14:00
Rosa, 14:00
Salmão
Salmão, 14:00
Salmão, 14:00
Tomate
Tomate, 14:00
Tomate, 14:00
Laranja
Laranja, 14:00
Laranja, 14:00
Tangerina
Tangerina, 14:00
Tangerina, 14:00
Âmbar
Âmbar, 14:00
Âmbar, 14:00
Ouro
Ouro, 14:00
Ouro, 14:00

O cartão passado

Regra copiada do Google e medida no DOM deles em 27/08. Ela não mudou quando a paleta ganhou luminância variável, e não deve mudar.

O chip deles não fica transparente: mede opacity: 1 e troca o preenchimento por uma versão pastel do mesmo pigmento. Medido no Pavão: futuro rgb(3,155,229), passado rgb(179,225,247), e 0,30 × 3 + 0,70 × 255 = 179 fecha nos três canais.

CamadaRegra
Fundo30% do pigmento sobre a superfície do tema, sólido
Primeira linhaA tinta cheia do tema — o nome continua legível
Segunda linhaA mesma tinta a 50% — a linha de apoio recua

NuncaNunca resolver isso com opacity

A prova está num print de cartões sobrepostos: com opacity, duas camadas a 30% empilham em 51% e um cartão vaza no outro. Camada sólida também impede as linhas de meia hora e o pontilhado da grade de atravessarem o cartão por dentro. Pousar sobre a superfície do tema, e não sobre branco fixo, é o que mantém a receita nos cinco temas: no escuro o pastel escurece junto.

O cartão cancelado

Vazado desde 29/08, escolha do founder numa galeria de dez propostas. Quem cancelou sumiu do dia, e um cartão sem corpo é a forma de dizer isso sem tirar a cor de quem era.

Medido no print do evento recusado do Google: o cartão perde o preenchimento, fica com o papel da tela e desenha traço, nome e risco na MESMA tinta, todos em rgb(144,207,179) sobre branco. É cor sólida, não transparência — a mesma regra do cartão passado.

CamadaRegra
FundoA superfície do tema, sem pigmento nenhum
Traço1px da tinta lavada, por dentro (outline com recuo de 1px)
Texto e riscoA mesma tinta do traço
Tarja do profissionalTinta CHEIA, por cima — é ela que ainda diz de quem era o horário
app/globals.css
.evt-vazado {
  --evt-vazado-tinta: oklch(
    calc(var(--evt-fundo-l) + var(--evt-dl, 0%) + var(--evt-vazado-dl))
      calc(var(--evt-fundo-c) * var(--evt-k, 1) * var(--evt-vazado-c))
      var(--evt-h)
  );
  background: var(--surface);
  color: var(--evt-vazado-tinta);
  outline: 1px solid var(--evt-vazado-tinta);
  outline-offset: -1px;
}
TemaDeslocamentoContraste da tinta nas 24Mediana
Claro e azure+15% de luz, croma × 0,51,35 a 2,671,76
Graphite, Forest, Slate+12% de luz, croma × 0,52,01 a 4,653,36

NotaO contraste baixo aqui é a decisão, não a falha

O cartão morto tem que sair da frente de quem varre a grade, e é por isso que a tinta lavada fica onde fica. O founder viu esses números ao lado de cada proposta antes de escolher. Quem quiser o texto mais legível sem perder o desenho mexe em --evt-vazado-dl, e essa é conversa com ele — não conserto de passagem.

Armadilha já pagaO traço apaga o anel de foco se ninguém devolver

.evt-vazado mora fora de qualquer camada e o evt-fio é utility: regra sem camada vence utility mesmo com especificidade menor, então o outline do vazado engoliria também o :focus-visible do fio. O anel é redeclarado dentro da própria regra.

A medida que decide se a paleta está boa

Lavar o pigmento destrói croma e preserva luminância. Numa paleta de luminância fixa, o lavado apaga a única dimensão que separava as cores — foi o que aconteceu aqui até 27/08.

A régua é a separação real entre as cores no estado lavado dividida pelo teto teórico daquela quantidade de cores. O teto sai de empacotar N cores no espaço inteiro com contraste mínimo de 4,5.

PaletaΔE mínimoTetoTaxaPares colididos
Google · 12 cores5,7011,7049%0 pares
Agenda até 27/08 · 24 cores2,708,6631%12 pares
Agenda hoje · 24 cores4,408,6651%5 pares

Empata com o Google carregando o dobro de nomes. O zero absoluto deles não é alcançável aqui: vinte e quatro matizes não cabem no mesmo círculo com a folga de doze.

NotaNão existe regra de luminância do Google pra copiar

A paleta deles varia 36 pontos de L, mas isso não é critério, é sedimento de anos de Material. Três hipóteses testadas e refutadas: L em função da matiz (Mirtilo e Lavanda são a mesma matiz com 15 pontos de diferença), L no pico de croma do sRGB, e C como fração fixa do pico. Os valores de luz e croma daqui saíram de otimização com duas travas: contraste mínimo em todos os temas, e ΔE ≤ 10 contra a cor anterior, pra nenhuma deixar de ser ela mesma.

Contraste do texto no cartão vivo

Aqui a página para de medir e passa a registrar uma decisão. O campo texto é escolha do founder, e ela não segue a medida.
TemaAté 27/08Hoje
Claro e azure3,01 a 3,622,18 a 8,17
Graphite8,44 a 10,824,68 a 11,07
Forest8,44 a 10,824,68 a 11,07
Slate8,44 a 10,824,68 a 11,07

Nos três temas escuros o texto claro serve nas 24 e a faixa é confortável. No tema claro ela vai de 2,18 a 8,17, porque 22 das 24 escrevem branco por escolha: sete passam AA, oito ficam só em AA-large e nove caem abaixo de 3,0, sendo a Esmeralda a pior.

NotaPor que não está "errado"

A medida recomendaria o inverso: dezenove escuras, cinco claras, piso em 4,52. Essa versão chegou a existir em produção por algumas horas em 28/08. O founder olhou as 24 numa galeria com o contraste de cada opção ao lado, virou dezessete cores para branco e ficou com o visual do Google, que shipa perto de 2,9 nesses chips. Está registrado aqui para ninguém "consertar" isso achando que foi descuido.

Armadilha já pagaMexeu em luz ou croma, volta a conversa

Mudar a luminância de uma cor muda o contraste das duas opções dela, e a escolha entre as duas é do founder, não da conta. A lista está travada em lib/agenda/cores.test.ts: se aquele teste cair, a pergunta não é qual valor é o certo, é quem mudou e se falou com ele.