Diseñador de paletas de colores
Los colores que se ven bien y además pasan el contraste provienen de un solo proceso: elegir tonos para el estado de ánimo, luego fijar la claridad con matemáticas. Las ruedas de armonía, el 60-30-10 y las tablas de psicología del color son heurísticas de partida sin evidencia de usabilidad detrás. El contraste, la moderación (un solo tono de acción) y un acento que destaque de su entorno son las partes que se sostienen. Construye para esas.
Todos los números provienen de scripts/palette.mjs (Node sin dependencias). Ejecútalo en lugar de estimar ratios o valores OKLCH a mano; el contraste calculado a mano suele estar equivocado con suficiente frecuencia como para importar (la investigación de la que proviene esta skill tenía varios valores con un error de 0.05 a 0.15).
S=<skill-dir>/scripts/palette.mjs
node $S contrast '#767676' '#ffffff' # 4.54:1, grados, APCA Lc
node $S oklch '#3F6B4E' # OKLCH exacto
node $S solve '#C0643F' '#FFFFFF' 4.5 darker # Ajusta solo L hasta que pase
node $S ramp 155 0.12 # Rampa OKLCH 50-950
node $S generate --hue 155 --chroma 0.07 --neutral-hue 95 --accent-offset -110 --format report
node $S generate ... --format css # también: css-light-dark | json | dtcg
node $S audit sage-wellness # un id de paleta curada, o cualquier roles.json
node $S presets # ajustes preestablecidos de división de área y mezcla de estados
node $S ratio 70 25 5 --preset calm # valida una división de área (porcentaje del área visible)
node $S states sage-wellness --css # mezclas resueltas de hover/active/disabled/tint + comprobaciones
node $S dark midnight-terminal # reglas de modo oscuro D1-D11 (añade --light <id|file>, --oled)
node $S cvd '#0072B2' '#D55E00' '#009E73' # separación para daltonismo
audit, generate, dark, states y ratio salen con código de error distinto de cero en caso de par fallido o regla FAIL, así que úsalos como puerta antes de mostrar algo al usuario. Para modo oscuro, generate y audit ejecutan las reglas oscuras automáticamente.
Flujo de trabajo: de la descripción a la paleta validada
- Interpreta la descripción. Color(es) de marca, palabras de estado de ánimo, industria, audiencia (edad, visión), modos (claro, oscuro o ambos), conformidad (AA por defecto; AAA para texto del cuerpo en salud, gobierno, audiencias mayores). Si el usuario dio solo una vibra, elige un tono de la tabla de decisión a continuación y declara la suposición en una línea en lugar de preguntar.
- Elige una estrategia. La opción por defecto es neutro matizado + un primario (+ opcionalmente un acento). Monocromo más colores semánticos es lo más seguro. Usa un complemento solo para hacer que el CTA destaque (efecto de aislamiento). Triádico y tetrádico pertenecen a gráficos e ilustraciones, rara vez en el chrome de la UI.
- Fija el tono y croma de anclaje. Con un hex de marca, ejecuta
oklchy conserva su tono. Limita el croma alrededor de 0.12 para terroso/bienestar, 0.20-0.26 para vibrante/tecnología. Sin uno, elige un tono distinto de los competidores obvios en la categoría. - Genera.
generateconstruye roles neutro, primario, acento y semánticos para cada modo y resuelve la claridad para que se cumplan los objetivos de contraste. Para una paleta hecha a mano, construye rampas conrampy asigna los pasos a los roles (tabla a continuación). - Valida cada par con
audit. Ante un fallo, mueve solo la claridad (solve), nunca el tono; reduce el croma si el color sale del espacio sRGB. Cada fallo en las 15 paletas curadas fue un acento de claridad media y croma alto (OKLCH L alrededor de 0.60-0.77): demasiado claro para texto blanco, demasiado oscuro para texto oscuro, demasiado cerca del blanco para 3:1. Solución: oscurece a L <= 0.55 y usa texto blanco, aclara a L >= 0.72 y usa texto oscuro, o mantenlo decorativo con un borde. - Comprobación de daltonismo con
cvd. Si primario, éxito y error colapsan (dE_OK < 0.10 bajo cualquier simulación), sepáralos por claridad y requiere un icono y una etiqueta, porque el tono por sí solo no puede transmitir significado (WCAG 1.4.1). - APCA es consultivo. WCAG 3 no ha adoptado un algoritmo de contraste (el borrador de trabajo de septiembre de 2026 dice que aún está por determinar), por lo que WCAG 2.2 decide aprobado/reprobado. Informa APCA Lc como advertencia: texto del cuerpo por debajo de |Lc| 75 es fino (común en modo oscuro); por debajo de 15 es invisible.
- Define estados con
states, no a mano. Los porcentajes de hover y active dependen de la paleta: los porcentajes preestablecidos planos dejaron al menos un paso de estado por debajo de dL 0.03 (apenas visible) en 37 de 45 combinaciones de paleta/preajuste que medimos, y solo el paso de hover en 26.node $S states <palette> --preset standard --cssresuelve el porcentaje de mezcla y la dirección (hacia el que de texto/fondo mantenga legible el on-primary), comprueba el contraste de cada estado y emite variablescolor-mix(in oklab, ...);generate --format css --states standardlas añade a cada modo. Deshabilitado: mezclado hacia el fondo más una pista no cromática. Foco: anillo de 2px, desplazamiento de 2px, >= 3:1 contra el fondo. Seleccionado y visitado necesitan una pista no cromática. - Elige las proporciones (ver "Reglas de porcentaje" a continuación) y declara el preajuste en las notas de entrega.
- Emite la tabla de roles (hex + OKLCH exacto), la tabla de aprobados/reprobados, propiedades personalizadas CSS y, opcionalmente,
@themede Tailwind v4 o JSON DTCG. Etiqueta la justificación como convención o evidencia (verreferences/evidence-and-conventions.md) para que el texto generado nunca repita el folclore de la psicología del color. - Muéstralo. Ofrece o construye la página de demostración (abajo) para que el usuario juzgue la paleta en un diseño real, no en una cuadrícula de muestras.
Contrato de roles
Cada paleta define estos roles para cada modo compatible. Los componentes consumen roles, nunca el hex sin procesar.
| Rol | Propósito | Mínimo |
|---|---|---|
bg, surface, surface-2 | lienzo, tarjetas, paneles elevados | distinguible (OKLCH dL >= ~0.03) |
border | divisores decorativos | ninguno |
border-strong | contornos de entrada, controles | 3:1 sobre bg (SC 1.4.11) |
text | cuerpo | 4.5:1 sobre bg y superficies (apunta a 7+) |
text-muted | texto secundario | 4.5:1 sobre bg y superficies |
primary / on-primary | relleno de acción principal / texto sobre él | relleno 3:1 sobre bg, texto de enlace 4.5:1; texto sobre relleno 4.5:1 |
accent / on-accent | segundo tono opcional | igual que primario si conlleva significado |
success warning error info | texto e iconos de estado | 4.5:1 sobre bg; nunca solo color |
focus-ring | foco del teclado | 3:1 vs colores adyacentes |
Mapeo de rampa a rol (escala 50-950): claro bg 50 o blanco, surface blanco/50, surface-2 100, border 200, border-strong 500, text 900-950, text-muted 600, primary 600-700, on-primary blanco, focus primary-600. Oscuro: bg 950 (o 900), surface 900, surface-2 800, border 800, border-strong 600, text 50-100, text-muted 400, primary 300-400, on-primary 950, focus primary-300. Trata el mapeo como una primera aproximación y deja que audit decida.
Reglas estrictas (WCAG 2.2 AA a menos que se solicite AAA)
- Texto 4.5:1; texto grande (>= 24px, o >= 18.66px negrita) 3:1; componentes de UI y gráficos significativos 3:1 (SC 1.4.11); AAA es 7:1 texto, 4.5:1 grande.
- Los bordes decorativos pueden ser tenues, pero un contorno de entrada que sea la única pista para el campo debe alcanzar 3:1. Un borde de entrada "elegante" de 1.3:1 es un fallo.
- El color nunca transmite significado por sí solo. Subraya los enlaces del cuerpo o dales 3:1 contra el texto circundante más una pista de hover/foco; los errores obtienen un icono y un mensaje; las series de gráficos obtienen etiquetas directas o formas.
- Los fondos matizados cambian las matemáticas. Los colores semánticos ajustados para blanco caen a aproximadamente 4.4:1 sobre un fondo de papel cálido; ejecuta
auditsobre el fondo real, no sobre blanco. - El contraste en degradados y fotos debe mantenerse en el peor punto (la región más clara y más oscura), o añade un velo.
Detalles, fórmulas, conjuntos seguros para daltonismo (Okabe-Ito) y umbrales APCA: references/accessibility.md.
Trabajando en OKLCH
- Usa
oklch(L C H)como la fuente de verdad.Les claridad percibida (0-1), por lo que colores con la misma L realmente parecen igual de claros; en HSL un amarillo al 50% y un azul al 50% son enormemente diferentes. Rotar el tono en OKLCH mantiene la claridad, por lo que los desplazamientos de armonía funcionan allí y no en HSL. - Matiza los neutros con el tono de la marca con un croma muy bajo: aproximadamente 0.005-0.015 cerca del blanco, 0.01-0.045 en oscuros. Los neutros cálidos (tono 60-100) se adaptan a bienestar, comida, editorial; fríos (240-270) a SaaS, finanzas, herramientas de desarrollo. Evita los grises puros errantes junto a los matizados.
- Objetivos de rampa: L 0.985, 0.967, 0.928, 0.872, 0.707, 0.554, 0.446, 0.372, 0.279, 0.208, 0.129 para los pasos 50-950, con croma disminuyendo en ambos extremos. Mapea la gama reduciendo el croma, no recortando; los navegadores recortan toscamente.
- Degradados: interpola
in oklaboin oklchpara evitar puntos medios grises y embarrados; evita degradados oscuros de croma casi nulo a pantalla completa (bandas) o añade ruido sutil. - Soporte (finales de 2026):
oklch()Línea base desde 2023;color-mix()Ampliamente disponible desde noviembre de 2025; sintaxis de color relativo en Chrome 122+, Firefox 128+, Safari 18+;light-dark()alcanza Ampliamente disponible el 13 de noviembre de 2026. Entrega propiedades personalizadas simples con unprefers-color-schememás una anulación[data-theme]como salida por defecto; ofrecelight-dark()como alternativa compacta. En la sintaxis de color relativo,les 0-1.
Tabla de decisión: de la descripción a la estrategia
| Señal de la descripción | Neutro | Primario | Acento | Modo | Objetivo |
|---|---|---|---|---|---|
| Bienestar, orgánico, spa, té | cálido, H 70-100, C 0.008-0.02 | salvia/musgo/verde azulado, C 0.05-0.10, L ~0.50 | análogo o complemento terroso (terracota, arcilla) | claro | AA, cuerpo 7:1 preferido |
| Comercio electrónico | neutro/cálido, C <= 0.01 | marca | tono de CTA aislado no usado en ningún otro lugar | claro | AA |
| SaaS / B2B | frío, H 250-270, C 0.01-0.04 | azul/añil/violeta | monocromo + semántico | claro + oscuro | AA |
| Herramienta de desarrollo | frío o gris puro | azul/violeta/verde, oscuro L 0.70-0.80 | mono; colores de sintaxis solo en código | oscuro primero + claro | AA, comprobar APCA |
| Agencia / portafolio | blanco roto tipo papel o casi negro | negro/blanco | un acento eléctrico, con bordes si falla 3:1 | cualquiera | AA |
| Finanzas | azul marino frío | azul marino/azul | ganancia/pérdida con +/- y flechas | claro (+ oscuro) | AA, AAA para cifras |
| Salud | neutro frío | verde azulado/azul | verde calmado | claro | AAA cuerpo |
| Infantil / creador | crema cálido | violeta/azul saturado | triádico, cada uno <= 10% del área | claro | AA |
Puntos de partida: references/palettes.md (15 paletas verificadas con CSS, OKLCH y tablas de aprobados/reprobados). Elige la más cercana, adapta el tono y el croma, vuelve a ejecutar audit.
Reglas de porcentaje y ajustes preestablecidos
Las divisiones de área son un presupuesto de área, no una ley: el 60-30-10 es una convención de diseño de interiores sin ningún estudio de usabilidad detrás de los números exactos, pero una pequeña participación del acento protege el único efecto respaldado por la investigación aquí (un CTA destaca solo si su tono es raro). Las participaciones son el porcentaje del área de fondo visible (la tinta del texto no se cuenta). Comprueba una división con ratio; mide una página real con scripts/measure-area.js en lugar de adivinar.
| Preajuste | División n-p-a | Uso para |
|---|---|---|
classic | 60-30-10 | marketing de comercio electrónico y SaaS, valor por defecto general |
calm | 70-25-5 | bienestar, salud, finanzas, editorial |
dense-app | 80-17-3 | tableros, administración, herramientas de desarrollo (claro u oscuro) |
product-first | 80-15-5 | catálogos donde las fotos llevan el color; un tono de CTA aislado |
editorial | 70-27-3 | brutalista/editorial: los bordes y la tinta hacen el trabajo |
dark-showcase | 70-22-8 | portafolio/agencia oscuro con un acento vívido |
bold-brand | 50-30-20 | creador, campaña, infantil: el acento puede liderar |
Reglas: las participaciones suman 100 (FAIL); el neutro es la participación más grande, >= 45; el acento se mantiene dentro del rango del preajuste (los degradados saturados y las superposiciones de marca cuentan como acento); el primario mantiene >= 70% del área de acento para que un tono de acción lidere; los colores semánticos <= 2% en reposo; los temas oscuros mantienen el neutro >= 70. Los preajustes de estado (subtle 8/14/50, standard 12/20/60, strong 16/26/70 como porcentajes mínimos para hover/active/disabled, tintes 8/10/14) se elevan por paleta mediante states hasta que el paso sea visible. Rangos, reglas A1-A7 y S1-S6, lógica de dirección y el fragmento de medición: references/proportions-and-states.md.
Modo oscuro
Un tema oscuro es una segunda paleta, nunca una inversión. El motor impone las reglas medibles (node $S dark ..., también ejecutado por generate y audit); el resto son reglas de implementación para aplicar a mano. Tabla completa con umbrales y correcciones: references/dark-mode-rules.md.
Medido (FAIL bloquea; WARN necesita una razón declarada):
- D1 bg no es negro puro: OKLCH L 0.13-0.24 (el verdadero
#000solo para una variante OLED declarada). - D2 el texto no es blanco puro: L 0.88-0.95. D3 texto/bg <= 17:1.
- D4 elevación por claridad: bg < surface < surface-2, aproximadamente +0.04 L por paso; las sombras no elevan en oscuro.
- D5 neutros matizados, chroma de bg <= 0.045.
- D6 el primario es un relleno claro (L >= 0.70) con on-primary oscuro, o un relleno profundo (L <= 0.58) con on-primary blanco; la banda 0.58-0.68 es una zona muerta. El relleno necesita 3:1 sobre bg y surface.
- D7 contra el tema claro: mismo tono (dentro de 10 grados), más claro, croma no más alto (reducir 10-30%).
- D8 colores de estado reajustados para oscuro: 4.5:1 sobre bg y sobre la superficie elevada, con icono y texto.
- D9 border-strong 3:1; los bordes decorativos siguen siendo visibles (dL >= 0.05). D11 anillo de foco 3:1.
- D10 APCA consultivo: texto |Lc| >= 75, atenuado >= 45 (apunta a 60); la polaridad oscura expone texto fino que WCAG 2 aprueba.
A mano: nunca uses filter: invert (N1); aclara en hover en lugar de oscurecer (N3); sin texto alfa (N4); atenúa fotos brillantes y envía variantes de logotipo claro/monocromo (N5); evita tipos pequeños y finos (N6); establece color-scheme y theme-color por esquema (N8); sigue el SO con un conmutador de tres estados y sin destello (N9); vuelve a comprobar los colores de los gráficos en la superficie oscura (N10). El modo claro se lee mejor para la mayoría de los usuarios con visión normal y el modo oscuro ayuda a algunos usuarios con baja visión, así que ofrece ambos. Paletas oscuras de referencia y arquitectura de tokens: references/dark-mode-and-tokens.md.
Antipatrones a detectar
Tres o más tonos saturados en el chrome; el tono de CTA reutilizado para encabezados, iconos e insignias; complementos saturados con la misma L (los bordes vibran); texto gris sobre fondos de color (usa el tono del fondo con L ajustada); texto gris claro sobre blanco roto "minimalista" por debajo de 4.5:1; acento de L media con texto blanco; outline: none sin reemplazo; estados hover y active que difieren por un pequeño cambio de tono (cambia L en 0.05-0.10); deshabilitado que parece habilitado; el mismo color de marca saturado reutilizado sin cambios en modo oscuro;
...