/**
 * El reel ocupa la ventana entera, menú incluido: sube por detrás de él
 * hasta el borde superior.
 *
 * Sale a sangre descontando el margen del body por los cuatro lados, no
 * midiendo la ventana: cualquier unidad `vw` incluye el ancho de la
 * barra de scroll vertical, así que un `100svw` se pasa de ancho justo
 * esos píxeles y provoca scroll horizontal. Con márgenes negativos el
 * reel sigue siendo un bloque normal y ocupa exactamente lo que hay.
 *
 * Arriba, además del margen, hay que descontar el menú.
 *
 * `overflow: clip` es para el reproductor de Vimeo, que se pinta más
 * grande que el hueco para poder recortarlo; sin esto asomaría por los
 * lados y sacaría scroll horizontal. Se recorta y ya está: `clip` no
 * crea caja de scroll, a diferencia de `hidden`.
 *
 * Y `container-type` lo convierte en la referencia que mide ese
 * reproductor. Puede llevarlo porque su tamaño no depende de lo que
 * tenga dentro: el alto es 100svh y el ancho, el de la línea.
 */
.reel {
  position: relative;
  display: grid;
  place-items: center;
  height: 100svh;
  margin-inline: calc(-1 * var(--fs-base));
  margin-top: calc(-1 * (var(--nav-height) + var(--fs-base)));
  container-type: size;
  overflow: clip;
}

/* Vale igual para el <video> y para el <img>: object-fit recorta los dos. */
.reel-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/**
 * El reel de un reproductor externo. Un iframe no es contenido
 * reemplazado como un vídeo
 * o una imagen, así que `object-fit` no le hace nada: llega con su 16:9
 * y hay que recortarlo a mano. Se le da el mayor de los dos tamaños que
 * cubren el hueco —o el ancho entero, o el alto entero— y se centra;
 * lo que sobre por el lado que toque lo corta el reel. Es `cover` hecho
 * a mano.
 *
 * Las unidades son de contenedor y no `vw`/`vh` a propósito: `100vw`
 * incluye el ancho de la barra de scroll, o sea que el iframe se pasaría
 * justo esos píxeles —el mismo problema que el reel esquiva con márgenes
 * negativos—. `cqw` y `cqh` miden el reel, que ya es exactamente el
 * hueco que hay que cubrir.
 *
 * `pointer-events: none` porque un reproductor de fondo no tiene nada
 * que pulsar: sin esto el iframe se quedaría con la rueda del ratón y
 * con la selección del texto de la introducción, que va encima. En
 * YouTube además es lo que lo hace inerte: `controls=0` esconde la
 * barra, pero un clic encima seguiría pausando el vídeo.
 */
.reel-embed {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: max(100cqw, calc(100cqh * 16 / 9));
  height: max(100cqh, calc(100cqw * 9 / 16));
  border: 0;
  pointer-events: none;
}

/**
 * El póster tapa al reproductor hasta que hay imagen. Un reproductor de
 * Vimeo tarda en dar su primer fotograma, y hasta que lo da el iframe es
 * un rectángulo vacío.
 *
 * Se coloca sola: lleva también `reel-media`, así que ya está recortada
 * al hueco igual que una portada de imagen. Lo único suyo es el fundido.
 *
 * El atributo lo pone reel.js cuando el reproductor avisa de que está
 * corriendo. Si no llega a avisar —el navegador puede negarse a
 * arrancar un vídeo solo— el póster se queda puesto, y eso es lo
 * correcto: quitarlo dejaría el rectángulo vacío a la vista.
 */
.reel-poster {
  transition: opacity 400ms ease-in-out;
}

.reel-poster[data-playing] {
  opacity: 0;
}

.reel-introduction {
  position: relative;
  max-width: var(--max-width);
  margin: 0;
  padding: var(--fs-base);
  text-align: center;
}

.projects {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-iterare);
  margin-top: var(--space-iterare);
}

.project-card {
  display: block;
  text-decoration: none;
}

/**
 * La figura se ciñe a la portada en vez de ocupar la columna. El ancho
 * lo pone images.css sobre la propia imagen, según su orientación, y de
 * ahí hacia fuera lo hereda todo: la lista centra la tarjeta y la
 * tarjeta se ajusta a la figura.
 *
 * Sin el fit-content la figura seguiría midiendo lo que la columna, y
 * con una portada vertical el área pinchable se extendería a los lados
 * de la foto. El `position: relative` no lo usa el título del hover
 * —ése va contra la ventana— sino el de las pantallas táctiles, que
 * vuelve a colocarse sobre su propia portada.
 */
.project-card figure {
  position: relative;
  margin: 0;
  width: fit-content;
}

.project-card img {
  display: block;
  width: 100%;
  height: auto;
}

/**
 * El título aparece al pasar por encima de la portada, centrado en la
 * ventana y no en la imagen: de ahí el `position: fixed`, que lo
 * posiciona contra el viewport y no contra la figura. Da igual dónde
 * caiga la portada en el scroll —el título sale siempre en el centro de
 * la pantalla.
 *
 * `pointer-events: none` es imprescindible: aunque sea invisible, la
 * capa cubre la ventana entera —opacity 0 no deja de recibir el ratón—
 * y se tragaría el hover del resto de portadas.
 *
 * `z-index` la mantiene por encima de las que vienen después. Sin él, la
 * figura de una tarjeta posterior es también un elemento posicionado y,
 * a igualdad de z-index, gana la que va más abajo en el documento: el
 * título quedaría tapado por la portada que hubiera en ese momento en
 * mitad de la pantalla, que es justo donde él se dibuja.
 *
 * En pantallas táctiles no hay hover, así que ahí se muestra siempre.
 */
.project-card figcaption {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease-in-out;
}

.project-card:hover figcaption,
.project-card:focus-visible figcaption {
  opacity: 1;
}

/**
 * Vertical no significa una letra debajo de otra: el título se escribe
 * tal cual y se gira 90°. Eso es exactamente lo que hace writing-mode
 * con texto latino, y a diferencia de un transform la caja también gira,
 * así que el centrado sigue funcionando solo.
 *
 * vertical-rl gira en sentido horario —se leería de arriba a abajo, con
 * las letras mirando a la derecha—, así que se le da la vuelta con
 * rotate(180deg): el texto queda de abajo a arriba y apuntando a la
 * izquierda. El valor que diría eso de una vez, `sideways-lr`, sólo lo
 * entiende Firefox; la pareja writing-mode + rotate funciona en todos.
 *
 * Girar 180° no mueve nada de sitio: el transform pivota sobre el centro
 * de la caja, que es justo donde `place-items: center` la ha dejado.
 */
.project-card figcaption span {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/**
 * Sin hover no hay puntero que pida el título, así que lo pide el
 * scroll: titles.js marca con `data-current` la portada que cruza el
 * centro de la pantalla y ésa es la única que enseña el suyo, en el
 * mismo sitio en que lo enseñaría el hover.
 *
 * Las dos reglas son las dos mitades de la mejora progresiva:
 *
 * - Sin JS no hay `data-scroll-titles` y manda la primera: los títulos
 *   se ven todos, cada uno sobre su portada. Centrados en la ventana se
 *   amontonarían unos encima de otros, de ahí el `absolute`.
 * - Con JS manda la segunda y se vuelve a lo mismo que en un ratón, con
 *   `data-current` haciendo el papel del `:hover`.
 */
@media (hover: none) {
  .project-card figcaption {
    position: absolute;
    opacity: 1;
  }

  [data-scroll-titles] .project-card figcaption {
    position: fixed;
    opacity: 0;
  }

  [data-scroll-titles] .project-card[data-current] figcaption {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .project-card figcaption,
  .reel-poster {
    transition: none;
  }
}
