/* ===========================================================================
   IDC Studios · web — las secciones de la página.
   Los tokens, las piezas comunes y el movimiento están en idc.css.
   =========================================================================== */

/* ---------------------------------------------------------------- estructura */
.ancho { width: min(var(--ancho), 100%); margin-inline: auto; padding-inline: var(--edge); }
.seccion { padding-block: var(--aire); }
/* Al llegar por un ancla, el `scroll-padding-top` del html deja la sección
   bajo la barra; este margen NEGATIVO se come el aire de arriba de la
   sección, así que lo que queda justo bajo la barra es el rótulo y el
   título, no una pantalla de vacío. */
.seccion.ancho { scroll-margin-top: calc(28px - var(--aire)); }
.seccion + .seccion { border-top: 1px solid var(--line-faint); }
/* La medida NO se le pone al contenedor: un titular de 100 px dentro de una
   caja de 30ch del texto base sale en seis líneas. Cada pieza lleva la suya,
   contada con SU propio tamaño de letra. */
.seccion__cab { margin-bottom: clamp(34px, 5vw, 64px); }
.seccion__cab h1 { max-width: 15ch; }
.seccion__cab h2 { max-width: 19ch; }
.seccion__cab .lead, .seccion__cab .chica { max-width: 52ch; }
/* la cabecera con el enlace a un lado */
.cab-fila {
  display: flex; flex-wrap: wrap; gap: 20px 32px;
  align-items: flex-end; justify-content: space-between;
  margin-bottom: clamp(34px, 5vw, 64px);
}
.cab-fila .seccion__cab { margin-bottom: 0; }

/* ---------------------------------------------------------------- barra */
.barra {
  position: sticky; top: 0; z-index: 40; min-height: var(--barra-h);
  background: rgba(7, 10, 15, .72); backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.barra.is-baja { border-bottom-color: var(--line-faint); background: rgba(7, 10, 15, .92); }
.barra__fila { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; min-height: var(--barra-h); }
.barra__esp { flex: 1; }
.menu { display: flex; align-items: center; gap: 2px; }
.menu a {
  color: var(--muted); text-decoration: none; font-size: 14.5px; font-weight: 500;
  padding: 9px 13px; border-radius: var(--r-chip); white-space: nowrap;
  transition: color var(--dur-corta) var(--ease), background-color var(--dur-corta) var(--ease);
}
.menu a:hover { color: var(--ink); background: rgba(140, 170, 215, .08); }
.menu a[aria-current="page"] { color: var(--ink); }
.menu-btn { display: none; }
/* En el móvil el botón de las páginas de texto no cabía junto a la marca y
   bajaba a una segunda fila: se ve «Volver» y el lector de pantalla oye la
   frase entera. */
@media (max-width: 400px) {
  .barra__largo { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

@media (max-width: 940px) {
  .barra .btn--cta { display: none; }
  .menu {
    order: 3; width: 100%;
    flex-direction: column; align-items: stretch; gap: 2px;
    padding: 6px 0 16px; border-top: 1px solid var(--line-faint);
  }
  .menu a { padding: 13px 12px; font-size: 16px; }
  /* El botón de plegar sólo existe si hay JavaScript: sin él, plegar el menú
     lo dejaría inalcanzable. Por eso cuelga de `.js`, que pone el propio
     HTML; sin JavaScript el menú se queda desplegado y todo se alcanza. */
  .js .menu-btn {
    display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px;
    border-radius: var(--r-chip); border: 1px solid var(--line); background: transparent;
    color: var(--ink); font: 500 14px var(--f-body); cursor: pointer;
  }
  .js .menu-btn:hover { border-color: rgba(140, 170, 215, .5); }
  .js .menu { display: none; }
  .js .menu[data-abierto="si"] { display: flex; }
  /* Con JavaScript el menú se abre ENCIMA de la página y no dentro de la
     barra: en el flujo empujaba todo 277 px, descolocaba las secciones fijadas
     (ScrollTrigger no se entera) y al cerrarlo el scroll volvía atrás. La
     barra es `sticky`, así que es la caja de referencia del `absolute`. Sin
     JavaScript sigue desplegado en el flujo, como antes. */
  .js .menu {
    position: absolute; top: 100%; left: 0; right: 0;
    padding: 6px var(--edge) 16px;
    background: rgba(7, 10, 15, .97);
    border-bottom: 1px solid var(--line-faint);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .45);
    max-height: calc(100svh - var(--barra-h)); overflow-y: auto; overscroll-behavior: contain;
  }
}

/* ================================================================= portada
   La primera pantalla entera: la rejilla de la marca de fondo, a lo ancho,
   y el texto encima. */
.portada {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: calc(100svh - var(--barra-h));
  display: flex; flex-direction: column; justify-content: center;
  padding-block: clamp(56px, 8vw, 96px) clamp(40px, 6vw, 72px);
}
.portada__cuerpo { position: relative; z-index: 1; width: 100%; }
.portada h1 { max-width: 16ch; }
.portada .lead { max-width: 50ch; margin-bottom: 30px; }
.portada .acciones { margin-bottom: clamp(44px, 7vw, 76px); }

/* la rejilla de fondo. Sin JavaScript esto es lo que se ve: la rejilla de la
   marca, quieta y dibujada en CSS; no es un hueco esperando un canvas. */
.portada__fondo {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    repeating-linear-gradient(90deg, #131a26 0 18px, transparent 18px 26px),
    repeating-linear-gradient(0deg, #131a26 0 12px, transparent 12px 20px),
    var(--bg);
  background-blend-mode: multiply;
}
#rejilla { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* El velo que protege el texto: fuerte (.76) bajo la columna de texto, más
   claro hacia la derecha, donde no hay nada escrito, y cerrado abajo para
   fundirse con la sección siguiente. El .76 no es a ojo: es el que deja
   el eyebrow azul por encima de 4,5:1 sobre la celda más clara que puede
   pintar el lienzo (azul o verde al 60 %). Ver el comentario del lienzo
   en efectos.js. */
.portada__fondo::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(7, 10, 15, .25), transparent 22%, transparent 78%, var(--bg)),
    linear-gradient(90deg, rgba(7, 10, 15, .76) 0 58%, rgba(7, 10, 15, .5) 76%, rgba(7, 10, 15, .22));
}
@media (max-width: 900px) {
  /* en pantalla estrecha el texto ocupa todo el ancho: el velo va parejo */
  .portada__fondo::after {
    background:
      linear-gradient(180deg, rgba(7, 10, 15, .25), transparent 22%, transparent 78%, var(--bg)),
      rgba(7, 10, 15, .76);
  }
}

/* La cabeza (assets/js/cabeza.js). En escritorio sale de abajo a la derecha,
   donde el velo es más claro y no hay texto; en el móvil va debajo de las
   cifras, centrada, apoyada en el borde de la portada. Los hombros se funden
   con la sección siguiente (máscara), como el velo del fondo. */
.cabeza {
  position: absolute; z-index: 0; bottom: 0; pointer-events: none;
  /* La portada va a todo el ancho (.portada__cuerpo), así que la cabeza se
     alinea con su borde, no con el del contenedor centrado. */
  right: var(--edge);
  width: min(30vw, 520px); aspect-ratio: 480 / 560;
  -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 98%);
  mask-image: linear-gradient(180deg, #000 72%, transparent 98%);
}
.cabeza::before {
  content: ""; position: absolute; inset: 4% -14% 10%;
  background: radial-gradient(closest-side, rgba(79, 140, 255, .13), rgba(7, 10, 15, .55) 62%, transparent);
}
.cabeza__foto, .cabeza__lienzo { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.cabeza--viva .cabeza__foto { visibility: hidden; }
/* En escritorio el titular se achica un poco para dejarle sitio a la cabeza:
   lo blanco del titular sobre la porcelana no se lee. */
@media (min-width: 901px) {
  .portada h1 { font-size: clamp(38px, 7.1vw, 96px); }
}
@media (max-width: 900px) {
  .cabeza {
    position: relative; right: auto; bottom: auto; align-self: center;
    width: min(72vw, 320px);
    margin: clamp(28px, 6vw, 44px) auto calc(-1 * clamp(40px, 6vw, 72px));
  }
}

/* las tres cifras de la portada. Van acotadas a la columna de texto para
   quedar bajo la parte fuerte del velo. */
.cifras {
  list-style: none; margin: clamp(40px, 6vw, 68px) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 24px;
}
.portada .cifras { max-width: 720px; }
.cifra { display: grid; gap: 4px; }
/* Las cifras en Newsreader (v2): números de texto, no de tabla. */
.cifra > b {
  font-family: var(--f-editorial); font-weight: 500; color: var(--ink);
  font-size: clamp(30px, 5.2vw, 56px); line-height: 1; letter-spacing: -0.02em;
  font-variant-numeric: lining-nums tabular-nums;
}
.cifra > span { color: var(--muted); font-size: clamp(12.5px, 1.2vw, 14.5px); }
@media (max-width: 560px) {
  .cifras { grid-template-columns: 1fr; gap: 16px; }
  .cifra { grid-template-columns: auto 1fr; align-items: baseline; gap: 12px; }
}

/* ============================================================== servicios */
.servicios { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.servicio {
  --imx: 0px; --imy: 0px; --lift: 0px;
  display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 8px clamp(24px, 4vw, 56px);
  align-items: start;
  padding: clamp(22px, 3vw, 32px) clamp(20px, 3vw, 30px);
  border: 1px solid var(--line-faint); border-radius: var(--r);
  background: rgba(18, 24, 34, .5);
  transform: translate3d(var(--imx), calc(var(--imy) + var(--lift)), 0);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
              opacity .4s var(--ease-out);
}
.servicio:hover { border-color: var(--line); --lift: -3px; }
.servicio__rotulo {
  grid-row: span 2; margin: 0; color: var(--accent);
  font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; padding-top: 4px;
}
.servicio h3 { margin: 0 0 6px; }
.servicio > p:last-child { margin: 0; color: var(--muted); max-width: 58ch; }
@media (max-width: 720px) {
  .servicio { grid-template-columns: 1fr; gap: 10px; }
  .servicio__rotulo { grid-row: auto; padding-top: 0; }
}

/* ================================================================ el caso */
.caso { position: relative; }
.caso__marco {
  border: 1px solid var(--line-faint); border-radius: var(--r);
  padding: clamp(26px, 4.5vw, 56px);
  background: linear-gradient(180deg, rgba(79, 140, 255, .05), rgba(18, 24, 34, .45));
}
.caso__cab { max-width: 60ch; }
.caso__cab h2 { margin-bottom: 14px; }
.caso__cab .lead { max-width: 58ch; }
.cifras--caso {
  margin: clamp(28px, 4vw, 44px) 0; padding: clamp(22px, 3vw, 28px) 0;
  border-block: 1px solid var(--line-faint);
}
.cifra--caso > b { font-size: clamp(24px, 3.8vw, 40px); color: var(--accent); }
.puntos {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(20px, 3vw, 34px) clamp(24px, 4vw, 48px);
}
.punto h3 { color: var(--ink); }
.punto p { color: var(--muted); font-size: 14.8px; margin: 0; }
.caso__pie {
  margin: clamp(26px, 4vw, 40px) 0 0; padding-top: 22px;
  border-top: 1px solid var(--line-faint);
  color: var(--muted); font-size: 14px; max-width: 70ch;
}

/* ===================================================== trabajos destacados
   Filas grandes, no tarjetas iguales: cada una ocupa su ancho, se levanta al
   pasar por encima y enseña su dato (estado y líneas) en mono. */
.destacados, .trabajos { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }

.destacado, .trabajo {
  --imx: 0px; --imy: 0px; --lift: 0px;
  position: relative;
  border-top: 1px solid var(--line-faint);
  transform: translate3d(var(--imx), calc(var(--imy) + var(--lift)), 0);
  transition: transform var(--dur) var(--ease), opacity .4s var(--ease-out),
              border-color var(--dur) var(--ease);
}
.destacados > :last-child, .trabajos > :last-child { border-bottom: 1px solid var(--line-faint); }
.destacado:hover, .trabajo:hover { --lift: -3px; border-color: var(--line); }

/* -- la fila corta de la portada */
.destacado {
  display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 11rem);
  gap: 10px clamp(24px, 3.5vw, 48px);
  align-items: start; padding: clamp(24px, 3.2vw, 34px) clamp(14px, 2vw, 22px);
}
.destacado__titulo { margin: 0 0 6px; }
/* El título enlaza (a su fila en /trabajos, o a la landing del proyecto) y
   es lo ÚNICO de la tarjeta sobre lo que el cursor dice «Ver». Se ve como
   título, no como enlace azul: la fila entera ya se levanta al pasar. */
.destacado__titulo a, .trabajo__titulo a {
  color: inherit; text-decoration: none;
  text-decoration-color: transparent; text-underline-offset: .18em;
  transition: text-decoration-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.destacado__titulo a:hover, .trabajo__titulo a:hover,
.destacado__titulo a:focus-visible, .trabajo__titulo a:focus-visible {
  text-decoration: underline; text-decoration-color: var(--accent);
}
.destacado__stack { margin: 0; color: var(--muted-2); font-size: 11.5px; letter-spacing: .02em; }
.destacado__texto { margin: 0; color: var(--muted); font-size: 14.8px; }
.destacado__meta { display: grid; gap: 10px; justify-items: start; }
.destacado__lineas { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.destacado__lineas b { color: var(--ink-2); font-weight: 500; }
@media (max-width: 900px) {
  .destacado { grid-template-columns: 1fr; gap: 12px; }
  .destacado__meta { grid-auto-flow: column; justify-content: start; align-items: center; gap: 14px; }
}

/* -- la fila completa de /trabajos */
.trabajo {
  display: grid; grid-template-columns: 3.4rem minmax(0, 1fr) minmax(0, 11rem);
  gap: 12px clamp(20px, 3vw, 44px);
  align-items: start; padding: clamp(26px, 3.4vw, 40px) clamp(14px, 2vw, 22px);
}
.trabajo__n { color: var(--muted-2); font-size: 13px; padding-top: .45em; }
.trabajo__titulo { font-size: clamp(20px, 2.4vw, 28px); line-height: 1.12; margin: 0 0 10px; letter-spacing: -.02em; }
.trabajo__resumen { margin: 0 0 12px; color: var(--muted); max-width: 62ch; }
.trabajo__stack { margin: 0; color: var(--muted-2); font-size: 11.5px; letter-spacing: .02em; }
.trabajo__acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin: 16px 0 0; }
.trabajo__meta { display: grid; gap: 12px; justify-items: start; }
.trabajo__lineas { display: grid; gap: 1px; }
.trabajo__lineas b {
  font-weight: 500; color: var(--ink); font-size: clamp(19px, 2vw, 25px);
  line-height: 1; letter-spacing: -.02em;
}
.trabajo__lineas > span { color: var(--muted); font-size: 12px; }
@media (max-width: 860px) {
  .trabajo { grid-template-columns: 2.6rem minmax(0, 1fr); }
  /* En una fila, pero que PUEDA partirse: a 320 px el chip y el número no
     caben juntos y se salían de la pantalla. */
  .trabajo__meta {
    grid-column: 2; display: flex; flex-wrap: wrap; justify-content: flex-start;
    align-items: center; gap: 10px 16px; margin-top: 4px;
  }
  .trabajo__lineas { grid-auto-flow: column; align-items: baseline; gap: 6px; }
  .trabajo__lineas b { font-size: 17px; }
}

.enlace-demo {
  --imx: 0px; --imy: 0px;
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--accent); text-decoration: none; font-weight: 500; font-size: 14.5px;
  transform: translate3d(var(--imx), var(--imy), 0);
  transition: transform var(--dur) var(--ease), color var(--dur) var(--ease);
}
.enlace-demo:hover { text-decoration: underline; }
.enlace-demo svg { width: 15px; height: 15px; flex: none; }

/* la leyenda de estados de /trabajos */
.leyenda {
  list-style: none; margin: 0 0 clamp(26px, 4vw, 40px); padding: 0;
  display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center;
}
.leyenda li { display: inline-flex; }

/* ========================================================== cómo trabajamos */
.pasos {
  list-style: none; counter-reset: paso; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: clamp(24px, 3.4vw, 42px) clamp(26px, 4vw, 56px);
}
.pasos li { counter-increment: paso; padding-top: 22px; position: relative; }
/* la línea de arriba se DIBUJA de izquierda a derecha cuando el paso entra
   (transform, no width). Sin `anima` está entera desde el principio. */
.pasos li::after, .ciudad::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--line-faint); transform-origin: 0 50%;
}
.anima .pasos li[data-reveal]::after, .anima .ciudad[data-reveal]::after {
  transform: scaleX(0); transition: transform .8s var(--ease-out) .12s;
}
.anima .pasos li[data-reveal].es-visible::after, .anima .ciudad[data-reveal].es-visible::after { transform: scaleX(1); }
.pasos li::before {
  content: counter(paso, decimal-leading-zero);
  display: block; font-family: var(--f-mono); font-size: 12px; color: var(--accent);
  letter-spacing: .1em; margin-bottom: 12px;
}
.pasos h3 { margin-bottom: 7px; }
.pasos p { color: var(--muted); margin: 0; font-size: 14.8px; }

/* ================================================================ contacto */
.contacto { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(28px, 5vw, 64px); align-items: start; }
@media (max-width: 880px) { .contacto { grid-template-columns: 1fr; } }
.correo {
  font-family: var(--f-mono); font-size: clamp(16px, 2.6vw, 24px); color: var(--accent);
  text-decoration: none; word-break: break-word; font-weight: 500;
  display: inline-block; transition: transform var(--dur) var(--ease);
}
.correo:hover { text-decoration: underline; transform: translateX(3px); }
.formulario { display: grid; gap: 18px; }
.formulario h3 { margin: 0; }
.aviso-js {
  border: 1px dashed var(--line); border-radius: var(--r-chico); padding: 12px 15px;
  color: var(--muted); font-size: 14px;
}

/* las ciudades */
.ciudades {
  list-style: none; margin: clamp(30px, 4vw, 44px) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 18px 28px;
}
.ciudad { display: grid; gap: 3px; padding-top: 18px; position: relative; }
.ciudad > b { font-family: var(--f-display); font-size: clamp(19px, 2.2vw, 25px); color: var(--ink); font-weight: 600; letter-spacing: -.02em; }
.ciudad__pais { font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--accent); }
.ciudad > span:last-child { color: var(--muted); font-size: 14px; }

/* ===================================================================== pie */
.pie { border-top: 1px solid var(--line-faint); padding-block: clamp(34px, 5vw, 56px) 44px; }
.pie__fila {
  display: flex; flex-wrap: wrap; gap: 16px 28px; align-items: center;
  justify-content: space-between; color: var(--muted); font-size: 13.5px;
}
.pie__enlaces { display: flex; flex-wrap: wrap; gap: 10px 22px; align-items: center; }
.pie a { color: var(--muted); text-decoration: underline; transition: color var(--dur-corta) var(--ease); }
.pie a:hover { color: var(--ink); }
.pie__nota { margin: 18px 0 0; color: var(--muted-2); font-size: 12.5px; max-width: 60ch; }
.pie__derechos { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
/* El pie se DESCUBRE debajo del contenido: queda pegado al fondo de la
   ventana y `main`, que lleva fondo opaco, se desliza por encima hasta
   dejarlo a la vista (criterio de Uncommon y de Eszter Bial). Es sólo
   `position: sticky`: nada se anima y sin movimiento el pie es un pie. */
html[data-motor="completo"] .pie, html[data-motor="liviano"] .pie { position: sticky; bottom: 0; z-index: 0; }
/* la puerta del panel del creador: discreta, pero alcanzable */
.pie__entrar {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--muted-2); text-decoration: none; font-family: var(--f-mono);
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--line-faint); border-radius: var(--r-chip); padding: 7px 14px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.pie__entrar:hover { color: var(--ink); border-color: var(--line); text-decoration: none; }
.pie__entrar svg { width: 13px; height: 13px; }
/* Con el dedo, 44 px de alto en todo lo que se toca (WCAG 2.5.5). Con ratón
   el pie sigue siendo una línea discreta. */
@media (pointer: coarse) {
  .marca { min-height: 44px; }
  .pie__enlaces { gap: 0 16px; }
  .pie__enlaces a { display: inline-flex; align-items: center; min-height: 44px; }
  .enlace-demo { min-height: 44px; }
  .btn--chico { min-height: 44px; }
  .correo { padding-block: 9px; }
}

/* ------------------------------------------------ páginas de texto (aviso legal) */
.texto { max-width: 70ch; }
.texto h1 { font-size: clamp(32px, 5.4vw, 60px); }
.texto h2 { font-size: clamp(20px, 2.6vw, 26px); margin-top: 44px; }
.texto h2:first-of-type { margin-top: 30px; }
.texto p, .texto li { color: var(--muted); }
.texto ul { padding-left: 22px; display: grid; gap: 8px; margin: 0 0 16px; }
.texto strong { color: var(--ink-2); }
.texto code { font-family: var(--f-mono); font-size: .9em; }

/* ===================================================== la frase que se dispersa
   Por defecto NO pasa nada: es un párrafo grande con la frase entera, que se
   lee sin JavaScript, sin motor y con `prefers-reduced-motion`. La altura de
   más y el `sticky` los enciende efectos.js con `.es-viva`, así que nunca hay
   dos pantallas y media de vacío esperando a un script. */
.dispersion { padding-block: var(--aire); border-top: 1px solid var(--line-faint); }
.dis-frase {
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(27px, 4.4vw, 54px); line-height: 1.08; letter-spacing: -.03em;
  color: var(--ink); max-width: 22ch; margin: 0;
}
.dis-pal { display: inline-block; will-change: auto; }
.dis-pal[data-queda="si"] { color: var(--accent); }

/* `svh` y no `vh`: en un móvil `100vh` es la pantalla CON la barra del
   navegador escondida, y lo fijo pega saltos cuando aparece. */
/* `overflow-x: clip` y no `hidden`: las palabras vuelan más allá del borde
   y sin esto ensanchaban el documento (525 px en un móvil de 390). `hidden`
   convertiría la sección en un contenedor de scroll y el `sticky` de dentro
   dejaría de pegarse a la ventana. */
.dispersion.es-viva { height: 260svh; padding-block: 0; overflow-x: clip; }
.dispersion.es-viva .dis-fijo {
  position: sticky; top: 0; height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
}
/* `--p` va de 0 a 1 con el scroll, y lo escribe efectos.js. Las tres que
   quedan crecen y se separan un punto; las demás se van, cada una por su
   lado, con su propio `transform` en línea. */
.dispersion.es-viva .dis-frase { max-width: 26ch; }
.dispersion.es-viva .dis-pal { will-change: transform, opacity; }
/* Aquí había un `letter-spacing` que crecía con el scroll. Parecía inofensivo
   y era el fallo: `letter-spacing` RECALCULA EL DISEÑO, así que al ensanchar
   las tres palabras la frase cortaba las líneas en otro sitio, y los destinos
   —medidos sobre el diseño de antes— mandaban las palabras a donde ya no
   estaban. Es literalmente la regla de esta web: sólo `transform` y
   `opacity`. No volver a poner nada aquí que mueva una caja. */

/* =============================================================== la cita
   Un momento propio: fondo limpio, tipografía grande y nada más. */
.cita__caja { margin: 0; max-width: 24ch; }
.cita blockquote { margin: 0; }
.cita blockquote p {
  font-family: var(--f-display); font-weight: 600; color: var(--ink);
  font-size: clamp(30px, 5.4vw, 64px); line-height: 1.02; letter-spacing: -.035em;
  margin: 0;
}
.cita blockquote p::before { content: "«"; color: var(--muted-2); }
.cita blockquote p::after { content: "»"; color: var(--muted-2); }
.cita figcaption {
  margin-top: 22px; font-family: var(--f-mono); font-size: 13px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}

/* ============================================ la tira de trabajos, de lado
   Por defecto es la lista vertical de siempre. Con `.es-viva` (escritorio
   ancho y motor completo) la sección se queda fija y la tira avanza en
   horizontal mientras se baja, píxel a píxel: el alto de la sección es
   exactamente lo que sobra de tira, así que la barra de scroll no miente. */
.tira { padding-block: var(--aire); }
.tira.es-viva { padding-block: 0; }
.tira.es-viva .tira__fijo {
  position: sticky; top: 0; height: 100svh;
  display: flex; flex-direction: column; justify-content: center; gap: 34px;
  overflow: hidden;
}
.tira.es-viva .tira__pista { overflow: hidden; padding-block: 10px; }
.tira.es-viva .tira__carril {
  display: flex; flex-wrap: nowrap; gap: 20px;
  padding-inline: var(--edge); width: max-content;
  will-change: transform;
}
/* dentro del carril cada trabajo es una ficha de ancho fijo */
.tira.es-viva .destacado {
  flex: 0 0 clamp(280px, 26vw, 380px);
  grid-template-columns: 1fr; align-content: start;
  border: 1px solid var(--line-faint); border-radius: var(--r);
  background: rgba(18, 24, 34, .5); padding: clamp(22px, 2vw, 28px);
}
.tira.es-viva .destacados > :last-child { border-bottom: 1px solid var(--line-faint); }
.tira.es-viva .destacado__texto { font-size: 14.2px; }
/* una pista de cuánto queda de tira, que también dice que hay que seguir bajando */
.tira.es-viva .tira__fijo::after {
  content: ""; position: absolute; left: var(--edge); right: var(--edge); bottom: 46px;
  height: 2px; border-radius: 2px; background: var(--line-faint);
  background-image: linear-gradient(90deg, var(--accent) 0 calc(var(--p, 0) * 100%),
                    transparent calc(var(--p, 0) * 100%));
}

/* ============================================ las secciones apiladas
   Sólo con `.es-viva`, que pone efectos.js (nunca sin movimiento). Cada
   sección se pega (`--pegado`: 0, o negativo si es más alta que la
   pantalla, para pegarse por abajo) y la siguiente entra por encima. La de
   abajo se encoge y se oscurece según `--tapa` (0-1), que también escribe
   efectos.js con el scroll. Fondo opaco a propósito: la de abajo no tiene
   que verse a través de la que entra. Sólo `transform` y `opacity`. */
.pila.es-viva { background: var(--bg-deep); }
.pila.es-viva > * {
  position: sticky; top: var(--pegado, 0px);
  background: var(--bg);
  transform-origin: 50% 40%;
  transform: scale(calc(1 - .06 * var(--tapa, 0)));
  will-change: transform;
}
.pila.es-viva > *::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: var(--bg-deep); opacity: calc(.6 * var(--tapa, 0));
}
/* la línea que separa secciones se lleva la sección que ENTRA, no la pila */
.pila.es-viva > .seccion + .seccion { border-top-color: var(--line); }

/* ============================================ el pliegue de las filas
   Con `html.pliega` (efectos.js, sólo con movimiento) cada fila de
   /trabajos se dobla cuando ya se leyó: `--pliegue` va de 0 a 1 con el
   scroll. La bisagra es el borde de ABAJO de la fila —la línea que la
   separa de la siguiente— y la parte de arriba se va hacia adentro de la
   pantalla, como una hoja que se tumba hacia atrás. Con la bisagra arriba
   quedaba un hueco entre la fila plegada y la siguiente; así la fila
   siguiente sigue pegada a la línea. La perspectiva es por fila y la
   sombra crece con el mismo número, más oscura cuanto más lejos.

   El `transform` junta en uno el pliegue, el imán (`--imx/--imy`), el
   hover (`--lift`) y la entrada (`--rev`, que antes ponía `[data-reveal]`
   con su propio `transform` y pisaba a los demás). Mientras se pliega no
   hay transición sobre `transform`: va atado al scroll, un píxel es un
   píxel. */
.pliega .trabajo { --rev: 0px; transform-origin: 50% 100%; }
.pliega.anima .trabajo[data-reveal] { --rev: 18px; }
.pliega.anima .trabajo[data-reveal].es-visible { --rev: 0px; }
.pliega .trabajo[data-reveal], .pliega .trabajo[data-reveal].es-visible {
  transform: perspective(1100px) rotateX(calc(var(--pliegue, 0) * 74deg))
             translate3d(var(--imx), calc(var(--imy) + var(--lift) + var(--rev)), 0);
}
.pliega .trabajo.es-plegada, .pliega.anima .trabajo.es-plegada[data-reveal].es-visible {
  transition: opacity .4s var(--ease-out), border-color var(--dur) var(--ease);
}
.pliega .trabajo::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: var(--pliegue, 0);
  background: linear-gradient(180deg, rgba(4, 6, 10, .92), rgba(4, 6, 10, .45) 60%, rgba(4, 6, 10, .12));
}

/* ============================================ la cinta de tecnologías
   Sin movimiento: una lista en varias líneas, entera y quieta. Con
   `.es-viva` (efectos.js duplica la pista) corre de lado en bucle, con
   `transform` y sin costura, y se para al pasar el ratón por encima. Con
   el reloj parado se ve la primera copia entera. */
.cinta {
  margin-top: clamp(40px, 6vw, 72px); padding-top: 22px;
  border-top: 1px solid var(--line-faint);
}
.cinta__rotulo {
  margin: 0 0 14px; font-family: var(--f-mono); font-size: 11.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted-2);
}
.cinta__ventana { display: flex; }
.cinta__pista {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px 26px;
  font-family: var(--f-mono); font-size: 13px; color: var(--muted); white-space: nowrap;
}
.cinta__pista li::before { content: "·"; color: var(--accent); margin-right: 10px; }
/* Los bordes se funden con dos degradados encima y NO con `mask-image`:
   una máscara sobre un `transform` animado, dentro de una sección pegada y
   escalada, hacía que el compositor pintara ahí un trozo de otra parte de
   la página (visto en Edge: la barra repetida a media pantalla). */
.cinta.es-viva { overflow: hidden; position: relative; }
.cinta.es-viva::before, .cinta.es-viva::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 8%; z-index: 1; pointer-events: none;
}
.cinta.es-viva::before { left: 0; background: linear-gradient(90deg, var(--bg), transparent); }
.cinta.es-viva::after { right: 0; background: linear-gradient(270deg, var(--bg), transparent); }
.cinta.es-viva .cinta__ventana { width: max-content; animation: idc-cinta 48s linear infinite; }
.cinta.es-viva:hover .cinta__ventana { animation-play-state: paused; }
.cinta.es-viva .cinta__pista { flex-wrap: nowrap; padding-right: 26px; }
@keyframes idc-cinta { to { transform: translate3d(-50%, 0, 0); } }

/* ===========================================================================
   TERCERA VUELTA (23-sep-2026) — pantalla completa y movimiento con GSAP.

   Lo que pidió Iván: que cada sección se sienta como una pantalla entera y
   limpia (nada de bordes a los costados ni cajas dentro de cajas), secciones
   que no se muevan todas igual, y al final de la página seguir bajando te
   lleva a la siguiente. El movimiento lo lleva assets/js/movimiento.js con
   GSAP + ScrollTrigger + Lenis, y SÓLO cuando <html> tiene `gs-vivo`: sin
   JavaScript, sin las librerías o con `prefers-reduced-motion`, todo lo de
   abajo es una página normal que se lee de corrido.
   =========================================================================== */

/* Sin separadores entre secciones: el cambio lo marca el movimiento. */
.seccion + .seccion, .dispersion { border-top: 0; }
html[data-motor="completo"] .pie, html[data-motor="liviano"] .pie { position: static; }

/* Lenis: el scroll suave no debe pelearse con el `scroll-behavior` nativo. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

/* --------------------------------------------------------- cómo trabajamos */
.pasos-h__cab h2 { max-width: 16ch; }
.pasos-h__pista {
  list-style: none; padding: 0 var(--edge);
  display: grid; gap: clamp(18px, 2.4vw, 30px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  width: min(var(--ancho), 100%); margin: clamp(28px, 4vw, 56px) auto 0;
}
.paso {
  position: relative; padding: clamp(24px, 3vw, 40px);
  border-radius: var(--r); background: linear-gradient(160deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line-faint); overflow: hidden;
}
.paso__n {
  display: block; font-size: clamp(52px, 7vw, 120px); line-height: .9; letter-spacing: -.04em;
  color: transparent; -webkit-text-stroke: 1px rgba(79, 140, 255, .55); margin-bottom: 18px;
}
.paso h3 { font-size: clamp(20px, 2vw, 28px); line-height: 1.15; margin-bottom: 12px; }
.paso p { color: var(--muted); margin: 0; font-size: clamp(15px, 1.2vw, 17px); line-height: 1.6; }
.pasos-h__pie { display: none; }

/* Con movimiento: la sección se queda fija y la pista corre de lado. */
.gs-vivo .pasos-h { padding-block: 0; }
.gs-vivo .pasos-h__fijo {
  height: 100svh; display: flex; flex-direction: column; justify-content: center;
  overflow: hidden; padding-top: var(--barra-h);
}
.gs-vivo .pasos-h__pista {
  display: flex; width: max-content; margin: clamp(22px, 3.5vh, 44px) 0 0;
  padding-inline: max(var(--edge), calc((100vw - var(--ancho)) / 2 + var(--edge)));
  gap: clamp(18px, 2.4vw, 32px); will-change: transform;
}
.gs-vivo .paso { width: min(78vw, 560px); min-height: min(50svh, 420px); flex: none; }
.gs-vivo .pasos-h__pie { display: block; margin-top: clamp(20px, 3.5vh, 40px); }
.pasos-h__barra { display: block; height: 2px; background: var(--line-faint); border-radius: 2px; overflow: hidden; }
.pasos-h__barra > span {
  display: block; height: 100%; background: var(--accent);
  transform-origin: 0 50%; transform: scaleX(0);
}
@media (max-height: 760px) {
  .gs-vivo .pasos-h__cab .lead { display: none; }
}
/* Si lo fijo no cabe, que sobre por ABAJO: con `center` a secas el
   rótulo y el título se iban debajo de la barra (320×568, horizontal). */
.gs-vivo .pasos-h__fijo { justify-content: safe center; }
/* Pantallas bajas: tarjetas compactas para que rótulo, título, tarjeta y
   barra de avance quepan en 100svh. */
@media (max-height: 640px) {
  .gs-vivo .pasos-h__fijo { padding-top: calc(var(--barra-h) + 12px); }
  .gs-vivo .pasos-h__cab .eyebrow { margin-bottom: 10px; }
  .gs-vivo .pasos-h__pista { margin-top: 16px; }
  .gs-vivo .paso { min-height: 0; padding: 20px 22px; }
  .gs-vivo .paso__n { font-size: 40px; margin-bottom: 10px; }
  .gs-vivo .pasos-h__pie { margin-top: 14px; }
}
/* El móvil en horizontal (360-430 px de alto). */
@media (max-height: 480px) {
  .gs-vivo .pasos-h__fijo { padding-top: calc(var(--barra-h) + 8px); }
  .gs-vivo .pasos-h__cab .eyebrow { display: none; }
  .gs-vivo .pasos-h__cab h2 { max-width: none; font-size: clamp(22px, 6.4vh, 28px); margin-bottom: 0; }
  .gs-vivo .paso { width: min(66vw, 560px); padding: 16px 22px; }
  .gs-vivo .paso__n { font-size: 28px; margin-bottom: 6px; }
  .gs-vivo .paso h3 { font-size: 18px; margin-bottom: 6px; }
  .gs-vivo .paso p { line-height: 1.5; }
}

/* ------------------------------------------------------ en qué se convierte */
.nube { position: relative; }
.nube__lienzo { display: none; }
.servicios-n { list-style: none; margin: clamp(28px, 4vw, 48px) 0 0; padding: 0; display: grid; gap: 26px; max-width: 520px; }
.servicio-n__rotulo { color: var(--accent); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; margin: 0 0 6px; }
.servicio-n h3 { font-size: clamp(19px, 1.8vw, 24px); margin-bottom: 6px; }
.servicio-n p:last-child { color: var(--muted); margin: 0; font-size: 15.5px; line-height: 1.6; }

.gs-vivo .nube { padding-block: 0; }
.gs-vivo .nube__fijo { position: relative; height: 100svh; overflow: hidden; display: flex; align-items: center; }
.gs-vivo .nube__lienzo { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
.gs-vivo .nube__texto { position: relative; z-index: 1; padding-top: var(--barra-h); pointer-events: none; }
.gs-vivo .nube__texto a { pointer-events: auto; }
.gs-vivo .servicios-n { gap: 12px; }
.gs-vivo .servicio-n {
  padding: 10px 0 10px 18px; border-left: 2px solid var(--line-faint);
  transition: border-color .4s var(--ease), opacity .4s var(--ease);
  opacity: .6;
}
.gs-vivo .servicio-n p:last-child {
  max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height .5s var(--ease-out), margin .5s var(--ease-out), opacity .4s var(--ease);
}
.gs-vivo .servicio-n.es-activo { opacity: 1; border-left-color: var(--accent); }
.gs-vivo .servicio-n.es-activo p:last-child { max-height: 9em; margin-top: 4px; opacity: 1; }
@media (max-width: 820px) and (max-aspect-ratio: 7/5) {
  .gs-vivo .nube__fijo { align-items: flex-end; }
  .gs-vivo .nube__texto {
    background: linear-gradient(0deg, rgba(7, 10, 15, .96) 62%, rgba(7, 10, 15, 0));
    padding-top: 48px; padding-bottom: 5svh;
  }
  .gs-vivo .nube__texto h2 { font-size: clamp(26px, 7vw, 34px); }
}

/* ----------------------------------------------------------------- la cita */
.zoom__cita { margin: 0 auto; width: min(var(--ancho), 100%); padding-inline: var(--edge); }
.zoom__cita blockquote { margin: 0; }
/* La cita va en Outfit aunque la v2 diga Newsreader para las citas: la cámara
   entra por el hueco de la «o», y el de Newsreader es angosto y ovalado, así
   que el círculo del portal pisaba el trazo (Iván lo vio el 7-oct-2026). Las
   comillas sí van en champán. */
.zoom__cita p {
  margin: 0; font-family: var(--f-display); font-weight: 600; color: var(--ink);
  font-size: clamp(46px, 9.4vw, 150px); line-height: .95; letter-spacing: -.045em; max-width: 13ch;
}
.zoom__cita p::before { content: "«"; color: var(--champan); }
.zoom__cita p::after { content: "»"; color: var(--champan); }
.zoom__cita figcaption { margin-top: 26px; font-family: var(--f-mono); color: var(--muted); letter-spacing: .12em; text-transform: uppercase; font-size: 13px; }
.zoom__portal { display: none; }

.gs-vivo .zoom { padding-block: 0; }
.gs-vivo .zoom__fijo { position: relative; height: 100svh; overflow: hidden; display: flex; align-items: center; }
.gs-vivo .zoom__cita { will-change: transform; }
.gs-vivo .zoom__portal {
  display: grid; place-items: center; position: absolute; inset: 0; z-index: 2;
  background: radial-gradient(120% 90% at 50% 40%, #0d1626, var(--bg) 70%);
  clip-path: circle(0px at var(--px, 50%) var(--py, 50%));
}
.zoom__portal-texto {
  font-family: var(--f-display); font-weight: 600; letter-spacing: -.04em;
  font-size: clamp(44px, 10vw, 160px); color: var(--ink); opacity: 0;
}

/* ------------------------------------------------------------ experiencia */
.exp__cab h2 { max-width: 14ch; font-size: clamp(34px, 6vw, 88px); line-height: .98; }
.caso-x { padding-block: clamp(48px, 8vw, 110px); }
.caso-x__fila {
  display: grid; gap: clamp(32px, 5vw, 80px); align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}
.caso-x--inverso .caso-x__fila { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
.caso-x--inverso .caso-x__texto { order: 2; }
.caso-x__rubro { color: var(--accent); font-size: 12px; letter-spacing: .1em; text-transform: uppercase; margin: 0 0 12px; }
.caso-x__titulo { font-size: clamp(36px, 5vw, 72px); line-height: 1; letter-spacing: -.035em; margin: 0 0 20px; }
.caso-x .puntos { margin-top: 28px; }
.caso-x__fotos { display: grid; gap: 22px; position: sticky; top: calc(var(--barra-h) + 24px); }
.foto { margin: 0; }
.foto__marco {
  border-radius: var(--r); overflow: hidden; border: 1px solid var(--line-faint);
  background: var(--panel); box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
}
.foto__marco img { display: block; width: 100%; height: auto; transform-origin: 50% 50%; }
.foto figcaption { margin-top: 10px; font-family: var(--f-mono); font-size: 12px; color: var(--muted-2); letter-spacing: .04em; }
.foto--corrida { width: 88%; margin-left: auto; }
.foto--alta { max-width: 460px; margin-inline: auto; }
.exp__pie { color: var(--muted-2); font-size: 13px; margin-top: 0; }
/* El móvil delante y el calendario detrás, asomando por la derecha. El
   teléfono lleva su marco (un bisel oscuro y esquinas de teléfono) para que se
   lea como una pantalla y no como otra tarjeta. */
.caso-x__fotos--movil {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: 0;
}
.foto--movil { position: relative; z-index: 2; }
.foto--movil .foto__marco {
  border-radius: 34px; border: 7px solid #161c27; background: #1c1c1a;
  box-shadow: 0 0 0 1px var(--line-faint), 0 40px 90px rgba(0, 0, 0, .6);
}
.caso-x__fotos--movil .foto--corrida { width: auto; margin-left: -34%; }
.caso-x__fotos--movil .foto--corrida figcaption { text-align: right; padding-left: 42%; }
/* Dos capturas del puesto de fichaje, lado a lado y la segunda más abajo:
   primero reconoce, después pide el gesto. */
.caso-x__fotos--par { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; align-items: start; }
.foto--bajada { margin-top: 18%; }
@media (max-width: 900px) {
  .caso-x__fila, .caso-x--inverso .caso-x__fila { grid-template-columns: 1fr; }
  .caso-x--inverso .caso-x__texto { order: 0; }
  .caso-x__fotos { position: static; }
  .foto--corrida { width: 100%; }
  .caso-x__fotos--movil { grid-template-columns: 1fr; gap: 28px; }
  .foto--movil { width: min(78%, 330px); margin-inline: auto; }
  .caso-x__fotos--movil .foto--corrida { margin-left: 0; }
  .caso-x__fotos--movil .foto--corrida figcaption { padding-left: 0; text-align: left; }
  .caso-x__fotos--par { gap: 12px; }
  .foto--bajada { margin-top: 12%; }
}
/* En un teléfono, lado a lado cada captura mide 132 px y no se lee: una
   debajo de la otra, a lo ancho. */
@media (max-width: 480px) {
  .caso-x__fotos--par { grid-template-columns: 1fr; gap: 22px; }
  .foto--bajada { margin-top: 0; }
}

/* ------------------------------------------------------------------ quién */
.quien__linkedin { margin-top: 22px; }
.quien__linkedin svg { width: 17px; height: 17px; }
.quien__fila { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(32px, 6vw, 96px); align-items: center; }
.quien__marca {
  display: grid; place-items: center; aspect-ratio: 1; max-width: 420px; width: 100%;
  border-radius: 28px; border: 1px solid var(--line-faint);
  background: radial-gradient(80% 80% at 30% 20%, rgba(79, 140, 255, .16), transparent 70%), var(--bg-lift);
}
.celdas--gigante { grid-template-columns: repeat(4, clamp(34px, 5vw, 60px)); gap: clamp(10px, 1.4vw, 16px); }
/* Las celdas gigantes llevan el RELIEVE de la v2 (miden más de 24 px: por
   debajo de eso el manual dice plano, como en la barra y el favicon): cara en
   degradé, brillo arriba y el canto oscuro asomando abajo. Encendidas, una
   capa de vidrio azul (o verde) sube de opacidad: un degradé no se puede
   fundir con `transition`, una opacidad sí. */
.celdas--gigante i {
  position: relative; width: auto; height: clamp(24px, 3.6vw, 42px); border-radius: 8px;
  background: linear-gradient(160deg, #1d2a44, #121c31);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10), 0 4px 0 #0a1222;
}
.celdas--gigante i::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; opacity: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .45), rgba(255, 255, 255, 0) 38%),
              linear-gradient(160deg, #6fa0ff, #2458d6);
  box-shadow: 0 4px 0 #16398f;
  transition: opacity .35s var(--ease);
}
.celdas--gigante i.a::after, .celdas--gigante i.es-luz::after { opacity: 1; }
.celdas--gigante i.o::after {
  background: linear-gradient(180deg, rgba(255, 255, 255, .42), rgba(255, 255, 255, 0) 38%),
              linear-gradient(160deg, #3fd6b0, #159478);
  box-shadow: 0 4px 0 #0f6b56;
}
.celdas--gigante i.o::after, .celdas--gigante i.o.es-luz::after { opacity: 1; }
.quien__texto h2 { font-size: clamp(34px, 5vw, 70px); line-height: 1; margin: 6px 0 22px; }
.quien__parrafos p { color: var(--muted); font-size: clamp(16px, 1.35vw, 19px); line-height: 1.65; max-width: 56ch; margin: 0 0 16px; }
@media (max-width: 820px) { .quien__fila { grid-template-columns: 1fr; } .quien__marca { max-width: 280px; } }

/* ----------------------------------------------------------- herramientas */
.herramientas h2 { max-width: 18ch; }
.logos {
  list-style: none; margin: clamp(30px, 4vw, 56px) 0 0; padding: 0;
  display: grid; gap: clamp(12px, 1.6vw, 18px);
  grid-template-columns: repeat(auto-fill, minmax(clamp(112px, 12vw, 160px), 1fr));
}
.logo {
  border-radius: var(--r-chico); background: var(--bg-lift); border: 1px solid var(--line-faint);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.logo:hover { transform: translateY(-4px); border-color: var(--line); background: var(--panel); }
/* Toda la tarjeta es el enlace a la página oficial (7-oct-2026). */
.logo__enlace {
  display: grid; justify-items: center; gap: 12px; padding: 22px 12px 18px; height: 100%;
  border-radius: inherit; color: inherit; text-decoration: none;
}
.logo__enlace:hover { color: inherit; }
.logo:focus-within { border-color: var(--accent); }
.logo__img {
  width: 40px; height: 40px; background: var(--ink-2);
  -webkit-mask: var(--logo) center / contain no-repeat; mask: var(--logo) center / contain no-repeat;
  transition: background var(--dur) var(--ease);
}
.logo:hover .logo__img { background: var(--accent); }
.logo__letra {
  width: 40px; height: 40px; display: grid; place-items: center; border-radius: 10px;
  border: 1.5px solid var(--ink-2); color: var(--ink-2); font-size: 15px; font-weight: 500;
}
.logo__nombre { font-size: 14px; color: var(--ink-2); text-align: center; }

/* -------------------------------------------------------------- siguiente */
.siguiente { position: relative; }
.siguiente__fijo { position: relative; min-height: 100svh; display: flex; flex-direction: column; overflow: hidden; }
.siguiente__fondo { position: absolute; inset: 0; display: grid; align-content: center; gap: 2vh; pointer-events: none; }
.siguiente__carril {
  margin: 0; white-space: nowrap; font-family: var(--f-display); font-weight: 600;
  font-size: clamp(40px, 7vw, 110px); letter-spacing: -.04em; color: rgba(140, 170, 215, .07);
  will-change: transform;
}
.siguiente__cuerpo { position: relative; z-index: 1; margin-block: auto; padding-block: var(--aire); }
.siguiente__enlace {
  display: inline-flex; align-items: center; gap: .18em; color: var(--ink); text-decoration: none;
  font-family: var(--f-display); font-weight: 600; letter-spacing: -.05em; line-height: .95;
  font-size: clamp(64px, 15vw, 240px);
}
.siguiente__enlace svg { width: .6em; height: .6em; transition: transform var(--dur) var(--ease); }
.siguiente__enlace:hover svg, .siguiente__enlace:focus-visible svg { transform: translateX(.12em); }
.siguiente__pista { display: none; color: var(--muted); font-size: 12.5px; letter-spacing: .12em; text-transform: uppercase; margin: 22px 0 10px; }
.siguiente__barra { display: none; width: min(420px, 70vw); height: 2px; background: var(--line-faint); border-radius: 2px; overflow: hidden; }
.siguiente__barra > span { display: block; height: 100%; background: var(--accent); transform-origin: 0 50%; transform: scaleX(0); }
.pie--dentro { position: relative; z-index: 1; border-top: 1px solid var(--line-faint); }

.gs-vivo .siguiente { height: 150svh; }
.gs-vivo .siguiente__fijo { position: sticky; top: 0; height: 100svh; }
.gs-vivo .siguiente__pista, .gs-vivo .siguiente__barra { display: block; }
.gs-vivo .siguiente__cuerpo { padding-block: 0; }

/* La cortina al irse a la página siguiente. */
.cortina {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  background: var(--bg); transform: translateY(100%);
}

/* ------------------------------------------------------------ la tela
   /trabajos: cada fila, al irse, se corta en tiras que se mueven como una
   tela al viento. Las tiras son copias de la fila recortadas con clip-path;
   mientras vuelan, la fila de verdad queda invisible pero ocupa su sitio. */
.trabajo { position: relative; }
.tela { position: absolute; inset: 0; pointer-events: none; perspective: 1400px; z-index: 3; }
.tela__tira {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  transform-style: preserve-3d; will-change: transform, opacity; backface-visibility: hidden;
}
.tela__tira > .trabajo { margin: 0 !important; visibility: visible !important; opacity: 1 !important; transform: none !important; }
/* La hoja que se va lleva fondo y un borde un tono más claro que las líneas
   de la lista: sin eso el texto volaba suelto sobre las filas de abajo y no
   se leía como una hoja. Cada tira es una copia recortada, así que el borde
   de arriba lo enseña la primera, el de abajo la última y los de los lados
   todas: el contorno de la hoja entera. */
.tela__tira > .trabajo {
  background: var(--bg);
  border: 1px solid rgba(170, 196, 235, .34) !important;
}
/* La sombra de cada tira es un elemento propio y se mueve con `opacity`.
   Antes era una variable (`--sombra`) que se HEREDA: cambiarla en cada
   cuadro invalidaba el estilo de toda la fila clonada dentro de cada tira
   (7 filas por cuadro en el móvil, 20-30 % de cuadros lentos). */
.tela__sombra {
  position: absolute; inset: 0; pointer-events: none;
  background: rgb(4, 6, 10); opacity: 0; will-change: opacity;
}
.trabajo.es-tela > :not(.tela) { visibility: hidden; }
.trabajo.es-tela { border-color: transparent; }

/* Las celdas grandes de «quién está» se encienden al pasar. */
/* (el encendido es la capa ::after de arriba, con su opacidad) */
/* Con movimiento, el logo lo mueve GSAP: la transición de `transform` del
   hover se pelearía con él. */
.gs-vivo .logo { transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease); }
.gs-vivo .logo:hover { transform: none; }
.zoom__o { display: inline-block; }
.zoom__pal { white-space: nowrap; }

/* ---------------------------------------------------------- /contacto
   Una pantalla entera: el titular grande a la izquierda, el formulario a
   la derecha, y el pie abajo. */
.contacto-p { min-height: calc(100svh - var(--barra-h)); display: flex; align-items: center; }
.contacto-p > .ancho { width: min(var(--ancho), 100%); }
.contacto-p h1 { font-size: clamp(40px, 7vw, 104px); line-height: .96; max-width: 11ch; }
.formulario__titulo { font-size: clamp(20px, 2vw, 26px); margin: 0 0 4px; }
/* Las salidas: botones a otra página al final de las que no tienen un
   «siguiente». Regla de la web: ningún camino sin salida. */
.salidas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(26px, 3vw, 36px); }
/* La frase partida en letras (movimiento.js, `frase`). `--k` va de 0 a 1:
   cuánto la levanta el cursor o la ola; con 0 es la letra de siempre. El
   recorte de las palabras del titular se abre para que la letra que sube no
   se corte. */
.frase-viva .pal { overflow: visible !important; }
.frase-viva .letras { display: inline-block; white-space: nowrap; }
.frase-viva .letra {
  display: inline-block; will-change: transform;
  color: color-mix(in oklab, var(--accent) calc(var(--k, 0) * 100%), var(--ink));
}

/* El título de la nube vive en la columna de texto: si ocupa todo el ancho,
   la nube le dibuja conceptos encima. */
.nube__texto h2 { max-width: 13ch; }

/* En el móvil no caben la nube y la lista entera en la misma pantalla: se ve
   sólo el servicio activo (los cuatro siguen en el HTML), y la nube se queda
   con la mitad de arriba. */
@media (max-width: 820px) and (max-aspect-ratio: 7/5) {
  .gs-vivo .nube__texto .eyebrow { display: none; }
  .gs-vivo .nube__texto h2 { max-width: none; }
  .gs-vivo .servicios-n { margin-top: 18px; display: grid; }
  .gs-vivo .servicio-n { grid-area: 1 / 1; }
  .gs-vivo .servicio-n:not(.es-activo) { visibility: hidden; }
  .gs-vivo .servicio-n p:last-child,
  .gs-vivo .servicio-n.es-activo p:last-child { max-height: none; margin-top: 4px; opacity: 1; }
}
/* El móvil en horizontal: título y servicio activo a la izquierda, la nube a
   la derecha (movimiento.js la pone al costado cuando la pantalla es apaisada). */
@media (max-height: 520px) and (min-aspect-ratio: 7/5) {
  .gs-vivo .nube__fijo { align-items: center; }
  .gs-vivo .nube__texto { padding-top: calc(var(--barra-h) + 4px); padding-bottom: 0; background: none; }
  .gs-vivo .nube__texto .eyebrow { display: none; }
  .gs-vivo .nube__texto > * { max-width: 46vw; }
  .gs-vivo .nube__texto h2 { font-size: clamp(22px, 7vh, 30px); }
  .gs-vivo .servicios-n { margin-top: 12px; }
  .gs-vivo .servicio-n:not(.es-activo) { display: none; }
}

/* ------------------------------------------------- el huevo: la gravedad
   assets/js/gravedad.js. Las copias que caen viven en una capa fija que
   llega hasta el suelo (el pie); el pie queda fuera, así que sus enlaces
   se siguen pudiendo pulsar. Sólo `transform` por cuadro. */
.pie__derechos, .portada .eyebrow { cursor: default; user-select: none; }
.pie--tiembla { animation: idc-tiembla .32s var(--ease-out); }
/* De lado y no girando: girar un párrafo ancho mueve sus puntas decenas de
   píxeles y el clic siguiente se escapaba. */
@keyframes idc-tiembla {
  25% { transform: translateX(-3px); }
  60% { transform: translateX(3px); }
}
.portada .eyebrow { width: fit-content; }
/* Con la gravedad suelta el scroll sigue (la pila puede ser más alta que la
   pantalla), así que el «siguiente» deja de ir pegado: su pie es el suelo.
   OJO si alguna vez se bloquea el scroll: `overflow` en <html> hace que el
   `overflow-x` del <body> deje de pasarse a la ventana, el body se vuelve
   contenedor de scroll y los `sticky` se corren (medido: 164 px). */
.gravedad .siguiente { height: auto !important; }
/* Lo que no se cayó desaparece (como en Google Gravity): queda el fondo, la
   pila y el pie. Sin esto, lo que no entraba en el tope se quedaba colgado
   en su sitio y parecía que la gravedad no le tocaba. */
html.gravedad-suelta main, html.gravedad-suelta .barra { visibility: hidden; }
html.gravedad-suelta footer { visibility: visible; }
.gravedad .siguiente__fijo { position: relative !important; height: auto !important; min-height: 100svh; }
.gravedad__mundo {
  position: absolute; left: 0; top: 0; width: 100%; z-index: 150;
  cursor: grab;
  /* recorta en el suelo lo que sobresale de su caja (el rabo de una «j»):
     sin esto se pintaba encima del pie */
  overflow: hidden;
}
.gravedad__mundo:active { cursor: grabbing; }
.gravedad__mundo > * {
  position: absolute !important; left: 0 !important; top: 0 !important; margin: 0 !important;
  box-sizing: border-box; pointer-events: none; transform-origin: 50% 50%;
  will-change: transform; transition: none !important; animation: none !important;
}
.gravedad__ordenar {
  position: fixed; top: 14px; left: 50%; z-index: 160;
  transform: translate(-50%, -140%); transition: transform .45s var(--ease-out);
}
.gravedad__ordenar.es-visible { transform: translate(-50%, 0); }

/* En el móvil el texto que se LEE va a 16 px; los rótulos en mono (eyebrow,
   pies de foto, tecnologías) se quedan como están. */
@media (max-width: 560px) {
  .punto p, .chica, .exp__pie, .paso p, .servicio-n p:last-child { font-size: 16px; }
}

/* ---------------------------------------------------------- /maquetas
   La puerta de los clientes: el titular y el código arriba, a dos columnas
   en escritorio, y debajo las maquetas que abre, en tarjetas. Sin código no
   se enseña nada: la lista la devuelve el servidor (assets/js/maquetas.js). */
.maquetas-p { min-height: calc(100svh - var(--barra-h)); display: flex; align-items: center; }
.maquetas-p > .ancho { width: min(var(--ancho), 100%); }
.maquetas {
  display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(28px, 5vw, 64px) clamp(28px, 5vw, 72px);
  align-items: end;
}
.maquetas h1 { font-size: clamp(40px, 6.4vw, 96px); line-height: .96; max-width: 12ch; }
.maquetas__form { display: grid; gap: 16px; }
.maquetas__form .campo input { font-size: 18px; letter-spacing: .04em; }
.maquetas__nota { margin: 0; }
.maquetas__aviso {
  margin: -4px 0 0; padding: 11px 14px; border-radius: var(--r-chico);
  border: 1px solid rgba(245, 165, 36, .35); background: var(--warn-soft); color: var(--ink);
  font-size: 14.5px; line-height: 1.5;
}
.maquetas__resultado, .maquetas__salidas { grid-column: 1 / -1; }
.maquetas__salidas { margin-top: 0; }
.maquetas__titulo { font-size: clamp(22px, 2.4vw, 30px); margin: 0 0 18px; outline: none; }
.maq-lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: 16px;
}
.maq {
  display: flex; flex-direction: column; gap: 12px; padding: clamp(20px, 2.6vw, 28px);
  border-radius: var(--r); border: 1px solid var(--line-faint); background: var(--panel);
  transition: border-color var(--dur) var(--ease);
}
.maq:hover { border-color: rgba(79, 140, 255, .45); }
.maq__titulo { font-size: clamp(19px, 1.8vw, 23px); margin: 0; }
.maq__texto { margin: 0; color: var(--muted); line-height: 1.6; flex: 1; }
.maq__abrir { align-self: flex-start; }
.maq__abrir svg { width: 17px; height: 17px; }
/* Al aparecer suben un poco. Sólo `transform`, nunca la opacidad: con el
   reloj parado (pestaña dormida) quedan 10 px más abajo, pero se leen. */
.anima .maq { animation: maq-sube .5s var(--ease) both; }
.anima .maq:nth-child(2) { animation-delay: .06s; }
.anima .maq:nth-child(3) { animation-delay: .12s; }
@keyframes maq-sube { from { transform: translateY(10px); } to { transform: none; } }
@media (max-width: 880px) {
  .maquetas { grid-template-columns: 1fr; align-items: start; }
  .maquetas-p { align-items: flex-start; }
}

/* ---------------------------------------------------------------------------
   /alta — el enlace de alta de un club (etapa 8, pista I; assets/js/alta.js).
   Visible por defecto: el resumen sólo se oculta con [hidden] hasta que hay
   algo que enseñar, nunca con opacity esperando una animación.
--------------------------------------------------------------------------- */
.alta__resumen { margin-top: clamp(24px, 3vw, 34px); }
.alta__resumen h2:first-of-type { margin-top: 0; }
.texto .alta__lineas { list-style: none; padding: 0; margin: 0 0 8px; display: grid; gap: 10px; }
.texto .alta__lineas li { color: var(--ink); font-size: clamp(17px, 1.6vw, 20px); font-family: var(--f-display); }
.texto .alta__total { margin: 4px 0 6px; color: var(--ink); font-weight: 600; }
.alta__accion { display: grid; gap: 10px; justify-items: start; margin-top: 30px; }
.alta__accion .chica { margin: 0; }
.alta__aviso { margin: 16px 0 0; color: var(--warn); }

/* ======================================================= de la 1.5 (6-oct)
   Las secciones que vinieron de la versión «Oficio», con la piel de la v2:
   los filetes en champán y los números en Newsreader. */

/* -- ¿Es para ti? Cuatro situaciones, numeradas en romano, con un filete
      encima de cada una. La cabecera se queda pegada a la izquierda mientras
      la lista pasa, en escritorio. */
.para-ti__fila {
  display: grid; gap: clamp(32px, 5vw, 80px);
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start;
}
.para-ti__cab { position: sticky; top: calc(var(--barra-h) + 32px); }
.para-ti__cab h2 { margin-bottom: 28px; }
.para-ti__lista { list-style: none; margin: 0; padding: 0; counter-reset: pt; }
.para-ti__item {
  counter-increment: pt; position: relative;
  border-top: 1px solid rgba(200, 169, 119, .3);
  padding: 26px 0 30px 72px;
  font-family: var(--f-display); font-size: clamp(21px, 2.2vw, 28px); line-height: 1.28;
  color: var(--ink); font-weight: 500; letter-spacing: -0.015em;
}
.para-ti__item:last-child { border-bottom: 1px solid rgba(200, 169, 119, .3); }
.para-ti__item::before {
  content: counter(pt, upper-roman); position: absolute; left: 0; top: 29px;
  font-family: var(--f-editorial); font-style: italic; font-size: 19px; color: var(--champan);
}
@media (max-width: 900px) {
  .para-ti__fila { grid-template-columns: 1fr; }
  .para-ti__cab { position: static; }
  .para-ti__item { padding-left: 48px; }
}

.herramientas__lead { margin-bottom: clamp(28px, 4vw, 44px); }

/* -- /contacto: qué pasa después de escribir, y las preguntas */
.despues { list-style: none; margin: 28px 0 0; padding: 0; display: grid; gap: 0; }
.despues__paso {
  display: grid; grid-template-columns: 44px 1fr; align-items: baseline;
  border-top: 1px solid var(--line-faint); padding: 14px 0;
}
.despues__paso p { margin: 0; color: var(--ink-2); }
.despues__n {
  font-family: var(--f-editorial); font-style: italic; font-size: 26px;
  color: var(--champan); line-height: 1;
}

.preguntas { padding-block: var(--aire); }
.preguntas__lista { max-width: 860px; margin-top: 28px; }
.pregunta { border-top: 1px solid rgba(200, 169, 119, .28); }
.pregunta:last-child { border-bottom: 1px solid rgba(200, 169, 119, .28); }
.pregunta summary {
  list-style: none; cursor: pointer; display: flex; justify-content: space-between; gap: 24px;
  padding: 22px 0; font-family: var(--f-display); font-weight: 500; color: var(--ink);
  font-size: clamp(19px, 1.9vw, 25px); line-height: 1.28; letter-spacing: -0.012em;
}
.pregunta summary::-webkit-details-marker { display: none; }
/* el «+» es lo que se toca: azul, no champán */
.pregunta summary::after {
  content: "+"; font-family: var(--f-body); font-weight: 300; color: var(--accent);
  font-size: 26px; line-height: 1; transition: transform var(--dur) var(--ease);
}
.pregunta[open] summary::after { transform: rotate(45deg); }
.pregunta p { color: var(--muted); max-width: 62ch; margin: 0 0 24px; }

/* -- el lema bajado a tierra, debajo del titular de /contacto */
.lema {
  font-family: var(--f-editorial); font-style: italic; font-size: clamp(19px, 1.8vw, 24px);
  color: var(--ink-2); max-width: 44ch; border-left: 1.5px solid var(--champan);
  padding-left: 18px; margin: 0 0 28px;
}
/* la palabra clave del lema sigue en champán mientras la ola la recorre */
.frase-viva em .letra { color: var(--champan); }
