/* ============================================================
   CAPA DE EFECTOS (?fx=1)
   En fichero aparte y todo colgando de :root[data-fx="on"]:
   con los efectos apagados la web queda exactamente igual.
   ============================================================ */

/* ---------- Telón animado ----------
   Ocupa TODA la zona de contenido, no la columna de texto.
   Antes se recortaba a 1046 px dentro de 1134 y se veía el
   rectángulo cortado a los lados. */
:root[data-fx="on"] .vista { position: relative; }
:root[data-fx="on"] .vista > *:not(.fx-telon) { position: relative; z-index: 1; }

.fx-telon {
  position: absolute; top: 0; left: 0;
  z-index: 0; pointer-events: none;
  opacity: 0; transition: opacity 1s cubic-bezier(.4, 0, .2, 1);
  /* Se desvanece por abajo y por los lados: ningún borde duro */
  -webkit-mask-image:
    linear-gradient(to bottom, #000 58%, transparent 100%),
    linear-gradient(to right, transparent 0, #000 13%, #000 87%, transparent 100%);
  mask-image:
    linear-gradient(to bottom, #000 58%, transparent 100%),
    linear-gradient(to right, transparent 0, #000 13%, #000 87%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
:root[data-fx="on"] .fx-telon { opacity: 1; }

/* ---------- Grano de película ---------- */
:root[data-fx="on"] body::after {
  content: ""; position: fixed; inset: -50%;
  z-index: 90; pointer-events: none; opacity: .032;
  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'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: fxGrano 8s steps(8) infinite;
}
@keyframes fxGrano {
  0%   { transform: translate(0, 0) }
  12%  { transform: translate(-3%, -2%) }
  25%  { transform: translate(2%, -3%) }
  37%  { transform: translate(-2%, 3%) }
  50%  { transform: translate(3%, 2%) }
  62%  { transform: translate(-3%, 1%) }
  75%  { transform: translate(1%, -3%) }
  87%  { transform: translate(-1%, 2%) }
  100% { transform: translate(0, 0) }
}

/* ---------- Entrada de la vista al cambiar de página ---------- */
@keyframes fxEntraVista {
  from { opacity: 0; transform: translate3d(0, 12px, 0); filter: blur(4px); }
  to   { opacity: 1; transform: none; filter: none; }
}
:root[data-fx="on"] .vista.fx-entra > .envol {
  animation: fxEntraVista .44s cubic-bezier(.22, .78, .28, 1) both;
}

/* ---------- Titular: revelado por máscara ---------- */
:root[data-fx="on"] .fx-titular {
  display: inline-block;
  clip-path: inset(0 100% -.25em 0);
  transition: clip-path .95s cubic-bezier(.22, .84, .26, 1);
}
:root[data-fx="on"] .fx-titular.fx-titular-on { clip-path: inset(0 0 -.25em 0); }

/* ---------- Revelado al entrar en pantalla ---------- */
:root[data-fx="on"] .fx-oculto {
  opacity: 0; transform: translate3d(0, 20px, 0);
  transition: opacity .6s cubic-bezier(.4, 0, .2, 1),
              transform .7s cubic-bezier(.22, .78, .28, 1);
  transition-delay: calc(var(--fx-i, 0) * 55ms);
}
:root[data-fx="on"] .fx-oculto.fx-visible { opacity: 1; transform: none; }

/* Con efectos, las entradas de golpe del sitio base sobran */
:root[data-fx="on"] .vista > *,
:root[data-fx="on"] .rejilla-mods > *,
:root[data-fx="on"] .rejilla-patrones > *,
:root[data-fx="on"] .pasos > *,
:root[data-fx="on"] .conceptos > * { animation: none; }

/* ---------- Las velas de los patrones se dibujan solas ----------
   OJO: la animación NO puede tocar la opacidad. Varias piezas del
   dibujo llevan su propia (`opacity=".12"` en las zonas sombreadas,
   `.9` en las guías) y un `opacity: 1` en CSS las machaca: el rango
   salía rojo macizo tapando el texto. Aquí solo se anima la forma;
   el desvanecido lo hace el SVG entero. */
@keyframes fxTrazo {
  from { transform: translateY(7px) scaleY(.72); }
  to   { transform: none; }
}
@keyframes fxAparece { from { opacity: 0; } to { opacity: 1; } }
:root[data-fx="on"] .pat-lienzo svg.fx-dibujando { animation: fxAparece .4s ease both; }
:root[data-fx="on"] .pat-lienzo svg rect,
:root[data-fx="on"] .pat-lienzo svg line,
:root[data-fx="on"] .pat-lienzo svg polyline,
:root[data-fx="on"] .pat-lienzo svg path { transform-origin: 50% 100%; }

/* ---------- Tarjetas: inclinación, luz al cursor y filo encendido ----------
   Sin overflow:hidden ni cambio de caja: el recorte lo hace el propio
   pseudoelemento heredando el radio, así no se descuadra nada. */
:root[data-fx="on"] .fx-tarjeta {
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg)) rotateY(var(--fx-ry, 0deg));
  transition: transform .4s cubic-bezier(.22, .78, .28, 1),
              border-color .15s cubic-bezier(.4, 0, .2, 1),
              box-shadow .4s cubic-bezier(.4, 0, .2, 1);
  position: relative;
}
:root[data-fx="on"] .fx-tarjeta::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit; z-index: 2;
  background: radial-gradient(360px circle at var(--fx-lx, 50%) var(--fx-ly, 0%),
    color-mix(in srgb, var(--neon) 10%, transparent), transparent 60%);
  opacity: 0; transition: opacity .35s cubic-bezier(.4, 0, .2, 1);
}
:root[data-fx="on"] .fx-tarjeta:hover::after { opacity: 1; }

/* Filo que se enciende siguiendo al cursor */
:root[data-fx="on"] .fx-tarjeta .fx-filo {
  position: absolute; inset: -1px; pointer-events: none;
  border-radius: inherit; padding: 1px; z-index: 0;
  background: radial-gradient(220px circle at var(--fx-lx, 50%) var(--fx-ly, 0%),
    color-mix(in srgb, var(--neon) 60%, transparent), 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 .35s cubic-bezier(.4, 0, .2, 1);
}
:root[data-fx="on"] .fx-tarjeta:hover .fx-filo { opacity: 1; }
:root[data-fx="on"] .fx-tarjeta:hover {
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg)) rotateY(var(--fx-ry, 0deg)) translateY(-3px);
  box-shadow: var(--shadow);
}

/* ---------- Botones magnéticos ---------- */
:root[data-fx="on"] .fx-iman {
  transform: translate3d(var(--fx-mx, 0), var(--fx-my, 0), 0);
  transition: transform .3s cubic-bezier(.22, .78, .28, 1),
              background .15s cubic-bezier(.4, 0, .2, 1),
              border-color .15s cubic-bezier(.4, 0, .2, 1);
}

/* ---------- Onda expansiva al pulsar ---------- */
.fx-onda {
  position: absolute; width: 8px; height: 8px; border-radius: 50%;
  margin: -4px 0 0 -4px; pointer-events: none; z-index: 3;
  background: currentColor; opacity: .2;
  animation: fxOnda .6s cubic-bezier(.22, .78, .28, 1) forwards;
}
@keyframes fxOnda { to { transform: scale(36); opacity: 0; } }
.btn-pri .fx-onda, .chip.on .fx-onda { background: #fff; opacity: .3; }

/* ---------- Foco que sigue al cursor ---------- */
.fx-foco { display: none; }
:root[data-fx="on"] .fx-foco {
  display: block; position: fixed; left: 0; top: 0;
  width: 680px; height: 680px; border-radius: 50%;
  pointer-events: none; z-index: 0; will-change: transform;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--neon) 4%, transparent) 0%, transparent 62%);
}
:root[data-fx="on"][data-tema="oscuro"] .fx-foco {
  background: radial-gradient(circle,
    color-mix(in srgb, var(--neon) 9%, transparent) 0%, transparent 62%);
}

/* ---------- Interruptor de la versión de prueba ---------- */
#fx-switch {
  position: fixed; right: 18px; bottom: 18px; z-index: 9999;
  padding: 9px 16px; border-radius: 100px; cursor: pointer;
  font-family: var(--sans); font-size: .8125rem; font-weight: 600;
  color: var(--tx-mid); background: var(--bg-elev);
  border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  transition: all .15s cubic-bezier(.4, 0, .2, 1);
}
#fx-switch:hover { color: var(--tx); border-color: var(--tx-dim); }
#fx-switch.on { color: #fff; background: var(--neon); border-color: transparent; }
:root[data-tema="oscuro"] #fx-switch.on { color: #1c1917; }

@media (prefers-reduced-motion: reduce) {
  :root[data-fx="on"] body::after, .fx-telon, .fx-foco { display: none !important; }
  :root[data-fx="on"] .fx-oculto { opacity: 1 !important; transform: none !important; }
  :root[data-fx="on"] .fx-titular { clip-path: none !important; }
  :root[data-fx="on"] .vista.fx-entra > .envol { animation: none !important; }
}
