/* ============================================================
   NODO VITAL — HERO FX
   Capa de efectos "WOW" para el hero. Se carga DESPUÉS de
   styles.css y solo añade / sobreescribe lo del hero.
   Quitar = borrar el <link> y el <script> de hero-fx.
   ============================================================ */

/* ---------- 1. Canvas de red interactiva ----------
   Reemplaza visualmente al SVG .hero-network. El canvas
   reacciona al mouse: las líneas se tensan e iluminan. */
.hero-fx-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
}
/* Ocultamos la red SVG vieja: el canvas la sustituye */
.hero-network { display: none !important; }

/* El hero ahora capta el mouse para alimentar el canvas */
.hero { cursor: none; }
.hero-inner { cursor: auto; }

/* ---------- 2. Glow que sigue al cursor ---------- */
.hero-cursor-glow {
  position: absolute;
  top: 0; left: 0;
  width: 460px; height: 460px;
  margin: -230px 0 0 -230px;
  border-radius: 50%;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(circle,
              rgba(255, 140, 130, 0.16) 0%,
              rgba(116, 167, 255, 0.10) 35%,
              transparent 70%);
  opacity: 0;
  transition: opacity 0.6s ease;
  will-change: transform;
}
.hero.fx-active .hero-cursor-glow { opacity: 1; }

/* ---------- 3. Núcleo vital: flotado + vida extra ---------- */
/* Grupo envolvente que flota suavemente. El <g class="sat">
   interior conserva su translate() posicional y su animación
   de entrada satIn intactos. */
.vital-node .sat-float {
  animation: satFloat var(--dur, 7s) ease-in-out infinite;
  animation-delay: var(--fdelay, 2s);
}
@keyframes satFloat {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(var(--fx, 4px), var(--fy, -5px)); }
}

/* Anillo extra que respira */
.vital-node .ring-breath {
  transform-origin: 260px 260px;
  animation: ringBreath 6s ease-in-out infinite;
}
@keyframes ringBreath {
  0%, 100% { transform: scale(1);    opacity: 0.35; }
  50%      { transform: scale(1.06); opacity: 0.7;  }
}

/* Pulso de energía que viaja por las conexiones del núcleo.
   Son <line> duplicadas que el JS inyecta con clase .conn-pulse */
.vital-node .conn-pulse {
  stroke: #ff8c82;
  stroke-width: 2.2;
  stroke-linecap: round;
  filter: drop-shadow(0 0 4px rgba(255, 140, 130, 0.9));
  animation: connPulse 2.8s var(--ease-out) infinite;
  animation-delay: var(--pdelay, 0s);
}
@keyframes connPulse {
  0%   { stroke-dashoffset: var(--len); opacity: 0; }
  12%  { opacity: 1; }
  55%  { opacity: 1; }
  78%  { stroke-dashoffset: calc(var(--len) * -1); opacity: 0; }
  100% { stroke-dashoffset: calc(var(--len) * -1); opacity: 0; }
}

/* El núcleo central late con más cuerpo */
.vital-node .core {
  transform-box: view-box;
  transform-origin: 260px 260px;
  animation: coreBreath 4.5s ease-in-out infinite;
}
@keyframes coreBreath {
  0%, 100% { transform: scale(1);    }
  50%      { transform: scale(1.045); }
}

/* Segundo anillo de pulso del core, desfasado */
.vital-node .core-pulse-2 {
  transform-origin: 260px 260px;
  animation: corePulse 2.4s ease-out infinite;
  animation-delay: 1.2s;
}

/* ---------- 4. Título: reveal por máscara + palabra que cambia ---------- */
/* Máscara de cortina para cada línea del H1 */
.hero-title .line {
  position: relative;
}
/* Palabra que rota: "afuera" -> "adentro" */
.word-swap {
  display: inline-block;
  position: relative;
  min-width: 4.6em;          /* reserva espacio, evita salto */
  text-align: left;
  vertical-align: bottom;
}
.word-swap .w {
  display: inline-block;
  transition: transform 0.55s var(--ease-out),
              opacity 0.45s var(--ease-out);
}
.word-swap .w.out {
  position: absolute;
  left: 0; top: 0;
}
.word-swap.swapping .w.in  { transform: translateY(0);     opacity: 1; }
.word-swap.swapping .w.out { transform: translateY(-0.9em); opacity: 0; }

/* Estado base: "in" escondida abajo */
.word-swap .w.in  { transform: translateY(0.9em); opacity: 0; }
.word-swap .w.out { transform: translateY(0);      opacity: 1; }

/* Cuando el JS marca .swapped, las posiciones se intercambian */
.word-swap.swapped .w.in  { transform: translateY(0);      opacity: 1; }
.word-swap.swapped .w.out { transform: translateY(-0.9em); opacity: 0; }

/* ---------- 5. Aparición del bloque visual con escala ---------- */
.hero-visual {
  opacity: 0;
  transform: scale(0.92) translateY(20px);
  animation: heroVisualIn 1.4s var(--ease-out) 0.4s forwards;
}
@keyframes heroVisualIn {
  to { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---------- Accesibilidad ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero-fx-canvas { display: none; }
  .hero-network   { display: block !important; opacity: 0.4; }
  .hero { cursor: auto; }
  .hero-cursor-glow,
  .vital-node .conn-pulse { display: none; }
  .vital-node .sat-float,
  .vital-node .ring-breath,
  .vital-node .core { animation: none; }
  .hero-visual { opacity: 1; transform: none; animation: none; }
  .word-swap .w.in  { display: none; }
  .word-swap .w.out { position: static; }
}

/* ---------- Móvil: aligeramos ---------- */
@media (max-width: 700px) {
  .hero-cursor-glow { display: none; }
  .hero { cursor: auto; }
}
