/* ============================================================
   DXMN Clothing — Motion Effects Pack
   Vanilla port ของ ReactBits (ไม่มี dependency, ไม่ต้อง build)
   ใช้คู่กับ assets/js/effects.js
   ------------------------------------------------------------
   1  (ว่าง — SpotlightCard ถอดออกแล้ว)
   2  (ว่าง — TiltedCard ถอดออกแล้ว)
   3  (ว่าง — GlareHover ถอดออกแล้ว)
   4  ShinyText       .fx-shiny
   5  FadeContent     [data-fx-reveal]
   6  AnimatedList    [data-fx-stagger]
   7  (ว่าง — ClickSpark ถอดออกแล้ว)
   8  (ว่าง — Magnet ถอดออกแล้ว)
   9  CountUp         [data-fx-countup] (JS)
   10 GradualBlur     .fx-blur-bottom
   11 Threads         [data-fx-threads] (JS/canvas)
   12 Stepper+        .store-stepper (อัปเกรดของเดิม)
   13 (ว่าง — FoldText ถอดออกแล้ว)
   14 TextReveal      [data-fx-text]
   ============================================================ */

/* 1) SpotlightCard — ถอดออกแล้ว (v1.0.234) ตามที่แจ้งว่าไม่เอาเงาตามเมาส์บนการ์ดสินค้า */

/* 2) TiltedCard — ถอดออกแล้ว (v1.0.202) ตามที่แจ้งว่าไม่เอาการ์ดเอียงตอนเมาส์ชี้ */

/* 3) GlareHover — ถอดออกแล้ว (v1.0.195) ตามที่แจ้งว่าไม่เอาแสงกวาดตอนเมาส์ชี้ */

/* ============================================================
   4) SHINY TEXT — ประกายวิ่งบนป้าย SALE / NEW / ปุ่ม
   ใช้ได้กับ element พื้นเข้มเท่านั้น (.p-tag พื้นดำ)
   ============================================================ */
/* ⚠️ ห้ามใส่ position:relative ที่นี่ — .p-tag เป็น position:absolute อยู่แล้ว
   ถ้าเซ็ตทับจะทำให้ป้ายหลุดออกจากมุมรูป (effects.css โหลดหลัง style.css จึงชนะ)
   host ต้องเป็น element ที่มี position อยู่แล้ว (absolute/relative) */
.fx-shiny { overflow: hidden; isolation: isolate; }
.fx-shiny::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    transform: translateX(-100%);
    background: linear-gradient(
        100deg,
        rgba(255, 255, 255, 0) 25%,
        rgba(255, 255, 255, .62) 50%,
        rgba(255, 255, 255, 0) 75%
    );
    animation: fxShine 3.4s var(--ease) infinite;
}
@keyframes fxShine {
    0%, 55% { transform: translateX(-100%); }
    100%    { transform: translateX(100%); }
}

/* ============================================================
   5) FADE CONTENT / SCROLL REVEAL — เนื้อหาลอยขึ้นตอนสกอลล์
   ============================================================ */
[data-fx-reveal] {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity .75s var(--ease-out), transform .75s var(--ease-out);
}
[data-fx-reveal].is-in {
    opacity: 1;
    transform: none;
}
/* กันหน้าขาวถ้า JS ตาย */
.no-js [data-fx-reveal],
html:not(.fx-ready) [data-fx-reveal] { opacity: 1; transform: none; }

/* ============================================================
   6) ANIMATED LIST — ลูกเข้าทีละตัวแบบ stagger
   ============================================================ */
/* ใช้ animation ไม่ใช่ transition — กัน transition-delay ค้างไปกวนเอฟเฟกต์ hover ทีหลัง */
[data-fx-stagger] > * { opacity: 0; }
[data-fx-stagger].is-in > * {
    animation: fxStaggerIn .6s var(--ease-out) both;
    animation-delay: calc(var(--fx-i, 0) * 55ms);
}
@keyframes fxStaggerIn {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: none; }
}
/* พออนิเมตจบให้ถอด animation ทิ้ง — ไม่งั้น fill-mode:both จะล็อก opacity/transform ไว้
   แล้วไปทับ inline style ที่ JS อื่นเซ็ตทีหลัง (เช่น fade-out การ์ดตอนลบออกจาก Wishlist) */
[data-fx-stagger] > .fx-done {
    animation: none !important;
    opacity: 1;
    transform: none;
}
html:not(.fx-ready) [data-fx-stagger] > * { opacity: 1; }

/* 7) ClickSpark — ถอดออกแล้ว (v1.0.196) ตามที่แจ้งว่าไม่เอาประกายตอนคลิก */

/* 8) Magnet — ถอดออกแล้ว (v1.0.199) ตามที่แจ้งว่าไม่เอาปุ่มขยับตามเมาส์ */

/* ============================================================
   9) COUNT UP — ตัวเลขนับขึ้น (กันเลขเต้นด้วย tabular-nums)
   ============================================================ */
[data-fx-countup] {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}
/* Counter — ป๊อปตอนตัวเลขเปลี่ยน (badge ตะกร้า) */
.fx-num-pop { animation: fxNumPop .42s var(--ease-out); }
@keyframes fxNumPop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.45); }
    100% { transform: scale(1); }
}

/* ============================================================
   10) GRADUAL BLUR — เบลอไล่ระดับที่ขอบ (progressive blur)
   ============================================================ */
.fx-blur-bottom { position: relative; }
.fx-blur-bottom::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 130px;
    z-index: 2;
    pointer-events: none;
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, .55) 45%, transparent 100%);
    mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, .55) 45%, transparent 100%);
}
/* backdrop-filter แพงบนมือถือ — เปิดเฉพาะจอใหญ่ */
@media (max-width: 899px) {
    .fx-blur-bottom::after { display: none; }
}

/* ขอบล่างของกล่องที่สกอลล์ได้ (cart drawer)
   ใช้ mask ไม่ใช่ ::after — เพราะ ::after ในกล่อง overflow:auto จะเลื่อนไปกับเนื้อหา
   mask ผูกกับ border box จึงค้างอยู่ที่ขอบล่างเสมอ */
.fx-blur-scroll {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent 100%);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent 100%);
}

/* ============================================================
   11) THREADS — เส้นบางไหวเป็นคลื่น (canvas 2D)
   ============================================================ */
[data-fx-threads] { position: relative; }
.fx-threads-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.2s var(--ease);
}
.fx-threads-canvas.is-on { opacity: 1; }
/* ดัน content ของ about-strip ขึ้นเหนือ canvas */
[data-fx-threads] > *:not(.fx-threads-canvas) { position: relative; z-index: 1; }

/* ============================================================
   12) STEPPER+ — อัปเกรด .store-stepper เดิมให้มี motion
   ============================================================ */
.store-stepper { counter-reset: fxstep; }
.store-step {
    position: relative;
    overflow: hidden;
    transition: border-color .35s var(--ease), background .35s var(--ease);
}
/* เส้น progress วิ่งจากซ้ายไปขวาในช่องที่ active */
.store-step::before {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 0;
    background: var(--black);
    transition: width .9s var(--ease-out);
}
.store-step.is-done::before { width: 100%; }
.store-step.is-active::before {
    width: 100%;
    animation: fxStepFill 1.1s var(--ease-out) both;
}
@keyframes fxStepFill { from { width: 0; } to { width: 100%; } }

/* วงกลมเลขขั้นตอนของช่อง active — เต้นเบาๆ */
.store-step.is-active span {
    animation: fxStepPulse 2.4s var(--ease) infinite;
}
@keyframes fxStepPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(10, 10, 10, .28); }
    55%      { box-shadow: 0 0 0 7px rgba(10, 10, 10, 0); }
}
/* ติ๊กถูกในช่องที่ผ่านแล้ว */
.store-step.is-done span { position: relative; }
.store-step.is-done span::after {
    content: '\2713';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--black);
    color: var(--white);
    border-radius: inherit;
    font-size: 15px;
    animation: fxStepCheck .45s var(--ease-out) both;
}
@keyframes fxStepCheck {
    from { opacity: 0; transform: scale(.4); }
    to   { opacity: 1; transform: scale(1); }
}

/* ============================================================
   13) CART DRAWER — รายการเข้าทีละชิ้นตอนเปิด (CSS ล้วน)
   ใช้ nth-child แทน JS index เพื่อให้ทำงานกับเนื้อหาที่ AJAX โหลดใหม่
   ============================================================ */
/* gate ด้วย .fx-ready — ถ้า effects.js โหลดไม่ขึ้น รายการจะไม่หายไปเฉยๆ */
.fx-ready .cart-drawer .cart-d-item { opacity: 0; }
.cart-drawer.active .cart-d-item {
    animation: fxDrawerItemIn .5s var(--ease-out) both;
}
.cart-drawer.active .cart-d-item:nth-child(1) { animation-delay: .08s; }
.cart-drawer.active .cart-d-item:nth-child(2) { animation-delay: .14s; }
.cart-drawer.active .cart-d-item:nth-child(3) { animation-delay: .20s; }
.cart-drawer.active .cart-d-item:nth-child(4) { animation-delay: .26s; }
.cart-drawer.active .cart-d-item:nth-child(5) { animation-delay: .32s; }
.cart-drawer.active .cart-d-item:nth-child(6) { animation-delay: .38s; }
.cart-drawer.active .cart-d-item:nth-child(n+7) { animation-delay: .44s; }
@keyframes fxDrawerItemIn {
    from { opacity: 0; transform: translateX(26px); }
    to   { opacity: 1; transform: none; }
}

/* ============================================================
   ACCESSIBILITY — เคารพ prefers-reduced-motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    [data-fx-reveal],
    [data-fx-stagger] > * {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
        animation: none !important;
    }
    .fx-shiny::after,
    .fx-threads-canvas { display: none !important; }
    .store-step::before { animation: none !important; }
    .store-step.is-active span,
    .store-step.is-done span::after,
    .fx-num-pop { animation: none !important; }
    .cart-drawer .cart-d-item { opacity: 1 !important; animation: none !important; }
}


/* ========================================================
   DEPTH CAROUSEL — vanilla port ของ ReactBits DepthCarousel
   การ์ดซ้อนกันในแกน Z (ตัว transform ถูกเซ็ตจาก effects.js ทุกเฟรม)
   ======================================================== */
.dc-root {
    position: relative;
    width: 100%;
    min-height: 460px;
    display: flex;
    align-items: center;
    justify-content: center;
    perspective: 1400px;
    perspective-origin: 50% 50%;
    touch-action: pan-y;
    outline: none;
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
}
.dc-root:active { cursor: grabbing; }
.dc-root:focus-visible {
    outline: 2px solid rgba(0, 0, 0, .45);
    outline-offset: 6px;
}
.is-dark .dc-root:focus-visible { outline-color: rgba(255, 255, 255, .5); }

.dc-stage {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
}

.dc-card {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 300px;
    height: 380px;
    transform: translate(-50%, -50%);
    transform-origin: center center;
    overflow: hidden;
    background: #0b0d12;
    box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .65), 0 8px 20px -10px rgba(0, 0, 0, .5);
    will-change: transform, opacity, filter;
    cursor: pointer;
}
.dc-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    pointer-events: none;
    -webkit-user-drag: none;
}
.dc-card-empty {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, .25);
    font-size: 40px;
}
.dc-tint {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    background: #05060a;
    mix-blend-mode: multiply;
}
.dc-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 40px 18px 16px;
    background: linear-gradient(to top, rgba(0, 0, 0, .8), transparent);
    color: #fff;
    font-family: var(--font-th);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1.5;
    pointer-events: none;
}

.dc-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3000;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, .16);
    border-radius: 999px;
    background: rgba(255, 255, 255, .85);
    backdrop-filter: blur(8px);
    color: #111;
    font-size: 22px;
    cursor: pointer;
    transition: background .2s ease, border-color .2s ease, transform .2s ease;
}
.dc-arrow:hover { background: #fff; border-color: rgba(0, 0, 0, .35); }
.dc-arrow:active { transform: translateY(-50%) scale(.94); }
.dc-arrow.is-prev { left: 12px; }
.dc-arrow.is-next { right: 12px; }
.is-dark .dc-arrow {
    border-color: rgba(255, 255, 255, .18);
    background: rgba(18, 20, 26, .55);
    color: #fff;
}
.is-dark .dc-arrow:hover { background: rgba(28, 31, 40, .9); border-color: rgba(255, 255, 255, .4); }

.dc-dots {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3000;
    display: flex;
    gap: 8px;
    padding: 9px 13px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .55);
    backdrop-filter: blur(6px);
}
.is-dark .dc-dots { background: rgba(14, 16, 22, .45); }
.dc-dot {
    width: 7px;
    height: 7px;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: rgba(0, 0, 0, .28);
    cursor: pointer;
    transition: width .25s ease, background .25s ease;
}
.dc-dot.is-active { width: 22px; background: #111; }
.is-dark .dc-dot { background: rgba(255, 255, 255, .32); }
.is-dark .dc-dot.is-active { background: #fff; }

@media (max-width: 767px) {
    .dc-root { min-height: 400px; }
    .dc-card { width: 230px; height: 300px; }
    .dc-arrow { width: 38px; height: 38px; font-size: 19px; }
    .dc-arrow.is-prev { left: 4px; }
    .dc-arrow.is-next { right: 4px; }
}

@media (prefers-reduced-motion: reduce) {
    .dc-card { will-change: auto; }
    .dc-arrow, .dc-dot { transition: none; }
}

/* 13) FoldText — ถอดออกแล้ว (v1.0.278) ตามที่แจ้งว่าหัวข้อขึ้นซ้ำสองรอบ
   ต้นเหตุคือสำเนาสำหรับตัวอ่านหน้าจอ (.fx-fold-sr) ไม่ถูกซ่อน ข้อความจึงโชว์ทั้งสองชุด */

/* ============================================================
   14) TEXT REVEAL — หัวข้อลอยขึ้นทีละคำ (JS ห่อคำให้ด้วย .fx-text-w)
   ⚠️ ไม่มีการสร้างข้อความชุดที่สอง — CSS นี้หายไปก็แค่ไม่มีอนิเมชัน
      ข้อความยังแสดงครบและไม่ซ้ำ (บทเรียนจาก FoldText v1.0.278)
   ============================================================ */
.fx-text-w {
    /* --fx-w = ลำดับคำ ตั้งมาจาก JS (cap ไว้แล้วไม่ให้หน่วงยาวเกิน) */
    --fx-text-delay: calc(var(--fx-w, 0) * 65ms);
    display: inline-block;
    /* ช่องว่างยังเป็น text node ปกติ การตัดบรรทัดจึงเกิดที่ช่องว่างเหมือนเดิม */
    white-space: pre;
    opacity: 0;
    transform: translateY(.42em);
    transition:
        opacity .8s var(--ease-out) var(--fx-text-delay),
        transform .8s var(--ease-out) var(--fx-text-delay);
}
.fx-text.is-in .fx-text-w { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
    .fx-text-w { opacity: 1 !important; transform: none !important; transition: none !important; }
}
