/* nxsv-css */

.nxsv {
    display: grid;
    grid-template-columns: repeat(var(--nxsv-cols, 4), minmax(0, 1fr));
    gap: var(--nxsv-gap, 16px);
    /* Ô hẹp hơn cột thì căn theo lựa chọn, mặc định giữa cột */
    justify-items: var(--nxsv-just, center);
}

.nxsv-item {
    display: block;
    width: 100%;
    /* Bề ngang riêng cho mỗi ô; bỏ trống thì vừa hết cột */
    max-width: var(--nxsv-iw, 100%);
    min-height: 60px;   /* nhìn thấy được ngay cả khi ô chưa có ảnh */
    position: relative;
    border-radius: 12px;
    overflow: hidden;
    background: #F6F5F3;
    text-decoration: none;
    /* Nhấc nhẹ khi rê chuột — đủ để biết bấm được, không giật cả trang */
    transition: transform .3s ease, box-shadow .3s ease, opacity .3s ease, filter .3s ease;
    box-shadow: 0 1px 3px rgba(35, 27, 21, .08);
}
.nxsv-h-lift .nxsv-item:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 28px rgba(35, 27, 21, .16);
}

/*
 * Kiểu "phóng ô đang trỏ, thu nhỏ ô bên cạnh".
 *
 * Dùng transform chứ không đổi chiều rộng hay số cột: transform vẽ lại ô mà KHÔNG tính
 * lại bố cục, nên các ô khác đứng yên tại chỗ và hàng không bị xô lệch. Đổi chiều rộng
 * thật thì cả lưới nhảy theo, và với 4 cột thì ô cuối dễ bị đẩy xuống hàng dưới.
 *
 * Tỉ lệ chọn 1.06 và 0.94 — đủ thấy rõ mà tổng bề ngang vẫn nằm trong khoảng trống sẵn có,
 * nên ô phóng to không đè lên ô bên cạnh.
 */
@media (min-width: 850px) and (hover: hover) {
    .nxsv-h-focus:hover .nxsv-item {
        transform: scale(.94);
        opacity: .72;
        filter: saturate(.75);
    }

    .nxsv-h-focus .nxsv-item:hover {
        transform: scale(1.06);
        opacity: 1;
        filter: none;
        z-index: 2;
        box-shadow: 0 16px 34px rgba(35, 27, 21, .2);
    }
}

/*
 * Kiểu "nở rộng": ô đang trỏ ăn thêm chỗ, các ô bên cạnh hẹp lại nhường.
 *
 * Khác kiểu "phóng nhẹ" ở chỗ đây là bố cục THẬT co giãn, không phải phóng hình. Lưới đổi
 * sang flex và mỗi ô dùng flex: nhường chỗ cho nhau, nên tổng bề ngang luôn đúng bằng hàng —
 * không ô nào tràn ra ngoài hay đè lên ô bên cạnh dù phóng bao nhiêu.
 *
 * Tỉ lệ 1.2 và 0.93: với bốn ô, ô đang trỏ chiếm 30% hàng thay vì 25% — rộng hơn đúng 20%.
 * Đủ để thấy rõ ô nào đang được trỏ mà hàng vẫn giữ nhịp đều, ba ô kia chỉ hẹp lại 7%.
 *
 * Bản trước để 1.6 và 0.8 cho ra 40%, nhìn như hàng bị vỡ nhịp mỗi lần rê chuột.
 *
 * Chỉ đổi flex chứ không đổi chiều cao: giữ nguyên chiều cao thì hàng không xô đẩy phần
 * nội dung bên dưới, thứ gây khó chịu nhất khi rê chuột qua lại.
 */
@media (min-width: 850px) and (hover: hover) {
    /*
     * Hiệu ứng dùng transform, KHÔNG đụng vào bố cục.
     *
     * Bản trước đổi khối sang flex rồi co giãn bề ngang thật — bố cục thay đổi theo từng
     * cú rê chuột nên ô nhảy chỗ, và số cột bị nuốt mất. transform chỉ vẽ lại ô tại chỗ:
     * lưới đứng yên, ô nào cũng giữ nguyên vị trí gốc.
     *
     * transform-origin để giữa nên ô thu nhỏ co về TÂM của chính nó, không lệch trên dưới.
     */
    /*
     * Chừa chỗ quanh khối để ô phóng to không bị cắt.
     *
     * Ô phóng 1.25 lần thì tràn ra ngoài ô lưới của nó; hàng hoặc mục bao ngoài thường đặt
     * overflow ẩn nên phần tràn bị cắt cụt. Cho khối này overflow hiện và chừa sẵn lề trong
     * đủ rộng thì phần tràn luôn nằm trong vùng thấy được.
     *
     * Lề âm ở ngoài bù lại đúng bằng lề trong, nên khối vẫn rộng đúng như cũ, không xê dịch
     * so với các phần khác của trang.
     */
    /*
     * Chừa lề vừa phải, và cho ô ở hai mép nở VÀO TRONG.
     *
     * Chừa lề rồi kéo lề âm ra ngoài vẫn bị cắt, vì hàng bao ngoài đặt ẩn phần tràn — lề âm
     * đẩy khối ra đúng vùng bị cắt đó. Nên giảm mức phóng và đổi điểm neo của ô đầu và ô
     * cuối: ô đầu nở sang phải, ô cuối nở sang trái, không ô nào vượt mép khối.
     */
    .nxsv-h-expand { overflow: visible; }

    .nxsv-h-expand .nxsv-item {
        transform-origin: center center;
        transition: transform .35s ease, opacity .35s ease, box-shadow .35s ease;
    }

    /* Rê vào khối: mọi ô thu nhỏ về tâm và mờ nhẹ */
    .nxsv-h-expand:hover .nxsv-item {
        /*
         * Thu mạnh tay: 0.7 thay vì 0.8.
         *
         * 0.8 gần như không thấy khác biệt khi ô vốn đã rộng, nên ba ô nhìn vẫn to ngang
         * nhau và bố cục không có trọng tâm.
         */
        transform: scale(.7);
        opacity: .8;
    }

    /* Ô đang trỏ: phóng to, nổi lên trên các ô khác */
    /* Ô thu nhỏ nằm dưới, ô đang phóng nằm trên — tránh viền chồng lên nhau */
    .nxsv-h-expand:hover .nxsv-item { z-index: 1; }

    .nxsv-h-expand .nxsv-item:hover {
        transform: scale(1.15);
        opacity: 1;
        z-index: 3;
        box-shadow: 0 14px 30px rgba(35, 27, 21, .22);
    }

    /*
     * Các ô ĐỨNG SAU ô đang trỏ: thu nhỏ rồi dịch sang PHẢI, nhường chỗ cho ô phóng to.
     */
    .nxsv-h-expand .nxsv-item:hover ~ .nxsv-item {
        /*
         * translateX đặt TRƯỚC scale.
         *
         * Trình duyệt áp dụng từ phải sang trái, nên "scale(.8) translateX(26px)" là thu nhỏ
         * rồi mới dịch trong hệ toạ độ đã thu — 26px thành 20,8px. Đảo lại thì dịch đúng
         * 26px như đã đặt.
         */
        transform: translateX(44px) scale(.7);
    }

    /*
     * Các ô ĐỨNG TRƯỚC ô đang trỏ: dịch sang TRÁI.
     *
     * CSS không có cách chọn "anh em phía trước", nên dùng :has() — trình duyệt hiện nay
     * đều hiểu. Trình duyệt quá cũ không hiểu thì ô vẫn thu nhỏ, chỉ không dịch ngang;
     * hỏng nhẹ chứ không vỡ gì.
     */
    .nxsv-h-expand .nxsv-item:has(~ .nxsv-item:hover) {
        transform: translateX(-44px) scale(.7);
    }

    /*
     * Ô đầu hàng nở sang PHẢI, ô cuối hàng nở sang TRÁI.
     *
     * Neo ở giữa thì ô sát mép nở đều hai bên và nửa bên ngoài rơi ra ngoài khối — đúng chỗ
     * bị hàng bao ngoài cắt. Đổi điểm neo về phía mép thì toàn bộ phần nở nằm trong khối.
     */
    .nxsv-h-expand .nxsv-item:first-child:hover  { transform-origin: left center; }
    .nxsv-h-expand .nxsv-item:last-child:hover   { transform-origin: right center; }

    /* Tên ở ô bị thu nhỏ dễ bị cắt, cho nó xuống dòng thay vì mất chữ */
    .nxsv-h-expand .nxsv-name { white-space: normal; }
}

/* Trên điện thoại và máy không có chuột thì mọi ô giữ nguyên */
@media (max-width: 849px), (hover: none) {
    .nxsv-h-focus .nxsv-item,
    .nxsv-h-expand .nxsv-item { transform: none; opacity: 1; filter: none; }

}

.nxsv-h-none .nxsv-item:hover { transform: none; box-shadow: 0 1px 3px rgba(35, 27, 21, .08); }
.nxsv-nolink { cursor: default; }
.nxsv-nolink { cursor: default; }

/*
 * Viền trắng quanh ảnh.
 *
 * Đặt lề trong cho chính ô, không phải cho khối: ảnh co lại bấy nhiêu và nền trắng của ô
 * lộ ra thành một khung bao quanh. Bo góc ảnh nhỏ hơn bo góc ô một chút cho hai đường cong
 * chạy song song, nếu bằng nhau thì nhìn như hai vòng tròn lệch tâm.
 */
.nxsv-item { padding: var(--nxsv-frame, 0); }
.nxsv-item .nxsv-media { border-radius: calc(12px - var(--nxsv-frame, 0px) / 2); }

.nxsv-media {
    display: block;
    position: relative;
    width: 100%;
    /* Chừa chỗ theo tỉ lệ trước khi ảnh tải xong, để bố cục không nhảy */
    padding-top: var(--nxsv-pt, 100%);
    overflow: hidden;
}
/* Chiều cao cố định: bỏ cách chừa chỗ theo tỉ lệ, đặt thẳng chiều cao */
.nxsv-fixed .nxsv-media {
    padding-top: 0;
    height: var(--nxsv-h, 280px);
}

.nxsv-media .nxsv-img,
.nxsv-media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}
/*
 * Chỉ phóng ảnh bên trong ở kiểu "nhấc nhẹ ô".
 *
 * Ảnh dựng đúng tỉ lệ khung thì bình thường vừa khít. Phóng thêm 6% là nó tràn ra và bị
 * khung cắt mất đầu đuôi — với ảnh chữ như bản đồ quy trình thì mất luôn dòng tiêu đề.
 *
 * Hai kiểu kia đã phóng cả ô rồi, phóng thêm ảnh bên trong chỉ gây cắt chứ không thêm gì.
 */
/*
 * Phóng ảnh bên trong CHỈ khi bật ô tích, không phụ thuộc kiểu hiệu ứng.
 *
 * Bản trước còn chừa cho kiểu "nhấc nhẹ ô" — mà đó lại là kiểu mặc định, nên với ai đang
 * dùng kiểu đó thì ảnh vẫn bị cắt y như cũ. Một công tắc duy nhất, không có ngoại lệ ngầm.
 */
.nxsv-zoom .nxsv-item:hover .nxsv-img { transform: scale(1.06); }
.nxsv-empty {
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, #F2EFEA, #FBFAF8);
    /* Viền đứt cho ô chưa chọn ảnh: nhìn là biết còn thiếu, thay vì tưởng hỏng */
    border: 1px dashed #D2CCC5;
    border-radius: 12px;
}

/* Khối rỗng trong trình dựng trang: vẫn chiếm chỗ để còn bấm vào mà thêm ô */
.nxsv:empty {
    min-height: 120px;
    border: 1px dashed #D2CCC5;
    border-radius: 12px;
}

.nxsv-veil {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(0, 0, 0, .68) 0%, rgba(0, 0, 0, .18) 45%, rgba(0, 0, 0, 0) 70%);
    opacity: 1;
    transition: opacity .25s ease;
}

.nxsv-name {
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 12px;
    color: #fff;
    font-weight: var(--nxsv-fw, 600);
    font-size: var(--nxsv-fs, 15px);
    line-height: 1.35;
    text-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}
/* Vạch nhỏ trên tên, dài ra khi rê chuột — chi tiết duy nhất có chuyển động */
.nxsv-name::before {
    content: "";
    display: block;
    /* Vạch to theo cỡ chữ: đặt chữ 28px mà vạch vẫn 22px thì nhìn lệch tỉ lệ */
    width: calc(var(--nxsv-fs, 15px) * 1.5);
    height: 3px;
    margin-bottom: 7px;
    border-radius: 2px;
    background: var(--nxsv-accent, #C67930);
    transition: width .3s ease;
}
.nxsv-item:hover .nxsv-name::before { width: calc(var(--nxsv-fs, 15px) * 3); }

.nxsv-badge {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 2;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--nxsv-accent, #C67930);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.6;
}

/* Kiểu chữ nằm dưới ảnh: bỏ lớp phủ, tên đổi sang màu chữ thường */
.nxsv-below .nxsv-veil { display: none; }
.nxsv-below .nxsv-name {
    position: static;
    padding: 11px 14px 13px;
    color: inherit;
    text-shadow: none;
}
.nxsv-below .nxsv-item { background: #fff; }

@media (max-width: 849px) {
    /*
     * Điện thoại: chuyển sang VUỐT NGANG, không dùng lưới.
     *
     * Lưới với 2 cột và 4 ô thì hai ô sau rơi xuống hàng dưới, trang dài thêm một đoạn mà
     * khách phải cuộn dọc mới thấy. Vuốt ngang thì hai ô đầu chiếm trọn bề ngang, hai ô còn
     * lại nằm ngay cạnh và kéo sang là thấy — giống cách mọi ứng dụng điện thoại đang làm.
     *
     * display:flex đè lên grid-template-columns trong thuộc tính style, nên số cột máy tính
     * không ảnh hưởng gì tới đây.
     */
    .nxsv {
        display: flex !important;
        flex-wrap: nowrap !important;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 2px;
    }
    .nxsv::-webkit-scrollbar { display: none; }

    /*
     * "Hé lộ" ô kế bên: mỗi ô hẹp hơn một chút so với chia đều (chia cho số ô + 0,18), nên mép ô
     * tiếp theo luôn ló ra bên phải — nhìn là biết còn nữa để vuốt. Một ô/màn hình → ô rộng ~85%.
     */
    .nxsv > .nxsv-item {
        flex: 0 0 calc((100% - (var(--nxsv-cols-sm, 2) - 1) * var(--nxsv-gap, 16px)) / (var(--nxsv-cols-sm, 2) + .18));
        max-width: none;
        scroll-snap-align: start;
    }
    .nxsv > .nxsv-item:last-child { scroll-snap-align: end; }

    /* Ô đang xem nổi lên, ô bên cạnh lùi nhẹ & dịu đi — tạo chiều sâu kiểu thẻ sang trọng */
    .nxsv.nxsv-live > .nxsv-item {
        transition: transform .45s cubic-bezier(.2,.8,.2,1), opacity .45s ease, box-shadow .45s ease;
        transform: scale(.94); opacity: .72; transform-origin: center center;
    }
    .nxsv.nxsv-live > .nxsv-item.is-active {
        transform: scale(1); opacity: 1;
        box-shadow: 0 16px 34px rgba(48,35,25,.20), 0 0 0 1px rgba(198,124,60,.45);
    }
    /* Mép phải mờ dần như tấm rèm — tắt khi đã tới ô cuối */
    .nxsv.nxsv-live:not(.is-end) {
        -webkit-mask-image: linear-gradient(90deg, #000 0, #000 84%, rgba(0,0,0,.35) 100%);
                mask-image: linear-gradient(90deg, #000 0, #000 84%, rgba(0,0,0,.35) 100%);
    }
    /* Lần đầu cuộn tới khối: cả dải khẽ trượt sang trái rồi về chỗ — gợi ý "vuốt được" */
    .nxsv.nxsv-nudge > .nxsv-item { animation: nxsvNudge 1.1s cubic-bezier(.3,.7,.3,1) .1s 1; }
    @keyframes nxsvNudge { 0%,100% { translate: 0 0; } 35% { translate: -38px 0; } 60% { translate: 6px 0; } }

    /* Thanh điều hướng dưới khối: số thứ tự · chấm vàng đồng · lời nhắc vuốt */
    .nxsv-nav {
        display: flex; align-items: center; justify-content: center; gap: 12px;
        margin: 14px 2px 0; font-family: inherit;
    }
    .nxsv-count { font-size: 13px; letter-spacing: 1.5px; color: #A1978C; white-space: nowrap; min-width: 58px; }
    .nxsv-count b { font-size: 19px; font-weight: 700; color: #302319; letter-spacing: .5px; }
    .nxsv-count i { display: inline-block; width: 16px; height: 1px; margin: 0 6px 4px; background: #C67C3C; vertical-align: middle; }
    .nxsv-dots { display: flex; align-items: center; gap: 7px; }
    .nxsv-dots button {
        width: 7px; height: 7px; padding: 0 !important; margin: 0 !important; border: 0 !important; border-radius: 99px !important;
        background: rgba(48,35,25,.18) !important; min-height: 0 !important; box-shadow: none !important; cursor: pointer;
        transition: width .35s cubic-bezier(.2,.8,.2,1), background .35s ease;
    }
    .nxsv-dots button.is-on { width: 26px; background: linear-gradient(90deg, #B06D33, #DDA26E 60%, #C67C3C) !important; }
    .nxsv-hint {
        display: inline-flex; align-items: center; gap: 6px; min-width: 58px; justify-content: flex-end;
        font-size: 11.5px; letter-spacing: 1.6px; text-transform: uppercase; color: #B06D33; white-space: nowrap;
        transition: opacity .4s ease;
    }
    .nxsv-hint svg { width: 22px; height: 12px; }
    .nxsv-hint svg path { animation: nxsvChev 1.4s ease-in-out infinite; }
    .nxsv-hint svg path:nth-child(2) { animation-delay: .18s; }
    .nxsv-hint svg path:nth-child(3) { animation-delay: .36s; }
    @keyframes nxsvChev { 0%,100% { opacity: .2; } 50% { opacity: 1; } }
    .nxsv-nav.is-touched .nxsv-hint { opacity: 0; }
    .nxsv.nxsv-live { padding: 8px 0 24px !important; margin-bottom: -10px; }
    /* Giảm còn 88% cỡ đã đặt, thay vì ép về một con số cứng làm hỏng lựa chọn của bạn */
    .nxsv-name { font-size: calc(var(--nxsv-fs, 15px) * .88); left: 10px; right: 10px; bottom: 9px; }

    /*
     * Chiều cao cố định trên điện thoại giảm còn 70%.
     *
     * Ô hẹp lại theo màn hình nhưng chiều cao pixel thì không, nên giữ nguyên số sẽ ra
     * những ô cao lêu nghêu. 70% giữ được tỉ lệ nhìn gần với bản máy tính.
     */
    .nxsv-fixed .nxsv-media { height: calc(var(--nxsv-h, 280px) * .7); }
}

@media (min-width: 850px) { .nxsv-nav { display: none !important; } }

/* Tôn trọng cài đặt giảm chuyển động của hệ điều hành */
@media (prefers-reduced-motion: reduce) {
    .nxsv.nxsv-nudge > .nxsv-item, .nxsv-hint svg path { animation: none !important; }
    .nxsv-item, .nxsv-img, .nxsv-name::before { transition: none; }
    .nxsv-item:hover, .nxsv:hover .nxsv-item { transform: none; opacity: 1; filter: none; }
    .nxsv-item:hover .nxsv-img { transform: none; }
}

