You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1094 lines
30 KiB
1094 lines
30 KiB
@import './fuentes.css';
|
|
@import './marca.css';
|
|
@import './tokens.css';
|
|
@import './controles.css';
|
|
/*
|
|
* ---------------------------------------------------------------------------
|
|
* DIRECCIÓN VISUAL
|
|
* ---------------------------------------------------------------------------
|
|
* Los colores de marca: azul marino oscuro aterciopelado y dorado.
|
|
*
|
|
* El marino lleva croma de verdad (0,04) en lugar de ser un gris azulado: eso
|
|
* es lo que le da el aspecto de terciopelo en vez de el de pizarra. Todos los
|
|
* fondos comparten el mismo tono, así que la profundidad la marca la claridad,
|
|
* nunca un cambio de color.
|
|
*
|
|
* El dorado es el único acento y lo llevan las cosas accionables; nada más lo
|
|
* usa, que es lo que hace que se note.
|
|
*
|
|
* Se compromete con un solo modo, sin variante clara: la portada es un fondo a
|
|
* sangre con texto encima y esa composición no sobrevive a un fondo blanco sin
|
|
* rehacerla entera. `color-scheme: dark` avisa al navegador para que sus
|
|
* controles vayan a juego.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
:root {
|
|
color-scheme: dark;
|
|
|
|
/* Marino, del más hondo al más cercano. Mismo tono, distinta claridad. */
|
|
|
|
/* Blancos apenas teñidos: por encima de 0,02 de croma dejarían de leerse
|
|
como blancos y competirían con el dorado. */
|
|
|
|
/*
|
|
* El oro. El plano de antes tiraba a amarillo; este baja de claridad y sube
|
|
* de croma, que es lo que separa un metal de un color de rotulador.
|
|
*/
|
|
/*
|
|
* El metal de la marca no cambia con el tema. Los acentos funcionales sí
|
|
* pueden adaptarse al fondo claro, pero el logotipo conserva estas tres
|
|
* tintas exactas en ambos modos.
|
|
*/
|
|
|
|
--c-accent: var(--c-marca-oro);
|
|
--c-form-action: oklch(0.8 0.095 230);
|
|
--c-form-action-hover: oklch(0.86 0.075 230);
|
|
--c-form-action-text: oklch(0.22 0.05 255);
|
|
--c-toggle-active: oklch(0.76 0.13 155);
|
|
--c-toggle-text: oklch(0.2 0.045 155);
|
|
--c-toggle-rail: var(--c-bg-raised);
|
|
--c-accent-text: oklch(0.16 0.042 264);
|
|
/*
|
|
* El dorado como superficie va aparte del dorado como texto, porque no
|
|
* pueden ser el mismo valor: relleno necesita ser claro para que encima se
|
|
* lea el marino, y escrito necesita ser oscuro para leerse sobre el fondo.
|
|
* En el tema oscuro coinciden; en el claro no, y por eso existe la
|
|
* distinción.
|
|
*/
|
|
--c-accent-superficie: var(--c-marca-oro);
|
|
/* Los dos extremos del reflejo: la luz que lo cruza y la sombra del canto. */
|
|
--c-accent-brillo: var(--c-marca-oro-brillo);
|
|
--c-accent-sombra: var(--c-marca-oro-sombra);
|
|
--c-accent-borde: var(--c-accent-sombra);
|
|
/* Los controles finos necesitan contraste incluso en la zona de brillo. */
|
|
--c-control-oro: var(--c-marca-oro);
|
|
--c-control-oro-brillo: var(--c-marca-oro-brillo);
|
|
--c-control-oro-sombra: var(--c-marca-oro-sombra);
|
|
|
|
/*
|
|
* El verdemar: el tercer color de la paleta, para datos.
|
|
*
|
|
* El mapa necesitaba dos intensidades de algo que no fuera el dorado, y
|
|
* mezclarlo con el fondo marino daba barro —literalmente un marrón sucio—.
|
|
* Este es de la misma familia que el marino, un paso hacia el verde, así que
|
|
* conviven sin pelearse; y deja el dorado para lo que se pulsa y lo que se
|
|
* elige, que es su trabajo en el resto del sitio.
|
|
*/
|
|
--c-dato: oklch(0.74 0.09 198);
|
|
/* El mismo tono, un paso por debajo: «también se canta aquí», no otro dato. */
|
|
--c-dato-tenue: oklch(0.66 0.085 198);
|
|
--c-dato-vacio: oklch(0.29 0.03 255);
|
|
|
|
/*
|
|
* Dos familias: una serif con carácter para los títulos y para la letra de
|
|
* las canciones —que es texto para leer despacio— y una sans de rejilla
|
|
* para interfaz, datos y navegación.
|
|
*/
|
|
--font-versos: var(--font-display);
|
|
|
|
/*
|
|
* El oro de una superficie no es un color plano: un metal refleja, y lo que
|
|
* lo hace parecer metal es la banda de luz que lo cruza. Cinco paradas —de
|
|
* la sombra del canto al brillo y otra vez a la sombra— bastan para
|
|
* sugerirlo sin que parezca un tubo de cromo.
|
|
*
|
|
* El fondo se pinta más alto que el elemento a propósito: así, al acercar el
|
|
* puntero, se desplaza y la luz recorre la pieza en vez de limitarse a
|
|
* aclararla. Es la diferencia entre algo que se ilumina y algo que gira.
|
|
*/
|
|
--gradiente-oro: linear-gradient(
|
|
166deg,
|
|
var(--c-accent-sombra) 0%,
|
|
var(--c-accent-superficie) 24%,
|
|
var(--c-accent-brillo) 46%,
|
|
var(--c-accent-superficie) 64%,
|
|
var(--c-accent-sombra) 100%
|
|
);
|
|
|
|
/*
|
|
* El metal propio del logotipo. Usa los colores fijos de marca en vez de los
|
|
* acentos funcionales del tema: cambiar el fondo no debe convertir el logo en
|
|
* otro dorado ni aplanar su banda de luz.
|
|
*/
|
|
--oro-escrito: linear-gradient(
|
|
166deg,
|
|
var(--c-marca-oro-sombra) 0%,
|
|
var(--c-marca-oro) 24%,
|
|
var(--c-marca-oro-brillo) 46%,
|
|
var(--c-marca-oro) 64%,
|
|
var(--c-marca-oro-sombra) 100%
|
|
);
|
|
|
|
/*
|
|
* El mismo metal, orientado de izquierda a derecha para controles lineales:
|
|
* barras de progreso, volumen y barras de desplazamiento. Esta gama se
|
|
* oscurece en claro para que incluso el reflejo se distinga del carril.
|
|
*/
|
|
--oro-control: linear-gradient(
|
|
90deg,
|
|
var(--c-control-oro-sombra) 0%,
|
|
var(--c-control-oro) 32%,
|
|
var(--c-control-oro-brillo) 52%,
|
|
var(--c-control-oro) 72%,
|
|
var(--c-control-oro-sombra) 100%
|
|
);
|
|
--oro-control-pulgar: radial-gradient(
|
|
circle at 34% 28%,
|
|
var(--c-control-oro-brillo) 0 12%,
|
|
var(--c-control-oro) 46%,
|
|
var(--c-control-oro-sombra) 100%
|
|
);
|
|
|
|
/*
|
|
* Los botones. Un solo tamaño y un solo relleno, porque antes convivían tres
|
|
* —el dorado a 16px con relleno 8/16, el de al lado a 14px con 12/24— y dos
|
|
* botones juntos con distinta letra se ven como un descuido.
|
|
*
|
|
* 15px es el mismo cuerpo del menú: lo pulsable se lee igual en todas
|
|
* partes.
|
|
*/
|
|
--boton-texto: 0.9375rem;
|
|
--boton-relleno: var(--sp-3) var(--sp-5);
|
|
/* La versión reducida, para las esquinas de una tarjeta o una fila. */
|
|
--boton-texto-corto: 0.8125rem;
|
|
--boton-relleno-corto: var(--sp-2) var(--sp-3);
|
|
/*
|
|
* El ancho útil: 1184px. Se probó a subirlo a 88rem (1408px) para aprovechar
|
|
* los monitores anchos y salió al revés: la prosa tiene una medida de
|
|
* lectura y no crece con el contenedor, así que lo único que se ensanchó
|
|
* fue el hueco a su derecha. En la página legal se veía a la legua.
|
|
*
|
|
* Si algún día se ensancha, hay que dar antes a cada texto una columna que
|
|
* crezca con él; sin eso, más ancho es más vacío.
|
|
*/
|
|
--container: 74rem;
|
|
|
|
/* Alto de la barra del reproductor: lo usa el padding inferior del layout. */
|
|
--player-height: 88px;
|
|
|
|
/*
|
|
* Altura aproximada de la cabecera, que ahora es pegajosa. No la mide nadie:
|
|
* es una referencia para separar de ella las anclas y las barras laterales
|
|
* que también se quedan fijas. Si cambia el espaciado de la cabecera, este
|
|
* número la sigue.
|
|
*/
|
|
--altura-cabecera: 4.75rem;
|
|
}
|
|
|
|
/*
|
|
* La inversión clara, y SOLO cuando se pide.
|
|
*
|
|
* El marino es el modo por defecto se pida lo que se pida al sistema, y no es
|
|
* un descuido: es la marca. Un sitio cuyo color forma parte de lo que cuenta no
|
|
* puede salir en blanco porque el portátil de quien entra venga configurado
|
|
* así; y al revés que en una herramienta de trabajo, aquí nadie va a pasar ocho
|
|
* horas seguidas leyendo. Antes esto seguía a `prefers-color-scheme` y llevaba
|
|
* a que media parte de las visitas viera una versión que no es la del sitio.
|
|
*
|
|
* El claro sigue entero y a un clic, en el botón de la cabecera, y la elección
|
|
* se recuerda. Lo que se deja de hacer es decidirlo por nadie a partir de una
|
|
* preferencia que se configuró pensando en otra cosa.
|
|
*
|
|
* Es una inversión de verdad, no un fondo blanco con lo mismo encima: el texto
|
|
* pasa a ser el propio marino y los fondos, blancos apenas teñidos de él. Así
|
|
* los dos modos son la misma marca vista de dos maneras.
|
|
*
|
|
* El dorado tiene que bajar de claridad aquí. El de 0,82 se lee bien sobre
|
|
* marino y desaparece sobre blanco, así que este es un dorado más hondo, casi
|
|
* bronce, que mantiene el contraste como texto.
|
|
*/
|
|
:root[data-tema='claro'] {
|
|
--c-toggle-active: oklch(0.43 0.09 155);
|
|
--c-toggle-text: oklch(0.99 0.005 155);
|
|
--c-form-action: oklch(0.3 0.075 255);
|
|
--c-form-action-hover: oklch(0.37 0.085 255);
|
|
--c-form-action-text: oklch(0.98 0.005 255);
|
|
color-scheme: light;
|
|
--c-bg: oklch(0.98 0.008 264);
|
|
--c-bg-raised: oklch(0.955 0.011 264);
|
|
--c-bg-sunken: oklch(0.915 0.016 264);
|
|
--c-border: oklch(0.86 0.02 264);
|
|
|
|
--c-text: oklch(0.24 0.055 264);
|
|
--c-text-muted: oklch(0.48 0.038 264);
|
|
|
|
--c-accent: oklch(0.42 0.135 70);
|
|
--c-accent-superficie: oklch(0.76 0.13 82);
|
|
--c-accent-text: oklch(0.24 0.055 264);
|
|
--c-accent-brillo: oklch(0.9 0.1 92);
|
|
--c-accent-sombra: oklch(0.63 0.12 74);
|
|
--c-accent-borde: var(--c-accent);
|
|
--c-control-oro: oklch(0.46 0.1 78);
|
|
--c-control-oro-brillo: oklch(0.58 0.11 78);
|
|
--c-control-oro-sombra: oklch(0.4 0.09 78);
|
|
|
|
/* En claro se invierten: el dato pintado tiene que ser oscuro sobre papel. */
|
|
--c-dato: oklch(0.5 0.085 200);
|
|
/* El mismo tono, un paso por debajo: «también se canta aquí», no otro dato. */
|
|
--c-dato-tenue: oklch(0.62 0.08 200);
|
|
--c-dato-vacio: oklch(0.93 0.012 255);
|
|
|
|
--c-danger: oklch(0.5 0.17 25);
|
|
--c-focus: oklch(0.5 0.13 264);
|
|
}
|
|
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
-webkit-text-size-adjust: 100%;
|
|
/*
|
|
* Sin esto, un enlace a un ancla dejaría su destino debajo de la cabecera
|
|
* pegajosa. Vale para los saltos con teclado y para el enlace de saltar al
|
|
* contenido, no solo para los `#` escritos a mano.
|
|
*/
|
|
scroll-padding-top: calc(var(--altura-cabecera) + var(--sp-4));
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--c-bg);
|
|
color: var(--c-text);
|
|
font-family: var(--font-body);
|
|
font-size: var(--fs-base);
|
|
line-height: var(--leading-body);
|
|
-webkit-font-smoothing: antialiased;
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
|
|
/*
|
|
* Los desplazamientos forman parte de la interfaz visible. Se pintan con el
|
|
* oro adaptado al fondo. Las reglas WebKit aportan el reflejo metálico;
|
|
* `scrollbar-color` conserva su contraste en Firefox.
|
|
*/
|
|
* {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--c-control-oro) var(--c-bg-sunken);
|
|
}
|
|
|
|
*::-webkit-scrollbar {
|
|
width: 0.65rem;
|
|
height: 0.65rem;
|
|
}
|
|
|
|
*::-webkit-scrollbar-track {
|
|
background: var(--c-bg-sunken);
|
|
border-radius: var(--radius-round);
|
|
}
|
|
|
|
*::-webkit-scrollbar-thumb {
|
|
min-width: 2.5rem;
|
|
border: 2px solid var(--c-bg-sunken);
|
|
border-radius: var(--radius-round);
|
|
background-color: var(--c-control-oro);
|
|
background-image: var(--oro-control);
|
|
}
|
|
|
|
*::-webkit-scrollbar-thumb:hover {
|
|
background-color: var(--c-control-oro-brillo);
|
|
}
|
|
|
|
/*
|
|
* Primitiva compartida por progreso y volumen. La zona recorrida usa el metal
|
|
* de marca; la pendiente conserva su tamaño con `background-size`, de modo que
|
|
* el brillo acaba siempre dentro de la parte ya recorrida.
|
|
*/
|
|
.rango-dorado {
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
height: 1rem;
|
|
background: transparent;
|
|
accent-color: var(--c-control-oro);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rango-dorado::-webkit-slider-runnable-track {
|
|
height: 5px;
|
|
border: 1px solid var(--c-control-oro-sombra);
|
|
border-radius: var(--radius-round);
|
|
background-color: var(--c-bg-sunken);
|
|
background-image: var(--oro-control);
|
|
background-repeat: no-repeat;
|
|
background-size: var(--avance, 0%) 100%;
|
|
}
|
|
|
|
.rango-dorado::-moz-range-track {
|
|
height: 5px;
|
|
border: 1px solid var(--c-control-oro-sombra);
|
|
border-radius: var(--radius-round);
|
|
background: var(--c-bg-sunken);
|
|
}
|
|
|
|
.rango-dorado::-moz-range-progress {
|
|
height: 5px;
|
|
border-radius: var(--radius-round);
|
|
background-color: var(--c-control-oro);
|
|
background-image: var(--oro-control);
|
|
}
|
|
|
|
.rango-dorado::-webkit-slider-thumb {
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
width: 14px;
|
|
height: 14px;
|
|
margin-top: calc((var(--sp-1) + var(--gap-hairline)) * -1);
|
|
border: 1px solid var(--c-control-oro-sombra);
|
|
border-radius: var(--radius-round);
|
|
background-color: var(--c-control-oro);
|
|
background-image: var(--oro-control-pulgar);
|
|
box-shadow: 0 0 0 2px var(--c-bg-raised);
|
|
}
|
|
|
|
.rango-dorado::-moz-range-thumb {
|
|
width: 14px;
|
|
height: 14px;
|
|
border: 1px solid var(--c-control-oro-sombra);
|
|
border-radius: var(--radius-round);
|
|
background-color: var(--c-control-oro);
|
|
background-image: var(--oro-control-pulgar);
|
|
box-shadow: 0 0 0 2px var(--c-bg-raised);
|
|
}
|
|
|
|
.rango-dorado:hover::-webkit-slider-thumb,
|
|
.rango-dorado:focus-visible::-webkit-slider-thumb,
|
|
.rango-dorado:hover::-moz-range-thumb,
|
|
.rango-dorado:focus-visible::-moz-range-thumb {
|
|
box-shadow:
|
|
0 0 0 2px var(--c-bg-raised),
|
|
0 0 0 4px color-mix(in oklab, var(--c-control-oro) 25%, transparent);
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4 {
|
|
font-family: var(--font-display);
|
|
line-height: var(--leading-heading);
|
|
margin: 0 0 var(--sp-3);
|
|
font-weight: var(--font-weight-regular);
|
|
letter-spacing: -0.015em;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
h1 {
|
|
font-size: var(--fs-3xl);
|
|
}
|
|
h2 {
|
|
font-size: var(--fs-2xl);
|
|
}
|
|
h3 {
|
|
font-size: var(--fs-xl);
|
|
}
|
|
|
|
p {
|
|
margin: 0 0 var(--sp-4);
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
a {
|
|
color: inherit;
|
|
text-underline-offset: 0.2em;
|
|
transition: color var(--duration-normal) var(--ease-standard);
|
|
}
|
|
|
|
/*
|
|
* Todo enlace responde al puntero. Antes no había ninguna regla global, así que
|
|
* los enlaces sin estilo propio —el del feed, los del pie— no daban ninguna
|
|
* señal de ser pulsables. El dorado es el color de lo accionable en esta web,
|
|
* así que es el que corresponde.
|
|
*
|
|
* Los componentes que ya deciden su propio color al pasar por encima ganan por
|
|
* especificidad: esto es el suelo, no una imposición.
|
|
*/
|
|
a:hover {
|
|
color: var(--c-accent);
|
|
}
|
|
|
|
/* Selección exclusiva: una barra común y un segmento verde activo. */
|
|
.toggle-rail {
|
|
display: inline-flex;
|
|
max-width: 100%;
|
|
padding: calc(var(--sp-1) - var(--gap-hairline));
|
|
gap: var(--sp-1);
|
|
border: 1px solid var(--c-border);
|
|
border-radius: var(--radius-overlay);
|
|
background: var(--c-toggle-rail);
|
|
}
|
|
.toggle-rail__option {
|
|
display: inline-flex;
|
|
flex: 1 1 auto;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--sp-2);
|
|
min-width: 0;
|
|
min-height: var(--control-height-compact);
|
|
padding: var(--sp-1) var(--sp-3);
|
|
border: 0;
|
|
border-radius: var(--radius-tarjeta);
|
|
background: transparent;
|
|
color: var(--c-text-muted);
|
|
font: inherit;
|
|
font-size: var(--boton-texto);
|
|
font-weight: var(--font-weight-regular);
|
|
letter-spacing: 0.01em;
|
|
line-height: var(--leading-ui);
|
|
cursor: pointer;
|
|
transition:
|
|
background-color var(--duration-normal) var(--ease-standard),
|
|
color var(--duration-normal) var(--ease-standard);
|
|
}
|
|
.toggle-rail__option:hover {
|
|
color: var(--c-text);
|
|
}
|
|
.toggle-rail__option[aria-pressed='true'] {
|
|
background: var(--c-toggle-active);
|
|
color: var(--c-toggle-text);
|
|
}
|
|
.toggle-rail__option:focus-visible {
|
|
outline: 2px solid var(--c-toggle-active);
|
|
outline-offset: 2px;
|
|
}
|
|
.toggle-rail__option:disabled {
|
|
cursor: not-allowed;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
/* Los formularios usan azul; las acciones de reproducción conservan el oro. */
|
|
.btn.btn--form-primary {
|
|
background: var(--c-form-action);
|
|
border-color: var(--c-form-action);
|
|
color: var(--c-form-action-text);
|
|
box-shadow: none;
|
|
transition:
|
|
background-color var(--duration-normal) var(--ease-standard),
|
|
border-color var(--duration-normal) var(--ease-standard);
|
|
}
|
|
.btn.btn--form-primary:hover {
|
|
background: var(--c-form-action-hover);
|
|
border-color: var(--c-form-action-hover);
|
|
color: var(--c-form-action-text);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
a {
|
|
transition: none;
|
|
}
|
|
}
|
|
|
|
img {
|
|
max-width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
}
|
|
|
|
ul,
|
|
ol {
|
|
margin: 0 0 var(--sp-4);
|
|
padding-left: var(--sp-5);
|
|
}
|
|
|
|
button {
|
|
font: inherit;
|
|
color: inherit;
|
|
}
|
|
|
|
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
|
|
outline: 2px solid var(--c-focus);
|
|
outline-offset: 2px;
|
|
border-radius: var(--radius-detail);
|
|
}
|
|
|
|
/* --- primitivas de layout ------------------------------------------------ */
|
|
|
|
.container {
|
|
width: 100%;
|
|
max-width: var(--container);
|
|
margin-inline: auto;
|
|
padding-inline: var(--sp-4);
|
|
}
|
|
|
|
.stack > * + * {
|
|
margin-top: var(--sp-4);
|
|
}
|
|
|
|
.muted {
|
|
color: var(--c-text-muted);
|
|
}
|
|
|
|
.eyebrow {
|
|
font-size: var(--fs-xs);
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--c-text-muted);
|
|
margin: 0 0 var(--sp-2);
|
|
}
|
|
|
|
.entradilla-pagina {
|
|
max-width: 56ch;
|
|
color: var(--c-text-muted);
|
|
font-size: var(--fs-lg);
|
|
font-weight: var(--font-weight-regular);
|
|
}
|
|
|
|
.visually-hidden {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
padding: 0;
|
|
margin: calc(var(--gap-hairline) * -1);
|
|
overflow: hidden;
|
|
clip-path: inset(50%);
|
|
white-space: nowrap;
|
|
border: 0;
|
|
}
|
|
|
|
.btn {
|
|
/*
|
|
* `background-color` y no el atajo `background`: el atajo reinicia también
|
|
* `background-image`, así que una variante con degradado —el botón dorado—
|
|
* lo perdía en cuanto esta regla o la de `:hover` se aplicaban, y se quedaba
|
|
* en un rectángulo oscuro con el borde de oro.
|
|
*/
|
|
background-color: transparent;
|
|
transition:
|
|
background-color 0.2s var(--ease-standard),
|
|
border-color 0.2s var(--ease-standard);
|
|
}
|
|
|
|
/*
|
|
* El botón secundario acusa el puntero con el fondo y el canto, no con el
|
|
* color del texto: teñirlo de dorado además sería una señal doble, y encima
|
|
* competiría con el botón dorado que suele tener al lado. El color se declara
|
|
* aquí para ganarle a la regla general de los enlaces, ya que muchos de estos
|
|
* botones lo son.
|
|
* La condición de disponibilidad no suma especificidad: las variantes de
|
|
* color deben conservar su texto, fondo y borde propios también en hover.
|
|
*/
|
|
.btn:hover:where(:not(:disabled)) {
|
|
background-color: var(--c-bg-raised);
|
|
border-color: var(--c-text-muted);
|
|
color: inherit;
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.45;
|
|
cursor: default;
|
|
}
|
|
|
|
/* --- diálogos ------------------------------------------------------------
|
|
*
|
|
* Una sola carcasa para acceso, contacto y búsqueda. El borde no forma parte
|
|
* del diálogo: la separación del plano inferior la dan el fondo y la sombra.
|
|
*/
|
|
.modal-screen {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
height: 100%;
|
|
max-height: 100%;
|
|
margin: 0;
|
|
padding: var(--sp-4);
|
|
border: 0;
|
|
background: transparent;
|
|
color: var(--c-text);
|
|
overflow: auto;
|
|
place-items: center;
|
|
}
|
|
|
|
.modal-screen[open] {
|
|
display: grid;
|
|
}
|
|
|
|
.modal-screen::backdrop {
|
|
background: var(--c-overlay);
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.modal-surface {
|
|
position: relative;
|
|
width: 100%;
|
|
border-radius: var(--radius-overlay);
|
|
background: var(--c-bg-raised);
|
|
box-shadow: var(--shadow-modal);
|
|
}
|
|
|
|
.modal-close {
|
|
position: absolute;
|
|
top: var(--sp-3);
|
|
right: var(--sp-3);
|
|
display: inline-grid;
|
|
place-items: center;
|
|
width: var(--control-height);
|
|
height: var(--control-height);
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: var(--radius-round);
|
|
background: transparent;
|
|
color: var(--c-text-muted);
|
|
cursor: pointer;
|
|
transition:
|
|
background-color var(--duration-normal) var(--ease-standard),
|
|
color var(--duration-normal) var(--ease-standard);
|
|
}
|
|
|
|
.modal-close:hover,
|
|
.modal-close:focus-visible {
|
|
background: var(--c-bg-sunken);
|
|
color: var(--c-text);
|
|
}
|
|
|
|
@media (max-width: 34rem) {
|
|
.modal-screen {
|
|
padding: var(--sp-3);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* El aspecto dorado, aparte del botón que lo estrenó.
|
|
*
|
|
* Lo lleva también el conmutador de vista de la página de música, que no es un
|
|
* `.btn` —va dentro de una barra y no puede tener canto ni esquinas propias—
|
|
* pero sí tiene que ser el mismo oro. Copiarlo era garantizar que un día uno de
|
|
* los dos se quedara plano.
|
|
*/
|
|
.btn--primary,
|
|
.oro {
|
|
/* El color plano queda de reserva: si el degradado no se pintara, el botón
|
|
sigue siendo dorado y legible, no transparente. */
|
|
background-color: var(--c-accent-superficie);
|
|
background-image: var(--gradiente-oro);
|
|
background-size: 100% 240%;
|
|
background-position: 0 22%;
|
|
color: var(--c-accent-text);
|
|
/* El filo de luz de arriba. Sin él, el degradado se ve pintado, no biselado. */
|
|
box-shadow: var(--shadow-control-highlight);
|
|
transition:
|
|
background-position 0.6s var(--ease-emphasized),
|
|
border-color 0.2s var(--ease-standard);
|
|
}
|
|
|
|
/* El canto sí es del botón: dentro de una barra no hay borde que teñir. */
|
|
.btn--primary {
|
|
border-color: var(--c-accent-borde);
|
|
}
|
|
|
|
/*
|
|
* Al acercar el puntero, la luz recorre la pieza. El color de fondo se repite
|
|
* aquí porque `.btn:hover` lo cambia por el gris de los botones normales: sin
|
|
* esto, un dorado que no llegara a pintar el degradado se vería oscuro.
|
|
*/
|
|
.btn--primary:hover,
|
|
.oro:hover {
|
|
background-color: var(--c-accent-superficie);
|
|
background-position: 0 78%;
|
|
border-color: var(--c-accent);
|
|
/*
|
|
* El color se repite aquí porque `.btn:hover` lo pone en `inherit` —para
|
|
* que la regla general de los enlaces no tiña de dorado los secundarios—.
|
|
* Ambas reglas tienen la misma especificidad y esta variante, declarada
|
|
* después, conserva el texto marino sobre el oro.
|
|
*/
|
|
color: var(--c-accent-text);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.btn--primary,
|
|
.oro {
|
|
transition: none;
|
|
}
|
|
}
|
|
|
|
/* --- etiquetas -----------------------------------------------------------
|
|
*
|
|
* La pastilla de una etiqueta. Estaba repetida en cinco sitios con cinco copias
|
|
* del mismo borde redondeado, y se escribe una vez.
|
|
*
|
|
* Va aquí y no en un componente porque a veces es un enlace —lleva a lo que
|
|
* agrupa— y a veces es solo texto: dentro de una tarjeta que ya es clicable,
|
|
* meter enlaces dentro de otro enlace deja una zona donde el clic hace una cosa
|
|
* distinta según el píxel exacto.
|
|
*/
|
|
.chips {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--sp-2);
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.chip {
|
|
display: inline-block;
|
|
padding: var(--sp-1) var(--sp-3);
|
|
border: 1px solid var(--c-border);
|
|
border-radius: var(--radius-boton);
|
|
font-size: var(--fs-xs);
|
|
color: var(--c-text-muted);
|
|
text-decoration: none;
|
|
transition:
|
|
border-color 0.3s var(--ease-standard),
|
|
color 0.3s var(--ease-standard);
|
|
}
|
|
|
|
a.chip:hover,
|
|
a.chip:focus-visible {
|
|
border-color: var(--c-accent);
|
|
color: var(--c-text);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.chip {
|
|
transition: none;
|
|
}
|
|
}
|
|
|
|
/* --- tarjetas ------------------------------------------------------------ */
|
|
|
|
/*
|
|
* El comportamiento de las tarjetas (aparición al entrar en pantalla y
|
|
* respuesta al puntero) vive aquí y no en cada componente: son tres tipos de
|
|
* tarjeta —estilo, álbum y canción— y tenían que moverse igual. Al ser CSS
|
|
* global no hace falta pelearse con el ámbito de Svelte para los atributos que
|
|
* escribe la acción `revelar` en tiempo de ejecución.
|
|
*
|
|
* Sobre el movimiento: nada usa `ease`, que es la curva por defecto y se nota
|
|
* como tal —arranca y frena igual, y todo acaba pareciéndose—. Aquí se sale
|
|
* rápido y se frena largo, que es como se mueve algo que pesa.
|
|
*/
|
|
.tarjeta {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
border: 1px solid var(--c-border);
|
|
border-radius: var(--radius-tarjeta);
|
|
background: var(--c-bg-raised);
|
|
overflow: hidden;
|
|
isolation: isolate;
|
|
transition:
|
|
background-color 0.38s var(--ease-standard),
|
|
border-color 0.32s var(--ease-standard),
|
|
box-shadow 0.42s var(--ease-emphasized);
|
|
}
|
|
|
|
/*
|
|
* El selector de listas es un panel superpuesto que nace dentro de la tarjeta.
|
|
* Mientras está abierto debe poder rebasar sus bordes y quedar sobre las
|
|
* tarjetas vecinas; al cerrarlo se recupera el recorte de portada y efectos.
|
|
*/
|
|
.tarjeta:has(details[open]) {
|
|
z-index: 10;
|
|
overflow: visible;
|
|
}
|
|
|
|
.tarjeta:has(details[open])::before,
|
|
.tarjeta:has(details[open])::after {
|
|
border-radius: inherit;
|
|
}
|
|
|
|
.tarjeta:has(details[open]) .tarjeta__medio {
|
|
border-radius: calc(var(--radius-tarjeta) - 1px) calc(var(--radius-tarjeta) - 1px) 0 0;
|
|
}
|
|
|
|
/*
|
|
* El reflejo. Nace donde está el puntero —lo escribe la acción `brillo` en
|
|
* `--mx` y `--my`— y por eso no se lee como un efecto enlatado. Sin JavaScript
|
|
* las variables no existen y cae arriba en el centro, que es un valor
|
|
* razonable, no un fallo.
|
|
*/
|
|
.tarjeta::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 0;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
background: radial-gradient(
|
|
18rem 18rem at var(--mx, 50%) var(--my, 0%),
|
|
color-mix(in oklab, var(--c-accent) 11%, transparent),
|
|
transparent 72%
|
|
);
|
|
transition: opacity var(--duration-slow) var(--ease-standard);
|
|
}
|
|
|
|
.tarjeta:hover::before,
|
|
.tarjeta:focus-within::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
/*
|
|
* Un destello breve cose visualmente portada y cuerpo al entrar en la tarjeta.
|
|
* Se anima esta capa, no el contenido, de modo que la portada no cambia de
|
|
* posición ni de tamaño. El recorrido solo ocurre una vez por entrada.
|
|
*/
|
|
.tarjeta::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 3;
|
|
pointer-events: none;
|
|
background: linear-gradient(
|
|
112deg,
|
|
transparent 24%,
|
|
color-mix(in oklab, var(--c-accent-brillo) 5%, transparent) 40%,
|
|
color-mix(in oklab, var(--c-accent-brillo) 21%, transparent) 50%,
|
|
color-mix(in oklab, var(--c-accent-brillo) 6%, transparent) 60%,
|
|
transparent 76%
|
|
);
|
|
transform: translateX(-125%);
|
|
opacity: 0;
|
|
}
|
|
|
|
.tarjeta:hover::after,
|
|
.tarjeta:focus-within::after {
|
|
animation: tarjeta-destello var(--duration-reveal) var(--ease-emphasized) both;
|
|
}
|
|
|
|
@keyframes tarjeta-destello {
|
|
0% {
|
|
transform: translateX(-125%);
|
|
opacity: 0;
|
|
}
|
|
18% {
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
transform: translateX(125%);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Aparición al entrar en pantalla, para cualquier elemento con la acción
|
|
* `revelar`. Vive aquí y no en cada componente por dos motivos: lo usan las
|
|
* tarjetas y también las listas del taller, y sobre todo porque el atributo lo
|
|
* escribe la acción en tiempo de ejecución, así que el compilador de Svelte no
|
|
* lo ve en el marcado y podaría la regla como si no se usara.
|
|
*
|
|
* El estado oculto lo pone la acción, nunca el CSS por su cuenta: sin
|
|
* JavaScript no hay atributo y todo se ve directamente.
|
|
*/
|
|
[data-revelar='oculto'] {
|
|
opacity: 0;
|
|
transform: translateY(18px) scale(0.985);
|
|
}
|
|
|
|
[data-revelar='visible'] {
|
|
/*
|
|
* backwards conserva el estado inicial durante el retraso, pero libera
|
|
* transform al terminar. Con both, el último fotograma seguía mandando para
|
|
* siempre y anulaba la respuesta de la tarjeta al puntero.
|
|
*/
|
|
animation: revelarse var(--duration-reveal) var(--ease-emphasized) var(--retraso-revelado, 0ms)
|
|
backwards;
|
|
}
|
|
|
|
@keyframes revelarse {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(18px) scale(0.985);
|
|
filter: blur(6px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: none;
|
|
filter: blur(0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Al acercarse, el borde, la sombra y el reflejo responden sin desplazar la
|
|
* tarjeta. Así la portada permanece anclada y el puntero no provoca saltos.
|
|
*/
|
|
.tarjeta:hover,
|
|
.tarjeta:focus-within {
|
|
background-color: color-mix(in oklab, var(--c-bg-raised) 94%, var(--c-accent));
|
|
border-color: color-mix(in oklab, var(--c-accent) 62%, var(--c-border));
|
|
box-shadow:
|
|
0 2px 8px -5px rgb(0 0 0 / 0.5),
|
|
0 22px 42px -26px rgb(0 0 0 / 0.88),
|
|
0 0 30px -18px color-mix(in oklab, var(--c-accent) 58%, transparent);
|
|
}
|
|
|
|
/* Al pulsar, la sombra se recoge sin mover ni escalar la portada. */
|
|
.tarjeta:active {
|
|
box-shadow:
|
|
0 1px 4px -3px rgb(0 0 0 / 0.5),
|
|
0 10px 22px -20px rgb(0 0 0 / 0.75),
|
|
inset 0 0 0 1px color-mix(in oklab, var(--c-accent) 18%, transparent);
|
|
transition-duration: var(--duration-fast);
|
|
}
|
|
|
|
.tarjeta__medio {
|
|
position: relative;
|
|
aspect-ratio: 1;
|
|
overflow: hidden;
|
|
background: var(--c-bg-sunken);
|
|
}
|
|
|
|
.tarjeta__medio--ancho {
|
|
aspect-ratio: 16 / 10;
|
|
}
|
|
|
|
.tarjeta__medio img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
transform: none;
|
|
transition: none;
|
|
}
|
|
|
|
/* Sombra al pie de la portada, para que el cuerpo no arranque de golpe. */
|
|
.tarjeta__medio::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: auto 0 0;
|
|
height: 45%;
|
|
pointer-events: none;
|
|
background: linear-gradient(
|
|
to top,
|
|
color-mix(in oklab, var(--c-bg) 70%, transparent),
|
|
transparent
|
|
);
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.tarjeta__cuerpo {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-2);
|
|
flex: 1;
|
|
padding: var(--sp-4);
|
|
}
|
|
|
|
.tarjeta__cabecera {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--sp-3);
|
|
}
|
|
|
|
.tarjeta__cabecera > :first-child {
|
|
min-width: 0;
|
|
}
|
|
|
|
/*
|
|
* Hace clicable la tarjeta entera sin envolverla en un enlace, que dejaría los
|
|
* botones dentro de él: ni sería HTML válido ni se podría usar con teclado.
|
|
*/
|
|
.tarjeta__enlace::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 1;
|
|
}
|
|
|
|
/*
|
|
* El subrayado del título crece desde la izquierda en vez de aparecer entero.
|
|
* Va con el fondo y no con un borde para poder animar el ancho sin que la línea
|
|
* cambie de sitio ni empuje al texto.
|
|
*/
|
|
.tarjeta__enlace {
|
|
background-image: linear-gradient(var(--c-accent), var(--c-accent));
|
|
background-repeat: no-repeat;
|
|
background-position: 0 100%;
|
|
background-size: 0 1px;
|
|
transition:
|
|
background-size 0.45s var(--ease-emphasized),
|
|
color 0.3s var(--ease-standard);
|
|
}
|
|
|
|
.tarjeta:hover .tarjeta__enlace,
|
|
.tarjeta:focus-within .tarjeta__enlace {
|
|
color: var(--c-accent);
|
|
background-size: 100% 1px;
|
|
}
|
|
|
|
/* El reproductor vive en el cuerpo y no tapa ningún detalle de la portada. */
|
|
.tarjeta__reproduccion {
|
|
position: relative;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
/*
|
|
* El selector lleva `.tarjeta` delante a propósito: los estilos del botón
|
|
* vienen de un componente y Svelte les añade su clase de ámbito, así que con
|
|
* menos peso no se aplicarían. Las tarjetas comparten la escala compacta de
|
|
* controles, proporcionada al título y al resto de sus acciones.
|
|
*/
|
|
.tarjeta .tarjeta__reproduccion button {
|
|
--lado-play: var(--control-height-compact);
|
|
min-width: var(--lado-play);
|
|
min-height: var(--lado-play);
|
|
width: var(--lado-play);
|
|
height: var(--lado-play);
|
|
padding: 0;
|
|
}
|
|
@media (pointer: coarse) {
|
|
.tarjeta .tarjeta__reproduccion button {
|
|
--lado-play: var(--control-height);
|
|
}
|
|
}
|
|
|
|
/* Lo que se apoya sobre la tarjeta y tiene que quedar por encima del enlace. */
|
|
.tarjeta__encima {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
[data-revelar='visible'] {
|
|
animation: none;
|
|
}
|
|
|
|
.tarjeta,
|
|
.tarjeta::before,
|
|
.tarjeta::after,
|
|
.tarjeta__enlace {
|
|
transition: none;
|
|
animation: none;
|
|
}
|
|
|
|
.tarjeta:hover,
|
|
.tarjeta:focus-within,
|
|
.tarjeta:active {
|
|
transform: none;
|
|
}
|
|
}
|
|
|
|
/* --- términos del glosario ------------------------------------------------
|
|
*
|
|
* El subrayado punteado es la convención de «esto tiene definición» desde
|
|
* mucho antes que la web, y se distingue de un enlace de verdad: un enlace
|
|
* lleva a otra página, esto abre un globo y te deja donde estabas.
|
|
*
|
|
* Va aquí y no en un componente porque el botón lo escribe el servidor dentro
|
|
* del HTML del capítulo, donde el ámbito de Svelte no llega.
|
|
*/
|
|
.termino {
|
|
border: 0;
|
|
padding: 0;
|
|
background: none;
|
|
font: inherit;
|
|
color: inherit;
|
|
cursor: help;
|
|
text-decoration: underline dotted;
|
|
text-decoration-color: color-mix(in oklab, var(--c-accent) 60%, transparent);
|
|
text-underline-offset: 0.2em;
|
|
text-decoration-thickness: 1px;
|
|
}
|
|
|
|
.termino:hover,
|
|
.termino:focus-visible {
|
|
color: var(--c-accent);
|
|
text-decoration-color: var(--c-accent);
|
|
}
|