/*
 * TrustWeb Builder — Page Loader CSS
 * ─────────────────────────────────────────────────────────────────────────────
 * THIẾT KẾ:
 * - Dùng CSS Custom Properties (override từ inline style PHP)
 * - will-change chỉ dùng khi thực sự cần (tránh lãng phí GPU layer)
 * - prefer-reduced-motion: tắt toàn bộ animation
 * - Không dùng JS để thêm class trong CSS — mọi state đều toggle class qua JS
 * - Mọi animation dùng transform/opacity (composite layers, không reflow)
 *
 * CSS CUSTOM PROPERTIES (inject inline từ PHP):
 * --twbl-bg     : màu nền overlay    (default #ffffff)
 * --twbl-accent : màu accent/spinner (default #4f46e5)
 * --twbl-speed  : duration ms        (default 420ms)
 * ─────────────────────────────────────────────────────────────────────────────
 */

/* ─── BASE DEFAULTS (nếu PHP không inject) ──────────────────────────────────── */
:root {
  --twbl-bg:      #ffffff;
  --twbl-accent:  #4f46e5;
  --twbl-speed:   420ms;
  --twbl-ease:    cubic-bezier(0.4, 0, 0.2, 1);
  --twbl-ease-in: cubic-bezier(0.4, 0, 1, 1);
  --twbl-ease-out:cubic-bezier(0, 0, 0.2, 1);
}

/* ─── OVERLAY BASE ──────────────────────────────────────────────────────────── */
.twb-loader {
  position: fixed;
  inset: 0;
  z-index: 999999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--twbl-bg);
  /* Trạng thái ban đầu: visible — JS thêm .is-leaving để trigger exit animation */
  opacity: 1;
  visibility: visible;
  pointer-events: all;
}

/* State: loader đang exit (thêm bởi JS) */
.twb-loader.is-leaving {
  pointer-events: none;
}

/* State: loader đã hoàn toàn ẩn (thêm bởi JS sau animation) */
.twb-loader.is-hidden {
  display: none;
}

/* State: loader enter (điều hướng trang mới) */
.twb-loader.is-entering {
  pointer-events: all;
}

/* ─── INNER WRAPPER ─────────────────────────────────────────────────────────── */
.twb-loader__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  color: var(--twbl-accent);
}

/* Dots: override về row để 3 chấm nằm ngang */
.twb-loader--dots .twb-loader__inner {
  flex-direction: row;
  gap: 0;
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: FADE
   Overlay đơn giản fade in/out — nhẹ nhất, không cần GPU layer đặc biệt
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--fade {
  transition:
    opacity    var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed) var(--twbl-ease);
}
.twb-loader--fade.is-leaving {
  opacity:    0;
  visibility: hidden;
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: SLIDE-UP (Curtain)
   Panel trượt lên từ dưới lên — premium feel, smooth
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--slide-up {
  transform-origin: bottom center;
  /* Exit: trượt lên trên với ease-in (gia tốc khi bắt đầu) */
  transition:
    transform  var(--twbl-speed) var(--twbl-ease-in),
    visibility var(--twbl-speed);
}
.twb-loader--slide-up.is-leaving {
  transform:  translateY(-105%);
  visibility: hidden;
}
/* Enter step 1: đặt vị trí off-screen phía dưới — KHÔNG transition */
.twb-loader--slide-up.is-entering {
  transform:  translateY(105%);
  transition: none;
}
/* Enter step 2: is-active được JS add sau 1 rAF → browser thấy vị trí mới,
   lần này mới bật transition để animate vào */
.twb-loader--slide-up.is-entering.is-active {
  transform:  translateY(0);
  transition: transform var(--twbl-speed) var(--twbl-ease-out);
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: SLIDE-RIGHT (Curtain ngang)
   Panel trượt từ trái sang phải
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--slide-right {
  transform-origin: left center;
  /* Exit: trượt sang phải với ease-in */
  transition:
    transform  var(--twbl-speed) var(--twbl-ease-in),
    visibility var(--twbl-speed);
}
.twb-loader--slide-right.is-leaving {
  transform:  translateX(105%);
  visibility: hidden;
}
/* Enter step 1: off-screen bên trái — KHÔNG transition */
.twb-loader--slide-right.is-entering {
  transform:  translateX(-105%);
  transition: none;
}
/* Enter step 2: animate vào từ trái */
.twb-loader--slide-right.is-entering.is-active {
  transform:  translateX(0);
  transition: transform var(--twbl-speed) var(--twbl-ease-out);
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: CLIP (Circular reveal)
   Reveal từ trung tâm bằng clip-path circle — hiệu ứng độc đáo, smooth
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--clip {
  transition:
    clip-path  var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed);
  clip-path: circle(150% at 50% 50%);
}
.twb-loader--clip.is-leaving {
  clip-path:  circle(0% at 50% 50%);
  visibility: hidden;
}
.twb-loader--clip.is-entering {
  clip-path: circle(0% at 50% 50%);
  transition: clip-path var(--twbl-speed) var(--twbl-ease-out);
}
.twb-loader--clip.is-entering.is-active {
  clip-path: circle(150% at 50% 50%);
}

/* Inner element cho clip: icon nhỏ ở trung tâm */
.twb-loader__clip {
  width:  56px;
  height: 56px;
  border-radius: 50%;
  background: var(--twbl-accent);
  opacity: 0.12;
  /* Đổi tên keyframe → twbl-clip-beat để tránh conflict với twbl-pulse-ring */
  animation: twbl-clip-beat calc(var(--twbl-speed) * 1.8) ease-in-out infinite;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--twbl-accent) 40%, transparent);
}
@keyframes twbl-clip-beat {
  0%   { transform: scale(0.85); opacity: .10; box-shadow: 0 0 0 0   color-mix(in srgb, var(--twbl-accent) 35%, transparent); }
  40%  { transform: scale(1.1);  opacity: .25; box-shadow: 0 0 0 18px color-mix(in srgb, var(--twbl-accent) 0%,  transparent); }
  100% { transform: scale(0.85); opacity: .10; box-shadow: 0 0 0 0   color-mix(in srgb, var(--twbl-accent) 0%,  transparent); }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: DOTS (Ba chấm nảy)
   Spinner nhẹ nhàng, thích hợp cho fade background
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--dots {
  transition:
    opacity    var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed);
}
.twb-loader--dots.is-leaving {
  opacity:    0;
  visibility: hidden;
}

.twb-loader__dot {
  display:       inline-block;
  width:         10px;
  height:        10px;
  margin:        0 5px;
  border-radius: 50%;
  background:    var(--twbl-accent);
  animation:     twbl-dots 0.9s ease-in-out infinite;
}
.twb-loader__dot:nth-child(1) { animation-delay:  0s; }
.twb-loader__dot:nth-child(2) { animation-delay: .15s; }
.twb-loader__dot:nth-child(3) { animation-delay: .30s; }

@keyframes twbl-dots {
  0%, 80%, 100% { transform: scale(0.6); opacity: .3; }
  40%           { transform: scale(1.1); opacity: 1;  }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: BAR (Progress bar)
   Thanh mảnh trên cùng viewport — gợi cảm giác load nhanh
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--bar {
  /* Bar dùng overlay transparent để không che content, chỉ có bar ở top */
  background:    transparent;
  align-items:   flex-start;
  justify-content: flex-start;
  transition:
    opacity    calc(var(--twbl-speed) * 0.5) var(--twbl-ease) calc(var(--twbl-speed) * 0.5),
    visibility var(--twbl-speed);
}
.twb-loader--bar.is-leaving {
  opacity:    0;
  visibility: hidden;
}

.twb-loader__bar {
  position: fixed;
  top:    0;
  left:   0;
  width:  100%;
  height: 3px;
  background: color-mix(in srgb, var(--twbl-accent) 20%, transparent);
  overflow: hidden;
  z-index: 1;
}
.twb-loader__bar-fill {
  height: 100%;
  width:  0%;
  background:   var(--twbl-accent);
  border-radius: 0 2px 2px 0;
  /* Animate: nhanh lên 80% sau đó giữ, đợi JS xong mới về 100% */
  animation: twbl-bar var(--twbl-speed) var(--twbl-ease-out) forwards;
}
@keyframes twbl-bar {
  0%  { width:  0%; }
  70% { width: 75%; }
  90% { width: 88%; }
  100%{ width: 95%; }
}
/* Khi leaving: điền nốt 100% */
.twb-loader--bar.is-leaving .twb-loader__bar-fill {
  animation: none;
  width:     100%;
  transition: width calc(var(--twbl-speed) * 0.4) var(--twbl-ease-out);
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: LOGO
   Overlay + logo/text + spinner — branded loading
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--logo {
  transition:
    opacity    var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed);
}
.twb-loader--logo.is-leaving {
  opacity:    0;
  visibility: hidden;
}

.twb-loader__logo-img {
  max-width:  180px;
  max-height:  80px;
  object-fit:  contain;
  animation:   twbl-logo-in calc(var(--twbl-speed) * 0.8) var(--twbl-ease-out) forwards;
}
.twb-loader__logo-text {
  font-size:   1.5rem;
  font-weight: 700;
  color:       var(--twbl-accent);
  letter-spacing: -0.02em;
  animation:   twbl-logo-in calc(var(--twbl-speed) * 0.8) var(--twbl-ease-out) forwards;
}
@keyframes twbl-logo-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0);    }
}

.twb-loader__spinner {
  width:  28px;
  height: 28px;
  color:  var(--twbl-accent);
  animation: twbl-spin 0.8s linear infinite;
}
@keyframes twbl-spin {
  to { transform: rotate(360deg); }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ANIMATION: PULSE (Sóng lan toả)
   Vòng tròn phát sóng từ trung tâm — elegant, không gây rối mắt
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--pulse {
  transition:
    opacity    var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed);
}
.twb-loader--pulse.is-leaving {
  opacity:    0;
  visibility: hidden;
}

.twb-loader__pulse-wrap {
  position: relative;
  /* Tăng kích thước container để sóng có room lan rộng hơn */
  width:  80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Nhân trung tâm: lớn hơn, có inner glow */
.twb-loader__pulse-core {
  position:      relative;
  z-index:       2;
  width:         20px;
  height:        20px;
  border-radius: 50%;
  background:    var(--twbl-accent);
  /* Glow effect — tạo chiều sâu cho nhân */
  box-shadow:
    0 0 0  4px color-mix(in srgb, var(--twbl-accent) 20%, transparent),
    0 0 12px 2px color-mix(in srgb, var(--twbl-accent) 30%, transparent);
  animation: twbl-pulse-core 1.6s ease-in-out infinite;
}
@keyframes twbl-pulse-core {
  0%, 100% { transform: scale(1);    }
  50%      { transform: scale(1.15); }
}

/* 3 vòng sóng lan — thêm 1 vòng thứ 3 để denser */
.twb-loader__pulse-ring {
  position:      absolute;
  /* Bắt đầu cùng kích thước với nhân (20px) thay vì cả container */
  width:         20px;
  height:        20px;
  border-radius: 50%;
  border:        2px solid var(--twbl-accent);
  animation:     twbl-pulse-ring 2s ease-out infinite;
  opacity:       0;
}
.twb-loader__pulse-ring:nth-child(1) { animation-delay: 0s;    }
.twb-loader__pulse-ring:nth-child(2) { animation-delay: 0.65s; }

@keyframes twbl-pulse-ring {
  0%   { transform: scale(1);   opacity: .75; }
  70%  { transform: scale(3.8); opacity: 0;   }
  100% { transform: scale(3.8); opacity: 0;   }
}

/* ─── REDUCED MOTION ────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .twb-loader,
  .twb-loader *,
  .twb-loader::before,
  .twb-loader::after {
    animation-duration:   0.01ms !important;
    animation-delay:      0ms    !important;
    transition-duration:  0.01ms !important;
  }
}
