/* ==========================================================================
   Cabecera — logo + nav (ver plantillas/base.html)
   ========================================================================== */

/* .cabecera sin borde propio: el corte-separador justo debajo (ver
   plantillas/base.html) hace de línea — nunca dos grises superpuestos. */
.cabecera-contenido {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-6);
  padding-block: var(--e-6); /* mínimo 20px de aire arriba/abajo del logo */
}

.marca {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  cursor: pointer;
}

.marca[aria-current="page"] {
  cursor: default;
}

.logo-svg {
  height: 42px;
  width: auto;
  color: var(--blanco);
  overflow: visible;
}

/* Alineación óptica con el logo, no matemática: el rostro tiene el pelo
   arriba y la punta abajo, así que centrar por caja lo deja descolocado.
   El translateY se ajustó a ojo hasta que la línea de texto quedara a la
   altura de los ojos del isotipo. */
.marca-nombre {
  font-family: var(--fuente-display);
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--blanco);
  white-space: nowrap;
  line-height: 1;
  transform: translateY(3px);
}

@media (max-width: 639px) {
  .marca-nombre {
    display: none;
  }
}

.mitad {
  transition: transform var(--dur-noto) var(--ease-noto);
}

/* Desplazamiento PERPENDICULAR a la recta de corte (~17°), no horizontal:
   unidades del viewBox, escalan solas con el tamaño del logo. Proporción
   0.3:1 (perpendicular a 17°); la magnitud se subió de 18/60 a 60/200
   porque a 42px de logo con la línea ya en su grosor real (2px) el valor
   original apenas desplazaba ~1px — imperceptible sin el grosor de línea
   anterior (14px) haciendo de "muleta" visual del corte. */
.marca:not([aria-current="page"]):hover .mitad-a,
.marca:not([aria-current="page"]):focus-visible .mitad-a {
  transform: translate(60px, -200px);
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.marca:not([aria-current="page"]):hover .mitad-b,
.marca:not([aria-current="page"]):focus-visible .mitad-b {
  transform: translate(-60px, 200px);
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.corte-logo {
  stroke-dasharray: 1200;
  stroke-dashoffset: 1200;
  opacity: 0;
  transition:
    stroke-dashoffset var(--dur-noto) var(--ease-noto),
    opacity 200ms;
}

.marca:not([aria-current="page"]):hover .corte-logo,
.marca:not([aria-current="page"]):focus-visible .corte-logo {
  stroke-dashoffset: 0;
  opacity: 1;
  transition:
    stroke-dashoffset var(--dur-kiritsuke) var(--ease-nukitsuke),
    opacity 100ms;
}

/* La diagonal es exclusiva del logo: en reposo reducido, ni desplazamiento
   ni línea — el resto del sitio ya respeta prefers-reduced-motion en
   movimiento.css, pero estas reglas viven en las propias mitades. */
@media (prefers-reduced-motion: reduce) {
  .marca:not([aria-current="page"]):hover .mitad-a,
  .marca:not([aria-current="page"]):hover .mitad-b,
  .marca:not([aria-current="page"]):focus-visible .mitad-a,
  .marca:not([aria-current="page"]):focus-visible .mitad-b {
    transform: none;
  }

  .marca:not([aria-current="page"]):hover .corte-logo,
  .marca:not([aria-current="page"]):focus-visible .corte-logo {
    opacity: 0;
    stroke-dashoffset: 1200;
  }
}

/* Pie anclado al fondo del viewport en páginas cortas (web, sobre-mí):
   sin esto el pie quedaba pegado al contenido y dejaba un vacío enorme
   por debajo, rompiendo la proporción con páginas más largas. */
main {
  flex: 1;
}

main:focus {
  outline: none;
}

/* ==========================================================================
   Componente "corte" — texto que se parte en dos mitades al pasar el
   ratón o el foco (nav, pie, productora, anterior/siguiente, etc). Usar
   siempre esta forma (ver plantillas/_macros.html, macro corte_texto):

     <span class="corte-texto">
       <span class="base" aria-hidden="true"><span class="corte-glifo">Texto</span></span>
       <span class="mitad-sup" aria-hidden="true"><span class="corte-glifo">Texto</span></span>
       <span class="mitad-inf" aria-hidden="true"><span class="corte-glifo">Texto</span></span>
       <span class="corte" aria-hidden="true"></span>
       <span class="sr-only">Texto</span>
     </span>

   Todo vive DENTRO de .corte-texto a propósito — incluido .corte, antes
   un hermano fuera de aquí. Así .corte-texto (position:relative) es el
   único contenedor de referencia para sus hijos absolutos: ni el
   padding, ni el line-height, ni nada del enlace que envuelve a
   .corte-texto (.nav-enlace, .cierre, etc.) puede ya desalinear el
   corte, porque no interviene en el cálculo. El elemento que envuelve a
   .corte-texto solo necesita position:relative; display:inline-block.

   .mitad-sup/.mitad-inf llevan el clip-path Y la posición absoluta — por
   eso el ajuste que centra las mayúsculas (--corte-ajuste-mayusculas, ver
   tokens.css) NO va en ellas directamente: moverlas a ellas arrastraría
   también la frontera del recorte, que vive en su propio espacio, y la
   línea de .corte (ajena a ese desplazamiento) quedaría descuadrada
   respecto a donde de verdad se parten las letras — pasó una vez, por
   eso el inciso. El ajuste va en .corte-glifo, un span interior que solo
   envuelve el texto: así el recorte y la línea se quedan fijos en el 50%
   de la misma caja sin moverse, y coinciden por construcción.

   En reposo se ve .base (el texto normal, una sola copia, sin costura
   posible). Al pasar el ratón o el foco sobre el enlace, .base se oculta
   y aparecen mitad-sup/mitad-inf — el cambio es con visibility, sin
   transición: lo único que anima es el transform de las mitades y el
   scaleX de la línea (ver cada enlace: .nav-enlace, .pie-enlace,
   .enlace-grande, .ficha-fila-enlace, .as-enlace, .cierre).
   ========================================================================== */

.corte-texto {
  position: relative;
  display: inline-block;
  line-height: 1.2;
}

/* El desplazamiento que centra las mayúsculas (--corte-ajuste-mayusculas,
   ver tokens.css) va en un span INTERIOR — .corte-glifo, alrededor del
   texto — nunca en .base/.mitad-sup/.mitad-inf directamente: esos tres
   llevan el clip-path y la posición absoluta, así que desplazarlos a
   ellos arrastra también la frontera del recorte con el glifo, y la
   línea de .corte (ajena a ese desplazamiento) se queda descuadrada
   respecto a donde de verdad se parten las letras. Desplazando solo el
   glifo, el recorte y la línea quedan en el 50% de la MISMA caja sin
   moverse, y por construcción coinciden. */
.corte-glifo {
  position: relative;
  top: var(--corte-ajuste-mayusculas);
}

.mitad-sup,
.mitad-inf {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  white-space: nowrap;
  visibility: hidden;
  transition: transform var(--dur-noto) var(--ease-noto);
}

.mitad-sup {
  clip-path: inset(0 0 50% 0);
}

.mitad-inf {
  clip-path: inset(50% 0 0 0);
}

.corte {
  display: block;
  position: absolute;
  left: -4px;
  /* width explícito en vez de "right: -4px" — un <span> vacío con
     position:absolute y left+right (sin contenido ni width propios) no
     siempre se expande al ancho resuelto: getComputedStyle lo calcula
     bien, pero el cuadro renderizado se queda en 0. width fijo evita por
     completo ese cálculo implícito. */
  width: calc(100% + 8px);
  /* -0.75px: la mitad del propio grosor (1.5px), para que el CENTRO de
     la línea caiga en el 50% — no su borde superior. calc() simple,
     porcentaje menos una constante en px: nada que ver con el var() con
     aritmética que se quitó del resto de este archivo. */
  top: calc(50% - 0.75px);
  height: 1.5px;
  background: var(--rojo-marca);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-noto) var(--ease-noto);
}

/* El cambio entre .base y las mitades: un solo bloque de reglas en vez de
   repetirlo por enlace, agrupando con :is() todos los que envuelven a
   .corte-texto directamente. .as-palabra es la excepción — el elemento
   que de verdad se pasa con el ratón es .as-enlace, no ella misma. */
:is(.nav-enlace, .pie-enlace, .enlace-grande, .ficha-fila-enlace, .cierre):not([aria-current="page"]):is(:hover, :focus-visible)
  .corte-texto
  .base {
  visibility: hidden;
}

:is(.nav-enlace, .pie-enlace, .enlace-grande, .ficha-fila-enlace, .cierre):not([aria-current="page"]):is(:hover, :focus-visible)
  .corte-texto
  :is(.mitad-sup, .mitad-inf) {
  visibility: visible;
}

.as-enlace:is(:hover, :focus-visible) .as-palabra .corte-texto .base {
  visibility: hidden;
}

.as-enlace:is(:hover, :focus-visible) .as-palabra .corte-texto :is(.mitad-sup, .mitad-inf) {
  visibility: visible;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Navegación — 6.3 elemento firma: la palabra se parte al pasar el ratón
   ========================================================================== */

.lista-nav {
  display: flex;
  align-items: center;
  gap: var(--e-8);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-enlace,
.pie-enlace {
  position: relative;
  display: inline-block;
  color: var(--gris);
  text-decoration: none;
  padding: 7px 0;
  overflow: visible;
  cursor: pointer;
}

.nav-enlace {
  font-size: var(--t-nav);
  letter-spacing: 0.1em;
}

/* El corte al pasar el ratón, solo donde hay un ratón de verdad — en
   touch, el ":hover" de un enlace se queda "pegado" tras tocarlo, y el
   enlace se ve partido sin que nadie lo esté señalando. */
@media (hover: hover) {
  .nav-enlace:not([aria-current="page"]):hover {
    color: var(--blanco);
  }

  .nav-enlace:not([aria-current="page"]):hover .mitad-sup,
  .nav-enlace:not([aria-current="page"]):hover .mitad-inf {
    transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
  }

  .nav-enlace:not([aria-current="page"]):hover .mitad-sup {
    transform: translateX(5px);
  }

  .nav-enlace:not([aria-current="page"]):hover .mitad-inf {
    transform: translateX(-5px);
  }

  .nav-enlace:not([aria-current="page"]):hover .corte {
    transform: scaleX(1);
    transition: transform var(--dur-kiritsuke) var(--ease-nukitsuke);
  }
}

/* Estado activo: segunda señal además del color, para daltonismo protán (ver 6.3) */
.nav-enlace[aria-current="page"] {
  color: var(--rojo-texto);
  font-weight: 500;
  cursor: default;
}

/* ==========================================================================
   Menú de móvil — hasta ~700px. El <button> se ve por CSS solo con el
   viewport, SIN depender de que estaticos/js/menu.js llegue a correr: si
   el script falla, tarda o se bloquea, el botón sigue siendo visible (ver
   el porqué en menu.js — antes dependía de que el script le quitara
   [hidden], y si el script no corría, no había forma de ver ni abrir el
   menú). Lo que sí necesita el script es FUNCIONAR: el panel a pantalla
   completa solo se activa bajo <html class="nav-js">, que pone menu.js al
   arrancar — sin JS, .lista-nav se queda como una fila normal con
   flex-wrap, visible y usable aunque el botón de al lado no haga nada.
   ========================================================================== */

.menu-boton {
  display: none;
}

@media (max-width: 699px) {
  /* nav ahora tiene dos hijos (botón + lista), no uno — sin esto, el
     <nav> (bloque, sin flex propio) los apila y el botón se desalinea
     del logo en cuanto .lista-nav crece (el reposo sin JS, con la lista
     envuelta en varias líneas). Cuando .nav-js SÍ está activa, .lista-nav
     pasa a position:fixed y sale de este flujo igualmente. */
  nav[aria-label="Principal"] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--e-4);
  }

  .lista-nav {
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: var(--e-2);
  }

  .menu-boton {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 201;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
  }

  .menu-icono {
    width: 30px;
    height: 30px;
  }

  /* Cerrado: dos rayas horizontales, en --rojo-marca (es un gráfico, no
     texto: la regla de "nunca en texto" no le aplica), sin radio — por
     eso stroke-linecap: butt, nunca round. */
  .menu-raya {
    stroke-linecap: butt;
    transform-box: fill-box;
    transform-origin: center;
    opacity: 1;
    transition:
      opacity var(--dur-nukitsuke) var(--ease-nukitsuke),
      transform var(--dur-nukitsuke) var(--ease-nukitsuke);
  }

  /* Abierto: la misma equis de icono_corte() (_macros.html) — trazo
     largo y corto, nunca iguales. Entra en kiritsuke, justo detrás del
     nukitsuke con que salen las rayas — el corte que sigue al gesto. */
  .menu-equis {
    stroke-linecap: butt;
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    transform: rotate(-25deg) scale(0.6);
    transition:
      opacity var(--dur-kiritsuke) var(--ease-nukitsuke),
      transform var(--dur-kiritsuke) var(--ease-nukitsuke);
  }

  .menu-boton[aria-expanded="true"] .menu-raya {
    opacity: 0;
    transform: rotate(25deg) scale(0.6);
  }

  .menu-boton[aria-expanded="true"] .menu-equis {
    opacity: 1;
    transform: rotate(0) scale(1);
    transition-delay: var(--delay-kiritsuke);
  }

  /* Al cerrar (nōtō — envainar, más lento que al abrir), mismo recorrido
     pero sin el delay de entrada: vuelven las rayas, se va la equis, a
     la vez. */
  .menu-boton:not([aria-expanded="true"]) .menu-raya,
  .menu-boton:not([aria-expanded="true"]) .menu-equis {
    transition-duration: var(--dur-noto);
    transition-timing-function: var(--ease-noto);
    transition-delay: 0s;
  }

  /* Bajo <html class="nav-js"> (la pone menu.js al arrancar, ver el
     porqué arriba): el nav de siempre pasa a panel a pantalla completa.
     Sin esa clase (JS bloqueado, roto o desactivado), .lista-nav se
     queda en su fila de siempre — visible, usable, sin depender del
     botón. */
  html.nav-js .lista-nav {
    position: fixed;
    inset: 0;
    z-index: 200;
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    gap: var(--e-8);
    background: var(--negro);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity var(--dur-noto) var(--ease-noto),
      visibility 0s linear var(--dur-noto);
  }

  html.nav-js .menu-boton[aria-expanded="true"] ~ .lista-nav {
    opacity: 1;
    visibility: visible;
    transition:
      opacity var(--dur-nukitsuke) var(--ease-nukitsuke),
      visibility 0s linear 0s;
  }

  html.nav-js .lista-nav .nav-enlace {
    font-size: var(--t-titulo);
    letter-spacing: 0.03em;
  }
}

/* ==========================================================================
   Pie
   ========================================================================== */

.corte-separador {
  /* 63%: solo por si algún <hr class="corte-separador"> se queda sin el
     style="--corte-pos: …" que pone build.py (ver
     constructor_posiciones_corte) — no debería pasar, pero sin fallback
     un --corte-pos vacío rompe el gradiente entero. La posición real de
     cada separador es determinista por página, no por su posición entre
     hermanos: ver build.py. */
  --corte-pos: 63%;
  position: relative;
  height: 1px;
  border: 0;
  width: 100%;
  margin: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--gris-linea) 6%,
    var(--gris-linea) calc(var(--corte-pos) - 5%),
    var(--rojo-marca) var(--corte-pos),
    var(--rojo-marca) calc(var(--corte-pos) + 3%),
    var(--gris-linea) calc(var(--corte-pos) + 8%),
    var(--gris-linea) 94%,
    transparent 100%
  );
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 320ms var(--ease-nukitsuke);
}

.corte-separador.visible {
  transform: scaleX(1);
}

/* El nav corta de izquierda a derecha; el pie, espejado, de derecha a
   izquierda — mismo corte, sentido opuesto. Ver plantillas/base.html. */
.corte-separador--pie {
  background: linear-gradient(
    270deg,
    transparent 0%,
    var(--gris-linea) 6%,
    var(--gris-linea) calc(var(--corte-pos) - 5%),
    var(--rojo-marca) var(--corte-pos),
    var(--rojo-marca) calc(var(--corte-pos) + 3%),
    var(--gris-linea) calc(var(--corte-pos) + 8%),
    var(--gris-linea) 94%,
    transparent 100%
  );
  transform-origin: right;
}

/* La gota es EXCLUSIVA de un solo separador por página (la marca la clase
   .gota desde loops.js): solo se pinta si esa clase está presente. */
.corte-separador.gota::after {
  content: "";
  position: absolute;
  left: var(--corte-pos);
  top: 100%;
  width: 1px;
  height: 5px;
  background: var(--rojo-marca);
  opacity: 0;
  transform: translateY(-2px);
  animation: gota-corte 900ms ease-in 400ms 1 forwards;
}

@keyframes gota-corte {
  0% {
    opacity: 0;
    transform: translateY(-2px);
  }
  12% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateY(3px);
  }
}

/* Sin margen propio de más: el corte-separador--pie justo encima ya marca
   la transición — un margin-top grande aquí solo duplicaba el corte del
   nav de antes de tener separador y dejaba una franja negra enorme. */

.pie-contenido {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-4);
  padding-block: var(--e-6);
}

.pie a {
  display: inline-block;
  width: auto;
}

.pie-copy {
  color: var(--gris);
  text-decoration: none;
}

/* Hasta ~700px: tres líneas apiladas y centradas (Instagram, Aviso legal,
   copyright) en vez de la fila que no cabe y empuja "Contacto" fuera de
   pantalla. En escritorio, .pie-contenido sigue como está. */
@media (max-width: 700px) {
  .pie-contenido {
    flex-direction: column;
    justify-content: center;
    text-align: center;
  }
}

.pie-enlace:hover,
.pie-enlace:focus-visible {
  color: var(--blanco);
}

.pie-enlace:hover .mitad-sup,
.pie-enlace:hover .mitad-inf,
.pie-enlace:focus-visible .mitad-sup,
.pie-enlace:focus-visible .mitad-inf,
.enlace-grande:hover .mitad-sup,
.enlace-grande:hover .mitad-inf,
.enlace-grande:focus-visible .mitad-sup,
.enlace-grande:focus-visible .mitad-inf {
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.pie-enlace:hover .mitad-sup,
.pie-enlace:focus-visible .mitad-sup,
.enlace-grande:hover .mitad-sup,
.enlace-grande:focus-visible .mitad-sup {
  transform: translateX(5px);
}

.pie-enlace:hover .mitad-inf,
.pie-enlace:focus-visible .mitad-inf,
.enlace-grande:hover .mitad-inf,
.enlace-grande:focus-visible .mitad-inf {
  transform: translateX(-5px);
}

.pie-enlace:hover .corte,
.pie-enlace:focus-visible .corte,
.enlace-grande:hover .corte,
.enlace-grande:focus-visible .corte {
  transform: scaleX(1);
  transition: transform var(--dur-kiritsuke) var(--ease-nukitsuke);
}

/* ==========================================================================
   Hero — portada
   ========================================================================== */

.hero {
  position: relative;
  display: grid;
  place-items: center;
  min-height: min(78vh, 720px);
}

/* Marca de agua decorativa detrás del nombre — sin el corte diagonal,
   exclusivo del logo del nav, y sin animación de dibujo: aquí es un fondo,
   no un logo interactivo. */
.hero-marca {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* viewBox cuadrado: height define también el ancho. Sin el término vw,
     en móvil estrecho se desborda horizontalmente y fuerza scroll lateral
     de toda la página — el límite de altura solo no basta. */
  height: min(80vh, 640px, 85vw);
  width: auto;
  opacity: 0.07;
  color: var(--blanco);
  pointer-events: none;
  z-index: 0;
}

.hero-texto {
  position: relative;
  z-index: 1;
  text-align: center;
}

.hero-nombre {
  position: relative;
  font-size: clamp(2.25rem, 9.5vw, 13rem);
  letter-spacing: 0.05em;
  line-height: 1;
  white-space: nowrap;
  margin: 0;
}

/* Cicatriz sobre el nombre al pasar el ratón — misma equis asimétrica que
   icono_corte (_macros.html): dos trazos, nunca iguales de largo. Aquí el
   sentido "/" es el más largo, "\" el más corto. Nukitsuke al entrar
   (rápido), nōtō al salir (el doble de lento) — igual que .mitad-sup/inf. */
.hero-nombre::before,
.hero-nombre::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  height: 3px;
  background: var(--rojo-marca);
  opacity: 0;
  pointer-events: none;
  transform-origin: center;
  transition:
    transform var(--dur-noto) var(--ease-noto),
    opacity var(--dur-noto) var(--ease-noto);
}

.hero-nombre::before {
  width: 62%;
  transform: translate(-50%, -50%) rotate(-38deg) scaleX(0);
}

.hero-nombre::after {
  width: 44%;
  transform: translate(-50%, -50%) rotate(38deg) scaleX(0);
}

.hero-nombre:hover::before,
.hero-nombre:hover::after {
  opacity: 1;
  transition:
    transform var(--dur-nukitsuke) var(--ease-nukitsuke),
    opacity var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.hero-nombre:hover::before {
  transform: translate(-50%, -50%) rotate(-38deg) scaleX(1);
}

.hero-nombre:hover::after {
  transform: translate(-50%, -50%) rotate(38deg) scaleX(1);
}

/* Chiburi — la sangre cae de las dos puntas de abajo del corte (donde "/"
   termina abajo-izquierda y "\" termina abajo-derecha), no del centro ni
   a lo largo del trazo. Posición en em, relativa a la propia h1: el corte
   es % del ancho del nombre, así que sus puntas también lo son. */
.hero-sangre {
  position: absolute;
  top: calc(50% + 1.38em);
  left: calc(50% - 1.76em);
  width: 3px;
  height: 16px;
  background: var(--rojo-marca);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%);
  /* Encima de los dos trazos del corte (el "\" es el último hijo del h1 y
     si no, pinta por encima y las tapa en su propia punta). */
  z-index: 1;
}

.hero-sangre--b {
  top: calc(50% + 0.98em);
  left: calc(50% + 1.25em);
  height: 11px;
}

.hero-nombre:hover .hero-sangre {
  animation: chiburi-hero var(--dur-chiburi) ease-in var(--dur-nukitsuke) 1 forwards;
}

.hero-nombre:hover .hero-sangre--b {
  animation-delay: calc(var(--dur-nukitsuke) + 80ms);
}

@keyframes chiburi-hero {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) translateY(0);
  }
  15% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) translateY(22px);
  }
}

.hero-linea {
  margin-top: var(--e-6);
}

/* Móvil estrecho: la línea de posicionamiento no cabe en una sola línea —
   se parte exactamente por el punto medio (nunca donde el navegador decida),
   una línea por oficio, centradas, y el punto se oculta. */
@media (max-width: 479px) {
  .hero-linea {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-1);
  }

  .hero-linea .posicionamiento-separador {
    display: none;
  }

  /* El clamp de escritorio deja el nombre pegado a su mínimo (2.25rem) en
     todo este rango. 12.5vw lo sube a ~90% del ancho sin desbordar a
     320px (medido, no a ojo), en una sola línea. */
  .hero-nombre {
    font-size: clamp(2.25rem, 12.5vw, 4rem);
  }
}

/* ==========================================================================
   Secciones de portada (bodas / videoclips / desarrollo web / contacto)
   ========================================================================== */

.seccion {
  padding-block: var(--e-16);
}

/* ==========================================================================
   Cierre de la portada — único enlace de este tipo en el sitio, ver 6.
   ========================================================================== */

.cierre-envoltorio {
  padding-block: var(--e-24);
  text-align: center;
}

.cierre {
  position: relative;
  display: inline-block;
  font-size: clamp(1.75rem, 5vw, 3.25rem);
  letter-spacing: 0.05em;
  color: var(--gris);
  text-decoration: none;
}

.cierre:hover,
.cierre:focus-visible {
  color: var(--blanco);
}

.cierre:hover .mitad-sup,
.cierre:hover .mitad-inf,
.cierre:focus-visible .mitad-sup,
.cierre:focus-visible .mitad-inf {
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

/* Desplazamiento proporcional al tamaño del texto (em, no 5px fijos):
   con .cierre llegando a 3.25rem, 5px fijos apenas se notan — en nav,
   pie, etc. 5px ya son ~1/3 de su font-size; aquí se iguala esa
   proporción para el mismo gesto a una escala mucho mayor. */
.cierre:hover .mitad-sup,
.cierre:focus-visible .mitad-sup {
  transform: translateX(0.12em);
}

.cierre:hover .mitad-inf,
.cierre:focus-visible .mitad-inf {
  transform: translateX(-0.12em);
}

.cierre:hover .corte,
.cierre:focus-visible .corte {
  transform: scaleX(1);
  transition: transform var(--dur-kiritsuke) var(--ease-nukitsuke);
}

.seccion-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--e-6);
}

.seccion-titulo {
  font-size: var(--t-seccion);
  letter-spacing: 0.12em;
}

.seccion-enlace {
  color: var(--gris);
  text-decoration: none;
}

.seccion-enlace:hover {
  color: var(--blanco);
}

/* ==========================================================================
   Rejilla y tarjetas de pieza — 5.4 / 8.3
   ========================================================================== */

.rejilla {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--e-6);
}

@media (min-width: 640px) {
  .rejilla {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .rejilla {
    grid-template-columns: repeat(3, 1fr);
  }
}

.tarjeta {
  display: block;
  color: var(--blanco);
  text-decoration: none;
}

.tarjeta-marco {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--negro);
  border: 1px solid var(--gris-linea);
  overflow: hidden;
}

.tarjeta-poster,
.tarjeta-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.tarjeta-vacia {
  width: 100%;
  height: 100%;
  background: var(--gris-linea);
}

/* Debajo de la miniatura, sobre el fondo de la página — no encima de la
   imagen: ahí se perdía la lectura en pósters claros o muy cargados
   (Sayonara, por ejemplo). Blanco liso, sin degradado detrás ni rojo en
   el texto (--rojo-marca nunca en texto). */
.tarjeta-titulo {
  display: block;
  margin-top: var(--e-3);
  font-size: 1rem;
  letter-spacing: 0.1em;
  color: var(--blanco);
}

.tarjeta-dato {
  margin-top: var(--e-1);
}

.tarjeta:hover .tarjeta-marco {
  border-color: var(--rojo-marca);
}

/* ==========================================================================
   Reproductor — fachada de vídeo, 8.1
   ========================================================================== */

.reproductor {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--negro);
  border: 1px solid var(--gris-linea);
  overflow: hidden;
}

.reproductor-poster {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.reproductor-boton {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

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

.reproductor-vacio {
  width: 100%;
  height: 100%;
  background: var(--gris-linea);
}

.reproductor-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Botón de reproducción — un triángulo de play a trazo, sin relleno, sin
   aro ni más adornos. Tamaño sobrio y centrado sobre el póster: 56-64px en
   móvil (no se come el póster), 80-96px en escritorio. El viewBox del SVG
   es 48x48 y el path no cambia — al escalar con width/height, el stroke y
   el dasharray (en unidades del viewBox) se escalan con él sin recalcular
   nada: el trazo no pierde proporción ni grosor relativo. */
.reproductor-icono {
  width: clamp(56px, 8vw, 96px);
  height: clamp(56px, 8vw, 96px);
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.6));
}

/* Al pasar el ratón o el foco, el trazo se redibuja — mismo gesto nukitsuke
   que .hero-nombre:hover. Dasharray fijo: el perímetro del triángulo
   M17 14 L34 24 L17 34 Z son dos lados de √(17²+10²)=√389≈19.72 más el
   cierre vertical de 20, total ≈59.5 — en unidades del viewBox, válido a
   cualquier tamaño de pantalla. */
.reproductor-trazo {
  stroke-dasharray: 59.5;
  stroke-dashoffset: 0;
}

.reproductor-boton:hover .reproductor-trazo,
.reproductor-boton:focus-visible .reproductor-trazo {
  animation: reproductor-trazo-redibujar var(--dur-nukitsuke) var(--ease-nukitsuke);
}

@keyframes reproductor-trazo-redibujar {
  from {
    stroke-dashoffset: 59.5;
  }
  to {
    stroke-dashoffset: 0;
  }
}

.reproductor-iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ==========================================================================
   Barra de controles propia — solo Vimeo con sitio.vimeo.controles_propios
   a true (ver 8.1). Oculta hasta que player.js la active tras cargar el SDK.
   ========================================================================== */

.reproductor-controles {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-2) var(--e-3);
  background: linear-gradient(to top, rgba(11, 11, 11, 0.85), transparent);
}

.rc-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--blanco);
  cursor: pointer;
  transition: color var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.rc-boton:hover,
.rc-boton:focus-visible {
  color: var(--rojo-texto);
}

.rc-icono {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* El atributo hidden no trae display:none de serie para SVG (su hoja de
   estilos por defecto es otra, sin esa regla) — hay que forzarlo a mano o
   play/pausa y sonido/silencio se ven los dos iconos a la vez. */
.rc-icono[hidden] {
  display: none;
}

.rc-progreso {
  flex: 1;
  display: flex;
  align-items: center;
  height: 32px;
  cursor: pointer;
}

.rc-progreso-pista {
  position: relative;
  width: 100%;
  height: 3px;
  background: rgba(242, 240, 236, 0.3);
}

.rc-progreso-relleno {
  position: absolute;
  inset: 0;
  transform: scaleX(0);
  transform-origin: left;
  background: var(--rojo-marca);
}

.rc-progreso:focus-visible {
  outline: 1.5px solid var(--rojo-marca);
  outline-offset: 4px;
}

/* ==========================================================================
   Ficha (boda / videoclip / proyecto web)
   ========================================================================== */

.ficha {
  padding-block: var(--e-16);
}

.ficha-titulo {
  font-size: var(--t-titulo);
  letter-spacing: 0.05em;
  margin: 0 0 var(--e-8);
}

/* Productora enlazada — mismo efecto de corte que el nav (ver 6.3) */
.ficha-fila-enlace {
  position: relative;
  display: inline-block;
  color: var(--blanco);
  text-decoration: none;
}

.ficha-fila-enlace:hover .mitad-sup,
.ficha-fila-enlace:hover .mitad-inf,
.ficha-fila-enlace:focus-visible .mitad-sup,
.ficha-fila-enlace:focus-visible .mitad-inf {
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.ficha-fila-enlace:hover .mitad-sup,
.ficha-fila-enlace:focus-visible .mitad-sup {
  transform: translateX(5px);
}

.ficha-fila-enlace:hover .mitad-inf,
.ficha-fila-enlace:focus-visible .mitad-inf {
  transform: translateX(-5px);
}

.ficha-fila-enlace:hover .corte,
.ficha-fila-enlace:focus-visible .corte {
  transform: scaleX(1);
  transition: transform var(--dur-kiritsuke) var(--ease-nukitsuke);
}

/* Ficha técnica — tabla de metadatos, oculta filas sin valor (ver build.py) */
.ficha-tecnica {
  display: grid;
  gap: var(--e-2);
  margin: var(--e-6) 0 var(--e-8);
}

.ficha-fila {
  display: flex;
  gap: var(--e-4);
  padding-block: var(--e-2);
  border-top: 1px solid var(--gris-linea);
}

.ficha-fila dt {
  flex: 0 0 auto;
  width: 8rem;
  color: var(--gris);
}

.ficha-fila dd {
  margin: 0;
  color: var(--blanco);
}

/* Estado de publicación de un proyecto web (ver 5.): solo texto, gris,
   sin fondo ni borde — nunca una insignia de color. */
.etiqueta-estado {
  color: var(--gris);
}

/* Ficha de proyecto web — capturas, enlace en vivo, problema/solución */
.capturas {
  display: grid;
  gap: var(--e-4);
}

.capturas img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--gris-linea);
}

.capturas a:hover img {
  border-color: var(--rojo-marca);
}

.captura-vacia {
  aspect-ratio: 16 / 9;
  background: var(--gris-linea);
}

.ficha-enlace {
  margin: var(--e-6) 0 0;
}

.ficha-bloque {
  margin: var(--e-8) 0;
  max-width: 62ch;
}

.ficha-trabajo {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  margin: 0;
  padding: 0;
  color: var(--blanco);
  max-width: 62ch;
}

.ficha-bloque h2 {
  margin: 0 0 var(--e-2);
}

.ficha-bloque p {
  margin: 0;
  color: var(--blanco);
}

/* Anterior / siguiente — 6.8: solo la palabra y el icono, sin título de pieza */
.anterior-siguiente {
  display: flex;
  justify-content: space-between;
  gap: var(--e-6);
  padding-block: var(--e-8);
}

.as-lado {
  flex: 1;
  min-width: 0;
}

.as-lado-derecha {
  text-align: right;
}

.as-enlace {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  text-decoration: none;
}

.as-lado-derecha .as-enlace {
  justify-content: flex-end;
}

.as-palabra {
  position: relative;
  display: inline-block;
  padding: 4px 0;
  font-size: var(--t-nav);
  letter-spacing: 0.1em;
  color: var(--gris);
}

.as-enlace:hover .as-palabra,
.as-enlace:focus-visible .as-palabra {
  color: var(--blanco);
}

.as-enlace:hover .as-palabra .mitad-sup,
.as-enlace:hover .as-palabra .mitad-inf,
.as-enlace:focus-visible .as-palabra .mitad-sup,
.as-enlace:focus-visible .as-palabra .mitad-inf {
  transition: transform var(--dur-nukitsuke) var(--ease-nukitsuke);
}

.as-enlace:hover .as-palabra .mitad-sup,
.as-enlace:focus-visible .as-palabra .mitad-sup {
  transform: translateX(5px);
}

.as-enlace:hover .as-palabra .mitad-inf,
.as-enlace:focus-visible .as-palabra .mitad-inf {
  transform: translateX(-5px);
}

.as-enlace:hover .as-palabra .corte,
.as-enlace:focus-visible .as-palabra .corte {
  transform: scaleX(1);
  transition: transform var(--dur-kiritsuke) var(--ease-nukitsuke);
}

/* Icono — dos trazos asimétricos (nunca una equis tipográfica, ver 6.8) */
.as-icono {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  color: var(--gris);
  transition: color var(--dur-nukitsuke) var(--ease-nukitsuke);
}

@media (max-width: 699px) {
  .as-icono {
    width: 30px;
    height: 30px;
    flex-basis: 30px;
  }
}

.as-lado-izquierda .as-icono {
  transform: scaleX(-1);
}

.as-enlace:hover .as-icono,
.as-enlace:focus-visible .as-icono {
  color: var(--rojo-marca);
}

/* Longitudes exactas de cada trazo, ambos segmentos rectos:
   M4 5 L20 19 → √(16²+14²) ≈ 21.26 · M17 6 L8 18 → √(9²+12²) = 15 */
.as-trazo-largo {
  stroke-dasharray: 21.26;
}

.as-trazo-corto {
  stroke-dasharray: 15;
}

.as-enlace:hover .as-trazo-largo,
.as-enlace:focus-visible .as-trazo-largo {
  animation: as-dibujar-largo var(--dur-nukitsuke) var(--ease-nukitsuke) backwards;
}

.as-enlace:hover .as-trazo-corto,
.as-enlace:focus-visible .as-trazo-corto {
  animation: as-dibujar-corto var(--dur-nukitsuke) var(--ease-nukitsuke) 80ms backwards;
}

@keyframes as-dibujar-largo {
  from {
    stroke-dashoffset: 21.26;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes as-dibujar-corto {
  from {
    stroke-dashoffset: 15;
  }
  to {
    stroke-dashoffset: 0;
  }
}

/* ==========================================================================
   Páginas de listado (bodas / videoclips / web)
   ========================================================================== */

.pagina-listado {
  padding-block: var(--e-16);
}

.pagina-listado h1 {
  font-size: var(--t-titulo);
  letter-spacing: 0.05em;
  margin: 0 0 var(--e-2);
}

/* Cifra de trayectoria (sitio.trayectoria) — nunca en portada, nunca como
   contador ni tarjeta: una línea de metadato más, del mismo peso que el
   resto (ver docs/especificaciones.md, "Cifras en listado"). */
.listado-cifra {
  margin: 0 0 var(--e-8);
}

/* ==========================================================================
   Contacto
   ========================================================================== */

.pagina-contacto {
  padding-block: var(--e-24);
  text-align: center;
}

/* El mínimo no es solo estético: .mitad-sup/.mitad-inf (el corte, ver
   .corte-texto) llevan white-space:nowrap aunque estén ocultos en
   reposo, y a 320px un mínimo de 2.5rem ya desborda horizontalmente
   (comprobado, no a ojo) — "Trabajemos juntos" entero sin partir no cabe
   en el ancho útil. 2rem sí cabe, con margen. */
.pagina-contacto-titulo {
  font-size: clamp(2rem, 9vw, 6rem);
  letter-spacing: 0.03em;
  margin: 0 0 var(--e-16);
}

.contacto-email {
  margin: 0 0 var(--e-8);
}

.enlace-grande {
  position: relative;
  display: inline-block;
  padding: 4px 0;
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  color: var(--blanco);
  text-decoration: none;
  cursor: pointer;
}

.enlace-grande:hover {
  color: var(--blanco);
}

/* El email real, para que se pueda seleccionar y copiar entero — más
   grande que el resto de enlaces, y partible si no cabe en una línea en
   móvil (ver corte_texto_plano en _macros.html). */
.contacto-email-enlace {
  font-size: clamp(1.5rem, 5.5vw, 3rem);
  overflow-wrap: anywhere;
}

.contacto-whatsapp {
  margin: 0 0 var(--e-8);
}

/* Instagram a la izquierda, LinkedIn a la derecha: caja fit-content
   centrada bajo el email, para que sus extremos queden a la altura de
   donde empieza y termina el texto del email. En móvil, si no caben en
   una fila, se apilan centrados. */
.contacto-redes {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  width: fit-content;
  max-width: 100%;
  margin: var(--e-8) auto 0;
  gap: var(--e-8);
}

@media (max-width: 480px) {
  .contacto-redes {
    flex-direction: column;
    align-items: center;
    width: 100%;
    gap: var(--e-4);
  }
}

/* ==========================================================================
   Aviso legal
   ========================================================================== */

.pagina-legal {
  padding-block: var(--e-16);
  max-width: 70ch;
}

.pagina-legal h1 {
  font-size: var(--t-titulo);
  letter-spacing: 0.05em;
  margin: 0 0 var(--e-8);
}

.bloque-legal {
  margin-top: var(--e-8);
  border-top: 1px solid var(--gris-linea);
  padding-top: var(--e-4);
}

.bloque-legal h2 {
  margin: 0 0 var(--e-3);
}

.bloque-legal p {
  margin: 0 0 var(--e-3);
  color: var(--blanco);
}

.bloque-legal code {
  font-family: var(--fuente-dato);
}

.datos-titular {
  display: grid;
  gap: var(--e-2);
  margin: 0;
}

.datos-titular > div {
  display: flex;
  gap: var(--e-4);
}

.datos-titular dt {
  width: 8rem;
  color: var(--gris);
}

.datos-titular dd {
  margin: 0;
  /* min-width:0 — por defecto un hijo flex no se encoge más allá del
     ancho de su contenido sin partir, así que un email largo (p. ej.
     "contacto@daigorobatto.com") empujaba la fila entera fuera de la
     pantalla en vez de partirse en dos líneas. */
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--blanco);
}

/* ==========================================================================
   404 — corte rojo a pantalla completa
   ========================================================================== */

.pagina-404 {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--e-4);
  text-align: center;
  overflow: hidden;
}

.corte-404 {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 3px;
  background: var(--rojo-marca);
  transform: scaleX(0);
  transform-origin: center;
  animation: barrer-404 var(--dur-nukitsuke) var(--ease-nukitsuke) forwards;
}

@keyframes barrer-404 {
  to {
    transform: scaleX(1);
  }
}

.pagina-404 h1 {
  font-size: var(--t-hero);
  letter-spacing: 0.06em;
  color: var(--rojo-texto);
  margin: 0;
}

.pagina-404 p {
  color: var(--gris);
  margin: 0;
}

.volver {
  margin-top: var(--e-4);
  color: var(--blanco);
  text-decoration: none;
  border-bottom: 1px solid var(--gris-linea);
  padding-bottom: 2px;
}

.volver:hover {
  color: var(--rojo-texto);
  border-color: var(--rojo-texto);
}
