/*
 * 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)
 * --twbl-logo-size / --twbl-logo-size-mobile : logo width
 * --twbl-spinner-size / --twbl-logo-gap       : logo mode sizing
 * ─────────────────────────────────────────────────────────────────────────────
 */

/* ─── BASE DEFAULTS (nếu PHP không inject) ──────────────────────────────────── */
:root {
  --twbl-bg:      #ffffff;
  --twbl-accent:  #4f46e5;
  --twbl-speed:   420ms;
  --twbl-logo-size: 180px;
  --twbl-logo-size-mobile: 140px;
  --twbl-logo-text-size: 30px;
  --twbl-logo-text-size-mobile: 23px;
  --twbl-spinner-size: 28px;
  --twbl-logo-gap: 16px;
  --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: var(--twbl-logo-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 (Processing bar centered)
   Thanh processing nhỏ gọn giữa màn hình — không còn thanh top bar thô cứng.
   Dùng transform/opacity để nhẹ, không reflow.
   ══════════════════════════════════════════════════════════════════════════════ */
.twb-loader--bar {
  background:
    radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--twbl-accent) 10%, transparent), transparent 38%),
    color-mix(in srgb, var(--twbl-bg) 92%, transparent);
  backdrop-filter: blur(2px);
  transition:
    opacity    var(--twbl-speed) var(--twbl-ease),
    visibility var(--twbl-speed) var(--twbl-ease);
}
.twb-loader--bar.is-leaving {
  opacity: 0;
  visibility: hidden;
}

.twb-loader__process {
  width: min(220px, calc(100vw - 48px));
  padding: 16px 18px;
  border: 1px solid color-mix(in srgb, var(--twbl-accent) 18%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--twbl-bg) 86%, #ffffff 14%);
  box-shadow:
    0 22px 60px rgba(15, 23, 42, .12),
    0 0 0 1px rgba(255,255,255,.55) inset;
  transform: translateY(0) scale(1);
  animation: twbl-process-in calc(var(--twbl-speed) * .75) var(--twbl-ease-out) both;
}
.twb-loader__process-mark {
  width: 22px;
  height: 22px;
  margin: 0 auto 10px;
  border-radius: 999px;
  background: var(--twbl-accent);
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--twbl-accent) 12%, transparent);
  animation: twbl-process-mark 1.1s ease-in-out infinite;
}
.twb-loader__bar {
  width: 100%;
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--twbl-accent) 13%, transparent);
  overflow: hidden;
}
.twb-loader__bar-fill {
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: linear-gradient(90deg, color-mix(in srgb, var(--twbl-accent) 72%, #ffffff 28%), var(--twbl-accent));
  box-shadow: 0 0 18px color-mix(in srgb, var(--twbl-accent) 35%, transparent);
  animation: twbl-bar var(--twbl-speed) var(--twbl-ease-out) forwards;
}
@keyframes twbl-process-in {
  from { opacity: 0; transform: translateY(10px) scale(.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes twbl-process-mark {
  0%, 100% { transform: scale(.84); opacity: .68; }
  50%      { transform: scale(1); opacity: 1; }
}
@keyframes twbl-bar {
  0%   { width: 0%; }
  55%  { width: 72%; }
  86%  { width: 88%; }
  100% { width: 94%; }
}
.twb-loader--bar.is-leaving .twb-loader__process {
  transform: translateY(-6px) scale(.98);
  transition: transform calc(var(--twbl-speed) * .45) var(--twbl-ease-in);
}
.twb-loader--bar.is-leaving .twb-loader__bar-fill {
  animation: none;
  width: 100%;
  transition: width calc(var(--twbl-speed) * .36) 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 .twb-loader__inner {
  gap: var(--twbl-logo-gap);
}
.twb-loader__logo-img {
  width: min(var(--twbl-logo-size), calc(100vw - 48px));
  max-height: min(180px, 34vh);
  object-fit: contain;
  animation: twbl-logo-in calc(var(--twbl-speed) * 0.8) var(--twbl-ease-out) forwards;
}
.twb-loader__logo-text {
  max-width: calc(100vw - 48px);
  font-size: var(--twbl-logo-text-size);
  font-weight: 700;
  color: var(--twbl-accent);
  line-height: 1.15;
  text-align: center;
  overflow-wrap: anywhere;
  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: var(--twbl-spinner-size);
  height: var(--twbl-spinner-size);
  color:  var(--twbl-accent);
  animation: twbl-spin 0.8s linear infinite;
}
@keyframes twbl-spin {
  to { transform: rotate(360deg); }
}


@media (max-width: 767px) {
  .twb-loader__logo-img {
    width: min(var(--twbl-logo-size-mobile), calc(100vw - 36px));
    max-height: min(140px, 30vh);
  }

  .twb-loader__logo-text {
    max-width: calc(100vw - 36px);
    font-size: var(--twbl-logo-text-size-mobile);
  }
}

/* ══════════════════════════════════════════════════════════════════════════════
   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;
  }
}

/* v4.0.10 — subtle center mark for fade/slide modes so the loader feels alive but stays light */
.twb-loader__soft-mark {
  width: 30px;
  height: 30px;
  border-radius: 14px;
  background: var(--twbl-accent);
  box-shadow:
    0 0 0 8px color-mix(in srgb, var(--twbl-accent) 12%, transparent),
    0 18px 38px color-mix(in srgb, var(--twbl-accent) 22%, transparent);
  opacity: .86;
  animation: twbl-soft-mark 1.18s ease-in-out infinite;
}
@keyframes twbl-soft-mark {
  0%, 100% { transform: translateY(0) scale(.92); opacity: .72; }
  50%      { transform: translateY(-4px) scale(1); opacity: 1; }
}
.twb-loader--fade {
  background:
    radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--twbl-accent) 7%, transparent), transparent 42%),
    var(--twbl-bg);
}
