/* Novastra · la biblioteca de ejercicios (/ejercicios y /en/exercises)
 *
 * ## Qué problema resuelve
 *
 * Antes esto eran 907 nombres subrayados repartidos en dos columnas. Funcionaba —Google los
 * encontraba y el buscador filtraba— pero no se podía *mirar*: un ejercicio de gimnasio se
 * reconoce por el gesto, no por su nombre, y "Aperturas inclinadas en polea" y "Aperturas
 * planas en polea en banco" son la misma línea de texto para cualquiera que no sepa ya cuál
 * quiere. La app enseña la foto desde el primer día; la web pedía leer.
 *
 * Ahora cada ejercicio es una fila con su fotograma, el color de su músculo y el material con
 * el que se hace. Las fotos son las mismas que descarga la app (novastra-media), así que no hay
 * un segundo juego de imágenes que mantener.
 *
 * ## Una sola forma, y por qué
 *
 * Hubo una versión con dos —rejilla de fichas grandes y lista— y un conmutador. La decisión del
 * dueño, después de usarla, fue quedarse solo con la lista, y conviene dejar escrito por qué
 * para no volver atrás: aquí se viene a **encontrar un ejercicio**, no a hojear un catálogo.
 * Una fila estrecha enseña cincuenta a la vez, alinea el material en columna y deja el nombre
 * entero; la ficha grande enseñaba veinte y cortaba los nombres largos a dos líneas.
 *
 * ## Las 907 fotos y el peso de la página
 *
 * Todas las filas están en el HTML (el buscador filtra lo que ya hay, sin pedir nada al
 * servidor), así que si cada `<img>` se cargara habría 29 MB de fotos. No pasa: `loading="lazy"`
 * no baja lo que no está cerca de la pantalla —medido en producción, 37 de 879— y
 * `content-visibility: auto` evita que el navegador calcule la posición de lo que no se ve.
 */

/* ------------------------------------------------------------------ los saltos a un musculo
 *
 * El sitio entero lleva `scroll-behavior: smooth` en el `<html>` (`landing.css`), y aqui eso
 * **rompia los atajos**: al pulsar "Piernas" la pagina se quedaba donde estaba.
 *
 * El motivo es la suma de dos cosas. La pagina mide decenas de miles de pixeles y las filas usan
 * `content-visibility: auto`, asi que el navegador solo conoce la posicion REAL de lo que ya ha
 * mirado; del resto lleva una estimacion. Un salto suave de cuarenta mil pixeles va recorriendo
 * y midiendo por el camino, el destino se mueve mientras viaja, y la animacion se queda a medias
 * o se cancela. Comprobado en produccion: con el salto instantaneo cae exactamente en la
 * seccion (39.260 px, la cabecera a cero); con el suave, se quedaba en 126.
 *
 * `:has()` y no una clase en el `<html>` porque el `<html>` lo escribe la plantilla y esto es
 * una regla de ESTA pagina: donde vive el problema es donde tiene que vivir el arreglo.
 *
 * El `scroll-margin-top` es lo otro que hace falta: sin el, el salto deja la cabecera del grupo
 * justo debajo de la barra flotante y parece que ha caido en el sitio equivocado.
 */
html:has(.biblioteca) { scroll-behavior: auto; }

.grupo { scroll-margin-top: 84px; }

/* ------------------------------------------------------------------ la página */

/* La biblioteca es más ancha que el resto de páginas públicas: `.publica` son 760 px, pensados
   para leer un texto. Aquí se viene a barrer con la vista. */
.biblioteca {
  max-width: var(--ancho);
  margin: 0 auto;
  padding: calc(var(--space-2xl) + 40px) var(--gutter) var(--space-2xl);
}

.biblioteca h1 {
  font-family: var(--font-display);
  font-size: var(--text-display-s);
  margin: 0 0 var(--space-2xs);
}

.biblioteca .entradilla {
  max-width: var(--medida);
  color: var(--color-dim);
  margin: 0;
}

/* ------------------------------------------------------------------ cabecera de músculo

   Se queda pegada arriba al bajar: con 92 ejercicios de pecho seguidos, a media lista ya no
   sabes en qué músculo estás. */

.grupo {
  margin: 0 0 var(--space-xl);
}

.grupo__cab {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: baseline;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-2xs);
  padding: var(--space-2xs) 0;
  /* Un velo y no un color opaco: debajo pasan filas, y un bloque sólido cortaría la página en
     dos. El desenfoque es lo que hace que el texto siga siendo legible por encima de una foto. */
  background: linear-gradient(
    to bottom,
    var(--color-paper) 55%,
    oklch(10.8% 0.026 288.6 / 0) 100%
  );
  backdrop-filter: blur(6px);
}

.grupo__cab h2 {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  margin: 0;
  /* El color del músculo, en el propio título. Se hereda de `--m` (lo pone el `data-grupo` del
     `<section>`, ver `app.css`), así que no hay once reglas escritas a mano. */
  color: var(--m, var(--color-ink));
}

.grupo__n {
  font-size: var(--text-xs);
  color: var(--color-dim);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------------ la lista */

.fichas {
  list-style: none;
  margin: 0;
  padding: 0;
}

.fichas li {
  /* El navegador se salta el calculo de lo que no se ve, y la altura reservada evita que la
     barra de desplazamiento pegue saltos al bajar.

     Dicho esto, y para que nadie se lleve una impresion equivocada: **el ahorro grande no es
     este**. Lo que evita bajarse veintinueve megas de fotos es `loading="lazy"` en cada `<img>`.
     Medido en produccion: 879 imagenes en el HTML, 37 bajadas, con esta regla y sin ella. */
  content-visibility: auto;
  contain-intrinsic-size: auto 54px;
}

.fichas li[hidden] { display: none; }
.grupo[hidden] { display: none; }

/* La fila: foto, nombre y material. Tres columnas y no cuatro: el musculo NO sale como columna
   aunque el dato este ahi. Dentro de "Pecho", repetir "Pecho" en noventa y dos filas seguidas es
   ruido puro, y la cabecera pegada arriba lo dice a veinte pixeles de distancia. Lo que cambia
   de fila a fila es el material, y esa si es una columna. */
.ficha {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) 9.5rem;
  align-items: center;
  gap: var(--space-xs);
  position: relative;
  padding: 5px var(--space-2xs);
  border-radius: 10px;
  border-bottom: var(--rule-thin) solid var(--color-rule);
  text-decoration: none;
  color: inherit;
  transition: background var(--dur-short) var(--ease-out);
}

.ficha:hover,
.ficha:focus-visible {
  background: var(--color-paper-2);
  outline: none;
}

.ficha:focus-visible {
  box-shadow: 0 0 0 2px var(--color-focus);
}

/* La foto, QUIETA.
 *
 * Aqui hubo un `scale(1.06)` y un cambio de brillo al pasar por encima. Se ha quitado, y el
 * motivo que dio el dueño es el bueno: cada ejercicio tiene **dos** fotogramas y la app los
 * alterna para enseñar el movimiento, asi que una foto que se mueve al pasar el raton promete
 * esa animacion y luego no la hace. Un gesto que insinua algo que no va a pasar es peor que
 * ninguno.
 *
 * Tampoco lleva correccion de color: la foto se ve como es. */
.ficha__foto {
  width: 72px;
  height: 48px;
  border-radius: 9px;
  overflow: hidden;
  background: var(--color-paper-3);
}

.ficha__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* La inicial, para los 27 ejercicios sin foto. No es un hueco vacío: es el mismo recurso que
   usa la app cuando no tiene imagen. */
.ficha__foto--sin {
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--m, var(--color-accent-hi));
  background:
    radial-gradient(120% 90% at 50% 0%, color-mix(in oklab, var(--m, var(--color-accent)) 22%, transparent), transparent 70%),
    var(--color-paper-3);
}

/* `display: contents` en los dos envoltorios: el nombre y el material pasan a ser columnas de la
   rejilla de la fila sin tocar el marcado que genera el HTML. */
.ficha__cuerpo,
.ficha__pie {
  display: contents;
}

.ficha__nom {
  font-size: var(--text-md);
  color: var(--color-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* La barra de color del músculo, al principio del nombre. */
  border-left: 3px solid var(--m, var(--color-accent));
  padding-left: var(--space-2xs);
}

/* El punto de color sobra cuando el nombre ya lleva su barra. Se genera igual porque lo usa la
   pastilla del índice de arriba, que sí lo necesita. */
.ficha .punto { display: none; }

/* El nombre del musculo no se pinta: lo dice la barra de color y, con letras, la cabecera que
   está justo encima. Se genera igualmente porque es lo que encuentra el buscador del navegador
   (Ctrl+F) y lo que oye un lector de pantalla al recorrer la fila. */
.ficha__mus {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* El material como pastilla y no como texto suelto: es la unica columna de datos que hay y tiene
   que leerse como una columna, no como una nota al margen. */
.ficha__eq {
  justify-self: start;
  max-width: 100%;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  border: var(--rule-thin) solid var(--color-rule);
  font-size: var(--text-xs);
  color: var(--color-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* "×2": el peso que se apunta es el de UNA mancuerna y el volumen cuenta las dos. Va absoluto y
   no en su propia columna: si ocupara columna, las filas sin ×2 dejarían un hueco y la lista
   perdería la alineación, que es lo único que tiene. */
.ficha__x2 {
  position: absolute;
  right: var(--space-2xs);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  border: var(--rule-thin) solid var(--color-rule-hi);
  color: var(--color-signal);
}

@media (max-width: 720px) {
  /* En el móvil no hay sitio para tres columnas: se cae la del material. La foto y el nombre son
     lo que se usa para elegir. */
  .ficha {
    grid-template-columns: 56px minmax(0, 1fr);
  }
  .ficha__foto { width: 56px; height: 38px; }
  .ficha__eq { display: none; }
  .ficha__nom { font-size: var(--text-sm); }
}

/* ------------------------------------------------------------------ índice de músculos

   Once pastillas que llevan a su sección. Es el índice de la página: sin él, saber qué hay
   dentro exige bajar 907 filas. */

.atajos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  list-style: none;
  margin: var(--space-md) 0 var(--space-lg);
  padding: 0;
}

.atajo {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 38px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  border: var(--rule-thin) solid var(--color-rule);
  background: var(--color-paper-2);
  color: var(--color-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  transition: border-color var(--dur-short) var(--ease-out), color var(--dur-short) var(--ease-out);
}

.atajo:hover,
.atajo:focus-visible {
  border-color: var(--m, var(--color-accent));
  color: var(--color-ink);
}

.atajo__n {
  font-size: var(--text-xs);
  color: var(--color-dim);
  font-variant-numeric: tabular-nums;
}
