/* ==========================================================================
   COMPONENTS — nav, cursor, botones, footer, project rows, disciplinas
   ========================================================================== */

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--edge);
  mix-blend-mode: difference;
  color: var(--color-ink); /* claro por default — el truco del difference-blend necesita un tono brillante como referencia */
  pointer-events: none;
}
.nav a, .nav button { pointer-events: auto; }

.nav__logo {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 500;
  letter-spacing: var(--tracking-tight);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}

.nav__link {
  position: relative;
  padding-bottom: 2px;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="page"]::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* ---------- Nav — menú mobile (hamburguesa) ---------- */
/* Cuando el nav pasó de 2 a 4 links (Work/Hall of Frames sumados a
   About/Let's talk) no se tocó mobile — ahí .nav__links seguía siendo un
   flex row sin wrap pensado, y con 4 ahora se parte en dos líneas
   apretadas contra el borde. Acá se resuelve de verdad: <720px
   .nav__links se esconde entera y aparece este botón de hamburguesa, que
   abre un panel de pantalla completa con los mismos links, grandes.
   El botón vive DENTRO de .nav (mix-blend-mode:difference, ver arriba),
   así que hereda gratis el mismo truco de legibilidad sobre cualquier
   fondo — no necesita su propio color especial. El panel .nav-mobile, en
   cambio, NO puede usar ese truco (es un fondo sólido, no texto) así que
   lleva --color-bg de posta. */
.nav__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
  gap: 5px;
  width: 26px;
  height: 20px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav__toggle-bar {
  display: block;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
/* El botón "morphea" de ☰ a ✕ con las mismas dos barras — nunca un tercer
   ícono que hay que cross-fadear, solo rotarlas hasta que se crucen en el
   centro (gap 5px + height 1.5px → 3.25px de traslado cierra la cruz). */
html.nav-open .nav__toggle-bar:nth-child(1) { transform: translateY(3.25px) rotate(45deg); }
html.nav-open .nav__toggle-bar:nth-child(2) { transform: translateY(-3.25px) rotate(-45deg); }

.nav-mobile {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: var(--color-bg);
  display: flex;
  align-items: center;
  padding: var(--space-xl) var(--edge);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-14px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), visibility 0s var(--dur-base);
}
html.nav-open .nav-mobile {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), visibility 0s;
}
/* El fondo entero se bloquea mientras el panel está abierto — Lenis corre
   con smoothTouch:false (ver motion.js), así que en el touch/mobile donde
   este menú existe el scroll de fondo ya es 100% nativo: alcanza con
   overflow:hidden acá, sin tener que pausar ningún motor de scroll. */
html.nav-open { overflow: hidden; }

.nav-mobile__links {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.nav-mobile__link {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}
.nav-mobile__index {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--color-muted);
}

@media (max-width: 719px) {
  .nav__links { display: none; }
  .nav__toggle { display: flex; }
}
@media (min-width: 720px) {
  /* Red de seguridad: si por lo que sea el panel quedó con la clase
     nav-open puesta (p. ej. se abrió en mobile y después se agrandó la
     ventana sin que el JS llegue a cerrarlo — nav.js igual lo cierra al
     cruzar el breakpoint, esto es el respaldo en CSS puro) nunca se
     muestra en desktop. */
  .nav-mobile { display: none; }
}

/* ---------- Custom cursor ---------- */
/* .cursor es solo un ancla de posición (0×0) — la única propiedad que JS
   toca por frame es su transform (translate3d), nunca width/height/top/left.
   El círculo visible vive en ::before y crece/decrece en hover vía
   transform:scale, así el cambio de tamaño es tan barato en GPU como el
   movimiento mismo (nunca animamos width/height). */
.cursor {
  position: fixed;
  top: 0; left: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: var(--z-cursor);
  will-change: transform;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cursor::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  box-sizing: border-box;
  width: var(--cursor-size);
  height: var(--cursor-size);
  border-radius: 50%;
  background-color: white;
  border: 1.5px solid transparent; /* siempre presente, invisible por default — así el borde de "open" no cambia el tamaño de la caja al aparecer */
  mix-blend-mode: difference;
  opacity: 0;
  transform: translate(-50%, -50%) scale(1);
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
  will-change: transform, opacity;
}
.cursor.is-active::before { opacity: 1; }
.cursor.is-hidden::before { opacity: 0; }

.cursor__label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--color-ink);
  opacity: 0;
  white-space: nowrap;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.cursor[data-mode="view"]::before,
.cursor[data-mode="play"]::before,
.cursor[data-mode="open"]::before,
.cursor[data-mode="drag"]::before {
  transform: translate(-50%, -50%) scale(6.8); /* 68px equivalente, ahora vía transform */
}
.cursor[data-mode="view"] .cursor__label,
.cursor[data-mode="play"] .cursor__label,
.cursor[data-mode="open"] .cursor__label,
.cursor[data-mode="drag"] .cursor__label {
  opacity: 1;
}

/* "Play" es el único estado que rompe el blanco/mix-blend genérico: rosa
   sólido — el mismo color que marca "esto reproduce" en los badges estáticos
   más abajo, para que el cursor y el badge cuenten la misma historia. */
.cursor[data-mode="play"]::before {
  background-color: var(--color-accent);
  mix-blend-mode: normal;
}
.cursor[data-mode="play"] .cursor__label {
  color: var(--color-accent-ink);
}

/* "Open" — links que te sacan de donde estás (nav, mailto, next-project,
   volver a Work) en vez de mostrar un preview en el lugar: anillo en vez de
   círculo sólido, para distinguir "esto navega" de "esto se explora acá". */
.cursor[data-mode="open"]::before {
  background-color: transparent;
  border-color: white;
}

@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cursor::before { transition: none; }
}

/* ---------- Play badge ---------- */
/* Marca estática "esto reproduce" en violeta — el custom cursor ya usa este
   mismo color en data-mode="play" (arriba), pero el cursor no existe en touch,
   así que sin esto el violeta nunca llegaría a mostrarse en mobile. Vive sobre
   los mismos contenedores que ya definen data-cursor="play" en el HTML real. */
.showreel__stage[data-cursor="play"]::after,
.work-item[data-cursor="play"] .work-item__media::after,
.media-grid__item[data-cursor="play"]::after,
.case-hero__cover[data-cursor="play"]::after {
  content: "";
  position: absolute;
  z-index: 2;
  bottom: var(--space-xs);
  left: var(--space-xs);
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--color-accent);
  pointer-events: none;
}
.showreel__stage[data-cursor="play"]::before,
.work-item[data-cursor="play"] .work-item__media::before,
.media-grid__item[data-cursor="play"]::before,
.case-hero__cover[data-cursor="play"]::before {
  content: "";
  position: absolute;
  z-index: 3;
  bottom: calc(var(--space-xs) + 1.375rem - 6px);
  left: calc(var(--space-xs) + 1.375rem - 4px);
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent var(--color-accent-ink);
  pointer-events: none;
}

/* Cuando alguno de estos containers además reproduce video real con play
   explícito del usuario (ver [data-video-trigger] / case-video.js), la
   insignia se esconde apenas arranca — ya cumplió su función de avisar
   "esto reproduce". Una sola regla acá, no repetida por selector, para que
   cualquier badge nuevo que se sume a la lista de arriba quede cubierto
   sin tener que acordarse de agregarlo dos veces. */
.showreel__stage.is-playing[data-cursor="play"]::after,
.work-item.is-playing[data-cursor="play"] .work-item__media::after,
.media-grid__item.is-playing[data-cursor="play"]::after,
.case-hero__cover.is-playing[data-cursor="play"]::after,
.showreel__stage.is-playing[data-cursor="play"]::before,
.work-item.is-playing[data-cursor="play"] .work-item__media::before,
.media-grid__item.is-playing[data-cursor="play"]::before,
.case-hero__cover.is-playing[data-cursor="play"]::before {
  display: none;
}

/* ---------- Buttons / links ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid currentColor;
  border-radius: var(--radius-full);
  overflow: hidden;
  position: relative;
}
.btn__arrow { transition: transform var(--dur-base) var(--ease-out); }
.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow { transform: translateX(6px); }
/* A pedido explícito: el rosa de marca tiene que aparecer en más lugares
   que solo el cursor/badges de play — al menos el hover de los botones, con
   un fill completo (no alcanza con solo cambiar el borde, "apenas se ve").
   Primer intento usaba --color-focus (se oscurece dentro de .showreel/
   .services para pasar contraste sobre el fondo claro) — pero eso hacía que
   el hover se viera más violeta que rosa ahí. A pedido explícito otra vez:
   siempre el rosa VÍVIDO de verdad (--color-accent, #e015d8), nunca la
   variante oscurecida, en cualquier sección — mismo criterio que ya se
   había aplicado en el color del manifiesto en una ronda anterior. Con
   texto SIEMPRE oscuro (--color-accent-ink) encima: el vívido no pasa
   contraste de texto con ink claro (3.45:1, falla AA en texto chico) pero
   sí con ink oscuro (4.72:1) — así que el texto no puede seguir al fondo
   de la sección acá, tiene que ser siempre el oscuro. */
.btn {
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.btn:hover,
.btn:focus-visible {
  background: var(--color-accent);
  color: var(--color-accent-ink);
  border-color: var(--color-accent);
}

.btn--solid {
  background: var(--color-ink);
  color: var(--color-bg);
  border-color: var(--color-ink);
}
.btn--solid:hover,
.btn--solid:focus-visible {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
}

.link-underline {
  position: relative;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out);
}
.link-underline:hover,
.link-underline:focus-visible {
  background-size: 100% 1px;
}

/* ---------- Section scaffolding ---------- */
.section {
  position: relative;
  padding-block: var(--space-2xl);
}
.section--tight { padding-block: var(--space-xl); }

.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
  border-bottom: 1px solid var(--color-line);
  padding-bottom: var(--space-sm);
}

.section__title {
  font-size: var(--fs-xxl);
  text-transform: uppercase;
}

/* ---------- Grid lines (sutil, refuerza el sistema editorial en secciones oscuras) ---------- */
.grid-lines {
  position: relative;
}
.grid-lines::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(var(--overlay-rgb), 0.05) 0,
    rgba(var(--overlay-rgb), 0.05) 1px,
    transparent 1px,
    transparent calc((100% - (11 * var(--grid-gap))) / 12 + var(--grid-gap))
  );
  background-position: var(--edge) 0;
  opacity: 0.6;
}

/* ---------- Footer ---------- */
.footer {
  background: var(--color-inverse-bg);
  color: var(--color-inverse-ink);
  padding: var(--space-xl) var(--edge) 0;
  overflow: hidden;
  /* Bloque invertido: fondo dorado claro, así que los tokens de texto/foco/
     énfasis se reescriben acá para seguir siendo legibles y consistentes. */
  --color-ink: var(--color-inverse-ink);
  --color-bg-alt: #ecdba8;
  --color-ink-soft: #4a3a63;
  --color-muted: #6c5c85;
  --overlay-rgb: 23, 11, 41;
  --color-emphasis: var(--color-accent-text);
  --color-mask: var(--color-inverse-bg);
  --color-focus: var(--color-accent-text);
}
.footer__top {
  display: grid;
  gap: var(--space-lg);
}
.footer__headline {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 1.2rem + 5vw, 6rem);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  max-width: 16ch;
}
.footer__cta {
  margin-top: var(--space-md);
}
.footer__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: 1px solid rgba(var(--overlay-rgb),0.16);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: rgba(var(--overlay-rgb),0.6);
}
@media (min-width: 720px) {
  .footer__grid { grid-template-columns: repeat(4, 1fr); }
}
.footer__group { display: grid; gap: var(--space-2xs); }
.footer__group strong { display: block; color: var(--color-inverse-ink); margin-bottom: var(--space-2xs); }
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
  padding-bottom: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: rgba(var(--overlay-rgb),0.5);
  letter-spacing: var(--tracking-wide);
}

/* ---------- Firma tipográfica gigante — el "último frame" de la pieza ---------- */
/* Antes se "escribía" de izquierda a derecha atada al scroll continuo
   (--scroll-p vía scroll-story.js). Volvió a pedido a una versión anterior:
   el nombre entra de una sola vez al llegar al footer, letra por letra,
   deslizándose de abajo hacia arriba — data-reveal="letters" (mismo motor
   IntersectionObserver que el resto del sitio, ver reveal.js/base.css), no
   un scrub aparte. scroll-story.js ya no toca este elemento. */
.footer__signature {
  display: block;
  width: 100%;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(4.5rem, 1rem + 21vw, 21rem);
  line-height: 0.78;
  letter-spacing: -0.045em;
  color: var(--color-inverse-ink);
  white-space: nowrap;
  user-select: none;
}

/* ---------- Media placeholder (usado hasta que se reemplacen assets reales) ---------- */
.media-ph {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ph-ratio, 4 / 5);
  background:
    repeating-linear-gradient(135deg, rgba(var(--overlay-rgb),0.05) 0 2px, transparent 2px 14px),
    var(--color-bg-alt);
  border: 1px solid var(--color-line);
  display: flex;
  align-items: flex-end;
  padding: var(--space-xs);
  overflow: hidden;
}
.media-ph__label {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ---------- Page transition overlay ---------- */
/* Fallback para navegadores sin View Transitions API nativa (ver
   transitions.js) — una cortina en clip-path del color de fondo real del
   sitio, nunca negro ni un flash claro sobre un sitio de tema oscuro.
   Mismo lenguaje visual que el ::view-transition-new(root) nativo en
   base.css (clip-path, sube desde abajo) — así, tenga o no el navegador
   soporte nativo, la transición se lee igual. */
.page-transition {
  position: fixed;
  inset: 0;
  z-index: var(--z-transition);
  background: var(--color-bg);
  clip-path: inset(100% 0 0 0);
  pointer-events: none;
}
.page-transition.is-covering {
  clip-path: inset(0% 0 0 0);
  transition: clip-path var(--dur-slow) var(--ease-emphasis);
}
.page-transition.is-revealing {
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--dur-slow) var(--ease-emphasis);
}
