/* ============================================
   MOVIMIENTO · capa de animacion de la home
   ============================================

   Todo lo de aqui esta detras de `html.ux-js`: sin JavaScript no se esconde
   nada y la pagina se ve completa. Y se apaga entero con
   `prefers-reduced-motion`, que no es un detalle de manual: hay gente a la que
   el movimiento le produce mareo de verdad.

   Solo se animan `opacity`, `transform` y `clip-path`. Ninguna propiedad que
   mueva la maquetacion, asi que nada de esto puede empeorar el CLS.

   Lo que depende del raton -inclinar tarjetas, botones magneticos- va detras de
   `(hover: hover) and (pointer: fine)`: en una pantalla tactil esos efectos no
   se pueden usar y solo estorban.

   Se revierte quitando las dos lineas de index.html que cargan
   movimiento.css y movimiento.js. */

:root {
  --mv-salida: cubic-bezier(.22, .61, .36, 1);
  --mv-rebote: cubic-bezier(.34, 1.36, .5, 1);
  --mv-tiempo: .78s;
}

/* ---------------------------------------------
   1. Entradas
   --------------------------------------------- */
html.ux-js .mv {
  opacity: 0;
  transform: translate3d(0, 38px, 0);
  transition:
    opacity var(--mv-tiempo) var(--mv-salida),
    transform var(--mv-tiempo) var(--mv-rebote);
  will-change: opacity, transform;
}

html.ux-js .mv--izquierda { transform: translate3d(-52px, 0, 0) rotate(-1.2deg); }
html.ux-js .mv--derecha { transform: translate3d(52px, 0, 0) rotate(1.2deg); }
html.ux-js .mv--escala { transform: scale(.9) translate3d(0, 26px, 0); }
html.ux-js .mv--suave { transform: translate3d(0, 20px, 0); }
html.ux-js .mv--giro { transform: translate3d(0, 44px, 0) rotate(-2.4deg) scale(.94); }

html.ux-js .mv.mv-dentro {
  opacity: 1;
  transform: none;
}

/* Al terminar se suelta el will-change: mantenerlo en decenas de elementos le
   cuesta memoria al navegador y ya no da nada a cambio. */
html.ux-js .mv.mv-listo { will-change: auto; transition: none; }

/* ---------------------------------------------
   2. Titulares: suben desde detras de su linea
   --------------------------------------------- */
html.ux-js .mv-titular {
  display: inline-block;
  clip-path: inset(0 0 -0.3em 0);
}
html.ux-js .mv-titular > .mv-titular-interior {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 108%, 0) skewY(3deg);
  transition:
    opacity .86s var(--mv-salida),
    transform .86s var(--mv-salida);
}
html.ux-js .mv-titular.mv-dentro > .mv-titular-interior {
  opacity: 1;
  transform: none;
}

/* ---------------------------------------------
   3. Imagenes: se destapan y se asientan
   --------------------------------------------- */
html.ux-js .mv-imagen {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.12);
  transition: clip-path 1s var(--mv-salida), transform 1.2s var(--mv-salida);
  will-change: clip-path, transform;
}
html.ux-js .mv-imagen.mv-dentro {
  clip-path: inset(0 0 0 0);
  transform: scale(1);
}

/* ---------------------------------------------
   4. Barra de progreso del scroll
   --------------------------------------------- */
html.ux-js .mv-progreso {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, #1350d6, #6ea8ff);
  z-index: 1200;
  pointer-events: none;
  will-change: transform;
}

/* ---------------------------------------------
   5. Parallax (lo mueve el JS con transform)
   --------------------------------------------- */
html.ux-js .mv-parallax { will-change: transform; transition: none; }

/* ---------------------------------------------
   6. Lo que necesita raton de verdad
   --------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  html.ux-js .mv-inclinable {
    transform-style: preserve-3d;
    transition: transform .4s var(--mv-salida), box-shadow .4s var(--mv-salida);
  }
  html.ux-js .mv-inclinable.mv-tocando {
    transition: transform .12s linear, box-shadow .3s var(--mv-salida);
    box-shadow: 0 22px 48px rgba(11, 26, 43, .16);
  }
  html.ux-js .mv-magnetico {
    transition: transform .34s var(--mv-rebote);
    will-change: transform;
  }
}

/* En pantalla tactil no hay puntero que seguir: el efecto se cambia por uno
   que si funciona con el dedo. */
@media (hover: none), (pointer: coarse) {
  html.ux-js .mv-inclinable:active {
    transform: scale(.985);
    transition: transform .18s ease;
  }
}

/* ---------------------------------------------
   7. Transicion entre paginas
   Una sola regla. El navegador que la entiende hace el fundido al navegar; el
   resto no hace nada y no se rompe.
   --------------------------------------------- */
@view-transition { navigation: auto; }

::view-transition-old(root) { animation: mv-salir .2s ease both; }
::view-transition-new(root) { animation: mv-entrar .34s var(--mv-salida) both; }

@keyframes mv-salir { to { opacity: 0; transform: translateY(-8px); } }
@keyframes mv-entrar { from { opacity: 0; transform: translateY(10px); } }

/* ---------------------------------------------
   8. El interruptor de accesibilidad
   --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv,
  html.ux-js .mv--izquierda,
  html.ux-js .mv--derecha,
  html.ux-js .mv--escala,
  html.ux-js .mv--suave,
  html.ux-js .mv--giro,
  html.ux-js .mv-titular > .mv-titular-interior,
  html.ux-js .mv-imagen {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  html.ux-js .mv-parallax,
  html.ux-js .mv-inclinable,
  html.ux-js .mv-magnetico { transform: none !important; transition: none !important; }
  html.ux-js .mv-progreso { display: none; }

  @view-transition { navigation: none; }
}

/* ===============================================
   9. GUIAR AL USUARIO
   La pagina ya tiene doce elementos flotantes (carrito, WhatsApp, barra de
   acciones, panel, spotlight). Meter otra barra fija seria ruido, asi que la
   guia se hace con movimiento DENTRO de la pagina, no con mas muebles.
   =============================================== */

/* 9a. Subrayado que se dibuja bajo cada titular: lleva la mirada de izquierda
   a derecha justo antes de que empiece a leer el bloque. */
html.ux-js .mv-subrayado { position: relative; }
html.ux-js .mv-subrayado::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -.18em;
  height: 3px;
  width: 100%;
  background: linear-gradient(90deg, #1350d6, #6ea8ff);
  border-radius: 3px;
  transform: scaleX(0);
  transform-origin: 0 50%;
  /* El retraso tiene que ser mayor que lo que tarda el titular en subir
     (.86s), o la linea aparece mientras el texto todavia va llegando y lo
     cruza por la mitad. Se vio en una captura. */
  transition: transform .8s .62s var(--mv-salida);
}
html.ux-js .mv-subrayado.mv-dentro::after { transform: scaleX(1); }

/* 9b. La pista de scroll del hero. Se va sola en cuanto la persona baja: una
   flecha que sigue ahi despues de hacer scroll es ruido, no ayuda. */
html.ux-js .mv-pista {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  font-size: .82rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #5a6a7b;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .6s var(--mv-salida), transform .6s var(--mv-salida);
}
html.ux-js .mv-pista.mv-dentro { opacity: 1; transform: none; }
html.ux-js .mv-pista.mv-fuera { opacity: 0; transform: translateY(-6px); pointer-events: none; }
html.ux-js .mv-pista i {
  display: block;
  width: 1px;
  height: 26px;
  background: linear-gradient(180deg, #1350d6, transparent);
  animation: mv-bajar 1.9s var(--mv-salida) infinite;
}

@keyframes mv-bajar {
  0% { transform: translateY(-8px) scaleY(.6); opacity: 0; }
  35% { opacity: 1; }
  100% { transform: translateY(14px) scaleY(1); opacity: 0; }
}

/* 9c. El boton de la seccion late UNA vez cuando esa seccion entra, y otra si
   la persona se queda quieta. No es un latido permanente: eso deja de avisar
   nada y solo molesta. */
@keyframes mv-latido {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(19, 80, 214, .5); }
  30% { transform: scale(1.045); box-shadow: 0 0 0 12px rgba(19, 80, 214, 0); }
  60% { transform: scale(1); box-shadow: 0 0 0 0 rgba(19, 80, 214, 0); }
}
html.ux-js .mv-latir { animation: mv-latido 1.5s var(--mv-salida) 1; }

/* 9d. Cuando la persona se detiene, el CTA visible se marca un momento. */
html.ux-js .mv-atencion {
  animation: mv-latido 1.5s var(--mv-salida) 2;
  position: relative;
  z-index: 3;
}

@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv-subrayado::after { transform: scaleX(1) !important; transition: none !important; }
  html.ux-js .mv-pista { opacity: 1 !important; transform: none !important; }
  html.ux-js .mv-pista i { animation: none !important; }
  html.ux-js .mv-latir,
  html.ux-js .mv-atencion { animation: none !important; }
}

/* ===============================================
   10. EL HERO, QUE ES LO QUE TODOS VEN
   La primera pantalla se lleva un tratamiento aparte: entra palabra por
   palabra, el acento llega al final y el conjunto se ordena de arriba abajo
   hasta terminar en el boton.
   =============================================== */

/* 10a. Titular palabra por palabra.
   Cada palabra es un inline-block y los espacios siguen siendo nodos de texto
   de verdad: asi el navegador corta las lineas exactamente donde las cortaba
   antes y el alto del titular no cambia ni un pixel. */
html.ux-js .mv-palabra {
  display: inline-block;
  /* SIN opacity. El h1 del hero es el elemento que marca el LCP (medido:
     H1.hero-title). Si las palabras entran desde opacidad 0, el texto no esta
     pintado y el LCP se retrasa toda la escalera de retardos, en la pagina de
     alguien que vive del SEO. Moviendolas solo con transform el texto esta
     pintado desde el primer fotograma y el barrido se ve igual. */
  transform: translate3d(0, .34em, 0) rotate(1.6deg);
  transition: transform .72s var(--mv-rebote);
  will-change: transform;
}
html.ux-js .mv-palabra.mv-dentro { transform: none; }

/* El acento entra al final y con mas cuerpo: es la palabra que importa. */
html.ux-js .mv-palabra--acento {
  transform: translate3d(0, .42em, 0) scale(.88);
}

/* 10b. El resto del hero se ordena de arriba abajo. */
html.ux-js .hero .hero-badge,
html.ux-js .hero .hero-sub,
html.ux-js .hero .hero-trust { transition-duration: .86s; }

html.ux-js .hero .hero-cta.mv { transform: translate3d(0, 26px, 0) scale(.94); }

/* 10c. Una linea que se dibuja delante del kicker. */
html.ux-js .hero .hero-badge { position: relative; }
html.ux-js .hero .hero-badge::before {
  content: "";
  position: absolute;
  left: -46px;
  top: 50%;
  width: 34px;
  height: 2px;
  background: #1350d6;
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform .8s .3s var(--mv-salida);
}
html.ux-js .hero .hero-badge.mv-dentro::before { transform: scaleX(1); }

@media (max-width: 1100px) {
  html.ux-js .hero .hero-badge::before { display: none; }
}

/* 10d. El visual entra destapandose, no solo apareciendo. */
html.ux-js .hero .hero-visual.mv-entrada {
  clip-path: inset(0 0 100% 0);
  opacity: 0;
  transform: translate3d(0, 30px, 0) scale(1.04);
  transition:
    clip-path 1.1s .2s var(--mv-salida),
    opacity .9s .2s var(--mv-salida),
    transform 1.1s .2s var(--mv-salida);
}
html.ux-js .hero .hero-visual.mv-entrada.mv-dentro {
  clip-path: inset(0 0 0 0);
  opacity: 1;
  transform: none;
}

/* 10e. Un foco que sigue al cursor por el hero. Es una capa pintada detras del
   contenido, sin eventos: no se puede pinchar ni tapa nada. */
@media (hover: hover) and (pointer: fine) {
  html.ux-js .hero { position: relative; isolation: isolate; }
  html.ux-js .hero .mv-foco {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0;
    transition: opacity .5s var(--mv-salida);
    background: radial-gradient(
      420px circle at var(--mv-x, 50%) var(--mv-y, 40%),
      rgba(19, 80, 214, .09),
      transparent 62%);
  }
  html.ux-js .hero:hover .mv-foco { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv-palabra {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  html.ux-js .hero .hero-badge::before { transform: scaleX(1) !important; transition: none !important; }
  html.ux-js .hero .hero-visual.mv-entrada {
    clip-path: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  html.ux-js .hero .mv-foco { display: none; }
}

/* ===============================================
   11. FLOTAR: MOVIMIENTO QUE NO PARA
   Las tarjetas decorativas siguen moviendose despues de entrar, muy despacio.

   REGLA: un elemento O FLOTA, O HACE PARALLAX, O SE INCLINA. Nunca dos. Los
   tres escriben `transform`, y una animacion CSS le gana a un transform puesto
   por JavaScript, asi que combinarlos apaga uno de los dos sin avisar. Las que
   flotan se sacaron a mano de las capas de parallax y de la lista de
   inclinables.

   Cada una lleva su propia duracion y su propio retraso: si todas se mueven al
   mismo compas parece un carrusel, no algo vivo.
   =============================================== */

@keyframes mv-flotar {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%  { transform: translate3d(0, -13px, 0) rotate(var(--mv-giro, .5deg)); }
  100% { transform: translate3d(0, 0, 0) rotate(0deg); }
}

html.ux-js .mv-flota {
  animation: mv-flotar var(--mv-dur, 6s) ease-in-out infinite;
  animation-delay: var(--mv-retraso, 0s);
  will-change: transform;
}

/* Fuera de pantalla se congela: no tiene sentido gastar bateria animando algo
   que nadie esta viendo. */
html.ux-js .mv-flota.mv-quieta { animation-play-state: paused; }

/* Al pasar el raton por encima se detiene y sube un poco: si la persona va a
   leer o a pinchar, lo ultimo que quiere es perseguir algo que se mueve. */
@media (hover: hover) and (pointer: fine) {
  html.ux-js .mv-flota:hover {
    animation-play-state: paused;
    transform: translate3d(0, -6px, 0);
    transition: transform .3s var(--mv-salida);
  }
}

@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv-flota {
    animation: none !important;
    transform: none !important;
  }
}

/* ===============================================
   12. DEVOLVER EL MOVIMIENTO AL HERO, SIN TOCAR EL LCP
   visual-upgrade.css trae esto, y esta bien puesto:

     body.visual-upgrade .hero-content,
     body.visual-upgrade .hero-content > *,
     body.visual-upgrade .hero-visual {
       opacity: 1 !important; transform: none !important;
       transition-delay: 0s !important;
     }

   "Above-the-fold content must paint immediately for mobile LCP". Por eso la
   entrada del hero no se veia: no es que fallara, es que esa regla la apagaba
   a proposito.

   No se pelea con la opacidad: arriba nada empieza invisible, y eso es
   correcto. Se devuelve SOLO el transform, que no retrasa el pintado porque
   el elemento ya esta ahi, solo desplazado. */

html.ux-js body.visual-upgrade .hero .hero-content > .mv {
  transform: translate3d(0, 22px, 0) !important;
  transition: transform .8s var(--mv-rebote) !important;
}
html.ux-js body.visual-upgrade .hero .hero-content > .mv.mv-dentro {
  transform: none !important;
}
html.ux-js body.visual-upgrade .hero .hero-content > .hero-cta.mv {
  transform: translate3d(0, 26px, 0) scale(.95) !important;
}
html.ux-js body.visual-upgrade .hero .hero-content > .hero-cta.mv.mv-dentro {
  transform: none !important;
}

/* Los retardos tambien vienen anulados con !important, asi que se reponen. */
html.ux-js body.visual-upgrade .hero .hero-badge.mv { transition-delay: .05s !important; }
html.ux-js body.visual-upgrade .hero .hero-sub.mv { transition-delay: .3s !important; }
html.ux-js body.visual-upgrade .hero .hero-cta.mv { transition-delay: .42s !important; }
html.ux-js body.visual-upgrade .hero .hero-trust.mv { transition-delay: .54s !important; }
html.ux-js body.visual-upgrade .hero .mv-pista { transition-delay: .68s !important; }

/* El visual se destapa con clip-path, que la regla no toca, y su parallax lo
   escribe el JS con prioridad important para poder ganarle. */
html.ux-js body.visual-upgrade .hero .hero-visual.mv-entrada {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.1s .2s var(--mv-salida);
}
html.ux-js body.visual-upgrade .hero .hero-visual.mv-entrada.mv-dentro {
  clip-path: inset(0 0 0 0);
}

@media (prefers-reduced-motion: reduce) {
  html.ux-js body.visual-upgrade .hero .hero-content > .mv,
  html.ux-js body.visual-upgrade .hero .hero-content > .mv.mv-dentro,
  html.ux-js body.visual-upgrade .hero .hero-content > .hero-cta.mv {
    transform: none !important;
    transition: none !important;
  }
  html.ux-js body.visual-upgrade .hero .hero-visual.mv-entrada { clip-path: none !important; }
}

/* ===============================================
   13. APILADO: UNA SECCION SOBRE OTRA
   El efecto de Semrush. Cada seccion del grupo se queda fija bajo la cabecera
   y la siguiente se desliza encima, como cartas que se van poniendo una sobre
   otra.

   Dos condiciones que lo hacen funcionar y que no son obvias:

   1. Las secciones del sitio son TODAS blancas. Apilar blanco sobre blanco no
      se ve: hacen falta la esquina redondeada arriba y la sombra hacia arriba
      para que el borde que entra se lea como una carta nueva.

   2. Al poner z-index en las apiladas, las secciones POSTERIORES tienen que
      subir tambien, o se quedarian por debajo y el apilado no se destaparia
      nunca.

   No se envuelve nada en un contenedor nuevo a proposito: dos de estas
   secciones llevan carruseles que ya midieron su ancho, y moverlos de sitio
   los descuadra. Solo se les cambian clases. */

html.ux-js .mv-piso {
  position: sticky;
  top: var(--mv-tope, 70px);
  transform-origin: 50% 0;
  will-change: transform;
}

/* La esquina redondeada y la sombra SOLO mientras esta seccion se esta
   deslizando sobre otra. Antes estaban puestas siempre, tambien cuando la
   seccion estaba quieta en medio de la pagina: eso dejaba un manchon gris
   difuso y una costura dura justo debajo del bloque de precios. La decoracion
   es parte del gesto, no del reposo. */
html.ux-js .mv-piso.mv-cubriendo {
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -10px 24px rgba(11, 26, 43, .07);
}

/* La de abajo se encoge un poco mientras la tapan: da la sensacion de que se
   aleja en vez de quedarse pegada. */
html.ux-js .mv-piso { transition: none; }

/* La primera no lleva esquina redondeada arriba: viene pegada a la anterior. */
html.ux-js .mv-piso--primero.mv-cubriendo { border-radius: 0; box-shadow: none; }

/* Las de despues del grupo tienen que pasar por encima. */
html.ux-js .mv-encima { position: relative; z-index: 20; }

@media (max-width: 1000px) {
  html.ux-js .mv-piso,
  html.ux-js .mv-piso.mv-cubriendo {
    position: static;
    border-radius: 0;
    box-shadow: none;
    transform: none !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv-piso {
    position: static;
    transform: none !important;
    box-shadow: none;
  }
}

/* ===============================================
   14. QUE EL APILADO SE LEA COMO TARJETAS, NO COMO TEXTO CORTADO
   El primer intento fallo por un motivo concreto: TODAS las secciones del
   sitio son blancas. Al deslizarse una sobre otra, el borde que entraba caia
   encima de una linea de texto y parecia una frase partida por la mitad, no
   una tarjeta nueva. Se vio en "cada una hace una parte del trabajo y cada /
   enlace lleva a lo que hago con ella".

   En Semrush cada panel se distingue del de abajo. Aqui se consigue igual:
   fondo alterno entre pisos y un canto visible desde que empieza a cubrir.
   =============================================== */

/* Fondo alterno: pares en blanco, impares en un gris azulado muy claro. Con
   dos tonos distintos, el borde que entra se lee como el canto de una tarjeta
   y no como un corte. */
html.ux-js body .mv-piso.mv-piso--base { background: #ffffff !important; }
html.ux-js body .mv-piso.mv-piso--tono { background: #f2f6fb !important; }

/* El canto se ve desde que la seccion empieza a cubrir a la de abajo, no solo
   a mitad del gesto: si aparece tarde, el primer tramo sigue pareciendo un
   texto cortado. */
html.ux-js .mv-piso.mv-cubriendo {
  border-radius: 22px 22px 0 0;
  border-top: 1px solid rgba(11, 26, 43, .10);
  box-shadow: 0 -14px 30px rgba(11, 26, 43, .10);
}

/* Y mientras esta cubriendo, la de abajo se apaga un poco: refuerza que hay
   una capa delante y no un salto raro. */
html.ux-js .mv-piso.mv-tapada { filter: brightness(.985); }

@media (prefers-reduced-motion: reduce) {
  html.ux-js .mv-piso.mv-tapada { filter: none; }
  html.ux-js body .mv-piso.mv-piso--tono { background: #ffffff !important; }
}

/* Cada piso ocupa el hueco visible y centra su contenido.
   Esto es lo que hace que el apilado no corte frases: si el contenido esta
   centrado, el borde de la seccion que entra barre PRIMERO el espacio vacio de
   abajo y solo llega al texto al final del recorrido. Sin esto, el borde se
   detiene a media linea y parece una frase partida.
   `align-content: center` sobre grid y no flex: con flex los hijos se pondrian
   en fila y estas secciones tienen varios bloques uno debajo de otro. */
/* Variante para las secciones que YA traen su propia maquetacion (el hero es
   flex con dos columnas). A esas no se les toca el display: convertirlas en
   grid de una columna apila sus columnas y la seccion pasa de 756 a 1239 px,
   que es justo lo que la dejaba cortada. Solo se les da altura y centrado. */
html.ux-js .mv-piso.mv-piso--altoflex {
  min-height: calc(100vh - var(--mv-tope, 70px) - 40px);
  align-items: center;
}

html.ux-js .mv-piso.mv-piso--alto {
  /* El mismo margen de 40 px que usa la guardia de "cabe o no cabe". Con
     valores distintos, el piso quedaba 40 px mas alto que el limite y la
     revision lo soltaba siempre. */
  min-height: calc(100vh - var(--mv-tope, 70px) - 40px);
  display: grid;
  align-content: center;
}

/* ===============================================
   16. BOTONES DE VIDRIO LIQUIDO
   El efecto del componente de React, portado a CSS.

   Por que portado y no montado: los CTA del sitio son <a href>. El componente
   renderiza un <button>, y cambiar un enlace por un boton quita el enlace
   interno, que en un sitio que vive del SEO es perdida real. Ademas serian
   ~40 KB de React para un boton, y si el JS falla te quedas sin llamada a la
   accion. El efecto no es React: son sombras superpuestas y un filtro SVG.

   La receta de sombras es la del original, tal cual. El filtro va en un <svg>
   oculto dentro de index.html, con el mismo id: #container-glass.
   =============================================== */

.btn-liquido {
  position: relative;
  background: transparent !important;
  border: 0 !important;
  isolation: isolate;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), filter .3s ease;
}

/* La capa del canto: es lo que da el grosor de cristal. */
.btn-liquido::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    0 0 6px rgba(0,0,0,.03),
    0 2px 6px rgba(0,0,0,.08),
    inset 3px 3px .5px -3px rgba(0,0,0,.9),
    inset -3px -3px .5px -3px rgba(0,0,0,.85),
    inset 1px 1px 1px -.5px rgba(0,0,0,.6),
    inset -1px -1px 1px -.5px rgba(0,0,0,.6),
    inset 0 0 6px 6px rgba(0,0,0,.12),
    inset 0 0 2px 2px rgba(0,0,0,.06),
    0 0 12px rgba(255,255,255,.15);
}

/* La capa que deforma lo que hay detras. Comprobado en Chromium: el filtro SVG
   en backdrop-filter SI se dibuja, los pixeles con y sin filtro difieren. */
.btn-liquido::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  backdrop-filter: url("#container-glass");
  -webkit-backdrop-filter: url("#container-glass");
}

.btn-liquido > * { position: relative; z-index: 1; }
.btn-liquido:hover { transform: scale(1.05); }
.btn-liquido:active { transform: scale(.99); }

/* Pildora, como el original: la receta de sombras esta calculada para un borde
   completamente redondeado. En un rectangulo de radio corto las sombras
   internas se comprimen y el cristal no se lee. */
/* Con la especificidad suficiente: limpio.css trae
     body.dtw-limpio .hero .btn-outline { border-radius: var(--radius) !important }
   que es (0,3,1) y le ganaba a un `.btn-liquido` suelto. El radio se quedaba
   en 4px y el cristal no se leia. */
.btn-liquido,
body.dtw-limpio .hero .btn-outline.btn-liquido,
body.dtw-corp .hero .btn-outline.btn-liquido {
  border-radius: 999px !important;
  padding-left: 26px !important;
  padding-right: 26px !important;
}

/* El vidrio va SOLO en el secundario, y es una decision, no un descuido.
   Para que se vea el cristal el fondo tiene que ser translucido, y con el
   fondo claro del hero eso deja el texto blanco en 3,6 de contraste: por
   debajo del 4,5 que se exige. El principal es el boton que trae clientes;
   se queda solido y legible. */
.hero .btn-outline.btn-liquido {
  color: #0a0a0a !important;
  font-weight: 600;
}

@media (prefers-reduced-motion: reduce) {
  .btn-liquido { transition: none; }
  .btn-liquido:hover { transform: none; }
}
