/* ==========================================================================
   ÓRBITA — Hoja base
   Tokens, tipografía, layout y componentes.
   La capa de movimiento vive en effects.css
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset
   -------------------------------------------------------------------------- */

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

img,
svg,
canvas {
  display: block;
  max-width: 100%;
}

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

ul,
ol {
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* El sitio es oscuro siempre. Se lo decimos al navegador para que las barras
     de desplazamiento y los controles nativos salgan oscuros y no en claro. */
  color-scheme: dark;

  /* Superficies */
  --bg: #05060a;
  --bg-elev: #0a0d16;
  --surface: rgba(255, 255, 255, 0.028);
  --surface-hi: rgba(255, 255, 255, 0.055);

  /* Bordes */
  --line: rgba(255, 255, 255, 0.09);
  --line-hi: rgba(255, 255, 255, 0.16);

  /* Texto */
  --text: #eef1f8;
  --text-dim: #a7b0c7;
  --text-mute: #6b7590;

  /* Acentos */
  --blue: #4d8dff;
  --purple: #a855f7;
  --cyan: #22d3ee;
  --grad: linear-gradient(115deg, var(--blue) 0%, var(--purple) 52%, var(--cyan) 100%);
  --grad-soft: linear-gradient(115deg, rgba(77, 141, 255, 0.16), rgba(168, 85, 247, 0.1) 55%, rgba(34, 211, 238, 0.14));

  /* Tipografía: solo fuentes de sistema, cero descargas.
     Orden de la pila: Helvetica (macOS, o Windows si está instalada), luego
     Aptos —neogrotesca de Microsoft, llega con Office 365, no con Windows— y
     por último Arial, que existe en todas partes. Georgia viene de serie en
     Windows y en macOS, así que la cursiva nunca falla. */
  --font-display: Helvetica, 'Helvetica Neue', Aptos, Arial, sans-serif;
  --font-accent: Georgia, 'Times New Roman', serif;
  --font-body: Helvetica, 'Helvetica Neue', Aptos, Arial, sans-serif;

  --fs-hero: clamp(2.9rem, 8.5vw, 7rem);
  --fs-h2: clamp(2rem, 4.6vw, 3.6rem);
  --fs-h3: clamp(1.2rem, 1.9vw, 1.55rem);
  --fs-lead: clamp(1.05rem, 1.6vw, 1.3rem);
  --fs-body: clamp(0.975rem, 1vw, 1.0625rem);
  --fs-small: 0.875rem;
  --fs-micro: 0.75rem;

  /* Ritmo */
  --shell: 1280px;
  --gutter: clamp(1.15rem, 4vw, 3rem);
  --section-y: clamp(4rem, 7.5vw, 7rem);
  --gap: clamp(1.25rem, 2.4vw, 2rem);

  /* Formas */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-pill: 999px;

  /* Movimiento */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --t-fast: 0.2s;
  --t-med: 0.35s;
  --t-slow: 0.6s;

  /* Sombras */
  --glow: 0 0 0 1px rgba(77, 141, 255, 0.25), 0 18px 50px -18px rgba(77, 141, 255, 0.55);
  --lift: 0 24px 60px -28px rgba(0, 0, 0, 0.9);

  /* Capas */
  --z-bg: 0;
  --z-content: 1;
  --z-header: 100;
  --z-curtain: 200;
  --z-preloader: 300;
  --z-modal: 400;
  --z-grain: 500;
  --z-cursor: 600;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

/* Lenis toma el control del scroll cuando está activo */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

body {
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  /* clip, no hidden: overflow-x:hidden obliga a overflow-y:auto, convierte al
     body en contenedor de scroll y ScrollTrigger deja de calcular bien las
     posiciones (los revelados nunca se disparan). clip recorta igual sin
     crear contenedor de scroll. */
  overflow-x: clip;
}

/* Halo de color fijo detrás de todo el documento */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  pointer-events: none;
  background:
    radial-gradient(60% 45% at 15% 0%, rgba(77, 141, 255, 0.16), transparent 60%),
    radial-gradient(50% 40% at 85% 12%, rgba(168, 85, 247, 0.13), transparent 60%),
    radial-gradient(70% 50% at 50% 100%, rgba(34, 211, 238, 0.08), transparent 65%);
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

h1 { font-size: var(--fs-hero); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); line-height: 1.25; }

p {
  color: var(--text-dim);
  text-wrap: pretty;
}

::selection {
  background: rgba(77, 141, 255, 0.35);
  color: #fff;
}

:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   4. Layout
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  position: relative;
  z-index: var(--z-content);
  padding-block: var(--section-y);
}

.section--tight {
  padding-block: clamp(3rem, 6vw, 5rem);
}

main,
.site-footer {
  position: relative;
  z-index: var(--z-content);
}

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--gutter);
  z-index: 999;
  padding: 0.75rem 1.25rem;
  background: var(--blue);
  color: #fff;
  border-radius: var(--r-sm);
  font-weight: 600;
  transition: top var(--t-fast) var(--ease);
}

.skip-link:focus {
  top: 1rem;
}

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

/* Encabezado de sección */

.section-head {
  max-width: 46rem;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

.section-head p {
  margin-top: 1.1rem;
  font-size: var(--fs-lead);
  color: var(--text-dim);
}

/* --------------------------------------------------------------------------
   5. Botones
   -------------------------------------------------------------------------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 48px;
  padding: 0.85rem 1.6rem;
  border-radius: var(--r-pill);
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: transform var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease),
    background-color var(--t-med) var(--ease), border-color var(--t-med) var(--ease),
    color var(--t-med) var(--ease);
}

.btn--primary {
  background: var(--grad);
  background-size: 180% 100%;
  color: #fff;
  box-shadow: 0 14px 40px -16px rgba(77, 141, 255, 0.9);
}

.btn--primary:hover {
  background-position: 100% 0;
  box-shadow: 0 20px 55px -16px rgba(168, 85, 247, 0.95);
}

.btn--ghost {
  border: 1px solid var(--line-hi);
  background: var(--surface);
  color: var(--text);
}

.btn--ghost:hover {
  border-color: rgba(77, 141, 255, 0.65);
  background: rgba(77, 141, 255, 0.1);
}

/* --- Botón con borde especular ------------------------------------------
   El contorno lo dibuja un shader WebGL (assets/js/specular.js) sobre un
   lienzo que desborda 20px por cada lado, para que el brillo pueda salirse
   del botón. Lo de aquí es la base: si no hay WebGL o el visitante pidió
   movimiento reducido, queda un botón de cristal con borde normal. */

.btn--specular {
  isolation: isolate;
  border: 1px solid var(--line-hi);
  background: rgba(255, 255, 255, 0.045);
  backdrop-filter: blur(8px);
  color: var(--text);
  box-shadow: none;
}

.btn--specular:hover {
  background: rgba(255, 255, 255, 0.075);
}

/* Con el shader activo el borde lo pinta él, no el CSS */
.btn--specular.is-specular-on {
  border-color: transparent;
}

/* Distingue la acción principal de la secundaria sin romper el material */
.btn--specular.btn--tinted {
  background: linear-gradient(115deg, rgba(77, 141, 255, 0.26), rgba(168, 85, 247, 0.2));
}

.btn--specular.btn--tinted:hover {
  background: linear-gradient(115deg, rgba(77, 141, 255, 0.36), rgba(168, 85, 247, 0.28));
}

.btn__fx {
  position: absolute;
  inset: -20px;
  z-index: 0;
  pointer-events: none;
}

.btn__fx canvas {
  display: block;
}

.btn__label {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}

.btn--lg {
  min-height: 60px;
  padding: 1.1rem 2.4rem;
  font-size: 1.05rem;
}

.btn__arrow {
  transition: transform var(--t-med) var(--ease);
}

.btn:hover .btn__arrow {
  transform: translateX(4px);
}

/* --------------------------------------------------------------------------
   6. Header y navegación
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-header);
  /* El fondo y el desenfoque ya no viven aquí sino en .header__inner, que es
     lo que se convierte en píldora al bajar. */
  padding-top: 0;
  transition: padding-top var(--t-med) var(--ease);
}

/* Al bajar, la barra se separa del borde para que la píldora flote */
.site-header.is-stuck {
  padding-top: clamp(0.5rem, 1.2vw, 0.9rem);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.05rem;
  /* Borde transparente desde el principio: si apareciera solo al hacer scroll,
     el contenido saltaría un píxel a cada lado. */
  border: 1px solid transparent;
  border-radius: 0;
  transition:
    max-width var(--t-med) var(--ease),
    padding var(--t-med) var(--ease),
    background-color var(--t-med) var(--ease),
    border-color var(--t-med) var(--ease),
    border-radius var(--t-med) var(--ease),
    box-shadow var(--t-med) var(--ease);
}

/* La píldora: más estrecha, redonda, translúcida y desenfocada */
.site-header.is-stuck .header__inner {
  max-width: min(1080px, calc(100% - clamp(1.5rem, 5vw, 3rem)));
  padding: 0.5rem 0.55rem 0.5rem 1.4rem;
  border-color: var(--line-hi);
  border-radius: var(--r-pill);
  background: rgba(10, 13, 22, 0.62);
  backdrop-filter: blur(18px) saturate(150%);
  box-shadow: 0 20px 50px -26px rgba(0, 0, 0, 0.95);
}

/* Marca */

.brand {
  display: inline-flex;
  align-items: center;
}

/* Lockup oficial de marca. No se recolorea ni se rota: las guías del kit
   prohíben expresamente rotar el anillo y alterar el gradiente.
   Altura mínima 38px porque el kit fija 140px de ancho mínimo para el
   lockup horizontal (relación 3.73:1) y por debajo el trazo se pierde. */
.brand__logo {
  width: auto;
  height: 44px;
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}

.brand:hover .brand__logo {
  opacity: 0.82;
  transform: translateY(-1px);
}

.footer__about .brand__logo {
  height: 52px;
}

/* Navegación */

.nav {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.nav__link {
  position: relative;
  padding: 0.6rem 0.95rem;
  border-radius: var(--r-pill);
  color: var(--text-dim);
  font-size: 0.94rem;
  font-weight: 500;
  transition: color var(--t-fast) var(--ease);
}

.nav__link::after {
  content: '';
  position: absolute;
  left: 0.95rem;
  right: 0.95rem;
  bottom: 0.35rem;
  height: 1px;
  background: var(--grad);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-med) var(--ease);
}

.nav__link:hover {
  color: var(--text);
}

.nav__link:hover::after,
.nav__link.is-active::after {
  transform: scaleX(1);
}

.nav__link.is-active {
  color: var(--text);
}

.nav__cta {
  margin-left: 0.6rem;
  min-height: 44px;
  padding: 0.65rem 1.35rem;
  font-size: 0.9rem;
}

/* Botón hamburguesa */

.menu-toggle {
  display: none;
  place-items: center;
  width: 46px;
  height: 46px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
}

.menu-toggle span {
  display: block;
  width: 18px;
  height: 1.5px;
  margin: 2.5px 0;
  border-radius: 2px;
  background: var(--text);
  transition: transform var(--t-med) var(--ease), opacity var(--t-fast) var(--ease);
}

.menu-toggle[aria-expanded='true'] span:nth-child(1) {
  transform: translateY(4px) rotate(45deg);
}

.menu-toggle[aria-expanded='true'] span:nth-child(2) {
  opacity: 0;
}

.menu-toggle[aria-expanded='true'] span:nth-child(3) {
  transform: translateY(-4px) rotate(-45deg);
}

/* Barra de progreso de lectura */

/* Fija al borde del viewport, no colgando del header: con la píldora flotando
   una línea de ancho completo bajo ella quedaría suelta. */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: transparent;
  pointer-events: none;
}

.scroll-progress__bar {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--grad);
  transform: scaleX(0);
  transform-origin: left;
}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100svh;
  padding-top: clamp(6.5rem, 12vh, 8.5rem);
  padding-bottom: clamp(3rem, 6vh, 5rem);
  overflow: hidden;
}

.hero--inner {
  min-height: 62svh;
  align-items: flex-end;
}

.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
}

.hero__title {
  max-width: 16ch;
  margin-bottom: 1.6rem;
}

/* Una palabra en serif cursiva contra la sans bold: el contraste hace de
   acento sin necesidad de una pastilla encima del titular.
   Color sólido a propósito. El titular pasa por SplitText, y un degradado con
   background-clip:text se rompe en cuanto el texto se reparte entre elementos
   hijos: es el mismo fallo que dejó invisible "perder clientes" en Nosotros. */
.hero__title em {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 700;
  /* Georgia tiene la altura de x mayor que Helvetica: al mismo tamaño
     nominal se ve más grande, así que se compensa a la baja. */
  font-size: 0.94em;
  letter-spacing: -0.01em;
  color: var(--cyan);

  /* Resplandor. Va en text-shadow y no en un degradado o un filtro porque
     text-shadow SE HEREDA: sobrevive al reparto en palabras que hace el
     revelado del titular. El halo base queda declarado aquí, así que si la
     animación no llega a ejecutarse la palabra sigue brillando. */
  text-shadow:
    0 0 14px rgba(34, 211, 238, 0.5),
    0 0 38px rgba(34, 211, 238, 0.3),
    0 0 80px rgba(34, 211, 238, 0.18);
  animation: orbita-brillo 4.5s var(--ease-soft) infinite;
}

/* La luz respira: el halo se abre y se cierra despacio */
@keyframes orbita-brillo {
  0%, 100% {
    text-shadow:
      0 0 14px rgba(34, 211, 238, 0.5),
      0 0 38px rgba(34, 211, 238, 0.3),
      0 0 80px rgba(34, 211, 238, 0.18);
  }
  50% {
    text-shadow:
      0 0 18px rgba(34, 211, 238, 0.7),
      0 0 52px rgba(34, 211, 238, 0.42),
      0 0 110px rgba(34, 211, 238, 0.26);
  }
}

.hero--inner .hero__title {
  max-width: 20ch;
}

.hero__lead {
  max-width: 44ch;
  margin-bottom: 2.4rem;
  font-size: var(--fs-lead);
  color: var(--text-dim);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-bottom: 2.5rem;
}

/* Anillos orbitales decorativos */

.hero__orbits {
  position: absolute;
  top: 50%;
  right: -6vw;
  z-index: 1;
  width: min(46vw, 620px);
  aspect-ratio: 1;
  translate: 0 -50%;
  pointer-events: none;
  /* Sin atenuación de grupo: así el logo y los aros se gradúan por separado
     y la marca puede ser lo más brillante de la composición. */
  opacity: 1;
}

.hero__orbits svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.orbit-ring {
  fill: none;
  stroke: url(#orbitGrad);
  stroke-width: 0.6;
  opacity: 0.5;
  transform-origin: 50% 50%;
  animation: orbit-spin 28s linear infinite;
}


/* --- El anillo intermedio es el isotipo de la marca ---------------------
   No gira: el kit prohíbe rotar el anillo. En su lugar se dibuja solo al
   cargar y el planeta respira despacio. Todo en CSS, así que también
   funciona si el JS o el CDN fallan. */

/* Los dos números para ajustar el logo del hero:
   esta opacidad y la escala del atributo transform del <g> en el HTML (0.33). */
.hero-logo {
  opacity: 0.85;
}

/* --- Estrella del centro -------------------------------------------------
   box-shadow no existe en SVG, así que va como elemento HTML encima. Se centra
   con márgenes negativos, no con transform, para dejar transform libre para el
   latido: si se combinan, el navegador aplica translate antes que transform y
   la escala arrastraría también el centrado.
   Los desenfoques van en proporción al tamaño, así que la estrella se puede
   redimensionar con una sola variable. Las proporciones son las del original
   de 300px: 50, 80 y 300 de desenfoque, con desplazamientos de 20 y 10. */

.hero-star {
  --star: clamp(16px, 2.6vw, 34px);
  /* Los del ejemplo eran #f0f y #0ff; aquí van los acentos de la web, que ya
     usan el aro y el punto que orbita. */
  --star-a: #a855f7;
  --star-b: #22d3ee;

  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: calc(var(--star) / -2);
  margin-left: calc(var(--star) / -2);
  width: var(--star);
  height: var(--star);
  border-radius: 50%;
  pointer-events: none;

  box-shadow:
    inset 0 0 calc(var(--star) * 0.167) #fff,
    inset calc(var(--star) * 0.067) 0 calc(var(--star) * 0.267) var(--star-a),
    inset calc(var(--star) * -0.067) 0 calc(var(--star) * 0.267) var(--star-b),
    inset calc(var(--star) * 0.067) 0 var(--star) var(--star-a),
    inset calc(var(--star) * -0.067) 0 var(--star) var(--star-b),
    0 0 calc(var(--star) * 0.167) #fff,
    calc(var(--star) * -0.033) 0 calc(var(--star) * 0.267) var(--star-a),
    calc(var(--star) * 0.033) 0 calc(var(--star) * 0.267) var(--star-b);

  animation: hero-star-latido 5.5s var(--ease-soft) infinite;
}

@keyframes hero-star-latido {
  0%, 100% { transform: scale(1); opacity: 0.92; }
  50% { transform: scale(1.14); opacity: 1; }
}

/* El estado por defecto es el FINAL: logo dibujado y visible. La animación
   arranca desde lo oculto con fill-mode backwards. Así, si las animaciones no
   llegan a ejecutarse, el logo se ve igualmente en lugar de desaparecer. */

/* Ni retardo ni fill-mode: la espera va dentro de los keyframes. Así el valor
   por defecto de la propiedad ya es el estado final visible, y si las
   animaciones no llegaran a ejecutarse el logo se ve igual en vez de
   desaparecer. Con animation-delay + backwards no era el caso. */
.hero-logo__arc {
  stroke-dasharray: var(--len);
  stroke-dashoffset: 0;
  animation: hero-logo-draw 2.2s var(--ease);
}

/* Longitudes reales de los arcos: 128° y 153° sobre un radio de 100 */
.hero-logo__arc--1 { --len: 223.41; }
.hero-logo__arc--2 { --len: 267.05; animation-duration: 2.6s; }

@keyframes hero-logo-draw {
  0%, 18% { stroke-dashoffset: var(--len); }
  100% { stroke-dashoffset: 0; }
}

/* Los cuerpos orbitan; el anillo no se mueve. El giro va en el grupo y la
   entrada en el círculo, para que no compitan por la misma propiedad.
   El origen local del grupo ya es el centro del anillo, así que rota sobre 0,0.
   El satélite está algo más cerca del centro que el planeta, así que va más
   rápido, como haría de verdad. */
.hero-logo__orbit {
  transform-origin: 0 0;
  animation: orbit-spin 30s linear infinite;
}

.hero-logo__orbit--satelite {
  animation-duration: 22s;
}

.hero-logo__planeta,
.hero-logo__satelite {
  transform-box: fill-box;
  transform-origin: center;
}

.hero-logo__planeta {
  animation: hero-logo-pop 2.9s var(--ease);
}

.hero-logo__satelite {
  animation: hero-logo-pop 3.2s var(--ease);
}

/* Aparecen cuando el anillo ya está trazado: se quedan escondidos el primer
   72% del recorrido y entran al final. */
@keyframes hero-logo-pop {
  0%, 72% { opacity: 0; transform: scale(0.2); }
  100% { opacity: 1; transform: scale(1); }
}

.orbit-dot {
  transform-origin: 50% 50%;
  animation: orbit-spin 12s linear infinite;
}

@keyframes orbit-spin {
  to { transform: rotate(360deg); }
}

/* Indicador de scroll */

/* Vertical a propósito: en horizontal el gesto se leía como "desliza al
   costado" en vez de "baja". */
.hero__scroll-wrap {
  margin-top: 1.75rem;
}

/* En viewports bajos el hero ya llena la pantalla y la pista sobra */
@media (max-height: 720px) {
  .hero__scroll-wrap {
    display: none;
  }
}

.hero__scroll {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-mute);
  font-size: var(--fs-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.hero__scroll-line {
  position: relative;
  width: 1px;
  height: 38px;
  background: var(--line-hi);
  overflow: hidden;
}

/* Destello que cae por el riel */
.hero__scroll-line::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 45%;
  background: var(--grad);
  animation: scroll-drop 2.1s var(--ease-soft) infinite;
}

.hero__scroll-arrow {
  font-size: 0.9rem;
  line-height: 1;
  color: var(--cyan);
  animation: scroll-nudge 2.1s var(--ease-soft) infinite;
}

@keyframes scroll-drop {
  0% { transform: translateY(-100%); opacity: 0; }
  25% { opacity: 1; }
  75% { opacity: 1; }
  100% { transform: translateY(230%); opacity: 0; }
}

@keyframes scroll-nudge {
  0%, 100% { transform: translateY(0); opacity: 0.55; }
  50% { transform: translateY(4px); opacity: 1; }
}

/* --------------------------------------------------------------------------
   8. Tarjetas (base compartida)
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  isolation: isolate;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
  transition: transform var(--t-med) var(--ease), border-color var(--t-med) var(--ease),
    background-color var(--t-med) var(--ease);
}

/* Borde degradado que aparece al pasar el ratón.
   z-index positivo: en tarjetas con imagen opaca (portafolio) un valor
   negativo dejaría el borde superior escondido debajo de la imagen. */
.card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(140deg, rgba(77, 141, 255, 0.75), rgba(168, 85, 247, 0.4) 45%, transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity var(--t-med) var(--ease);
  pointer-events: none;
}

/* Foco de luz que sigue al puntero */
.card::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(
    360px circle at var(--mx, 50%) var(--my, 50%),
    rgba(77, 141, 255, 0.16),
    transparent 62%
  );
  opacity: 0;
  transition: opacity var(--t-med) var(--ease);
  pointer-events: none;
}

.card:hover {
  border-color: transparent;
  background: var(--surface-hi);
}

.card:hover::before,
.card:hover::after {
  opacity: 1;
}

.card__icon {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin-bottom: 1.4rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--grad-soft);
  /* Los iconos son SVG de trazo: heredan el color del texto y llevan un
     único acento en cian, igual que el planeta del isotipo. */
  color: var(--text);
  transition: transform var(--t-med) var(--ease);
}

.card:hover .card__icon {
  transform: translateY(-3px) rotate(-6deg);
}

.card__icon svg {
  width: 26px;
  height: 26px;
}

.card h3 {
  margin-bottom: 0.75rem;
}

.card p {
  font-size: var(--fs-body);
}

/* --------------------------------------------------------------------------
   9. Servicios
   -------------------------------------------------------------------------- */

.services {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--gap);
}

.service__list {
  display: grid;
  gap: 0.15rem;
  margin-top: 1.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}

.service__list li {
  position: relative;
  padding: 0.5rem 0 0.5rem 1.75rem;
  color: var(--text-dim);
  font-size: 0.95rem;
}

.service__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.15rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--grad);
  box-shadow: 0 0 10px rgba(77, 141, 255, 0.7);
}

.service__tag {
  position: absolute;
  top: clamp(1.6rem, 3vw, 2.4rem);
  right: clamp(1.6rem, 3vw, 2.4rem);
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--text-mute);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   10. Mockup del chatbot
   -------------------------------------------------------------------------- */

.chatbot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.chat-window {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-hi);
  border-radius: var(--r-lg);
  background: linear-gradient(170deg, rgba(15, 19, 32, 0.95), rgba(8, 10, 18, 0.95));
  box-shadow: var(--lift), 0 0 80px -40px rgba(77, 141, 255, 0.6);
  overflow: hidden;
}

.chat-window__bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.025);
}

.chat-window__dots {
  display: flex;
  gap: 6px;
}

.chat-window__dots i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line-hi);
}

.chat-window__dots i:first-child { background: #ff5f57; }
.chat-window__dots i:nth-child(2) { background: #febc2e; }
.chat-window__dots i:nth-child(3) { background: #28c840; }

.chat-window__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
}

.chat-window__status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
  color: var(--text-mute);
  font-size: var(--fs-micro);
}

.chat-window__status::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #28c840;
  box-shadow: 0 0 8px #28c840;
}

.chat-log {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 1.4rem 1.2rem;
}

.chat-msg {
  display: flex;
  max-width: 82%;
}

.chat-msg--bot { align-self: flex-start; }
.chat-msg--user { align-self: flex-end; }

.chat-msg p {
  padding: 0.75rem 1rem;
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--text);
}

.chat-msg--bot p {
  border: 1px solid var(--line);
  border-radius: 4px 16px 16px 16px;
  background: rgba(255, 255, 255, 0.045);
  color: var(--text-dim);
}

.chat-msg--user p {
  border-radius: 16px 4px 16px 16px;
  background: var(--grad);
  color: #fff;
}

.chat-window__composer {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.1rem;
  border-top: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.02);
  color: var(--text-mute);
  font-size: 0.88rem;
}

.chat-window__composer span {
  flex: 1;
}

.chat-window__send {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--grad-soft);
  border: 1px solid var(--line);
  font-size: 0.8rem;
}

.chatbot__aside h2 {
  margin-bottom: 1.2rem;
}

.chatbot__tagline {
  margin-bottom: 1.2rem;
  color: var(--text);
  font-size: var(--fs-lead);
  font-weight: 500;
  line-height: 1.4;
}

.chatbot__points {
  display: grid;
  gap: 0.85rem;
  margin: 1.8rem 0 2.2rem;
}

.chatbot__points li {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  color: var(--text-dim);
  font-size: 0.97rem;
}

.chatbot__points b {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin-top: 2px;
  border-radius: 50%;
  background: var(--grad-soft);
  border: 1px solid var(--line);
  color: var(--cyan);
  font-size: 0.7rem;
}

/* --------------------------------------------------------------------------
   11. FAQ
   -------------------------------------------------------------------------- */

.faq {
  max-width: 52rem;
  margin-inline: auto;
  border-top: 1px solid var(--line);
}

.faq__item {
  border-bottom: 1px solid var(--line);
}

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  width: 100%;
  padding: 1.5rem 0.25rem;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  font-weight: 600;
  text-align: left;
  color: var(--text);
  transition: color var(--t-fast) var(--ease);
}

.faq__q:hover {
  color: var(--blue);
}

.faq__sign {
  position: relative;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
}

.faq__sign::before,
.faq__sign::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 13px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--blue);
  translate: -50% -50%;
  transition: transform var(--t-med) var(--ease);
}

.faq__sign::after {
  transform: rotate(90deg);
}

.faq__q[aria-expanded='true'] .faq__sign::after {
  transform: rotate(0deg);
}

/* Animación de altura sin JS: grid-template-rows 0fr -> 1fr */
.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-med) var(--ease);
}

.faq__a > div {
  overflow: hidden;
}

.faq__item.is-open .faq__a {
  grid-template-rows: 1fr;
}

.faq__a p {
  padding: 0 0.25rem 1.6rem;
  font-size: 0.98rem;
}

/* --------------------------------------------------------------------------
   12. Línea de tiempo (Nosotros)
   -------------------------------------------------------------------------- */

.timeline {
  position: relative;
  max-width: 46rem;
  margin-inline: auto;
  padding-left: clamp(2rem, 5vw, 3.5rem);
}

.timeline__rail {
  position: absolute;
  top: 0.6rem;
  bottom: 0.6rem;
  left: 0;
  width: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}

.timeline__rail::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grad);
  transform: scaleY(var(--progress, 1));
  transform-origin: top;
}

.timeline__item {
  position: relative;
  padding-bottom: clamp(2rem, 4vw, 3rem);
}

.timeline__item:last-child {
  padding-bottom: 0;
}

.timeline__item::before {
  content: '';
  position: absolute;
  top: 0.55rem;
  left: calc(clamp(2rem, 5vw, 3.5rem) * -1 - 5px);
  width: 12px;
  height: 12px;
  border: 2px solid var(--bg);
  border-radius: 50%;
  background: var(--line-hi);
  transition: background var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease);
}

.timeline__item.is-reached::before {
  background: var(--cyan);
  box-shadow: 0 0 0 4px rgba(34, 211, 238, 0.18), 0 0 16px rgba(34, 211, 238, 0.8);
}

.timeline__step {
  display: inline-block;
  margin-bottom: 0.6rem;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cyan);
}

.timeline__item h3 {
  margin-bottom: 0.6rem;
}

/* --------------------------------------------------------------------------
   13. Equipo y valores
   -------------------------------------------------------------------------- */

.grid-2,
.grid-3,
.grid-4 {
  display: grid;
  gap: var(--gap);
}

.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.member {
  text-align: left;
}

.member__avatar {
  display: block;
  width: 71.4px;
  height: 71.4px;
  margin-bottom: 1.3rem;
  border-radius: 50%;
  object-fit: cover;
  transition: transform var(--t-med) var(--ease);
}

.member:hover .member__avatar {
  transform: scale(1.06) rotate(-5deg);
}

.member__role {
  margin-bottom: 0.9rem;
  color: var(--cyan);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.02em;
}

/* El correo de cada uno, para que "somos los que van a contestar tus correos"
   sea literal y no una promesa. El punto se enciende al pasar por encima. */
.member__mail {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 1.25rem;
  color: var(--text-dim);
  font-size: var(--fs-small);
  letter-spacing: -0.01em;
  transition: color var(--t-fast) var(--ease);
}

.member__mail::before {
  content: '';
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--cyan);
  opacity: 0.65;
  transition: opacity var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease);
}

.member__mail:hover {
  color: var(--text);
}

.member__mail:hover::before {
  opacity: 1;
  box-shadow: 0 0 10px var(--cyan);
}

/* Declaración grande de misión */

.statement {
  max-width: 34ch;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.4vw, 2.6rem);
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: -0.03em;
  color: var(--text);
}

/* Estado base y respaldo sin JS. Cuando effects.js parte la frase en letras,
   repinta el degradado carácter a carácter: background-clip:text sobre el <em>
   deja de tener glifos propios en cuanto el texto pasa a vivir en hijos, y la
   frase se volvía invisible. */
.statement em {
  font-style: normal;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.statement em .char {
  will-change: transform, opacity, filter;
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

/* --------------------------------------------------------------------------
   14. Portafolio
   -------------------------------------------------------------------------- */

.filters {
  position: relative;
  display: inline-flex;
  gap: 0.25rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
  padding: 0.3rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
}

/* Píldora deslizante */
.filters__pill {
  position: absolute;
  top: 0.3rem;
  bottom: 0.3rem;
  left: 0;
  border-radius: var(--r-pill);
  background: var(--grad);
  transform: translateX(var(--pill-x, 0));
  width: var(--pill-w, 0);
  transition: transform var(--t-med) var(--ease), width var(--t-med) var(--ease);
  pointer-events: none;
}

.filters__btn {
  position: relative;
  z-index: 1;
  min-height: 42px;
  padding: 0.55rem 1.35rem;
  border-radius: var(--r-pill);
  color: var(--text-dim);
  font-size: 0.92rem;
  font-weight: 500;
  transition: color var(--t-med) var(--ease);
}

.filters__btn:hover {
  color: var(--text);
}

.filters__btn.is-active {
  color: #fff;
}

.work {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--gap);
}

.work__item {
  padding: 0;
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease),
    border-color var(--t-med) var(--ease);
}

/* GSAP deja opacity y transform en el atributo style al revelar la tarjeta,
   así que el estado de salida necesita ganar a esos valores en línea. */
.work__item.is-hiding {
  opacity: 0 !important;
  transform: scale(0.94) !important;
}

.work__item[hidden] {
  display: none;
}

.work__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: #0a0d16;
}

/* Las capturas reales conviven con los marcadores SVG hasta que se sustituyan
   todos los proyectos, así que ambos reciben el mismo tratamiento. */
.work__media svg,
.work__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* El marco es 16:10 y las capturas no siempre lo son, así que algo se
     recorta. Anclando arriba, lo que se pierde sale del pie de la captura
     en vez de partirse entre la cabecera y el pie. */
  object-position: top center;
  transition: transform var(--t-slow) var(--ease);
}

.work__item:hover .work__media svg,
.work__item:hover .work__media img {
  transform: scale(1.07);
}

/* Suave: funde el pie de la imagen con la tarjeta sin tapar la captura. */
.work__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(5, 6, 10, 0.5), transparent 38%);
}

.work__tag {
  position: absolute;
  top: 1rem;
  left: 1rem;
  z-index: 2;
  padding: 0.3rem 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--r-pill);
  background: rgba(5, 6, 10, 0.6);
  backdrop-filter: blur(8px);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.work__body {
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
}

.work__body h3 {
  margin-bottom: 0.6rem;
}

/* Enlace extendido: el texto del enlace es el nombre del proyecto —lo que un
   lector de pantalla debe anunciar— pero la zona pulsable cubre la tarjeta
   entera. Así se evita envolver todo en un <a> gigante. */
.work__link {
  color: inherit;
  transition: color var(--t-fast) var(--ease);
}

.work__link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
}

.work__item:hover .work__link {
  color: var(--blue);
}


.work__body p {
  font-size: 0.95rem;
  margin-bottom: 1.3rem;
}

.work__stack {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.work__stack span {
  padding: 0.28rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(168, 85, 247, 0.09);
  color: #cbb2f5;
  font-size: var(--fs-micro);
}

/* Tarjetas de chatbot: sin imagen que mostrar, así que no heredan el molde
   de .work__item (pensado para una captura a sangre). Vuelven al padding
   normal de .card y su único elemento interactivo es el enlace de WhatsApp. */
.work__item--bot {
  padding: clamp(1.6rem, 3vw, 2.4rem);
}

.work__item--bot h3 {
  margin-bottom: 0.6rem;
}

.work__item--bot p {
  margin-bottom: 1.6rem;
  font-size: var(--fs-body);
}

.work__whatsapp {
  width: 100%;
}

.work__whatsapp-icon {
  flex: none;
  width: 20px;
  height: 20px;
}

.work__empty {
  padding: 3rem 1rem;
  text-align: center;
  color: var(--text-mute);
}

/* --------------------------------------------------------------------------
   15. Ventana ampliada del portafolio
   -------------------------------------------------------------------------- */

body.modal-open {
  overflow: hidden;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: none;
  place-items: center;
  padding: clamp(0.75rem, 3vw, 2.5rem);
}

.lightbox.is-open {
  display: grid;
}

.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 4, 8, 0.86);
  backdrop-filter: blur(10px);
}

.lightbox__panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: min(100%, 1080px);
  max-height: calc(100svh - clamp(1.5rem, 6vw, 5rem));
  border: 1px solid var(--line-hi);
  border-radius: var(--r-lg);
  background: linear-gradient(170deg, rgba(16, 20, 34, 0.98), rgba(8, 10, 18, 0.98));
  box-shadow: var(--lift);
  overflow: hidden;
}

/* Sin fill-mode y partiendo de lo oculto: si la animación no corre, la
   ventana se ve igual. */
.lightbox.is-open .lightbox__panel {
  animation: lightbox-in 0.4s var(--ease);
}

@keyframes lightbox-in {
  from { opacity: 0; transform: translateY(18px) scale(0.985); }
}

.lightbox__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line-hi);
  border-radius: 50%;
  background: rgba(5, 6, 10, 0.7);
  backdrop-filter: blur(8px);
  color: var(--text);
  font-size: 1.5rem;
  line-height: 1;
  transition: background-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}

.lightbox__close:hover {
  background: rgba(168, 85, 247, 0.3);
  transform: rotate(90deg);
}

/* --- Escenario de la captura --- */

.lightbox__stage {
  position: relative;
  display: grid;
  place-items: center;
  flex: 1;
  min-height: 0;
  background: #06070b;
}

.lightbox__frame {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  min-height: 0;
}

.lightbox__shot {
  display: block;
  max-width: 100%;
  max-height: 100%;
  line-height: 0;
}

.lightbox__frame img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--t-med) var(--ease);
}

.lightbox__frame img.is-loaded {
  opacity: 1;
}

.lightbox__nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-top: -23px;
  border: 1px solid var(--line-hi);
  border-radius: 50%;
  background: rgba(5, 6, 10, 0.75);
  backdrop-filter: blur(8px);
  color: var(--text);
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}

.lightbox__nav[data-dir='prev'] { left: 0.9rem; }
.lightbox__nav[data-dir='next'] { right: 0.9rem; }

.lightbox__nav:hover {
  border-color: rgba(77, 141, 255, 0.7);
  background: rgba(77, 141, 255, 0.28);
}

.lightbox__nav[hidden] {
  display: none;
}

.lightbox__counter {
  position: absolute;
  right: 0.9rem;
  bottom: 0.9rem;
  z-index: 2;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(5, 6, 10, 0.75);
  color: var(--text-dim);
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
}

/* --- Puntos --- */

/* Barra inferior: solo los puntos de navegación. La ventana es para ver
   capturas; el título, la descripción y el stack ya están en la tarjeta, y al
   sitio se entra pulsando la propia captura.
   flex-shrink:0 para que la imagen no la comprima y le recorte el contenido. */
.lightbox__bar {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 1rem;
  border-top: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.02);
}

.lightbox__dots {
  display: flex;
  flex: 1;
  justify-content: center;
  gap: 0.5rem;
}

.lightbox__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 50%;
  background: var(--line-hi);
  transition: width var(--t-med) var(--ease), background-color var(--t-med) var(--ease);
}

.lightbox__dot.is-active {
  width: 26px;
  border-radius: var(--r-pill);
  background: var(--grad);
}

/* --- Ventana ampliada: sitio en vivo (proyectos que no bloquean el iframe) --- */

/* Más ancha que la de capturas: aquí hay un sitio real que recorrer,
   no una sola imagen que mirar. */
.lightbox__panel.is-embed {
  width: min(100%, 1360px);
  /* Sin esto, el iframe (height:100%) no tiene de qué heredar altura: el
     panel normal solo tiene max-height y se ajusta al contenido, que para
     una imagen basta pero para un iframe se queda en su alto por defecto. */
  height: min(85vh, 900px);
}

/* Barrita tipo navegador: los tres puntos, la URL y el enlace directo.
   El mismo lenguaje visual que la ventana del chatbot del home, para que se
   lea como "esto es una ventana de verdad" y no como un adorno más. */
.lightbox__browserbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.025);
}

.lightbox__trafficlights {
  display: flex;
  flex-shrink: 0;
  gap: 6px;
}

.lightbox__trafficlights i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line-hi);
}

.lightbox__url {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-dim);
  font-size: var(--fs-micro);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lightbox__open {
  flex-shrink: 0;
  color: var(--text-dim);
  font-size: var(--fs-micro);
  white-space: nowrap;
  transition: color var(--t-fast) var(--ease);
}

.lightbox__open:hover {
  color: var(--blue);
}

/* El iframe llena todo el escenario: aquí no se centra ni se recorta como
   una captura, es una ventana real al sitio. */
.lightbox__embed {
  display: none;
  width: 100%;
  height: 100%;
  border: 0;
  /* La mayoría de sitios reales parten de blanco: evita el parpadeo oscuro
     del fondo de la ventana mientras el iframe carga. */
  background: #fff;
}

.lightbox__panel.is-embed .lightbox__embed {
  display: block;
}



@media (max-width: 620px) {
  .lightbox__nav {
    width: 40px;
    height: 40px;
  }
}

/* --------------------------------------------------------------------------
   16. Contacto
   -------------------------------------------------------------------------- */

.contact {
  position: relative;
  padding: clamp(2.5rem, 6vw, 5rem) clamp(1.5rem, 5vw, 4rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--grad-soft);
  text-align: center;
  overflow: hidden;
}

.contact::after {
  content: '';
  position: absolute;
  top: -60%;
  left: 50%;
  width: 120%;
  aspect-ratio: 1;
  translate: -50% 0;
  background: radial-gradient(circle, rgba(77, 141, 255, 0.14), transparent 60%);
  pointer-events: none;
}

.contact > * {
  position: relative;
  z-index: 1;
}

.contact h2 {
  margin-bottom: 1.1rem;
}

.contact p {
  max-width: 48ch;
  margin-inline: auto;
  font-size: var(--fs-lead);
}

.contact__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.9rem;
  margin-top: 2.4rem;
}

.contact__note {
  margin-top: 1.6rem;
  color: var(--text-mute);
  font-size: var(--fs-small);
}

/* --------------------------------------------------------------------------
   17. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  /* Recorta la marca de agua, que desborda a propósito */
  overflow: hidden;
  margin-top: clamp(4rem, 9vw, 8rem);
  border-top: 1px solid var(--line);
  background: linear-gradient(to bottom, transparent, rgba(10, 13, 22, 0.85));
}

/* El contenido va por encima de la marca de agua */
.site-footer .shell {
  position: relative;
  z-index: 1;
}

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-block: clamp(3rem, 6vw, 4.5rem);
}

.footer__about p {
  max-width: 34ch;
  margin: 1.1rem 0 1.6rem;
  font-size: 0.95rem;
}

.footer__col h4 {
  margin-bottom: 1.1rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-mute);
}

.footer__col a,
.footer__col p {
  display: block;
  margin-bottom: 0.65rem;
  color: var(--text-dim);
  font-size: 0.95rem;
  transition: color var(--t-fast) var(--ease);
}

.footer__col a:hover {
  color: var(--blue);
}

.socials {
  display: flex;
  gap: 0.6rem;
}

.socials a {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  font-size: 0.95rem;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
    background-color var(--t-fast) var(--ease);
}

.socials a:hover {
  transform: translateY(-3px);
  border-color: rgba(77, 141, 255, 0.7);
  background: rgba(77, 141, 255, 0.14);
}

/* Logotipo tipográfico gigante */
/* Marca de agua: va detrás del contenido, no debajo. Antes era un bloque
   propio de unos 270px de alto y era lo que alargaba el pie. */
.footer__wordmark {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Centrada sobre el contenido, no anclada abajo: así cruza por detrás de
     las columnas, que es donde se lee como marca de agua. */
  translate: -50% -50%;
  z-index: 0;
  font-family: var(--font-display);
  font-size: clamp(5rem, 24vw, 21rem);
  font-weight: 700;
  /* La caja debe cubrir los glifos enteros: background-clip:text solo pinta
     dentro de ella, y con 0.8 la tilde de la Ó quedaba fuera y se perdía.
     Al estar posicionada en absoluto, crecer no ocupa espacio. */
  line-height: 1.15;
  letter-spacing: -0.05em;
  white-space: nowrap;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.035));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  user-select: none;
  pointer-events: none;
}

/* --- El final de la página: el pie se convierte en luz -------------------

   --lit va de 0 (pie oscuro, como el resto del sitio) a 1 (blanco cegador).
   Lo enciende un IntersectionObserver en main.js al llegar el pie.

   Dos reglas que sostienen todo el efecto:

   1. Redefinir los tokens de color AQUÍ dentro. Como las variables CSS se
      heredan, todo el contenido del pie —textos, bordes, superficies,
      hovers— se invierte solo, sin escribir una regla por elemento.

   2. El resplandor de encima y el fondo del pie usan EXACTAMENTE el mismo
      color. rgba(255,255,255,L) sobre el fondo de página compone lo mismo
      que color-mix(#fff L%, --bg), así que el borde superior no existe:
      la luz entra en el pie sin costura y el pie es la propia luz.

   Si el JS no corre, --lit se queda en 1: pie blanco con texto negro, que
   es un estado legible. Nada depende del JS para poder leerse. */

@property --lit {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}

.site-footer--star {
  --lit: 1;
  /* Porcentaje de mezcla, acotado por si el valor se sale de rango */
  --mezcla: clamp(0%, calc(var(--lit) * 100%), 100%);

  --text: color-mix(in srgb, #070910 var(--mezcla), #eef1f8);
  --text-dim: color-mix(in srgb, #3f4657 var(--mezcla), #a7b0c7);
  --text-mute: color-mix(in srgb, #4f5668 var(--mezcla), #6b7590);
  --line: color-mix(in srgb, rgba(7, 9, 16, 0.14) var(--mezcla), rgba(255, 255, 255, 0.09));
  --line-hi: color-mix(in srgb, rgba(7, 9, 16, 0.24) var(--mezcla), rgba(255, 255, 255, 0.16));
  --surface: color-mix(in srgb, rgba(7, 9, 16, 0.05) var(--mezcla), rgba(255, 255, 255, 0.028));
  --blue: color-mix(in srgb, #1b46c9 var(--mezcla), #4d8dff);

  color: var(--text);
  /* El horizonte lo marca la luz, nunca una línea */
  border-top-color: rgba(255, 255, 255, calc((1 - var(--lit)) * 0.09));

  /* El limbo de la estrella.

     Un border-radius elíptico NO sirve: la curvatura de una elipse se dispara
     en los extremos del eje mayor, así que el arco llega casi vertical a los
     lados y se ve el quiebre. Un arco de CÍRCULO tiene radio constante de un
     extremo al otro, que es lo que se pide.

     Se dibuja con un degradado radial de radio gigante (3,5 anchos de
     pantalla) centrado muy por debajo: de ese círculo solo se ve el casquete
     de arriba. La geometría sale de ahí: si R = 3,5·W, el arco baja
     R - √(R² - (W/2)²) = 0,0359·W entre el centro y los bordes. Subir ese
     factor aplana la curva; bajarlo la pronuncia. */
  --radio: 350vw;
  --sagita: 3.59vw;
  --halo: 330px;

  /* Un único color para el pie y para el corazón del degradado: al ser
     literalmente el mismo valor, en el borde no puede haber costura. */
  --luz: color-mix(in srgb, #ffffff var(--mezcla), #05060a);

  background-color: var(--luz);
  background-image: none;
  border-radius: 0;
  box-shadow: none;

  /* El pie deja de recortar para que el casquete pueda salirse por arriba.
     De recortar la marca de agua se encarga ahora .footer__marca. */
  overflow: visible;

  /* La ignición. Rápida y con la curva empinada en el medio: el cruce en el
     que texto y fondo comparten gris es el punto ilegible del efecto, y así
     se pasa por él en un parpadeo en vez de quedarse ahí. */
  transition: --lit 900ms cubic-bezier(0.83, 0, 0.17, 1);
}

/* Estado apagado. La variante del <html> es solo para el primer pintado:
   fija el apagado SIN transición, para que una recarga con la página abajo
   no muestre el pie blanco un instante. */
.site-footer--star.is-cold {
  --lit: 0;
}

.is-pie-frio .site-footer--star {
  --lit: 0;
  transition: none;
}

/* El casquete, dibujado justo encima del pie. El halo va en el mismo
   degradado que el relleno: nace del mismo color, así que la luz y el pie
   son una sola cosa y el borde inferior de esta franja no se ve. */
.site-footer--star::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  translate: 0 -100%;
  z-index: 0;
  height: calc(var(--sagita) + var(--halo));
  pointer-events: none;
  background: radial-gradient(
    circle var(--radio) at 50% calc(var(--halo) + var(--radio)),
    var(--luz) 0 var(--radio),
    rgba(255, 255, 255, calc(var(--lit) * 0.95)) calc(var(--radio) + 16px),
    rgba(240, 249, 255, calc(var(--lit) * 0.72)) calc(var(--radio) + 62px),
    rgba(206, 230, 255, calc(var(--lit) * 0.46)) calc(var(--radio) + 135px),
    rgba(168, 203, 255, calc(var(--lit) * 0.24)) calc(var(--radio) + 230px),
    rgba(150, 190, 255, 0) calc(var(--radio) + var(--halo)));
}

/* Recorta la marca de agua, que desborda a propósito. Antes lo hacía el
   overflow del pie, pero ahora el pie tiene que dejar salir el casquete. */
.footer__marca {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* La marca de agua pasa de tinta clara a tinta oscura cruzándose consigo misma */
.site-footer--star .footer__wordmark {
  background-image:
    linear-gradient(to bottom,
      rgba(7, 9, 16, calc(var(--lit) * 0.09)),
      rgba(7, 9, 16, calc(var(--lit) * 0.034))),
    linear-gradient(to bottom,
      rgba(255, 255, 255, calc((1 - var(--lit)) * 0.11)),
      rgba(255, 255, 255, calc((1 - var(--lit)) * 0.035)));
}

/* El logotipo es blanco: sobre el fondo encendido hay que pasarlo a negro.
   brightness(0) deja la silueta y respeta la transparencia. */
.site-footer--star .brand__logo {
  filter: brightness(calc(1 - var(--lit)));
}

.site-footer--star .socials a:hover {
  border-color: color-mix(in srgb, rgba(27, 70, 201, 0.5) var(--mezcla), rgba(77, 141, 255, 0.7));
  background: color-mix(in srgb, rgba(27, 70, 201, 0.09) var(--mezcla), rgba(77, 141, 255, 0.14));
}


/* --------------------------------------------------------------------------
   18. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .chatbot,
  .split {
    grid-template-columns: 1fr;
  }

  .hero__orbits {
    right: -28vw;
    width: min(80vw, 480px);
    opacity: 0.4;
  }
}

@media (max-width: 780px) {
  .menu-toggle {
    display: grid;
  }

  .nav {
    position: fixed;
    inset: 0;
    z-index: -1;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 0.5rem;
    padding: 6rem var(--gutter) 3rem;
    background: rgba(5, 6, 10, 0.96);
    backdrop-filter: blur(20px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t-med) var(--ease), visibility var(--t-med);
  }

  .nav.is-open {
    opacity: 1;
    visibility: visible;
  }

  .nav__link {
    padding: 1rem 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-weight: 600;
    letter-spacing: -0.03em;
    color: var(--text);
    opacity: 0;
    transform: translateY(18px);
    transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
  }

  .nav.is-open .nav__link {
    opacity: 1;
    transform: none;
    transition-delay: calc(60ms * var(--i, 0) + 80ms);
  }

  .nav__link::after {
    display: none;
  }

  .nav__cta {
    margin: 1.75rem 0 0;
    min-height: 54px;
    font-size: 1rem;
    opacity: 0;
    transform: translateY(18px);
    transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
  }

  .nav.is-open .nav__cta {
    opacity: 1;
    transform: none;
    transition-delay: 320ms;
  }

  /* Con el menú desplegado la píldora estorba: se deshace y deja ver el fondo */
  body.nav-open .header__inner {
    background: transparent;
    backdrop-filter: none;
    border-color: transparent;
    box-shadow: none;
  }

  body.nav-open {
    overflow: hidden;
  }
}

@media (max-width: 620px) {
  .hero {
    min-height: auto;
    padding-top: 8rem;
  }

  .hero__actions .btn {
    width: 100%;
  }

  .footer__grid {
    grid-template-columns: 1fr;
  }

  .work {
    grid-template-columns: 1fr;
  }

  .filters {
    display: flex;
    width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .filters::-webkit-scrollbar {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   19. Movimiento reducido
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    /* Sin esto, una animación con retardo mantendría su fotograma inicial
       durante ese tiempo: el logo del hero se quedaba oculto medio segundo. */
    animation-delay: -0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .hero__scroll-line::after {
    height: 100%;
    opacity: 1;
    transform: none;
  }
}
