radionicapp / css /tokens.css
Javier Villarroel
feat: la aurora sustituye a la nebulosa en el cielo
f747c64
Raw History Blame Contribute Delete
14.6 kB
/* ============================================================================
TOKENS — el único archivo de diseño
----------------------------------------------------------------------------
Aquí vive TODO lo que se puede ver: colores, tamaños, tipografía, tiempos,
curvas, sombras y los parámetros del cielo. Ningún otro archivo (ni CSS ni
JS) puede escribir un color, un tamaño o una duración literal.
Hay dos capas, y el orden importa:
1. PRIMITIVOS — la paleta cruda. Nombres de cosas: "noche", "teal".
No dicen para qué sirven. Solo se usan dentro de este archivo.
2. SEMÁNTICOS — nombres de función: "superficie-carta", "texto-tenue".
Es lo ÚNICO que pueden usar los componentes.
Por qué dos capas: si un componente usa --c-noche directamente, el día
que quieras cambiar el estilo entero tendrías que ir componente por
componente. Con la indirección, cambias a qué apunta cada semántico aquí y
el resto del proyecto se entera solo.
Para cambiar el estilo completo: reescribe el bloque SEMÁNTICOS.
Para retocar un color: cambia su primitivo.
AURORA GLASS — la piel actual. Noche profunda, vidrio esmerilado, y tres
acentos de aurora (teal, violeta, rosa) que reaparecen en el cielo
(js/aurora.js) y en el acento de la acción principal. Ya no hay carta de
hueso: todo lo que antes vivía sobre claro ahora vive sobre vidrio, con
tinta clara encima.
========================================================================== */
:root {
/* ── 1. PRIMITIVOS ──────────────────────────────────────────────────── */
/* Noche: el cielo, de arriba abajo */
--c-noche: #070b1f;
--c-noche-2: #0d1336;
--c-noche-rgb: 7 11 31;
--c-noche-2-rgb: 13 19 54;
/* Los tres acentos de la aurora */
--c-teal: #2de2c4;
--c-teal-claro: #9cf3e3;
--c-teal-rgb: 45 226 196;
--c-violeta: #7b5cff;
--c-violeta-rgb: 123 92 255;
--c-rosa: #ff6fa8;
--c-rosa-rgb: 255 111 168;
/* Tinta: el texto, sobre vidrio o sobre noche, siempre claro */
--c-tinta: #eef0ff;
--c-tinta-rgb: 238 240 255;
/* El texto oscuro que va DENTRO del botón teal (necesita contraste sobre
un acento claro, no sobre vidrio). */
--c-tinta-profunda: #061018;
--c-blanco: #fff;
--c-sombra: 0 0 0;
--c-estrella: 255 255 255;
/* Espacio */
--e-0: 0px;
--e-1: 4px;
--e-2: 7px;
--e-3: 9px;
--e-4: 12px;
--e-5: 14px;
--e-6: 16px;
--e-7: 24px;
--e-8: 30px;
--e-9: 34px;
--e-10: 40px;
--e-11: 56px;
/* Tipografía */
--f-familia: "SF Pro Display", "Helvetica Neue", "Segoe UI Variable Display",
"Segoe UI", "Avenir Next", "Nimbus Sans", "Liberation Sans", Arial, sans-serif;
--f-peso-titulo: 200;
--f-peso-claro: 300;
--f-peso-normal: 400;
--f-peso-medio: 500;
--f-xs: 10.5px;
--f-s: 12.5px;
--f-sm: 13.5px;
--f-m: 15px;
--f-md: 15.5px;
--f-l: 17px;
--f-xl: 46px;
--f-alto-apretado: 1.22;
--f-alto-normal: 1.6;
--f-espaciado-titulo: -0.035em;
--f-espaciado-ancho: 0.04em;
/* Radios */
--r-s: 4px;
--r-m: 8px;
--r-l: 16px;
--r-xl: 30px;
--r-pastilla: 27px;
--r-circulo: 50%;
/* Cortes responsivos.
Ojo: CSS no admite var() dentro de @media, así que en los componentes el
número va escrito. Se declaran aquí igualmente porque son una decisión de
diseño, y tests/tokens.test.js comprueba que ningún @media use un corte
que no esté en esta lista. */
--corte-estrecho: 900px;
--corte-movil: 640px;
/* Medidas de pieza */
--m-carta-ancho: 1104px;
--m-carta-alto: 716px;
--m-panel-ancho: 220px;
--m-simbolo: 70px;
--m-simbolo-estrecho: 58px;
--m-simbolo-movil: 52px;
--m-escenario-estrecho: 45dvh;
/* En móvil el lienzo es la puerta de entrada. Tiene un alto fijo para que
no salte al elegir una foto, pero ya no queda subordinado al formulario. */
--m-escenario-movil: 45dvh;
--m-margen-ventana-movil: 26px;
--m-miniatura-alto-movil: 54px;
--m-simbolo-dibujo: 32px;
--m-numero: 19px;
--m-miniatura-ancho: 54px;
--m-miniatura-alto: 62px;
--m-accion-alto: 54px;
--m-anillo: 360px;
--m-difuminado-alto: 180px; /* cuánto abarca la banda de luz */
--m-trazo-simbolo: 1.35;
--m-icono: 44px;
--m-menu-imagen: 224px;
--m-visor-maximo: 92dvh;
--m-intencion-minima: 54px;
--m-intencion-abierta: 132px;
--m-modal-intencion: 520px;
--m-modal-texto: 236px;
--giro-imagen: 0deg;
/* Tiempo */
--t-instante: 0.2s;
--t-retardo-2: 0.15s;
--t-retardo-3: 0.3s;
--t-rapido: 0.22s;
--t-medio: 0.45s;
--t-entrada: 0.7s;
--t-lento: 1.2s;
--t-respiracion: 6s;
--t-parpadeo: 7s;
--t-aplicando: 2800ms; /* lo lee el JS: cuánto dura el aplicar */
/* Curvas */
--curva-suave: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--curva-calma: ease-in-out;
/* Resorte: un rebote breve, para lo que responde a un toque. */
--curva-resorte: cubic-bezier(0.34, 1.56, 0.44, 1);
/* Planeo: entra rápido y frena largo, para lo que se desliza. */
--curva-planeo: cubic-bezier(0.22, 0.8, 0.24, 1);
/* Cielo (lo lee el JS al generar las estrellas) */
--cielo-lejanas: 462;
--cielo-cercanas: 77;
--cielo-semilla: 7;
--cielo-alfa-lejana-min: 0.14;
--cielo-alfa-lejana-max: 0.4;
--cielo-alfa-cercana-min: 0.5;
--cielo-alfa-cercana-max: 0.9;
--cielo-estrella-lejana: 1px;
--cielo-estrella-cercana: 2px;
--cielo-horizonte-alto: 220px;
/* El cielo gira como una bóveda: todo el campo rota despacio alrededor de un
eje que queda por debajo de la pantalla, así que cada estrella describe un
arco y las de cerca del eje se mueven menos que las de arriba. No es una
traslación: nada se desplaza en línea recta.
Para que se mueva más: sube el giro o baja el tiempo. */
--cielo-eje-x: 50vw;
--cielo-eje-y: 140vh;
--cielo-giro: 5deg;
--cielo-deriva: 189s;
--cielo-giro-cercanas: 11deg;
--cielo-deriva-cercanas: 117s;
/* Destellos: de tanto en tanto, una estrella al azar entre estas brilla
de golpe y con fuerza. El JS elige cuál y cuándo (sin período fijo);
acá solo el tamaño, el resplandor y cada cuánto puede tocarle a alguna. */
--cielo-destellos: 14;
--cielo-estrella-destello: 2.5px;
--cielo-destello-resplandor: 5px;
--cielo-destello-duracion: 0.5s;
--cielo-destello-espera-min: 0.12s;
--cielo-destello-espera-max: 0.9s;
/* Aurora (lo lee el JS: color de cada cinta y cuánto deforman la imagen
durante la magia — ver js/aurora.js y js/distorsion.js). La forma de
las cintas (frecuencias, fases, alto) no es un valor de diseño en el
mismo sentido que un color o una duración: vive en el propio módulo. */
--aurora-cinta-1: var(--c-teal);
--aurora-cinta-2: var(--c-violeta);
--aurora-cinta-3: var(--c-rosa);
/* Cuánto se difumina el velo de la magia sobre la imagen. */
--aurora-velo-difuminado: 40px;
/* Cuánto se deforma la imagen en el pico de la magia, como fracción de su
lado corto (0.06 = empuja hasta un 6 %). 0 la deja quieta. */
--aurora-distorsion: 0.06;
/* El velo de la zona de la imagen, sin nada de magia encima. */
--velo-escenario-alfa: 0.28;
/* ── 2. SEMÁNTICOS ──────────────────────────────────────────────────── */
/* Lo único que pueden usar los componentes. */
/* Fondos y superficies */
--fondo-umbral: linear-gradient(
180deg,
var(--c-noche) 0%,
var(--c-noche-2) 100%
);
--fondo-velo-bajo: radial-gradient(
120% 80% at 50% 108%,
rgb(var(--c-teal-rgb) / 0.12) 0%,
rgb(var(--c-teal-rgb) / 0) 62%
);
--fondo-velo-alto: radial-gradient(
90% 60% at 78% -10%,
rgb(var(--c-violeta-rgb) / 0.22) 0%,
rgb(var(--c-violeta-rgb) / 0) 60%
);
/* El punto de rosa. Súbele o bájale el alfa para que se note más o menos. */
--fondo-velo-rosa: radial-gradient(
70% 50% at 22% 82%,
rgb(var(--c-rosa-rgb) / 0.16) 0%,
rgb(var(--c-rosa-rgb) / 0) 65%
);
/* ── El vidrio: la receta que comparten la carta, los iconos de la
imagen, los menús, los círculos de energía y el botón secundario. Cada
componente la vuelve a escribir con estos mismos tokens (no hay mixins
en CSS), pero el valor nace acá una sola vez. */
--vidrio-fondo: linear-gradient(
150deg,
rgba(255, 255, 255, 0.095),
rgba(255, 255, 255, 0.028) 48%,
rgba(255, 255, 255, 0.055)
);
--vidrio-desenfoque: blur(22px) saturate(165%);
--vidrio-sombra:
inset 0 1px 0 rgba(255, 255, 255, 0.2),
inset 0 -1px 0 rgba(255, 255, 255, 0.035),
0 40px 90px -42px rgba(0, 0, 0, 0.7),
0 2px 8px rgba(0, 0, 0, 0.18);
/* El borde de 1px: un degradado recortado con mask, no un `border` plano. */
--vidrio-borde-degradado: linear-gradient(
158deg,
rgba(255, 255, 255, 0.52),
rgba(255, 255, 255, 0.09) 26%,
rgba(255, 255, 255, 0.02) 58%,
rgba(255, 255, 255, 0.24)
);
--vidrio-grano-tamano: 180px;
--vidrio-grano-opacidad: 0.075;
/* El ruido en sí lo pone js/cielo.js al arrancar (un lienzo 128×128 al
azar, una sola vez): acá solo el valor por defecto, sin ruido. */
--grano: none;
--superficie-carta: var(--vidrio-fondo);
/* La zona de la imagen es translúcida y oscura: el cielo se ve también
dentro de la carta. */
--superficie-escenario: rgb(var(--c-noche-rgb) / var(--velo-escenario-alfa));
--superficie-simbolo: var(--vidrio-fondo);
/* Texto sobre la noche */
--texto-noche: var(--c-tinta);
--texto-noche-tenue: rgb(var(--c-tinta-rgb) / 0.56);
--texto-noche-apunte: rgb(var(--c-tinta-rgb) / 0.76);
/* Texto sobre la carta: ya no es de vidrio claro sobre hueso, es tinta
clara sobre vidrio oscuro. Misma escala de alfas que el texto de la
noche, porque ahora es la misma superficie. */
--texto-principal: var(--c-tinta);
--texto-tenue: rgb(var(--c-tinta-rgb) / 0.56);
--texto-apagado: rgb(var(--c-tinta-rgb) / 0.56);
--texto-secundario: rgb(var(--c-tinta-rgb) / 0.76);
--texto-marcador: rgb(var(--c-tinta-rgb) / 0.32);
/* Bordes */
--borde-carta: rgb(var(--c-tinta-rgb) / 0.14);
--borde-panel: rgb(var(--c-tinta-rgb) / 0.12);
--borde-sutil: rgb(var(--c-tinta-rgb) / 0.14);
--borde-simbolo: rgb(var(--c-tinta-rgb) / 0.16);
--borde-simbolo-hover: rgb(var(--c-tinta-rgb) / 0.32);
--borde-marcado: rgb(var(--c-tinta-rgb) / 0.24);
/* La zona de la imagen es translúcida y oscura: lo que va encima de ella
se escribe en tinta clara. */
--borde-hueco: rgb(var(--c-tinta-rgb) / 0.32);
--texto-escenario: rgb(var(--c-tinta-rgb) / 0.76);
--texto-escenario-tenue: rgb(var(--c-tinta-rgb) / 0.56);
--texto-escenario-fuerte: var(--c-tinta);
--borde-hueco-fuerte: var(--c-tinta);
--superficie-herramientas: var(--vidrio-fondo);
--superficie-menu: var(--vidrio-fondo);
--borde-menu: rgb(var(--c-tinta-rgb) / 0.14);
--texto-herramientas: var(--c-tinta);
--superficie-barra-imagen: var(--vidrio-fondo);
--texto-barra-imagen: var(--c-tinta);
--borde-barra-imagen: rgb(var(--c-tinta-rgb) / 0.14);
--velo-visor: rgb(var(--c-sombra) / 0.82);
--velo-modal: rgb(var(--c-sombra) / 0.5);
/* Acción principal: la pastilla teal, con el anillo teal cuando resplandece */
--accion-fondo: linear-gradient(120deg, var(--c-teal), var(--c-teal-claro));
--accion-texto: var(--c-tinta-profunda);
--accion-fondo-hover: linear-gradient(120deg, var(--c-teal-claro), var(--c-teal));
--accion-secundaria-borde: rgb(var(--c-tinta-rgb) / 0.24);
--accion-umbral-fondo: var(--c-tinta);
--accion-umbral-texto: var(--c-noche);
--accion-umbral-hover: var(--c-blanco);
/* Símbolos */
--simbolo-trazo: currentColor;
--simbolo-color: rgb(var(--c-tinta-rgb) / 0.56);
--simbolo-color-activo: var(--c-teal);
/* El anillo y el resplandor de la energía elegida. */
--anillo-activo:
0 0 0 2px rgb(var(--c-teal-rgb) / 0.85),
0 0 16px rgb(var(--c-teal-rgb) / 0.55);
/* Sombras */
--sombra-carta: 0 60px 120px -50px rgb(var(--c-sombra) / 0.85);
--sombra-imagen: 0 30px 60px -40px rgb(var(--c-sombra) / 0.6);
/* El momento de aplicar */
--aplicando-anillo: rgb(var(--c-estrella) / 0.32);
/* La banda de luz que recorre la imagen de arriba abajo.
Es una campana: la opacidad sube y baja siguiendo una gaussiana, muestreada
en 21 paradas. Con tres paradas (transparente → luz → transparente) el
degradado es recto y se le ven los bordes, porque la pendiente cambia de
golpe; así no hay ningún borde que ver.
Para subir o bajar la intensidad, toca --revelado-fuerza. */
--revelado-fuerza: 0.55;
--revelado-difuminado: linear-gradient(
180deg,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0132)) 0%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0301)) 5%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0628)) 10%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.1201)) 15%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.2107)) 20%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.3391)) 25%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.5006)) 30%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.6775)) 35%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.8411)) 40%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.9577)) 45%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 1.0000)) 50%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.9577)) 55%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.8411)) 60%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.6775)) 65%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.5006)) 70%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.3391)) 75%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.2107)) 80%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.1201)) 85%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0628)) 90%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0301)) 95%,
rgb(var(--c-estrella) / calc(var(--revelado-fuerza) * 0.0132)) 100%
);
--revelado-suavizado: 18px; /* desenfoque extra, remata los extremos */
--aplicando-cielo-intensidad: 1.55;
/* Horizonte del cielo */
--cielo-horizonte: linear-gradient(
180deg,
rgb(var(--c-noche-rgb) / 0) 0%,
rgb(var(--c-noche-2-rgb) / 0.9) 100%
);
}