/* =======================
   Keyframes
   ======================= */
@keyframes fade-in {
  from { opacity: 0; transform: translate(0, 0); }
  to   { opacity: 1; transform: translate(0, 0); }
}
@keyframes fade-in-up {
  from { opacity: 0; transform: translateY(30px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in-down {
  from { opacity: 0; transform: translateY(-30px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in-left {
  from { opacity: 0; transform: translateX(-30px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes fade-in-right {
  from { opacity: 0; transform: translateX(30px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* =======================
   Estado inicial (ocultos)
   - Oculta cualquier clase que contenga "fade-in"
   ======================= */
[class*="fade-in"] {
  opacity: 0;
  will-change: opacity, transform;
}

/* =======================
   Configuración común al volverse visibles
   - Duración, timing, fill-mode y delay por variable
   ======================= */
[class*="fade-in"].visible {
  animation-duration: var(--fade-dur, 0.8s);
  animation-timing-function: ease-out;
  animation-fill-mode: both;   /* aplica el primer fotograma durante el delay */
  animation-delay: var(--fade-delay, 0s);
}

/* =======================
   Asignación de animation-name por grupo
   (incluye sus variantes -1s, -2s, -3s)
   ======================= */
.fade-in.visible,
.fade-in-1s.visible, .fade-in-2s.visible, .fade-in-3s.visible {
  animation-name: fade-in;
}
.fade-in-up.visible,
.fade-in-up-1s.visible, .fade-in-up-2s.visible, .fade-in-up-3s.visible {
  animation-name: fade-in-up;
}
.fade-in-down.visible,
.fade-in-down-1s.visible, .fade-in-down-2s.visible, .fade-in-down-3s.visible {
  animation-name: fade-in-down;
}
.fade-in-left.visible,
.fade-in-left-1s.visible, .fade-in-left-2s.visible, .fade-in-left-3s.visible {
  animation-name: fade-in-left;
}
.fade-in-right.visible,
.fade-in-right-1s.visible, .fade-in-right-2s.visible, .fade-in-right-3s.visible {
  animation-name: fade-in-right;
}

/* =======================
   Variantes de delay por clase
   (puedes añadir más si quieres)
   ======================= */
.fade-in-1s, .fade-in-up-1s, .fade-in-down-1s, .fade-in-left-1s, .fade-in-right-1s {
  --fade-delay: 1s;
}
.fade-in-2s, .fade-in-up-2s, .fade-in-down-2s, .fade-in-left-2s, .fade-in-right-2s {
  --fade-delay: 2s;
}
.fade-in-3s, .fade-in-up-3s, .fade-in-down-3s, .fade-in-left-3s, .fade-in-right-3s {
  --fade-delay: 3s;
}

/* =======================
  LOADER DOTS
======================= */
#loader {
      position: fixed;
      inset: 0;
      background: #000;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 9999;
      opacity: 1;
      transition: opacity .9s ease;
    }

    #loader.hidden {
      display: none;
    }

    .dot-number {
      display: grid;
      gap: 6px;
    }

    .dot {
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: #fff;
      opacity: .15;
    }

    .dot.on {
      opacity: 1;
    }