/* ============================================================
   WEBMASTER LEO — Capa de efectos

   Recurso de marca: EL IRIS.
   Funde los cuatro elementos del brief §2 en una sola figura:
   ojo felino (vigilancia) + lupa (análisis) + gráfica ascendente
   (crecimiento) + líneas de velocidad (cohete). Se usa a tres
   escalas: grande en el hero, mediano como marca de sección,
   pequeño como viñeta. Es lo que permite reconocer la marca
   aunque el logo no esté a la vista — brief §21.

   Todo lo de aquí es decorativo y se apaga entero al final del
   archivo con prefers-reduced-motion.
   ============================================================ */

/* ============================================================
   1. ESCENA
   ============================================================ */
.scene { position: relative; isolation: isolate; overflow: hidden; }
.scene > .wrap { position: relative; z-index: 5; }
.fx { position: absolute; inset: 0; pointer-events: none; }

/* Grano: quita el aspecto plano del color digital. Sin esto, los
   negros grandes se ven baratos y bandean en pantallas malas. */
.fx-grain {
  position: absolute; inset: 0; z-index: 4; pointer-events: none;
  opacity: .22; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

/* Velo: el brief pide alto contraste. Sin degradado de protección,
   el texto blanco compite con la iluminación azul. */
.fx-veil {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(98deg,
    rgba(5,7,10,.96) 2%, rgba(5,7,10,.82) 34%, rgba(5,7,10,.38) 72%, rgba(5,7,10,.6) 100%);
}
.fx-veil--soft {
  background: radial-gradient(130% 100% at 50% 40%, transparent 18%, rgba(5,7,10,.9) 78%);
}

/* Profundidad: degradado premium oficial #05070A → #063B8F → #0878F9,
   contenido para que el azul ilumine y no domine (regla 60/30/10). */
.fx-depth {
  position: absolute; inset: -30% -15% auto -15%; height: 120%; z-index: 0;
  background:
    radial-gradient(48% 55% at 22% 30%, rgba(6,59,143,.55), transparent 70%),
    radial-gradient(40% 46% at 78% 18%, rgba(8,120,249,.28), transparent 72%),
    radial-gradient(36% 40% at 62% 78%, rgba(0,200,255,.14), transparent 74%);
  filter: blur(46px);
  animation: fx-drift 18s var(--e-soft) infinite alternate;
}
@keyframes fx-drift { to { transform: translate3d(2.5%, 1.5%, 0) scale(1.08); opacity: .78; } }

/* ============================================================
   2. LÍNEAS DE VELOCIDAD — brief §15
   Diagonales que cruzan la escena. Comunican dirección y avance.
   ============================================================ */
.fx-speed {
  position: absolute; inset: -20%; z-index: 1; opacity: .5;
  background-image: repeating-linear-gradient(
    108deg,
    transparent 0 38px,
    rgba(8,120,249,.16) 38px 39px,
    transparent 39px 96px
  );
  -webkit-mask-image: radial-gradient(80% 70% at 70% 40%, #000 10%, transparent 76%);
          mask-image: radial-gradient(80% 70% at 70% 40%, #000 10%, transparent 76%);
  animation: fx-streak 9s linear infinite;
}
/* El bucle es invisible porque el desplazamiento (96px sobre el eje
   de la trama) equivale exactamente a un periodo del patrón. */
@keyframes fx-streak { to { background-position: 96px 0; } }

/* ============================================================
   3. EL IRIS — recurso de marca
   ============================================================ */
.iris { display: block; width: 100%; height: auto; overflow: visible; }

.iris .ring {
  fill: none; stroke: rgba(8,120,249,.30); stroke-width: 1;
}
.iris .ring--outer { stroke: rgba(8,120,249,.18); }
.iris .ring--dash {
  stroke: rgba(0,200,255,.45); stroke-width: 1.2;
  stroke-dasharray: 3 9; transform-origin: 50% 50%;
  animation: fx-rotate 46s linear infinite;
}
.iris .ring--dash-rev {
  stroke: rgba(8,120,249,.35); stroke-dasharray: 2 14;
  transform-origin: 50% 50%; animation: fx-rotate 34s linear infinite reverse;
}
@keyframes fx-rotate { to { transform: rotate(360deg); } }

/* Barrido de vigilancia: el gesto del ojo felino. */
.iris .sweep { transform-origin: 50% 50%; animation: fx-rotate 7.5s linear infinite; }

/* Pupila: elipse vertical, no círculo — es lo que la hace felina. */
.iris .pupil { fill: url(#irisCore); }
.iris .pupil-slit { fill: var(--black); opacity: .82; }

.iris .node { fill: var(--cyan); opacity: .55; animation: fx-pulse 3.6s var(--e-soft) infinite alternate; }
.iris .node:nth-of-type(2n) { animation-duration: 4.4s; animation-delay: -1.2s; fill: var(--blue); }
.iris .node:nth-of-type(3n) { animation-duration: 5.2s; animation-delay: -2.6s; fill: var(--yellow); opacity: .5; }
@keyframes fx-pulse { to { opacity: 1; r: 3.6; } }

/* Gráfica ascendente que se dibuja sola: SEO creciendo. */
.iris .growth {
  fill: none; stroke: url(#irisGrad); stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 8px rgba(0,200,255,.6));
  stroke-dasharray: 520; stroke-dashoffset: 520;
  animation: fx-draw 3.2s var(--e-out) .5s forwards;
}
@keyframes fx-draw { to { stroke-dashoffset: 0; } }

/* Punta del cohete: el punto que corona la curva. */
.iris .tip { fill: var(--yellow); filter: drop-shadow(0 0 10px rgba(255,196,0,.8)); opacity: 0;
  animation: fx-appear .5s var(--e-out) 3.4s forwards; }
@keyframes fx-appear { to { opacity: 1; } }

/* Marca de sección: el iris reducido, estático salvo el barrido. */
.iris--mark { width: 2.5rem; height: 2.5rem; flex: none; }

/* ============================================================
   3.bis EL IRIS COMO LENTE — retrato dentro de la figura
   Los anillos dejan de ser adorno y pasan a ser el encuadre: la
   marca observa, y quien observa está en el centro.
   ============================================================ */
.lens { position: relative; width: 100%; aspect-ratio: 1; isolation: isolate; }
.lens .iris { position: absolute; inset: 0; z-index: 2; }

/* Variante grande del hero: el iris crece y la foto ocupa más disco.
   Se sale ligeramente de la columna a propósito, para que la figura
   respire y no quede encajonada. */
.lens--xl { width: clamp(100%, 100%, 118%); margin-inline: auto; }
@media (min-width: 64rem) { .lens--xl { width: 116%; margin-left: -8%; } }
.lens--xl .lens__photo { inset: 16%; }

.lens__photo {
  position: absolute; z-index: 1;
  inset: 21%;                    /* deja los anillos exteriores libres */
  border-radius: 50%; overflow: hidden;
  border: 1px solid rgba(0,200,255,.35);
  box-shadow:
    0 0 0 8px rgba(5,7,10,.9),          /* separa la foto del anillo   */
    0 0 60px rgba(8,120,249,.32),
    inset 0 -40px 60px -20px rgba(5,7,10,.9);
}
.lens__photo img {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%;
  filter: saturate(.85) contrast(1.06);
}
/* Tinte azul sobre la foto: el brief §14 pide integrar fotografía con
   iluminación azul y sombras profundas, no pegarla tal cual. */
.lens__photo::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(70% 60% at 30% 15%, rgba(0,200,255,.20), transparent 62%),
    linear-gradient(180deg, transparent 42%, rgba(5,7,10,.72) 100%);
  mix-blend-mode: screen;
}
.lens__photo::before {
  content: ""; position: absolute; inset: 0; z-index: 2; border-radius: 50%;
  box-shadow: inset 0 0 44px rgba(6,59,143,.55);
}

/* Reflejo de lente que recorre el cristal al pasar el puntero */
.lens:hover .lens__photo { box-shadow: 0 0 0 8px rgba(5,7,10,.9), 0 0 80px rgba(0,200,255,.4), inset 0 -40px 60px -20px rgba(5,7,10,.9); }
.lens__photo { transition: box-shadow var(--d-slow) var(--e-soft); }

@media (max-width: 62rem) {
  .lens { max-width: 26rem; margin-inline: auto; }
}

/* ============================================================
   4. REVELACIÓN AL SCROLL
   El estado inicial solo aplica si hay JS (clase .js en <html>),
   así sin JS el contenido se ve igual.
   ============================================================ */
.js [data-reveal] {
  opacity: 0; transform: translate3d(0, 20px, 0);
  transition: opacity var(--d-slow) var(--e-out), transform var(--d-slow) var(--e-out);
}
.js [data-reveal="left"]  { transform: translate3d(-24px, 0, 0); }
.js [data-reveal="right"] { transform: translate3d(24px, 0, 0); }
.js [data-reveal="zoom"]  { transform: scale(.96); }
.js [data-reveal].is-in   { opacity: 1; transform: none; }
.js [data-stagger] > * { transition-delay: calc(var(--i, 0) * 70ms); }

/* ============================================================
   5. RESPLANDOR QUE SIGUE AL PUNTERO
   ============================================================ */
.glow::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(18rem 18rem at var(--mx, 50%) var(--my, 0%),
              rgba(0,200,255,.13), transparent 66%);
  opacity: 0; transition: opacity var(--d-base) var(--e-soft);
}
.glow:hover::after, .glow:focus-within::after { opacity: 1; }
.glow > * { position: relative; z-index: 1; }

/* ============================================================
   6. INDICADORES
   ============================================================ */
.dot {
  width: .45rem; height: .45rem; border-radius: 50%; flex: none;
  background: var(--cyan); box-shadow: 0 0 0 0 rgba(0,200,255,.7);
  animation: fx-ping 2.6s var(--e-soft) infinite;
}
@keyframes fx-ping {
  70%  { box-shadow: 0 0 0 .5rem rgba(0,200,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,200,255,0); }
}

/* Barra de progreso de lectura */
.progress {
  position: fixed; left: 0; top: 0; height: 2px; z-index: 90; width: var(--p, 0%);
  background: var(--grad-tech); box-shadow: 0 0 14px rgba(0,200,255,.7);
  transition: width 90ms linear;
}

/* Separador luminoso */
.rule {
  height: 1px; border: 0; margin: 0;
  background: linear-gradient(90deg, transparent, var(--line-2) 20%, var(--blue) 50%, var(--line-2) 80%, transparent);
  opacity: .7;
}

/* ============================================================
   7. APAGADO TOTAL — accesibilidad
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .fx-depth, .fx-speed,
  .iris .ring--dash, .iris .ring--dash-rev, .iris .sweep, .iris .node,
  .dot {
    animation: none !important;
  }
  .iris .growth { stroke-dashoffset: 0; animation: none !important; }
  .iris .tip { opacity: 1; animation: none !important; }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .btn:hover { transform: none !important; }
  .card:hover { transform: none !important; }
}
