/* ============================================================
   CHAMÁN — one page · styles.css
   Fase 1: estructura de bloques full viewport + nav fijo
   Paleta extraída del diseño (onepage-desktop.jpg)
   ============================================================ */

/* Safiro Medium — reemplaza a Bebas Neue en todo el texto chico (rediseño 11-ago-2026).
   woff2 del Webfont Kit oficial de atipo foundry, TAL CUAL viene: la licencia
   desktop prohíbe convertir formatos y modificar (por eso no se subsetea; son 14.8 KB).
   Licencia webfont: 1 sitio, pageviews ilimitados, perpetua. PDFs en el disco WD,
   Chamán/2026/assets/tipografia-safiro/. */
@font-face {
  font-family: 'Safiro';
  src: url('../fonts/Safiro-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* Boldonse — tipografía de marca para los TEXTOS GRANDES (manual de identidad) */
@font-face {
  font-family: 'Boldonse';
  src: url('../fonts/Boldonse-Regular.woff2') format('woff2'),
       url('../fonts/Boldonse-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --blanco:  #FFFFFF;
  --lila:    #D8D1E1;   /* morado bajito */
  --negro:   #1D1C1A;
  --coral:   #F1928C;
  --morado:  #6539A7;   /* confirmado en Figma (título manifiesto) */
  --tinta:   #161513;
  --negro-puro: #000000;   /* color del nav según spec */

  /* Tipografías de marca: SAFIRO Medium (nav/UI/cuerpo) + Boldonse (textos grandes).
     Safiro reemplazó a Bebas Neue Book en el rediseño del 11-ago-2026: cambia el
     ancho de TODO el texto chico y los párrafos pasan de caja alta a caja baja.
     El nombre --font-nav se conserva para no tocar sus 12 usos.
     --font-ui es solo fallback del body (ningún texto visible lo usa hoy). */
  --font-nav:     'Safiro', sans-serif;
  --font-display: 'Boldonse', sans-serif;
  --font-ui:      system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Caja de contenido del diseño (Mafer maquetó todo a 1620px).
     Referencia para clamp: preferred = px_diseño / 16.2 vw
     → el valor del diseño es exacto cuando el viewport = 1620px,
       se mantiene fijo por encima (caja centrada) y escala por debajo. */
  --content-max: 1620px;
  --gutter:      clamp(20px, 4vw, 40px);

  --nav-font: clamp(15px, 1.235vw, 20px);    /* 20px  @1620 (Safiro, era Bebas 32) */
  --nav-h:    clamp(76px, 9.26vw, 150px);    /* 150px @1620 */
  --logo-w:   clamp(120px, 11.98vw, 194px);  /* 194px @1620 */

  --cta-w:    clamp(180px, 13.58vw, 220px);  /* 220px @1620 */
  --cta-h:    clamp(50px, 3.70vw, 60px);     /* 60px  @1620 */
  --cta-icon: clamp(19px, 1.48vw, 24px);     /* 24px  @1620 */

  /* Empuje óptico. Con Bebas valía 0.09em porque su cut solo-mayúsculas se apoyaba
     alto en la caja. Safiro tiene métricas normales: con lh 150 y fs 20 el centro
     de sus mayúsculas cae a 74.72 de una banda de 150 (centro real 75), o sea ya
     está centrado y cualquier empuje lo descuadraría. */
  --cap-nudge: 0em;

  /* Tamaños de titulares Boldonse (ref 1620 → px/16.2 vw).
     manifiesto = exacto de Figma; espíritus y contacto medidos. */
  --fs-manif: clamp(60px, 9.57vw, 155px);   /* 155px @1620 — confirmado */
  --fs-esp:   clamp(44px, 4.94vw, 80px);    /* 80px — título Espíritus */
  --fs-cont:  clamp(44px, 4.94vw, 80px);    /* 80px — título Contacto */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-ui);
  color: var(--tinta);
  background: var(--blanco);
  overflow-x: hidden;
}

/* ============ NAV FIJO ============ */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  /* Temas del nav según el fondo del bloque (diseño Mafer). Default = claro. */
  --nav-logo:   var(--negro-puro);   /* logo + hamburguesa */
  --nav-link:   var(--negro-puro);   /* links inactivos */
  --nav-active: var(--morado);       /* link activo + su dot */
  --nav-cta-bg: var(--coral);        /* botón Escríbenos */
  --nav-cta-fg: var(--tinta);
  --nav-cta-bg-h: var(--nav-cta-fg); /* hover = swap bg/fg */
  --nav-cta-fg-h: var(--nav-cta-bg);
  /* Velo del nav al scrollear (ver "VELO" abajo). Default = blanco. */
  --nav-veil-rgb: 255, 255, 255;
  --nav-veil-a:   .72;
  background-color: rgba(var(--nav-veil-rgb), 0);
  /* El blur se declara en reposo a 0 para poder transicionarlo: si solo
     existiera en .is-scrolled, al cruzar los 100px aparecería de golpe. */
  -webkit-backdrop-filter: blur(0px) saturate(1);
  backdrop-filter: blur(0px) saturate(1);
  transition: background-color .35s ease, backdrop-filter .35s ease, -webkit-backdrop-filter .35s ease;
}
.site-header[data-nav="dark"] {      /* fondo negro */
  --nav-logo:   var(--blanco);
  --nav-link:   var(--morado);
  --nav-active: var(--blanco);
  --nav-cta-bg: var(--coral);
  --nav-cta-fg: var(--tinta);
}
.site-header[data-nav="coral"] {     /* fondo coral */
  --nav-logo:   var(--negro-puro);
  /* INVERTIDO en el rediseño del 11-ago-2026: antes inactivos negros y activo
     blanco; ahora inactivos blancos y activo negro. Los temas claro y oscuro no
     cambian. OJO accesibilidad: blanco sobre coral da 2.3:1 (el negro daba 9.2:1)
     — es decisión de diseño de Mafer validada por Manuel. */
  --nav-link:   var(--blanco);
  --nav-active: var(--negro-puro);
  --nav-cta-bg: var(--tinta);        /* botón negro (coral sobre coral no contrasta) */
  --nav-cta-fg: var(--coral);        /* letras + ícono coral (feedback cliente 25-jul) */
  /* El swap por defecto dejaría un botón coral sobre fondo coral (invisible):
     en este tema el hover mantiene el negro y aclara el texto a blanco. */
  --nav-cta-bg-h: var(--tinta);
  --nav-cta-fg-h: var(--blanco);
}

/* ---- VELO DEL NAV (feedback cliente 25-jul) --------------------------------
   Hasta 100px de recorrido el nav va limpio sobre el hero; a partir de ahí
   aparece una banda traslúcida que difumina lo que pasa por detrás (mismo
   efecto que el nav de negocioclic: blur 14px + saturate 1.7).
   El velo toma el color del bloque que está debajo (`data-veil`, lo escribe
   nav.js junto con el tema) para que se lea como la misma sección, más densa,
   en vez de una banda blanca sobre el bloque negro. */
.site-header[data-veil="blanco"] { --nav-veil-rgb: 255, 255, 255; --nav-veil-a: .72; }
.site-header[data-veil="lila"]   { --nav-veil-rgb: 216, 209, 225; --nav-veil-a: .78; }
.site-header[data-veil="negro"]  { --nav-veil-rgb: 29, 28, 26;    --nav-veil-a: .66; }
.site-header[data-veil="coral"]  { --nav-veil-rgb: 241, 146, 140; --nav-veil-a: .74; }

/* SIN `saturate` (3-sep-2026, feedback de Manuel: «sobre fondo coral se ven dos
   tonos de coral»). El velo pinta el color del bloque al 74% y deja pasar el 26%
   del fondo DESENFOCADO; si además se satura ese 26%, sobre un bloque de color
   plano la banda ya no da el mismo color que el bloque y aparece un corte duro a
   la altura del nav. Medido a 1440x900 sobre Conjuros: banda rgb(245,142,136)
   contra bloque rgb(241,146,140). Sin saturate la cuenta cierra sola —74% de
   coral sobre 26% de coral sigue siendo coral— y donde pasa una card por detrás
   el desenfoque sigue haciendo su trabajo, que era el objetivo del velo.
   El saturate venía copiado del nav de negocioclic. En blanco no hacía nada
   (es acromático) y en lila y negro desviaba menos de 2 niveles por canal; el
   único tono que lo delataba era el coral, que es el más saturado de la paleta.
   Se deja `saturate(1)` explícito, no se borra: la transición desde el reposo
   sólo interpola si las dos listas de filtros tienen las mismas funciones. */
.site-header.is-scrolled {
  background-color: rgba(var(--nav-veil-rgb), var(--nav-veil-a));
  -webkit-backdrop-filter: blur(14px) saturate(1);
  backdrop-filter: blur(14px) saturate(1);
}
/* Sin backdrop-filter (navegadores viejos) el velo traslúcido dejaría el texto
   ilegible sobre el contenido que pasa detrás → se opaca casi por completo. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-scrolled { background-color: rgba(var(--nav-veil-rgb), .96); }
}

.header-inner {
  width: min(var(--content-max), 100% - var(--gutter) * 2);  /* caja 1620 centrada */
  margin: 0 auto;
  height: var(--nav-h);            /* line-height 150px del diseño = banda del nav */
  display: flex;
  align-items: center;             /* vertical alignment: middle */
  justify-content: space-between;
  gap: 24px;
}

.logo {
  display: inline-flex;
  color: var(--nav-logo);
  transition: color .3s ease;
}
.logo-svg {
  width: var(--logo-w);
  height: auto;
  display: block;
}

/* Nav + botón agrupados y pegados a la derecha de la caja 1620 (diseño Mafer) */
.nav-cluster {
  display: flex;
  align-items: center;
  gap: clamp(24px, 3vw, 48px);
}
.main-nav {
  display: flex;
  align-items: center;
  gap: clamp(24px, 3.5vw, 56px);
}
.nav-link {
  /* Specs Figma (rediseño): Safiro Medium 500 · 20px · lh 150 · ls −2% · uppercase */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: var(--nav-font);
  letter-spacing: -.02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--nav-link);
  transition: color .3s ease;
  transform: translateY(var(--cap-nudge));  /* centrado óptico */
}
.nav-link:hover { opacity: .7; }

/* Estado activo: SOLO color, sin dot. El rediseño del 11-ago-2026 retiró el punto
   de 9px que iba bajo el link (no aparece en ninguno de los 9 marcos del PDF
   nuevo); el activo se distingue únicamente por el color del tema. */
.nav-link.is-active { color: var(--nav-active); }

.btn-cta {
  /* Diseño Mafer: 220 × 60 px, sin borde, pastilla coral */
  width: var(--cta-w);
  height: var(--cta-h);
  font-family: var(--font-nav);
  font-weight: 400;
  font-size: var(--nav-font);
  letter-spacing: .01em;
  text-transform: uppercase;
  text-decoration: none;
  /* En el header toma el tema; fuera (menú overlay) cae a coral/tinta */
  color: var(--nav-cta-fg, var(--tinta));
  background: var(--nav-cta-bg, var(--coral));
  border: none;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  transition: background .25s ease, color .25s ease;
}
.btn-cta:hover {
  background: var(--nav-cta-bg-h, var(--tinta));
  color: var(--nav-cta-fg-h, var(--coral));
}
.btn-cta__label { transform: translateY(var(--cap-nudge)); }  /* centrado óptico, sin mover el ícono */
.cta-icon {
  width: var(--cta-icon);
  height: var(--cta-icon);
  flex-shrink: 0;
}

/* Hamburguesa (Lucide menu) — oculta en desktop, visible en tablet/mobile */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: none;
  border: none;
  color: var(--nav-logo);
  transition: color .3s ease;
  cursor: pointer;
}
.nav-toggle svg {
  /* +15% sobre el tamaño original clamp(30,3.6vw,42) — feedback cliente 25-jul */
  width: clamp(35px, 4.14vw, 48px);
  height: auto;
}

/* ============ MENÚ OVERLAY (tablet / mobile) ============ */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--blanco);
  display: flex;
  flex-direction: column;
  padding: 0 var(--gutter) calc(var(--gutter) + 20px);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity .3s ease, transform .3s ease, visibility .3s ease;
  overflow-y: auto;
}
.mobile-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.mobile-menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h);
  flex-shrink: 0;
}
.mm-logo-img { width: var(--logo-w); height: auto; display: block; }
.menu-close {
  background: none;
  border: none;
  color: var(--tinta);
  cursor: pointer;
  display: inline-flex;
  padding: 0;
}
/* La X del overlay va del mismo tamaño que la hamburguesa (spec Figma) → +15% igual */
.menu-close svg { width: clamp(35px, 4.14vw, 48px); height: auto; }

.mobile-menu__nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(4px, 1.5vh, 18px);
}
.mm-link {
  font-family: var(--font-nav);
  font-weight: 500;
  /* Mafer no rediseñó el overlay, pero Safiro es MUCHO más ancha que la Bebas
     condensada que había: "MANIFIESTO" pasa a 6.52px de tinta por px de cuerpo y
     con el clamp anterior (mín. 48px) se desbordaba a 320px de ancho (313 > 280).
     Este rango deja la palabra más larga dentro del gutter de 320 a 1023. */
  /* 12-ago: −20% pedido por Jonathan. Los tres términos del clamp van por 0.8
     (40→32, 12.2→9.76vw, 100→80) para que el recorte sea parejo en toda la gama. */
  font-size: clamp(32px, 9.76vw, 80px);
  line-height: 1.1;
  letter-spacing: .01em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  color: var(--tinta);
  padding: .18em 0;
}
/* Estado activo en el menú = banda morada full-width + texto blanco */
.mm-link.is-active {
  color: var(--blanco);
  background: var(--morado);
  margin: 0 calc(var(--gutter) * -1);   /* full-bleed hasta los bordes */
}
/* El cuerpo sale del ANCHO DEL BOTÓN, no del viewport: "ESCRÍBENOS" + gap .5em +
   flecha .71em ocupan 7.695 px por cada px de cuerpo, así que con el 84% de la
   pastilla para el contenido queda un 8% de aire a cada lado. El clamp anterior
   (10.2vw hasta 50px) no miraba a la pastilla, que se topa en 360px: de 490px de
   ancho en adelante el contenido medía 385 dentro de un botón de 360 y se salía,
   y a 320px se salía también por el otro extremo. Ahora respira 21–30px por lado
   en toda la gama y nunca se desborda. */
.mobile-menu__cta {
  align-self: center;
  flex-shrink: 0;
  width: min(360px, 84vw);
  height: clamp(64px, 17vw, 84px);
  font-size: clamp(26px, 9.18vw, 39px);
}
/* Flecha desacoplada del em del texto: su alto = alto de las MAYÚSCULAS (cap-height Bebas 0.70 ÷ ratio visual flecha 0.98 = 0.71em) */
.mobile-menu__cta .cta-icon { width: 0.71em; height: 0.71em; }

/* ============ BLOQUES ============ */
.bloque {
  position: relative;
  min-height: 100svh;      /* full alto viewport (svh = estable en mobile) */
  width: 100%;
  display: grid;
  place-items: center;
}

/* ---- Viñetas de navegación del manifiesto (bloques 2-3-4) ----
   Fijas al borde de la caja 1620, centradas verticalmente. Solo visibles
   mientras se recorren los bloques 2-4. Activo baja 1→2→3.
   Medidas Mafer: inactivo ~14px, activo ~20px, separación ~40px centro a centro. */
.dots-nav {
  position: fixed;
  top: 50%;
  right: max(var(--gutter), (100vw - var(--content-max)) / 2);
  transform: translateY(-50%);
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(18px, 1.6vw, 26px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .35s ease, visibility .35s ease;

  /* colores por fondo (los ajusta el JS con data-bg) */
  --dot-off: var(--tinta);
  --dot-on:  var(--coral);
  /* Halo del MISMO color que el fondo del panel: sobre el fondo plano no se
     ve nada —es el mismo color— y sobre una ilustración despega el punto.
     Hizo falta al encender las viñetas en tablet (23-ago): ahí el arte 3D
     sangra hasta el borde derecho y pasa justo por debajo de la columna de
     puntos, así que los oscuros desaparecían sobre la calavera. Medido a
     1023×768: los TRES puntos caen dentro de la caja del arte. */
  --dot-halo: transparent;
}
.dots-nav.is-visible { opacity: 1; visibility: visible; pointer-events: auto; }
.dots-nav[data-bg="lila"]  { --dot-off: var(--tinta);  --dot-on: var(--coral);  --dot-halo: var(--lila); }
.dots-nav[data-bg="negro"] { --dot-off: var(--blanco); --dot-on: var(--coral);  --dot-halo: var(--negro); }
.dots-nav[data-bg="coral"] { --dot-off: var(--tinta);  --dot-on: var(--blanco); --dot-halo: var(--coral); }

.dots-nav .dot {
  width: clamp(10px, 0.864vw, 14px);   /* 14px @1620 */
  height: clamp(10px, 0.864vw, 14px);
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--dot-off);
  cursor: pointer;
  /* El anillo va en `box-shadow` y no en `border`: el borde entraría en la
     caja del punto y le cambiaría el tamaño medido de Mafer. */
  box-shadow: 0 0 0 1.5px var(--dot-halo), 0 0 4px 1.5px var(--dot-halo);
  transition: background .3s ease, transform .3s ease, box-shadow .3s ease;
}
.dots-nav .dot.is-active {
  background: var(--dot-on);
  transform: scale(1.42);              /* activo ~20px */
}
/* Mobile (Mafer): viñetas HORIZONTALES al pie del bloque, centradas */
@media (max-width: 767px) {
  .dots-nav {
    top: auto;
    right: auto;
    left: 50%;
    bottom: clamp(16px, 3.4vh, 30px);
    transform: translateX(-50%);
    flex-direction: row;
    gap: clamp(14px, 4vw, 22px);
  }
  .dots-nav .dot {
    width: clamp(11px, 2.97vw, 13.5px);
    height: clamp(11px, 2.97vw, 13.5px);
  }
}

/* ---- Botón flotante de WhatsApp (pedido del cliente, 26-ago) ----
   Fijo abajo a la derecha en TODOS los tamaños. z-index 150: por encima del
   contenido y de las viñetas (90), y por DEBAJO del menú overlay (200), para
   que el menú abierto lo tape en vez de dejarlo flotando encima.
   El aro blanco no se ve sobre los fondos claros y despega el disco negro
   sobre el negro del footer, que es el único fondo donde se perdía. */
.wa-float {
  position: fixed;
  right: clamp(16px, var(--gutter), 40px);
  bottom: clamp(16px, 3vh, 30px);
  z-index: 150;
  width:  clamp(46px, 4.2vw, 60px);
  height: clamp(46px, 4.2vw, 60px);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--tinta);
  color: var(--blanco);
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .45), 0 6px 18px rgba(0, 0, 0, .22);
  transition: transform .25s ease, background .25s ease;
}
.wa-float svg { width: 56%; height: 56%; display: block; }
.wa-float:hover { background: var(--morado); transform: scale(1.06); }
@media (prefers-reduced-motion: reduce) {
  .wa-float { transition: none; }
  .wa-float:hover { transform: none; }
}
/* En móvil las viñetas del manifiesto van abajo AL CENTRO y el botón a la
   derecha: no se cruzan, pero se le da algo más de aire al pie. */
@media (max-width: 767px) {
  .wa-float { bottom: clamp(14px, 2.6vh, 24px); }
}
/* En pantallas muy angostas (≤360) la última línea del copyright llega hasta
   donde flota el botón y quedaba tapada: se le da al pie ese aire de más. */
@media (max-width: 360px) {
  footer.footer { padding-bottom: calc(78.5 * var(--u) + 34px); }
}

/* ---- Indicador de scroll al pie del hero ---- */
.scroll-hint {
  position: absolute;
  left: 50%;
  bottom: clamp(24px, 3vw, 48px);
  transform: translateX(-50%);
  color: var(--tinta);
  display: block;
}
.scroll-hint-svg {
  width: auto;
  height: clamp(56px, 5.19vw, 84px);   /* 84px @1620 */
  display: block;
}
/* Ícono mobile (solo chevron, Mafer) — oculto por defecto; se muestra en ≤480 */
.scroll-hint-svg--mob { display: none; width: auto; height: 38px; }
/* Desktop (12-ago): el ícono baja un 20% y se ancla a 32px del borde inferior.
   Al encoger y bajar, gana ~20px de aire contra "LAS MARCAS". La animación no
   se toca: vive dentro del SVG, en unidades de usuario, así que escala sola. */
@media (min-width: 1024px) {
  .scroll-hint { bottom: 32px; }
  .scroll-hint-svg { height: clamp(44.8px, 4.152vw, 67.2px); }
}
/* Ruedita: baja y se desvanece (animación clásica de mouse) */
.sh-wheel {
  animation: sh-wheel 1.8s cubic-bezier(.4,0,.2,1) infinite;
  transform-box: fill-box;
  transform-origin: center;
}
@keyframes sh-wheel {
  0%      { transform: translateY(-3px); opacity: 0; }
  25%     { opacity: 1; }
  70%     { transform: translateY(4px);  opacity: 0; }
  100%    { transform: translateY(4px);  opacity: 0; }
}
/* Chevrons: pulso en secuencia hacia abajo */
.sh-chev {
  animation: sh-chev 1.8s ease-in-out infinite;
  opacity: .35;
}
.sh-chev-1 { animation-delay: .15s; }
.sh-chev-2 { animation-delay: .35s; }
@keyframes sh-chev {
  0%, 60%, 100% { opacity: .3; }
  30%           { opacity: 1; }
}

/* El footer no mide alto full (su padding lo define footer.footer) */
footer.bloque { min-height: auto; }

.bg-blanco { background: var(--blanco); color: var(--tinta); }

/* ---- Hero: cover full-bleed (fallback del video) ---- */
.hero { overflow: hidden; }
.hero-cover {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero .scroll-hint { z-index: 2; }

/* ---- Hero: TITULAR EN TEXTO VIVO -------------------------------------------
   Antes iba horneado dentro del bitmap, así que en cualquier proporción que no
   fuera 16:9 el recorte lo descuadraba (obs. del cliente 25-jul). Ahora es <h1>.

   Medidas tomadas del Figma de Mafer (rasterizado 1:1) y verificadas contra las
   métricas del woff2: nuestro corte de Boldonse calza con el suyo, así que los
   px del diseño se usan tal cual, sin factor de corrección.

     desktop 1920×1080 · fs 105.6 (=5.5vw) · interlínea 158 (1.496) · caja 1178 (11.155em)
     tablet   768×1024 · fs 69.9  (=9.098vw) · interlínea 100 (1.431)
     mobile   390×844  · fs 40.8  (=10.45vw) · interlínea 56  (1.374)

   ESCALADO: el bloque se dimensiona para caber SIEMPRE en la franja libre entre
   el nav y el indicador de scroll (`--hero-avail`). Por eso el tamaño es el
   menor entre el proporcional al ancho y el que entra a lo alto: en 1920×1080
   gana el del diseño (105.6px exactos) y en pantallas más bajas —1280×720,
   1440×800— manda el alto, que es justo donde antes se cortaba. */
.hero-title {
  /* alto que ocupan el indicador de scroll y su separación al borde */
  --hero-hint:  calc(clamp(24px, 3vw, 48px) + clamp(56px, 5.19vw, 84px));
  --hero-avail: calc(100svh - var(--nav-h) - var(--hero-hint));

  --hero-lh:    1.496;                     /* interlínea (desktop) */
  --hero-gap:   1.496;                     /* hueco de la máscara = 1 renglón */
  --hero-blk:   calc(4 * var(--hero-lh) + var(--hero-gap));   /* alto del bloque, en em */
  --fs-hero:    min(5.5vw, calc(var(--hero-avail) / var(--hero-blk)));

  position: absolute;
  z-index: 1;
  left: 50%;
  top: calc(var(--nav-h) + (var(--hero-avail) - var(--hero-blk) * var(--fs-hero)) / 2);
  transform: translateX(-50%);
  width: min(calc(11.155 * var(--fs-hero)), 100% - var(--gutter) * 2);

  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-hero);
  line-height: var(--hero-lh);
  text-transform: uppercase;
  color: var(--tinta);
  display: flex;
  flex-direction: column;
  row-gap: calc(var(--hero-gap) * 1em);
  pointer-events: none;                    /* no debe estorbar al cursor sobre el hero */
}
.hero-group { display: flex; flex-direction: column; }
.hero-group--top { align-items: flex-start; }
.hero-group--bot { align-items: flex-end; }
.hero-line { display: block; white-space: nowrap; }

/* Tablet y mobile: Mafer centra los 4 renglones y abre el hueco de la máscara
   (en desktop el hueco es un renglón; acá es bastante más). */
@media (max-width: 1023px) {
  .hero-title {
    --hero-lh:  1.431;
    --hero-gap: 4.179;
    /* en ≤1023 el indicador es el doble chevron de Mafer (38px), no el ratón de 84 */
    --hero-hint: calc(clamp(24px, 3vw, 48px) + 38px);
    --fs-hero:  min(9.098vw, calc(var(--hero-avail) / var(--hero-blk)));
    width: calc(100% - var(--gutter) * 2);
    text-align: center;
  }
  .hero-group--top,
  .hero-group--bot { align-items: center; }
}
@media (max-width: 767px) {
  .hero-title {
    --hero-lh:  1.374;
    --hero-gap: 5.937;
    --fs-hero:  min(10.45vw, calc(var(--hero-avail) / var(--hero-blk)));
  }
  /* A este alto el `cover` escala el retrato por el ancho y la máscara queda
     ~25% más chica que en la maqueta de Mafer (en tablet calza exacta, porque
     ahí manda el ancho). Se compensa con zoom + un empuje para recentrarla. */
  .hero-cover img { transform: scale(1.25) translateY(-1.78%); }
}
.bg-lila   { background: var(--lila);   color: var(--morado); }
.bg-negro  { background: var(--negro);  color: var(--blanco); }
.bg-coral  { background: var(--coral);  color: var(--tinta); }

/* ============ MANIFIESTO (bloques 2-3-4 · scroll bloqueado) ============
   Por defecto (mobile / sin JS / reduced-motion): paneles en flujo normal,
   cada uno a viewport completo, apilados verticalmente.
   En desktop, el JS añade .is-pinned y GSAP fija la sección apilando paneles. */
.manifiesto { position: relative; }
.manifiesto__stack { position: relative; }
.panel {
  position: relative;
  min-height: 100svh;
  width: 100%;
  display: grid;
  place-items: center;
}
.manifiesto.is-pinned .manifiesto__stack { height: 100svh; overflow: hidden; }
.manifiesto.is-pinned .panel {
  position: absolute;
  inset: 0;
  min-height: 0;
  height: 100%;
  will-change: transform;
}

/* ============ TITULARES (Boldonse) ============
   Boldonse tiene caps más altas que el em (~1.18×); de ahí el line-height amplio.
   Tamaños en :root (--fs-*), medidos del PDF (manifiesto = exacto de Figma). */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0;
  line-height: 1.32;   /* Boldonse: caps ~1.18× em → necesita leading amplio */
  margin: 0;
}
.block-inner {
  width: min(var(--content-max), 100% - var(--gutter) * 2);
  margin: 0 auto;
}
/* Subtítulo del manifiesto. Figma (rediseño): Safiro Medium 44 / lh 40 / ls 0,
   CAJA BAJA (antes Bebas en caja alta) y caja de 366 de ancho.
   El interlineado es MENOR que el cuerpo (40 sobre 44): es deliberado, así lo
   dibujó Mafer. El ancho de 366 es lo que parte el texto en 4 líneas —
   "Creadores de comunicación" mide 528 y no entra— así que los <br> del HTML
   sobran y se anulan. */
.block-sub {
  font-family: var(--font-nav);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  line-height: calc(40 / 44);
  font-size: clamp(19px, 2.716vw, 44px);   /* 44px @1620 */
  width: min(366px, 22.6vw);
  color: var(--tinta);
  margin-top: 1em;
}
.bg-negro .block-sub { color: var(--blanco); }

/* Titulares por bloque (los que usa el HTML) */
.title-manif { font-size: var(--fs-manif); line-height: 1.42; color: var(--morado); }
.title-esp   { font-size: var(--fs-esp);   color: var(--morado); }

/* ============ BLOQUE 2 · MANIFIESTO (layout Mafer) ============
   Título 4 líneas a la izquierda, subtítulo en el hueco, calavera a la derecha. */
.panel-inner { position: relative; height: 100%; }
.panel-manif .panel-title {
  position: absolute;
  left: 0;
  top: 54%;
  transform: translateY(-50%);
  /* alto-aware: evita que el título desborde el panel en pantallas bajas */
  font-size: min(var(--fs-manif), 14.5svh);
}
.panel-manif .panel-sub {
  position: absolute;
  left: 32%;
  top: 57%;
  margin: 0;
  font-size: clamp(19px, 2.716vw, 44px);   /* 44px @1620 (Figma rediseño) */
  line-height: calc(40 / 44);
}
.panel-manif .panel-art {
  position: absolute;
  right: 0;
  top: 51%;
  transform: translateY(-50%);
  width: 54%;
  height: auto;
  pointer-events: none;
  user-select: none;
}
/* Bloque 3 · corazón: un poco más chico y bajo que la calavera */
.panel-marcas .panel-art { width: 50%; top: 55%; }

/* ============ PANEL 4 · STATS (coral) ============
   3 cards con borde; la del medio va offset abajo; la imagen 3D se monta
   (superpone) sobre su label con margin negativo + z-index. */
.panel-stats { padding-top: var(--nav-h); }
.stats-grid {
  width: min(1388px, 100% - var(--gutter) * 2);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 4.1vw, 67px);
  align-items: start;
}
.stat-card {
  border: 1.5px solid var(--tinta);
  border-radius: clamp(18px, 1.85vw, 30px);
  min-height: clamp(420px, 40vw, 648px);
  padding: clamp(34px, 3.1vw, 50px) clamp(14px, 1.5vw, 24px) clamp(28px, 2.8vw, 46px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.stat-card--low { margin-top: clamp(28px, 3.3vw, 54px); }  /* card central más abajo */

/* Envoltura número+label: transparente en desktop (no altera el layout de columna);
   en mobile se vuelve una caja del grid (ver media ≤767). */
.stat-head { display: contents; }

/* La cifra se cuenta desde 0 al entrar el bloque (ver nav.js). Como Boldonse
   trae los dígitos PROPORCIONALES —y muy dispares: el 0 mide 108 px donde el 1
   mide 45 a cuerpo 100— contar sobre el propio texto haría bailar la cifra de
   ancho en cada tic, y con la card centrada el baile se ve.
   Por eso van dos capas: un fantasma con el valor FINAL, invisible pero en
   flujo, que fija el ancho de la caja de una vez; y encima, en absoluto, la
   cifra que corre. La caja nunca cambia de tamaño y el número no se mueve.
   Sin JS queda sólo el valor final, que es el marcado de siempre. */
.stat-num {
  position: relative;
  font-family: var(--font-display);
  text-transform: uppercase;
  line-height: 1;
  color: var(--morado);
  font-size: clamp(56px, 6.17vw, 100px);  /* +12/+50/+20 = 100px (Figma) */
}
.stat-num__ghost { visibility: hidden; }
.stat-num__val   { position: absolute; left: 0; right: 0; top: 0; }
.stat-label {
  font-family: var(--font-display);
  text-transform: uppercase;
  line-height: 1;
  color: var(--morado);
  font-size: clamp(28px, 3.09vw, 50px);   /* AÑOS/MARCAS/PREMIOS = 50px (Figma) */
  margin-top: clamp(18px, 2.1vw, 34px);   /* gap número→label ~16px visual (Boldonse desborda) */
}
.stat-img {
  width: clamp(150px, 15.8vw, 256px);
  height: auto;
  margin-top: clamp(-34px, -1.7vw, -16px);  /* montaje: se superpone levemente al label */
  position: relative;
  z-index: 2;
  pointer-events: none;
}
.stat-desc {
  /* Figma (rediseño): Safiro Medium 32 / lh 40 / ls 2% / centrado, en CAJA BAJA. */
  font-family: var(--font-nav);
  font-weight: 500;
  text-transform: none;
  letter-spacing: .02em;
  line-height: calc(40 / 32);
  color: var(--tinta);
  font-size: clamp(18px, 1.975vw, 32px);  /* 32px @1620 */
  margin-top: auto;
}
/* Los <br class="br-d/br-m"> del diseño ANTERIOR (Bebas en caja alta, 3 líneas
   en desktop y 2 en mobile) se retiraron del HTML el 12-ago: con Safiro en caja
   baja el reparto lo da el ancho de la card (2/3/3 líneas) y los saltos
   forzados ya venían anulados por CSS, así que eran marcado inerte. */
/* Retoques finos por card (Jonathan/Mafer) */
.stat-card:nth-child(1) .stat-img,
.stat-card:nth-child(2) .stat-img { transform: translateY(20px); }        /* imagen abajo 20px */
/* card1 y card2 desc: en su posición original (subieron 20px y ahora bajaron 20px → net 0) */
.stat-card:nth-child(3) .stat-img { transform: translateY(10px) scaleX(-1) rotate(-5.84deg); } /* abajo 10px + espejo + rotate -5.84° (el espejo invierte el giro → orientación opuesta al cerebro) */
.stat-card:nth-child(3) .stat-desc { transform: translateY(20px); }       /* texto abajo 20px */
/* card izquierda: TODOS sus elementos 10px más abajo (parejo, sin mover el borde) */
.stat-card:nth-child(1) .stat-num,
.stat-card:nth-child(1) .stat-label,
.stat-card:nth-child(1) .stat-desc { transform: translateY(10px); }
.stat-card:nth-child(1) .stat-img { transform: translateY(30px) rotate(5.84deg); } /* 20+10 abajo + rotate 5.84° (Figma -5.84° = CSS +5.84°) */

/* ============ DESKTOP ≥1024 · MANIFIESTO A ESCALA ÚNICA ============
   Misma premisa que el hero: el panel de Mafer es una caja de 1620×1080 con
   una banda de nav de 150 arriba (→ 930 útiles). Todo (título, subtítulo,
   imagen 3D, cards) se expresa en unidades de ESE diseño y se multiplica por
   una sola escala --u = min(lo que da el ancho, lo que da el alto).
   Antes cada pieza se clampeaba solo contra el ancho: en pantallas bajas el
   título encogía por su guarda de alto y el resto no → la composición se
   desincronizaba y se cortaba. Con --u encoge todo junto y nunca desborda.
   Medidas tomadas del PDF de Figma a 1:1 (ver reference_chaman_design_specs). */
@media (min-width: 1024px) {
  .manifiesto .panel {
    --u-w: calc(min(var(--content-max), 100vw - var(--gutter) * 2) / 1620);
    --u-h: calc((100svh - var(--nav-h)) / 930);
    --u:   min(var(--u-w), var(--u-h));
    /* Y del diseño 0 dentro del panel: la línea 150 del diseño cae en el borde
       inferior del nav; el sobrante (cuando manda el ancho) se reparte parejo. */
    --frame-top: calc(var(--nav-h) - 150 * var(--u)
                      + (100svh - var(--nav-h) - 930 * var(--u)) / 2);
  }

  /* --- Paneles 2 y 3: la caja de diseño, centrada --- */
  .panel-manif .panel-inner {
    position: absolute;
    top: var(--frame-top);
    left: 50%;
    margin-left: calc(-810 * var(--u));   /* 1620/2 */
    width: calc(1620 * var(--u));
    height: calc(1080 * var(--u));
    max-width: none;
  }
  /* Título: caja en x=150 (borde de la caja de contenido), y=145 del diseño.
     155/220 es el spec exacto de Figma. */
  .panel-manif .panel-title {
    position: absolute;
    top: calc(145 * var(--u));
    left: 0;
    transform: none;
    font-size: calc(155 * var(--u));
    line-height: 1.419355;                /* 220/155 */
    white-space: nowrap;
  }
  /* Subtítulo: Bebas 35/40 SIN letter-spacing — así medían las 3 líneas del
     Figma al px (con el .02em de .block-sub salían ~10% más largas y la
     primera línea se metía debajo de la calavera). La x difiere entre paneles. */
  .panel-manif .panel-sub {
    position: absolute;
    top: calc(606 * var(--u));            /* cap top 610 − 4 de offset de línea */
    /* OJO: left es relativo a la CAJA de contenido (arranca en x=150 del canvas),
       no al canvas de 1920. La tinta del Figma va en 698 → 698−150−2(lsb) = 546. */
    left: calc(546 * var(--u));
    transform: none;
    margin: 0;
    font-size: calc(44 * var(--u));       /* Figma rediseño: 44 / lh 40 / ls 0 */
    line-height: calc(40 / 44);
    letter-spacing: 0;
    width: calc(366 * var(--u));          /* la caja es lo que parte el texto en 4 */
  }
  .panel-marcas .panel-sub { top: calc(611 * var(--u)); left: calc(560 * var(--u)); width: calc(352 * var(--u)); }  /* caja de Figma: 352×211 */

  /* Imágenes 3D: caja del Figma, no "54% pegado al borde" (eso las hacía ~10%
     más grandes y las montaba sobre el texto — obs. 5 del cliente).
     Los renders 3D que tenemos NO son exactamente los del Figma (proporción
     distinta), así que se ancla la arista que manda en cada caso y se respeta
     el aspect ratio del asset:
       · calavera → alto de Mafer (763) + borde derecho e Y de la corona; así el
         lapicero cae donde corresponde y deja libre el subtítulo.
       · corazón  → ancho de Mafer (787) + borde derecho; así la punta de la
         flecha no invade "UNIMOS". */
  /* La calavera se corrió 50 a la derecha (right 72 → 22) en el rediseño: su
     silueta arrancaba en x=950 y el subtítulo nuevo, que va en 698 y mide 293,
     le chocaba 41px. En el Figma la calavera arranca en 1000 A LA ALTURA DEL
     TEXTO y deja el hueco 645→1000 que el subtítulo necesita. El corazón del
     bloque 3 NO se toca: el nuestro arranca en 1061, más a la derecha aún. */
  .panel-manif .panel-art {
    position: absolute;
    top: calc(226 * var(--u));
    right: calc(22 * var(--u));
    left: auto;
    transform: none;
    width: calc(748 * var(--u));       /* → alto 763 */
  }
  .panel-marcas .panel-art {
    top: calc(221 * var(--u));
    right: calc(45 * var(--u));
    width: calc(787 * var(--u));       /* → alto 711 */
  }

  /* --- Panel 4 · stats: la grilla también cuelga de --u --- */
  .panel-stats { padding: 0; }
  .panel-stats .stats-grid {
    position: absolute;
    top: calc(var(--frame-top) + 236 * var(--u));
    left: 50%;
    margin: 0 0 0 calc(-695 * var(--u));   /* 1390/2 */
    width: calc(1390 * var(--u));
    gap: calc(65 * var(--u));
  }
  .panel-stats .stat-card {
    min-height: calc(650 * var(--u));
    border-radius: calc(30 * var(--u));
    padding: calc(50 * var(--u)) calc(24 * var(--u)) calc(46 * var(--u));
  }
  .panel-stats .stat-card--low { margin-top: calc(54 * var(--u)); }
  .panel-stats .stat-num   { font-size: calc(100 * var(--u)); }
  .panel-stats .stat-label { font-size: calc(50 * var(--u)); margin-top: calc(34 * var(--u)); }
  .panel-stats .stat-img   { width: calc(256 * var(--u)); margin-top: calc(-32.6 * var(--u)); }
  .panel-stats .stat-desc  { font-size: calc(32 * var(--u)); }
  /* Los retoques finos de montaje también escalan (antes eran px fijos) */
  .panel-stats .stat-card:nth-child(1) .stat-num,
  .panel-stats .stat-card:nth-child(1) .stat-label,
  .panel-stats .stat-card:nth-child(1) .stat-desc { transform: translateY(calc(10 * var(--u))); }
  .panel-stats .stat-card:nth-child(1) .stat-img  { transform: translateY(calc(30 * var(--u))) rotate(5.84deg); }
  .panel-stats .stat-card:nth-child(2) .stat-img  { transform: translateY(calc(20 * var(--u))); }
  /* La card del medio es la única cuyo párrafo ocupa 5 líneas: su contenido
     llena los 650 de alto, el `margin-top:auto` de la descripción se queda sin
     holgura y la imagen —que va 20 más abajo— le cae encima (medido: −20 en
     TODOS los anchos de escritorio, no solo en laptops chicas). El margen
     inferior reserva ese desplazamiento más el mismo aire que tiene la card 1;
     la card crece 40 y abajo sobran ~126, así que no toca el borde del panel.
     Las cards 1 y 3 tienen holgura de sobra: no se mueven. */
  .panel-stats .stat-card:nth-child(2) .stat-img  { margin-bottom: calc(40 * var(--u)); }
  .panel-stats .stat-card:nth-child(3) .stat-img  { transform: translateY(calc(10 * var(--u))) scaleX(-1) rotate(-5.84deg); }
  .panel-stats .stat-card:nth-child(3) .stat-desc { transform: translateY(calc(20 * var(--u))); }
}

/* Mobile / sin pin (≤767): apilar centrado (maqueta mobile de Mafer) */
@media (max-width: 767px) {
  .panel-manif .panel-inner {
    height: auto;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(14px, 2.56vh, 24px);   /* separación título→subtítulo (−20% adicional) */
    padding: calc(var(--nav-h) + 3vh) 0 20vh;  /* reserva inferior mayor: sube la composición y la separa de las viñetas */
    text-align: center;
  }
  .panel-manif .panel-title,
  .panel-manif .panel-sub,
  .panel-manif .panel-art { position: static; transform: none; }
  /* Conjunto (título+subtítulo+imagen) al 80% del tamaño previo, pedido por Jonathan.
     line-height 1.4: las caps de Boldonse (~1.18em) necesitan leading amplio o se enciman. */
  .panel-manif .panel-title { font-size: clamp(38px, 11.7vw, 53px); line-height: 1.4; text-align: center; }
  .panel-manif .panel-sub { font-size: clamp(20px, 7.7vw, 33px); line-height: calc(40 / 44); width: auto; }
  /* la calavera/corazón se acercan al subtítulo hasta montarse un poco (Figma) */
  .panel-manif .panel-art { width: min(59%, 288px); margin-top: calc(clamp(-42px, -5.28vh, -21px) + 12px); }  /* 4 + 8 (12-ago) */
  /* la calavera (bloque 2): a medio camino del ajuste anterior (Jonathan)
     +6px en todos los viewports mobile (pedido 30-jul): tapaba "...Y AFECTIVA" */
  .panel-manif:not(.panel-marcas) .panel-art { margin-top: calc(clamp(-38px, -4.79vh, -17px) + 18px); }  /* 6 del 30-jul + 4 + 8 del rediseño */

  /* Panel 4 · stats (layout mobile de Mafer): número+label a la izquierda,
     imagen 3D a la derecha, descripción abajo a todo el ancho. */
  .panel-stats { display: block; min-height: auto; padding: calc(var(--nav-h) + 4vh) 0 14vh; }
  .stats-grid {
    grid-template-columns: 1fr;
    width: min(440px, 100% - var(--gutter) * 2);
    gap: clamp(22px, 5.5vw, 34px);
  }
  .stat-card,
  .stat-card--low {
    display: grid;
    grid-template-columns: auto 1fr;   /* col1 = grupo número+label; col2 = imagen */
    grid-template-areas:
      "head img"
      "desc desc";
    column-gap: clamp(6px, 2.4vw, 14px);
    align-items: center;   /* imagen centrada vertical en su fila */
    text-align: left;
    min-height: 0;
    margin-top: 0;
    padding: clamp(15px, 4.2vw, 25px) clamp(22px, 6vw, 30px);  /* márgenes sup/inf −20% y −4px (menos aire, como Figma) */
  }
  /* grupo número+label: caja del grid, CENTRADA vertical en la fila de la imagen
     → el bloque número+label queda alineado con la imagen (más prolijo) */
  .stat-head {
    grid-area: head;
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: center;   /* label centrado bajo su cifra */
  }
  /* número −20% previo; label −30% y −20% encima */
  .stat-num   { font-size: clamp(48px, 15.2vw, 74px); text-align: center; white-space: nowrap; }
  .stat-label { font-size: clamp(19px, 6.16vw, 29px); margin-top: clamp(12px, 3.5vw, 16px); text-align: center; white-space: nowrap; }
  .stat-img {
    grid-area: img;
    align-self: center;
    justify-self: end;
    width: clamp(115px, 36vw, 158px);   /* +20% respecto al mobile previo */
    margin: 0;
  }
  .stat-desc {
    grid-area: desc;
    text-align: left;
    margin-top: clamp(1px, 0.6vw, 3px);   /* gap grupo→párrafo −50% (el resto lo da el centrado del bloque) */
    font-size: clamp(17px, 4.8vw, 22px);  /* menor: cabe en 2 líneas */
    line-height: 1.15;
  }
  /* el montaje/retoques del desktop (translateY/rotate) no aplican al layout mobile */
  .stat-card .stat-num,
  .stat-card .stat-label,
  .stat-card .stat-img,
  .stat-card .stat-desc { transform: none !important; }
  /* AÑOS: rotada 10° horario + bajada 12px (la rotación la había subido). translateY primero = baja recto */
  .panel-stats .stat-card:nth-child(1) .stat-img { transform: translateY(12px) rotate(10deg) !important; }
  /* PREMIOS: espejada + 10° horario. El espejo invierte el giro → rotate(-10) para que SE VEA horario */
  .panel-stats .stat-card:nth-child(3) .stat-img { transform: scaleX(-1) rotate(-10deg) !important; }
  /* párrafos a 2 líneas: mostrar los saltos mobile, ocultar los de desktop */
}

/* ============ MOBILE (≤767) · MANIFIESTO PINEADO EN HORIZONTAL ============
   Obs. #6 del cliente (25-jul): en móvil los 3 paneles pasan de derecha a
   izquierda con la sección enganchada — el desktop pero en el eje X.
   El JS pone .is-pinned solo si hay GSAP y no hay reduced-motion; sin eso
   sigue vigente el bloque de arriba (flujo vertical, tal como se aprobó).

   POR QUÉ ESTE BLOQUE EXISTE: al pinear, cada panel queda clavado a UN
   viewport exacto y lo que sobra se corta. Medido, HOY no cabe ninguno:
   el de stats se pasa entre 35 y 324px en todos los móviles, y en pantallas
   cortas (≤667 de alto) también se pasan los dos manifiestos.
   La solución es el molde de escala única del proyecto, pero con el CONTENIDO
   como divisor: --sh/--sh2 valen "1px del diseño a 390 de ancho" y encogen
   cuando falta alto. Cada medida va como min(clamp de ancho, N * unidad):
   manda la más chica → en pantallas altas gobierna el ancho y todo queda
   idéntico a hoy; en pantallas cortas gobierna el alto y encoge parejo.
   Las N son la tinta medida a 390 (manifiestos 535, stats 673). */
@media (max-width: 767px) {
  /* EL BLOQUE PINEADO SIGUE AL VIEWPORT VISIBLE (dvh), NO AL CHICO (svh).
     Con 100svh el bloque queda más corto que la pantalla cuando la barra de URL
     del teléfono se esconde, y por debajo asomaba una franja del bloque
     siguiente (Team, blanco) justo donde van las viñetas: sobre ese blanco las
     viñetas inactivas (blancas, sobre el panel negro) se volvían invisibles y
     solo se veía la activa. Los TAMAÑOS siguen calculados con svh (--hfree),
     así que cuando la barra aparece y desaparece cambia la caja, nunca el texto. */
  .manifiesto.is-pinned .manifiesto__stack { height: 100dvh; }

  .manifiesto.is-pinned {
    /* alto libre = viewport − nav − (8px de aire arriba + 68 para las viñetas) */
    --hfree: calc(100svh - var(--nav-h) - 76px);
    --sh:  calc(var(--hfree) / 673);   /* unidad del panel de stats */
    /* 575 y no los 535 medidos a 390: por encima de ~500px de ancho el subtítulo
       y el gap siguen creciendo con vw, así que la tinta pesa más por unidad.
       Con 535 la composición se metía 3px bajo el nav en 540×720 y 767×700
       (ventanas de escritorio angostadas, no teléfonos). No cambia nada de 390
       para arriba: ahí sigue mandando el clamp de ancho. */
    --sh2: calc(var(--hfree) / 575);   /* unidad de los dos manifiestos */
  }

  /* --- paneles 2 y 3 (calavera / corazón) --- */
  .manifiesto.is-pinned .panel-manif .panel-inner {
    height: 100%;
    min-height: 0;
    padding: calc(var(--nav-h) + 8px) 0 68px;
    gap: min(clamp(14px, 2.56vh, 24px), calc(21.6 * var(--sh2)));
  }
  .manifiesto.is-pinned .panel-manif .panel-title {
    font-size: min(clamp(38px, 11.7vw, 53px), calc(45.63 * var(--sh2)));
  }
  .manifiesto.is-pinned .panel-manif .panel-sub {
    font-size: min(clamp(18px, 6.16vw, 26px), calc(24.02 * var(--sh2)));
  }
  .manifiesto.is-pinned .panel-manif .panel-art {
    width: min(59%, 288px, calc(230.1 * var(--sh2)));
  }

  /* --- panel 4 (stats) --- */
  .manifiesto.is-pinned .panel-stats {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-height: 0;
    padding: calc(var(--nav-h) + 8px) 0 68px;
  }
  .manifiesto.is-pinned .stats-grid {
    gap: min(clamp(22px, 5.5vw, 34px), calc(22 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-card,
  .manifiesto.is-pinned .stat-card--low {
    padding: min(clamp(15px, 4.2vw, 25px), calc(16.38 * var(--sh)))
             min(clamp(22px, 6vw, 30px), calc(23.4 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-num {
    font-size: min(clamp(48px, 15.2vw, 74px), calc(59.28 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-label {
    font-size: min(clamp(19px, 6.16vw, 29px), calc(24.02 * var(--sh)));
    margin-top: min(clamp(12px, 3.5vw, 16px), calc(13.65 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-img {
    width: min(clamp(115px, 36vw, 158px), calc(140.4 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-desc {
    font-size: min(clamp(17px, 4.8vw, 22px), calc(18.72 * var(--sh)));
    margin-top: min(clamp(1px, 0.6vw, 3px), calc(2.34 * var(--sh)));
  }
}

/* ---- MOBILE ANCHO (431–767) · aire entre el objeto 3D y su párrafo ----
   Los objetos de AÑOS y PREMIOS van rotados, y una caja rotada ocupa más alto
   que la suya: su tinta baja ~22 y ~10 por debajo de la fila del grid, mientras
   el párrafo arranca 3 más abajo. Hasta 430 no se nota porque la primera línea
   es corta y termina antes de llegar al objeto; de 431 para arriba el párrafo
   pasa de 3 a 2 líneas, la primera se alarga y se mete debajo de la flecha
   (medido a 460: 16 px de tinta encima de la línea, 298 píxeles del objeto
   dentro de la caja del texto).

   Por qué solo acá: al perder una línea la card se acorta ~24, así que este
   aire NO agranda el panel respecto de 430 — y el panel de móvil va justo, ya
   se sale de su padding. La maqueta de 390, que es la aprobada, no se toca.
   El aire también encoge con --sh en pantallas cortas, como todo el bloque. */
@media (min-width: 431px) and (max-width: 767px) {
  .panel-stats .stat-card:nth-child(1) .stat-desc { margin-top: 26px; }
  .panel-stats .stat-card:nth-child(3) .stat-desc { margin-top: 14px; }
  .manifiesto.is-pinned .panel-stats .stat-card:nth-child(1) .stat-desc {
    margin-top: min(26px, calc(26 * var(--sh)));
  }
  .manifiesto.is-pinned .panel-stats .stat-card:nth-child(3) .stat-desc {
    margin-top: min(14px, calc(14 * var(--sh)));
  }
}

/* ============ TABLET (768–1023) · Manifiesto (2-3-4) — maqueta tablet de Mafer ============
   El pin es desktop-only (≥1024), así que aquí los bloques van en flujo normal.
   Bloques 2 y 3: título arriba-izq + subtítulo debajo + imagen 3D abajo-derecha (sangra).
   Bloque 4 (stats): 3 cards apiladas, cada una HORIZONTAL (número+label | imagen | descripción).
   Las viñetas quedan verticales a la derecha (default desktop). NO toca mobile (≤767). */
@media (min-width: 768px) and (max-width: 1023px) {
  /* --- Bloques 2 y 3 --- */
  .panel-manif .panel-inner {
    height: 100%;
    padding-top: calc(var(--nav-h) + 4vh);
  }
  .panel-manif .panel-title {
    position: static;
    transform: none;
    top: auto; left: auto;
    text-align: left;
    font-size: clamp(66px, 11.9vw, 100px);   /* ~92px @768 */
    line-height: 1.3;   /* Boldonse (caps ~1.18em) necesita leading o se encima */
  }
  .panel-manif .panel-sub {
    position: static;
    transform: none;
    top: auto; left: auto;
    text-align: left;
    margin-top: clamp(16px, 2vh, 28px);
    font-size: clamp(22px, 3.4vw, 32px);
    line-height: 1.15;
  }
  .panel-manif .panel-art {
    position: absolute;
    right: calc(-1 * var(--gutter));   /* sangra hasta el borde de pantalla */
    bottom: 0;
    top: auto;
    transform: none;
    width: 64%;
  }
  .panel-marcas .panel-art { width: 60%; }

  /* --- Bloque 4 · stats: 3 cards apiladas, cada una horizontal --- */
  .panel-stats { padding: calc(var(--nav-h) + 3vh) 0 5vh; }
  .stats-grid {
    grid-template-columns: 1fr;
    width: min(var(--content-max), 100% - var(--gutter) * 2);
    margin: 0 auto;
    padding-right: 58px;   /* hueco para las viñetas verticales de la derecha */
    gap: clamp(20px, 3vh, 34px);
  }
  .stat-card,
  .stat-card--low {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, auto) 1fr;
    grid-template-areas: "head img desc";
    align-items: center;
    column-gap: clamp(14px, 2.6vw, 30px);
    text-align: left;
    min-height: 0;
    margin-top: 0;
    padding: clamp(22px, 3vw, 38px) clamp(24px, 3.4vw, 42px);
  }
  .stat-head {
    grid-area: head;
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: center;   /* label centrado bajo la cifra */
  }
  .stat-num   { font-size: clamp(54px, 7.8vw, 78px); text-align: center; white-space: nowrap; }
  .stat-label { font-size: clamp(23px, 3.5vw, 34px); margin-top: clamp(4px, 1vw, 8px); text-align: center; white-space: nowrap; }
  .stat-img {
    grid-area: img;
    align-self: center;
    justify-self: center;
    width: clamp(150px, 22vw, 200px);
    margin: 0;
  }
  .stat-desc {
    grid-area: desc;
    align-self: center;
    text-align: left;
    margin-top: 0;
    font-size: clamp(20px, 2.8vw, 26px);
    line-height: 1.22;
  }
  /* imágenes: mismas rotaciones que mobile; se anula el montaje desktop */
  .stat-card .stat-num,
  .stat-card .stat-label,
  .stat-card .stat-img,
  .stat-card .stat-desc { transform: none !important; }
  .panel-stats .stat-card:nth-child(1) .stat-img { transform: rotate(10deg) !important; }
  .panel-stats .stat-card:nth-child(3) .stat-img { transform: scaleX(-1) rotate(-10deg) !important; }
}

/* ============ TABLET (768-1023) · MANIFIESTO PINEADO ============
   Desde el 23-ago-2026 este rango también engancha la sección (antes no tenía
   ninguna rama: el manifiesto pasaba de largo y las viñetas no aparecían
   nunca). El pase es VERTICAL como en desktop —no horizontal como en móvil—
   porque la maqueta de Mafer para tablet es una composición vertical y las
   viñetas van en columna a la derecha; de hecho `.stats-grid` ya reservaba
   sus 58px de hueco desde entonces.

   POR QUÉ HACE FALTA ESTE BLOQUE: al pinear, cada panel queda clavado a UN
   viewport exacto y lo que sobra se corta. En el marco de Mafer (768×1024)
   sobra sitio, pero MEDIDO en pantallas bajas los tres paneles ya se pasan hoy
   —1023×768: +41 los manifiestos y +178 los stats; 768×600: +111 y +176— y
   ahí el recorte se comería media tarjeta.

   La solución es la misma que en móvil: una unidad que vale «1px del diseño a
   768×1024» y encoge cuando falta alto. Cada medida va como
   `min(clamp de ancho, N * unidad)` → manda la más chica, así que en pantallas
   altas gobierna el ancho y todo queda idéntico a hoy, y en las bajas gobierna
   el alto y encoge parejo. Las N son la tinta medida a 768×1024: los dos
   manifiestos ocupan 657 bajo el nav (41 de aire + 475 de titular + 21 + 120
   de subtítulo) y los stats 756 (31 + 674 + 51). */
@media (min-width: 768px) and (max-width: 1023px) {
  .manifiesto.is-pinned {
    /* svh y no dvh: los TAMAÑOS se calculan con el viewport chico, así que
       cuando la barra del navegador aparece y desaparece cambia la caja, nunca
       el texto. Es la misma separación que en la rama de móvil. */
    --hfree: calc(100svh - var(--nav-h));
    --sh2: calc(var(--hfree) / 657);   /* unidad de los paneles 2 y 3 */
    --sh:  calc(var(--hfree) / 756);   /* unidad del panel 4 (stats) */
  }

  /* --- paneles 2 y 3 (calavera / corazón) --- */
  .manifiesto.is-pinned .panel-manif .panel-inner {
    height: 100%;
    min-height: 0;
    padding-top: calc(var(--nav-h) + min(4vh, calc(41 * var(--sh2))));
  }
  .manifiesto.is-pinned .panel-manif .panel-title {
    font-size: min(clamp(66px, 11.9vw, 100px), calc(91.39 * var(--sh2)));
  }
  .manifiesto.is-pinned .panel-manif .panel-sub {
    margin-top: min(clamp(16px, 2vh, 28px), calc(20.48 * var(--sh2)));
    font-size: min(clamp(22px, 3.4vw, 32px), calc(26.11 * var(--sh2)));
  }
  /* El arte va anclado abajo y sangra, así que por abajo nunca se sale: lo que
     pasa en pantallas bajas es que se come el titular. Por eso también encoge
     con el alto. */
  .manifiesto.is-pinned .panel-manif .panel-art {
    width: min(64%, calc(452.19 * var(--sh2)));
  }
  .manifiesto.is-pinned .panel-marcas .panel-art {
    width: min(60%, calc(424.0 * var(--sh2)));
  }

  /* --- panel 4 (stats) --- */
  .manifiesto.is-pinned .panel-stats {
    height: 100%;
    min-height: 0;
    padding: calc(var(--nav-h) + min(3vh, calc(30.72 * var(--sh)))) 0
             min(5vh, calc(51.2 * var(--sh)));
  }
  .manifiesto.is-pinned .stats-grid {
    gap: min(clamp(20px, 3vh, 34px), calc(30.72 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-card,
  .manifiesto.is-pinned .stat-card--low {
    padding: min(clamp(22px, 3vw, 38px), calc(23.04 * var(--sh)))
             min(clamp(24px, 3.4vw, 42px), calc(26.11 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-num {
    font-size: min(clamp(54px, 7.8vw, 78px), calc(59.9 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-label {
    font-size: min(clamp(23px, 3.5vw, 34px), calc(26.88 * var(--sh)));
    margin-top: min(clamp(4px, 1vw, 8px), calc(7.68 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-img {
    width: min(clamp(150px, 22vw, 200px), calc(168.95 * var(--sh)));
  }
  .manifiesto.is-pinned .stat-desc {
    font-size: min(clamp(20px, 2.8vw, 26px), calc(21.5 * var(--sh)));
  }
}

/* ============ BLOQUE 5 · TEAM (marquesinas / carruseles automáticos) ============
   3 filas: palabra Boldonse fija (alternando lado) + tira de fotos en scroll infinito.
   La tira se duplica ×4 y se traslada -25% (= 1 copia) → loop sin costura. */
.team {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(28px, 4.6vw, 74px);
  padding: calc(var(--nav-h) + 2vh) 0;
  overflow: hidden;
}
.team-row {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.6vw, 42px);
  width: 100%;
}
.team-word {
  flex: none;
  font-size: clamp(44px, 4.94vw, 80px);   /* ~80px @1620 */
  line-height: 1;
  color: var(--tinta);
  white-space: nowrap;
}
/* palabra alineada al borde de la caja 1620 */
.team-row--left  .team-word { margin-left:  max(var(--gutter), (100vw - var(--content-max)) / 2); }
.team-row--right .team-word { margin-right: max(var(--gutter), (100vw - var(--content-max)) / 2); }

.team-marquee {
  flex: 1;
  min-width: 0;
  overflow: hidden;            /* la tira sangra al borde de pantalla y se recorta ahí */
}
.team-track {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: team-marquee 22s linear infinite;
}
.team-track--rev { animation-direction: reverse; }   /* fila 2 en sentido opuesto */
.team-track img {
  height: clamp(110px, 10.8vw, 175px);   /* 175px = alto nativo de la tira (sin upscale) */
  width: auto;
  margin-right: clamp(16px, 1.7vw, 28px);/* gap del join ≈ gap interno entre caras */
  display: block;
  flex: none;
}
@keyframes team-marquee { to { transform: translateX(-25%); } }

@media (prefers-reduced-motion: reduce) {
  .team-track { animation: none; }
}

/* reflow de la frase: desktop "HACER / EQUIPO / ES UN INSTINTO";
   mobile+tablet (Mafer) "HACER / EQUIPO ES / UN INSTINTO" */
.team-es { display: none; }

/* ---- TEAM mobile + tablet (≤1023): palabra centrada arriba, marquesina full-bleed debajo ---- */
@media (max-width: 1023px) {
  .team-es      { display: inline; }
  .team-es-desk { display: none; }

  .team-row,
  .team-row--left,
  .team-row--right {
    flex-direction: column;
    align-items: center;
    gap: clamp(10px, 2.2vw, 20px);   /* palabra→marquesina (unidad) */
  }
  .team-row--right { flex-direction: column-reverse; }  /* palabra queda arriba pese al orden del HTML */

  .team-row--left .team-word,
  .team-row--right .team-word {
    margin: 0;
    text-align: center;
    white-space: nowrap;
  }
  .team-marquee { flex: none; width: 100%; }
}

/* tamaños mobile */
@media (max-width: 767px) {
  .team-word { font-size: clamp(38px, 11vw, 52px); }
  .team-track img { height: clamp(140px, 38vw, 168px); }
  .team { gap: clamp(22px, 5vw, 40px); }
}
/* tamaños tablet */
@media (min-width: 768px) and (max-width: 1023px) {
  .team-word { font-size: clamp(80px, 11.3vw, 116px); }
  .team-track img { height: clamp(150px, 22vw, 188px); }
  .team { gap: clamp(28px, 3.6vw, 44px); }
}

/* ============ BLOQUE 6 · ESPÍRITUS (stack de cards + grid morado) ============ */
.espiritus {
  position: relative;
  display: block;            /* anula el grid de .bloque */
  overflow: hidden;
}
.trama {
  position: absolute;
  top: 0;
  height: 100%;
  width: auto;
  z-index: 0;
  pointer-events: none;
  display: block;
}
.trama img { height: 100%; width: auto; display: block; }
.trama--l { left: 0; }
.trama--r { right: 0; }

.espiritus-title {
  position: absolute;
  top: calc(var(--nav-h) + clamp(28px, 3.75vw, 68px));  /* bajado: menos margen con el mazo */
  left: max(var(--gutter), (100vw - var(--content-max)) / 2);
  z-index: 1;              /* rediseño: el título va DETRÁS de la ilustración y las cards */
  color: var(--morado);
}

/* Ilustración 3D (esfera cromada en llamas). Va DELANTE del título y DETRÁS de las
   cards: en el diseño tapa la S final de ESPÍRITUS y las cards la tapan a ella. */
.esp-ilus {
  position: absolute;
  z-index: 2;
  aspect-ratio: 980 / 1010;              /* proporción del asset */
  pointer-events: none;
  user-select: none;
  display: none;                         /* sólo la enciende el @media de 1024 */
}

/* Viewport del carrusel: transparente en desktop/tablet (no altera nada);
   en mobile se vuelve la caja que recorta el mazo dejando 20px a los lados. */
.esp-viewport { display: contents; }

/* Mazo de cards en 3D (posición JS via GSAP scroll/dots) */
.esp-stack {
  position: absolute;
  left: 50%;
  top: 60%;
  transform: translate(-50%, -50%);
  width: min(74%, 516px);
  aspect-ratio: 516 / 474;        /* caja de Mafer (rediseño 11-ago) */
  z-index: 3;
  touch-action: pan-y;            /* swipe horizontal → JS; vertical → scroll de página */
}
/* Las cards NO son negras opacas: son negro al 91%. Medido en tres puntos del
   diseño — sobre el fondo dan [2,2,2], sobre el título morado [9,5,15] (= #6539A7
   al 8.9%) y sobre la esfera [6,5,7]. Por eso se transparentan las llamas. */
.esp-card {
  position: absolute;
  inset: 0;
  border-radius: clamp(16px, 1.5vw, 30px);
  overflow: hidden;
  background: rgba(0, 0, 0, .91);
  will-change: transform, opacity;
  backface-visibility: hidden;
}
/* Logo vectorial centrado. --lw = ancho en px de diseño (ya normalizado a card
   central en el HTML). El velo de las vecinas se aplica al LOGO, no a la card:
   así lo hizo Mafer (los SVG laterales venían con opacity .5 horneada).
   El ancho va en % DE LA CARD, no en --u (12-ago): --lw está medido contra la
   card de 516 del desktop, pero en tablet la card es 420 y en mobile 280, así
   que con --u el logo salía al 90% y al 135% de su card y se desbordaba. En
   porcentaje ocupa la misma fracción en los tres tamaños y el desktop no se
   entera (378/516 = 73.256% de 516u = 378u, idéntico a antes). */
.esp-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: calc(var(--lw) / 516 * 100%);
  max-height: 62%;
  object-fit: contain;
  height: auto;
  display: block;
  opacity: calc(1 - var(--dim, 0) * .5);
  /* SIN transition, a propósito. `--dim` no da saltos: lo escribe render() en
     cada cuadro, tanto al arrastrar como en el enganche, así que el degradado
     ya viene interpolado. Con una transition encima, cada escritura REINICIA
     una animación de 450ms sobre los 9 logos y el velo va siempre por detrás
     del dedo — que es justo el retraso que se notaba al deslizar. */
}

/* Viñetas verticales a la derecha (clickeables) */
.esp-dots {
  position: absolute;
  right: max(var(--gutter), (100vw - var(--content-max)) / 2);
  top: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* MISMA SEPARACIÓN que las viñetas del manifiesto (pedido de Jonathan, 12-ago):
     este clamp y el de ≤767 están copiados tal cual de .dots-nav. Iban en
     22 * --u en los tres breakpoints, que daba otro número en cada uno. */
  gap: clamp(18px, 1.6vw, 26px);
}
/* MISMO TAMAÑO que las viñetas del manifiesto (.dots-nav .dot), pedido de
   Jonathan el 12-ago: los dos clamps y la escala del activo son literalmente los
   de allá. Antes iban en 15 * --u, que da otro número en cada breakpoint —a 768
   eran 15px contra 10, y a 1024 eran 8.7 contra 10—. La activa queda un punto
   por encima: 1.42 (unos 14→20px), como en el manifiesto. */
.esp-dot {
  width: clamp(10px, 0.864vw, 14px);
  height: clamp(10px, 0.864vw, 14px);
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--blanco);
  opacity: .5;
  cursor: pointer;
  transition: background .3s ease, opacity .3s ease, transform .3s ease;
}
.esp-dot.is-active {
  background: var(--coral);
  opacity: 1;
  transform: scale(1.42);
}
/* El mobile del manifiesto usa su propio clamp; las de espíritus lo copian. */
@media (max-width: 767px) {
  .esp-dot {
    width: clamp(11px, 2.97vw, 13.5px);
    height: clamp(11px, 2.97vw, 13.5px);
  }
  .esp-dots { gap: clamp(14px, 4vw, 22px); }
}

/* ---- Espíritus MOBILE (≤767): carrusel eje X, card portrait, viñetas horizontales abajo ----
   MISMA PREMISA QUE DESKTOP, sobre el marco mobile de Mafer: 390×844 con banda de
   nav de 84 arriba (→ 760 útiles). Antes el título iba en 15vw y el mazo en un 62%
   del alto: ninguna de las dos miraba a la otra, así que en pantallas cortas se
   juntaban. Ahora las dos cuelgan de la misma escala --u y el aire entre ellas es
   una fracción fija del marco: no se pueden pisar nunca.
   Medidas del PDF mobile de Figma a 1:1:
     título  Boldonse 55, centrado, cap top y=149
     card    268×470 en (61, 263) — centrada; el asset es 402×705 (=1.5×)
     viñetas Ø15 (activa Ø20), paso 37, fila centrada en y=782.5
     recorte del carrusel: 22 de margen a cada lado (346 de ancho útil) */
@media (max-width: 767px) {
  /* MOBILE del rediseño: Mafer NO entregó marco mobile, así que la composición es
     nuestra, derivada del desktop. Marco de trabajo 390×844 con nav de 84.
     Contenido de y=150 (cap del título) a y=630 (pie de las viñetas) = 480.
     El paso del carrusel BAJA a 85%: con el 103.78% del diseño, una card de 310
     sobre 390 de ancho deja a las vecinas fuera de la pantalla y el coverflow se
     convierte en una card suelta. */
  .espiritus {
    --u-w: calc(100vw / 390);
    --esp-aire: clamp(22px, 4.5svh, 44px);   /* ver nota del bloque >=1024 */
    --u-h: calc((100svh - var(--nav-h) - var(--esp-aire)) / 480);
    /* Tope de 1.25: el contenido nuevo es más corto (480 contra los 760 del mazo
       viejo), así que --u-h deja de ser el freno y en el borde del breakpoint
       (767px) el bloque se dibujaba al 197%. Mismo recurso que el footer. */
    --u:   min(var(--u-w), var(--u-h), 1.25px);
    --esp-libre: calc(100svh - var(--nav-h) - 480 * var(--u));
    --frame-top: calc(var(--nav-h) - 150 * var(--u)
                      + min(calc(var(--esp-libre) / 2),
                            max(0px, calc(var(--esp-libre) - var(--esp-aire)))));
  }
  /* 157.6 = 150 (cap top) − el offset de cap de Boldonse con lh 0.9677 (−0.1462em):
     con el interlineado más corto que el cuerpo, el offset es NEGATIVO y se suma. */
  .espiritus-title {
    top: calc(var(--frame-top) + 157.6 * var(--u));
    left: 50%;
    transform: translateX(-50%);          /* centrado en X (12-ago) */
    text-align: center;
    font-size: calc(52 * var(--u));
    line-height: calc(150 / 155);
    letter-spacing: .01em;
  }
  .esp-viewport { display: contents; }
  /* Card 310 → 280 (12-ago, criterio de Jonathan: se veían grandes). El top sube
     de 260 a 274 para que el CENTRO del mazo no se mueva (402.4u antes y ahora):
     así encoge sin descolocar el aire con el título ni con las viñetas. */
  .esp-stack {
    --step-pct: 85;
    position: absolute;
    left: 50%;
    top: calc(var(--frame-top) + 274 * var(--u));
    margin-left: calc(-140 * var(--u));
    transform: none;
    width: calc(280 * var(--u));
  }
  .esp-card { border-radius: calc(18 * var(--u)); }
  /* 9 viñetas con paso 37 miden 316 de ancho: a 390 entran con 37 de aire a cada
     lado, y por debajo encogen con --u. */
  .esp-dots {
    right: auto;
    left: 50%;
    top: calc(var(--frame-top) + 600 * var(--u));
    bottom: auto;
    transform: translate(-50%, -50%);
    flex-direction: row;
    justify-content: center;
  }
  .trama { width: clamp(44px, 16vw, 74px); height: auto; top: 50%; transform: translateY(-50%); }
  .trama img { width: 100%; height: auto; }
}

/* ---- Espíritus TABLET (768–1023): carrusel eje X, card apaisada, viñetas verticales derecha ----
   Marco tablet de Mafer: 768×1024 con banda de nav de 140 (→ 884 útiles).
   Acá estaba el choque que reportó Jonathan: el título iba en 12vw (92px a 768,
   30% más grande que el diseño) y el mazo colgaba del 55% del alto. En una ventana
   apaisada —p. ej. 900×600, que es un navegador de escritorio angostado por debajo
   de 1024— el mazo subía hasta y=77 y el título le quedaba encima. Con --u los dos
   encogen juntos y el aire entre ellos nunca puede volverse negativo.
   Medidas del PDF tablet de Figma a 1:1:
     título  Boldonse 71, centrado, cap top y=197
     card    600×550 en (84, 390) — centrada; el asset es 900×825 (=1.5×)
     viñetas Ø15 (activa Ø20), paso 37, columna en x=708, grupo centrado en y=545 */
@media (min-width: 768px) and (max-width: 1023px) {
  /* TABLET del rediseño: tampoco hay marco de Mafer. Marco de trabajo 768×1024 con
     nav de 140. Contenido de y=210 (cap del título) a y=810 (pie de viñetas) = 600.
     Acá SÍ cabe el paso del diseño (103.78%): con la card en 420 las vecinas
     asoman ~135px, que es la misma lectura del desktop.
     Las viñetas pasan de la columna derecha a la FILA de abajo, como el rediseño. */
  .espiritus {
    --u-w: calc(100vw / 768);
    --esp-aire: clamp(26px, 5svh, 56px);     /* ver nota del bloque >=1024 */
    --u-h: calc((100svh - var(--nav-h) - var(--esp-aire)) / 600);
    --u:   min(var(--u-w), var(--u-h));
    --esp-libre: calc(100svh - var(--nav-h) - 600 * var(--u));
    --frame-top: calc(var(--nav-h) - 210 * var(--u)
                      + min(calc(var(--esp-libre) / 2),
                            max(0px, calc(var(--esp-libre) - var(--esp-aire)))));
  }
  /* 219.9 = 210 (cap top) + 9.9 (offset de cap de Boldonse con lh 0.9677, negativo). */
  .espiritus-title {
    top: calc(var(--frame-top) + 219.9 * var(--u));
    left: 50%;
    transform: translateX(-50%);          /* centrado en X (12-ago) */
    text-align: center;
    font-size: calc(68 * var(--u));
    line-height: calc(150 / 155);
    letter-spacing: .01em;
  }
  .esp-stack {
    --step-pct: 103.78;
    top: calc(var(--frame-top) + 330 * var(--u));
    left: 50%;
    margin-left: calc(-210 * var(--u));
    transform: none;
    width: calc(420 * var(--u));
  }
  .esp-card { border-radius: calc(24 * var(--u)); }
  .esp-dots {
    top: calc(var(--frame-top) + 800 * var(--u));
    bottom: auto;
    right: auto;
    left: 50%;
    flex-direction: row;
    transform: translate(-50%, -50%);
  }
}

/* ============ DESKTOP ≥1024 · ESPÍRITUS A ESCALA ÚNICA ============
   Misma premisa que el hero y el manifiesto: el bloque de Mafer es una caja de
   1620×1080 con una banda de nav de 150 arriba (→ 930 útiles). Título, mazo y
   viñetas se expresan en unidades de ESE diseño y se multiplican por una sola
   escala --u = min(lo que da el ancho, lo que da el alto).
   Antes cada pieza se clampeaba por su cuenta y ninguna miraba el alto: el mazo
   quedaba fijo en 1200px de ancho, así que en pantallas bajas se comía el título
   y se salía por abajo. Con --u encoge todo junto y nunca desborda.
   Medidas tomadas del PDF de Figma a 1:1 (ver reference_chaman_design_specs):
     título   caja x=360 (= borde izq. de la card), cap top y=186, Boldonse 81
     mazo     1200×550 en (360, 408) — centrado en el marco
     viñetas  Ø15 (activa Ø20), paso 37 centro a centro, grupo centrado en y=540,
              centro de columna en x=1759
   Las tramas laterales NO entran acá: son textura a sangre, siguen a 100% de alto. */
@media (min-width: 1024px) {
  .espiritus {
    --u-w: calc(min(var(--content-max), 100vw - var(--gutter) * 2) / 1620);
    /* 739 = extento de la TINTA del contenido: cap top del título (246) al borde
       inferior de las viñetas (985). El aire de Mafer es 96 arriba / 95 abajo,
       o sea simétrico, así que el sobrante se reparte por igual. */
    --u-h: calc((100svh - var(--nav-h) - var(--esp-aire)) / 739);
    --u:   min(var(--u-w), var(--u-h));
    --esp-libre: calc(100svh - var(--nav-h) - 739 * var(--u));
  /* AIRE MÍNIMO BAJO LAS VIÑETAS (3-sep-2026, pedido de Manuel: «los bullets se
     ven muy abajo»). El marco centra la tinta con el sobrante repartido a partes
     iguales, así que cuando manda --u-h (ventana ANCHA y BAJA) el sobrante es
     CERO y el pie de las viñetas queda pegado al borde del bloque, besando el
     coral de Conjuros. Medido: a 1440x720 quedaban 1,3 px de aire; a 1440x900,
     75. El umbral es --u-h < --u-w, o sea alto < 0,549*ancho - 36 entre 1024 y
     1700 de ancho, y alto < 889 por encima de 1700: casi cualquier portátil.
     Arreglo en dos piezas, para NO tocar lo que ya se veía bien:
       (1) --u-h reserva --esp-aire, así que en el caso alto-limitado la
           composición encoge lo justo y deja ese aire;
       (2) --frame-top deja de repartir a ciegas: da al pie --esp-aire y el resto
           arriba, y sólo vuelve al reparto simétrico cuando sobra de verdad
           (>= 2*--esp-aire), que es el caso ancho-limitado de siempre. */
    --esp-aire: clamp(32px, 6svh, 72px);
    --frame-top: calc(var(--nav-h) - 246 * var(--u)
                      + min(calc(var(--esp-libre) / 2),
                            max(0px, calc(var(--esp-libre) - var(--esp-aire)))));
  }

  /* Título Boldonse 155 / lh 150 / ls 1% (Figma). OJO: el interlineado es MENOR
     que el cuerpo, así que el cap se sale por arriba de su caja de línea — el
     offset da −22.66 (= (0.9677−1.92)/2 + 0.33 em) y por eso se SUMA al cap top
     de 246 en vez de restarse. 655.3 = 960 − 304.7, y 304.7 es el borde de la
     caja: la tinta arranca en 314 menos el lsb de la E (0.06em = 9.3px). */
  .espiritus-title {
    top: calc(var(--frame-top) + 268.66 * var(--u));
    left: 50%;
    margin-left: calc(-655.3 * var(--u));
    transform: none;
    font-size: calc(155 * var(--u));
    line-height: calc(150 / 155);
    letter-spacing: .01em;
  }

  /* Ilustración: 480 de ancho en (1145, 140). Los valores salen de correlacionar
     la máscara del render contra la del PDF en la banda y150-392 (la única franja
     donde la esfera se ve limpia, sin cards ni nav encima). */
  .esp-ilus {
    display: block;
    background: url('../img/ch-esp-ilustracion.webp') center / contain no-repeat;
    top: calc(var(--frame-top) + 140 * var(--u));
    left: calc(50% + 185 * var(--u));
    width: calc(480 * var(--u));
  }

  /* Coverflow: card central 516×474 en (702, 395), centrada en x=960. */
  .esp-stack {
    --step-pct: 103.78;          /* 535.5 de paso ÷ 516 de card (lo lee nav.js) */
    top: calc(var(--frame-top) + 395 * var(--u));
    left: 50%;
    margin-left: calc(-258 * var(--u));
    transform: none;
    width: calc(516 * var(--u));
  }
  .esp-card { border-radius: calc(30 * var(--u)); }

  /* Viñetas: rediseño → fila HORIZONTAL centrada abajo (antes columna a la
     derecha). Centro del grupo en x=960, centro de los puntos en y=975.5. */
  .esp-dots {
    top: calc(var(--frame-top) + 975.5 * var(--u));
    bottom: auto;
    left: 50%;
    right: auto;
    flex-direction: row;
    transform: translate(-50%, -50%);
  }

  /* Tramas: siguen sangrando de arriba a abajo, pero su ANCHO ya no cuelga del
     alto del viewport sino de --u (el asset mide 425×1080 = justo lo que ocupa
     en el Figma). Antes, en ventanas altas y angostas (p. ej. 1024×1366) las dos
     tramas crecían hasta juntarse y se comían la composición.
     El sobrante se recorta por el lado INTERIOR, que es donde la grilla ya está
     desvanecida, así que el recorte no se nota. */
  .espiritus .trama { width: calc(425 * var(--u)); }
  .espiritus .trama img { width: 100%; height: 100%; object-fit: cover; }
  .espiritus .trama--l img { object-position: left center; }
  .espiritus .trama--r img { object-position: right center; }
}

/* ============ BLOQUE 7 · CONJUROS (grid de servicios) ============
   3 arriba + 2 abajo centrados. Ícono recto (sin ángulo) montado ~30px sobre
   el título (incluida Branding, que en el diseño se le escapó). */
.conjuros {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(var(--nav-h) + 3vh) 0 5vh;
}
.conjuros-grid {
  width: min(var(--content-max), 100% - var(--gutter) * 2);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3.4vw, 55px);           /* separación entre filas */
}
/* Anchos EXACTOS de Figma, relativos a la caja de contenido (1620).
   Fila superior: 447 + 507 + 335 = 1289; los 2 huecos de space-between
   dan (1620-1289)/2 ≈ 165px ≈ los ~164px pedidos.
   Fila inferior: 448 + 448 centrados con hueco 282px (=17.41% de 1620). */
.conj-row--3 {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}
.conj-row--3 .conj:nth-child(1) { width: 27.59%; }  /* 447px */
.conj-row--3 .conj:nth-child(2) { width: 31.30%; }  /* 507px */
.conj-row--3 .conj:nth-child(3) { width: 20.68%; }  /* 335px */
.conj-row--2 {
  display: flex;
  justify-content: center;
  gap: 17.41%;                              /* ~282px @1620 */
}
.conj-row--2 .conj { width: 27.65%; }       /* 448px */
.conj {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.conj-icon {
  height: clamp(130px, 12.3vw, 200px);
  width: auto;
  position: relative;
  z-index: 2;                              /* ícono sobre el título (montaje) */
  pointer-events: none;
  user-select: none;
}
/* Diseño Gráfico: Mafer rotó el ícono en Figma → va al espejo */
.conj-row--3 .conj:nth-child(3) .conj-icon { transform: scaleX(-1); }
.conj-title {
  font-size: clamp(30px, 2.78vw, 45px);    /* 45px @1620 (Figma) */
  line-height: 1.556;                       /* 70/45 (Figma) */
  letter-spacing: .01em;
  color: var(--tinta);
  margin-top: clamp(-16px, -0.925vw, -9px);/* montaje ~50% (antes muy montado) */
  position: relative;
  z-index: 1;
}
.conj-desc {
  /* Derivado del PDF (es el único sin captura de Figma): el cap de la B da 20.0px
     exacto y tres líneas de distinto largo concuerdan en ls ≈1%, con paso 20. */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: clamp(14px, 1.235vw, 20px);   /* 20px @1620 */
  line-height: 1;
  letter-spacing: .01em;
  text-transform: none;
  color: var(--tinta);
  margin-top: clamp(16px, 1.67vw, 27px);   /* gap título→desc */
  width: 100%;                              /* envuelve dentro de la caja exacta de Figma */
}

/* ---- CONJUROS · MOBILE (≤767): los 5 items en una sola columna ----
   Márgenes de bloque de Figma: sup 120 / inf 100 / laterales 32; gap 40.
   Título Boldonse 35/58 (1.657); desc Bebas 20/100%. Se mantiene el
   montaje del ícono sobre su título (estilo de Mafer). */
@media (max-width: 767px) {
  .conjuros {
    justify-content: flex-start;
    min-height: 0;                          /* alto = contenido + márgenes (no 100svh) */
    padding: 120px 32px 100px;              /* Figma: sup 120 / inf 100 / lat 32 */
  }
  .conjuros-grid {
    width: 100%;
    gap: 40px;
  }
  .conj-row { display: contents; }         /* aplana ambas filas a la columna */
  .conjuros-grid .conj { width: 100% !important; }
  .conj-icon {
    height: clamp(150px, 46vw, 190px);
  }
  .conj-title {
    font-size: clamp(29px, 8.97vw, 38px);  /* 35px @390 */
    line-height: 1.657;                     /* 58/35 (Figma) */
    margin-top: clamp(-20px, -4.9vw, -12px);/* montaje ícono→título (solapado -10px) */
  }
  .conj-desc {
    font-size: clamp(18px, 5.13vw, 22px);  /* 20px @390 */
    line-height: 1.05;                      /* ~100% Figma */
    margin-top: clamp(8px, 2.6vw, 12px);
  }
}

/* ---- CONJUROS · TABLET (768–1023): igual que mobile, 5 items en una columna
   centrada, pero a escala 768. Medido del viewport-tablet.pdf: título Boldonse
   ~66px, desc Bebas ~28px, íconos ~165px, pitch ~355 (gap ~80). ---- */
@media (min-width: 768px) and (max-width: 1023px) {
  .conjuros {
    justify-content: flex-start;
    min-height: 0;
    padding: 200px 44px 124px;              /* Figma tablet: ícono en y=200, cierre a 124 del borde */
  }
  .conjuros-grid {
    width: 100%;
    gap: 80px;                              /* separación entre ítems */
  }
  .conj-row { display: contents; }          /* aplana las 2 filas a la columna */
  .conjuros-grid .conj { width: 100% !important; }
  .conj-icon {
    height: clamp(150px, 21vw, 185px);      /* ~165px @768 */
  }
  .conj-title {
    font-size: clamp(36px, 5.47vw, 46px);   /* 42px @768 (Figma) */
    line-height: 1.667;                       /* 70/42 (Figma) */
    letter-spacing: .01em;                    /* 1% (Figma) */
    margin-top: clamp(-22px, -2.3vw, -13px); /* montaje ícono→título */
  }
  /* En tablet los títulos van en 1 sola línea (Figma): se anula el <br>
     que desktop/mobile usan para partir en 2. El espacio antes del <br>
     en el HTML preserva la separación entre palabras. */
  .conj-title br { display: none; }
  .conj-desc {
    font-size: clamp(22px, 3.26vw, 28px);   /* 25px @768 (Figma; medido por ancho de cadena) */
    line-height: 1;                          /* 100% Figma (paso medido = 25px exactos) */
    margin-top: clamp(10px, 1.6vw, 16px);
    /* La caja crece con la MISMA proporción que la fuente (69vw = 530 @768),
       si no, pasado 768 el texto deja de caber en 2 renglones. */
    max-width: min(600px, 69vw);
    margin-left: auto;
    margin-right: auto;
  }
}

/* ============ DESKTOP ≥1024 · CONJUROS A ESCALA ÚNICA ============
   Misma premisa que el hero, el manifiesto y espíritus: el bloque de Mafer es
   una caja de 1620×1080 con banda de nav de 150 arriba, y TODO se expresa en
   unidades de ese diseño multiplicadas por una sola escala
   --u = min(lo que da el ancho, lo que da el alto).

   Qué estaba roto (medido en 13 resoluciones sobre el sitio actual):
   (a) el bloque NO cabía en una pantalla en casi ningún tamaño <1920 —
       desbordaba +199 en 1366×700, +159 en 1600×900, +136 en 1366×768,
       +150 en 1024×600— porque cada pieza se clampeaba por su cuenta contra
       el ANCHO y nadie miraba el alto, mientras .bloque promete 100svh;
   (b) las descripciones se partían en 3 líneas en vez de 2 desde 1366 hacia
       abajo: la fuente bajaba por clamp/vw (con piso de 17px) pero la caja
       bajaba por porcentaje de la caja de contenido, así que dejaban de
       encoger juntas y el texto ya no entraba en 2 renglones.
   Con --u la fuente y su caja son la MISMA fracción del diseño, así que el
   corte de línea de Mafer se conserva a cualquier tamaño y el alto total del
   bloque nunca supera la pantalla.

   Divisor de alto = 791.75 = lo que MIDE el contenido (borde superior del
   ícono de la fila 1 → borde inferior de la caja de texto de la fila 2), no
   los 930 útiles del marco. Así el aire que Mafer dejó (18 arriba / 120.25
   abajo) se consume ANTES de encoger el diseño, y el sobrante se reparte
   luego en esa misma proporción (13.02% / 86.98%). Resultado: a 1920×1080
   sale calcado del Figma, y en pantallas más chicas el ancho manda casi
   siempre —la tipografía queda todo lo grande que el diseño permite— sin
   perder nunca la garantía de que entra.

   Medidas del PDF de Figma a 1:1 (bloque y 6480..7559 de home.png):
     fila 1  ítems 447 / 507 / 335 en space-between sobre 1620; ícono alto 200,
             top y=168; título Boldonse 45 / lh 70 / ls 0, cap top y=366;
             desc Safiro 20 / lh 20.5 / ls .01em, cap top y=519 (3 líneas)
     fila 2  ítems 448 + 448, hueco 283.5, centrados; ícono alto 200, top y=638;
             título Boldonse 50 (¡más grande que la fila 1!) cap top y=830;
             desc cap top y=912 (3 líneas)
   El rediseño de ago-2026 bajó el desc de 25 a 20px: con 25 de Safiro los
   párrafos se iban a 4 líneas y el contenido medía 866.75 contra los 791.75
   declarados → se derramaba y lo cortaba el bloque siguiente en toda altura
   menor a 1080. Alto real del contenido nuevo: 802.53 (se declara 806 para
   dejar holgura al descendente de la última línea).
   Los desplazamientos negativos del título son el "montaje" del ícono sobre
   la palabra, y salen de restar la posición de la caja de línea a la del cap
   (offset de cap de Boldonse: 0.1478em a lh 1.5556 y 0.07em a lh 1.4). */
@media (min-width: 1024px) {
  .conjuros {
    display: block;
    padding: 0;
    --u-w: calc(min(var(--content-max), 100vw - var(--gutter) * 2) / 1620);
    /* El divisor es el MARCO COMPLETO bajo el nav (930 = 1080 - 150), no sólo el
       contenido (806): así los márgenes de Mafer —18 arriba, 106 abajo— escalan
       con el bloque en vez de quedar como residuo. Cuando manda el alto, la
       sobra vale 930u - 806u = 124u y el reparto 0.1452 devuelve los 18u de
       arriba exactos. */
    --u-h: calc((100svh - var(--nav-h)) / 930);
    --u:   min(var(--u-w), var(--u-h));
    --grid-top: calc(var(--nav-h)
                     + (100svh - var(--nav-h) - 806 * var(--u)) * 0.1452);
  }
  .conjuros-grid {
    position: absolute;
    top: var(--grid-top);
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
    width: calc(1620 * var(--u));
    gap: calc(60.5 * var(--u));             /* fila 1 → ícono de la fila 2 en y=638 */
  }
  .conj-row--3 .conj:nth-child(1) { width: calc(447 * var(--u)); }
  .conj-row--3 .conj:nth-child(2) { width: calc(507 * var(--u)); }
  .conj-row--3 .conj:nth-child(3) { width: calc(335 * var(--u)); }
  .conj-row--2      { gap: calc(283.5 * var(--u)); }
  .conj-row--2 .conj { width: calc(448 * var(--u)); }

  .conj-icon { height: calc(200 * var(--u)); }

  .conj-title {
    font-size: calc(45 * var(--u));
    line-height: 1.5556;                    /* 70/45 (Figma) */
    letter-spacing: 0;                      /* Figma: 0, no 1% */
    margin-top: calc(-8.65 * var(--u));     /* montaje ícono→título */
  }
  .conj-desc {
    font-size: calc(20 * var(--u));         /* rediseño: 25 → 20 (paso medido = 20.5px) */
    line-height: 1.025;
    margin-top: calc(16.7 * var(--u));
  }
  /* La fila de abajo lleva el título más grande en el diseño (cap 59 vs 54). */
  .conj-row--2 .conj-title {
    font-size: calc(50 * var(--u));
    line-height: 1.4;                       /* 70/50 → misma caja de línea */
    margin-top: calc(-11.5 * var(--u));
  }
  .conj-row--2 .conj-desc { margin-top: calc(12.5 * var(--u)); }
}

/* ============ BLOQUE 8 · CONTACTO (blanco) ============
   Título morado arriba-izq (Boldonse 80/115) + lead (Bebas 35/40) debajo.
   Formulario en pastillas a la derecha. Dos manos 3D: cursor (contacto-2)
   flota desde arriba apuntando abajo; mano humana (contacto-1) anclada al
   borde inferior apuntando arriba. Casi se tocan los dedos (a la altura de
   la última O de conocernOs). */
.contacto {
  display: block;                          /* anula el grid centrado de .bloque */
  overflow: hidden;                        /* recorta el brazo que sangra bajo el borde inferior */
}
.contacto-inner {
  position: relative;
  width: min(var(--content-max), 100% - var(--gutter) * 2);
  margin: 0 auto;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 809px) min(654px, 46vw);  /* form 654px (Figma) */
  justify-content: space-between;
  align-content: center;
  gap: clamp(24px, 3vw, 60px);
  padding: calc(var(--nav-h) + 3.5vh) 0 0;
}
/* Orden de capas (atrás→adelante): título · manos · párrafo · formulario */
.contacto-head { grid-column: 1; align-self: center; }
.contacto-title {
  position: relative;
  z-index: 1;                               /* detrás de las manos */
  font-size: var(--fs-cont);               /* 80px @1620 */
  line-height: 1.4375;                      /* 115/80 (Figma) */
  letter-spacing: 0;
  color: var(--morado);
}
.contacto-lead {
  position: relative;
  z-index: 4;                               /* por encima de las manos */
  /* Figma (rediseño): Safiro Medium 36 / lh 49 / ls 1%, CAJA BAJA, caja 539 → 2 líneas. */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: clamp(20px, 2.222vw, 36px);   /* 36px @1620 */
  line-height: calc(49 / 36);
  letter-spacing: .01em;
  text-transform: none;
  color: var(--tinta);
  max-width: 575px;                         /* Figma 539; +36 porque nuestro texto
                                                lleva el "de" que el PDF omitió */
  margin-top: clamp(20px, 2.3vw, 38px);
}

/* Formulario en pastillas */
.contacto-form {
  grid-column: 2;
  align-self: center;
  position: relative;
  z-index: 5;                               /* la capa de más adelante */
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.7vw, 28px);
}
.cf-field { display: block; }
.cf-input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--tinta);          /* Figma: 1px, no 1.5 */
  border-radius: 999px;
  background: #fff;                          /* relleno blanco: tapa las manos que pasan por detrás */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: clamp(15px, 1.48vw, 24px);    /* 24px @1620 (Figma) */
  letter-spacing: 0;
  text-transform: uppercase;               /* los placeholders SÍ siguen en caja alta */
  color: var(--tinta);
  /* Se conserva el lh holgado: la Ú de "NÚMERO" es el glifo más alto y con
     line-height normal el <input> le recortaba la tilde. */
  line-height: 1.3;
  padding: clamp(17px, 1.65vw, 27px) clamp(24px, 2vw, 34px);
  outline: none;
  transition: border-color .2s ease;
}
.cf-input::placeholder { color: var(--tinta); opacity: 1; }
.cf-input:focus { border-color: var(--morado); }
.cf-input.is-invalid { border-color: var(--coral); }
.cf-textarea {
  border-radius: clamp(26px, 2.4vw, 40px);
  resize: vertical;
  min-height: clamp(96px, 9vw, 150px);
  line-height: 1.15;
}
.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
/* Oculto a la vista, presente para lectores de pantalla y control por voz.
   No se usa display:none ni visibility:hidden porque ésos SÍ lo esconden
   también de la accesibilidad, que es justo lo contrario de lo que se busca. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.cf-submit {
  align-self: flex-start;
  margin-top: clamp(4px, 0.6vw, 10px);
  border: none;
  border-radius: 999px;
  background: var(--tinta);
  color: #fff;
  /* Figma: Safiro Medium 24 / ls 0 / uppercase, en caja de 140×60. Va con
     width/height en vez de padding porque la caja del botón es un dato del
     diseño, no una consecuencia del texto. */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: clamp(15px, 1.48vw, 24px);    /* 24px @1620 */
  letter-spacing: 0;
  text-transform: uppercase;
  width: clamp(104px, 8.64vw, 140px);
  height: clamp(46px, 3.70vw, 60px);
  padding: 0;
  cursor: pointer;
  transition: opacity .2s ease;
}
.cf-submit:hover { opacity: .88; }
.cf-submit[disabled] { opacity: .5; cursor: default; }
.cf-status {
  min-height: 1.2em;
  margin: 0;
  font-family: var(--font-nav);
  font-size: clamp(15px, 1.2vw, 19px);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--morado);
}
.cf-status.is-error { color: var(--coral); }

/* Manos 3D — ancladas al CENTRO VERTICAL (que sigue al título centrado) para
   que las puntas de los dedos se junten a cualquier altura de viewport.
   Cursor: su punta (dedo abajo) está en el borde inferior de su imagen →
   se ancla por `bottom`. Mano humana: su punta (dedo arriba) está en el borde
   superior de su imagen → se ancla por `top`, y el brazo extra sangra hacia
   abajo (clip por overflow:hidden del bloque). El punto de encuentro cae a la
   altura de la última O de CONOCERNOS (~57px bajo el centro del bloque). */
.contacto-hand {
  position: absolute;
  width: auto;
  pointer-events: none;
  user-select: none;
}
.contacto-hand--cursor {              /* cursor pixelado, apunta abajo, flota */
  bottom: calc(50% - 62px);           /* bajadas 20px (antes -42px) */
  left: 30%;
  height: min(464px, 46vh);           /* 464px Figma (antes 556) */
  z-index: 2;
}
.contacto-hand--human {               /* mano humana, apunta arriba, brazo sangra abajo */
  top: calc(50% + 62px);              /* bajadas 20px (antes +42px) */
  left: 41%;
  height: min(730px, 72vh);           /* misma proporción de reducción (464×1.573) */
  transform: scale(0.9);              /* −10% con pivote en la base → la punta baja y gana */
  transform-origin: center bottom;    /* separación con el dedo del puntero */
  z-index: 3;
}

/* ---- CONTACTO · MOBILE (≤767) ----
   El marco mobile de Mafer para este bloque mide 390×1038: NO cabe en una
   pantalla, es un bloque que SCROLLEA por diseño. Por eso acá --u no lleva
   término de alto: es solo proporción de ancho sobre 390, con tope 1.15 para
   que en pantallas grandes de teléfono no siga creciendo sin fin.

   Estaba bastante más comprimido que el diseño: las pastillas medían 52 de
   alto contra 70, el hueco entre ellas 9 contra 13, y las manos —más grandes
   de lo que Mafer las puso y más a la izquierda— se montaban sobre el lead
   "Déjanos tus datos…" (el punto 7 del feedback del 25-jul). Con la geometría
   del marco las manos caen sobre el título, que es donde Mafer las quiso, y
   el lead queda limpio.

   Medidas del PDF mobile a 1:1 (bloque = y 7153..8190 de mob.png):
     título Boldonse 35 / lh 50, caja x=25, caps en y=128/178/228
     lead   Bebas 20 / lh 25, 3 líneas, cap top y=304
     form   x=25 ancho 341; pills 70 con hueco 13 (tops 400/482/564);
            textarea 228 en y=646; botón 140×50 en y=886;
            placeholders Bebas 20 a 32 del borde; ENVIAR Bebas 32
     manos  AL ESPEJO (verificado por correlación contra el cursor del
            desktop: 0.94 espejado vs 0.14 sin espejar): cursor alto 168 con
            su caja en y=71..238 / x=262..378; mano humana debajo, tapada por
            la primera pastilla a partir de y=400 */
@media (max-width: 767px) {
  .contacto { --u: min(calc(100vw / 390), 1.15px); }   /* --u es una LONGITUD (px), como en el resto del sitio */
  .contacto-inner {
    display: block;
    position: relative;
    min-height: 0;
    width: 100%;
    padding: calc(125 * var(--u)) calc(25 * var(--u)) calc(103 * var(--u));
  }
  .contacto-head {
    align-self: auto;
    position: static;
    min-height: 0;
  }
  .contacto-title {
    font-size: calc(35 * var(--u));
    line-height: 1.4286;                       /* 50/35 (Figma) */
    z-index: 1;
  }
  /* 12-ago: a 3 líneas el texto cruzaba la mano y se volvía ilegible (negro sobre
     negro). Pasa a 4 líneas —«Déjanos tus datos / y hablemos de lo / que podemos /
     hacer juntos.»— con la caja en 175 y el cuerpo en 19. El 21 no daba: con la
     mano ya alineada, cualquier caja que cortara en 4 dejaba el renglón más largo
     11u encima de los dedos. Medido contra la silueta real, renglón por renglón:
     ahora el más largo libra por 6u. */
  .contacto-lead {
    font-size: calc(19 * var(--u));
    line-height: calc(49 / 36);                /* proporción del rediseño */
    /* 25.5 = 300.5 (caja del lead) − 275 (fin de las 3 líneas del título) */
    margin-top: calc(25.5 * var(--u));
    max-width: calc(175 * var(--u));
    z-index: 4;
  }
  .contacto-form {
    margin-top: calc(24.5 * var(--u));
    gap: calc(13 * var(--u));
    z-index: 5;                                /* las pills tapan la mano */
  }
  .cf-input {
    display: block;
    height: calc(70 * var(--u));
    padding: 0 calc(32 * var(--u));
    font-size: calc(19 * var(--u));
    letter-spacing: 0;
  }
  .cf-textarea {
    height: calc(228 * var(--u));
    min-height: 0;
    padding: calc(20 * var(--u)) calc(32 * var(--u));
    border-radius: calc(24 * var(--u));
  }
  /* 140×50, medido del PDF mobile (banda negra en y 886..935). Estaba en 80 de
     alto —un 60% de más— y se veía hinchado. Con el cuerpo en 19 la mayúscula
     ocupa 13.3 y quedan 18.3 de aire arriba y abajo. */
  .cf-submit {
    width: calc(140 * var(--u));
    height: calc(50 * var(--u));
    padding: 0;
    margin-top: 0;
    font-size: calc(19 * var(--u));
    letter-spacing: .01em;
    font-weight: 400;
  }
  .cf-status { font-size: calc(15 * var(--u)); }
  /* Manos al espejo sobre el título (no sobre el lead) */
  .contacto-hand { left: auto; bottom: auto; transform-origin: center center; }
  .contacto-hand--cursor {
    top: calc(71 * var(--u));
    right: calc(12 * var(--u));
    height: calc(168 * var(--u));
    transform: scaleX(-1);                     /* Figma mobile: sin rotar */
    z-index: 2;
  }
  .contacto-hand--human {
    top: calc(257 * var(--u));
    /* 100 = 63 del Figma + 37. El +10 anterior era a ojo; esto está medido: la
       punta del dedo del cursor (píxel más bajo de su asset, x=663/1050) caía en
       304.5 y la de la mano (píxel más alto, x=39.5/900, tras el espejo y el giro
       de −13°) en 331.7 → 27.2u a la derecha. Ahora coinciden. */
    right: calc(100 * var(--u));
    height: calc(188 * var(--u));              /* misma razón que en desktop (548/464) */
    transform: scaleX(-1) rotate(-13deg);
    z-index: 3;
  }
}

/* ---- CONTACTO · TABLET (768–1023) ----
   Igual que mobile: el marco tablet de Mafer mide 768×1408, o sea el bloque
   SCROLLEA por diseño y --u es solo proporción de ancho sobre 768 (tope 1.2).

   Lo que estaba fuera del diseño: el título iba con line-height 1.06 (las 3
   líneas ocupaban 228 en vez de los 300 de Mafer, muy apretadas), el textarea
   200 en vez de 228, y las dos manos iban SIN espejo cuando en el Figma de
   tablet están espejadas igual que en mobile.

   Medidas del PDF tablet a 1:1 (bloque = y 8192..9599 de tab.png):
     título Boldonse 70 / lh 100, caja x=51, caps en y=219/319/419
     lead   Bebas 30 / lh 35, 2 líneas, cap top y=536
     form   x=57.5 ancho 654 (el MISMO del desktop); pills 80 con hueco 20
            (tops 722/822/922); textarea 228 en y=1022; botón 140×60 en
            y=1271; placeholders Bebas 25 a 32 del borde; ENVIAR Bebas 32
     manos  al espejo: cursor alto 242 girado ~4° (caja y=172..424 /
            x=470..654); mano humana debajo, tapada por la primera pastilla */
@media (min-width: 768px) and (max-width: 1023px) {
  .contacto { --u: min(calc(100vw / 768), 1.2px); }    /* --u es una LONGITUD (px) */
  .contacto-inner {
    display: block;
    position: relative;
    min-height: 0;
    width: 100%;
    padding: calc(213.1 * var(--u)) calc(51 * var(--u)) calc(78 * var(--u));
  }
  .contacto-head {
    position: static;
    align-self: auto;
    min-height: 0;
  }
  .contacto-title {
    font-size: calc(70 * var(--u));
    line-height: 1.4286;                       /* 100/70 (Figma), no 1.06 */
    color: var(--morado);
    z-index: 1;
  }
  .contacto-lead {
    font-size: calc(31 * var(--u));
    line-height: calc(49 / 36);                /* proporción del rediseño */
    /* 18.9 = 532 (caja del lead) − 513.1 (fin de las 3 líneas del título) */
    margin-top: calc(18.9 * var(--u));
    max-width: calc(492 * var(--u));
    z-index: 4;
  }
  .contacto-form {
    /* 120 = 722 (1.ª pastilla) − 602 (fin del lead) */
    margin-top: calc(120 * var(--u));
    width: calc(654 * var(--u));
    margin-left: auto;
    margin-right: auto;
    gap: calc(20 * var(--u));
    z-index: 5;
  }
  .cf-input {
    display: block;
    height: calc(80 * var(--u));
    padding: 0 calc(32 * var(--u));
    font-size: calc(24 * var(--u));                   /* Figma rediseño */
    letter-spacing: 0;
  }
  .cf-textarea {
    height: calc(228 * var(--u));
    min-height: 0;
    padding: calc(25 * var(--u)) calc(32 * var(--u));
    border-radius: calc(24 * var(--u));
  }
  .cf-submit {
    width: calc(140 * var(--u));                      /* Figma: 140×60 */
    height: calc(60 * var(--u));
    padding: 0;
    margin-top: 0;
    font-size: calc(24 * var(--u));
    letter-spacing: .01em;
  }
  .cf-status { font-size: calc(19 * var(--u)); }
  /* Manos al espejo arriba-derecha, sobre el título */
  .contacto-hand { left: auto; bottom: auto; transform-origin: center center; }
  .contacto-hand--cursor {
    top: calc(172 * var(--u));
    right: calc(116 * var(--u));
    height: calc(256 * var(--u));
    transform: scaleX(-1) rotate(-4deg);
    z-index: 2;
  }
  .contacto-hand--human {
    top: calc(486 * var(--u));
    right: calc(164 * var(--u));
    height: calc(262 * var(--u));
    transform: scaleX(-1) rotate(-5deg);       /* ajuste por silueta contra el Figma */
    z-index: 3;
  }
}

/* ============ DESKTOP ≥1024 · CONTACTO A ESCALA ÚNICA ============
   Misma premisa que hero, manifiesto, espíritus y conjuros: el bloque de Mafer
   es una caja de 1920×1080 (contenido 1620 centrado) con banda de nav de 150
   arriba, y TODO se expresa en unidades de ese diseño por una sola escala
   --u = min(lo que da el ancho, lo que da el alto).

   Acá el defecto NO era que se saliera de pantalla (medido: en las 18
   resoluciones probadas el bloque siempre cupo). Era que la composición de
   Mafer no se reproducía NI SIQUIERA a 1920×1080, porque cada pieza se
   clampeaba por su cuenta contra el ancho y las manos se anclaban con números
   mágicos sobre el 50% de la caja:
     · el título caía 50px más abajo que en el Figma y el lead 51px;
     · el formulario arrancaba 36px más abajo y terminaba 74px más abajo,
       porque el textarea rendía 150 en vez de 228 y el botón 72×192 en vez
       de 60×140;
     · la mano humana se dibujaba a 657 de alto cuando el diseño la pone en
       548 (un 20% más grande);
     · el punto donde casi se tocan los dedos —que Mafer puso a media altura
       de la última línea, CONOCERNOS— se había corrido al arranque de esa
       línea, y con cada resolución se movía;
     · a 1512×760 el botón ENVIAR quedaba pegado al filo inferior (0px de
       aire), porque el alto del formulario no miraba el alto de la ventana.
   Con --u las dos manos, el título y el formulario son fracciones fijas del
   mismo marco: el encuentro de los dedos cae siempre en el mismo punto de la
   palabra y el bloque entero entra a cualquier tamaño.

   Divisor de alto = 756 = lo que MIDE el contenido (borde superior del cursor
   → borde inferior de la línea de estado del form), no los 930 útiles del
   marco: el aire que dejó Mafer (9 arriba / 165 abajo, que es por donde sangra
   el brazo) se consume ANTES de encoger el diseño, y el sobrante se reparte
   después en esa misma proporción (5.17% / 94.83%). El brazo de la mano humana
   sigue sangrando fuera del bloque a propósito (lo recorta overflow:hidden).

   Medidas del PDF de Figma a 1:1 (bloque = y 7560..8639 de home.png), en X
   sobre el canvas de 1920 (centro 960) y en Y sobre el bloque:
     título   Boldonse 80 / lh 115 / ls 0, caja en x=150, 3 líneas,
              caps en y=359 / 474 / 589 → caja arranca en 351.9
     lead     Bebas 35 / lh 40 / ls 0, x=150, 2 líneas, cap top y=738
     form     x=1116, ancho 654; pills 80 de alto con paso 100 (tops 275/375/
              475); textarea 228 en y=575 (radio 24); botón 140×60 en y=824;
              placeholders Bebas 25 / ls 0 a 32 del borde; ENVIAR Bebas 32
     cursor   alto 464, top y=159, izq x=649  (asset 1050×1515, sale solo)
     mano     alto 548, top y=667, izq x=831  (asset 900×1467; ajuste por
              silueta con IoU 0.905 — se ve el 75% y el resto sangra) */
@media (min-width: 1024px) {
  .contacto {
    --u-w: calc(min(var(--content-max), 100vw - var(--gutter) * 2) / 1620);
    /* Igual que en conjuros: el divisor es el MARCO COMPLETO bajo el nav
       (930 = 1080 − 150), no sólo el contenido (756), para que los 165px de
       margen inferior de Mafer escalen con el bloque en vez de quedar como
       residuo. Cuando manda el alto, la sobra vale 930u − 756u = 174u y el
       reparto 0.0517 devuelve --frame-top = nav − 150u exacto. */
    --u-h: calc((100svh - var(--nav-h)) / 930);
    --u:   min(var(--u-w), var(--u-h));
    /* Y del diseño 0 = borde superior del bloque; el cursor (y=159) se apoya
       en el reparto del sobrante. */
    --frame-top: calc(var(--nav-h) - 159 * var(--u)
                      + (100svh - var(--nav-h) - 756 * var(--u)) * 0.0517);
  }
  /* La caja interior deja de maquetar: pasa a ser el lienzo del marco. */
  .contacto-inner {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    min-height: 0;
  }

  .contacto-head {
    position: absolute;
    top: calc(var(--frame-top) + 351.9 * var(--u));   /* cap de la 1.ª línea en y=359 */
    left: 50%;
    margin-left: calc(-810 * var(--u));               /* x=150 del canvas */
  }
  .contacto-title {
    font-size: calc(80 * var(--u));
    line-height: 1.4375;                              /* 115/80 (Figma) */
  }
  .contacto-lead {
    font-size: calc(36 * var(--u));                   /* Figma rediseño */
    line-height: calc(49 / 36);                       /* 49/36 (Figma) */
    /* 36.85 = 733.75 (caja del lead) − 696.9 (fin de las 3 líneas del título) */
    margin-top: calc(36.85 * var(--u));
    max-width: calc(575 * var(--u));                  /* corta en 2 como Mafer */
  }

  .contacto-form {
    position: absolute;
    top: calc(var(--frame-top) + 275 * var(--u));
    left: 50%;
    margin-left: calc(156 * var(--u));                /* x=1116 del canvas */
    width: calc(654 * var(--u));
    gap: calc(20 * var(--u));                         /* paso 100 con pills de 80 */
  }
  .cf-input {
    /* en línea (por defecto) el textarea deja 3px de hueco bajo la línea base
       y corría el botón fuera de su posición del Figma */
    display: block;
    height: calc(80 * var(--u));
    padding: 0 calc(32 * var(--u));
    font-size: calc(24 * var(--u));                   /* Figma rediseño */
    letter-spacing: 0;
  }
  .cf-textarea {
    height: calc(228 * var(--u));
    min-height: 0;                                    /* si no, el clamp base lo estira */
    padding: calc(25 * var(--u)) calc(32 * var(--u));
    border-radius: calc(24 * var(--u));
  }
  .cf-submit {
    width: calc(140 * var(--u));                      /* Figma: 140×60 (medido y
                                                         confirmado en el panel) */
    height: calc(60 * var(--u));
    padding: 0;
    margin-top: calc(1 * var(--u));                   /* 21 de hueco con el textarea */
    font-size: calc(24 * var(--u));
    letter-spacing: 0;
  }
  /* El mensaje de estado no existe en el Figma: va FUERA del flujo para que la
     caja del formulario mida exactamente lo de Mafer (609), pero su alto sí
     está contado en el divisor (por eso 756 y no 725). */
  .cf-status {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: calc(8 * var(--u));
    font-size: calc(19 * var(--u));
    line-height: 1.2;
    min-height: 0;
  }

  /* Manos: ancladas al marco, no al 50% de la caja. Así el punto de encuentro
     de las puntas (cursor termina en 623, la mano arranca en 667) cae siempre
     a la misma altura de CONOCERNOS. */
  .contacto-hand { bottom: auto; right: auto; }
  .contacto-hand--cursor {
    top: calc(var(--frame-top) + 159 * var(--u));
    left: 50%;
    margin-left: calc(-311 * var(--u));               /* x=649 del canvas */
    height: calc(464 * var(--u));
  }
  .contacto-hand--human {
    top: calc(var(--frame-top) + 667 * var(--u));
    left: 50%;
    margin-left: calc(-129 * var(--u));               /* x=831 del canvas */
    height: calc(548 * var(--u));
    transform: none;                                  /* el alto ya es el del diseño */
  }
}

/* ============ BLOQUE 9 · FOOTER (negro) ============
   MEDIDO del Figma el 30-jul-2026. El hallazgo que manda en todo el bloque:
   **Mafer dibujó el footer al MISMO tamaño en el marco de 1620 y en el de 768.**
   Coinciden pixel a pixel en los dos PDFs — mismos anchos de tinta del nav
   (95/46/81/82), mismo SVG de 578×177, mismas Y (45/109/189/349), misma línea de
   copyright de 421 de ancho. Es decir: el footer NO escala con el marco, es una
   composición de tamaño fijo centrada, y es el único bloque del sitio así. Por
   eso acá la corrección va al REVÉS que en los demás bloques: hay que dejar de
   escalarlo con vw. Antes, con clamps sobre vw, a 1024 el footer se dibujaba al
   65% del diseño (nav 20.5 en vez de 28, íconos 34 en vez de 52, copy 13/20).

   Geometría del Figma (idéntica en desktop y tablet; origen = borde superior de
   la banda negra):
     · nav      · 4 celdas de 178 (riel de 712 centrado) con el texto centrado en
                  cada celda — el paso por centros es 178 exacto, no un gap fijo;
                  Bebas 28 / ls 1% / cap top y=45 / color lila #D8D1E1 (medido
                  214,209,224 — ni blanco ni el gris al 50% que teníamos)
     · SÍGUENOS · el SVG a escala 1:1 (578×177), top y=109
     · redes    · alto 52 (Behance 46), hueco 35, y el grupo va 17px por debajo
                  del centro del SVG (centro de íconos en y=214.5)
     · copy     · Bebas 20 / ls 0 / BLANCO, cap top y=357; logo Chamán de alto 31
                  con la tinta en y=349..380
     · banda    · 460 de alto en desktop y 484 en tablet (Mafer le dio 24 más de
                  aire abajo en el marco chico)

   `--u` acá existe solo como válvula de seguridad: vale 1px salvo que el riel de
   712 no quepa (a 768 justos entra exacto con los 28 de margen de Mafer). Como
   siempre, --u es una LONGITUD en px, nunca un número. */
footer.footer {
  --u: min(1px, calc((100vw - 56px) / 712));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;                                    /* márgenes específicos por elemento (Figma) */
  /* 43.6 = cap top 45 − el empuje de cap de Bebas con lh 1 (0.05em × 28 = 1.4) */
  padding: calc(43.6 * var(--u)) var(--gutter) calc(78.5 * var(--u));
}
.footer-siguenos {                            /* SÍGUENOS en SVG (contorno, 578×177 Figma) */
  display: block;
  width: calc(578 * var(--u));
  height: auto;
}
.footer-nav {
  /* Rejilla de 4 celdas iguales: reproduce el paso de 178 por centros del Figma.
     Con un `gap` de flex los huecos salían 149/140/162 en vez de 178/178/178. */
  display: grid;
  grid-template-columns: repeat(4, calc(178 * var(--u)));
  justify-items: center;
  width: calc(712 * var(--u));
}
.footer-link {
  /* Figma (rediseño): Safiro Medium 20 / lh 150 / ls 0. OJO: mismo cuerpo que el
     nav de arriba pero con ls 0, no −2%. Son dos estilos distintos. */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: calc(20 * var(--u));
  line-height: 1;
  letter-spacing: 0;
  text-transform: uppercase;
  /* Morado de marca por pedido del cliente (26-ago). Antes era el lila #D8D1E1
     del Figma. OJO accesibilidad: #6539A7 sobre el negro del pie da ~2.2:1
     (el lila daba ~13:1); es decisión de diseño del cliente, como el blanco
     sobre coral del nav. El hover sube a blanco. */
  color: var(--morado);
  text-decoration: none;
  transition: color .2s ease;
}
.footer-link:hover { color: var(--blanco); }

/* SÍGUENOS (contorno) con íconos encima */
.footer-follow {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  margin-top: calc(37.4 * var(--u));         /* base del nav (71.6) → top del SVG (109) */
}
.footer-social {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: calc(35 * var(--u));
  transform: translateY(calc(18 * var(--u)));  /* centro de íconos 18px bajo el del SVG */
}
.footer-social li { display: flex; }
.footer-ic { display: flex; align-items: center; transition: opacity .2s ease; }
.footer-ic:hover { opacity: .68; }
.footer-ic img {
  height: calc(52 * var(--u));
  width: auto;
  display: block;
}
.ic-behance img { height: calc(46 * var(--u)); }

/* Línea de contacto (pedido del cliente, 26-ago): va entre las redes y el
   copyright, en BLANCO. Se reparte el hueco de 64.5 que había entre el SVG de
   SÍGUENOS y el copyright: 42 hasta esta línea y 26 desde ella al copyright. */
.footer-cta {
  margin-top: calc(42 * var(--u));
  /* El pie es un flex en columna: sin este tope el párrafo se mide a
     max-content, no parte por ningún lado y se sale del margen lateral. */
  max-width: 100%;
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: calc(20 * var(--u));
  line-height: 1.2;
  letter-spacing: 0;
  text-align: center;
  color: var(--blanco);
}
.footer-cta a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, .45);
  transition: border-color .2s ease, color .2s ease;
}
.footer-cta a:hover { color: var(--coral); border-bottom-color: var(--coral); }

/* Copyright */
.footer-copy {
  margin-top: calc(26 * var(--u));           /* antes 64.5: la línea de contacto ocupa el resto */
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  column-gap: calc(9 * var(--u));
  row-gap: 0;
  /* Figma (rediseño): Safiro Medium 16 / lh 22 / ls 0, en CAJA MIXTA
     ("© Copyright 2026 Todos los derechos reservados"), no en versales. */
  font-family: var(--font-nav);
  font-weight: 500;
  font-size: calc(16 * var(--u));
  line-height: calc(22 / 16);
  letter-spacing: 0;
  text-transform: none;
  color: var(--blanco);
}
/* El hueco entre "2026" y "Todos…" en el Figma es un ESPACIO de la fuente
   (~3.4px a 16), no el gap de 9 que separa al logo. */
.footer-copy > span:last-child { margin-left: calc(-5.4 * var(--u)); }
.footer-logo {
  height: calc(31 * var(--u));
  width: auto;
  color: var(--blanco);                    /* currentColor → logo blanco */
  display: inline-block;
  transform: translateY(calc(-1.5 * var(--u)));   /* tinta del logo a y=349 */
}

/* ---- FOOTER (9) MOBILE (≤767): orden = SÍGUENOS+redes · nav · copyright ----
   Marco de Mafer 390×484. Acá SÍ hay escala propia, y no es uniforme: el
   wordmark va a 0.60 del desktop (344 de ancho), los íconos a 0.75 (39), el nav
   a 0.71 (20) y el copyright + el logo a 1.00 (20 y 31, los mismos del desktop).
   Con --u = 100vw/390 el SVG mantiene sus márgenes de 23px hasta 320. */
@media (max-width: 767px) {
  footer.footer {
    --u: min(calc(100vw / 390), 1.15px);
    padding: calc(39 * var(--u)) 0 calc(48 * var(--u));
    gap: 0;
  }
  /* Reordenamiento visual: en el DOM va nav→follow→copy; Mafer lo quiere follow→nav→copy */
  .footer-follow { order: 1; margin-top: 0; }
  .footer-nav    { order: 2; margin-top: calc(37.1 * var(--u)); }
  /* La línea de contacto se lleva parte del hueco de 86.5 que había entre el
     nav y el copyright: 52 hasta ella y 26 de ella al copyright. */
  .footer-cta    { order: 3; margin-top: calc(52 * var(--u)); font-size: calc(16 * var(--u)); }
  .footer-copy   { order: 4; margin-top: calc(26 * var(--u)); }

  .footer-siguenos { width: calc(344 * var(--u)); }
  .footer-social {
    gap: calc(26 * var(--u));
    transform: translateY(calc(14 * var(--u)));
  }
  .footer-ic img   { height: calc(39 * var(--u)); }
  .ic-behance img  { height: calc(34.5 * var(--u)); }

  /* Nav apilado y centrado. El paso entre líneas del Figma es 31 exacto, así que
     va como line-height con gap 0 (antes: lh 18 + gap 20 = paso 38). */
  .footer-nav {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0;
    width: auto;
  }
  .footer-link {
    font-size: calc(14 * var(--u));                   /* 0.71 del nav del footer, como antes */
    line-height: calc(31 * var(--u));
    text-align: center;
  }

  .footer-copy { line-height: calc(22 * var(--u)); column-gap: calc(8 * var(--u)); }
  /* Los márgenes negativos dejan la caja del logo en 22 para que no estire la
     primera línea: el paso 394→416 del Figma es el line-height, no logo+aire. */
  .footer-logo {
    margin-block: calc(-4.5 * var(--u));
    transform: translateY(calc(-6.5 * var(--u)));
  }
  /* Salto de línea forzado tras "2026": la última línea va sola y centrada */
  .footer-copy > span:last-child { flex-basis: 100%; text-align: center; margin-left: 0; }
}

/* ---- FOOTER (9) TABLET (768–1023): la MISMA composición del desktop, tal cual
   el Figma. Lo único propio del marco chico es el aire de abajo: banda de 484 en
   vez de 460. ---- */
@media (min-width: 768px) and (max-width: 1023px) {
  footer.footer { padding-bottom: calc(102.5 * var(--u)); }
}

/* ============ RESPONSIVE ============ */
/* ---- TABLET (≤1024): logo completo + botón + hamburguesa; links al menú ---- */
@media (max-width: 1024px) {
  .main-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .logo-svg { width: 194px; }              /* logo completo en tablet */
}

/* ---- Pantallas angostas (≤600): el CTA se queda AL LADO DE LA HAMBURGUESA
   (pedido del cliente, 26-ago). Antes se escondía acá para no desbordar: a 390
   el botón de 180×50 no entra junto al logo y al menú. Vuelve en versión
   compacta —ancho por contenido y no fijo, alto y cuerpo menores— y con los
   huecos del header apretados. El CTA del menú overlay se conserva. ---- */
@media (max-width: 600px) {
  .header-inner { gap: clamp(8px, 2.6vw, 14px); }
  .nav-cluster  { gap: clamp(10px, 3vw, 16px); }
  .nav-cluster .btn-cta {
    width: auto;                              /* el ancho lo da el texto, no --cta-w */
    height: clamp(32px, 9vw, 40px);
    padding: 0 clamp(11px, 3.4vw, 16px);
    font-size: clamp(10px, 2.9vw, 13px);
    gap: .45em;
  }
  .nav-cluster .cta-icon {
    width:  clamp(11px, 3.2vw, 14px);
    height: clamp(11px, 3.2vw, 14px);
  }
}

/* ---- TABLET + MOBILE (≤1023): Hero swap del ícono de scroll (mouse → doble chevron de Mafer).
   Mouse completo solo en desktop (≥1024). ---- */
@media (max-width: 1023px) {
  .scroll-hint-svg      { display: none; }
  .scroll-hint-svg--mob { display: block; }
}

/* ---- MOBILE (≤480): logo a la mitad ---- */
@media (max-width: 480px) {
  .logo-svg,
  .mm-logo-img { width: 98px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ============================================================
   ANIMACIONES DE ENTRADA
   Por ahora SOLO desktop (≥1024). Todo va dentro de
   `(prefers-reduced-motion: no-preference)`: quien pide menos
   movimiento ve la web quieta, sin estados invisibles.

   Regla de oro de este bloque: el estado escondido nunca puede
   quedar colgado. Por eso el manifiesto cuelga de `.is-pinned`,
   que solo existe si GSAP cargó y enganchó la sección — si el
   CDN falla o el JS revienta, el contenido se ve normal.
   ============================================================ */

/* texto solo para lectores de pantalla (las letras partidas van aria-hidden) */
.u-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Agrupador de palabra del efecto letra por letra (lo crea splitLetters).
   Las letras son inline-block —lo necesitan para el transform— así que sin este
   nowrap el navegador corta la línea ENTRE letras y parte las palabras. */
.ltr-w { white-space: nowrap; }

/* Saltos de línea del subtítulo del manifiesto. Mafer NO deja que el texto fluya:
   parte "efectiva" y "y afectiva." en líneas distintas, cosa que el wrap natural
   no hace (le cabe "efectiva y" de sobra en los 366 de caja). Van forzados en
   desktop y anulados en ≤1023, donde la caja es otra.
   El ESPACIO va antes del <br> a propósito: al ocultarlo en móvil las palabras
   quedan separadas (si no, salía "comunicaciónefectiva"). */
@media (max-width: 1023px) { .block-sub .br-d { display: none; } }

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {

  /* ---- NAV · entra una sola vez, con la portada ----
     Se anima `.header-inner` (logo + links + botón) y NO `.site-header`: la
     cabecera es la que lleva el velo con `backdrop-filter`, y ponerle opacidad
     o transform le cambia la forma de muestrear el fondo.
     Se dispara con `hero-listo`, que se enciende UNA vez por carga y no se
     apaga nunca: por eso no puede repetirse ni oscilar al scrollear. */
  .js .header-inner {
    opacity: 0;
    transform: translateY(-12px);
  }
  .js.hero-listo .header-inner {
    animation: navEntra .9s cubic-bezier(.16, 1, .3, 1) 80ms forwards;
  }

  /* ---- HERO · la portada aparece y recién entonces sube el titular ----
     Las dos clases viven en el <html> y las pone el script en línea del <head>:
       · `js`         → el hero puede arrancar escondido desde el primer pintado
                        (sin JS no se marca nada y el hero se ve normal);
       · `hero-listo` → la imagen de portada terminó de cargar.
     Antes el titular arrancaba con la página: si la portada tardaba, el texto
     entraba sobre el vacío y se veía raro.

     .hero-line es la ventana que recorta; el recorte se abre .1em a los lados
     (`overflow-clip-margin`) para no morder la última letra, porque en flex el
     renglón mide exactamente lo que el texto. */
  .js .hero-cover img {
    scale: 1.07;
    opacity: 0;
    transition: scale 1.9s cubic-bezier(.16, 1, .3, 1),
                opacity .9s ease-out;
  }
  .js.hero-listo .hero-cover img { scale: 1; opacity: 1; }

  .js .hero-line {
    overflow: hidden;      /* respaldo para navegadores sin `clip` */
    overflow: clip;
    overflow-clip-margin: .1em;
  }
  .js .hero-line__in {
    display: block;
    transform: translateY(118%);
    will-change: transform;
  }
  .js.hero-listo .hero-line__in {
    animation: heroRise 1.05s cubic-bezier(.16, 1, .3, 1) forwards;
    animation-delay: calc(var(--i, 0) * 115ms + 200ms);
  }
  .hero-group--top .hero-line:nth-child(2) .hero-line__in { --i: 1; }
  .hero-group--bot .hero-line:nth-child(1) .hero-line__in { --i: 2; }
  .hero-group--bot .hero-line:nth-child(2) .hero-line__in { --i: 3; }

  /* ---- Indicador de scroll · entra el ÚLTIMO ----
     El 4.º renglón arranca a 545ms (3×115 + 200) y dura 1.05s → aterriza en
     1595ms. El ícono espera a eso y recién ahí se disuelve, sin desplazarse
     (lleva translateX(-50%) para centrarse: animar sólo la opacidad no se lo
     toca). Reutiliza `conjFunde`, que es un fundido a 1 genérico. */
  .js .scroll-hint { opacity: 0; }
  .js.hero-listo .scroll-hint {
    animation: conjFunde .6s ease-out 1650ms forwards;
  }

  /* ---- MANIFIESTO 1 y 2 · imagen 3D con zoom out ----
     Va en la propiedad `scale` y no en `transform` a propósito: las
     imágenes ya usan `transform` para su posicionado en otros anchos,
     y `scale` se compone con él en vez de pisarlo. */
  .manifiesto.is-pinned .panel-manif .panel-art {
    scale: 1.26;                       /* recorrido al doble (era .13 sobre 1) */
    opacity: 0;
    /* .1 de siempre + los .5 extra que pidió Jonathan: la imagen entra
       claramente después del texto, no junto con él */
    transition: scale 1.25s cubic-bezier(.16, 1, .3, 1) .6s,
                opacity .85s ease-out .6s;
  }
  .manifiesto.is-pinned .panel-manif.is-in .panel-art { scale: 1; opacity: 1; }

  /* ---- MANIFIESTO 1 y 2 · texto letra por letra, de borroso a foco ----
     El índice de cada letra lo escribe el JS en --i al partir el texto. */
  .manifiesto.is-pinned .ltr {
    display: inline-block;
    opacity: 0;
    filter: blur(12px);
    transform: translateY(.2em) scale(1.16);
  }
  .manifiesto.is-pinned .panel.is-in .ltr {
    animation: ltrIn .72s cubic-bezier(.22, 1, .36, 1) forwards;
    animation-delay: calc(var(--i, 0) * var(--step, 26ms) + var(--d, 0ms));
  }
  /* el subtítulo entra después del titular y con paso más corto (tiene
     el triple de letras: con el mismo paso la última llegaba tardísimo) */
  .manifiesto.is-pinned .panel-sub { --d: 320ms; --step: 14ms; }

  /* ---- CONJUROS · cada pieza de la card emerge desde abajo con rebote ----
     Referencia de Jonathan: el producto del slider de sliderrevolution
     (pin de Pinterest) sube a su sitio y al llegar cae un poquito.
     Ese "rebote hacia abajo" es la curva: el bezier se pasa de 1, así que la
     pieza sobrepasa su posición final hacia arriba y vuelve a bajar.
     Se anima cada ELEMENTO (ícono, título, descripción), no la card entera.

     El desplazamiento va en la propiedad `translate` y NO en `transform`:
     el ícono de Diseño Gráfico ya lleva `transform: scaleX(-1)` y `translate`
     se compone con él en vez de pisarlo. */
  .conjuros.js-reveal .conj-icon,
  .conjuros.js-reveal .conj-title,
  .conjuros.js-reveal .conj-desc {
    translate: 0 46px;
    opacity: 0;
  }
  /* CADA FILA arranca por su cuenta (ver el observador en nav.js): si las 5
     cards colgaran del bloque entero, las dos de abajo se animaban fuera de
     pantalla y al llegar scrolleando ya estaban puestas. */
  .conjuros.js-reveal .conj-row.is-in .conj-icon,
  .conjuros.js-reveal .conj-row.is-in .conj-title,
  .conjuros.js-reveal .conj-row.is-in .conj-desc {
    /* dos animaciones porque el rebote es solo del movimiento: si la curva con
       sobrepaso también manejara la opacidad, parpadearía al pasarse de 1 */
    /* la curva sale de --curva para poder darle a la imagen 3D un rebote un
       poco más marcado que al texto sin repetir toda la declaración (el
       atajo `animation` reiniciaría el animation-delay a 0) */
    animation: conjSube .85s var(--curva, cubic-bezier(.21, 1.7, .45, 1)) forwards,
               conjFunde .45s ease-out forwards;
    /* 500ms de arranque: da tiempo a que la fila termine de entrar en cuadro */
    animation-delay: calc(500ms + var(--c, 0) * 120ms + var(--e, 0) * 90ms);
  }
  /* orden dentro de la card */
  .conjuros .conj-icon  { --e: 0; --curva: cubic-bezier(.21, 2.05, .45, 1); }  /* rebota una pizca más */
  .conjuros .conj-title { --e: 1; }
  .conjuros .conj-desc  { --e: 2; }
  /* orden de las cards DENTRO de su fila (nth-child cuenta desde cada fila) */
  .conjuros .conj:nth-child(1) { --c: 0; }
  .conjuros .conj:nth-child(2) { --c: 1; }
  .conjuros .conj:nth-child(3) { --c: 2; }

  /* ---- CONTACTO · el formulario entra con el mismo gesto de las cards ----
     Cada pastilla y el botón emergen desde abajo con el mismo rebote de
     Conjuros, escalonados de arriba hacia abajo. Arrancan después del titular
     (260ms) para que la lectura vaya primero al texto y después al formulario.
     El estado escondido cuelga de `js-pop`, que pone el JS: sin él no se
     esconde nada. */
  .contacto-form.js-pop .cf-field,
  .contacto-form.js-pop .cf-submit {
    translate: 0 46px;
    opacity: 0;
  }
  .contacto-form.js-pop.is-in .cf-field,
  .contacto-form.js-pop.is-in .cf-submit {
    animation: conjSube .85s cubic-bezier(.21, 1.7, .45, 1) forwards,
               conjFunde .45s ease-out forwards;
    animation-delay: calc(260ms + var(--e, 0) * 90ms);
  }
  .contacto-form .cf-field:nth-of-type(1) { --e: 0; }
  .contacto-form .cf-field:nth-of-type(2) { --e: 1; }
  .contacto-form .cf-field:nth-of-type(3) { --e: 2; }
  .contacto-form .cf-field:nth-of-type(4) { --e: 3; }
  .contacto-form .cf-submit                { --e: 4; }

  /* ---- MISMO EFECTO DE LETRAS FUERA DEL MANIFIESTO ----
     Título de Espíritus y textos de Contacto. Esos bloques no están pineados,
     así que el disparador es la propia aparición en pantalla y la clase va en
     el elemento (la pone el JS al partirlo en letras). */
  .js-ltr .ltr {
    display: inline-block;
    opacity: 0;
    filter: blur(12px);
    transform: translateY(.2em) scale(1.16);
  }
  .js-ltr.is-in .ltr {
    animation: ltrIn .72s cubic-bezier(.22, 1, .36, 1) forwards;
    animation-delay: calc(var(--i, 0) * var(--step, 26ms) + var(--d, 0ms));
  }
  /* el lead de Contacto tiene ~60 letras: con el paso del titular la última
     llegaba tardísimo, así que va más rápido y arranca después */
  .contacto-lead.js-ltr { --step: 13ms; --d: 300ms; }

  /* ---- MANIFIESTO 3 · mismo efecto que las cards de Conjuros ----
     Cada pieza (cifra, etiqueta, imagen y descripción) emerge desde abajo y
     rebota al llegar; la imagen rebota una pizca más, igual que allá.
     OBLIGATORIO usar `translate` y no `transform`: estas piezas ya llevan
     `transform: translateY(...)` (y rotaciones) como retoque de montaje.
     El arranque acá es corto (120ms y no los 500 de Conjuros) porque el panel
     llega pineado, ya encuadrado: no hay que esperar a que termine de entrar. */
  /* El borde no se mueve (la caja tiene que quedarse quieta), solo aparece:
     se funde el COLOR del borde, no la opacidad de la card — si no, se
     llevaría puesto el contenido, que tiene su propia entrada. */
  .manifiesto.is-pinned .panel-stats .stat-card {
    border-color: transparent;
    transition: border-color 1.1s ease-out .12s;
  }
  .manifiesto.is-pinned .panel-stats.is-in .stat-card { border-color: var(--tinta); }

  .manifiesto.is-pinned .panel-stats .stat-num,
  .manifiesto.is-pinned .panel-stats .stat-label,
  .manifiesto.is-pinned .panel-stats .stat-img,
  .manifiesto.is-pinned .panel-stats .stat-desc {
    translate: 0 46px;
    opacity: 0;
  }
  .manifiesto.is-pinned .panel-stats.is-in .stat-num,
  .manifiesto.is-pinned .panel-stats.is-in .stat-label,
  .manifiesto.is-pinned .panel-stats.is-in .stat-img,
  .manifiesto.is-pinned .panel-stats.is-in .stat-desc {
    animation: conjSube .85s var(--curva, cubic-bezier(.21, 1.7, .45, 1)) forwards,
               conjFunde .45s ease-out forwards;
    animation-delay: calc(120ms + var(--c, 0) * 120ms + var(--e, 0) * 90ms);
  }
  /* orden dentro de la card: de arriba hacia abajo */
  .panel-stats .stat-num   { --e: 0; }
  .panel-stats .stat-label { --e: 1; }
  .panel-stats .stat-img   { --e: 2; --curva: cubic-bezier(.21, 2.05, .45, 1); }
  .panel-stats .stat-desc  { --e: 3; }
  /* orden de las 3 cards */
  .panel-stats .stat-card:nth-child(1) { --c: 0; }
  .panel-stats .stat-card:nth-child(2) { --c: 1; }
  .panel-stats .stat-card:nth-child(3) { --c: 2; }
}

/* ============================================================
   CAPA MOBILE + TABLET (≤1023)
   Hereda lo barato del desktop (nav, hero, zoom out de portada, rebote de las
   cards) y REPLANTEA lo caro o lo que no calza en táctil:
     · el desenfoque letra-por-letra NO se usa acá (crea una capa por letra y
       en gama media pesa) → título de Espíritus y textos de Contacto entran
       como bloque, apareciendo y subiendo, SIN blur;
     · recorridos y escalonados más cortos (en el teléfono se ve una card a la
       vez; encadenar cinco hace que las últimas lleguen tarde);
     · el formulario entra con FUNDIDO SOLO, sin desplazamiento: que las
       pastillas vuelen justo cuando el dedo va a tocarlas es molesto;
     · Conjuros dispara POR CARD (en vertical un bloque ocupa mucho alto; el
       "por fila" del desktop dejaría la de abajo animándose fuera de cuadro);
     · el manifiesto pineado horizontal NO se toca: el pase ES su animación.
   Las custom properties de orden se redeclaran acá (son inertes hasta que una
   animación las lee) para no tocar el bloque de desktop. */
@media (max-width: 1023px) and (prefers-reduced-motion: no-preference) {

  /* NAV — un fundido, una sola vez, con la portada */
  .js .header-inner { opacity: 0; transform: translateY(-10px); }
  .js.hero-listo .header-inner { animation: navEntra .8s cubic-bezier(.16, 1, .3, 1) 60ms forwards; }

  /* HERO — la portada aparece con zoom out y recién ahí sube el titular.
     El zoom va en `scale` (propiedad), NO en transform: en ≤767 la portada ya
     lleva `transform: scale(1.25)` y `scale` se compone con él (1.06×1.25 →
     1×1.25) en vez de pisarlo. */
  .js .hero-cover img {
    scale: 1.06;
    opacity: 0;
    transition: scale 1.6s cubic-bezier(.16, 1, .3, 1),
                opacity .8s ease-out;
  }
  .js.hero-listo .hero-cover img { scale: 1; opacity: 1; }

  .js .hero-line {
    overflow: hidden;
    overflow: clip;
    overflow-clip-margin: .12em;
  }
  .js .hero-line__in {
    display: block;
    transform: translateY(118%);
    will-change: transform;
  }
  .js.hero-listo .hero-line__in {
    animation: heroRise .95s cubic-bezier(.16, 1, .3, 1) forwards;
    animation-delay: calc(var(--i, 0) * 95ms + 160ms);
  }
  .hero-group--top .hero-line:nth-child(2) .hero-line__in { --i: 1; }
  .hero-group--bot .hero-line:nth-child(1) .hero-line__in { --i: 2; }
  .hero-group--bot .hero-line:nth-child(2) .hero-line__in { --i: 3; }

  /* Indicador de scroll · el último en entrar. Acá el 4.º renglón arranca a
     445ms (3×95 + 160) y dura .95s → aterriza en 1395ms. */
  .js .scroll-hint { opacity: 0; }
  .js.hero-listo .scroll-hint {
    animation: conjFunde .55s ease-out 1450ms forwards;
  }

  /* ESPÍRITUS + CONTACTO (títulos y lead) — aparecen y suben, SIN blur.
     Mismo gesto que las cards pero con curva suave (el texto no debe rebotar).
     La clase `js-rise` la pone el JS solo en ≤1023. */
  .js-rise {
    opacity: 0;
    translate: 0 24px;
  }
  .js-rise.is-in {
    animation: conjSube .8s cubic-bezier(.16, 1, .3, 1) forwards,
               conjFunde .55s ease-out forwards;
  }

  /* FORMULARIO — fundido solo, sin desplazamiento (táctil). Escalonado corto. */
  .contacto-form.js-pop .cf-field,
  .contacto-form.js-pop .cf-submit { opacity: 0; }
  .contacto-form.js-pop.is-in .cf-field,
  .contacto-form.js-pop.is-in .cf-submit {
    animation: conjFunde .55s ease-out forwards;
    animation-delay: calc(var(--e, 0) * 60ms);
  }
  .contacto-form .cf-field:nth-of-type(1) { --e: 0; }
  .contacto-form .cf-field:nth-of-type(2) { --e: 1; }
  .contacto-form .cf-field:nth-of-type(3) { --e: 2; }
  .contacto-form .cf-field:nth-of-type(4) { --e: 3; }
  .contacto-form .cf-submit                { --e: 4; }

  /* CONJUROS — cada pieza emerge con rebote, recorrido y escalonado más cortos.
     Dispara por CARD (`.conj.is-in`, lo marca el JS), no por fila. */
  .conjuros.js-reveal .conj-icon,
  .conjuros.js-reveal .conj-title,
  .conjuros.js-reveal .conj-desc {
    translate: 0 30px;
    opacity: 0;
  }
  .conjuros.js-reveal .conj.is-in .conj-icon,
  .conjuros.js-reveal .conj.is-in .conj-title,
  .conjuros.js-reveal .conj.is-in .conj-desc {
    animation: conjSube .8s var(--curva, cubic-bezier(.21, 1.7, .45, 1)) forwards,
               conjFunde .4s ease-out forwards;
    animation-delay: calc(var(--e, 0) * 70ms);
  }
  .conjuros .conj-icon  { --e: 0; --curva: cubic-bezier(.21, 2.05, .45, 1); }
  .conjuros .conj-title { --e: 1; }
  .conjuros .conj-desc  { --e: 2; }
}

/* ---- ESPÍRITUS · entrada del mazo (12-ago) ----------------------------------
   El bloque no tenía ninguna: el título entraba (letras en desktop, subida en
   mobile) y el carrusel simplemente estaba ahí.

   Va sobre el CONTENEDOR, nunca sobre las cards: sus `transform` y su `opacity`
   los escribe nav.js en cada frame del coverflow, así que cualquier animación
   CSS encima se la comería el siguiente render. `.esp-stack` en cambio no lo
   toca nadie.

   Se usan las propiedades independientes `translate` y `scale` —no `transform`—
   por la misma razón de siempre en este archivo: así componen con lo que ya
   haya puesto en `transform` en vez de pisarlo. En las viñetas eso es lo que
   permite escalonarlas: la activa lleva `transform: scale(1.42)` y el `scale: 1`
   de la animación se multiplica con él en vez de anularlo.

   Los 120ms de retraso del mazo dejan que el título se lea primero: en desktop
   los dos disparadores caen casi a la vez porque el bloque mide una pantalla. */
@media (prefers-reduced-motion: no-preference) {
  .esp-stack.js-deck {
    opacity: 0;
    translate: 0 34px;
    scale: .94;
  }
  .esp-stack.js-deck.is-in {
    animation: espMazo .95s cubic-bezier(.16, 1, .3, 1) 120ms forwards,
               conjFunde .6s ease-out 120ms forwards;
  }

  .esp-dots.js-deck-dots .esp-dot { scale: 0; }
  .esp-dots.js-deck-dots.is-in .esp-dot {
    animation: espVineta .45s cubic-bezier(.16, 1, .3, 1) forwards;
    animation-delay: calc(var(--d, 0) * 40ms + 430ms);
  }
  .esp-dots .esp-dot:nth-child(1) { --d: 0; }
  .esp-dots .esp-dot:nth-child(2) { --d: 1; }
  .esp-dots .esp-dot:nth-child(3) { --d: 2; }
  .esp-dots .esp-dot:nth-child(4) { --d: 3; }
  .esp-dots .esp-dot:nth-child(5) { --d: 4; }
  .esp-dots .esp-dot:nth-child(6) { --d: 5; }
  .esp-dots .esp-dot:nth-child(7) { --d: 6; }
  .esp-dots .esp-dot:nth-child(8) { --d: 7; }
  .esp-dots .esp-dot:nth-child(9) { --d: 8; }
}
@keyframes espMazo   { to { translate: 0 0; scale: 1; } }
@keyframes espVineta { to { scale: 1; } }

@keyframes navEntra { to { opacity: 1; transform: none; } }
@keyframes heroRise { to { transform: translateY(0); } }
@keyframes ltrIn    { to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes conjSube  { to { translate: 0 0; } }
@keyframes conjFunde { to { opacity: 1; } }

/* ============================================================
   HERO CON VIDEO  (14-ago-2026, aprobado por Jonathan)
   Antes el ícono venía HORNEADO dentro del bitmap de portada. Ahora es un
   <video> con canal alfa encima del fondo, y el fondo pasa a ser el mismo
   bitmap SIN el ícono (hero-fondo-horizontal / -vertical).
   Estas reglas vivían en assets/css/hero-video-2.css, la hoja suelta de la
   página de prueba. Se traen aquí para que producción no cargue una segunda
   hoja: el hero es el elemento más grande de la primera pantalla y una
   petición más de CSS lo retrasa.

   EL PROBLEMA
   El fondo va con object-fit:cover, así que se recorta distinto en cada
   proporción de pantalla. Mientras el ícono estaba horneado se recortaba
   junto con él y la composición "frase + ícono" siempre calzaba. Con el
   ícono aparte, ponerle cover también solo funcionaría si video y fondo
   tuvieran la MISMA proporción — cierto en desktop, falso en vertical.

   LA SOLUCIÓN
   No se recorta el video: se ANCLA AL ÍCONO. Se calcula dónde y de qué
   tamaño tiene que quedar el ícono —tomando como verdad el hero aprobado—
   y se dimensiona y centra el video para que su ícono caiga justo ahí. Como
   el resto del cuadro es transparente, que el video se salga de la pantalla
   da igual: .hero ya recorta con overflow.

   LAS MEDIDAS (a 1:1 de los propios archivos)
     hero-desktop.webp  1920×1080 → ícono 627×511, centro (958, 543)
     hero-portrait.webp 1080×1920 → ícono 599×484, centro (531, 993.5)
     chaman-hero-v2.*   1560×1170 → ícono 1460×1124, centro (751, 570)
   Los fondos de Mafer son esos mismos bitmaps sin el ícono: difieren en un
   7% de píxeles y ese 7% es el recuadro del ícono.

   LAS CUENTAS
     s = escala cover del fondo = max(100vw/bw, 100svh/bh)
     k = escala a la que dibujar el video = s · (icw / viw)
     centro en pantalla = 50vw + (icx − bw/2)·s − (vix − vw/2)·k
   ============================================================ */

.hero--video {
  --vw: 1560; --vh: 1170;       /* cuadro del video */
  --vix: 751; --viy: 570;       /* centro de su ícono */
  --viw: 1460;                  /* ancho de su ícono */
  --s: max(calc(100vw / var(--bw)), calc(100svh / var(--bh)));
  --k: calc(var(--s) * var(--icw) / var(--viw));
}

/* Desktop y tablet horizontal: manda el fondo 1920×1080.
   --icx va 20 px a la izquierda del horneado (958 → 938) por criterio de
   Jonathan. En px de DISEÑO, así el empujón escala con --s. */
@media (min-width: 1024px) {
  .hero--video { --bw: 1920; --bh: 1080; --icx: 938; --icy: 543;   --icw: 627; }
}

/* ---- Vertical, en DOS tramos ----
   No es el mismo problema arriba y abajo, y se ve en la medición real:

     viewport        ícono      hueco arriba   hueco abajo
     768×1024        426×328       −1,1 px       −34,8 px
     430×932         291×224      +30,7 px       +12,2 px
     393×852         266×205      +27,5 px       +11,7 px

   (huecos entre el borde del ícono y la caja de línea de «Ideas» y «Para»;
   en negativo se solapan.)
   En TABLET el ícono no cabe entre los dos grupos del titular y se monta
   sobre «Para»: hay que subirlo. En MÓVIL sí cabe pero cuelga, y además se
   ve pequeño para el cuerpo de letra: hay que agrandarlo y centrarlo.
   Los dos tramos juntos cubren exactamente ≤1023, sin hueco ni solape. */

/* Tablet vertical: --icy 993.5 → 960 son 33,75 px de diseño, que a 768 de
   ancho (escala 0,7111) son los 24 px de pantalla que pidió Jonathan. */
@media (min-width: 768px) and (max-width: 1023px) {
  .hero--video { --bw: 1080; --bh: 1920; --icx: 531; --icy: 960;   --icw: 599; }
}

/* Móvil: --icw +10% y --icy sube 17,75 px de diseño. Lo segundo NO es un
   retoque suelto: al crecer, el ícono se expande igual hacia arriba y hacia
   abajo, y abajo solo había 11,7 px — sin subirlo quedaría a 1,7 px de
   «Para». Subiéndolo, los dos huecos quedan en ~10 px. */
@media (max-width: 767px) {
  .hero--video { --bw: 1080; --bh: 1920; --icx: 531; --icy: 976;   --icw: 659; }
}

.hero--video .hero-vid {
  position: absolute;
  z-index: 2;                    /* encima de la frase (.hero-title va en 1) */
  width: calc(var(--vw) * var(--k));
  left: calc(50vw  + (var(--icx) - var(--bw) / 2) * var(--s)
                   - (var(--vix) - var(--vw) / 2) * var(--k));
  top:  calc(50svh + (var(--icy) - var(--bh) / 2) * var(--s)
                   - (var(--viy) - var(--vh) / 2) * var(--k));
  transform: translate(-50%, -50%);
  pointer-events: none;          /* no debe estorbar al cursor ni al scroll */
}
.hero--video .hero-vid__el { display: block; width: 100%; height: auto; }

/* El indicador de scroll tiene que quedar por encima del cuadro del video,
   que es enorme y transparente pero igual se interpondría. */
.hero--video .scroll-hint { z-index: 3; }

/* Entrada: el video se funde junto con la portada, colgando de las mismas
   clases que el resto del hero, así entra sincronizado y no antes. */
@media (prefers-reduced-motion: no-preference) {
  .js .hero--video .hero-vid { opacity: 0; transition: opacity .9s ease-out; }
  .js.hero-listo .hero--video .hero-vid { opacity: 1; }
}

/* Respaldo sin animación: se retira el video y vuelve el bitmap con el ícono
   horneado, que es la composición aprobada. */
@media (prefers-reduced-motion: reduce) {
  .hero--video .hero-vid { display: none; }
  .hero--video .hero-cover img { content: url('../img/hero-desktop.webp'); }
}
@media (prefers-reduced-motion: reduce) and (max-width: 1023px) {
  .hero--video .hero-cover img { content: url('../img/hero-portrait.webp'); }
}
