/* ------------------------------------------------------------------
   Vinilos — hoja de estilo única. El JavaScript es opcional: sin él la
   página entera sigue funcionando con <details> nativo.
   ------------------------------------------------------------------ */

:root {
  color-scheme: light dark;

  --paper-light: #f7f4ef;
  --paper-dark: #0c0d0f;
  --surface-light: #ffffff;
  --surface-dark: #16181b;
  --sunken-light: #efeae1;
  --sunken-dark: #1a1d21;
  --ink-light: #17181a;
  --ink-dark: #e9e6e1;
  --muted-light: #6a6862;
  --muted-dark: #9b978f;
  --line-light: #e2dcd1;
  --line-dark: #2a2e34;

  --paper: light-dark(var(--paper-light), var(--paper-dark));
  --surface: light-dark(var(--surface-light), var(--surface-dark));
  --sunken: light-dark(var(--sunken-light), var(--sunken-dark));
  --ink: light-dark(var(--ink-light), var(--ink-dark));
  --muted: light-dark(var(--muted-light), var(--muted-dark));
  --line: light-dark(var(--line-light), var(--line-dark));

  --p1: light-dark(#b3341b, #ff8158);
  --p2: light-dark(#8a6210, #e6b04c);
  --p3: light-dark(#1c6670, #5cc3ce);
  --owned: light-dark(#2f6b3d, #74d18d);

  /* `light-dark()` solo acepta colores: usarlo en `opacity` descarta la
     declaración entera y el valor se queda en 1. Por eso este número va en una
     variable propia, con su media query más abajo. Los dos colores de al lado
     sí pueden usarla, y la usan: dejarlos en la media query los ataría al
     sistema operativo si algún día se agrega un selector de tema manual,
     mientras el resto de la página respetaría el forzado. */
  --plato-op: 0.5;
  --plato-surco: light-dark(#00000014, #ffffff1c);
  --plato-brillo: light-dark(#00000010, #ffffff10);

  /* ----------------------------------------------------------------
     Cinco pasos para todo lo que no es un título. Antes había veinte
     tamaños sueltos para estos mismos cinco papeles, con diferencias de
     media décima de rem que no significaban nada y que solo servían para
     que cada retoque agregara un tamaño más.

     fs-1 la letra menuda de las pastillas y las etiquetas de figura
     fs-2 los rótulos en versalita y los datos de la tarjeta
     fs-3 el texto secundario de la ficha, los botones y el pie
     fs-4 el título de la tarjeta y los textos de apoyo
     fs-5 los párrafos de sección

     Los títulos siguen con `clamp()` propio: son fluidos por diseño y no
     entran en esta escala.
     ---------------------------------------------------------------- */
  --fs-1: 0.6875rem;
  --fs-2: 0.75rem;
  --fs-3: 0.8125rem;
  --fs-4: 0.875rem;
  --fs-5: 0.9375rem;

  --shell: min(1160px, 100% - 2.5rem);
  /* El ancho del texto corrido. En el teléfono manda la pantalla; a partir de
     ahí se corta en la medida de lectura, porque la rejilla de discos llega a
     1160px y una línea de ese largo (unos 140 caracteres medidos) hace perder
     el renglón al saltar de línea. */
  --texto: 100%;
  --radius: 12px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Un único easing con rebote corto para todo el movimiento de la página. */
  --resorte: linear(
    0, 0.402 7.4%, 0.711 15.3%, 0.929 23.4%, 1.008 28.3%, 1.067 33.9%,
    1.099 40.2%, 1.104 45.7%, 1.09 52.5%, 1.006 76.7%, 0.995 89.7%, 1
  );

  scrollbar-color: light-dark(#b9b2a6, #3a3f46)
    light-dark(var(--sunken-light), var(--sunken-dark));
}

@media (prefers-color-scheme: dark) {
  :root {
    --plato-op: 0.62;
  }
}

/* La medida de lectura solo hace falta donde hay ancho de sobra: en el
   teléfono el texto ya va tan angosto como la pantalla. */
@media (width >= 48rem) {
  :root {
    --texto: 68ch;
  }
}

@supports not (color: light-dark(#000, #fff)) {
  :root {
    --paper: var(--paper-light);
    --surface: var(--surface-light);
    --sunken: var(--sunken-light);
    --ink: var(--ink-light);
    --muted: var(--muted-light);
    --line: var(--line-light);
    --p1: #b3341b;
    --p2: #8a6210;
    --p3: #1c6670;
    --owned: #2f6b3d;
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --paper: var(--paper-dark);
      --surface: var(--surface-dark);
      --sunken: var(--sunken-dark);
      --ink: var(--ink-dark);
      --muted: var(--muted-dark);
      --line: var(--line-dark);
      --p1: #ff8158;
      --p2: #e6b04c;
      --p3: #5cc3ce;
      --owned: #74d18d;
    }
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* `hidden` no es más que un `display: none` de la hoja del navegador, así que
   cualquier regla de autor que declare `display` le gana en la cascada y el
   elemento se sigue viendo con el atributo puesto.
   Pasó con el buscador: `.barra-busca` lleva `display: contents` y sin
   JavaScript salía un campo de búsqueda que no buscaba nada y un botón de
   disco al azar que no abría ninguno. Le pasaba igual a `.ficha-nav`, que es
   `display: flex`.
   El `!important` es lo que hace que el atributo signifique lo que dice, sin
   tener que acordarse de escribir una regla por cada caso. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  /* La barra de arriba es fija y mide poco más de 3rem: sin esta reserva tapa
     el encabezado de todo lo que se salta, sea un enlace `#disco-...`, el
     disco al azar o el primer resultado del buscador. */
  scroll-padding-block-start: 4.5rem;
}

body {
  margin: 0;
  /* El hueco de la barra fija, que ahora se ve desde el arranque. Reservarlo
     aquí en vez de en el inicio evita que la barra tape el primer título. */
  padding-block-start: 3.5rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* Sin esto, llegar al buscador con el teclado cuesta pasar por las 109
   portadas, que son 109 paradas de tabulación seguidas. */
.saltar {
  position: absolute;
  z-index: 40;
  inset-block-start: 0.4rem;
  inset-inline-start: 0.4rem;
  padding: 0.5rem 0.9rem;
  font-size: var(--fs-3);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--ink);
  border-radius: 999px;
  translate: 0 -200%;
}

.saltar:focus-visible {
  translate: 0;
}

h1,
h2,
h3 {
  line-height: 1.15;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

img {
  max-inline-size: 100%;
  block-size: auto;
}

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Un solo anillo de foco para todo lo que se enfoca. Antes unos controles
   traían contorno y otros solo cambiaban de color, que sobre el papel claro
   casi no se distingue: quien navega con teclado perdía el rastro al pasar de
   una portada a un botón. Va en `:where()` para no ganarle a las reglas que
   además ajustan el desplazamiento. */
:where(a, button, input, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--tone, var(--ink));
  outline-offset: 2px;
}


/* --- estructura -------------------------------------------------- */

/* `display: block` explícito: la clase se pone sobre cualquier elemento, y
   sobre uno en línea ni el ancho ni el margen automático hacen nada. Pasó con
   el mensaje de «sin resultados», que era un <span> y salía pegado al borde
   izquierdo mientras el resto de la página iba centrado. */
.shell {
  display: block;
  width: var(--shell);
  margin-inline: auto;
}

.group,
main > section {
  padding-block: clamp(2.5rem, 6vw, 4rem);
  border-top: 1px solid var(--line);
}

#nota {
  padding-block: clamp(2rem, 4.5vw, 3rem);
}

.note {
  display: grid;
  gap: 0.9rem;
}

.note h2 {
  font-size: clamp(1.2rem, 2.8vw, 1.5rem);
  letter-spacing: -0.015em;
}

.note p {
  color: var(--muted);
  max-width: var(--texto);
  font-size: 1rem;
}

/* ------------------------------------------------------------------
   El glosario cierra la nota. Se separa con una línea porque deja de ser
   texto corrido y pasa a ser una tabla de consulta.
   ------------------------------------------------------------------ */

.glosario {
  margin-block-start: 0.6rem;
  padding-block-start: 1.5rem;
  border-block-start: 1px solid var(--line);
}

.glosario h3 {
  font-size: var(--fs-2);
  font-family: var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  margin: 0 0 1rem;
}

/* Las columnas se acomodan solas: en pantalla ancha caben tres y en el
   teléfono queda una, sin puntos de corte escritos a mano. */
.glosario dl {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.1rem 2rem;
}

.glosario dl > div {
  display: grid;
  gap: 0.15rem;
}

/* Un paso por encima de su definición. El reemplazo por la escala dejó a los
   dos en el mismo tamaño y aplanó la jerarquía que había: el término se
   distinguía por tamaño además de por el grosor y el color. */
.glosario dt {
  font-weight: 600;
  font-size: var(--fs-5);
}

.glosario dd {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-4);
}

.eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.section-head {
  display: grid;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
}

.section-head h2 {
  font-size: clamp(1.6rem, 4vw, 2.35rem);
  letter-spacing: -0.025em;
}

.section-note {
  color: var(--muted);
  max-width: var(--texto);
  font-size: var(--fs-5);
  margin-bottom: 1.5rem;
}

/* --- portada ----------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(3rem, 9vw, 5.5rem) clamp(2.25rem, 5vw, 3.5rem);
  overflow: hidden;
}

/* Sin max-width propio: con `margin-inline: auto` del contenedor, cualquier
   tope centraba el bloque en vez de dejarlo alineado con el resto. */
.hero-inner {
  position: relative;
  z-index: 1;
}

.hero h1 {
  font-size: clamp(2.6rem, 9vw, 4.5rem);
  letter-spacing: -0.04em;
  margin-block: 0.7rem 0.9rem;
}

/* El tope corto es lo que mantiene el texto fuera del disco del fondo: sin
   él la última línea llega hasta el borde y queda encima de los surcos. */
.hero-lead {
  font-size: clamp(1rem, 2.2vw, 1.18rem);
  color: var(--muted);
  max-inline-size: 44ch;
}

/* --- el tocadiscos ------------------------------------------------ */

/* El disco es fondo, y de fondo solo cabe a partir de 48rem: en una pantalla
   estrecha no hay ancho detrás del texto donde ponerlo sin cruzarlo, y sacarlo
   del fondo para colgarlo al final del inicio lo dejaba flotando suelto. */
.plato {
  display: none;
}

.plato-disco {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, var(--p1) 0 6.2%, transparent 6.6%),
    repeating-radial-gradient(
      circle at 50% 50%,
      transparent 0 3px,
      var(--plato-surco) 3px 4px
    ),
    radial-gradient(
      circle at 50% 50%,
      var(--plato-brillo) 0 49.5%,
      transparent 50%
    );
}

/* En la franja de tableta el disco todavía alcanza la barra de progreso, que
   es lo que más abajo llega del bloque de texto, así que ahí va más chico y
   más arriba. El tamaño se interpola en vez de cambiar de tope: con dos reglas
   de topes distintos, al cruzar 64rem pasaba de 22rem a 34rem en un solo píxel
   de ventana y se veía saltar al redimensionar. */
@media (width >= 48rem) {
  .plato {
    display: block;
    position: absolute;
    inset-block-start: -16%;
    inset-inline-end: -10%;
    inline-size: clamp(22rem, 46vw, 34rem);
    aspect-ratio: 1;
    z-index: 0;
    pointer-events: none;
    opacity: var(--plato-op);
    /* De fondo el disco no es un objeto sino una textura: sin negro, sin
       volumen y desvanecido por el borde, para que no se lea como una pieza
       recortada en la esquina. */
    mask-image: radial-gradient(circle at center, #000 58%, transparent 78%);
  }
}

.progress {
  display: grid;
  gap: 0.55rem;
  margin-block-start: clamp(1.75rem, 4vw, 2.5rem);
  max-width: 32rem;
}

.progress-track {
  block-size: 0.6rem;
  border-radius: 999px;
  background: var(--sunken);
  border: 1px solid var(--line);
  overflow: hidden;
}

.progress-track span {
  display: block;
  block-size: 100%;
  inline-size: var(--pct);
  background: var(--owned);
  border-start-end-radius: 999px;
  border-end-end-radius: 999px;
  transform-origin: left center;
}

.progress-labels {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: var(--fs-4);
  color: var(--muted);
}

.progress-labels b {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.progress-done b {
  color: var(--owned);
}

/* --- barra de arriba ---------------------------------------------- */

/* Se ve desde el arranque. Antes entraba al salir el inicio de pantalla, y con
   eso la primera pantalla no daba ninguna señal de que hubiera buscador, saltos
   ni disco al azar. Va fija, y el hueco lo reserva el `padding` del body para
   que no tape nada al principio de la página. */
.barra {
  /* Un tono base propio. `app.js` lo reemplaza por el del grupo que se esté
     viendo, pero arriba del todo todavía no hay ninguno, y ahí cada regla
     caía en su propio valor de reserva: el anillo de foco del botón salía del
     color del texto y su borde del color de acento, dos colores distintos en
     el mismo control. Ese es justo el estado en el que se carga la página. */
  --tone: var(--p1);
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 30;
  background: color-mix(in oklab, var(--paper) 85%, transparent);
  backdrop-filter: blur(14px);
  border-block-end: 1px solid var(--line);
}

.barra-inner {
  display: flex;
  align-items: center;
  gap: 0.5rem 0.75rem;
  padding-block: 0.55rem;
}

/* --- los saltos entre grupos -------------------------------------- */

/* Anclas de verdad: funcionan sin JavaScript. Llevan solo el número porque el
   nombre del grupo no cabe, y ese número es el mismo que encabeza su sección.
   El nombre completo va en el `aria-label` y, en cuanto entras en el grupo, la
   barra lo escribe al lado. */
.saltos {
  display: flex;
  gap: 0.3rem;
  flex: none;
}

/* No crecen a 2,75rem en táctil como el resto de los controles: cuatro de ese
   tamaño más el buscador no caben en un teléfono de 360px, que es un ancho
   demasiado común para romperlo. A 1,7rem quedan en 27px, por encima del
   mínimo exigible de 24, y el presupuesto de 2,75rem se gasta donde sí hay
   sitio y donde fallar el toque cuesta caro: cerrar la ficha y los enlaces
   que salen a las tiendas. */
.salto {
  --tone: var(--muted);
  display: grid;
  place-items: center;
  inline-size: 1.7rem;
  block-size: 1.7rem;
  border-radius: 50%;
  font-family: var(--mono);
  font-size: var(--fs-1);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  color: var(--tone);
  border: 1px solid color-mix(in oklab, var(--tone) 45%, transparent);
}

.salto[data-salto="p1"] { --tone: var(--p1); }
.salto[data-salto="p2"] { --tone: var(--p2); }
.salto[data-salto="p3"] { --tone: var(--p3); }
.salto[data-salto="tengo"] { --tone: var(--owned); }

.salto:hover,
.salto:focus-visible {
  border-color: var(--tone);
  background: color-mix(in oklab, var(--tone) 14%, transparent);
}

/* El grupo que se está viendo va relleno. Lo marca app.js con el mismo
   observador que ya escribe el nombre al lado. */
.salto[aria-current] {
  background: var(--tone);
  border-color: var(--tone);
  color: var(--paper);
}

/* Toda la barra a partir del buscador. Sin JavaScript no existe, y los saltos
   de al lado sí, así que el `hidden` va aquí y no en la barra entera. */
.barra-busca {
  display: contents;
}

.barra-nivel {
  display: none;
  font-family: var(--mono);
  font-size: var(--fs-2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tone, var(--muted));
  white-space: nowrap;
}

/* Se oculta a la vista, no del árbol de accesibilidad: lleva `aria-live` y es
   lo único que anuncia cuántos discos quedan al filtrar. Con `display: none`
   el teléfono, que es donde más se busca, se quedaba sin ese aviso. */
.barra-cuenta {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (width >= 44rem) {
  .barra-nivel {
    display: block;
  }

  .barra-cuenta {
    position: static;
    inline-size: auto;
    block-size: auto;
    overflow: visible;
    clip-path: none;
    font-size: var(--fs-3);
    font-variant-numeric: tabular-nums;
    color: var(--muted);
  }
}

/* Un tope para que en pantalla ancha no se estire a media página, y un mínimo
   para que en el teléfono no se encoja hasta dejar el texto en «Busc». */
.barra-buscar {
  display: block;
  flex: 1 1 8rem;
  max-inline-size: 26rem;
  min-inline-size: 7.5rem;
}

/* El botón del disco al azar: solo el símbolo mientras no sobre ancho. */
.azar-texto {
  display: none;
}

@media (width >= 34rem) {
  .azar-icono {
    display: none;
  }

  .azar-texto {
    display: inline;
  }
}

/* Por debajo de esto ya no caben los saltos y el buscador a la vez, y el
   buscador es lo que no puede faltar: los grupos siguen teniendo su propio
   encabezado unos centímetros más abajo. */
@media (width < 22.5rem) {
  .saltos {
    display: none;
  }
}

.barra input {
  inline-size: 100%;
  font: inherit;
  font-size: var(--fs-4);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
}

.barra input::placeholder {
  color: var(--muted);
}

.barra input:focus-visible {
  outline: 2px solid var(--tone, var(--p1));
  outline-offset: 1px;
  border-color: transparent;
}

.barra button {
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-3);
  font-weight: 500;
  white-space: nowrap;
  color: var(--ink);
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
}

.barra button:hover,
.barra button:focus-visible {
  border-color: var(--tone, var(--p1));
  color: var(--tone, var(--p1));
}

/* No basta con decir que no hay nada: sin una salida, la única forma de volver
   a ver la lista es adivinar que hay que borrar el campo a mano. */
.sin-resultados {
  padding-block: clamp(2rem, 6vw, 4rem);
  color: var(--muted);
  border-top: 1px solid var(--line);
}

.sin-resultados .shell {
  display: grid;
  justify-items: start;
  gap: 1rem;
}

#limpiar {
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-3);
  font-weight: 500;
  color: var(--ink);
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.4rem 0.95rem;
}

#limpiar:hover,
#limpiar:focus-visible {
  border-color: var(--ink);
}

/* --- bloques de prioridad ---------------------------------------- */

/* Los tres bloques se separan con la misma línea que separa las secciones de
   primer nivel: viven dentro de `#quiero`, así que no los alcanza la regla de
   `.group, main > section`.

   El primero la lleva igual que los otros dos. La línea del grupo no le sirve:
   está hasta arriba de `#quiero`, antes de la entrada y de la figura de los
   niveles, así que entre ese trazo y el encabezado del primer bloque quedan
   dos bloques de texto de por medio y el «1» acababa pegado al párrafo. */
.priority {
  --tone: var(--muted);
  padding-block: clamp(2rem, 5vw, 3rem);
  border-top: 1px solid var(--line);
}

#p1 {
  --tone: var(--p1);
}

#p2 {
  --tone: var(--p2);
}

#p3 {
  --tone: var(--p3);
}

#tengo {
  --tone: var(--owned);
}

.priority-head {
  display: grid;
  gap: 0.6rem;
  margin-bottom: 1.6rem;
}

.priority-head h3 {
  font-size: clamp(1.3rem, 3.2vw, 1.7rem);
  letter-spacing: -0.02em;
}

.priority-tag {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.7rem;
  font-size: var(--fs-4);
  color: var(--tone);
  margin: 0;
}

.priority-tag b {
  font-family: var(--mono);
  font-size: var(--fs-2);
  font-weight: 600;
  line-height: 1.5;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding-inline: 0.5rem;
}

.priority-count {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.priority-motive {
  color: var(--muted);
  max-width: var(--texto);
  font-size: var(--fs-5);
}

.priority-edition {
  max-width: var(--texto);
  font-size: var(--fs-4);
  color: var(--tone);
  margin-block-start: 0.2rem;
}

/* --- rejilla de portadas ------------------------------------------ */

.albums {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 1.6rem 1.1rem;
  align-items: start;
}

.album {
  position: relative;
  break-inside: avoid;
}

.album:hover,
.album:focus-within {
  z-index: 4;
}

.album summary {
  display: grid;
  gap: 0.1rem;
  cursor: pointer;
  list-style: none;
}

.album summary::-webkit-details-marker {
  display: none;
}

.album summary:focus-visible {
  outline: 2px solid var(--tone, var(--ink));
  outline-offset: 3px;
  border-radius: 6px;
}

.album-hint {
  font-size: var(--fs-2);
  color: var(--tone, var(--muted));
  margin-top: 0.3rem;
  opacity: 0;
}

.album-hint::after {
  content: " ›";
}

.album summary:hover .album-hint,
.album summary:focus-visible .album-hint,
.album details[open] summary .album-hint {
  opacity: 1;
}

/* Sin hover (táctil) la pista se muestra siempre: es la única señal de que
   la tarjeta se puede abrir. */
@media (hover: none) {
  .album-hint {
    opacity: 1;
  }
}

.album summary:hover .cover,
.album details[open] summary .cover {
  filter: brightness(1.06);
}

.cover {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 0.6rem;
  background: var(--sunken);
  border: 1px solid light-dark(#00000012, #ffffff14);
  box-shadow: 0 1px 2px light-dark(#0000001a, #00000066),
    0 8px 18px -10px light-dark(#00000026, #00000099);
}

.cover-empty {
  display: grid;
  place-items: center;
  position: relative;
  background: repeating-radial-gradient(
      circle at 50% 50%,
      transparent 0 3px,
      light-dark(#00000010, #ffffff12) 3px 4px
    ),
    var(--sunken);
}

.cover-empty i {
  font-style: normal;
  font-family: var(--mono);
  font-size: 1.4rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  background: var(--sunken);
  border-radius: 50%;
  inline-size: 44%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}

.album-artist {
  font-size: var(--fs-2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.35;
}

/* Dos líneas exactas: ni menos ni más. Sin la reserva, el año se queda a
   distinta altura en cada tarjeta según lo que mida el título y la fila entera
   se lee desalineada; sin el recorte, los tres títulos de 109 que pasan de dos
   líneas desalinean su fila igual.

   Recortar aquí no esconde nada: el corte es visual, así que el título entero
   sigue en el árbol de accesibilidad para quien use un lector de pantalla, y
   se lee completo en la ficha, que está a un clic. */
.album-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-size: var(--fs-4);
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.35;
  min-block-size: 2.7em;
}

/* Lo que desalinea el año dentro de una fila es que algo de arriba crezca. El
   título ya no lo hace, porque tiene su reserva de dos líneas. Queda el nombre
   del artista, que se parte en seis de los 109, y esos seis se dejan enteros a
   propósito: recortar «Duke Ellington & John Coltrane» pierde la mitad de la
   información, y en una lista para comprar discos el nombre completo vale más
   que la alineación de su fila. */
.album-meta {
  font-size: var(--fs-2);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  line-height: 1.35;
  margin-top: 0.15rem;
}

#tengo .album-artist {
  color: var(--owned);
}

#tengo .cover {
  box-shadow: 0 1px 2px light-dark(#0000001a, #00000066),
    0 0 0 2px color-mix(in oklab, var(--owned) 55%, transparent);
}

/* --- el panel: lo que se ve sin JavaScript ------------------------- */

/* Flota sobre la rejilla en vez de empujarla: si el panel ocupara sitio, la
   fila entera creceria y dejaria un hueco debajo de las demas tarjetas.

   De base se queda del ancho de su columna, que son 9rem: ensancharlo sacaría
   de la pantalla los de la última columna. Donde hay posicionamiento por
   anclaje eso ya no aplica y el panel se ensancha, más abajo. */
.panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  max-block-size: min(26rem, 60vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 3;
  display: grid;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding: 0.75rem 0.8rem 0.85rem;
  background: var(--surface);
  border: 1px solid var(--tone, var(--line));
  border-radius: 8px;
  box-shadow: 0 14px 34px -14px light-dark(#00000040, #000000cc);
}

/* Con anclaje el panel deja de medir lo que mide su columna. El navegador
   voltea solo los que se saldrían por el borde, que es lo que antes no se
   podía saber en CSS.

   La condición se pone sobre `position-try-fallbacks` y no sobre `anchor-name`
   porque hubo versiones de Chrome que traían el anclaje con el nombre viejo de
   esta propiedad: preguntando por el nombre nuevo se quedan fuera solas.

   `.album` tiene que dejar de ser el bloque contenedor. Si sigue siendo
   `relative`, el panel desborda su tarjeta de 9rem por los dos lados, no hay
   lado bueno al que voltear y el volteo no se activa nunca. Medido: con
   `relative` se salían de pantalla 12 de 24 paneles a 360px; sin él, ninguno
   entre 360 y 1920. Su `z-index` de foco se va con el `relative`, y no hace
   falta: los `<details>` comparten `name`, así que nunca hay dos paneles
   abiertos que puedan taparse.

   Nada de `center` en `position-area`: con esa palabra, un panel más ancho que
   su hueco aborta el recorrido de alternativas y se queda en la primera. */
@supports (position-try-fallbacks: flip-inline) {
  .album {
    position: static;
  }

  .album summary {
    anchor-name: --tarjeta;
  }

  .panel {
    position-anchor: --tarjeta;
    position-area: block-end span-inline-end;
    inset: auto;
    inline-size: min(22rem, calc(100vw - 2rem));
    position-try-fallbacks: flip-inline;
  }

  /* Con 22rem las tres pastillas ya caben en fila. */
  .panel .enlaces {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
  }
}

/* Artista y título están justo encima, en la tarjeta: dentro del desplegable
   sobran. Solo aparecen cuando este mismo contenido se clona en la ficha. */
.panel .solo-ficha {
  display: none;
}

/* Con JavaScript el desplegable no se usa nunca: lo reemplaza la ficha. */
.js .panel {
  display: none;
}

.datos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

.dato {
  font-family: var(--mono);
  font-size: var(--fs-1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
}

.dato-ano {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.resena {
  font-size: var(--fs-3);
  color: var(--muted);
  line-height: 1.5;
}

.fuente {
  font-size: var(--fs-2);
}

.fuente a {
  color: var(--tone, var(--ink));
  text-underline-offset: 2px;
}

.bloque {
  display: grid;
  gap: 0.35rem;
}

.bloque-label {
  font-family: var(--mono);
  font-size: var(--fs-1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.bloque-texto {
  font-size: var(--fs-3);
  color: var(--muted);
  line-height: 1.45;
}

/* La edición que hay que descartar. Va con el color del nivel para que no se
   lea como continuación del consejo de arriba, que dice lo contrario. */
.bloque-evitar {
  color: var(--tone, var(--muted));
}

.enlaces {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.enlaces a {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.34rem 0.7rem;
  font-size: var(--fs-3);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.enlaces a::after {
  content: "↗";
  font-size: 0.72em;
  opacity: 0.5;
}

.enlaces a:hover,
.enlaces a:focus-visible {
  border-color: var(--tone, var(--ink));
  color: var(--tone, var(--ink));
}

/* Dentro del panel flotante los enlaces van apilados: la columna mide 9rem y
   tres pastillas en fila quedarían partidas. */
.panel .enlaces {
  display: grid;
  gap: 0.3rem;
}

.panel .enlaces a {
  justify-content: center;
}

/* --- la ficha ------------------------------------------------------ */

/* El color del nivel no llega solo: la ficha vive fuera de la sección, así
   que app.js copia ahí el id y el tono se elige aquí. */
.ficha[data-nivel="p1"] { --tone: var(--p1); }
.ficha[data-nivel="p2"] { --tone: var(--p2); }
.ficha[data-nivel="p3"] { --tone: var(--p3); }
.ficha[data-nivel="tengo"] { --tone: var(--owned); }

.barra[data-nivel="p1"] { --tone: var(--p1); }
.barra[data-nivel="p2"] { --tone: var(--p2); }
.barra[data-nivel="p3"] { --tone: var(--p3); }
.barra[data-nivel="tengo"] { --tone: var(--owned); }

/* Mientras la ficha está abierta la página de detrás no se desplaza. */
:root:has(.ficha[open]) {
  overflow: hidden;
}

/* Filtrando, el texto de arriba estorba: lo que importa son los resultados. */
:root[data-filtrando] #nota,
:root[data-filtrando] .section-note,
:root[data-filtrando] .priority-motive,
:root[data-filtrando] .priority-edition,
/* La cuenta del nivel es el total y contradiría a lo que se ve filtrando. */
:root[data-filtrando] .priority-count {
  display: none;
}

.ficha {
  --tone: var(--p1);
  inline-size: min(54rem, 100% - 1.5rem);
  max-block-size: calc(100dvb - 1.5rem);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 40px 90px -30px light-dark(#00000055, #000000e6);
  overflow: clip;
}

.ficha::backdrop {
  background: light-dark(#2a231bb0, #05060899);
  backdrop-filter: blur(6px);
}

/* Tres piezas colocadas por áreas: en móvil la portada va al lado del título
   y el resto debajo, a todo lo ancho; desde tableta la portada baja por la
   columna izquierda y el resto se apila a su derecha.

   Con áreas y no con `display: contents`: al soltar la cabecera dentro de la
   rejilla, los bloques se repartían solos entre las dos columnas y la ficha
   quedaba desarmada. */
.ficha-cuerpo {
  display: grid;
  grid-template-columns: clamp(5.5rem, 27vw, 7.5rem) minmax(0, 1fr);
  grid-template-areas:
    "arte titulos"
    "texto texto";
  align-content: start;
  gap: 0.9rem;
  padding: 1.1rem;
  max-block-size: calc(100dvb - 1.5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.ficha .solo-ficha {
  display: block;
}

.ficha-arte {
  grid-area: arte;
  display: grid;
  align-content: start;
  gap: 0.7rem;
}

.ficha-arte .cover {
  margin: 0;
  border-radius: 6px;
}

/* Debajo de la portada, que en pantalla ancha es justo donde sobraba sitio:
   la columna de la portada mide 16rem y la ficha es bastante más alta. */
.ficha-nav {
  display: flex;
  gap: 0.4rem;
}

.ficha-nav button {
  appearance: none;
  cursor: pointer;
  flex: 1;
  min-inline-size: 2.75rem;
  min-block-size: 2.75rem;
  display: grid;
  place-items: center;
  font: inherit;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--ink);
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.ficha-nav button:hover:not(:disabled),
.ficha-nav button:focus-visible {
  border-color: var(--tone);
  color: var(--tone);
}

/* En los extremos de la lista no hay a dónde ir. Se apaga en vez de
   desaparecer para que los dos botones no bailen de sitio. */
.ficha-nav button:disabled {
  cursor: default;
  opacity: 0.35;
}

.ficha-titulos {
  grid-area: titulos;
  display: grid;
  align-content: start;
  gap: 0.35rem;
  min-inline-size: 0;
  /* El botón de cerrar flota sobre esta esquina. Sin la reserva, un nombre de
     artista o un título largo se meten por debajo y quedan ilegibles. */
  padding-inline-end: 2.25rem;
}

.ficha-texto {
  grid-area: texto;
  display: grid;
  align-content: start;
  gap: 0.85rem;
  min-inline-size: 0;
}

.ficha-artista {
  font-size: var(--fs-2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tone);
}

.ficha-titulo {
  font-size: clamp(1.15rem, 4.5vw, 1.5rem);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* La reseña se recorta por líneas en vez de por caracteres: así la ficha
   cabe entera en la pantalla del teléfono sin tener que desplazarla, y quien
   quiera el texto completo tiene el enlace justo debajo. */
.ficha .resena {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  overflow: hidden;
  font-size: var(--fs-4);
  max-inline-size: 62ch;
}

@media (height < 44rem) {
  .ficha .resena {
    -webkit-line-clamp: 4;
    line-clamp: 4;
  }
}

.ficha-cerrar {
  position: absolute;
  inset-block-start: 0.55rem;
  inset-inline-end: 0.55rem;
  z-index: 5;
  inline-size: 2rem;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  color: var(--muted);
  background: color-mix(in oklab, var(--surface) 78%, transparent);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line);
  border-radius: 50%;
}

.ficha-cerrar:hover,
.ficha-cerrar:focus-visible {
  color: var(--ink);
  border-color: var(--ink);
}

/* Desde tableta la ficha se abre en dos columnas y la portada crece. La altura
   entra en la condición porque un teléfono en horizontal pasa de sobra el
   ancho y no llega al alto: con la portada de 16rem ahí no quedaba sitio ni
   para una línea de texto sin desplazar. */
@media (width >= 44rem) and (height >= 30rem) {
  .ficha-cuerpo {
    grid-template-columns: 16rem minmax(0, 1fr);
    grid-template-areas:
      "arte titulos"
      "arte texto";
    gap: 1rem 1.8rem;
    padding: 1.6rem 1.7rem;
  }

  .ficha-titulos {
    gap: 0.4rem;
  }

  .ficha-titulo {
    font-size: clamp(1.5rem, 3vw, 2rem);
  }

  .ficha .resena {
    -webkit-line-clamp: 10;
    line-clamp: 10;
    font-size: var(--fs-5);
  }
}

/* --- pie ---------------------------------------------------------- */

footer {
  border-top: 1px solid var(--line);
  padding-block: 2.5rem 3.5rem;
  color: var(--muted);
  font-size: var(--fs-3);
}

footer .shell {
  display: grid;
  gap: 0.5rem;
}

.thanks {
  color: var(--ink);
  font-size: clamp(1rem, 2.4vw, 1.15rem);
  max-width: var(--texto);
  margin-block-end: 0.3rem;
}

/* ==================================================================
   FIGURAS
   Cuatro dibujos que muestran lo que la nota explica en texto. Todo lo
   que se mueve sale de --avance, que va de 0 a 1.

   El valor inicial es 1, la figura terminada. Sin JavaScript, sin
   soporte de animaciones por scroll y con movimiento reducido, la
   figura se ve completa: el movimiento agrega el recorrido, nunca el
   significado.
   ================================================================== */

@property --avance {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

.figura {
  display: grid;
  gap: 0.7rem;
  margin: 0;
}

/* Contenedor con nombre: lo que decide si una figura cabe en una línea es el
   ancho que le queda aquí dentro, no el de la ventana. */
.figura-lienzo {
  container: figura / inline-size;
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(0.9rem, 3vw, 1.5rem);
}

.figura figcaption {
  color: var(--muted);
  font-size: var(--fs-4);
  max-width: var(--texto);
}

/* --- 1. la onda que se aplasta ------------------------------------ */

.onda {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.5rem 0.9rem;
}

/* La onda se estira a lo ancho: son rectángulos, no un dibujo con forma que
   proteger. El único trazo, la silueta, lleva `vector-effect` para no
   deformarse con el estirado. */
.onda-svg {
  inline-size: 100%;
  block-size: clamp(6rem, 16vw, 9rem);
  overflow: visible;
}

/* La silueta es lo que hace que la figura se entienda quieta: sin ella, la
   onda aplastada no dice de dónde viene. Por eso no baja de este contraste. */
.onda-silueta {
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.3;
  stroke-linejoin: round;
  opacity: 0.7;
}

.onda-barras rect {
  fill: var(--p1);
  transform-box: fill-box;
  transform-origin: center;
  transform: scaleY(calc(var(--h0) + (var(--h1) - var(--h0)) * var(--avance)));
}

/* El medidor se encoge al revés que la onda: cuanto más plana, menos rango. */
.onda-medidor {
  display: grid;
  justify-items: center;
  gap: 0.4rem;
  block-size: 100%;
}

.onda-regla {
  inline-size: 3px;
  block-size: 100%;
  min-block-size: 3.5rem;
  border-radius: 999px;
  background: linear-gradient(var(--p1), var(--muted));
  transform-origin: center;
  scale: 1 calc(1 - 0.62 * var(--avance));
}

.onda-regla-texto {
  writing-mode: vertical-rl;
  font-family: var(--mono);
  font-size: var(--fs-1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.onda-etiquetas {
  grid-column: 1;
  display: grid;
  margin: 0;
  font-family: var(--mono);
  font-size: var(--fs-2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Las dos ocupan la misma celda y se relevan en opacidad. */
.onda-etiquetas span {
  grid-area: 1 / 1;
}

/* El relevo es seco, no un cruce: cada una manda en su mitad del recorrido.
   Cruzándolas, a mitad de camino las dos se ven a medias y, como no miden lo
   mismo, sus letras se superponen y lo que se lee es un borrón. */
.onda-antes {
  color: var(--muted);
  opacity: clamp(0, (0.5 - var(--avance)) / 0.5, 1);
}

.onda-despues {
  color: var(--p1);
  opacity: clamp(0, (var(--avance) - 0.5) / 0.5, 1);
}

/* --- 2. la cadena del máster -------------------------------------- */

.cadena {
  display: grid;
  gap: 0.35rem 0;
}

.cadena-via {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.cadena-caja {
  border: 1px solid var(--linea-via, var(--line));
  border-radius: 999px;
  padding: 0.3rem 0.75rem;
  font-size: var(--fs-3);
  white-space: nowrap;
  color: var(--tinta-via, var(--muted));
}

/* Contenedor propio para que el punto de abajo pueda medirse contra el ancho
   de ESTA pista con `cqi`, que es lo que le permite viajar con `translate` en
   vez de recalculando su posición. */
.cadena-pista {
  container-type: inline-size;
  position: relative;
  flex: 1;
  min-inline-size: 2.5rem;
  block-size: 2px;
  border-radius: 999px;
  background: var(--line);
}

/* El punto viajero. Cada pista cubre su mitad del recorrido.

   Se mueve con `translate` y no con `inset-inline-start`: la posición recalcula
   el diseño en cada cuadro, y este punto avanza durante todo el desplazamiento
   por la figura, no una sola vez. El resto de las figuras ya se movía solo con
   `scale` y `opacity`; esta era la excepción. */
.cadena-pista i {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 0;
  inline-size: 8px;
  block-size: 8px;
  margin-block-start: -4px;
  margin-inline-start: -4px;
  border-radius: 50%;
  background: var(--tinta-via, var(--muted));
  translate: calc(
      clamp(0, (var(--avance) - var(--tramo) * 0.34) / 0.34, 1) * 100cqi
    )
    0;
}

.cadena-surco {
  inline-size: 6rem;
  block-size: auto;
  flex: none;
}

.cadena-surco polyline {
  fill: none;
  stroke: var(--tinta-via, var(--muted));
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - clamp(0, (var(--avance) - 0.62) / 0.38, 1));
}

.cadena-nota {
  margin: 0 0 0.9rem;
  font-size: var(--fs-3);
  color: var(--tinta-via, var(--muted));
}

.cadena-via + .cadena-nota:last-child {
  margin-block-end: 0;
}

/* El camino de la cinta va en el color del primer nivel; el del archivo se
   queda en gris, que es exactamente lo que la figura quiere decir. */
.cadena-analogica,
.cadena-analogica + .cadena-nota {
  --tinta-via: var(--p1);
  --linea-via: color-mix(in oklab, var(--p1) 45%, transparent);
}

/* Las dos ondas son lo que hay que comparar, así que tienen que estar puestas
   igual. Y no lo estaban: «Cinta» es corta y «Archivo comprimido» no, así que
   la vía de arriba dejaba su onda al lado de las cajas mientras la de abajo la
   mandaba a una línea propia. Medido: la vía del archivo entra completa desde
   480px, no antes, y entre 400 y 470 las dos quedaban desalineadas.

   Por debajo de ese ancho bajan las dos, y de paso a lo ancho: es el único
   sitio donde la diferencia entre los dos surcos se ve de verdad, y en 6rem
   no se veía. */
@media (width < 30rem) {
  .cadena-surco {
    flex: 0 0 100%;
    inline-size: 100%;
  }
}

/* --- 3. el deadwax ------------------------------------------------ */

.deadwax {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.deadwax-disco {
  position: relative;
  inline-size: min(11rem, 44vw);
  aspect-ratio: 1;
  flex: none;
  border-radius: 50%;
  background:
    /* la etiqueta */
    radial-gradient(circle at 50% 50%, var(--p1) 0 15%, transparent 15.4%),
    /* la franja lisa. Va tapando los surcos a propósito: que ahí no haya
       surcos es exactamente lo que la figura señala. */
      radial-gradient(
        circle at 50% 50%,
        transparent 0 15%,
        light-dark(#26272b, #0d0f12) 15.4% 28%,
        transparent 28.4%
      ),
    /* el brillo del vinilo, ya fuera de la franja para no competir con ella */
      radial-gradient(
        circle at 50% 50%,
        transparent 0 36%,
        var(--plato-brillo) 36% 43%,
        transparent 43.4%
      ),
    repeating-radial-gradient(
      circle at 50% 50%,
      transparent 0 3px,
      var(--plato-surco) 3px 4px
    ),
    light-dark(#2a2b2f, #101215);
}

/* Dos aros finos encierran la franja, como una acotación en un plano. Rellenar
   la banda de color competía con el rojo de la etiqueta y se perdía. */
.deadwax-anillo {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 50%,
    transparent 0 14.6%,
    var(--p1) 14.6% 15.4%,
    transparent 15.4% 27.6%,
    var(--p1) 27.6% 28.4%,
    transparent 28.4%
  );
  opacity: calc(0.35 + 0.65 * var(--avance));
  scale: calc(0.94 + 0.06 * var(--avance));
}

.deadwax-hilo {
  flex: none;
  block-size: 1px;
  inline-size: 1.5rem;
  background: var(--p1);
  transform-origin: left center;
  scale: var(--avance) 1;
}

.deadwax-llamada {
  display: grid;
  gap: 0.2rem;
  transform-origin: left center;
  opacity: calc(0.15 + 0.85 * var(--avance));
  scale: calc(0.72 + 0.28 * var(--avance));
}

.deadwax-franja {
  font-family: var(--mono);
  font-size: var(--fs-1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--p1);
}

.deadwax-grabado {
  font-family: var(--mono);
  font-size: 1.35rem;
  letter-spacing: 0.06em;
  /* Grabado, no impreso: el trazo se lee hundido en el vinilo. */
  color: light-dark(#4a4c52, #c9ccd2);
  text-shadow: 0 1px 0 light-dark(#ffffffcc, #00000099);
}

.deadwax-nota {
  font-size: var(--fs-3);
  color: var(--muted);
  max-inline-size: 22ch;
}

/* Cuando la llamada ya no cabe al lado y baja, el hilo quedaría apuntando a
   nada. Ahí sobra: la cercanía y el color ya dicen que van juntos. */
@container figura (width < 28rem) {
  .deadwax-hilo {
    display: none;
  }
}

/* --- 4. los tres niveles en cifras -------------------------------- */

.niveles-barra {
  display: flex;
  gap: 3px;
  block-size: 0.85rem;
}

.niveles-barra span {
  flex: var(--peso);
  background: var(--color);
  border-radius: 999px;
  transform-origin: left center;
  /* Escalonado: cada tramo arranca cuando el anterior va por la mitad. */
  scale: clamp(0, (var(--avance) - var(--turno) * 0.22) / 0.34, 1) 1;
}

.niveles-lista {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}

.niveles-lista li {
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  align-items: baseline;
  gap: 0.15rem 0.7rem;
  font-size: var(--fs-4);
}

.niveles-lista b {
  color: var(--color);
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
}

.niveles-titulo {
  font-weight: 600;
}

.niveles-rango {
  grid-column: 2;
  color: var(--muted);
  font-size: var(--fs-3);
}

/* ==================================================================
   MOVIMIENTO
   Todo va dentro de no-preference: con movimiento reducido la página
   se comporta igual que antes de tener animaciones.
   ================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* --- el tacto de la portada ------------------------------------- */

  .album summary {
    transition: scale 0.18s var(--resorte);
  }

  .album summary:active {
    scale: 0.985;
  }

  .cover {
    transition: box-shadow 0.22s ease, filter 0.22s ease, translate 0.24s var(--resorte);
  }

  .album summary:hover .cover {
    translate: 0 -2px;
    box-shadow: 0 2px 4px light-dark(#00000024, #00000077),
      0 16px 30px -12px light-dark(#00000038, #000000cc);
  }

  /* Era la única transición fuera de esta guarda. */
  .album-hint {
    transition: opacity 0.15s ease;
  }

  .enlaces a,
  .barra button,
  .salto,
  .ficha-nav button,
  #limpiar {
    transition: border-color 0.15s ease, color 0.15s ease,
      background-color 0.15s ease, translate 0.2s var(--resorte),
      scale 0.12s ease;
  }

  .enlaces a:hover,
  .barra button:hover {
    translate: 0 -1px;
  }

  /* Al presionar. Antes solo lo tenía la portada, así que en táctil, donde no
     hay hover, los botones no daban ninguna señal de haber sido tocados. */
  .enlaces a:active,
  .barra button:active,
  .salto:active,
  .ficha-nav button:active:not(:disabled),
  #limpiar:active {
    scale: 0.96;
  }

  /* --- el tocadiscos del inicio ----------------------------------- */

  /* Lo que se ve girar es el brillo: los surcos son un anillo simétrico y
     rotarlos no se notaría. */
  .plato-disco {
    animation: girar 16s linear infinite;
  }

  @keyframes girar {
    to {
      rotate: 1turn;
    }
  }

  /* --- la barra de progreso crece al cargar ----------------------- */

  /* Con `scale` y no con `inline-size`: animar el ancho recalcula el diseño en
     cada cuadro durante los 1,2s, y aquí basta con estirar lo ya dibujado. */
  .progress-track span {
    animation: crecer 1.2s 0.2s var(--resorte) both;
  }

  @keyframes crecer {
    from {
      scale: 0 1;
    }
    to {
      scale: 1 1;
    }
  }

  /* --- las portadas entran al bajar -------------------------------- */

  /* Decorativo: en los navegadores sin animaciones por scroll la rejilla
     aparece asentada y no falta nada, así que no lleva respaldo en JS.
     `animation-timeline` va después de la abreviatura o esta lo borra.

     Anima `summary` y no `.album`: los fotogramas usan `translate` y `scale`,
     y cualquiera de los dos vuelve a su elemento bloque contenedor de lo que
     lleve dentro posicionado, igual que `transform`. Puesto en `.album`, el
     panel volvía a quedar preso de la tarjeta de 9rem y el volteo por anclaje
     no se activaba nunca. `summary` es hermano del panel, así que lo mueve sin
     encerrarlo, y es justo la cara visible de la tarjeta: se ve igual. */
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .album summary {
      animation: entrar auto linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 20%;
    }
  }

  @keyframes entrar {
    from {
      opacity: 0;
      translate: 0 16px;
      scale: 0.94;
    }
  }

  /* --- las figuras avanzan al bajar --------------------------------- */

  /* `animation-timeline` va después de la abreviatura o esta lo borra.
     En Firefox esto no existe y lo suple app.js escribiendo la misma
     propiedad; sin JavaScript la figura ya se ve terminada. */
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .figura {
      animation: avanzar auto linear both;
      animation-timeline: view();
      animation-range: entry 50% cover 60%;
    }
  }

  @keyframes avanzar {
    from {
      --avance: 0;
    }
    to {
      --avance: 1;
    }
  }

  /* --- la barra de arriba ------------------------------------------ */

  .barra {
    transition: translate 0.32s var(--resorte), visibility 0.32s;
  }

  /* --- la ficha entra y sale --------------------------------------- */

  .ficha {
    transition: opacity 0.22s, translate 0.34s var(--resorte),
      scale 0.34s var(--resorte), display 0.34s allow-discrete,
      overlay 0.34s allow-discrete;
  }

  .ficha:not([open]) {
    opacity: 0;
    translate: 0 12px;
    scale: 0.97;
  }

  @starting-style {
    .ficha[open] {
      opacity: 0;
      translate: 0 12px;
      scale: 0.97;
    }
  }

  .ficha::backdrop {
    transition: opacity 0.28s, display 0.28s allow-discrete,
      overlay 0.28s allow-discrete;
  }

  .ficha:not([open])::backdrop {
    opacity: 0;
  }

  @starting-style {
    .ficha[open]::backdrop {
      opacity: 0;
    }
  }

  /* --- el contenido de la ficha llega escalonado ------------------- */

  /* El turno lo numera app.js con `--i`, y no `nth-child`, porque las piezas
     se colocan por áreas y el orden visual no es el del documento. La portada
     queda fuera: de eso se encarga la transición de vistas. */
  .ficha[open] .ficha-titulos,
  .ficha[open] .ficha-texto > * {
    animation: subir 0.34s var(--resorte) both;
    animation-delay: calc(var(--i, 0) * 45ms);
  }

  @keyframes subir {
    from {
      opacity: 0;
      translate: 0 10px;
    }
  }

  /* --- el disco recién abierto se señala un momento ---------------- */

  .album[data-destacado] .cover {
    animation: destacar 1.6s ease-out both;
  }

  @keyframes destacar {
    0%,
    100% {
      box-shadow: 0 1px 2px light-dark(#0000001a, #00000066),
        0 8px 18px -10px light-dark(#00000026, #00000099);
    }
    25%,
    60% {
      box-shadow: 0 0 0 3px var(--tone, var(--p1)),
        0 8px 22px -10px light-dark(#00000040, #000000cc);
    }
  }
}

/* La portada viaja de la rejilla a la ficha. app.js pone el nombre en una
   sola portada cada vez: dos elementos con el mismo nombre a la vez abortan
   la transición entera. */
::view-transition-group(portada) {
  animation-duration: 0.4s;
}

::view-transition-old(portada),
::view-transition-new(portada) {
  animation: none;
  mix-blend-mode: normal;
}

/* ==================================================================
   SUPERFICIES TÁCTILES
   En pantalla táctil no hay puntero fino que apunte a un blanco de 32
   píxeles. Solo crecen ahí: con ratón la densidad de la página se
   conserva. Va al final del archivo a propósito, para ganarle a las
   medidas que cada control declara más arriba.
   ================================================================== */

@media (pointer: coarse) {
  /* Con los controles más altos la barra crece, y el hueco que le reserva el
     body tiene que crecer con ella o vuelve a tapar el primer título. */
  body {
    padding-block-start: 4.25rem;
  }

  .enlaces a,
  .barra button,
  .ficha-nav button,
  #limpiar {
    min-block-size: 2.75rem;
    padding-inline: 1rem;
  }

  .barra input {
    padding-block: 0.6rem;
  }

  .ficha-cerrar {
    inline-size: 2.75rem;
  }

  /* El enlace de la reseña es una línea de texto: se le da alto propio sin
     estirar el renglón que lo rodea. */
  .fuente a {
    display: inline-flex;
    align-items: center;
    min-block-size: 2.75rem;
  }
}

/* --- impresión ---------------------------------------------------- */

@media print {
  :root {
    color-scheme: light;
  }

  body {
    background: #fff;
    color: #000;
    font-size: 9.5pt;
    /* En papel no hay barra fija que esquivar. */
    padding-block-start: 0;
  }

  .plato,
  .barra,
  .saltar,
  .sin-resultados,
  .ficha,
  .hero-lead,
  .figura,
  #nota {
    display: none;
  }

  .hero {
    padding-block: 0 0.5rem;
  }

  .group,
  main > section,
  .priority {
    border-top: none;
    padding-block: 0.5rem;
  }

  .priority-motive {
    font-size: 8.5pt;
  }

  .albums {
    grid-template-columns: repeat(6, 1fr);
    gap: 0.7rem 0.5rem;
  }

  .cover {
    box-shadow: none;
    border: 1px solid #ccc;
    margin-bottom: 0.25rem;
  }

  .album-hint,
  .panel {
    display: none;
  }

  .priority,
  .album {
    break-inside: avoid;
  }
}
