/* ════════════════════════════════════════════════════════════
   MOTION-FX · librería completa (61 clases) — v2
   Generada por extracción desde motion-fx-catalogo-v2.html.
   NO editar a mano: cambios en los lotes fuente y re-extraer.
   Ajustes por proyecto: SOLO variables --fx-* (aquí o inline).
   ════════════════════════════════════════════════════════════ */
:root{
  --fx-duration: 5s;
  --fx-ease: cubic-bezier(.22,.85,.3,1);
  --fx-accent: #6366F1;
  --fx-accent-2: #06B6D4;
  --fx-radius: 0px;
  --fx-ratio: 16 / 9;
  --fx-zoom: 1.12;
  --fx-img: none;
  --fx-duo-lo: #00a7e1;
  --fx-duo-hi: #f5f0e0;
  --fx-blur: 18px;
  --fx-shine: .55;
  --fx-clip-from: inset(11% 11% 11% 11% round 26px);
  --fx-clip-to: inset(0% 0% 0% 0% round 0px);
  --fx-line: 2px;
  --fx-line-color: #00a7e1;
  --fx-dot: 6px;
  --fx-halftone-color: #0B0C10;
  --fx-halftone-opacity: .55;
  --fx-glitch-shift: 7px;
  --fx-parallax: 12;
  --fx-spot: 120px;
  --fx-spot-dim: .55;
  --fx-pixel: 28;
  --fx-pixel-duration: 1100;
  --fx-tiles: 6;
  --fx-tile-spread: 600;
  --fx-pos: 50%;
  --fx-stroke: 1.5px;
  --fx-word-dur: 2200;
  --fx-blur-text: 12px;
  --fx-marker: #ffd84d;
  --fx-marker-h: .58em;
  --fx-stagger: 55ms;
  --fx-glitch-a: #ff0044;
  --fx-glitch-b: #00e5ff;
  --fx-type-speed: 45;
  --fx-magnet: .34;
  --fx-fill-color: #00a7e1;
  --fx-fill-ink: #0B0C10;
  --fx-confetti: 28;
  --fx-confetti-size: 7px;
  --fx-press-dur: 1200;
  --fx-press-fill: rgba(255,255,255,.20);
  --fx-spot-card: 320px;
  --fx-spot-color: rgba(0,167,225,.22);
  --fx-beam-w: 1.5px;
  --fx-beam-color: #00a7e1;
  --fx-beam-dur: 4s;
  --fx-glass: 14px;
  --fx-glass-bg: rgba(255,255,255,.07);
  --fx-glass-line: rgba(255,255,255,.16);
  --fx-acc-dur: .38s;
  --fx-depth: 2400px;
  --fx-shade: .7;
}


/* ════════════════════════════════════════════════════════════
   L1 · BASE — wrapper universal
   ════════════════════════════════════════════════════════════ */
.fx-media{
  position: relative;
  display: inline-block;
  vertical-align: middle;
  align-self: flex-start;
  overflow: hidden;
  border-radius: var(--fx-radius);
  isolation: isolate;
  line-height: 0;
  max-width: 100%;
}
.fx-media > img,
.fx-media > picture > img,
.fx-media > video{
  display: block; width: 100%; height: auto;
  border-radius: inherit;
}
.fx-media--open{ overflow: visible }
.fx-media--fill{ display: block; width: 100%; align-self: stretch }
.fx-media--ratio{ aspect-ratio: var(--fx-ratio) }
.fx-media--ratio > img{ height: 100%; object-fit: cover }

/* ════════════════════════════════════════════════════════════
   L1 · T1 — CLASE SUELTA (funcionan también sobre <img> pelado)
   ════════════════════════════════════════════════════════════ */
/* 05 · fx-duotone-flat — bitono barato, solo cadena de filtros.
   Menos fiel que fx-duotone pero sin wrapper ni capas. */
.fx-duotone-flat, .fx-duotone-flat > img{
  filter: grayscale(1) sepia(1)
          saturate(var(--fx-duo-sat, 4.5))
          hue-rotate(var(--fx-duo-hue, 168deg))
          contrast(1.04);
}

/* 06 · fx-img-reveal-blur — de desenfocada a nítida al entrar */
.fx-img-reveal-blur, .fx-img-reveal-blur > img{
  animation: fx-img-reveal-blur calc(var(--fx-duration) * .24) var(--fx-ease) both;
}
@keyframes fx-img-reveal-blur{
  from{ filter: blur(var(--fx-blur)); transform: scale(1.06); opacity: 0 }
  to  { filter: blur(0);              transform: none;        opacity: 1 }
}

/* 07 · fx-grayscale-warm — B/N cálido que gana color al hover */
.fx-grayscale-warm, .fx-grayscale-warm > img{
  filter: grayscale(1) sepia(var(--fx-warm, .28)) contrast(1.02);
  transition: filter .45s var(--fx-ease);
}
.fx-grayscale-warm:hover, .fx-grayscale-warm:hover > img,
.fx-grayscale-warm:focus-within > img{
  filter: grayscale(0) sepia(0) saturate(var(--fx-warm-sat, 1.15));
}

/* ════════════════════════════════════════════════════════════
   L1 · T2 — NECESITAN WRAPPER
   ════════════════════════════════════════════════════════════ */
/* 01 · fx-ken-burns — zoom lento panorámico, en bucle
   `alternate` evita el salto al reiniciar: vuelve andando, no cortando. */
.fx-ken-burns > img{
  transform-origin: var(--fx-origin, 50% 50%);
  animation: fx-ken-burns calc(var(--fx-duration) * 4) ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes fx-ken-burns{
  from{ transform: scale(1) translate3d(0,0,0) }
  to  { transform: scale(var(--fx-zoom))
                   translate3d(var(--fx-pan-x, -3%), var(--fx-pan-y, -2%), 0) }
}

/* 02 · fx-duotone — bitono real por blend mode
   Base en gris; multiply tiñe las luces, screen tiñe las sombras.
   El `isolation:isolate` del wrapper impide que el blend se escape al fondo. */
.fx-duotone > img{ filter: grayscale(1) contrast(1.06) }
.fx-duotone::before,
.fx-duotone::after{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
}
.fx-duotone::before{ background: var(--fx-duo-hi); mix-blend-mode: multiply }
.fx-duotone::after { background: var(--fx-duo-lo); mix-blend-mode: screen }

/* 03 · fx-zoom-frame — la imagen crece dentro del marco al hover */
.fx-zoom-frame > img{
  transition: transform .55s var(--fx-ease);
  will-change: transform;
}
.fx-zoom-frame:hover > img,
.fx-zoom-frame:focus-within > img{ transform: scale(var(--fx-zoom)) }

/* 04 · fx-shine-sweep — destello diagonal cruzando al hover */
.fx-shine-sweep::after{
  content: ''; position: absolute; inset: -30%; pointer-events: none;
  background: linear-gradient(75deg,
    transparent 42%,
    rgba(255,255,255, var(--fx-shine)) 50%,
    transparent 58%);
  transform: translateX(-100%);
}
.fx-shine-sweep:hover::after,
.fx-shine-sweep:focus-within::after{
  animation: fx-shine-sweep .9s var(--fx-ease);
}
@keyframes fx-shine-sweep{
  from{ transform: translateX(-100%) }
  to  { transform: translateX(100%) }
}

/* ════════════════════════════════════════════════════════════
   L1 · T2 — PASO 3
   ════════════════════════════════════════════════════════════ */
/* 08 · fx-clip-shape — máscara de forma que se abre al hover.
   clip-path solo interpola entre la MISMA función y el mismo
   número de vértices: inset↔inset, circle↔circle, polygon de 4↔4. */
.fx-clip-shape > img{
  clip-path: var(--fx-clip-from);
  transition: clip-path .55s var(--fx-ease);
}
.fx-clip-shape:hover > img,
.fx-clip-shape:focus-within > img{ clip-path: var(--fx-clip-to) }

.fx-clip-shape--diamond{
  --fx-clip-from: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  --fx-clip-to:   polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}
.fx-clip-shape--iris{
  --fx-clip-from: circle(30% at 50% 50%);
  --fx-clip-to:   circle(75% at 50% 50%);
}

/* 09 · fx-border-draw — el marco se dibuja trazo a trazo.
   Dos capas en esquinas opuestas: primero crece el lado vertical,
   después el horizontal (los delays se invierten al salir). */
.fx-border-draw::before,
.fx-border-draw::after{
  content: ''; position: absolute; width: 0; height: 0;
  box-sizing: border-box; pointer-events: none;
  transition: width .3s linear, height .3s linear;
}
.fx-border-draw::before{
  top: 0; left: 0;
  border-top:  var(--fx-line) solid var(--fx-line-color);
  border-left: var(--fx-line) solid var(--fx-line-color);
  transition-delay: .3s, 0s;
}
.fx-border-draw::after{
  bottom: 0; right: 0;
  border-bottom: var(--fx-line) solid var(--fx-line-color);
  border-right:  var(--fx-line) solid var(--fx-line-color);
  transition-delay: .3s, 0s;
}
.fx-border-draw:hover::before,  .fx-border-draw:focus-within::before,
.fx-border-draw:hover::after,   .fx-border-draw:focus-within::after{
  width: 100%; height: 100%;
  transition-delay: 0s, .3s;
}

/* 10 · fx-caption-slide — el pie de foto sube al hover.
   OJO: el wrapper lleva line-height:0, hay que devolvérselo al texto. */
.fx-caption-slide .fx-media__caption{
  position: absolute; left: 0; right: 0; bottom: 0;
  line-height: 1.45;
  padding: 26px 16px 14px;
  color: #fff; font-size: 14px; text-align: left;
  background: linear-gradient(to top, rgba(0,0,0,.82), rgba(0,0,0,0));
  transform: translateY(101%);
  opacity: 0;
  transition: transform .4s var(--fx-ease), opacity .4s var(--fx-ease);
}
.fx-caption-slide:hover .fx-media__caption,
.fx-caption-slide:focus-within .fx-media__caption{
  transform: none; opacity: 1;
}

/* 11 · fx-halftone-hover — trama de puntos serigráfica al pasar.
   El tamaño del punto es fijo: el halftone de verdad (punto que
   crece con la luminancia) necesita filtro SVG. */
.fx-halftone-hover > img{ transition: filter .35s var(--fx-ease) }
.fx-halftone-hover:hover > img,
.fx-halftone-hover:focus-within > img{ filter: contrast(1.35) saturate(.85) }
.fx-halftone-hover::after{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background-image: radial-gradient(circle at center,
    var(--fx-halftone-color) 42%, transparent 44%);
  background-size: var(--fx-dot) var(--fx-dot);
  mix-blend-mode: multiply;
  opacity: 0;
  transition: opacity .35s var(--fx-ease);
}
.fx-halftone-hover:hover::after,
.fx-halftone-hover:focus-within::after{ opacity: var(--fx-halftone-opacity) }

/* 12 · fx-glitch-rgb — separación de canales, sin copiar el <img>.
   Cada capa aísla un canal con background-blend-mode:multiply contra
   un color puro, y las dos se recomponen con mix-blend-mode:screen.
   Rojo + cian a offset 0 = imagen original, así que al terminar la
   ráfaga no queda ningún artefacto. */
.fx-glitch-rgb::before,
.fx-glitch-rgb::after{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background-size: cover; background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: multiply;
  mix-blend-mode: screen;
  opacity: 0;
}
.fx-glitch-rgb::before{
  background-image: linear-gradient(#f00,#f00), var(--fx-img);
}
.fx-glitch-rgb::after{
  background-image: linear-gradient(#0ff,#0ff), var(--fx-img);
}
.fx-glitch-rgb:hover > img,
.fx-glitch-rgb:focus-within > img{ opacity: 0 }
.fx-glitch-rgb:hover::before,
.fx-glitch-rgb:focus-within::before{
  opacity: 1; animation: fx-glitch-r .4s steps(1,end);
}
.fx-glitch-rgb:hover::after,
.fx-glitch-rgb:focus-within::after{
  opacity: 1; animation: fx-glitch-c .4s steps(1,end);
}
@keyframes fx-glitch-r{
  0%  { transform: translate(0,0) }
  15% { transform: translate(calc(var(--fx-glitch-shift) * -1), 2px) }
  35% { transform: translate(var(--fx-glitch-shift), -3px) }
  55% { transform: translate(calc(var(--fx-glitch-shift) * -.5), 1px) }
  75% { transform: translate(calc(var(--fx-glitch-shift) * .6), 2px) }
  100%{ transform: translate(0,0) }
}
@keyframes fx-glitch-c{
  0%  { transform: translate(0,0) }
  15% { transform: translate(var(--fx-glitch-shift), -2px) }
  35% { transform: translate(calc(var(--fx-glitch-shift) * -1), 3px) }
  55% { transform: translate(calc(var(--fx-glitch-shift) * .5), -1px) }
  75% { transform: translate(calc(var(--fx-glitch-shift) * -.6), -2px) }
  100%{ transform: translate(0,0) }
}

/* ════════════════════════════════════════════════════════════
   L1 · T3 — NECESITAN JAVASCRIPT
   ════════════════════════════════════════════════════════════ */
/* 13 · fx-parallax-inner — la imagen se mueve más lenta que el marco.
   Obligatorio combinarlo con .fx-media--ratio: sin altura fija no hay
   recorrido que repartir. La imagen se estira por arriba y por abajo
   para que nunca asome el fondo. */
.fx-parallax-inner > img{
  position: absolute; left: 0; width: 100%;
  top: calc(var(--fx-parallax) * -1%);
  height: calc(100% + var(--fx-parallax) * 2%);
  object-fit: cover;
  will-change: transform;
}

/* 14 · fx-focus-spotlight — foco de color siguiendo el cursor.
   La capa de arriba es la imagen a todo color, enmascarada por un
   círculo; debajo queda la versión apagada. Consume --fx-img. */
.fx-focus-spotlight > img{
  filter: grayscale(.9) brightness(var(--fx-spot-dim));
  transition: filter .3s var(--fx-ease);
}
.fx-focus-spotlight::after{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background-image: var(--fx-img);
  background-size: cover; background-position: center;
  -webkit-mask-image: radial-gradient(circle var(--fx-spot) at var(--fx-mx,50%) var(--fx-my,50%), #000 55%, transparent 100%);
          mask-image: radial-gradient(circle var(--fx-spot) at var(--fx-mx,50%) var(--fx-my,50%), #000 55%, transparent 100%);
  opacity: 0;
  transition: opacity .25s var(--fx-ease);
}
@media (hover: hover) and (pointer: fine){
  .fx-focus-spotlight:hover::after{ opacity: 1 }
}
/* en táctil el foco no existe: se degrada a imagen normal */
@media not all and (hover: hover){
  .fx-focus-spotlight > img{ filter: none }
}

/* 15 · fx-pixelate-in — de pixelado a nítido, con <canvas> encima.
   El canvas tapa la imagen mientras dura la animación y se funde al
   terminar. No se lee ningún píxel, así que no hay problema de CORS. */
.fx-media__canvas{
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%; display: block;
  border-radius: inherit; pointer-events: none;
  opacity: 0;
  transition: opacity .3s linear;
}

/* 16 · fx-tile-mosaic — entrada por baldosas.
   El mosaico se construye con divs que comparten --fx-img y se
   destruye al acabar, para no dejar 36 nodos vivos en la página. */
.fx-media__mosaic{
  position: absolute; inset: 0; z-index: 2;
  display: grid; pointer-events: none;
  border-radius: inherit; overflow: hidden;
}
.fx-media__tile{
  background-image: var(--fx-img);
  background-repeat: no-repeat;
  opacity: 0; transform: scale(.55);
  animation: fx-tile-in .55s var(--fx-ease) forwards;
}
@keyframes fx-tile-in{
  to{ opacity: 1; transform: scale(1.004) }  /* el 1.004 tapa las costuras */
}

/* 17 · fx-compare-slider — antes/después con divisor.
   Componente propio: no usa .fx-media, tiene su propia raíz. */
.fx-compare-slider{
  position: relative; overflow: hidden; isolation: isolate;
  aspect-ratio: var(--fx-ratio);
  border-radius: var(--fx-radius);
  line-height: 0;
}
.fx-compare-slider img{
  position: absolute; inset: 0; display: block;
  width: 100%; height: 100%; object-fit: cover;
}
.fx-compare-slider__after{ clip-path: inset(0 0 0 var(--fx-pos)) }
.fx-compare-slider__range{
  position: absolute; inset: 0; z-index: 3;
  width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: ew-resize;
}
.fx-compare-slider__handle{
  position: absolute; top: 0; bottom: 0; left: var(--fx-pos);
  width: 2px; margin-left: -1px; z-index: 2; pointer-events: none;
  background: #fff; box-shadow: 0 0 14px rgba(0,0,0,.55);
}
.fx-compare-slider__handle::after{
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 40px; height: 40px; margin: -20px 0 0 -20px;
  border: 2px solid #fff; border-radius: 50%;
  background: rgba(0,0,0,.28);
}
.fx-compare-slider:focus-within .fx-compare-slider__handle::after{
  box-shadow: 0 0 0 3px var(--fx-accent-2);
}

/* ════════════════════════════════════════════════════════════
   L2 · preambulo
   ════════════════════════════════════════════════════════════ */
.fx-sr{
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ════════════════════════════════════════════════════════════
   L2 · TEXTO · T1
   ════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════
   L2 · T1 — CLASE SUELTA
   ════════════════════════════════════════════════════════════ */
/* 18 · fx-text-outline-fill — contorno que se rellena de abajo arriba.
   -webkit-text-fill-color:transparent en vez de color:transparent:
   así `color` sigue vivo y currentColor pinta el contorno. */
.fx-text-outline-fill{
  -webkit-text-stroke: var(--fx-stroke) currentColor;
  -webkit-text-fill-color: transparent;
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 0%;
  -webkit-background-clip: text; background-clip: text;
  transition: background-size .45s var(--fx-ease);
}
.fx-text-outline-fill:hover,
.fx-text-outline-fill:focus-visible{ background-size: 100% 100% }

/* 19 · fx-underline-grow — subrayado que crece desde la izquierda */
.fx-underline-grow{
  background: linear-gradient(var(--fx-line-color), var(--fx-line-color))
              no-repeat 0 100% / 0% var(--fx-line);
  padding-bottom: .12em;
  transition: background-size .35s var(--fx-ease);
}
.fx-underline-grow:hover,
.fx-underline-grow:focus-visible{ background-size: 100% var(--fx-line) }
.fx-underline-grow--center{ background-position: 50% 100% }

/* 20 · fx-blur-in — el texto entra desenfocado */
.fx-blur-in{ animation: fx-blur-in .85s var(--fx-ease) both }
@keyframes fx-blur-in{
  from{ filter: blur(var(--fx-blur-text)); opacity: 0; transform: translateY(.28em) }
  to  { filter: blur(0);                   opacity: 1; transform: none }
}

/* 21 · fx-highlight-marker — trazo de rotulador.
   Se dispara al entrar en pantalla (.is-inview) o al hover. */
.fx-highlight-marker{
  background: linear-gradient(var(--fx-marker), var(--fx-marker))
              no-repeat 0 86% / 0% var(--fx-marker-h);
  padding: 0 .12em;
  transition: background-size .55s var(--fx-ease);
}
.fx-highlight-marker.is-inview,
.fx-highlight-marker:hover{ background-size: 100% var(--fx-marker-h) }

/* 22 · fx-glitch-text — dos copias de color por encima del texto real.
   Necesita data-text con el mismo contenido. */
.fx-glitch-text{ position: relative; display: inline-block }
.fx-glitch-text::before,
.fx-glitch-text::after{
  content: attr(data-text);
  position: absolute; top: 0; left: 0; width: 100%;
  opacity: 0; pointer-events: none;
}
.fx-glitch-text::before{ color: var(--fx-glitch-a) }
.fx-glitch-text::after { color: var(--fx-glitch-b) }
.fx-glitch-text:hover::before,
.fx-glitch-text:focus-visible::before{ opacity: .92; animation: fx-glitch-ta .45s steps(2,end) }
.fx-glitch-text:hover::after,
.fx-glitch-text:focus-visible::after { opacity: .92; animation: fx-glitch-tb .45s steps(2,end) }
@keyframes fx-glitch-ta{
  0%  { transform: none;                 clip-path: inset(0) }
  20% { transform: translate(-3px, 1px); clip-path: inset(8% 0 62% 0) }
  45% { transform: translate(3px, -1px); clip-path: inset(52% 0 18% 0) }
  70% { transform: translate(-2px, 0);   clip-path: inset(24% 0 42% 0) }
  100%{ transform: none;                 clip-path: inset(0) }
}
@keyframes fx-glitch-tb{
  0%  { transform: none;                 clip-path: inset(0) }
  20% { transform: translate(3px, -1px); clip-path: inset(45% 0 30% 0) }
  45% { transform: translate(-3px, 2px); clip-path: inset(12% 0 55% 0) }
  70% { transform: translate(2px, 0);    clip-path: inset(60% 0 10% 0) }
  100%{ transform: none;                 clip-path: inset(0) }
}

/* ════════════════════════════════════════════════════════════
   L2 · TEXTO · T3
   ════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════
   L2 · T3 — NECESITAN JAVASCRIPT
   ════════════════════════════════════════════════════════════ */
/* 23 · fx-word-rotate — carrusel vertical de palabras */
.fx-word-rotate{
  display: inline-block; overflow: hidden;
  height: 1.25em; vertical-align: bottom; line-height: 1.25;
}
.fx-word-rotate__list{
  display: block;
  transition: transform .55s var(--fx-ease);
}
.fx-word-rotate__list.is-instant{ transition: none }
.fx-word-rotate__list > *{ display: block; height: 1.25em; line-height: 1.25 }

/* 24 · fx-char-wave — ola carácter a carácter */
.fx-char-wave__char{
  display: inline-block;
  animation: fx-char-wave 1.7s var(--fx-ease) infinite;
  animation-delay: calc(var(--i) * var(--fx-stagger));
}
@keyframes fx-char-wave{
  0%, 55%, 100%{ transform: none }
  28%          { transform: translateY(-.32em) }
}

/* 25 · fx-typewriter — el fantasma reserva la caja, así no salta el layout */
.fx-typewriter{ position: relative; display: inline-block }
.fx-typewriter__ghost{ visibility: hidden }
.fx-typewriter__out{ position: absolute; inset: 0 }
.fx-typewriter__out::after{
  content: ''; display: inline-block;
  width: .08em; height: 1em; background: currentColor;
  vertical-align: -.14em; margin-left: .06em;
  animation: fx-caret 1s steps(1) infinite;
}
@keyframes fx-caret{ 50%{ opacity: 0 } }

/* ════════════════════════════════════════════════════════════
   L2 · BOTÓN · T1
   ════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════
   L2 · T1 — CLASE SUELTA
   ════════════════════════════════════════════════════════════ */
/* 26 · fx-fill-sweep — el color barre el botón al hover.
   Sin pseudo-elemento: es un background-image con background-size
   animado, así el ::before queda libre para otros efectos. */
.fx-fill-sweep{
  background-image: linear-gradient(var(--fx-fill-color), var(--fx-fill-color));
  background-repeat: no-repeat;
  background-position: 0 50%;
  background-size: 0% 100%;
  transition: background-size .38s var(--fx-ease), color .3s var(--fx-ease);
}
.fx-fill-sweep:hover,
.fx-fill-sweep:focus-visible{ background-size: 100% 100%; color: var(--fx-fill-ink) }
.fx-fill-sweep--up{ background-position: 50% 100%; background-size: 100% 0% }
.fx-fill-sweep--up:hover,
.fx-fill-sweep--up:focus-visible{ background-size: 100% 100% }
.fx-fill-sweep--center{ background-position: 50% 50% }

/* ════════════════════════════════════════════════════════════
   L2 · BOTÓN · T2
   ════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════
   L2 · T2 — NECESITAN ESTRUCTURA INTERNA
   ════════════════════════════════════════════════════════════ */
/* 27 · fx-icon-arrow-slide — la flecha se desplaza al hover */
.fx-icon-arrow-slide{ display: inline-flex; align-items: center; gap: .55em }
.fx-icon-arrow-slide__icon{
  display: inline-block;
  transition: transform .32s var(--fx-ease);
}
.fx-icon-arrow-slide:hover .fx-icon-arrow-slide__icon,
.fx-icon-arrow-slide:focus-visible .fx-icon-arrow-slide__icon{ transform: translateX(.4em) }
.fx-icon-arrow-slide--back .fx-icon-arrow-slide__icon{ order: -1 }
.fx-icon-arrow-slide--back:hover .fx-icon-arrow-slide__icon{ transform: translateX(-.4em) }

/* 28 · fx-loading-dots — tres puntos latiendo */
.fx-loading-dots{ display: inline-flex; align-items: center; gap: .32em }
.fx-loading-dots > i{
  width: .38em; height: .38em; border-radius: 50%;
  background: currentColor;
  animation: fx-loading-dots 1.05s ease-in-out infinite;
}
.fx-loading-dots > i:nth-child(2){ animation-delay: .14s }
.fx-loading-dots > i:nth-child(3){ animation-delay: .28s }
@keyframes fx-loading-dots{
  0%, 80%, 100%{ transform: scale(.55); opacity: .45 }
  40%          { transform: scale(1);   opacity: 1 }
}
/* patrón de uso: el botón cambia la etiqueta por los puntos */
.fx-btn.is-loading .fx-btn__label{ display: none }
.fx-btn:not(.is-loading) .fx-loading-dots{ display: none }

/* ════════════════════════════════════════════════════════════
   L2 · BOTÓN · T3
   ════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════
   L2 · T3 — NECESITAN JAVASCRIPT
   ════════════════════════════════════════════════════════════ */
/* 29 · fx-magnetic-hover — el botón se acerca al cursor.
   OJO: incompatible con overflow:hidden en cualquier ancestro,
   el botón se sale de su caja y queda recortado. */
.fx-magnetic-hover{
  transition: transform .38s var(--fx-ease);
  will-change: transform;
}
.fx-magnetic-hover.is-magnet{ transition: transform .09s linear }

/* 30 · fx-confetti-burst — 28 partículas al click, destruidas al acabar.
   El botón NO puede llevar overflow:hidden. */
.fx-confetti-burst{ position: relative; overflow: visible }
.fx-confetti{
  position: absolute; left: 50%; top: 50%;
  width: 0; height: 0; pointer-events: none; z-index: 5;
}
.fx-confetti > i{
  position: absolute;
  width: var(--fx-confetti-size);
  height: calc(var(--fx-confetti-size) * .6);
  border-radius: 1px;
  animation: fx-confetti 900ms var(--fx-ease) forwards;
}
@keyframes fx-confetti{
  from{ transform: translate(0,0) rotate(0); opacity: 1 }
  to  { transform: translate(var(--x), calc(var(--y) + 80px)) rotate(var(--r)); opacity: 0 }
}

/* 31 · fx-long-press — mantener pulsado para confirmar.
   Las tres propiedades defensivas evitan que Android e iOS abran
   el menú de selección a mitad de la pulsación. */
.fx-long-press{
  position: relative; overflow: hidden;
  touch-action: none;
  user-select: none; -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.fx-long-press__fill{
  position: absolute; inset: 0; z-index: 0;
  transform: scaleX(0); transform-origin: left;
  background: var(--fx-press-fill);
  pointer-events: none;
}
.fx-long-press > *{ position: relative; z-index: 1 }
.fx-long-press.is-done{ background-color: #1c7a4f !important; border-color: #1c7a4f !important }

/* ════════════════════════════════════════════════════════════
   L3 · preambulo
   ════════════════════════════════════════════════════════════ */
@property --fx-angle{
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

/* ════════════════════════════════════════════════════════════
   L3 · T1 — CLASE SUELTA
   ════════════════════════════════════════════════════════════ */
/* 32 · fx-glass-blur — cristal esmerilado.
   Necesita algo detrás que desenfocar: sobre fondo plano no se
   nota nada. Un ancestro con `filter` u `overflow` propio puede
   anular el backdrop-filter. */
.fx-glass-blur{
  background: var(--fx-glass-bg);
  -webkit-backdrop-filter: blur(var(--fx-glass)) saturate(1.5);
          backdrop-filter: blur(var(--fx-glass)) saturate(1.5);
  border: 1px solid var(--fx-glass-line);
  border-radius: var(--fx-radius);
  transition: backdrop-filter .35s var(--fx-ease), background .35s var(--fx-ease);
}
.fx-glass-blur--hover{
  --fx-glass: 3px;
  --fx-glass-bg: rgba(255,255,255,.04);
}
.fx-glass-blur--hover:hover{
  --fx-glass: 18px;
  --fx-glass-bg: rgba(255,255,255,.10);
}

/* ════════════════════════════════════════════════════════════
   L3 · T2 — NECESITAN ESTRUCTURA O ESTADO
   ════════════════════════════════════════════════════════════ */
/* 33 · fx-border-beam — haz de luz recorriendo el borde.
   El truco es un conic-gradient enmascarado a la franja del borde:
   mask normal menos mask de content-box = solo el marco. */
.fx-border-beam{
  position: relative;
  border-radius: var(--fx-radius);
  isolation: isolate;
}
.fx-border-beam::before{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  padding: var(--fx-beam-w);
  background: conic-gradient(from var(--fx-angle),
    transparent 0 68%,
    var(--fx-beam-color) 84%,
    transparent 92% 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: fx-border-beam var(--fx-beam-dur) linear infinite;
}
@keyframes fx-border-beam{ to{ --fx-angle: 360deg } }

/* 34 · fx-accordion-smooth — apertura fluida sin medir alturas.
   grid-template-rows 0fr → 1fr sí es animable; height:auto no.
   El hijo necesita overflow:hidden y min-height:0. */
.fx-accordion-smooth{
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--fx-acc-dur) var(--fx-ease);
}
.fx-accordion-smooth.is-open{ grid-template-rows: 1fr }
.fx-accordion-smooth > *{ overflow: hidden; min-height: 0 }
.fx-accordion-smooth__trigger [data-chevron]{
  display: inline-block;
  transition: transform var(--fx-acc-dur) var(--fx-ease);
}
[aria-expanded="true"] [data-chevron]{ transform: rotate(180deg) }

/* ════════════════════════════════════════════════════════════
   L3 · T3 — NECESITA JAVASCRIPT
   ════════════════════════════════════════════════════════════ */
/* 35 · fx-spotlight-follow — halo siguiendo el cursor.
   Reutiliza exactamente el mismo fxSpotlight del lote 1: la
   función solo escribe --fx-mx / --fx-my, el resto es CSS. */
.fx-spotlight-follow{ position: relative; isolation: isolate }
.fx-spotlight-follow::after{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(var(--fx-spot-card) circle at var(--fx-mx,50%) var(--fx-my,50%),
    var(--fx-spot-color), transparent 68%);
  opacity: 0;
  transition: opacity .3s var(--fx-ease);
}
@media (hover: hover) and (pointer: fine){
  .fx-spotlight-follow:hover::after{ opacity: 1 }
}

/* ════════════════════════════════════════════════════════════
   V1 · T1 — CLASE SUELTA (11)
   ════════════════════════════════════════════════════════════ */
/* 01 · fx-shadow-lift — elevación suave al hover */
.fx-shadow-lift{
  transition: transform .28s var(--fx-ease), box-shadow .28s var(--fx-ease);
}
.fx-shadow-lift:hover{
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0,0,0,.45);
}

/* 02 · fx-hard-shadow-press — sombra sólida, el elemento se hunde */
.fx-hard-shadow-press{
  --fx-press-color: currentColor;
  box-shadow: 6px 6px 0 var(--fx-press-color);
  transition: transform .16s var(--fx-ease), box-shadow .16s var(--fx-ease);
}
.fx-hard-shadow-press:hover{
  transform: translate(3px,3px);
  box-shadow: 3px 3px 0 var(--fx-press-color);
}
.fx-hard-shadow-press:active{
  transform: translate(6px,6px);
  box-shadow: 0 0 0 var(--fx-press-color);
}

/* 03 · fx-neon-pulse — resplandor que late */
.fx-neon-pulse{
  --fx-glow: var(--fx-accent);
  --fx-intensity: 1;
  animation: fx-neon-pulse calc(var(--fx-duration) * .5) ease-in-out infinite;
}
@keyframes fx-neon-pulse{
  0%,100%{ box-shadow: 0 0 calc(10px * var(--fx-intensity)) var(--fx-glow),
                       0 0 calc(28px * var(--fx-intensity)) color-mix(in srgb, var(--fx-glow) 45%, transparent) }
  50%    { box-shadow: 0 0 calc(22px * var(--fx-intensity)) var(--fx-glow),
                       0 0 calc(56px * var(--fx-intensity)) color-mix(in srgb, var(--fx-glow) 65%, transparent) }
}

/* 04 · fx-tilt-follow — inclinación 3D al hover */
.fx-tilt-follow{
  --fx-tilt: 9deg;
  transform-style: preserve-3d;
  transition: transform .3s var(--fx-ease);
}
.fx-tilt-follow:hover{
  transform: perspective(900px) rotateX(var(--fx-tilt)) rotateY(calc(var(--fx-tilt) * -1)) scale(1.03);
}

/* 05 · fx-noise-grain — grano de película, SVG inline, sin imagen */
.fx-noise-grain{
  --fx-grain: .18;
  position: relative;
  isolation: isolate;
}
.fx-noise-grain::after{
  content:"";
  position:absolute; inset:0;
  pointer-events:none;
  opacity: var(--fx-grain);
  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'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 06 · fx-aurora-wash — manchas de color difusas en deriva lenta */
.fx-aurora-wash{
  --fx-a: var(--fx-accent);
  --fx-b: var(--fx-accent-2);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.fx-aurora-wash::before{
  content:"";
  position:absolute; inset:-40%;
  z-index:-1;
  background:
    radial-gradient(38% 46% at 22% 30%, color-mix(in srgb, var(--fx-a) 70%, transparent), transparent 70%),
    radial-gradient(42% 40% at 78% 66%, color-mix(in srgb, var(--fx-b) 70%, transparent), transparent 70%);
  filter: blur(28px);
  animation: fx-aurora calc(var(--fx-duration) * 3) ease-in-out infinite alternate;
}
@keyframes fx-aurora{
  0%  { transform: translate(-6%,-4%) rotate(0deg)   scale(1) }
  100%{ transform: translate(7%,5%)   rotate(22deg)  scale(1.18) }
}

/* 07 · fx-dot-matrix — trama de puntos tipo semitono */
.fx-dot-matrix{
  --fx-dot: rgba(255,255,255,.16);
  --fx-dot-size: 14px;
  background-image: radial-gradient(var(--fx-dot) 1.4px, transparent 1.5px);
  background-size: var(--fx-dot-size) var(--fx-dot-size);
}

/* 08 · fx-blueprint-grid — retícula milimetrada */
.fx-blueprint-grid{
  --fx-grid: rgba(255,255,255,.07);
  --fx-grid-size: 24px;
  background-image:
    linear-gradient(var(--fx-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--fx-grid) 1px, transparent 1px);
  background-size: var(--fx-grid-size) var(--fx-grid-size);
}

/* 09 · fx-conic-shimmer — borde iridiscente girando */
.fx-conic-shimmer{
  --fx-ring: 2px;
  position: relative;
  isolation: isolate;
}
.fx-conic-shimmer::before{
  content:"";
  position:absolute; inset: calc(var(--fx-ring) * -1);
  z-index:-1;
  border-radius: inherit;
  background: conic-gradient(from 0deg,
    var(--fx-accent), var(--fx-accent-2), #F472B6, var(--fx-accent));
  animation: fx-conic calc(var(--fx-duration) * .8) linear infinite;
}
@keyframes fx-conic{ to{ transform: rotate(1turn) } }

/* 10 · fx-gradient-sweep — degradado barriendo el texto */
.fx-gradient-sweep{
  background: linear-gradient(100deg,
    currentColor 0%, currentColor 38%,
    var(--fx-accent-2) 50%,
    currentColor 62%, currentColor 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: fx-sweep calc(var(--fx-duration) * .8) linear infinite;
}
@keyframes fx-sweep{
  0%  { background-position: 160% 0 }
  100%{ background-position: -60% 0 }
}

/* 11 · fx-shake-error — vibración lateral de validación fallida */
.fx-shake-error{
  animation: fx-shake .42s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes fx-shake{
  10%,90%{ transform: translateX(-2px) }
  20%,80%{ transform: translateX(4px) }
  30%,50%,70%{ transform: translateX(-7px) }
  40%,60%{ transform: translateX(7px) }
}

/* ════════════════════════════════════════════════════════════
   V1 · T2 — NECESITAN WRAPPER (8)
   ════════════════════════════════════════════════════════════ */
/* 12 · fx-billboard-spin — rotateY continuo, cartel de dos caras */
.fx-billboard-spin{
  display: inline-block;
  align-self: flex-start;
  perspective: var(--fx-depth);
  perspective-origin: 50% 50%;
}
.fx-billboard-spin__inner{
  position: relative; display: block;
  transform-style: preserve-3d;
  transform-origin: 50% 50%;
  animation: fx-billboard var(--fx-duration) linear infinite;
  will-change: transform;
}
.fx-billboard-spin__face{
  display:block; white-space:nowrap;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
}
.fx-billboard-spin__face--back{
  position:absolute; inset:0;
  transform: rotateY(180deg);
}
@keyframes fx-billboard{
  0%  { transform: rotateY(0deg);   filter: brightness(1) }
  25% { filter: brightness(var(--fx-shade)) }
  50% { transform: rotateY(180deg); filter: brightness(1) }
  75% { filter: brightness(var(--fx-shade)) }
  100%{ transform: rotateY(360deg); filter: brightness(1) }
}

/* 13 · fx-card-flip — 0→180 al hover, revela el reverso */
.fx-card-flip{ perspective: 1200px; display:block }
.fx-card-flip__inner{
  position: relative;
  transform-style: preserve-3d;
  transition: transform .62s var(--fx-ease);
  height: 100%;
}
.fx-card-flip:hover .fx-card-flip__inner{ transform: rotateY(180deg) }
.fx-card-flip__face{
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
  display:flex; align-items:center; justify-content:center;
  height:100%; border-radius:inherit;
}
.fx-card-flip__face--back{
  position:absolute; inset:0;
  transform: rotateY(180deg);
}

/* 14 · fx-coin-toss — giro sobre el eje X (vertical) */
.fx-coin-toss{
  display:inline-block; align-self:flex-start;
  perspective: var(--fx-depth);
}
.fx-coin-toss__inner{
  position:relative; display:block;
  transform-style: preserve-3d;
  animation: fx-coin var(--fx-duration) linear infinite;
}
.fx-coin-toss__face{
  display:block; backface-visibility:hidden; -webkit-backface-visibility:hidden;
}
.fx-coin-toss__face--back{
  position:absolute; inset:0; transform: rotateX(180deg);
}
@keyframes fx-coin{
  0%  { transform: rotateX(0deg);   filter: brightness(1) }
  25% { filter: brightness(var(--fx-shade)) }
  50% { transform: rotateX(180deg); filter: brightness(1) }
  75% { filter: brightness(var(--fx-shade)) }
  100%{ transform: rotateX(360deg); filter: brightness(1) }
}

/* 15 · fx-depth-stack — capas con translateZ, paralaje al hover */
.fx-depth-stack{
  perspective: 900px;
  display:block;
}
.fx-depth-stack__inner{
  position:relative;
  transform-style: preserve-3d;
  transition: transform .4s var(--fx-ease);
  height:100%;
}
.fx-depth-stack:hover .fx-depth-stack__inner{
  transform: rotateX(12deg) rotateY(-12deg);
}
.fx-depth-stack__layer{ transition: transform .4s var(--fx-ease) }
.fx-depth-stack__layer--1{ transform: translateZ(0px) }
.fx-depth-stack__layer--2{ transform: translateZ(28px) }
.fx-depth-stack__layer--3{ transform: translateZ(58px) }

/* 16 · fx-marquee-loop — cinta infinita horizontal */
.fx-marquee-loop{
  --fx-marquee-speed: 14s;
  display:flex; overflow:hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.fx-marquee-loop__track{
  display:flex; flex-shrink:0; gap:2rem; padding-right:2rem;
  animation: fx-marquee var(--fx-marquee-speed) linear infinite;
  will-change: transform;
}
@keyframes fx-marquee{ to{ transform: translateX(-100%) } }

/* 17 · fx-mask-wipe — revelado por máscara al entrar */
.fx-mask-wipe{ display:block; overflow:hidden }
.fx-mask-wipe__inner{
  display:block;
  animation: fx-wipe .9s var(--fx-ease) both;
}
@keyframes fx-wipe{
  from{ clip-path: inset(0 100% 0 0); transform: translateX(-14px) }
  to  { clip-path: inset(0 0 0 0);    transform: none }
}

/* 18 · fx-split-reveal — letras entrando una a una */
.fx-split-reveal{ display:inline-block; overflow:hidden }
.fx-split-reveal__char{
  display:inline-block;
  animation: fx-split .55s var(--fx-ease) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}
@keyframes fx-split{
  from{ opacity:0; transform: translateY(70%) rotate(6deg) }
  to  { opacity:1; transform: none }
}

/* 19 · fx-sticky-scale — el elemento crece al fijarse en scroll */
.fx-sticky-scale{ position: sticky; top: 12px }
.fx-sticky-scale__inner{
  transition: transform .35s var(--fx-ease), box-shadow .35s var(--fx-ease);
  transform-origin: top center;
}
.fx-sticky-scale.is-stuck .fx-sticky-scale__inner{
  transform: scale(1.06);
  box-shadow: 0 14px 34px rgba(0,0,0,.45);
}

/* ════════════════════════════════════════════════════════════
   V1 · T3 — NECESITAN JS (7) · ver <script> al final
   ════════════════════════════════════════════════════════════ */
/* 20 · fx-type-scramble — letras aleatorias que resuelven */
.fx-type-scramble{ font-variant-numeric: tabular-nums }

/* 21 · fx-counter-roll — cifras rodando tipo odómetro */
.fx-counter-roll{ font-variant-numeric: tabular-nums; display:inline-block }

/* 22 · fx-ripple-tap — onda desde el punto de clic */
.fx-ripple-tap{ position: relative; overflow: hidden; isolation: isolate }
.fx-ripple-tap__wave{
  position:absolute; border-radius:50%;
  background: currentColor; opacity:.32;
  transform: scale(0); pointer-events:none;
  animation: fx-ripple .62s ease-out forwards;
}
@keyframes fx-ripple{ to{ transform: scale(2.6); opacity:0 } }

/* 23 · fx-scroll-progress — barra ligada al scroll del contenedor */
.fx-scroll-progress{ position:relative }
.fx-scroll-progress__bar{
  height:4px; border-radius:99px;
  background: linear-gradient(90deg, var(--fx-accent), var(--fx-accent-2));
  width: 0%;
  transition: width .08s linear;
}

/* 24 · fx-skeleton-shimmer — placeholder de carga con brillo */
.fx-skeleton-shimmer{
  --fx-skel: rgba(255,255,255,.06);
  --fx-skel-hi: rgba(255,255,255,.16);
  background: linear-gradient(90deg, var(--fx-skel) 25%, var(--fx-skel-hi) 37%, var(--fx-skel) 63%);
  background-size: 400% 100%;
  animation: fx-skeleton 1.5s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes fx-skeleton{ from{ background-position: 100% 0 } to{ background-position: -100% 0 } }

/* 25 · fx-success-check — trazo SVG dibujándose */
.fx-success-check circle{
  stroke-dasharray: 151; stroke-dashoffset: 151;
  animation: fx-draw .5s var(--fx-ease) forwards;
}
.fx-success-check path{
  stroke-dasharray: 40; stroke-dashoffset: 40;
  animation: fx-draw .35s var(--fx-ease) .38s forwards;
}
@keyframes fx-draw{ to{ stroke-dashoffset: 0 } }

/* 26 · fx-rise-stagger — entrada escalonada desde abajo */
.fx-rise-stagger > *{
  opacity:0; transform: translateY(16px);
}
.fx-rise-stagger.is-visible > *{
  animation: fx-rise .6s var(--fx-ease) forwards;
  animation-delay: calc(var(--i, 0) * 90ms);
}
@keyframes fx-rise{ to{ opacity:1; transform:none } }

/* ---------- ACCESIBILIDAD GLOBAL ---------- */
@media (prefers-reduced-motion: reduce){
  .fx-billboard-spin__inner, .fx-coin-toss__inner, .fx-marquee-loop__track,
  .fx-neon-pulse, .fx-aurora-wash::before, .fx-conic-shimmer::before,
  .fx-gradient-sweep, .fx-skeleton-shimmer{ animation: none !important }
  .fx-billboard-spin__face--back, .fx-coin-toss__face--back{ display:none }
  .fx-mask-wipe__inner, .fx-split-reveal__char, .fx-rise-stagger > *{
    animation: none !important; opacity:1 !important; transform:none !important;
    clip-path: none !important;
  }
  .fx-gradient-sweep{ color: inherit; -webkit-text-fill-color: currentColor }
}

/* ════════════════════════════════════════════════════════════
   MOVIMIENTO REDUCIDO
   ════════════════════════════════════════════════════════════ */
/* L1 */
@media (prefers-reduced-motion: reduce){
  .fx-media *, .fx-media::before, .fx-media::after,
  [class*="fx-"]{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .fx-ken-burns > img{ animation: none !important }
  .fx-parallax-inner > img{ transform: none !important }
}
/* L2 */
@media (prefers-reduced-motion: reduce){
  [class*="fx-"]{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .fx-char-wave__char{ animation: none !important }
  .fx-typewriter__out::after{ animation: none !important }
  .fx-loading-dots > i{ animation: none !important; opacity: .7 }
}
/* L3 */
@media (prefers-reduced-motion: reduce){
  [class*="fx-"]{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .fx-border-beam::before{ animation: none !important; opacity: .5 }
}
