Sistema de Color
Resumen
Una biblioteca curada de paletas de color listas para usar (claro + oscuro) en cuatro dominios — UI de aplicación web, marketing/landing, visualización de datos y terminal/TUI — más la metodología para construir nuevas paletas y verificar su accesibilidad.
Principio central: elige colores por rol semántico (fondo, texto, primario, error…), no por tono crudo. Cada paleta aquí asigna valores hexadecimales a roles, por lo que un tema se mantiene intercambiable, consistente y accesible. Elige un rol primero, luego lee su valor hexadecimal — hardcodear un valor hexadecimal donde pertenece un rol es lo que rompe la tematización más adelante.
Navegación
El índice y el contrato de roles a continuación responden "qué paleta" por sí solos. Carga un archivo de referencia cuando la tarea necesite su contenido — no los cuatro.
| Cargar | Cuándo |
|---|---|
| references/carbon.md | Construir una página o artefacto que deba usar Carbon — lee solo este archivo; contiene los roles, el kit de panel y las tríadas de Carbon en ambos modos |
| references/palettes.md | Necesitas valores hexadecimales para cualquier otra paleta — los cuatro dominios, claro + oscuro; las tríadas fill/subtle/emphasis; las escalas de 12 pasos detrás de Dusk, Driftwood y Meadow |
| references/contrast.md | Verificar umbrales WCAG/APCA, seguridad para daltonismo, o depurar un par que falla |
| references/build-your-own.md | Ninguna paleta de la biblioteca se ajusta y estás generando una nueva escala (la receta OKLCH) |
| references/theory.md | Elegir un esquema de armonía, o justificar una decisión de espacio de color / escala |
Biblioteca de Paletas (índice rápido)
Donde una paleta es la primera opción correcta está marcada ⭐; marketing y TUI no tienen predeterminada porque la elección sigue la marca o el tema de terminal propio del usuario.
UI de Aplicación Web — claro + oscuro, 13 roles semánticos + una tríada por color
- Carbon ⭐ (predeterminada) — pizarra azul profunda, oscuro primero. Paneles de análisis, informes de rendimiento y herramientas de desarrollo. Incluye un kit completo de panel (píldoras de grado A–F, secuencia de etapas ordenada, tono de código en línea, resaltado de éxito). Recurre a Graphite en su lugar cuando el modo claro debe estar ajustado a mano por igual.
- Graphite — pizarra fría + azul. Paneles B2B densos, herramientas de desarrollo; la opción predeterminada de paridad claro+oscuro.
- Evergreen — esmeralda de marca sobre zinc neutro verdadero. Fresco, seguro, identidad no azul.
- Terracotta — neutros cálidos de arcilla/café + óxido. Editorial, plataformas de contenido, herramientas de escritura.
- Bloom — lila/violeta pastel, modo oscuro profundo. Herramientas de desarrollo amigables, aplicaciones divertidas pero limpias.
- Teal Slate — verde azulado profundo sobre pizarra fría, un solo acento cálido. Informes técnicos, paneles SRE / límite de velocidad; combina con una fuente mono para figuras.
Generadas a partir de escalas OKLCH de 12 pasos, que se incluyen junto con sus roles para que puedan extenderse o rederivarse:
- Dusk — primario índigo, acento turquesa, grises fríos casi neutros. Herramientas de enfoque, editores, aplicaciones de sesión larga.
- Driftwood — primario marino profundo sobre neutros de arena cálida, acento arcilla. La que cambia sus neutros a fríos en modo oscuro.
- Meadow — primario salvia apagado, acento oro viejo, neutros hueso cálidos. La más suave del conjunto; reposada en lugar de segura.
Marketing / Landing — claro + oscuro, degradados de héroe
- Sunbloom — calidez coral/ámbar refinada. Marcas accesibles para consumidores/creadores.
- Tidewater — verde azulado/salvia. Fintech, bienestar, confianza B2B.
- Obsidian & Gold — casi negro + oro metálico. Premium, lujo, agencia.
- Paper & Ink — papel cálido + tinta negra + un acento terracota. Blogs, texto largo, portafolios.
Visualización de Datos — consciente del daltonismo, cálido/frío terroso
- Categórico: Lunar Valley ⭐ (predeterminada) · Hearthstead · Vintage Warm · Glass Wall · Okabe-Ito (usa cuando la seguridad CVD sea un requisito estricto)
- Secuencial: Viridis ⭐ (predeterminada) · Magma · Inferno · Plasma · ColorBrewer Blues · YlOrRd (todas perceptualmente uniformes)
- Divergente: Console & Window ⭐ (predeterminada) · Alien Sun · Orchard Dusk · Coffee & Coolant — todas cálido↔frío, sin rojo↔verde
Terminal / TUI — 16-ANSI + bg/fg/cursor/selection
- Solarized Dark · Nord · Catppuccin Mocha · Catppuccin Latte (el único esquema claro) · Dracula · Tokyo Night
→ Tablas hexadecimales completas: Carbon en references/carbon.md, todas las demás paletas en references/palettes.md
Roles semánticos (el contrato)
Las paletas de UI llenan estos roles. Asigna la intención a un rol, luego el rol a un valor hexadecimal.
| Rol | Qué es |
|---|---|
background | Lienzo base de la app/página |
surface | Tarjetas, paneles, hojas |
surface-elevated | Superficies elevadas (popovers, modales); en modo oscuro más claro = más elevado |
border | Divisores, bordes de entrada, anillos de enfoque |
text-primary | Primer plano de alto énfasis |
text-secondary | Etiquetas atenuadas, sugerencias, subtítulos |
primary / primary-hover | Color de acción de marca + su estado hover |
accent | Énfasis secundario, distinto del primario |
success / warning / error / info | Estados semánticos (verde / ámbar / rojo / azul por convención occidental) |
Cada rol de color necesita entonces una tríada, porque un solo valor hexadecimal no puede hacer tres trabajos. Un valor creado para estar sobre no es automáticamente legible como texto, y un relleno sólido es demasiado fuerte como fondo de insignia en densidad de tabla.
| Token | Trabajo | Bootstrap 5.3 lo llama | Material 3 lo llama |
|---|---|---|---|
{c}-fill + {c}-on-fill | Botones, chips activos | --bs-{c} + color-contrast() | primary + on-primary |
{c}-subtle + {c}-emphasis | Fondo de insignia/nota + su etiqueta | --bs-{c}-bg-subtle + -text-emphasis | primary-container + on-primary-container |
{c}-subtle-border | Borde alrededor de ese fondo | --bs-{c}-border-subtle | — |
link | El tono de marca como texto sobre surface | (dividido en v6) | — |
Las tríadas listas para las nueve paletas de UI están en palettes.md, excepto las de Carbon, que están en carbon.md. Los rellenos en modo oscuro son tonos claros, por lo que sus etiquetas son el neutro más oscuro de la paleta, no blanco.
Las paletas de visualización de datos proporcionan en su lugar listas de colores ordenados (categórico = series distintas; secuencial = rampa de bajo→alto; divergente = cálido↔frío con un punto medio neutro). Los esquemas TUI proporcionan las 16 ranuras ANSI más 4 roles especiales.
Conceptos principales
- Diseña en OKLCH, no HSL. OKLCH es perceptualmente uniforme; la "luminosidad" HSL miente (el azul con igual L se ve mucho más oscuro que el amarillo con igual L), por lo que incluso los pasos HSL producen escalas grumosas.
- Armonía: elige un esquema (monocromático / análogo / complementario / triádico…) y deja que un color domine en saturación y área; desatura el resto.
- Escalas: 10–12 pasos, espacia la luminosidad uniformemente, pico de croma en el rango medio y afínalo en los extremos para que los tintes no se vean lavados y las sombras no sean turbias.
- Contraste: WCAG AA — texto del cuerpo ≥ 4.5:1, texto grande y UI/bordes ≥ 3:1.
- Claro vs oscuro no es una inversión, y las relaciones WCAG 2 exageran el contraste cerca del negro. Ambos modos de fallo y sus soluciones están en Errores Comunes a continuación; los umbrales y el procedimiento APCA están en references/contrast.md.
- Seguridad para daltonismo: codifica el significado con texto, icono o posición además del tono, ya que ~8% de los hombres no pueden separar los tonos por sí solos. Para datos divergentes usa cálido↔frío (azul/naranja, verde azulado/rosa) en lugar de rojo↔verde.
Ejemplos
Ejemplo: elegir colores para un panel SaaS
✅ Correcto
Usuario: "Necesito colores para un panel de administración, claro y oscuro."
→ Recomendar Carbon (pizarra azul profunda, oscuro primero, hecho para UI de datos densos) — la predeterminada;
ofrecer Graphite si la paridad del modo claro ajustada a mano importa más que el kit de panel.
→ Copiar su tabla rol→hex de carbon.md (ambos modos).
→ Aplicar por rol: background→surface→border→text, primary para el CTA principal,
success/warning/error para insignias de estado. Confirmar text-primary sobre background ≥ 4.5:1.
❌ Anti-patrón
→ Elegir cuatro tonos de una paleta Coolors y asignarlos ad hoc: #2b2d42 nav, #8d99ae texto,
#edf2f4 fondo, #ef233c botones. Modo oscuro = invertir los valores hexadecimales.
Por qué funciona: una paleta asignada por roles se coloca directamente en variables CSS y es accesible por construcción. La versión ad hoc no tiene rampa neutra, ni niveles de elevación, ni colores de estado, e invertir una paleta clara produce superficies negro puro y tonos de marca desteñidos (ver Errores Comunes: claro vs oscuro no es una inversión).
Ejemplo: color de insignia de estado
✅ Correcto
.badge-error { background: var(--error); color: #fff; } /* rol, no un rojo hardcodeado */
❌ Anti-patrón
.badge-error { background: #ff0000; color: #000; } /* tono crudo; #f00 sobre #000 ≈ 5.2:1 pero deslumbra,
y no se tematizará ni cambiará a modo oscuro */
Por qué falla: hardcodear un tono rompe la tematización y el modo oscuro, y el rojo puro/negro puro causa halación.
Ejemplo: elegir una paleta de gráfico
✅ Correcto
Series categóricas (≤8) → Lunar Valley (predeterminada), o Okabe-Ito cuando se requiera seguridad CVD.
Continuo bajo→alto → Viridis (perceptualmente uniforme, seguro para daltonismo).
Datos con signo y punto medio → Console & Window (cálido↔frío, centro neutro).
Pasadas ~8 colores categóricos, las series dejan de ser distinguibles — agrupar en "Otros" en su lugar.
❌ Anti-patrón
Doce series categóricas coloreadas desde los roles success/warning/error/info de la paleta de UI más
matices de marca; ganancia/pérdida codificada verde↔rojo sin etiquetas.
Por qué funciona: empareja la estructura de los datos con la familia de paleta adecuada y respeta el límite de distinguibilidad. El anti-patrón reutiliza roles de estado de UI que chocan con la identidad de las series, excede el límite de ~8 tonos, y codifica rojo↔verde sin respaldo de texto o icono para usuarios con daltonismo.
Errores Comunes
- Síntoma: El color de marca es ilegible como texto del cuerpo. Causa: Los tonos medios saturados (ámbar, coral, verde azulado) a menudo fallan 4.5:1 sobre su propio fondo — un color de relleno y un color de texto son pasos diferentes de la misma rampa. Solución: mantén
fillylinkcomo valores separados; oscurece el texto un paso hasta que lo supere. En esta biblioteca solo Evergreen claro diverge (#059669soporta una etiqueta de botón a 4.70:1 pero alcanza 3.77:1 como enlace sobre blanco, por lo que sulinkes#00875b), que es exactamente por qué la división se pasa por alto. - Síntoma: Las insignias de estado se ven correctas pero gritan en densidad de tabla. Causa: un fondo sólido
--errordetrás de texto blanco es correcto para un botón y demasiado fuerte para una insignia a nivel de fila. Solución: usa el fondo{c}-subtlecon su etiqueta{c}-emphasisemparejada. Reutilizar el tono de estado como su propia etiqueta sobre ese matiz falla 4.5:1 más a menudo de lo que acierta — toma el valor emparejado de palettes.md (el de Carbon de carbon.md) en lugar de asumir. - Síntoma: Una paleta generada a partir de una escala de 12 pasos aún falla contraste. Causa: el mapa de pasos no es una garantía de contraste. Radix garantiza los pasos 11 y 12 contra el paso 2 y nada más; el paso 9 rara vez soporta una etiqueta de botón a 4.5:1, y el paso 8 rara vez alcanza 3:1 como borde de control. Solución: resuelve esos dos contra su fondo real. En modo claro comprométete con una etiqueta blanca y oscurece el relleno — resolver hacia la etiqueta que ya puntúe más alto produce un lavado pálido que pasa y se ve débil.
- Síntoma: Una paleta que se ve bien en modo claro se siente turbia en oscuro. Causa: el matiz neutro se eligió una vez y se heredó. Un tono cálido que se lee como papel con alta luminosidad se lee como marrón con baja luminosidad. Solución: Vuelve a decidir el matiz y croma neutros por modo; cambiar a frío con croma muy bajo es la respuesta habitual. Driftwood en palettes.md hace esto (tono 64 claro, 224 oscuro); Meadow's salvia no lo necesitó.
- Síntoma: Una paleta copiada de Color Hunt, Coolors o un artículo de tendencia no puede construir una interfaz. Causa: las paletas de galería son cuatro tonos decorativos sin rampa neutra, sin tinta oscura y sin estados — 16 de las 30 paletas más gustadas de Color Hunt no pueden soportar texto del cuerpo a 4.5:1 con ningún par de sus colores. Solución: toma los tonos como material semilla y construye escalas a partir de ellos (build-your-own.md); Dusk, Driftwood y Meadow se hicieron así.
- Síntoma: El texto secundario/atenuado ("dimmed",
text-secondary) se ve bien en la herramienta de diseño pero falla contraste en la aplicación. Causa: las bibliotecas de componentes envían un color de texto atenuado predeterminado (ej. eldimmedde Mantine) ajustado para jerarquía visual, no para contraste — comúnmente alrededor de ~3.4:1, muy por debajo del mínimo AA de 4.5:1. Solución: elige y verifica tu propio valor hexadecimaltext-secondarycontra contrast.md en lugar de heredar el predeterminado de la biblioteca, y vuelve a verificar por tema — la misma anulación puede pasar en un tema y fallar en otro. Vuelve a verificar también en superficies teñidas/elevadas (tarjetas, filas rayadas), no solo en el lienzo plano. - Síntoma: El modo oscuro "pasa WCAG" pero es difícil de leer. Causa: La matemática de WCAG 2 exagera el contraste cerca del negro. Solución: Vuelve a verificar los pares oscuros con APCA (Lc), no solo la relación 4.5:1.
- Síntoma: El tema oscuro se ve plano, la elevación ilegible. Causa: Fondo
#000puro + superficies de la misma luminosidad. Solución: Eleva la base a ~#0d1117–#1e1e2ey haz que cada nivel de elevación sea más claro. - Síntoma: Un gráfico es ilegible para usuarios con daltonismo. Causa: Codificación rojo↔verde o significado solo por tono. Solución: Cambia a una paleta divergente cálido↔frío y agrega etiquetas/iconos; para categórico usa el conjunto seguro Okabe-Ito (en palettes.md).
- Síntoma: El texto del gráfico permanece con bajo contraste aunque tu paleta defina el color de texto correcto. Causa: Las bibliotecas de gráficos (Recharts, gráficos Mantine) renderizan texto de ejes/leyenda/valores como SVG con su propio
fillen línea, evitando tus tokens de color por completo. Solución: Apunta directamente a los elementos de texto de la biblioteca (ej..recharts-wrapper text { fill: var(--text) }) — la cascada CSS nunca llega allí. - Síntoma: Los colores TUI desaparecen en algunos terminales. Causa: Valor hexadecimal hardcodeado, o texto importante colocado en negro brillante (ranura 8). Solución: Vincula el significado a las ranuras ANSI 1–6 para que el tema propio del usuario lo renderice, y mantén la ranura 8 solo para desénfasis.
- Síntoma: Los pasos de la paleta se ven grumosos/desiguales. Causa: Espaciar la luminosidad en HSL/RGB. Solución: Reconstruye la escala en OKLCH usando la receta en build-your-own.md.
Referencias
| Archivo | Contenido |
|---|---|
| references/carbon.md | Específico de Carbon: roles de UI claro/oscuro, kit de panel, tríadas por color |
| references/palettes.md | Todas las demás paletas: web, marketing, gráficos, terminal. Tablas completas. |
| references/contrast.md | Umbrales WCAG AA/AAA, puntos de corte APCA, pares de ejemplo, métodos de verificación |
| references/build-your-own.md | Receta OKLCH: diseñar una nueva escala de 12 pasos desde un tono semilla |
| references/theory.md | Esquemas de armonía, espacios de color, psicología del color, notas de historia del diseño |
Sistema de Color seleccionado para agentes de IA. Usa siempre los archivos de referencia en lugar de hardcodear valores hexadecimales.