/* =======================================================================
   BTN-LOADER  —  Premium button loading / success / error states  v2
   Applied to every submit & action button across the entire site.

   HTML structure injected by btn-loader.js:
     <button class="bl [original-classes]">
       <span class="bl-text">  …original HTML…  </span>
       <span class="bl-spin" aria-hidden="true">  <svg…>  </span>
       <span class="bl-ok"   aria-hidden="true">  <svg…>  </span>
       <span class="bl-err"  aria-hidden="true">  <svg…>  </span>
     </button>

   State classes added to the <button>:
     .bl-on      → loading  (spinner visible)
     .bl-ok-on   → success  (checkmark visible, AJAX only)
     .bl-err-on  → error    (X visible, AJAX only)
======================================================================= */

/* ── 1. Base ──────────────────────────────────────────────────────── */
button.bl {
    position: relative;
    overflow: hidden;
    vertical-align: middle;
    /* Set by JS: btn.style.minWidth — keeps width stable during animation */
}

/* ── 2. Label layer (original button content) ─────────────────────── */
button.bl .bl-text {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    /* idle → visible at rest */
    opacity: 1;
    transform: translateY(0);
    transition: opacity .2s ease, transform .26s cubic-bezier(.4, 0, .2, 1);
    will-change: opacity, transform;
}

/* ── 3. Icon overlay layers (spinner / checkmark / X) ─────────────── */
button.bl .bl-spin,
button.bl .bl-ok,
button.bl .bl-err {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* idle → hidden, shifted down */
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
    transition: opacity .2s ease, transform .26s cubic-bezier(.4, 0, .2, 1);
    will-change: opacity, transform;
}

/* ── 4. SVG sizing ────────────────────────────────────────────────── */

/* Default (Bootstrap regular / custom full-width) */
button.bl .bl-spin svg,
button.bl .bl-ok   svg,
button.bl .bl-err  svg {
    width:  20px;
    height: 20px;
}

/* Small table-action buttons */
button.btn-sm.bl .bl-spin svg,
button.btn-sm.bl .bl-ok   svg,
button.btn-sm.bl .bl-err  svg {
    width:  15px;
    height: 15px;
}

/* Large full-width auth / primary buttons */
button.btn-submit.bl  .bl-spin svg,
button.btn-submit.bl  .bl-ok   svg,
button.btn-submit.bl  .bl-err  svg,
button.btn-login.bl   .bl-spin svg,
button.btn-login.bl   .bl-ok   svg,
button.btn-login.bl   .bl-err  svg,
button.primary_btn.bl .bl-spin svg,
button.primary_btn.bl .bl-ok   svg,
button.primary_btn.bl .bl-err  svg,
button.resend-btn.bl  .bl-spin svg,
button.resend-btn.bl  .bl-ok   svg,
button.resend-btn.bl  .bl-err  svg {
    width:  20px;
    height: 20px;
}

/* ── 5. Spinner arc rotation ──────────────────────────────────────── */
@keyframes bl-spin {
    to { transform: rotate(360deg); }
}

button.bl .bl-spin svg {
    animation: bl-spin .75s linear infinite;
    transform-origin: 50% 50%;   /* centre of rendered SVG box */
}

/* ── 6. Checkmark stroke-draw ──────────────────────────────────────── */
@keyframes bl-draw {
    from { stroke-dashoffset: 22; }
    to   { stroke-dashoffset: 0;  }
}

button.bl.bl-ok-on .bl-ok .bl-chk {
    animation: bl-draw .36s cubic-bezier(.4, 0, .2, 1) forwards .04s;
}

/* ── 7. Shimmer sweep (loading only) ──────────────────────────────── */
@keyframes bl-shim {
    from { transform: translateX(-130%); }
    to   { transform: translateX(130%);  }
}

button.bl.bl-on::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        105deg,
        transparent 20%,
        rgba(255,255,255,.22) 50%,
        transparent 80%
    );
    animation: bl-shim 1.25s ease infinite;
    pointer-events: none;
    z-index: 5;
}

/* Reduce shimmer on dark-bg buttons that already look bright */
[data-bs-theme="dark"] button.bl.bl-on::after,
[data-theme="dark"]    button.bl.bl-on::after {
    background: linear-gradient(
        105deg,
        transparent 20%,
        rgba(255,255,255,.10) 50%,
        transparent 80%
    );
}

/* ── 8. Success pulse ring (AJAX buttons) ─────────────────────────── */
@keyframes bl-ok-pulse {
    0%   { box-shadow: 0 0 0 0   rgba(25,135,84,.50); }
    65%  { box-shadow: 0 0 0 9px rgba(25,135,84,.00); }
    100% { box-shadow: 0 0 0 0   rgba(25,135,84,.00); }
}

/* ── 9. Error shake + pulse ring (AJAX buttons) ───────────────────── */
@keyframes bl-shake {
    0%,100% { transform: translateX(0);  }
    20%,60% { transform: translateX(-5px); }
    40%,80% { transform: translateX( 5px); }
}

@keyframes bl-err-pulse {
    0%   { box-shadow: 0 0 0 0   rgba(220,53,69,.50); }
    65%  { box-shadow: 0 0 0 9px rgba(220,53,69,.00); }
    100% { box-shadow: 0 0 0 0   rgba(220,53,69,.00); }
}

/* ── 10. LOADING STATE ────────────────────────────────────────────── */
button.bl.bl-on {
    pointer-events: none !important;
    cursor:          not-allowed !important;
    opacity:         .86;
}

button.bl.bl-on .bl-text {
    opacity:   0;
    transform: translateY(-10px);
}

button.bl.bl-on .bl-spin {
    opacity:   1;
    transform: translateY(0);
}

/* ── 11. SUCCESS STATE ────────────────────────────────────────────── */
button.bl.bl-ok-on {
    pointer-events: none !important;
    cursor:          default !important;
    filter:          brightness(1.07);
    animation:       bl-ok-pulse .65s ease forwards;
}

button.bl.bl-ok-on .bl-text {
    opacity:   0;
    transform: translateY(-10px);
}

button.bl.bl-ok-on .bl-ok {
    opacity:   1;
    transform: translateY(0);
}

/* Small buttons — skip pulse ring (too tiny) */
button.btn-sm.bl.bl-ok-on { animation: none; }

/* ── 12. ERROR STATE ──────────────────────────────────────────────── */
button.bl.bl-err-on {
    pointer-events: none !important;
    cursor:          not-allowed !important;
    filter:          brightness(.93);
    animation:       bl-err-pulse .65s ease forwards, bl-shake .42s ease;
}

button.bl.bl-err-on .bl-text {
    opacity:   0;
    transform: translateY(-10px);
}

button.bl.bl-err-on .bl-err {
    opacity:   1;
    transform: translateY(0);
}

/* Small buttons — only shake, no ring */
button.btn-sm.bl.bl-err-on { animation: bl-shake .42s ease; }

/* ── 13. Transparent / link-style buttons ─────────────────────────── */
/* btn-link and resend-btn have no background → shimmer is invisible,
   which is fine; the spinner + opacity still give clear loading feedback */
button.btn-link.bl.bl-on::after,
button.resend-btn.bl.bl-on::after {
    display: none;   /* no shimmer on transparent bg buttons */
}

/* ── 14. Icon-only btn-sm: ensure minimum tap area ───────────────── */
button.btn-sm.bl {
    min-width: 30px;
    min-height: 28px;
}
