/*
 * TrustWeb Builder — TrustExtra CSS v3.5.1
 * ─────────────────────────────────────────────────────────────────────────────
 * Animations (scroll-triggered entrance) + Parallax on Scroll
 *
 * NGUYÊN TẮC:
 * - Chỉ dùng transform + opacity (composite layer, không gây reflow/repaint)
 * - will-change chỉ đặt trên element đang animate — bỏ ngay sau khi xong
 * - prefers-reduced-motion: tắt TOÀN BỘ hiệu ứng (WCAG 2.1 SC 2.3.3)
 *
 * BUG-4 FIX: Parallax dùng CSS custom properties (--twb-x-px/py/pz)
 * thay vì overwrite element.style.transform trực tiếp.
 * → Không conflict với Elementor motion effects hay CSS transform khác.
 * → JS chỉ setProperty 3 CSS vars, CSS ghép translate3d() từ vars đó.
 * ─────────────────────────────────────────────────────────────────────────────
 */

/* ─── ANIMATION STATES ───────────────────────────────────────────────────────
 * .twb-x-pending   : element chờ vào viewport → ẩn
 * .twb-x-animating : đang chạy animation → will-change active
 * .twb-x-done      : xong → visible, cleanup
 * ──────────────────────────────────────────────────────────────────────────── */

.twb-x-pending {
  opacity: 0;
}

.twb-x-animating {
  will-change: transform, opacity;
}

/*
 * .twb-x-done: visible hoàn toàn sau khi animation xong.
 *
 * QUAN TRỌNG — không set transform: none !important globally.
 * Nếu element cũng có parallax, transform: none sẽ kill parallax.
 * Logic: JS sẽ KHÔNG add .twb-x-done nếu element có parallax —
 * chỉ cleanup animation classes, để parallax tiếp quản transform.
 * Với element chỉ có animation (không parallax): JS add .twb-x-done bình thường.
 */
.twb-x-done {
  opacity: 1 !important;
  will-change: auto !important;
}

/* Reset transform chỉ khi element KHÔNG có parallax */
.twb-x-done:not(.twb-x-parallax-active) {
  transform: none !important;
}

/* ─── PARALLAX — CSS CUSTOM PROPERTY APPROACH ───────────────────────────────
 *
 * BUG-4 FIX: JS set --twb-x-px/py/pz, CSS ghép thành translate3d().
 *
 * Cách hoạt động:
 *   JS:  item.el.style.setProperty('--twb-x-py', '-24.5px')
 *   CSS: transform: translate3d(var(--twb-x-px,0), var(--twb-x-py,0), var(--twb-x-pz,0))
 *
 * Lý do KHÔNG dùng element.style.transform trực tiếp:
 *   - Elementor "Motion Effects" (Pro) cũng set inline transform → bị overwrite
 *   - Elementor _wrapper có thể có CSS transform từ sticky header logic
 *   - CSS vars approach: cả 2 transforms coexist thông qua CSS cascade
 *
 * Lưu ý: CSS vars chỉ set khi parallax active nên fallback 0 là an toàn.
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * Parallax transform: chỉ active khi element KHÔNG đang pending/animating.
 *
 * Lý do: nếu element có cả parallax + animation đồng thời:
 *   - Khi pending/animating: animation keyframe cần control transform hoàn toàn
 *     (ví dụ fadeInUp: translateY(40px) → translateY(0))
 *   - Nếu parallax transform active cùng lúc: specificity conflict → animation
 *     bị overwrite hoặc behave sai
 *   - Sau khi animation xong (classes removed): parallax tiếp quản transform
 *
 * Sequential flow: [pending] → [animating+run-X] → [done/clean] → [parallax active]
 */
[data-twb-extra].twb-x-parallax-active:not(.twb-x-pending):not(.twb-x-animating) {
  will-change: transform;
  transform: translate3d(
    var(--twb-x-px, 0px),
    var(--twb-x-py, 0px),
    var(--twb-x-pz, 0px)
  );
}

/* ─── KEYFRAMES ──────────────────────────────────────────────────────────────
 * Start từ trạng thái "ẩn/lệch" → kết thúc "tự nhiên".
 * JS set --twb-x-dur và --twb-x-delay via inline style trên element.
 * ──────────────────────────────────────────────────────────────────────────── */

@keyframes twbx-fadeIn {
  from { opacity: 0; filter: blur(2px); }
  to   { opacity: 1; filter: blur(0); }
}

@keyframes twbx-fadeInUp {
  from { opacity: 0; transform: translate3d(0, 32px, 0) scale(.985); filter: blur(3px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: blur(0); }
}

@keyframes twbx-fadeInDown {
  from { opacity: 0; transform: translate3d(0, -28px, 0) scale(.985); filter: blur(3px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: blur(0); }
}

@keyframes twbx-fadeInLeft {
  from { opacity: 0; transform: translate3d(-36px, 0, 0) scale(.99); filter: blur(2px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: blur(0); }
}

@keyframes twbx-fadeInRight {
  from { opacity: 0; transform: translate3d(36px, 0, 0) scale(.99); filter: blur(2px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: blur(0); }
}

@keyframes twbx-zoomIn {
  from { opacity: 0; transform: translate3d(0, 16px, 0) scale(.94); filter: blur(2px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: blur(0); }
}

@keyframes twbx-slideUp {
  from { opacity: 0; transform: translate3d(0, 44px, 0); filter: blur(2px); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); filter: blur(0); }
}

@keyframes twbx-bounceIn {
  0%   { opacity: 0; transform: scale(0.6); }
  55%  { opacity: 1; transform: scale(1.06); }
  75%  { transform: scale(0.96); }
  90%  { transform: scale(1.02); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes twbx-flipInX {
  from { opacity: 0; transform: perspective(600px) rotateX(-70deg); }
  to   { opacity: 1; transform: perspective(600px) rotateX(0deg); }
}

@keyframes twbx-flipInY {
  from { opacity: 0; transform: perspective(600px) rotateY(-70deg); }
  to   { opacity: 1; transform: perspective(600px) rotateY(0deg); }
}

/* ─── ANIMATION CLASSES ──────────────────────────────────────────────────────
 * Áp dụng khi JS add class .twb-x-run-{name}
 * Duration + delay set qua CSS custom properties --twb-x-dur / --twb-x-delay
 * ──────────────────────────────────────────────────────────────────────────── */

/* Nhóm 1: Trượt và Mờ (Fades & Slides) - Expo Out (Nhanh lúc đầu, êm ái lúc sau) */
.twb-x-run-fadeIn {
  animation: twbx-fadeIn var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-fadeInUp {
  animation: twbx-fadeInUp var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-fadeInDown {
  animation: twbx-fadeInDown var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-fadeInLeft {
  animation: twbx-fadeInLeft var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-fadeInRight {
  animation: twbx-fadeInRight var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-slideUp {
  animation: twbx-slideUp var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* Nhóm 2: Xoay (Flips) - Expo Out (Giữ nguyên cảm giác êm của 3D) */
.twb-x-run-flipInX {
  animation: twbx-flipInX var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

.twb-x-run-flipInY {
  animation: twbx-flipInY var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* Nhóm 3: Phóng to (Zoom) - Subtle Spring (Căng nhẹ ở đích rồi nhả ra) */
.twb-x-run-zoomIn {
  animation: twbx-zoomIn var(--twb-x-dur, 900ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.34, 1.25, 0.3, 1) both;
}

/* Nhóm 4: Nhún nảy (Bounce) - Cubic Out (Hỗ trợ nhịp độ đều cho keyframes phức tạp) */
.twb-x-run-bounceIn {
  animation: twbx-bounceIn var(--twb-x-dur, 1000ms) var(--twb-x-delay, 0ms)
             cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

/* ─── PREFERS-REDUCED-MOTION ─────────────────────────────────────────────────
 * Tắt TOÀN BỘ animation + parallax khi user yêu cầu giảm chuyển động
 * (WCAG 2.1 success criterion 2.3.3)
 * ──────────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  [class*="twb-x-run-"],
  .twb-x-pending,
  .twb-x-animating {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    will-change: auto !important;
  }

  [data-twb-extra].twb-x-parallax-active,
  [data-twb-extra].twb-x-parallax-active:not(.twb-x-pending):not(.twb-x-animating) {
    will-change: auto;
    transform: none !important;
    /* Reset CSS vars parallax về 0 */
    --twb-x-px: 0px;
    --twb-x-py: 0px;
    --twb-x-pz: 0px;
  }
}
/* ─── STICKY — smart fixed sticky layer ─────────────────────────────────────
 * Native sticky chỉ dùng làm fallback khi JS chưa chạy. JS runtime sẽ chuyển
 * sang position: fixed + placeholder để menu/header vẫn sticky dù nằm trong
 * section/header ngắn của Elementor.
 * Không dùng transform cho sticky để tránh conflict với Parallax/Animation.
 * ──────────────────────────────────────────────────────────────────────────── */

[data-twb-extra].twb-x-sticky {
  transition:
    box-shadow var(--twb-sticky-state-duration, 220ms) ease,
    background-color var(--twb-sticky-state-duration, 220ms) ease,
    border-color var(--twb-sticky-state-duration, 220ms) ease,
    color var(--twb-sticky-state-duration, 220ms) ease,
    opacity var(--twb-sticky-state-duration, 220ms) ease;
}

/*
 * Breakpoint correctness: JS adds this class only when Elementor's *actual*
 * current device mode is allowed for the element. This avoids hardcoded media
 * queries diverging from Elementor Site Settings/custom breakpoints.
 */
/* Native sticky chỉ là fallback cho Sticky bắt đầu ngay (startAt=0).
 * Với delayed sticky, giữ nguyên positioning Normal của Elementor cho tới khi
 * Smart Fixed JS thực sự vượt ngưỡng; không ép relative/top/bottom trước ngưỡng. */
[data-twb-extra].twb-x-sticky.twb-x-sticky-device-active:not(.twb-x-sticky--delayed) {
  position: sticky;
  z-index: var(--twb-sticky-z, 50);
}

[data-twb-extra].twb-x-sticky-device-active:not(.twb-x-sticky--delayed).twb-x-sticky--top {
  top: var(--twb-sticky-offset, 0px);
}

[data-twb-extra].twb-x-sticky-device-active:not(.twb-x-sticky--delayed).twb-x-sticky--bottom {
  bottom: var(--twb-sticky-offset, 0px);
}

[data-twb-extra].twb-x-sticky-ready {
  backface-visibility: hidden;
}

[data-twb-extra].twb-x-sticky-fixed {
  box-sizing: border-box;
  margin: 0 !important;
  will-change: left, width;
}

/* Smart Sticky không animate wrapper khi đổi flow -> fixed. Việc đổi geometry
 * phải tức thời và ổn định; Sticky State bên dưới chỉ transition các thuộc tính
 * thị giác (màu/icon/background), tránh jank và tránh replay khi resize/orientation. */

/* Elementor editor giữ Normal state tuyệt đối. JS chỉ gắn marker class
 * .twb-x-sticky-editor-preview để lifecycle nhận diện, nhưng CSS không thay
 * position/background/typography của element đang chỉnh. */

.twb-x-sticky-placeholder {
  min-height: 1px;
  pointer-events: none;
  visibility: hidden;
}

[data-twb-extra].twb-x-sticky-effect-shadow.twb-x-stuck {
  box-shadow: 0 12px 34px rgba(15, 23, 42, 0.14);
}

[data-twb-extra].twb-x-sticky--bottom.twb-x-sticky-effect-shadow.twb-x-stuck {
  box-shadow: 0 -12px 34px rgba(15, 23, 42, 0.14);
}

[data-twb-extra].twb-x-sticky-effect-glass.twb-x-stuck {
  background-color: rgba(255, 255, 255, 0.82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.10);
}

[data-twb-extra].twb-x-sticky-effect-border.twb-x-stuck {
  box-shadow: inset 0 -1px 0 rgba(15, 23, 42, 0.12);
}

[data-twb-extra].twb-x-sticky--bottom.twb-x-sticky-effect-border.twb-x-stuck {
  box-shadow: inset 0 1px 0 rgba(15, 23, 42, 0.12);
}

/* ─── STICKY STATE SYSTEM ──────────────────────────────────────────────────
 * Opt-in only. Elementor controls set CSS variables on the sticky wrapper;
 * undefined variables produce invalid declarations, so Normal styles remain
 * untouched unless the user explicitly chooses an override.
 * ─────────────────────────────────────────────────────────────────────────── */
[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-bg.twb-x-stuck {
  background-color: var(--twb-sticky-state-bg) !important;
  /* Background Sticky là một state độc lập: nếu Normal dùng image/gradient,
   * layer đó phải được loại bỏ thay vì nằm trên màu Sticky. */
  background-image: none !important;
}

/* Elementor background overlay là một layer riêng với background của wrapper.
 * Khi người dùng đã chọn Background khi Sticky, tắt overlay Normal để state
 * Sticky thực sự độc lập thay vì tiếp tục pha gradient/image cũ. */
[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-bg.twb-x-stuck > .elementor-background-overlay {
  opacity: 0 !important;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-text.twb-x-stuck {
  color: var(--twb-sticky-state-text) !important;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-text.twb-x-stuck :where(
  h1, h2, h3, h4, h5, h6, p, small, strong, em,
  .elementor-heading-title,
  .elementor-widget-text-editor,
  .elementor-icon-list-text,
  .twb-oc-trigger-text,
  .twb-overlay-trigger-label,
  .twb-wc-mini-cart__text,
  .twb-wc-mini-cart__subtotal
):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *) {
  color: var(--twb-sticky-state-text) !important;
  transition: color var(--twb-sticky-state-duration, 220ms) ease;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-link.twb-x-stuck a:not(.elementor-button):not(.elementor-social-icon):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *) {
  color: var(--twb-sticky-state-link) !important;
  fill: var(--twb-sticky-state-link) !important;
  transition:
    color var(--twb-sticky-state-duration, 220ms) ease,
    fill var(--twb-sticky-state-duration, 220ms) ease;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-link-hover.twb-x-stuck a:not(.elementor-button):not(.elementor-social-icon):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *):hover,
[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-link-hover.twb-x-stuck a:not(.elementor-button):not(.elementor-social-icon):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *):focus-visible {
  color: var(--twb-sticky-state-link-hover) !important;
  fill: var(--twb-sticky-state-link-hover) !important;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-icon.twb-x-stuck :where(
  .elementor-icon,
  .elementor-icon-list-icon,
  .elementor-button-icon,
  .twb-nav-toggle,
  .twb-submenu-indicator,
  .twb-oc-trigger > i,
  .twb-oc-trigger > svg,
  .twb-search-icon-inner,
  .twb-overlay-trigger,
  .twb-search-clear,
  .twb-search-btn .twb-btn-icon,
  .twb-wc-mini-cart__icon,
  .twb-btn-icon
):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *) {
  color: var(--twb-sticky-state-icon) !important;
  fill: var(--twb-sticky-state-icon) !important;
  border-color: var(--twb-sticky-state-icon) !important;
  transition:
    color var(--twb-sticky-state-duration, 220ms) ease,
    fill var(--twb-sticky-state-duration, 220ms) ease,
    border-color var(--twb-sticky-state-duration, 220ms) ease;
}

[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-icon.twb-x-stuck :where(
  .elementor-icon,
  .elementor-icon-list-icon,
  .elementor-button-icon,
  .twb-nav-toggle,
  .twb-submenu-indicator,
  .twb-oc-trigger > i,
  .twb-oc-trigger > svg,
  .twb-search-icon-inner,
  .twb-overlay-trigger,
  .twb-search-clear,
  .twb-search-btn .twb-btn-icon,
  .twb-wc-mini-cart__icon,
  .twb-btn-icon
):not(.twb-oc-panel *):not(.twb-wc-mini-cart__panel *):not(.twb-search-results *) svg {
  color: var(--twb-sticky-state-icon) !important;
  fill: var(--twb-sticky-state-icon) !important;
}

/* Off-Canvas normal controls set fill directly on svg path. Override the path
 * itself while stuck so the visible icon follows Sticky Icon color too. */
[data-twb-extra].twb-x-sticky-state-enabled.twb-x-sticky-state-has-icon.twb-x-stuck .twb-oc-trigger > svg path {
  fill: var(--twb-sticky-state-icon) !important;
}

@media (prefers-reduced-motion: reduce) {
  [data-twb-extra].twb-x-sticky {
    transition: none !important;
  }

  [data-twb-extra].twb-x-sticky-state-enabled.twb-x-stuck :where(
    h1, h2, h3, h4, h5, h6, p, small, strong, em,
    .elementor-heading-title,
    .elementor-widget-text-editor,
    .elementor-icon-list-text,
    a,
    .elementor-icon,
    .elementor-icon-list-icon,
    .elementor-button-icon,
    .twb-nav-toggle,
    .twb-submenu-indicator,
    .twb-oc-trigger,
    .twb-oc-trigger-text,
    .twb-overlay-trigger,
    .twb-overlay-trigger-label,
    .twb-search-icon-inner,
    .twb-search-clear,
    .twb-search-btn,
    .twb-wc-mini-cart__toggle,
    .twb-wc-mini-cart__text,
    .twb-wc-mini-cart__subtotal,
    .twb-wc-mini-cart__icon,
    .twb-btn-icon
  ) {
    transition: none !important;
  }

}
