/* ===================================================================
   VT DIALOG — hộp thoại + thông báo ngắn DÙNG CHUNG cho toàn hệ thống
   Cặp với wwwroot/js/vt-dialog.js.

   ⚠⚠ TỆP NÀY KHÔNG CÒN VẼ HỘP THOẠI. Từ 23/09/2026 `VTUI` đổi ruột sang
      `DevExpress.ui.dialog.custom` + `DevExpress.ui.notify`, nên khung, nút, hoạt ảnh
      đều do DevExtreme lo. Khối `.vtd-nen` / `.vtd-hop` / `.vtd-nut` / `.vtd-toast`
      (~100 dòng) đã XOÁ vì không thẻ nào trong hệ mang các lớp ấy nữa.

   Việc còn lại của tệp: **ép tương phản đạt WCAG cho nút trong hộp thoại**.

   ⚠⚠ VÌ SAO CẦN — lỗi đã dính và chỉ lộ ra khi đo lại 23/09/2026:
      `vt-dialog.js` vẫn tính màu nền đủ tương phản rồi ghi ra `--vtd-bg-*` / `--vtd-fg-*`,
      NHƯNG hai biến đó chỉ được đọc bởi `.vtd-nut button` — lớp vừa bị xoá. Tức cả cơ chế
      bảo đảm tương phản chạy vào hư không: nút chính của hộp thoại lấy thẳng
      `--dx-color-primary` + chữ trắng, và tỉ lệ tụt về **2.39 ở Fluent Yellow · 2.42 ở
      Green · 4.39 ở Green Grey tối · 4.45 ở Pink** (cần 4.5). Bảng «Đo tương phản» ở
      /Home/UiKit lúc ấy vẫn báo 54/54 đạt vì nó đo đúng mấy lớp `.vtd-*` đã chết —
      số rất thuyết phục nhưng nói về giao diện không còn tồn tại.

   ⚠ CHỈ nhắm `.dx-dialog-button` (nút BÊN TRONG hộp thoại), không nhắm
     `.dx-button-default` nói chung: đổi màu mọi nút chính là đổi diện mạo cả phần mềm —
     hàng trăm màn hình — trong khi vấn đề chỉ nằm ở hộp thoại.
   =================================================================== */

/* ── Tương phản nút trong hộp thoại ────────────────────────────────── */
/* Nền: màu theme đã được vt-dialog.js đẩy đậm/nhạt từng nấc 4% cho tới khi đạt 4,5.
   Chữ: JS chọn trắng hay đen theo bên nào tương phản cao hơn — KHÔNG ép trắng, vì màu
   chính của theme sáng (nhất là vàng) sinh ra để làm điểm nhấn trên nền trắng, không
   phải để làm nền cho chữ trắng. */
.dx-dialog-button.dx-button-default.dx-button-mode-contained {
    background-color: var(--vtd-bg-primary, var(--dx-color-primary));
    border-color:     var(--vtd-bg-primary, var(--dx-color-primary));
}
.dx-dialog-button.dx-button-default.dx-button-mode-contained .dx-button-text,
.dx-dialog-button.dx-button-default.dx-button-mode-contained .dx-icon {
    color: var(--vtd-fg-primary, #fff);
}
.dx-dialog-button.dx-button-danger.dx-button-mode-contained {
    background-color: var(--vtd-bg-danger, var(--dx-color-danger));
    border-color:     var(--vtd-bg-danger, var(--dx-color-danger));
}
.dx-dialog-button.dx-button-danger.dx-button-mode-contained .dx-button-text,
.dx-dialog-button.dx-button-danger.dx-button-mode-contained .dx-icon {
    color: var(--vtd-fg-danger, #fff);
}
/* Hover/focus phải giữ nguyên luật trên, nếu không DevExtreme trả lại màu gốc của theme
   ngay khi rê chuột — nút đạt chuẩn lúc đứng yên rồi tụt chuẩn lúc người dùng chạm vào. */
.dx-dialog-button.dx-button-default.dx-button-mode-contained.dx-state-hover,
.dx-dialog-button.dx-button-default.dx-button-mode-contained.dx-state-focused,
.dx-dialog-button.dx-button-default.dx-button-mode-contained.dx-state-active {
    background-color: color-mix(in srgb, var(--vtd-bg-primary, var(--dx-color-primary)) 88%,
                                var(--vtd-inverse-primary, #000));
    border-color:     color-mix(in srgb, var(--vtd-bg-primary, var(--dx-color-primary)) 88%,
                                var(--vtd-inverse-primary, #000));
}
.dx-dialog-button.dx-button-danger.dx-button-mode-contained.dx-state-hover,
.dx-dialog-button.dx-button-danger.dx-button-mode-contained.dx-state-focused,
.dx-dialog-button.dx-button-danger.dx-button-mode-contained.dx-state-active {
    background-color: color-mix(in srgb, var(--vtd-bg-danger, var(--dx-color-danger)) 88%,
                                var(--vtd-inverse-danger, #000));
    border-color:     color-mix(in srgb, var(--vtd-bg-danger, var(--dx-color-danger)) 88%,
                                var(--vtd-inverse-danger, #000));
}

/* ── Thông báo ngắn phải nổi TRÊN popup ────────────────────────────── */
/* ⚠ GOM TỪ 4 TỆP CSS tự vá cùng một bệnh (`hc-modal`, `sc-modal`, `decision-form`,
   `common-popup` đều khai `z-index: 10100 !important` cho `.dx-toast-wrapper`, còn
   `rq-modal` vá thêm cả vị trí). Popup của hệ đặt z-index tới 9999–10000, cao hơn
   toast mặc định (~1500), nên không có dòng này thì thông báo bị popup che hoàn toàn —
   người dùng bấm Lưu, việc hỏng, mà không thấy báo gì.
   Đặt ở đây một lần: màn hình mới không phải tự phát hiện lại và tự vá lần thứ sáu. */
/* ⚠ PHẢI CAO HƠN MỌI THỨ ĐANG CÓ, không chỉ hơn popup. Thang thật trong hệ (đo
   23/09/2026): modal 9999 · dropdown trong modal 12000 · chatbot 99999 ·
   khung chat AI 1.000.000 · bảng chọn cảm xúc của chat 1.000.010. Đặt 10100 như bốn
   tệp modal từng vá là vẫn bị khung chat che — mà lúc đang chat cũng là lúc cần thấy
   báo lỗi. Thông báo là dải nhỏ tự tắt sau vài giây nên nằm trên cùng không che gì lâu. */
/* ⚠ PHẢI CÓ `!important`: DevExtreme đặt z-index INLINE trên wrapper (đo được 9501)
   và inline luôn thắng CSS thường. Bốn tệp modal cũ khai `!important` là có lý do —
   bỏ đi lúc gom là dòng này im lặng mất tác dụng (đã dính ngay trong lượt gom 23/09,
   bắt được vì đo lại z-index thật chứ không tin là đã sửa xong).
   Đánh đổi: popup mở SAU thông báo sẽ nằm dưới nó. Chấp nhận được vì thông báo tự tắt
   sau vài giây, còn thông báo bị che thì mất hẳn. */
.dx-overlay-wrapper.dx-toast-wrapper { z-index: 1000100 !important; }

/* ── Trạng thái ĐANG TẢI / RỖNG (25/09/2026) ───────────────────────── */
/* Cặp với VTUI.showLoading / setButtonBusy / loadingHtml / emptyHtml trong vt-dialog.js và hai
   partial Views/Shared/_VtuiLoading.cshtml, _VtuiEmpty.cshtml (máy chủ vẽ sẵn cùng markup).

   ══ HỢP ĐỒNG THEME ══════════════════════════════════════════════════════════════════════
   THEME MỚI CHỈ CẦN THÊM MỘT KHỐI vào sổ theme wwwroot/css/vtui-theme.css — KHÔNG sửa JS, KHÔNG
   sửa tệp này (bảng biến đầy đủ, cả toast/hộp thoại, ở đầu sổ theme):
       html[data-vt-theme="mã-theme"] { --vtui-text: …; --vtui-accent: …; --vtui-empty-border: …; }
   Biến nào không khai thì dùng giá trị mặc định (cột phải). Mẫu thật: khối Neo và Bamboo
   trong sổ theme wwwroot/css/vtui-theme.css — chúng khai đúng cách một theme mới sẽ khai.

     Biến                     Tác dụng                                  Mặc định
     --vtui-text              màu chữ của khối (chữ phụ tự pha nhạt)    --dx-color-text của theme DevExtreme
     --vtui-accent            màu vòng xoay                             màu chính theme, JS tự ép đủ tương phản
     --vtui-spinner-size      cỡ vòng xoay ở khối đang tải              1.6em
     --vtui-spinner-width     độ dày nét vòng xoay                      .16em
     --vtui-spinner-speed     thời gian quay một vòng                   .8s
     --vtui-spinner-track     màu phần vòng mờ                          accent pha 22%
     --vtui-font-size         cỡ chữ của khối                           13px
     --vtui-empty-padding     đệm khối rỗng                             28px 16px
     --vtui-empty-gap         khoảng cách icon ↔ chữ                    8px
     --vtui-empty-bg          nền khối rỗng                             trong suốt
     --vtui-empty-border      viền khối rỗng                            không
     --vtui-empty-radius      bo góc khối rỗng                          0
     --vtui-empty-margin      lề ngoài khối rỗng                        0
     --vtui-empty-icon-size   cỡ icon khối rỗng                         32px (bản gọn 20px)
     --vtui-empty-icon-color  màu icon                                  chữ pha 58%
     --vtui-error / --vtui-error-bg   chữ+icon / nền của khối LỖI (emptyHtml tone:'error')
                                          màu đỏ theme đẩy ≥ 4,5 / như khối rỗng
     --vtui-empty-hint-color  màu dòng gợi ý                            chữ pha 74%
     --vtui-veil              màu màn phủ của VTUI.showLoading          màu .content-loading-overlay của theme

   ĐỔI HÌNH, không chỉ màu (cũng chỉ bằng CSS của theme):
   · ICON MẶC ĐỊNH của khối rỗng (khi nơi gọi không truyền icon) mang lớp .vtui-empty-icon--default:
         html.theme-xxx .vtui-empty-icon--default::before { content: "\f07c"; font-family: "Tên font"; }
     hoặc dùng ảnh:  html.theme-xxx .vtui-empty-icon--default::before { content: ""; }
                     html.theme-xxx .vtui-empty-icon--default { width: 40px; height: 40px;
                         background: url(/img/theme-xxx/empty.svg) center / contain no-repeat; }
     ⚠ Đừng viết cứng mã glyph của DevExtreme ở đây: mã «box» khác nhau giữa các bản theme dx.
     Icon do nơi gọi truyền riêng (vd 'fas fa-bug') mang ý nghĩa nghiệp vụ nên KHÔNG bị đổi theo theme.
   · HÌNH VÒNG XOAY:  html.theme-xxx .vtui-loading .vtui-spinner { border: 0;
                         background: url(/img/theme-xxx/spinner.svg) center / contain no-repeat; }
     (animation vtui-spin vẫn quay ảnh). Vòng xoay trong NÚT bận (.vtui-spinner--inline) cố ý giữ
     màu chữ của nút — đừng đè nó bằng ảnh màu cố định, nút chính sẽ mất vòng xoay.
   · HỘP của lớp phủ showLoading là dxLoadPanel — tô bằng .dx-loadpanel-content như theme vẫn tô
     DevExtreme (Neo/Bamboo đã làm vậy).
   Thêm theme xong: mở /Home/UiKit#trang-thai ở theme đó rồi bấm «Đo tương phản» ở mục Theme & màu.

   ⚠ BIẾN ĐỌC Ở CHỖ DÙNG, KHÔNG KHAI LẠI TRÊN PHẦN TỬ. Bản đầu khai --vtui-text ngay trên
     .vtui-empty nên theme khai ở cấp html KHÔNG đè được (khai trên phần tử luôn thắng giá trị
     thừa kế). Nay mọi quy tắc đọc var(--vtui-x, mặc định).
   ⚠ Chữ mờ pha với `transparent`, KHÔNG pha với màu nền: khối này nằm trên đủ loại nền (thẻ,
     popup, lưới, nền trang Neo #FFF8F0…), pha alpha thì chữ tự hoà lên đúng nền dưới nó. */

/* Khối biến của TỪNG theme (Neo, Bamboo, Fluent…) nằm ở SỔ THEME wwwroot/css/vtui-theme.css —
   mỗi theme một khối riêng. Tệp này chỉ giữ QUY TẮC đọc biến, không giữ giá trị của theme nào. */

/* Màu dùng nội bộ, tính từ biến của theme (tên có gạch dưới = riêng, theme đừng khai). */
.vtui-loading, .vtui-empty, .vtui-spinner {
    --_vtui-text: var(--vtui-text, var(--dx-color-text, var(--ink, #242424)));
    /* --vtui-accent-safe do vt-dialog.js tính: màu chính đẩy đậm tới ≥ 3,2 trên nền theme. */
    --_vtui-accent: var(--vtui-accent, var(--vtui-accent-safe, var(--dx-color-primary, var(--navy, #0f6cbd))));
}

/* Vòng xoay: một vòng tròn khuyết, vẽ bằng viền — không ảnh, không font icon. */
.vtui-spinner {
    display: inline-block; flex: none; box-sizing: border-box;
    width: 1.25em; height: 1.25em; border-radius: 50%;
    border: var(--vtui-spinner-width, .16em) solid var(--vtui-spinner-track, color-mix(in srgb, var(--_vtui-accent) 22%, transparent));
    border-top-color: var(--_vtui-accent);
    animation: vtui-spin var(--vtui-spinner-speed, .8s) linear infinite;
    vertical-align: -.2em;
}
/* Trong NÚT: màu chữ của chính nút. ⚠ Đừng dùng màu chính của theme ở đây — nút chính có nền
   màu chính, vòng xoay cùng màu nền thì biến mất (đúng lý do không dùng dxLoadIndicator). */
.vtui-spinner--inline {
    width: 1em; height: 1em; border-width: .14em; margin-right: .45em; vertical-align: -.14em;
    border-color: color-mix(in srgb, currentColor 28%, transparent);
    border-top-color: currentColor;
}
.vtui-spinner--alone { margin-right: 0; }   /* nút chỉ có icon: không lệch sang trái */
@keyframes vtui-spin { to { transform: rotate(360deg); } }

.vtui-loading {
    display: flex; align-items: center; justify-content: center; gap: .6em;
    padding: 24px 16px; font-size: var(--vtui-font-size, 13px);
    color: color-mix(in srgb, var(--_vtui-text) 80%, transparent);
}
.vtui-loading .vtui-spinner { width: var(--vtui-spinner-size, 1.6em); height: var(--vtui-spinner-size, 1.6em); }
.vtui-loading--inline { display: inline-flex; padding: 0; gap: .4em; font-size: inherit; vertical-align: middle; }
.vtui-loading--inline .vtui-spinner { width: 1em; height: 1em; border-width: .14em; }

.vtui-empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: var(--vtui-empty-gap, 8px); padding: var(--vtui-empty-padding, 28px 16px);
    margin: var(--vtui-empty-margin, 0);
    background: var(--vtui-empty-bg, transparent);
    border: var(--vtui-empty-border, none); border-radius: var(--vtui-empty-radius, 0);
    text-align: center; font-size: var(--vtui-font-size, 13px);
    color: var(--_vtui-text);
}
/* 58%: biểu tượng chỉ để trang trí (aria-hidden) nhưng vẫn giữ ≥ 3:1 trên mọi theme — 50% chỉ
   được 2,9 ở Bamboo sáng (đo 25/09/2026). */
.vtui-empty-icon {
    font-size: var(--vtui-empty-icon-size, 32px); line-height: 1;
    color: var(--vtui-empty-icon-color, color-mix(in srgb, var(--_vtui-text) 58%, transparent));
}
/* Icon DevExtreme tự đặt cỡ 18px — ép lại theo cỡ của khối. */
.vtui-empty-icon.dx-icon { width: auto; height: auto; font-size: var(--vtui-empty-icon-size, 32px); }
.vtui-empty-text { font-weight: 600; }
/* Liên kết trong khối rỗng («Nhấn Thêm…»): màu CHỮ của khối + gạch chân, KHÔNG màu nhấn — màu
   nhấn chỉ bảo đảm 3,2 (đủ cho vòng xoay, thiếu cho chữ 13px); link xanh mặc định của Bootstrap
   đo được 3,06 ở theme tối (Firefox 25/09/2026). Theme muốn khác thì khai --vtui-empty-link. */
.vtui-empty a { color: var(--vtui-empty-link, inherit); text-decoration: underline; cursor: pointer; }
.vtui-empty-hint { margin-top: 2px; color: var(--vtui-empty-hint-color, color-mix(in srgb, var(--_vtui-text) 74%, transparent)); }
/* Bản gọn: nằm ngang, cho ô nhỏ (thẻ dashboard, dòng trong danh sách, panel hẹp). Cố ý KHÔNG
   nhận viền/nền/lề của theme: nó là một dòng ghi chú trong khung khác, đóng khung thêm là thừa. */
.vtui-empty--compact {
    flex-direction: row; gap: 10px; padding: 12px; text-align: left;
    margin: 0; border: 0; border-radius: 0; background: none;
}
.vtui-empty--compact .vtui-empty-icon,
.vtui-empty--compact .vtui-empty-icon.dx-icon { font-size: 20px; }

/* Bản TRONG DÒNG (emptyHtml inline:true) — chữ giữ chỗ trong ô/trường: không khung, không lề, kế thừa
   cỡ chữ; màu = màu dòng gợi ý (đo ≥ 5,7 trên 10 theme) vì «Chưa cấu hình» vẫn là chữ phải đọc được. */
.vtui-empty--inline {
    display: inline; padding: 0; margin: 0; gap: 0; border: 0; border-radius: 0; background: none;
    text-align: inherit; font-size: inherit; font-weight: inherit;
    color: var(--vtui-empty-hint-color, color-mix(in srgb, var(--_vtui-text) 74%, transparent));
}
.vtui-empty--inline.vtui-empty--error { color: var(--_vtui-error); background: none; }

/* Biến thể LỖI của CÙNG khối (emptyHtml tone:'error') — chỉ đổi màu chữ/icon (+ nền nếu theme khai),
   bố cục, cỡ, bản gọn giữ nguyên. Màu: --vtui-error của theme, không có thì màu đỏ của theme đã được
   vt-dialog.js đẩy tới ≥ 4,5 (--vtui-danger-safe). */
.vtui-empty--error {
    --_vtui-error: var(--vtui-error, var(--vtui-danger-safe, var(--dx-color-danger, #c50f1f)));
    background: var(--vtui-error-bg, var(--vtui-empty-bg, transparent));
}
.vtui-empty--error .vtui-empty-text,
.vtui-empty--error .vtui-empty-icon { color: var(--_vtui-error); }
.vtui-empty--error.vtui-empty--compact { background: var(--vtui-error-bg, none); }

/* Nút đang bận: ẩn icon cũ (vòng xoay đứng vào chỗ đó), chặn bấm cả với thẻ <a>. */
.vtui-busy > i, .vtui-busy > .fa, .vtui-busy > .fas, .vtui-busy > .far, .vtui-busy > svg { display: none; }
/* Chặn chuột. ⚠ KHÔNG hạ opacity: nút bận phải đọc được chữ «Đang lưu…» — lý do setButtonBusy
   không dùng `disabled` (kiểu vô hiệu tô chữ xám trên nền xám, đo 25/09/2026 còn 1,29–1,65). */
.vtui-busy[aria-disabled="true"] { pointer-events: none; cursor: progress; }
.vtui-busy { cursor: progress; }

/* Lớp phủ khung: nằm TRÊN nội dung khung (lưới có thanh cuộn z-index riêng) nhưng DƯỚI popup
   mở sau — nên không đặt z-index cao kiểu thông báo. Lớp phủ cả trang thì để DevExtreme lo. */
.vtui-loading-host { position: absolute; }
/* Lớp phủ chuyển trang SPA (site.js): khối đang tải to hơn một nấc cho vừa cả vùng nội dung. */
.content-loading-overlay > .vtui-loading { font-size: 15px; }

/* ── Giảm chuyển động ──────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .dx-toast-wrapper .dx-overlay-content,
    .dx-dialog-wrapper .dx-overlay-content { animation: none !important; transition: none !important; }
    /* ⚠ QUAY CHẬM, KHÔNG DỪNG: vòng tải đứng im là người dùng tưởng app treo (đúng luật đã chốt
       ở theme-bamboo.css). Người bật «giảm chuyển động» cần ít chuyển động, không phải mất tín hiệu. */
    .vtui-spinner { animation-duration: calc(var(--vtui-spinner-speed, .8s) * 3); }
}
