/* =========================================================
   Traza — hoja de estilos del sitio
   Editorial minimalista: papel, carbón y un acento terracota.
   Todos los valores de color/tipografía/espaciado vienen de tokens.css
   (ver diseno/claude/tokens/ en el proyecto para la fuente de verdad).
   ========================================================= */

/* ---- Tipografías propias del sitio (OFL, fonts/OFL.txt) ----
   Archivo e Inter, subconjunto latino en woff2, tal como las sirve Google
   Fonts pero desde el propio sitio. Son fuentes variables (un archivo por
   familia) y se declaran solo los pesos que se usan: Archivo 400–700 e
   Inter 400. Para otro peso de Inter basta ampliar su font-weight (el
   archivo ya lo trae). Se precargan en el <head> de cada página. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---- Reset ligero ---- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

:root {
  /* Retícula común: margen lateral, radio del anillo (lo
     ajusta js/anillo.js) y alto que ocupa la cabecera fija, usado para que
     lo que queda debajo (filtro "sticky", cabecera del detalle) no se tape. */
  --hm: min(6.25vw, 100px);
  --ring-r: min(35vh, 24.06vw);
  --header-height: calc(var(--hm) + 48px);
  --paper: #FAFAF7; /* papel real de Traza (no cambia con el tema de la página) */
}
@media (max-width: 767px) {
  :root { --hm: 25px; --ring-r: 47.4vw; }
}

/* El atributo [hidden] debe ganar siempre sobre cualquier display: grid/flex
   de un componente, para que los estados (cargando / vacío / error / contenido)
   sean mutuamente excluyentes y nunca se superpongan. */
[hidden] { display: none !important; }
img { max-width: 100%; display: block; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, p, dl, dd, dt, figure { margin: 0; }
input { font: inherit; }

/* Sin desplazamiento animado del navegador: el suavizado lo hace js/scroll.js. */
html { scroll-behavior: auto; }

body {
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-text);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  min-width: 375px;
  overflow-x: hidden;
}

/* Tema de la página (cambia con la navegación interna): fondo y color base. */
body[data-theme="dark"] { background: var(--color-carbon-warm); color: var(--paper); }
a, button { -webkit-tap-highlight-color: transparent; }

/* ---- Foco visible (accesibilidad) ---- */
:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--color-ink);
  color: var(--color-paper);
  padding: var(--space-3) var(--space-5);
  z-index: var(--z-toast);
}
.skip-link:focus { left: var(--space-4); top: var(--space-4); }

/* ---- Tipografía base ---- */
.eyebrow {
  font-family: var(--font-display);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-gray-700);
  font-weight: var(--weight-medium);
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-heading);
  color: var(--color-ink);
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
/* Región de anuncios de la navegación: fija, para no alargar la página. */
[data-nav-live] { position: fixed !important; top: 0; left: 0; }

/* =========================================================
   Cabecera persistente
   Sin fondo ni borde, sobre el margen, igual en todas las páginas: logotipo
   a la izquierda y ES/EN · Proyectos|Inicio · Nosotros a la derecha. Proyectos
   (equivalente a All) e Inicio (Focus) comparten ranura. En el detalle, X
   arriba al centro; en nosotros, X en lugar del logotipo. Los cambios los
   anima js/nav.js; estos son los estados quietos (y los de sin JavaScript).
   ========================================================= */
.site-header {
  position: fixed;
  top: var(--hm);
  left: var(--hm);
  right: var(--hm);
  z-index: var(--z-header);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  color: var(--paper);
  pointer-events: none;
}
.site-header[data-tone="dark"] { color: var(--color-ink); }
.site-header > *, .nav-menu > * { pointer-events: auto; }

/* Marca (js/data.js, brand): nombre en letras o logotipo en imagen. Un
   nombre largo pasa a dos líneas antes de llegar a la X centrada del detalle. */
.brand {
  max-width: calc(50% - 22.5px - 16px);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 18px;
  line-height: 25px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}
/* Logotipo en imagen de una sola tinta: toma el color de la cabecera (papel
   sobre las páginas oscuras, tinta en el detalle) con el mismo cambio de
   700 ms lineal que el texto. */
.brand__logo {
  display: block;
  width: auto;
  max-width: 100%;
  height: 25px;
  object-fit: contain;
  object-position: left center;
  filter: brightness(0) invert(0.98);
  transition: filter 700ms linear;
}
.site-header[data-tone="dark"] .brand__logo { filter: brightness(0) invert(0.07); }

.nav-menu {
  display: flex;
  align-items: flex-start;
  gap: 60px;
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 21px;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
}
.nav-slot { display: inline-grid; }
.nav-slot__item { grid-area: 1 / 1; text-align: right; }
.nav-slot__item, .nav-about { position: relative; }
/* Subrayado con el acento al pasar el ratón (y en la página actual). */
.nav-slot__item::after, .nav-about::after {
  content: "";
  position: absolute;
  left: 0; right: 100%; bottom: -3px;
  height: 1px;
  background: var(--color-accent);
  transition: right 450ms var(--ease-c7);
}
.nav-slot__item:hover::after, .nav-about:hover::after, .nav-about[aria-current="page"]::after { right: 0; }

/* Selector de idioma: ES y EN en cajas de 60 px
   (35 en móvil); el activo con el acento y opacidad 1, el otro al 40 %. El
   estado es --on (0..1), que js/nav.js anima durante el cambio (700 ms,
   ease). El acento claro sobre fondo oscuro y el terracota sobre papel. */
@property --lang-on { syntax: "<color>"; inherits: true; initial-value: transparent; }
.site-header { --lang-on: var(--color-accent-light); transition: --lang-on 700ms linear; }
.site-header[data-tone="dark"] { --lang-on: var(--color-accent); }
.lang-group { display: flex; margin-right: -20px; }
.lang-btn {
  position: relative;
  width: 60px;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  text-align: center;
  color: color-mix(in srgb, var(--lang-on) calc(var(--on, 0) * 100%), currentColor);
  opacity: calc(0.4 + 0.6 * var(--on, 0));
}
.lang-btn[aria-pressed="true"] { --on: 1; }
.lang-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -3px;
  width: 1.6em;
  height: 1px;
  background: var(--lang-on);
  transform: translateX(-50%) scaleX(0);
  transition: transform 450ms var(--ease-c7);
}
.lang-btn[aria-pressed="false"]:hover::after { transform: translateX(-50%) scaleX(1); }

/* Ranura de Proyectos/Inicio; en nosotros, una línea de 60 px (30 en móvil)
   que escala desde la derecha (js/nav.js, --k de 0 a 1). */
.nav-slot__words, .nav-line { grid-area: 1 / 1; }
.nav-slot__words { display: inline-grid; }
.nav-line {
  align-self: center;
  justify-self: center;
  width: 60px;
  height: 1px;
  background: currentColor;
  opacity: 0.45;
  transform: scaleX(var(--k, 0));
  transform-origin: 100% 50%;
  pointer-events: none;
}
.site-header[data-slot="line"] .nav-line { --k: 1; }

/* X de cierre: caja de 45×45 con dos trazos de 16×1 a ±45°. */
.header-x {
  position: absolute;
  width: 45px;
  height: 45px;
  color: inherit;
  transition: color 450ms var(--ease-c7);
}
/* Con el cursor propio (html.has-cursor) el hover lo dan su disco y su aro:
   el acento invertido por la exclusión se leería azul dentro del disco. */
html:not(.has-cursor) .header-x:hover, .header-x:focus-visible { color: var(--color-accent); }
.header-x span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 1px;
}
.header-x span::before { content: ""; position: absolute; inset: 0; background: currentColor; transform-origin: 0 50%; }
.header-x span:first-child { transform: translate(-50%, -50%) rotate(45deg); }
.header-x span:last-child { transform: translate(-50%, -50%) rotate(-45deg); }
/* Hover de la X: cada trazo se recoge hacia su extremo (C3) y se
   redibuja desde él (700 ms, C4, a los 300 y 550 ms); el segundo, 250 ms
   después del primero. */
@media (hover: hover) {
  .header-x:hover span:first-child::before { animation: traza-x-1 1000ms linear both; }
  .header-x:hover span:last-child::before { animation: traza-x-2 1250ms linear both; }
}
/* Curvas literales: var() no vale como curva dentro de @keyframes (C3 y C4). */
@keyframes traza-x-1 {
  0% { transform: scaleX(1); animation-timing-function: cubic-bezier(.165, .84, .44, 1); }
  30% { transform: scaleX(0); animation-timing-function: cubic-bezier(.77, 0, .175, 1); }
  100% { transform: scaleX(1); }
}
@keyframes traza-x-2 {
  0% { transform: scaleX(1); }
  20% { transform: scaleX(1); animation-timing-function: cubic-bezier(.165, .84, .44, 1); }
  44% { transform: scaleX(0); animation-timing-function: cubic-bezier(.77, 0, .175, 1); }
  100% { transform: scaleX(1); }
}
.header-x--detail { left: calc(50% - 22.5px); top: calc(80px - var(--hm)); }
.header-x--about { left: calc(75px - var(--hm)); top: calc(75px - var(--hm)); }

/* Estados quietos: oculto = 10 px más abajo (el logotipo, 10 px más arriba) y sin opacidad. */
.site-header[data-slot="all"] [data-slot-focus],
.site-header[data-slot="focus"] [data-slot-all],
.site-header[data-slot="none"] .nav-slot__item,
.site-header[data-slot="line"] .nav-slot__item,
.site-header[data-mode="brand"] [data-x-about],
.site-header[data-x="off"] [data-x-detail] {
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
}
.site-header[data-mode="close"] [data-brand] {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
}

@media (max-width: 767px) {
  .brand { font-size: 13px; line-height: 18px; }
  .brand__logo { height: 18px; }
  .nav-menu { gap: 22px; font-size: 10px; line-height: 15px; }
  /* Zona de toque amplia sin mover el texto. */
  .nav-about, .lang-btn { padding: 12px 0; margin: -12px 0; }
  .nav-about::after, .lang-btn::after { bottom: 9px; }
  /* Selector compacto: la X centrada del detalle queda libre a su izquierda. */
  .nav-menu { gap: 0; }
  .lang-group { margin-right: 12px; }
  .lang-btn { width: 30px; }
  /* Proyectos e Inicio viven en la barra inferior; la ranura solo guarda la
     línea de nosotros y solo ocupa sitio allí: crece (700 ms, C1) con la línea
     y el selector se desliza a la izquierda. */
  .nav-slot__words { display: none; }
  .nav-slot {
    width: 0;
    height: 15px;
    overflow: hidden;
    transition: width 700ms var(--ease-c1) 225ms, margin-right 700ms var(--ease-c1) 225ms;
  }
  .site-header[data-slot="line"] .nav-slot { width: 30px; margin-right: 16px; transition-delay: 300ms; }
  .nav-line { width: 30px; }
  .header-x span { width: 12px; }
  .header-x--detail { top: -15px; }
  .header-x--about { left: -15px; top: -18px; }
}

/* =========================================================
   Acceso a WhatsApp (mejora de Traza): sobrio, con el lenguaje del anillo,
   sin verde. En escritorio, abajo a la izquierda (simétrico al contador), en
   un carril que el contenido de cada página deja libre; js/nav.js lo oculta
   si algo visible llega a pasar por debajo. En móvil vive dentro de la barra
   inferior opaca, entre la etiqueta y la flecha derecha.
   ========================================================= */
.whatsapp-float {
  position: fixed;
  z-index: var(--z-whatsapp);
  left: var(--hm);
  bottom: calc(var(--hm) - 13px);
  width: 36px;
  height: 36px;
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(250, 250, 247, 0.3);
  color: var(--paper);
  transition: background-color 450ms var(--ease-c7), border-color 450ms var(--ease-c7), color 450ms var(--ease-c7);
}
body[data-theme="light"] .whatsapp-float { border-color: rgba(18, 18, 18, 0.22); color: var(--color-ink); }
.whatsapp-float svg { width: 16px; height: 16px; }
/* Hover con el lenguaje de los enlaces (el aro del cursor): un aro
   exterior de 1 px entra al 40 % encogiendo de 1,2 a 1 (400 ms lineal y
   600 ms C3) y sale volviendo a 1,2 (700 ms C6); el trazo y el icono pasan
   al acento (450 ms C7). Sin relleno ni verde. */
.whatsapp-float::after {
  content: "";
  position: absolute;
  inset: -9px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  transform: scale(1.2);
  transition: opacity 700ms var(--ease-c6), transform 700ms var(--ease-c6);
  pointer-events: none;
}
@media (hover: hover) {
  html:not(.has-cursor) .whatsapp-float:hover,
  html:not(.has-cursor) body[data-theme] .whatsapp-float:hover { border-color: var(--color-accent-light); color: var(--color-accent-light); }
  html:not(.has-cursor) body[data-theme="light"] .whatsapp-float:hover { border-color: var(--color-accent); color: var(--color-accent); }
  html:not(.has-cursor) .whatsapp-float:hover::after { opacity: 0.4; transform: scale(1); transition: opacity 400ms linear, transform 600ms var(--ease-c3); }
}
.whatsapp-float:focus-visible::after { opacity: 0.4; transform: scale(1); transition: opacity 400ms linear, transform 600ms var(--ease-c3); }
/* En nosotros, desde 1521 px, el contacto lateral fijo (que incluye WhatsApp)
   ocupa esta esquina: el acceso flotante cede su sitio. */
@media (min-width: 1521px) {
  body[data-page="nosotros"] .whatsapp-float { display: none; }
}
/* Se apaga con el velo del final del detalle. */
.whatsapp-float { filter: opacity(calc(1 - var(--veil, 0))); }
@media (max-width: 767px) {
  .whatsapp-float {
    left: calc(73% - 17px);
    bottom: calc(15px + env(safe-area-inset-bottom, 0px));
    width: 34px;
    height: 34px;
  }
  .whatsapp-float svg { width: 15px; height: 15px; }
}

/* =========================================================
   Botones
   ========================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--text-small);
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  padding: 14px 28px;
  border-radius: var(--radius-sm);
  border: var(--border-hair-strong);
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.btn--outline-light { background: transparent; color: var(--color-white); border-color: rgba(255,255,255,0.6); }
.btn--outline-light:hover { background: var(--color-white); color: var(--color-ink); }

/* =========================================================
   Portada (función corazón)
   Retícula: foto a sangre con
   viñeta, anillo fino centrado, título dentro del anillo, anterior y
   siguiente a media altura con sus líneas, contador abajo a la derecha y,
   en móvil, barra inferior. Colores y tipografía de Traza (tokens.css).
   Las animaciones las pinta js/home.js fotograma a fotograma.
   ========================================================= */
.page-home {
  --home-text: var(--color-paper);
  --home-text-80: rgba(250, 250, 247, 0.8); /* papel de Traza al 80 / 60 / 30 % */
  --home-text-60: rgba(250, 250, 247, 0.6);
  --home-text-30: rgba(250, 250, 247, 0.3);
  background: var(--color-carbon-warm);
  color: var(--home-text);
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.main--home {
  --home-text: var(--color-paper);
  --home-text-80: rgba(250, 250, 247, 0.8);
  --home-text-60: rgba(250, 250, 247, 0.6);
  --home-text-30: rgba(250, 250, 247, 0.3);
}

.hero {
  position: relative;
  height: 100vh;
  height: 100dvh;
  background: var(--color-carbon-warm);
  color: var(--home-text);
  overflow: hidden;
}

/* Lienzo WebGL (js/hero3d.js): visible solo cuando ya pintó su primer cuadro. */
.hero-3d {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  visibility: hidden;
}
.hero.is-3d-active .hero-3d { visibility: visible; }
.hero.is-3d-active .hero-slides,
.hero.is-3d-active .hero-shade { display: none; }

/* Respaldo sin WebGL: las mismas fotos con fundido y la viñeta en CSS. */
.hero-slides { position: absolute; inset: 0; z-index: 0; }
/* Si una foto no carga, el reemplazo es el fondo neutro de su figura, a
   sangre y sin icono (el mismo tono que usa el 3D), bajo la viñeta. */
.hero-slide { position: absolute; inset: 0; opacity: 0; background: var(--color-photo-empty); }
.hero-slide picture { display: block; width: 100%; height: 100%; }
.hero-slide__img { width: 100%; height: 100%; object-fit: cover; }
.hero-slide__img.is-fallback { visibility: hidden; }
/* Viñeta equivalente a la del shader: tinta cálida de Traza (#15110E) con la
   opacidad que deja el brillo de 75 % en el centro y 10 % en las esquinas. */
.hero-shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(circle at 50% 50%,
    rgba(21, 17, 14, 0.25) 0, rgba(21, 17, 14, 0.25) min(26vh, 28.08vw), rgba(21, 17, 14, 0.34) min(40vh, 43.2vw),
    rgba(21, 17, 14, 0.58) min(56vh, 60.48vw), rgba(21, 17, 14, 0.79) min(70vh, 75.6vw), rgba(21, 17, 14, 0.9) min(86vh, 92.88vw));
}

/* Títulos apilados en el centro del anillo; js/home.js los cruza. */
.hero-titles { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.hero-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: max-content;
  max-width: calc(var(--ring-r) * 1.5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  color: var(--home-text);
  /* Sombra muy suave: solo para que el título se lea sobre fotos claras. */
  text-shadow: 0 0 18px rgba(21, 17, 14, 0.45);
  opacity: 0;
  visibility: hidden;
  pointer-events: auto;
}
.hero-title__name {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(2.1vw, 30px);
  line-height: 1.36;
  letter-spacing: var(--tracking-display);
  color: inherit;
  text-wrap: balance;
}
.hero-title__meta {
  font-family: var(--font-display);
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--home-text-80);
  /* Cuerpo de 11 px: sombra más cercana que la del nombre para leerse sobre fotos claras. */
  text-shadow: 0 0 8px rgba(21, 17, 14, 0.6);
}

/* Anterior y siguiente a media altura, con sus líneas hacia el centro. */
.hero-nav {
  position: absolute;
  z-index: 3;
  top: 50%;
  width: 90px;
  height: 52px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: 12px;
  line-height: 12px;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  color: var(--home-text-60);
  transition: color 450ms var(--ease-c7);
}
.hero-nav:hover { color: var(--home-text); }
.hero-nav--prev { left: var(--hm); justify-content: flex-start; }
.hero-nav--next { right: var(--hm); justify-content: flex-end; }
.hero-line {
  position: absolute;
  z-index: 3;
  top: calc(50% - 3px);
  width: max(0px, calc(50% - var(--hm) - 96px - 1.21 * var(--ring-r)));
  height: 1px;
  background: var(--home-text-30);
  pointer-events: none;
}
.hero-line--prev { left: calc(var(--hm) + 96px); transform-origin: 0 50%; }
.hero-line--next { right: calc(var(--hm) + 96px); transform-origin: 100% 50%; }

/* Contador: obra actual, línea temporizadora (relleno con el acento) y total. */
.hero-counter {
  position: absolute;
  z-index: 7;
  right: var(--hm);
  bottom: calc(var(--hm) - 13px);
  height: 36px;
  display: flex;
  align-items: center;
  gap: 22px;
  font-family: var(--font-display);
  font-size: 12px;
  line-height: 12px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: var(--home-text);
}
.hero-counter__num { display: flex; }
.hero-counter__digit { position: relative; display: block; }
.hero-counter__d { display: block; }
.hero-counter__d--in { position: absolute; left: 0; top: 0; opacity: 0; }
.hero-counter__line { position: relative; width: 40px; height: 1px; background: var(--home-text-30); overflow: hidden; }
.hero-counter__fill { position: absolute; inset: 0; background: var(--color-accent-light); transform: scaleX(0); transform-origin: 0 50%; }


.hero-skeleton {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-carbon-warm);
}
.hero-skeleton__label {
  font-family: var(--font-display);
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  color: var(--home-text-60);
  font-size: var(--text-small);
  opacity: 0;
}
/* Solo en la demostración ?estado=cargando; la espera real la indica el anillo pequeño. */
.hero.is-demo-cargando .hero-skeleton__label { animation: hero-skeleton-in 300ms linear 900ms forwards; }
@keyframes hero-skeleton-in { to { opacity: 1; } }

.hero-empty {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-4);
  padding: var(--space-7);
  background: var(--color-carbon-warm);
  color: var(--color-paper);
}
.hero-empty__title { font-size: var(--text-h1); color: var(--color-paper); }
.hero-empty__text { max-width: 32rem; color: var(--color-gray-300); }
.hero.is-empty .hero-nav,
.hero.is-empty .hero-line,
.hero.is-empty .hero-counter { display: none; }

@media (max-width: 767px) {
  .hero-title { max-width: min(300px, calc(var(--ring-r) * 1.69)); gap: 6px; }
  .hero-title__name { font-size: 17px; line-height: 1.4; }
  .hero-title__meta { font-size: 9px; }
  .hero-nav,
  .hero-line { display: none; }
  .hero-counter {
    right: auto;
    bottom: auto;
    left: 50%;
    top: calc(50% + 0.827 * var(--ring-r));
    height: 30px;
    transform: translate(-50%, -50%);
    gap: 16px;
    font-size: 10px;
    line-height: 10px;
  }
  .hero-counter__line { width: 30px; }
}

/* =========================================================
   Listado: zigzag a dos columnas sobre el
   carbón cálido. Miniaturas apagadas (25 %) que se encienden con el puntero
   (80 %); número y título montados sobre el borde de la foto. El filtro de
   Traza ocupa el hueco que deja arriba el desfase de la columna derecha.
   ========================================================= */
.main--list {
  --tw: min(28.125vw, 450px);       /* ancho de la miniatura (405 a 1440) */
  --th: calc(var(--tw) * 0.6222);   /* alto: 62,22 % del ancho */
  --off: min(14.375vw, 230px);      /* desfase de la columna derecha */
  --gap: 20vh;                      /* margen entre ítems de una columna */
}
.works { padding: 31vh 0 calc(31vh - 96px); }
.works-board { position: relative; width: 82vw; max-width: 1400px; margin: 0 auto; }
.works-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: calc(var(--th) + 8px);
  row-gap: var(--gap);
  padding-bottom: var(--gap);
}
.work { position: relative; }
.work:nth-child(even) { top: var(--off); }
/* La miniatura al 20 % de su columna (desde el borde exterior). */
.work__link { position: relative; display: block; width: var(--tw); margin-left: 20%; }
.work:nth-child(even) .work__link { margin-left: calc(80% - var(--tw)); }
.work__frame {
  position: relative;
  display: block;
  height: var(--th);
  overflow: hidden;
  background: var(--color-carbon-warm);
}
/* Foto al 130 % del marco, anclada arriba (paralaje interior en js/scroll.js). */
.work__frame img {
  width: 100%;
  height: 130%;
  object-fit: cover;
  opacity: 0.25;
  transition: opacity 800ms var(--ease-c7);
}
.work.is-hot .work__frame img { opacity: 0.8; transition-duration: 450ms; }
.work__frame img.is-fallback { object-fit: contain; padding: var(--space-5); }
/* Cortina del color de la página: crece desde abajo al plegarse. */
.work__curtain {
  position: absolute;
  inset: 0;
  background: var(--color-carbon-warm);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  pointer-events: none;
}
/* Número y título: 20 % del ancho a la izquierda de la foto; la altura la
   pone el paralaje (75 px + 0,19 × y de la foto en pantalla). */
.work__meta {
  position: absolute;
  z-index: 1;
  top: 0;
  left: calc(var(--tw) * -0.2);
  width: max-content;
  max-width: calc(var(--tw) * 1.2);
  translate: 0 128px;
  text-shadow: 0 0 18px rgba(21, 17, 14, 0.45);
}
.work__head { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 14px; }
.work__num {
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 18px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: rgba(250, 250, 247, 0.5);
}
.work__cat {
  font-family: var(--font-display);
  font-size: 10px;
  line-height: 18px;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: rgba(250, 250, 247, 0.5);
}
.work__title {
  display: block;
  margin-top: 12px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(2.1vw, 30px);
  line-height: 1.36;
  letter-spacing: var(--tracking-display);
  color: var(--paper);
  text-wrap: balance;
}

/* Filtro: botones de texto con el hover de las miniaturas (opacidad, 450 ms
   C7 al entrar y 800 ms C7 al salir, con los mismos bloqueos). El activo
   lleva el acento claro y su subrayado crece de izquierda a derecha. */
.works-filter {
  position: absolute;
  z-index: 2;
  top: 0;
  left: calc(90% - var(--tw) * 1.2);
  right: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 28px;
}
.works-filter__btn {
  position: relative;
  padding: 2px 0 6px;
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 21px;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--paper);
  opacity: 0.55;
  transition: opacity 800ms var(--ease-c7), color 450ms var(--ease-c7);
}
.works-filter__btn.is-hot { opacity: 1; transition-duration: 450ms, 450ms; }
.works-filter__btn.is-active { opacity: 1; color: var(--color-accent-light); }
.works-filter__btn span::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 800ms var(--ease-c4);
}
.works-filter__btn.is-active span::after { transform: scaleX(1); transform-origin: 0 50%; transition: transform 1000ms var(--ease-c5); }

/* Estados (vacío, vacío por filtro, error) en el sitio del primer ítem. */
.works-state {
  position: relative;
  z-index: 1;
  margin-left: calc(10% - var(--tw) * 0.2);
  width: calc(40% + var(--tw) * 0.2);
  padding-bottom: 20vh;
}
.works-state__title {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(2.1vw, 30px);
  line-height: 1.36;
  letter-spacing: var(--tracking-display);
  color: inherit;
  max-width: 24rem;
}
.works-state__text { margin-top: 12px; max-width: 26rem; font-size: 15px; line-height: 1.65; opacity: 0.7; }
.works-state__cta {
  margin-top: 26px;
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 21px;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  box-shadow: inset 0 -1px 0 rgba(250, 250, 247, 0.3);
}
main[data-theme="light"] .works-state__cta { box-shadow: inset 0 -1px 0 rgba(18, 18, 18, 0.25); }

/* Esqueleto de carga: los mismos marcos del zigzag con un brillo lento. */
.works-list--skeleton .work__frame {
  width: var(--tw);
  margin-left: 20%;
  background: linear-gradient(100deg, #3A312A 20%, #463C34 40%, #3A312A 60%);
  background-size: 200% 100%;
  animation: shimmer 1.6s linear infinite;
}
.works-list--skeleton .work:nth-child(even) .work__frame { margin-left: calc(80% - var(--tw)); }
@keyframes shimmer { to { background-position: -200% 0; } }

/* Subrayado de enlaces (firma de Traza con el acento): crece de izquierda a
   derecha (1000 ms, C5) y se recoge hacia la derecha (800 ms, C4). */
.link-line { position: relative; display: inline-block; padding-bottom: 4px; }
.link-line::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 800ms var(--ease-c4);
}
main[data-theme="dark"] .link-line::after { background: var(--color-accent-light); }
.link-line:hover::after, .link-line:focus-visible::after,
a:hover > .link-line::after, a:focus-visible > .link-line::after { transform: scaleX(1); transform-origin: 0 50%; transition: transform 1000ms var(--ease-c5); }

@media (max-width: 1280px) {
  .work__title, .works-state__title { font-size: max(16px, 1.875vw); }
}
@media (max-width: 767px) {
  .main--list {
    --tw: 38vw;                     /* 142,5 a 375 */
    --th: calc(38vw * 0.6222);
    --off: 14.375vw;
    --gap: 25vw;
  }
  .works { padding: 140px 0 70px; }
  .works-board { width: 86.667vw; }
  .work__link { margin-left: 4vw; }
  .work:nth-child(even) .work__link { margin-left: calc(100% - var(--tw)); }
  .work__meta { left: -15px; max-width: calc(var(--tw) + 15px); translate: 0 32px; }
  .work__head { column-gap: 8px; }
  .work__cat { font-size: 9px; line-height: 16px; }
  .work__city { display: none; }
  .work__num { line-height: 16px; }
  .work__title { margin-top: 4px; font-size: 14px; line-height: 1.4; }
  /* Filtro en fila deslizable sobre el zigzag. */
  .works-filter {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    margin: -12px -6.667vw 28px;
    padding: 0 6.667vw;
    flex-wrap: nowrap;
    gap: 22px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .works-filter::-webkit-scrollbar { display: none; }
  .works-filter__btn { flex: none; font-size: 11px; padding: 12px 0; }
  .works-filter__btn span::after { bottom: 10px; }
  .works-state { margin-left: 0; width: 100%; padding-bottom: 40px; }
  .works-state__title { font-size: 20px; }
  .works-list--skeleton .work__frame { margin-left: 4vw; }
  .works-list--skeleton .work:nth-child(even) .work__frame { margin-left: calc(100% - var(--tw)); }
}

/* =========================================================
   Nosotros: página oscura en
   secciones numeradas. El número cuelga 60 px a la izquierda de una
   columna de 50 vw que empieza en 25 vw (720 px en x 360 a 1440); en móvil,
   número en x 25 y contenido de 55 a 350. Sin inclinación ni paralaje: todo
   el contenido se desplaza como un bloque. Texto al 60 % del papel.
   ========================================================= */
.main--about {
  --col-x: 25vw;
  --col-w: 50vw;
  --num-gap: 60px;
  --about-dim: rgba(250, 250, 247, 0.6);
  --about-line: rgba(250, 250, 247, 0.1);
}
.about { padding-top: 39vh; }
.about-body { position: relative; display: flow-root; }
.about-sec {
  position: relative;
  margin-left: var(--col-x);
  width: var(--col-w);
  padding-top: 40px;
  margin-bottom: 95px;
}
.about-sec--name { padding-top: 0; margin-bottom: 170px; }
.about-num {
  position: absolute;
  left: calc(-1 * var(--num-gap));
  top: 40px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 13px;
  line-height: 31px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: var(--paper);
}
/* 01 a la altura de las mayúsculas del nombre. */
.about-sec--name .about-num { top: 2px; line-height: 13px; }

/* 01 · Nombre del estudio (12 vw, dos líneas que pueden salir por la
   derecha). Cada línea es una máscara: las letras entran desde arriba. */
.about-name {
  /* Las mayúsculas de Archivo quedan 0,12 em por debajo del borde de su
     línea: se suben para que arranquen justo en el relleno superior, sin
     mover el manifiesto. */
  position: relative;
  top: -0.12em;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 12vw;
  line-height: 1;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  color: var(--paper);
  white-space: nowrap;
}
.about-name:focus { outline: none; box-shadow: none; }
.about-name__line { display: block; overflow-x: visible; overflow-y: clip; }
.about-name__ch, .about-name__sp { display: inline-block; }
.about-name__ch { transform-origin: 50% 50%; }
.about-manifest { margin-top: 40px; }
.about-manifest p,
.about-p {
  font-size: 18px;
  line-height: 2.2;
  color: var(--about-dim);
}

/* 02–04 · Título de sección de 22 px y cuerpo 40 px debajo. */
.about-h {
  margin-bottom: 40px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 22px;
  line-height: 31px;
  letter-spacing: var(--tracking-display);
  color: var(--paper);
}

/* 02 · Equipo: presentación y personas con avatares abstractos. */
.about-team__list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px 40px;
  margin-top: 44px;
}
.about-team__list:first-child { margin-top: 0; }
.about-member {
  display: grid;
  grid-template-columns: 56px 1fr;
  grid-template-rows: auto auto;
  column-gap: 20px;
  align-content: center;
}
.about-member__avatar { position: relative; grid-row: 1 / span 2; width: 56px; height: 56px; overflow: hidden; align-self: center; }
/* Franja superior con el acento (2 % del alto), encima del avatar. */
.about-member__avatar::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2%; background: var(--color-accent); }
.about-member__avatar img { width: 100%; height: 100%; object-fit: cover; }
.about-member__name { align-self: end; font-size: 16px; line-height: 1.5; color: var(--paper); }
.about-member__role { align-self: start; font-size: 14px; line-height: 1.6; color: var(--about-dim); }

/* 03 · Hitos (equivalente a la lista de premios): año en una columna de
   80 px y texto en x 440; debajo, el proyecto entre corchetes. Paso ≈88 px. */
.about-mile {
  display: grid;
  grid-template-columns: 80px 1fr;
  padding-bottom: 14px;
  color: var(--about-dim);
}
.about-mile__year { grid-row: 1 / span 2; font-size: 18px; line-height: 40px; font-variant-numeric: tabular-nums; }
.about-mile__text { font-size: 18px; line-height: 40px; }
.about-mile__proj { grid-column: 2; font-size: 14px; line-height: 34px; }
.about-mile__proj .link-line { padding-bottom: 1px; color: var(--about-dim); transition: color 450ms var(--ease-c7); }
.about-mile__proj .link-line:hover { color: var(--paper); }

/* 04 · Datos del estudio: tabla de dos columnas (etiqueta de 160 px), paso
   ≈52 px; separador de 1 px y contacto 95 px más abajo. */
.about-studio__name { font-size: 18px; line-height: 1.6; color: var(--paper); opacity: 0.8; }
.about-studio__tag { margin-top: 6px; font-size: 13px; line-height: 1.8; color: var(--about-dim); }
.about-facts { margin-top: 22px; }
.about-facts > div { display: grid; grid-template-columns: 160px 1fr; }
.about-facts dt,
.about-facts dd { margin: 0; padding-bottom: 12px; font-size: 18px; line-height: 40px; color: var(--about-dim); }
.about-contact { margin-top: 80px; padding-top: 95px; border-top: 1px solid var(--about-line); }
.about-contact__h,
.about-aside__in .about-contact__h {
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 18px;
  line-height: 1.4;
  letter-spacing: var(--tracking-display);
  color: var(--paper);
}
.about-contact__l { font-size: 18px; line-height: 2; color: var(--about-dim); }
.about-contact__l .link-line { padding-bottom: 2px; transition: color 450ms var(--ease-c7); }
.about-contact__l .link-line:hover { color: var(--paper); }
/* Enlaces de nosotros: subrayado tenue fijo (15 %) y el barrido de firma encima. */
.main--about .link-line::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: rgba(250, 250, 247, 0.15);
}

/* Contacto lateral (≥1521 px): fijo abajo a la izquierda en x = 6,25 vw
   y con el borde inferior a min(6,25 vw; 100 px); la banda lo empuja con 95 px
   de separación. Con scroll nativo es sticky; con el suavizado, js/nosotros.js. */
.about-aside { display: none; }
@media (min-width: 1521px) {
  .about-contact { display: none; }
  .about-aside {
    position: absolute;
    left: var(--hm);
    top: 0;
    bottom: 95px;
    width: calc(var(--col-x) - var(--num-gap) - var(--hm) - 40px);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    pointer-events: none;
  }
  .about-aside__in { position: sticky; bottom: var(--hm); pointer-events: auto; }
  main.is-smooth .about-aside__in { position: relative; bottom: auto; }
  .about-aside__in .about-contact__h { font-size: 16px; margin-bottom: 6px; }
  .about-aside__in .about-contact__l { font-size: 14px; line-height: 1.9; }
}

/* 05 · Banda final a todo el ancho: 350 px (500 desde 1521,
   300 hasta 1000, 150 en móvil), tinta cálida. Fila: número, título con 40 de
   aire, línea que ocupa el resto e icono con 40 de aire. */
.about-band {
  position: relative;
  display: block;
  height: var(--band-h);
  overflow: hidden;
  background: var(--color-ink-warm);
  color: var(--paper);
}
/* Fila de 31 px a un 56 % del alto (posiciones enteras: la línea de 1 px
   queda nítida). */
.about-band { --band-h: 350px; }
.about-band__row {
  position: absolute;
  z-index: 1;
  left: var(--col-x);
  width: var(--col-w);
  top: calc(var(--band-h) * 0.56 - 15px);
  height: 31px;
  display: flex;
  align-items: center;
}
.about-band .about-num { top: 0; }
.about-band__title {
  flex: none;
  padding-right: 40px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 22px;
  line-height: 31px;
  letter-spacing: var(--tracking-display);
  white-space: nowrap;
}
.about-band__line { position: relative; flex: 1; height: 1px; overflow: hidden; }
.about-band__track {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -25px;
  right: 0;
  background: rgba(250, 250, 247, 0.5);
  transition: transform 1200ms var(--ease-c8);
}
.about-band__fill {
  position: absolute;
  inset: 0;
  background: var(--color-accent-light);
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 1200ms var(--ease-c4);
}
.about-band__icon {
  flex: none;
  width: 25px;
  height: 19px;
  margin-left: 40px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  overflow: visible;
  transition: transform 1200ms var(--ease-c8);
}
/* Capa más oscura: en reposo una banda más abajo, sesgada 9° desde abajo a la
   izquierda; entra subiendo y enderezándose (1000 ms C5, +100) y sale por
   arriba con −3° desde arriba a la izquierda (1200 ms C4, +100); después
   vuelve abajo sin transición. */
.about-band__layer {
  position: absolute;
  inset: 0;
  background: var(--color-ink-deep);
  transform: translateY(100%) skewY(9deg);
  transform-origin: 0 100%;
}
.about-band.is-in .about-band__layer { transform: translateY(0) skewY(0deg); transition: transform 1000ms var(--ease-c5) 100ms; }
.about-band.is-out .about-band__layer { transform: translateY(-100%) skewY(-3deg); transform-origin: 0 0; transition: transform 1200ms var(--ease-c4) 100ms; }
.about-band.is-in .about-band__icon { transform: translateX(-20px); transition: transform 800ms var(--ease-c8) 100ms; }
.about-band.is-in .about-band__track { transform: translateX(-25px); transition: transform 800ms var(--ease-c8) 175ms; }
.about-band.is-in .about-band__fill { transform: scaleX(1); transform-origin: 0 50%; transition: transform 800ms var(--ease-c5); }
.about-band:focus-visible { box-shadow: inset 0 0 0 2px var(--color-accent-light); border-radius: 0; }
@media (min-width: 1521px) { .about-band { --band-h: 500px; } }
@media (max-width: 1000px) { .about-band { --band-h: 300px; } }

/* Contador de sección (escritorio): 01–05 abajo a la derecha, rodillo
   por dígito y línea con el acento claro hasta n/5. */
.section-counter {
  position: fixed;
  z-index: 38;
  right: var(--hm);
  bottom: calc(var(--hm) - 13px);
  height: 36px;
  display: flex;
  align-items: center;
  gap: 22px;
  font-family: var(--font-display);
  font-size: 12px;
  line-height: 12px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: var(--paper);
  pointer-events: none;
}
.section-counter__line { position: relative; width: 40px; height: 1px; background: rgba(250, 250, 247, 0.3); overflow: hidden; }
.section-counter__fill { position: absolute; inset: 0; background: var(--color-accent-light); transform: scaleX(0); transform-origin: 0 50%; }

@media (max-width: 767px) {
  .main--about { --col-x: 55px; --col-w: calc(100vw - 80px); --num-gap: 30px; }
  .about { padding-top: 160px; }
  .about-name { font-size: 14vw; }
  .about-sec { padding-top: 30px; margin-bottom: 30px; }
  .about-sec--name { padding-top: 0; margin-bottom: 120px; }
  .about-num { top: 30px; font-size: 11px; line-height: 26px; }
  .about-sec--name .about-num { top: 1px; line-height: 11px; }
  .about-manifest { margin-top: 32px; }
  .about-manifest p,
  .about-p { font-size: 14px; line-height: 31px; }
  .about-h { margin-bottom: 30px; font-size: 18px; line-height: 26px; }
  .about-team__list { grid-template-columns: 1fr; gap: 20px; margin-top: 30px; }
  .about-team__list:first-child { margin-top: 0; }
  .about-member { grid-template-columns: 48px 1fr; column-gap: 16px; }
  .about-member__avatar { width: 48px; height: 48px; }
  .about-member__name { font-size: 14px; }
  .about-member__role { font-size: 12px; }
  .about-mile { grid-template-columns: 60px 1fr; padding-bottom: 10px; }
  .about-mile__year,
  .about-mile__text { font-size: 14px; line-height: 31px; }
  .about-mile__text { line-height: 25px; padding: 3px 0; }
  .about-mile__proj { font-size: 11px; line-height: 26px; }
  .about-studio__name { font-size: 14px; }
  .about-studio__tag { font-size: 11px; }
  .about-facts > div { grid-template-columns: 115px 1fr; }
  .about-facts dt,
  .about-facts dd { padding-bottom: 8px; font-size: 14px; line-height: 31px; }
  .about-contact { margin-top: 40px; padding-top: 40px; }
  .about-contact__h { font-size: 15px; }
  .about-contact__l { font-size: 14px; }
  .about-band { --band-h: 150px; }
  .about-band__row { top: 60px; }
  .about-band .about-num { line-height: 31px; }
  .about-band__title { padding-right: 22px; font-size: 18px; line-height: 26px; }
  .about-band__icon { width: 15px; height: 14px; margin-left: 22px; }
  .section-counter { display: none; }
}

/* =========================================================
   Detalle: claro y silencioso, con el papel
   y el gris 100 de Traza. Banda superior con el título centrado y el número
   y el año a la derecha; galería apilada en una columna de 1000 px que pasa
   por encima de la banda; ficha y paso entre proyectos al final.
   ========================================================= */
/* Columna de 1000 px (87,5 vw por debajo de 1140); en anchos intermedios deja
   libre el carril del acceso a WhatsApp. */
main[data-theme="light"] { --col: min(1000px, 87.5vw, calc(100vw - 2 * (var(--hm) + 60px))); }
@media (max-width: 767px) { main[data-theme="light"] { --col: 87.5vw; } }
.dt-band {
  position: relative;
  z-index: 0;
  height: max(50vh, 350px);
  padding: max(23vh, 161px) 0 0;
  text-align: center;
  background: var(--color-paper);
}
.dt-title {
  max-width: min(60vw, 760px);
  margin: 0 auto;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(2.1vw, 30px);
  line-height: 1.36;
  letter-spacing: var(--tracking-display);
  color: var(--color-ink);
  text-wrap: balance;
}
.dt-title:focus { outline: none; }
.dt-meta {
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-gray-700);
}
/* Número de la obra (12 px) y año (14 px), alineados con el borde derecho de
   la galería; cada cifra sube (o cae) en su propia caja. */
.dt-num {
  position: absolute;
  top: max(23vh, 161px);
  right: calc(50% - var(--col) / 2);
  margin: 0;
  text-align: right;
  font-family: var(--font-display);
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
}
.dt-num__n { display: block; height: 30px; font-size: 12px; line-height: 16px; }
.dt-num__y { display: block; font-size: 14px; line-height: 20px; }
.dt-digit { display: inline-block; overflow: hidden; vertical-align: top; }
.dt-digit__in { display: inline-block; }

.dt-body { position: relative; z-index: 1; padding-top: 15vh; }
/* Banda gris (gris 100 → papel a mitad del cuerpo), al 50 % de la velocidad. */
.dt-body__bg {
  position: absolute;
  inset: 0 0 auto;
  height: 100%;
  background: linear-gradient(180deg, var(--color-gray-100) 0, var(--color-paper) 50%);
  pointer-events: none;
}
.dt-gallery {
  position: relative;
  width: var(--col);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8.3vh;
}
.dt-photo { position: relative; }
.dt-photo__frame {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  padding: 0;
  overflow: hidden;
  background: var(--color-gray-150);
  cursor: zoom-in;
}
/* Foto a 1,1× en su marco: recorre el sobrante con el scroll. */
.dt-photo__frame img { width: 100%; height: 100%; object-fit: cover; scale: 1.1; }
.dt-photo__frame img.is-fallback { object-fit: contain; padding: var(--space-8); scale: 1; }

/* Ficha del proyecto (Traza): datos clave y descripción. */
.dt-sheet {
  position: relative;
  width: var(--col);
  margin: 16.6vh auto 0;
  padding-top: 28px;
  border-top: 1px solid rgba(18, 18, 18, 0.14);
  display: grid;
  grid-template-columns: minmax(240px, 34%) 1fr;
  column-gap: 64px;
}
.dt-sheet__h {
  grid-column: 1 / -1;
  margin-bottom: 20px;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-gray-700);
}
.dt-facts > div {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid rgba(18, 18, 18, 0.1);
}
.dt-facts > div:first-child { padding-top: 0; }
.dt-facts dt {
  font-family: var(--font-display);
  font-size: 11px;
  line-height: 22px;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-gray-700);
}
.dt-facts dd { font-family: var(--font-display); font-size: 15px; line-height: 22px; color: var(--color-ink); }
.dt-desc { max-width: 36rem; font-size: 17px; line-height: 1.75; color: rgba(18, 18, 18, 0.78); }

/* Paso al proyecto anterior/siguiente con el subrayado de firma. */
.dt-pager {
  position: relative;
  width: var(--col);
  margin: 12vh auto 0;
  padding: 28px 0 14vh;
  border-top: 1px solid rgba(18, 18, 18, 0.14);
  display: flex;
  justify-content: space-between;
  gap: 32px;
}
.dt-pager__link { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; max-width: 45%; }
.dt-pager__link--next { align-items: flex-end; text-align: right; }
.dt-pager__k {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-gray-700);
}
.dt-pager__t {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(1.8vw, 24px);
  line-height: 1.3;
  letter-spacing: var(--tracking-display);
  color: var(--color-ink);
}

.dt-skeleton { padding-top: max(23vh, 161px); }
.dt-skeleton__title { width: 260px; height: 28px; margin: 0 auto; background: var(--color-gray-100); }
.dt-skeleton__photo { width: var(--col); aspect-ratio: 3 / 2; margin: calc(27vh + 15vh - 28px) auto 0; background: var(--color-gray-100); }
.dt-error { width: var(--col); margin: 0 auto; padding: max(23vh, 161px) 0 20vh; color: var(--color-ink); }

/* Contador de fotos (escritorio): actual, línea con el acento y total. */
.photo-counter {
  position: fixed;
  z-index: 38;
  right: var(--hm);
  bottom: calc(var(--hm) - 13px);
  height: 36px;
  display: flex;
  align-items: center;
  gap: 22px;
  font-family: var(--font-display);
  font-size: 12px;
  line-height: 12px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
  pointer-events: none;
}
.photo-counter__num { display: flex; }
.photo-counter__line { position: relative; width: 40px; height: 1px; background: rgba(18, 18, 18, 0.12); overflow: hidden; }
.photo-counter__fill { position: absolute; inset: 0; background: var(--color-accent); transform: scaleX(0); transform-origin: 0 50%; }
.pc-digit { position: relative; display: block; height: 12px; overflow: hidden; }
.pc-digit__in { display: block; }
/* Cifras que salen (js/anim.js, rodillo): encima de la actual, fuera del flujo. */
.pc-digit__in.is-out { position: absolute; left: 0; top: 0; }

/* Final del detalle: 100 vh vacíos y un velo de tinta cálida ligado al scroll. */
.detail-end { position: relative; z-index: 1; height: 100vh; background: var(--color-paper); }

@media (max-width: 767px) {
  .dt-band { height: 50vh; padding-top: 25vh; }
  .dt-title { max-width: 300px; font-size: 17px; line-height: 1.4; }
  .dt-meta { font-size: 9px; }
  .dt-num { top: auto; bottom: 21px; right: 25px; }
  .dt-num__n { height: 25px; }
  .dt-body { padding-top: 40px; }
  .dt-gallery { gap: 25px; }
  .dt-sheet { grid-template-columns: 1fr; row-gap: 28px; margin-top: 64px; }
  .dt-desc { font-size: 16px; }
  .dt-pager { flex-direction: column; margin-top: 48px; padding-bottom: 80px; }
  .dt-pager__link, .dt-pager__link--next { max-width: none; align-items: flex-start; text-align: left; }
  .dt-pager__t { font-size: 18px; }
  .photo-counter { display: none; }
  .dt-skeleton { padding-top: 25vh; }
  .dt-skeleton__photo { margin-top: calc(25vh + 40px - 28px); }
}

/* =========================================================
   Ampliación de una foto y visor de la galería (ficha, función 3).
   En escritorio la foto cubre la pantalla y los controles van sobre ella;
   en pantallas táctiles cabe entera sobre el papel.
   ========================================================= */
.zoom { position: fixed; inset: 0; z-index: 100; touch-action: none; }
.zoom__bg { position: absolute; inset: 0; background: var(--color-paper); }
.zoom__stage { position: absolute; cursor: zoom-out; }
.zoom__pane { position: absolute; inset: 0; overflow: hidden; transform-origin: 0 0; }
.zoom__img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Controles sobre la foto: discos de tinta cálida de 45 px (el lenguaje del
   cursor propio) con la X y las flechas en papel. */
.zoom__close, .zoom__nav {
  position: absolute;
  width: 45px;
  height: 45px;
  border-radius: 50%;
  background: rgba(21, 17, 14, 0.55);
  color: var(--paper);
  transition: background-color 450ms var(--ease-c7), color 450ms var(--ease-c7);
}
.zoom__close:hover, .zoom__nav:hover { background: rgba(21, 17, 14, 0.8); }
html:not(.has-cursor) .zoom__close:hover, html:not(.has-cursor) .zoom__nav:hover, .zoom__close:focus-visible, .zoom__nav:focus-visible { color: var(--color-accent-light); }
.zoom__close { left: calc(50% - 22.5px); top: 80px; }
.zoom__close span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 1px;
  background: currentColor;
}
.zoom__close span:first-child { transform: translate(-50%, -50%) rotate(45deg); }
.zoom__close span:last-child { transform: translate(-50%, -50%) rotate(-45deg); }
.zoom__nav { top: calc(50% - 22.5px); display: flex; align-items: center; justify-content: center; }
.zoom__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.zoom__nav svg { width: 12px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1; }
.zoom__nav--prev { left: var(--hm); }
.zoom__nav--next { right: var(--hm); }
/* Pie de foto y contador sobre un degradado de tinta cálida. */
.zoom.is-cover::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 180px;
  background: linear-gradient(180deg, rgba(21, 17, 14, 0), rgba(21, 17, 14, 0.5));
  opacity: var(--zoom-ui, 0);
  pointer-events: none;
}
.zoom__caption, .zoom__counter {
  position: absolute;
  z-index: 1;
  bottom: calc(var(--hm) - 13px);
  margin: 0;
  line-height: 36px;
  color: var(--paper);
}
.zoom__caption { left: var(--hm); max-width: 44vw; font-size: 13px; }
.zoom__counter {
  right: var(--hm);
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: var(--tracking-nav);
  font-variant-numeric: tabular-nums;
}
.zoom:not(.is-cover) .zoom__close { top: 10px; background: none; color: var(--color-ink); }
.zoom:not(.is-cover) .zoom__nav { top: auto; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); background: none; color: var(--color-ink); }
.zoom:not(.is-cover) .zoom__nav--prev { left: 8px; }
.zoom:not(.is-cover) .zoom__nav--next { right: 8px; }
.zoom:not(.is-cover) .zoom__caption {
  left: 25px;
  right: 25px;
  bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  max-width: none;
  line-height: 1.5;
  text-align: center;
  color: var(--color-gray-700);
}
.zoom:not(.is-cover) .zoom__counter {
  left: 50%;
  right: auto;
  bottom: calc(7px + env(safe-area-inset-bottom, 0px));
  translate: -50% 0;
  line-height: 50px;
  color: var(--color-ink);
}

/* =========================================================
   Pie de página: discreto y centrado, lejos del acceso a WhatsApp.
   ========================================================= */
.site-footer {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 24px;
  padding: 0 var(--space-6) 48px;
  font-size: 11px;
  line-height: 1.6;
  text-align: center;
  color: var(--color-gray-700);
}
main[data-theme="dark"] .site-footer { color: rgba(250, 250, 247, 0.45); }
.site-footer span:empty { display: none; }


/* =========================================================
   Capa persistente (js/nav.js, js/anillo.js, js/lamina.js, js/scroll.js)
   Orden de abajo arriba: contenido de la portada (5) · lámina WebGL (10) ·
   anillo fino (12) · contenido de las demás páginas (15) · título en
   tránsito (30) · velo del final del detalle (40) · cabecera y barra (50) ·
   WhatsApp (60) · panel de entrada directa (90) · anillo pequeño (95).
   ========================================================= */
main { position: relative; z-index: 15; }
main.main--home { z-index: 5; }
/* Escritorio: el contenido va en un contenedor fijo que js/scroll.js desplaza
   (scroll virtual); un separador da al documento su altura. */
main.is-smooth {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  will-change: transform;
}
.scroll-spacer { width: 1px; pointer-events: none; }

/* Anillo fino persistente: claro en la portada, gris al fondo en las páginas
   oscuras, oculto en el detalle. js/anillo.js le da el radio y el trazo. */
.stage-ring {
  position: fixed;
  z-index: 12;
  left: 50%;
  top: 50%;
  width: calc(var(--ring-r) * 2 + 2px);
  height: calc(var(--ring-r) * 2 + 2px);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.stage-ring svg { display: block; width: 100%; height: 100%; overflow: visible; }
.stage-ring circle { fill: none; }
.stage-ring__base { stroke: var(--paper); stroke-width: 1; }
/* Arco de posición con el acento claro y trazo de 2 px (la base, de 1 px):
   con ese grosor el acento se lee sobre cualquier foto oscura. */
.stage-ring__arc { stroke: var(--color-accent-light); stroke-width: 2; opacity: 0; }
.stage-ring[data-tono="gris"] .stage-ring__base { stroke-opacity: 0.15; }
.stage-ring[data-tono="oculto"] { opacity: 0; }

/* Asa del anillo (portada, escritorio): punto de
   9 px en la cabeza del arco, visible con el puntero en la zona de escucha, y
   aro de 72 px que entra al pasar por el asa (de 1,4 a 1,2) y, al arrastrar,
   se rellena y escala a 0,75. js/home.js la coloca y la anima por fotograma. */
.hero-handle {
  position: fixed;
  z-index: 13;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
.hero-handle__dot,
.hero-handle__ring {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
}
.hero-handle__dot {
  left: -4.5px;
  top: -4.5px;
  width: 9px;
  height: 9px;
  background: var(--color-accent-light);
}
.hero-handle__ring {
  left: -36px;
  top: -36px;
  width: 72px;
  height: 72px;
  border: 1px solid var(--home-text-60);
  transform: scale(1.4);
}
.hero-handle__ring::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--color-paper);
  opacity: calc(var(--fill, 0) * 0.3);
}
@media (max-width: 767px), (pointer: coarse) {
  .hero-handle { display: none; }
}

/* Barra inferior móvil (sin menú desplegable), opaca y del color de la
   página: anterior, etiqueta y siguiente en todas las páginas (Proyectos en
   la portada, el detalle y nosotros; Inicio en el listado, equivalente a
   Focus) y el acceso a WhatsApp. El contenido le deja su alto. */
body { --bar-bg: var(--color-carbon-warm); --bar-fg: var(--paper); }
body[data-theme="light"] { --bar-bg: var(--paper); --bar-fg: var(--color-ink); }
body.page-home { --bar-bg: var(--color-ink-warm); }
.hero-bar { display: none; }
@media (max-width: 767px) {
  .hero-bar {
    display: flex;
    position: fixed;
    z-index: var(--z-header);
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(57px + env(safe-area-inset-bottom, 0px));
    padding: 0 8px calc(7px + env(safe-area-inset-bottom, 0px));
    align-items: center;
    justify-content: space-between;
    background: var(--bar-bg);
    color: var(--bar-fg);
    transition: background-color 700ms linear, color 700ms linear;
  }
  .hero-bar__arrow {
    width: 44px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: inherit;
  }
  .hero-bar__arrow svg { width: 12px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1; }
  .hero-bar__slot { display: inline-grid; justify-items: center; }
  .hero-bar__all {
    grid-area: 1 / 1;
    font-family: var(--font-display);
    font-size: 10px;
    line-height: 15px;
    letter-spacing: var(--tracking-nav);
    text-transform: uppercase;
    padding: 17px 24px;
  }
  .hero-bar[data-mode="off"] { opacity: 0; visibility: hidden; }
  .hero-bar:not([data-mode="list"]) [data-bar-focus],
  .hero-bar[data-mode="list"] [data-bar-all] { opacity: 0; visibility: hidden; transform: translateY(10px); }
  /* El contenido de las páginas con scroll deja sitio a la barra. */
  main:not(.main--home) { padding-bottom: calc(57px + env(safe-area-inset-bottom, 0px)); }
  html { scroll-padding-bottom: 80px; }
  /* Detalle: franja de papel detrás de la cabecera (las fotos pasan por debajo). */
  .site-header::before {
    content: "";
    position: absolute;
    z-index: -1;
    left: calc(-1 * var(--hm));
    right: calc(-1 * var(--hm));
    top: calc(-1 * var(--hm));
    height: 66px;
    background: var(--paper);
    opacity: 0;
    transition: opacity 700ms linear;
    pointer-events: none;
  }
  body[data-page="proyecto"][data-theme="light"] .site-header::before { opacity: calc(1 - var(--veil, 0)); }
  /* Al final del detalle, el velo cubre también la barra. */
  .hero-bar::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-ink-warm);
    opacity: var(--veil, 0);
    pointer-events: none;
  }
  body[data-page="proyecto"] { scroll-padding-top: 80px; }
}

/* Lámina de cambio de página (WebGL propio, js/lamina.js). */
.lamina {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  pointer-events: none;
  display: none;
}
.lamina.is-on { display: block; }

/* Anillo pequeño de carga: dos aros de 2 px, uno al 30 % y otro con dos
   lados llenos y dos al 20 %, girando una vuelta cada 800 ms. */
.loader-ring {
  position: fixed;
  z-index: 95;
  left: var(--hm);
  bottom: var(--hm);
  width: 30px;
  height: 30px;
  color: var(--paper);
  mix-blend-mode: exclusion;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.loader-ring.is-on { visibility: visible; }
.loader-ring::before,
.loader-ring span {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(250, 250, 247, 0.3);
}
.loader-ring span {
  border-color: currentColor currentColor rgba(250, 250, 247, 0.2) rgba(250, 250, 247, 0.2);
  animation: traza-giro 800ms linear infinite;
}
@keyframes traza-giro { to { transform: rotate(1turn); } }
@media (max-width: 767px) {
  .loader-ring { left: 17px; bottom: calc(22px + env(safe-area-inset-bottom, 0px)); width: 25px; height: 25px; }
}

/* =========================================================
   Cursor propio (js/cursor.js). Solo escritorio con
   puntero fino y hover, sin "reducir movimiento". El puntero nativo no se
   oculta. Disco de 100 px escalado (15, 40 o 45 px)
   con mezcla por exclusión; sobre las fotos ampliables, disco de tinta con
   mezcla normal y un signo + que gira a −. El aro de los enlaces va aparte,
   sin mezcla; los halos del clic, neutros y con exclusión.
   ========================================================= */
.cursor-punto, .cursor-aro, .cursor-halo { position: fixed; left: 0; top: 0; pointer-events: none; }
.cursor-punto { z-index: 105; width: 0; height: 0; mix-blend-mode: exclusion; }
.cursor-punto.is-tinta { mix-blend-mode: normal; }
.cursor-disco {
  position: absolute;
  left: -50px;
  top: -50px;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: var(--paper);
  opacity: 0;
  will-change: transform, opacity;
}
.cursor-punto.is-tinta .cursor-disco { background: var(--color-ink-warm); }
/* Signo + de dos barras de 2 px (30 % de los 45 px del disco); la vertical
   se tumba y queda − con la foto ampliada (500 ms, C1). */
.cursor-signo { position: absolute; left: -6.75px; top: -6.75px; width: 13.5px; height: 13.5px; opacity: 0; transition: opacity 400ms ease; }
.cursor-signo::before,
.cursor-signo::after { content: ""; position: absolute; left: 0; top: calc(50% - 1px); width: 100%; height: 2px; background: var(--paper); }
.cursor-signo::after { transform: rotate(90deg); transition: transform 500ms var(--ease-c1); }
.cursor-punto.is-foto .cursor-signo { opacity: 1; }
.cursor-punto.is-menos .cursor-signo::after { transform: rotate(0deg); }
.cursor-aro {
  z-index: 104;
  width: 80px;
  height: 80px;
  margin: -40px 0 0 -40px;
  border: 1px solid currentColor;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
}
/* Halo del clic neutro: papel translúcido con la misma exclusión que el
   disco (claro sobre fondo oscuro, oscuro sobre papel), así el disco que
   pasa por encima queda neutro. */
.cursor-halo {
  z-index: 104;
  width: 100px;
  height: 100px;
  margin: -50px 0 0 -50px;
  border-radius: 50%;
  background: var(--paper);
  mix-blend-mode: exclusion;
  opacity: 0;
}
@media (hover: none), (pointer: coarse) {
  .cursor-punto, .cursor-aro, .cursor-halo { display: none; }
}

/* Desintegración del título de la portada al ir a nosotros. */
.hero-letra { position: relative; }

/* Título en tránsito entre el anillo y la cabecera del detalle. */
.transit-title { position: fixed; inset: 0; z-index: 30; pointer-events: none; }
.transit-title__layer {
  position: absolute;
  left: 0;
  top: 0;
  width: max-content;
  transform-origin: 0 0;
  will-change: transform, opacity;
}
/* Con el aspecto del título de la portada, centrado en el anillo. */
.transit-title__ring {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: min(2.1vw, 30px);
  line-height: 1.36;
  letter-spacing: var(--tracking-display);
  text-align: center;
  text-wrap: balance;
  max-width: calc(var(--ring-r) * 1.5);
  text-shadow: 0 0 18px rgba(21, 17, 14, 0.45);
}
@media (max-width: 767px) {
  .transit-title__ring { font-size: 17px; line-height: 1.4; max-width: min(300px, calc(var(--ring-r) * 1.69)); }
}

/* Velo del final del detalle, ligado al scroll. */
.end-veil {
  position: fixed;
  left: 0;
  right: 0;
  top: -5%;
  height: 110%;
  z-index: 40;
  background: var(--color-ink-warm);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.end-veil.is-on { visibility: visible; }
.end-veil__label {
  position: absolute;
  left: 50%;
  top: 50%;
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(250, 250, 247, 0.3);
  transform: translate(-50%, -50%);
}

/* =========================================================
   Cargador de entrada (js/cargador.js). Solo en la
   primera visita de la sesión (html.traza-cargador). Panel del color de la
   página (carbón cálido en la portada; tinta cálida, más oscura, en las
   demás) con el logotipo centrado en dos capas, gris y clara, que se
   descubren por una ventana. Si JavaScript no llega, se quita solo a los 12 s.
   ========================================================= */
.cargador {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 90;
  overflow: hidden;
  background: var(--color-ink-warm);
  animation: traza-panel-seguro 300ms linear 12s forwards;
}
.cargador.is-js { animation: none; }
html.traza-cargador .cargador { display: block; }
body.page-home .cargador { background: var(--color-carbon-warm); }
@keyframes traza-panel-seguro { to { opacity: 0; visibility: hidden; } }
.cargador__in { position: absolute; inset: 0; }
/* Logotipo: el wordmark de la cabecera en una caja de 21,25 vw (entre 170
   y 340 px). Única excepción a los tokens de tracking: la altura de letra es una fracción de ese ancho y
   js/cargador.js reparte el resto entre las letras, sin espaciado tras la
   última, así que la tinta llena la caja y queda centrada. */
.cargador__logo {
  --cargador-ancho: clamp(170px, 21.25vw, 340px);
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--cargador-ancho);
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: calc(var(--cargador-ancho) * 0.11);
  line-height: 1.25;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}
.cargador__medida { display: block; visibility: hidden; }
.cargador__capa { position: absolute; inset: 0; overflow: hidden; transform: translateX(-100%); }
.cargador__capa > span { display: block; transform: translateX(100%); }
.cargador__capa--gris { color: var(--color-gray-500); }
.cargador__capa--clara { color: var(--paper); }
/* En la portada, al terminar, el logotipo pasa bajo el lienzo de la intro. */
.cargador__logo.is-suelto { position: fixed; z-index: 0; color: var(--paper); }

/* Anillo pequeño en el primer pintado del cargador (después lo anima JS). */
html.traza-cargador .loader-ring:not(.is-js) {
  visibility: visible;
  animation: traza-anillo-op 600ms ease forwards, traza-anillo-esc 600ms var(--ease-c3) forwards;
}
@keyframes traza-anillo-op { from { opacity: 0; } to { opacity: 1; } }
@keyframes traza-anillo-esc { from { scale: 0.8; } to { scale: 1; } }

/* Visitas siguientes (html.traza-espera): sin cargador, la página espera
   sobre su fondo y entra con su animación; JS lo retira enseguida (si no
   llega, todo vuelve a verse a los 4 s). */
html.traza-espera body:not(.page-home) main,
html.traza-espera .site-header,
html.traza-espera .hero-bar,
html.traza-espera .whatsapp-float,
html.traza-espera [data-page-part]:not([hidden]) { opacity: 0; animation: traza-espera-seguro 0s linear 4s forwards; }
@keyframes traza-espera-seguro { to { opacity: 1; } }

/* Hasta que js/main.js confirma la marca y el acento de js/data.js (al
   ejecutarse, antes del primer pintado habitual), la cabecera no se ve: así
   nunca asoma la marca de la demo si el HTML no se regeneró. Si JavaScript no
   llega, vuelve a los 3 s. */
html.identidad-espera .site-header { visibility: hidden; animation: traza-i18n-seguro 0s linear 3s forwards; }

/* Recarga con el idioma guardado en inglés: los textos esperan ocultos a que
   js/i18n.js los traduzca (si JavaScript no llega, vuelven a los 3 s). */
html.i18n-wait [data-i18n] { visibility: hidden; animation: traza-i18n-seguro 0s linear 3s forwards; }
@keyframes traza-i18n-seguro { to { visibility: visible; } }

/* Durante un cambio de página: todo bloqueado y cursor de espera. */
html.is-navigating, html.is-navigating * { cursor: wait !important; }
html.is-navigating main,
html.is-navigating .site-header,
html.is-navigating .hero-bar { pointer-events: none; }

/* =========================================================
   Páginas oscuras (listado y nosotros): carbón cálido de Traza
   con el papel como texto y el acento en el filtro activo. Solo cambian los
   colores; la retícula y los componentes son los de siempre.
   ========================================================= */
main[data-theme="dark"] {
  --color-paper: var(--color-carbon-warm);
  --color-ink: var(--paper);
  --color-gray-700: rgba(250, 250, 247, 0.62);
  --color-gray-300: rgba(250, 250, 247, 0.3);
  --color-gray-150: #463C34;
  --color-gray-100: #3A312A;
  --border-hair: 1px solid rgba(250, 250, 247, 0.14);
  --border-hair-strong: 1px solid rgba(250, 250, 247, 0.3);
  color: var(--paper);
}

/* Detalle: el pie pasa por encima de la banda gris, que va más lenta. */
main[data-theme="light"] .site-footer { position: relative; z-index: 1; background: var(--color-paper); }


@media (prefers-reduced-motion: reduce) {
  .dt-photo__frame img { scale: 1; }
  .work__frame img { height: 100%; }
  /* Sin transiciones (no solo más cortas): con una duración mínima, cualquier
     cambio de estilo pasaba a ser una transición y, en ese mismo instante,
     el texto que deja de esperar al idioma seguía oculto. */
  * , *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}
