 :root{
      --loader-bg: rgba(38, 38, 38, 0.85); /* background overlay */
      --dot-color: #00deb4;                 /* dot color */
      --dot-size: 14px;                     /* diameter of each dot */
      --dot-gap: 10px;                      /* gap between dots */
      --animation-duration: 1s;             /* cycle duration */
      --z-index: 9999;                      /* overlay z-index */
    }

/* -------------------------
       Full-screen overlay
       ------------------------- */
    .full-screen-loader {
      position: fixed;
      inset: 0; /* top:0; right:0; bottom:0; left:0; */
      align-items: center;
      justify-content: center;
      background: var(--loader-bg);
      z-index: var(--z-index);
      /* Prevent pointer interactions while loader is shown */
      pointer-events: auto;
      display: none;
    }

    /* Visually hidden text for screen readers */
    .sr-only {
      position: absolute !important;
      width: 1px; height: 1px;
      padding: 0; margin: -1px;
      overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
      border: 0;
    }

    /* -------------------------
       Dot row
       ------------------------- */
    .dot-row {
      display: flex;
      gap: var(--dot-gap);
      align-items: flex-end; /* better baseline for the "bounce" */
    }

    .dot {
      width: var(--dot-size);
      height: var(--dot-size);
      border-radius: 50%;
      background: var(--dot-color);
      transform: translateY(0);
      opacity: 0.25;
      will-change: transform, opacity;
      /* make dots not selectable */
      user-select: none;
    }

    /* staggered animation: scale/translate + opacity */
    @keyframes dotPulse {
      0%   { transform: translateY(0) scale(1);    opacity: 0.25; }
      30%  { transform: translateY(-8px) scale(1.15); opacity: 1; }
      60%  { transform: translateY(0) scale(1);    opacity: 0.4; }
      100% { transform: translateY(0) scale(1);    opacity: 0.25; }
    }

    .dot:nth-child(1) { animation: dotPulse var(--animation-duration) ease-in-out infinite; animation-delay: 0s; }
    .dot:nth-child(2) { animation: dotPulse var(--animation-duration) ease-in-out infinite; animation-delay: calc(var(--animation-duration) * 0.15); }
    .dot:nth-child(3) { animation: dotPulse var(--animation-duration) ease-in-out infinite; animation-delay: calc(var(--animation-duration) * 0.30); }

    /* Accessible reduced-motion: stop animation and leave visible static dots */
    @media (prefers-reduced-motion: reduce) {
      .dot { animation: none; opacity: 1; transform: translateY(0); }
    }

    /* Small-screen scaling: make dots slightly larger on touch devices */
    @media (max-width: 480px) {
      :root { --dot-size: 18px; --dot-gap: 12px; }
    }

    /* Utility: visually hide the overlay but keep in DOM (for hiding loader via class) */
    .hidden { display: none !important; }