﻿:root {
    --tvu-primary: #1f4e79;
    --tvu-primary-dark: #163a5a;
    --tvu-accent: #f0a30a;
    --tvu-vang: #fff2cc;
}

body {
    font-family: "Segoe UI", "Inter", system-ui, -apple-system, sans-serif;
    font-size: 0.94rem;
    background: #f5f7fa;
}

.bg-tvu {
    background: linear-gradient(90deg, var(--tvu-primary), var(--tvu-primary-dark));
}

/* Logo trường trên thanh điều hướng.

   Nền TRÒN TRẮNG là bắt buộc, không phải trang trí: logo chính thức màu xanh đậm, mà thanh
   điều hướng cũng xanh đậm (#1f4e79 → #163a5a). Đặt thẳng lên thì hai màu gần nhau tới mức
   logo gần như biến mất. Chip trắng giữ nguyên màu chuẩn của logo mà vẫn đọc được. */
/* Nhắm vào ảnh BÊN TRONG bọc, không nhắm vào một lớp trên chính thẻ img: thẻ img do
   partial _LogoTvu dựng và dùng chung cho cả trang đăng nhập, nơi KHÔNG cần chip trắng
   (nền sáng). Gắn lớp vào partial thì phải truyền thêm tham số chỉ để một chỗ dùng. */
.brand-logo-boc {
    display: inline-flex;
    flex: 0 0 auto;
}

.brand-logo-boc img {
    background: #fff;
    border-radius: 50%;
    padding: 2px;
    /* Ảnh nguồn vuông và logo là hình tròn, nên bo tròn không cắt mất phần nào. */
    object-fit: contain;
}

.brand-chu {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
    min-width: 0;
}

.brand-ten { font-weight: 600; }

/* Tên trường: nhỏ và nhạt hơn tên ứng dụng. Nó trả lời "của ai", còn dòng trên trả lời
   "cái gì" — thứ người dùng cần đọc trước. Hai dòng cùng cỡ thì không dòng nào nổi. */
.brand-truong {
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.01em;
    opacity: 0.82;
}

/* Màn hình hẹp: bỏ dòng tên trường, giữ logo và tên ứng dụng. Thanh điều hướng trên điện
   thoại chỉ còn vài chục pixel bề ngang — nhồi hai dòng vào là cả hai đều bị cắt. */
@media (max-width: 575.98px) {
    .brand-truong { display: none; }
}

.navbar-dark .nav-link.active {
    color: #fff;
    font-weight: 600;
    border-bottom: 2px solid var(--tvu-accent);
}

.card {
    border: 1px solid #e3e8ef;
    border-radius: 0.5rem;
}

.card-header {
    background: #fff;
    border-bottom: 1px solid #e3e8ef;
    font-weight: 600;
}

/* Nhóm 4 cột "công việc dài ngày" — giữ nền vàng như biểu mẫu Excel gốc */
.khoi-dai-ngay {
    background: var(--tvu-vang);
    border: 1px solid #e6d08a;
    border-radius: 0.5rem;
}

.o-dai-ngay {
    background: var(--tvu-vang) !important;
}

.the-so {
    background: #fff;
    border: 1px solid #e3e8ef;
    border-radius: 0.5rem;
    padding: 0.85rem 1rem;
    height: 100%;
}

.the-so .nhan {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #64748b;
}

.the-so .giatri {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--tvu-primary);
    line-height: 1.15;
}

.the-so .phu {
    font-size: 0.8rem;
    color: #64748b;
}

table.bang-gon {
    font-size: 0.88rem;
}

table.bang-gon th {
    background: #eef2f7;
    color: #33445c;
    font-weight: 600;
    vertical-align: middle;
}

tr.dong-xong td {
    background: #e2efda;
}

tr.dong-chua td {
    background: #fce4e4;
}

tr.dong-bo-qua td {
    background: #f1f3f5;
    color: #6c757d;
}

.chip {
    display: inline-block;
    font-size: 0.75rem;
    padding: 0.12rem 0.45rem;
    border-radius: 999px;
    background: #eef2f7;
    color: #33445c;
    white-space: nowrap;
}

.chip-cowork {
    background: #dbeafe;
    color: #1e40af;
}

.chip-chat {
    background: #ede9fe;
    color: #5b21b6;
}

.tien-do-lon {
    height: 1.35rem;
    font-size: 0.8rem;
}

.text-truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bang-cuon {
    overflow-x: auto;
}

.required::after {
    content: " *";
    color: #dc3545;
}

/* Cảnh báo "Cần bổ sung" — mỗi dòng có liên kết tới đúng chỗ cần xử lý */
.danh-sach-canh-bao > li {
    margin-bottom: 0.3rem;
}

.danh-sach-canh-bao > li:last-child {
    margin-bottom: 0;
}

.lien-ket-canh-bao {
    display: inline-block;
    margin-left: 0.35rem;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    color: #8a5a00;
    border-bottom: 1px dashed currentColor;
}

.lien-ket-canh-bao:hover,
.lien-ket-canh-bao:focus {
    color: #5c3c00;
    border-bottom-style: solid;
}

.lien-ket-canh-bao-con {
    color: #7a4f00;
    text-decoration: underline;
    text-decoration-style: dotted;
}

.lien-ket-canh-bao-con:hover,
.lien-ket-canh-bao-con:focus {
    color: #4a3000;
    text-decoration-style: solid;
}

/* Sản phẩm trung gian chép từ ngày trước, đang chờ xác nhận */
.chip-cho-xac-nhan {
    background: #fff3cd;
    color: #8a5a00;
    border: 1px solid #e6d08a;
}

/* Trang chép nhật ký sang ngày mới */
tr.dong-duoc-chon td {
    background: #eaf2fb;
}

tr.dong-lap-lai.dong-duoc-chon td {
    background: #e2eefb;
}


/* ---------- Tài liệu vận hành kết xuất từ Markdown (/Admin/QuyTrinh) ---------- */
.tai-lieu { max-width: 62rem; }
.tai-lieu > *:first-child { margin-top: 0; }
.tai-lieu > *:last-child { margin-bottom: 0; }

.tai-lieu h2 {
    font-size: 1.35rem;
    margin: 2rem 0 .75rem;
    padding-bottom: .35rem;
    border-bottom: 2px solid var(--bs-warning, #ffc107);
}
.tai-lieu h3 { font-size: 1.1rem; margin: 1.5rem 0 .6rem; }
.tai-lieu h4 { font-size: .95rem; margin: 1.15rem 0 .5rem; }

.tai-lieu p, .tai-lieu li { line-height: 1.65; }
.tai-lieu ul, .tai-lieu ol { padding-left: 1.3rem; }

/* Bảng trong tài liệu phải cuộn ngang được, không đẩy cả trang lệch. */
.tai-lieu table {
    display: block;
    overflow-x: auto;
    max-width: 100%;
    width: max-content;
    border-collapse: collapse;
    margin: 0 0 1.1rem;
    font-size: .9rem;
}
.tai-lieu th, .tai-lieu td {
    border: 1px solid var(--bs-border-color, #dee2e6);
    padding: .45rem .7rem;
    text-align: left;
    vertical-align: top;
}
.tai-lieu th { background: var(--bs-tertiary-bg, #f8f9fa); white-space: nowrap; }

.tai-lieu blockquote {
    border-left: 3px solid var(--bs-warning, #ffc107);
    background: var(--bs-tertiary-bg, #f8f9fa);
    margin: 0 0 1.1rem;
    padding: .7rem 1rem;
    border-radius: 0 .375rem .375rem 0;
}
.tai-lieu blockquote > *:last-child { margin-bottom: 0; }

.tai-lieu code {
    background: var(--bs-tertiary-bg, #f1f3f5);
    padding: .1rem .3rem;
    border-radius: .25rem;
    font-size: .87em;
}

/* Khối mã — gồm cả sơ đồ mermaid. Trong app hiển thị dạng mã nguồn sơ đồ;
   bản có hình vẽ nằm ở docs/QUY_TRINH.md và bản sổ tay chia sẻ. */
.tai-lieu pre {
    background: var(--bs-tertiary-bg, #f8f9fa);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: .375rem;
    padding: .8rem 1rem;
    overflow-x: auto;
    font-size: .82rem;
    margin: 0 0 1.1rem;
}
.tai-lieu pre code { background: none; padding: 0; }

.tai-lieu hr { margin: 2rem 0; opacity: .25; }

/* Sơ đồ mermaid trong tài liệu: căn giữa, cuộn ngang khi hẹp. */
.tai-lieu pre.mermaid {
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--bs-border-color, #dee2e6);
    text-align: center;
    padding: 1rem;
    /* Trước khi vẽ xong, giữ nguyên dạng mã cho khỏi nhấp nháy bố cục. */
    font-size: .8rem;
    line-height: 1.5;
}
/* Giữ cỡ thật của sơ đồ; khung <pre> đã có overflow-x: auto nên cuộn ngang được. */
.tai-lieu pre.mermaid svg { max-width: none; height: auto; }
/* Sau khi vẽ xong, thẻ pre chỉ còn chứa SVG — trả về phông thường cho khỏi lệch kiểu chữ. */
.tai-lieu pre.mermaid:has(svg) { font-family: var(--bs-body-font-family, system-ui, sans-serif); }

/* Vẽ hỏng thì quay lại hiển thị mã nguồn sơ đồ, kèm ghi chú. */
.tai-lieu pre.so-do-loi { text-align: left; border-color: var(--bs-warning, #ffc107); }
.tai-lieu pre.so-do-loi::before {
    content: "Không vẽ được sơ đồ — hiển thị mã nguồn:";
    display: block;
    font-family: var(--bs-body-font-family);
    font-size: .8rem;
    color: var(--bs-secondary-color, #6c757d);
    margin-bottom: .5rem;
}


/* ---------- Dải nhắc tải lại khi dữ liệu đổi ở nơi khác ---------- */
.nhac-tai-lai {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    transform: translateX(-50%);
    z-index: 1080;
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    max-width: min(46rem, calc(100vw - 2rem));
    padding: .7rem 1rem;
    border: 1px solid var(--bs-warning, #ffc107);
    border-left: 4px solid var(--bs-warning, #ffc107);
    border-radius: .5rem;
    background: var(--bs-body-bg, #fff);
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .18);
    font-size: .9rem;
    line-height: 1.45;
}
.nhac-tai-lai span { flex: 1 1 18rem; }

@media (prefers-reduced-motion: no-preference) {
    .nhac-tai-lai { animation: nhac-hien .18s ease-out; }
    @keyframes nhac-hien {
        from { opacity: 0; transform: translate(-50%, .5rem); }
        to   { opacity: 1; transform: translate(-50%, 0); }
    }
}

/* ---------- Cửa sổ nhắc lịch checklist ----------
   Góc DƯỚI BÊN PHẢI và KHÔNG tự đóng — chỉ đóng khi người dùng bấm xác nhận.
   Cố ý không dùng toast của Bootstrap: toast có cơ chế tự ẩn, mà lời nhắc tự biến mất
   sau vài giây thì người đang gõ dở không kịp thấy, cảnh báo trễ hạn mất hết tác dụng. */
.nhac-checklist {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1080;
    width: min(24rem, calc(100vw - 2rem));
    background: #fff;
    border: 1px solid #dee2e6;
    border-left: 4px solid #0d6efd;
    border-radius: .5rem;
    box-shadow: 0 .5rem 1.25rem rgba(0, 0, 0, .18);
    padding: .75rem .9rem;
    font-size: .875rem;
}

.nhac-checklist.nhac-tre-han {
    border-left-color: #dc3545;
    background: #fff5f5;
}

.nhac-checklist-dau {
    margin-bottom: .4rem;
}

.nhac-checklist-ds {
    margin: 0 0 .6rem;
    padding-left: 1.1rem;
}

.nhac-checklist-ds li + li {
    margin-top: .3rem;
}

.nhac-checklist-nut {
    display: flex;
    gap: .4rem;
    flex-wrap: wrap;
}

@media (prefers-reduced-motion: no-preference) {
    .nhac-checklist { animation: nhac-hien .18s ease-out; }
}

/* ---------- Lưới lịch trực dạng tháng ---------- */
.lich-truc {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    min-width: 56rem;
}

.lich-truc th {
    background: #f6f8fa;
    border: 1px solid #dee2e6;
    padding: .4rem .5rem;
    font-size: .8rem;
    font-weight: 600;
    text-align: left;
    color: #495057;
}

.lich-truc td {
    border: 1px solid #dee2e6;
    vertical-align: top;
    padding: .35rem .4rem;
    height: 6.5rem;
    font-size: .8rem;
}

.o-dau {
    display: flex;
    align-items: center;
    gap: .3rem;
    margin-bottom: .25rem;
}

.o-ngay { font-weight: 600; }
.o-thang { font-size: .7rem; color: #6c757d; }
.o-nhan { font-size: .65rem; }

/* Ngày lấn sang tháng bên cạnh: vẫn hiện để lưới không lệch cột, nhưng làm mờ. */
.o-ngoai-thang { background: #fbfbfc; }
.o-ngoai-thang .o-ngay { color: #adb5bd; font-weight: 400; }

.o-cuoi-tuan { background: #f3f6fb; }
.o-ngay-le { background: #fdf3f3; }
.o-hom-nay { box-shadow: inset 0 0 0 2px #0d6efd; }
.o-toi-truc { background: #eef6ee; }

/* Ngày nghỉ chưa ai trực — chỗ cần chú ý nhất trên lịch. */
.o-thieu-truc { background: #fff8e6; }

/* Nghỉ phép: ĐỌC TỪ TMS_Core, không sửa được ở đây.
   Vẽ khác hẳn lượt của ứng dụng — viền đứt và màu riêng — để nhìn là biết ngay đây không phải
   thứ bấm vào sửa được. Trông giống lượt bình thường thì người ta sẽ bấm rồi tưởng hỏng. */
.o-nghi-phep {
    border: 1px dashed #c98a94;
    border-left: 3px solid #8f3a46;
    background: #fdf1f2;
    border-radius: .25rem;
    padding: .15rem .35rem;
    margin-bottom: .25rem;
    font-size: .72rem;
    line-height: 1.3;
}

.o-nghi-phep-ten {
    display: block;
    font-weight: 600;
    color: #1f2a35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.o-nghi-phep-loai {
    display: block;
    color: #8f3a46;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.o-le {
    font-size: .7rem;
    color: #b02a37;
    margin-bottom: .2rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.o-luot {
    display: block;
    background: #fff;
    border: 1px solid #dee2e6;
    border-left: 3px solid #0d6efd;
    border-radius: .2rem;
    padding: .12rem .3rem;
    margin-bottom: .2rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color .15s ease, box-shadow .15s ease, border-color .15s ease;
}

.o-luot:hover, .o-luot:focus-visible {
    background-color: #f0f7ff;
    box-shadow: 0 1px 4px rgba(13, 110, 253, .25);
    border-color: #86b7fe;
    outline: none;
}

.o-toi-truc .o-luot { border-left-color: #198754; }

.o-cham {
    display: inline-block;
    width: .4rem;
    height: .4rem;
    border-radius: 50%;
    background: #0d6efd;
    margin-right: .25rem;
    vertical-align: middle;
}

.o-toi-truc .o-cham { background: #198754; }

.o-ca { color: #6c757d; font-size: .7rem; }

.o-thieu { font-size: .7rem; color: #997404; }

/* Khối chú thích cũ dùng ô vuông .mau đã BỎ: nó trông y hệt checkbox chưa tick nên người
   dùng bấm vào và báo là lỗi. Bản thay thế dùng .dai-mau dạng thanh bo tròn, ở cuối tệp. */

/* ---------- Chú thích màu của lịch trực ----------
   Dạng THANH BO TRÒN, không phải ô vuông có viền. Bản trước dùng ô vuông nên trông y hệt
   checkbox chưa tick: người dùng bấm vào mà không có gì xảy ra và báo là lỗi. */
.chu-thich-nhom {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem;
}

.chu-thich-nhan { color: #495057; font-weight: 600; }

.chu-thich {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    color: #6c757d;
}

.dai-mau {
    display: inline-block;
    width: 1.5rem;
    height: .6rem;
    border-radius: 1rem;
    border: 1px solid rgba(0, 0, 0, .12);
}

/* NỘI DUNG cần thực hiện, hiện thẳng trên ô lịch. Cắt một dòng bằng ellipsis: ô lịch tháng
   vốn hẹp, để nội dung dài tự xuống ba bốn dòng thì một ngày đẩy cả hàng cao lên và lưới mất
   nhịp. Toàn văn vẫn có trong tooltip và trong cửa sổ chi tiết. */
.o-noidung {
    display: block;
    font-size: .68rem;
    color: #495057;
    font-style: italic;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ＋ phân trực trên ô ngày. Nhạt khi nghỉ, rõ khi trỏ vào — nó là lối đi phụ, không được hút
   mắt hơn chính nội dung lịch. */
.o-them {
    margin-left: auto;
    padding: 0 .3rem;
    border: 1px solid transparent;
    border-radius: .25rem;
    background: transparent;
    color: #6c757d;
    font-size: .8rem;
    line-height: 1.2;
    cursor: pointer;
}

.o-them:hover,
.o-them:focus-visible {
    color: var(--tvu-primary, #003087);
    border-color: #cfdcf5;
    background: #eef4ff;
}

/* × huỷ lượt: góc trên bên phải của chính chip, chỉ rõ khi trỏ vào ô lịch.
   Hiện thường trực thì mỗi ô lịch có một dấu × đỏ nằm sẵn cạnh chuột — lời mời bấm nhầm.
   Chip đã là position:relative (xem .o-luot), nên nút neo theo chip. */
.o-luot { position: relative; }

.o-huy-nut {
    position: absolute;
    right: .1rem;
    top: .1rem;
    padding: 0 .25rem;
    border: 1px solid transparent;
    border-radius: .25rem;
    background: transparent;
    color: #adb5bd;
    font-size: .8rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .12s;
}

td:hover .o-huy-nut,
.o-huy-nut:focus-visible { opacity: 1; }

.o-huy-nut:hover,
.o-huy-nut:focus-visible {
    color: #b02a37;
    border-color: #f1aeb5;
    background: #fff5f5;
}

/* Khối SỬA lượt trực trong cửa sổ chi tiết (/LichTruc).
   Gấp trong <details> vì cửa sổ này mở ra chủ yếu để XEM số điện thoại — bày sẵn một biểu mẫu
   tám ô mỗi lần bấm vào ô lịch là làm rối đúng việc hay làm nhất. */
.lt-sua > summary { list-style: none; cursor: pointer; }
.lt-sua > summary::-webkit-details-marker { display: none; }
.lt-sua > summary::after { content: " ▾"; }
.lt-sua[open] > summary::after { content: " ▴"; }

.dai-toi { background: #cfe8cf; }
.dai-khong-truc { background: #ded7f2; }
.dai-le { background: #f7d4d4; }
.dai-cuoi-tuan { background: #d7e2f3; }
.dai-thieu { background: #ffe9a8; }
.dai-nghi-phep { background: #fdf1f2; border: 1px dashed #c98a94; }

/* Số điện thoại hiện gọn trong ô lịch. */
.o-dt {
    color: #495057;
    font-size: .7rem;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Lượt HỖ TRỢ trên lịch: viền xám và chữ nhạt hơn, để mắt bắt ngay ai là trực chính. */
.o-luot.o-ho-tro { border-left-color: #adb5bd; }
.o-luot.o-ho-tro .o-cham { background: #adb5bd; }

.o-vaitro {
    display: inline-block;
    font-size: .65rem;
    color: #6c757d;
    background: #f1f3f5;
    border-radius: .2rem;
    padding: 0 .25rem;
}

/* Lượt KHÔNG PHẢI TRỰC (đi họp, đi dạy, hội nghị, công tác): màu khác hẳn trực.
   Nhìn vào lịch phải phân biệt được ngay ai đang GÁC và ai chỉ có mặt ở một buổi khác —
   hai thứ khác nhau cả về trách nhiệm lẫn về tiền. Dùng tím-xám để không lẫn với xanh của
   trực chính, cũng không lẫn với xám của hỗ trợ. */
.o-luot.o-khong-truc { border-left-color: #7c6bb0; }
.o-luot.o-khong-truc .o-cham { background: #7c6bb0; }

.o-loai {
    display: inline-block;
    font-size: .65rem;
    color: #574a86;
    background: #efecf8;
    border: 1px solid #d9d2ee;
    border-radius: .2rem;
    padding: 0 .25rem;
}


/* ============================================================================
   PHÂN CÔNG LỊCH TRỰC  (/Admin/LichTruc)
   ----------------------------------------------------------------------------
   Bản trước là bảng ba cột, cột cuối rộng 26rem chứa nguyên một biểu mẫu kèm ô
   chọn nhiều người cao bốn dòng — LẶP LẠI Ở MỌI HÀNG. Một tháng 18 ngày trực là
   18 ô chọn giống hệt nhau, bảng tràn ra ngoài màn hình và nút "Phân" bị cắt mất.

   Ở đây mỗi ngày là một thẻ trên một dòng: ô ngày bên trái, người trực ở giữa,
   biểu mẫu phân công gấp trong <details> bên phải. Ngày CHƯA có ai trực thì mở
   sẵn — đó đúng là ngày cần làm gì đó.
   ============================================================================ */

.pc-ds {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.pc-ngay {
    border: 1px solid #e3e8ef;
    border-left: 4px solid #ced4da;
    border-radius: .5rem;
    background: #fff;
    padding: .6rem .75rem;
}

/* Ngày nghỉ chưa ai trực: việc cần làm, phải nhìn ra ngay từ đầu danh sách. */
.pc-ngay.pc-thieu {
    border-left-color: #dc3545;
    background: #fff8f8;
}

.pc-ngay.pc-du { border-left-color: #198754; }

/* Ngày làm việc chỉ phân trực khi có việc ngoại lệ — để nhạt, đừng tranh chú ý
   với ngày nghỉ bắt buộc phải có người. */
.pc-ngay.pc-ngay-thuong {
    border-left-color: #dee2e6;
    background: #fbfcfd;
}

.pc-ngay.pc-hom-nay {
    box-shadow: 0 0 0 2px var(--tvu-vang);
}

.pc-dong {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
}

/* Ô ngày: cỡ cố định để các dòng thẳng hàng, mắt lướt dọc được. */
.pc-o-ngay {
    flex: 0 0 5.5rem;
    text-align: center;
    line-height: 1.15;
}

.pc-o-ngay .pc-thu {
    display: block;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #6c757d;
}

.pc-o-ngay .pc-so {
    display: block;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--tvu-primary);
    font-variant-numeric: tabular-nums;
}

.pc-ngay-thuong .pc-o-ngay .pc-so { color: #6c757d; font-weight: 600; }

.pc-nguoi {
    flex: 1 1 18rem;
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    align-items: center;
    min-width: 0;
}

/* Một lượt trực = một viên. Viền trái phân biệt trực chính với hỗ trợ, giống hệt
   cách lịch tháng làm — hai trang nói cùng một ngôn ngữ thị giác. */
.pc-luot {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    background: #f1f5fa;
    border: 1px solid #dde5ef;
    border-left: 3px solid var(--tvu-primary);
    border-radius: .3rem;
    padding: .15rem .3rem .15rem .4rem;
    font-size: .82rem;
    max-width: 100%;
}

.pc-luot.pc-ho-tro { border-left-color: #adb5bd; background: #f8f9fa; }

/* Công tác khác (họp, tập huấn, đi học): viền trái NÉT ĐỨT để phân biệt ngay từ xa với
   lượt trực thật. Người đọc lịch cần thấy ngay ai đang gác và ai chỉ có mặt trên lịch —
   khi có sự cố cuối tuần thì gọi người trực, không gọi người đang ngồi họp. */
.pc-luot.pc-khac {
    border-left-style: dashed;
    border-left-color: #7a6ea8;
    background: #f7f6fb;
}

.pc-luot .pc-vai-khac { background: #6f639e; }

.pc-luot .pc-ten { font-weight: 600; }

/* Tên người là thứ phải đọc được nguyên vẹn; ghi chú dài thì cắt bớt chứ đừng đẩy tên xuống. */
.pc-luot .pc-ten { white-space: nowrap; }
.pc-luot .pc-phu { color: #6c757d; font-size: .75rem; }

.pc-luot .pc-vai {
    font-size: .65rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    /* Nhãn hai chữ "TRỰC CHÍNH" vỡ đôi trên màn hình hẹp trông như lỗi hiển thị. */
    white-space: nowrap;
    color: #fff;
    background: var(--tvu-primary);
    border-radius: .2rem;
    padding: 0 .25rem;
}

.pc-luot.pc-ho-tro .pc-vai { background: #868e96; }

/* Nút huỷ: nhỏ và nhạt cho tới khi rê chuột. Mười tám nút đỏ chói trên một trang
   làm mắt tưởng cả tháng đang có lỗi. */
.pc-huy {
    border: 0;
    background: none;
    color: #adb5bd;
    line-height: 1;
    padding: 0 .15rem;
    border-radius: .2rem;
    font-size: .95rem;
}

.pc-huy:hover, .pc-huy:focus-visible { color: #dc3545; background: #ffe9ec; }

.pc-trong { color: #adb5bd; font-size: .85rem; font-style: italic; }
.pc-thieu-nhan { color: #b02a37; font-size: .85rem; font-weight: 600; }

/* Biểu mẫu phân công, gấp lại khi chưa cần. */
.pc-mo { flex: 0 0 auto; }

.pc-mo > summary {
    list-style: none;
    cursor: pointer;
    /* Chỉ rộng bằng chữ. Không có dòng này thì summary là block: lúc mở, biểu mẫu bên dưới
       kéo cả khối rộng ra và cái nút thành một thanh xanh dài suốt hàng. */
    width: fit-content;
    font-size: .82rem;
    padding: .2rem .6rem;
    border: 1px solid var(--tvu-primary);
    color: var(--tvu-primary);
    border-radius: .3rem;
    white-space: nowrap;
    user-select: none;
}

.pc-mo > summary::-webkit-details-marker { display: none; }
.pc-mo > summary:hover { background: #eef3f9; }
.pc-mo[open] > summary { background: var(--tvu-primary); color: #fff; }

.pc-mo > summary::after { content: " ▾"; }
.pc-mo[open] > summary::after { content: " ▴"; }

.pc-mo[open] { flex: 1 1 100%; }

.pc-form {
    flex: 1 1 100%;
    margin-top: .6rem;
    padding-top: .6rem;
    border-top: 1px dashed #dde5ef;
}

/* Ô chọn người là thứ chiếm chỗ nhất — cho nó hẳn một hàng riêng khi đã mở,
   thay vì bóp vào một cột hẹp như bản cũ. */
.pc-form .pc-chon-nguoi { min-height: 6.5rem; }

/* Nút SỬA của từng lượt trực. Cùng khuôn với .pc-huy: nhỏ và nhạt cho tới khi rê chuột —
   mỗi ngày có thể có ba bốn lượt, mà mỗi lượt hai nút đậm màu thì cả bảng thành nút. */
.pc-sua { flex: 0 0 auto; }

.pc-sua > summary {
    list-style: none;
    cursor: pointer;
    /* fit-content vì cùng lý do như .pc-mo: không có nó thì summary là block và lúc mở,
       biểu mẫu bên dưới kéo cái nút thành một thanh dài suốt hàng. */
    width: fit-content;
    color: #adb5bd;
    line-height: 1;
    padding: .15rem .3rem;
    margin-left: -.15rem;
    border-radius: .2rem;
    font-size: .9rem;
    user-select: none;
}

.pc-sua > summary::-webkit-details-marker { display: none; }

.pc-sua > summary:hover,
.pc-sua > summary:focus-visible { color: var(--tvu-primary); background: #eef3f9; }

/* Mở ra thì chiếm trọn hàng — biểu mẫu sáu ô không nhét vừa cạnh một cái viên tên. */
.pc-sua[open] { flex: 1 1 100%; }
.pc-sua[open] > summary { color: #fff; background: var(--tvu-primary); }

/* ---------- Lưới chấm công BM17 ---------- */

/* Lưới 31 cột ngày + 3 hàng con mỗi người: chữ phải nhỏ và ô phải hẹp, nếu không thì một
   tháng không lọt màn hình và người dùng phải cuộn ngang để đọc một dòng. */
.bcc {
    font-size: .78rem;
    --bcc-o: 1.35rem;
}

.bcc th, .bcc td { padding: .15rem .25rem; vertical-align: middle; }

.bcc thead th {
    background: #f4f7fb;
    font-weight: 600;
    font-size: .7rem;
    text-align: center;
}

.bcc .bcc-stt { width: 2.5rem; }
.bcc .bcc-buoi { width: 1.8rem; font-weight: 600; color: #6c757d; }
.bcc .bcc-cong { width: 4.2rem; }

/* Chiều rộng thừa dồn hết vào cột HỌ VÀ TÊN, không dồn vào cột tiền.

   Bảng Bootstrap rộng 100%, mà phần lớn cột ở đây có bề rộng cố định, nên chỗ dư bị chia
   cho các cột không khoá. Để cột tiền cũng co giãn thì nó phình ra và trông như có một cột
   trống giữa "Làm đêm" và "Thành tiền" — đúng chỗ người xem tưởng là thiếu cột. */
.bcc .bcc-ten { min-width: 11rem; }
.bcc .bcc-tien { width: 7rem; }

.bcc .bcc-ngay {
    width: var(--bcc-o);
    min-width: var(--bcc-o);
    padding: .15rem 0;
}

/* Cột THỨ BẢY, CHỦ NHẬT tô nền — giống hệt cách BM17 giấy tô, nên người quen đọc bản giấy
   nhìn vào là nhận ra ngay. Trước đây tô theo "ngày được chấm công", nên ngày lễ và ngày quản
   trị bật tay cũng bị tô: màn hình và bản in ra hai bức tranh khác nhau, mà đây lại chính là
   màn hình dùng để đối chiếu với bản in. */
.bcc .bcc-ngay-cuoi-tuan { background: #dfe6ef; }

/* Ngày được chấm công mà KHÔNG phải cuối tuần — ngày lễ, hoặc ngày quản trị bật tay. Đánh dấu
   bằng gạch chân chứ không bằng nền: thông tin này vẫn cần, nhưng không được tranh chỗ với
   thứ mà biểu mẫu gốc đang nói. */
.bcc .bcc-ngay-tinh-them { border-bottom: 2px solid var(--tvu-accent); }

.bcc .bcc-o {
    width: var(--bcc-o);
    min-width: var(--bcc-o);
    text-align: center;
    padding: .15rem 0;
    font-weight: 700;
    color: transparent;
}

/* Ô trống của cột cuối tuần: nền nhạt để cả cột đọc thành một dải liền như trên bản in. */
.bcc .bcc-o-cuoi-tuan { background: #eef2f7; }

.bcc .bcc-o-co { background: #e3efe8; color: #1c6b45; }

/* Có dấu mà không ra tiền — ô cần chú ý nhất trên cả lưới. Người trực hôm đó sẽ tìm tên
   mình trong hồ sơ và không thấy, nên nó phải đập vào mắt người lập hồ sơ trước. */
.bcc .bcc-o-loai { background: #fbe9c8; color: #8a5a00; cursor: help; }

.bcc .bcc-cong-so { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Người không vào hồ sơ vẫn hiện, chỉ làm mờ — biến mất lặng lẽ là cách nhanh nhất để không
   ai phát hiện mình xếp lịch sai. */
.bcc .bcc-ngoai { opacity: .55; }

.bcc-nhan-ngoai {
    font-size: .65rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: #8a5a00;
    border: 1px solid #e0c48a;
    border-radius: .2rem;
    padding: 0 .25rem;
    margin-left: .25rem;
}

.bcc-chu { margin-right: 1.2rem; white-space: nowrap; }
.bcc-chu .bcc-o { width: 1.35rem; border: 1px solid #ced4da; border-radius: .15rem; }

/* Chế độ "xem giống bản in": gỡ đúng phần chênh lệch giữa màn hình và BM17 sắp in ra —
   các ô có trực mà không vào hồ sơ, và những người không vào hồ sơ.

   Chỉ giấu HIỂN THỊ, không đổi số liệu: cột cộng giờ và thành tiền vốn đã không tính chúng,
   nên bật hay tắt công tắc này thì tổng vẫn y nguyên. */
.bcc.bcc-giong-ban-in .bcc-o-loai {
    background: transparent;
    color: transparent;
    cursor: default;
}

.bcc.bcc-giong-ban-in .bcc-ngoai { display: none; }

/* Vai trò dưới tên là thông tin cho người QUẢN TRỊ đối chiếu, không có trên biểu mẫu —
   BM15 và BM17 chỉ in họ và tên. Ẩn nốt khi xem giống bản in. */
.bcc.bcc-giong-ban-in .bcc-vai-tro { visibility: hidden; }

/* ---------- Trang cấu hình chấm công ---------- */

/* Ngày không được chấm công: làm mờ để bảng đọc lướt được — mắt lướt qua phần mờ và dừng
   ở phần rõ, đúng những ngày sẽ ra tiền. */
.cc-bang .cc-mo { opacity: .55; }

/* Có người trực mà ngày lại KHÔNG được chấm. Đây là dòng cần chú ý nhất trên cả bảng:
   người trực hôm đó sẽ tìm tên mình trong hồ sơ và không thấy. */
.cc-bang .cc-canh-bao { background: #fff8e6; }
.cc-bang .cc-canh-bao td:first-child { box-shadow: inset 3px 0 0 #f0ad4e; }

.cc-bang .cc-so { font-variant-numeric: tabular-nums; }

/* Phép tính ra con số của ngày. Nhỏ và nhạt hơn con số chính: đây là phần để ĐỐI CHIẾU khi
   thấy lạ, không phải phần đọc mỗi ngày — to bằng con số thì cả bảng thành một khối chữ và
   chính con số cần đọc lại chìm đi. */
.cc-bang .cc-phep-tinh {
    margin-top: .2rem;
    font-size: .7rem;
    line-height: 1.35;
    color: #6c757d;
    font-variant-numeric: normal;
    white-space: normal;
    text-align: right;
}

.cc-bang .cc-pt-ten { color: #495057; }
.cc-bang .cc-pt-ten::after { content: ":"; }
.cc-bang .cc-pt-tinh { font-variant-numeric: tabular-nums; }

.cc-nguoi {
    display: inline-block;
    margin: 0 .5rem .15rem 0;
    font-size: .85rem;
}

.cc-nguoi-khac { opacity: .6; }

/* Nhãn giải thích vì sao một người không vào hồ sơ — nhỏ, nhạt, đứng ngay sau tên họ. */
.cc-nhan-khac {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: #6f639e;
    border: 1px solid #cfc9e4;
    border-radius: .2rem;
    padding: 0 .25rem;
}

.cc-nhan-dat {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--tvu-primary);
    background: #eef3f9;
    border-radius: .2rem;
    padding: 0 .25rem;
}

/* Trông như NÚT chứ không như một dòng chữ.
   Đây là chỗ bật/tắt chấm công cho một ngày — thứ quyết định người trực hôm đó có tiền hay
   không. Để nó là chữ nhỏ màu xanh thì người dùng đọc lướt qua và không nhận ra là bấm được;
   đã xảy ra thật: người dùng báo "chưa thấy chức năng này". */
.cc-dat > summary {
    list-style: none;
    cursor: pointer;
    user-select: none;
    display: inline-block;
    font-size: .78rem;
    padding: .1rem .5rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: .25rem;
    background: var(--bs-body-bg, #fff);
    color: var(--tvu-primary);
    white-space: nowrap;
}

.cc-dat > summary::-webkit-details-marker { display: none; }

.cc-dat > summary:hover {
    background: var(--tvu-primary);
    color: #fff;
    border-color: var(--tvu-primary);
}

/* Nhóm chọn ca trực. Viền nhạt bao quanh để ba ô tick đọc thành MỘT nhóm lựa chọn, không
   lẫn với ô "cho phép nhiều trực chính" ở cuối biểu mẫu — hai thứ khác hẳn nhau về hệ quả. */
.pc-chon-ca {
    display: flex;
    flex-wrap: wrap;
    gap: .15rem 1.1rem;
    padding: .45rem .7rem;
    border: 1px solid #dde5ef;
    border-radius: .3rem;
    background: #fbfcfe;
}

.pc-chon-ca .form-check { margin-right: 0; }
.pc-chon-ca .form-check-label { font-size: .85rem; }

/* "Cả ngày" tách khỏi ba ca lẻ bằng một vạch: nó không phải ca thứ tư mà là lựa chọn thay
   thế cho cả ba. Đứng liền một dãy bốn ô giống hệt nhau thì đọc thành bốn ca. */
.pc-chon-ca .pc-ca-ngay {
    padding-right: 1rem;
    border-right: 1px solid #dde5ef;
}

/* Ca lẻ khi đang chọn "Cả ngày": làm mờ để thấy chúng đang không có tác dụng. Cố ý KHÔNG
   dùng disabled — ô disabled không nhận focus bàn phím nên người dùng phím tab không tới
   được, và đây vẫn là chỗ họ cần bấm để đổi ý. */
.pc-chon-ca .pc-ca-mo { opacity: .45; }
.pc-chon-ca .pc-ca-mo:focus-within { opacity: 1; }

/* Khung giờ của ca: nhạt hơn tên ca. Nó là thông tin tra cứu, không phải thứ để chọn. */
.pc-chon-ca .form-check-label span { font-size: .75rem; }

/* Hàng cuối biểu mẫu: ô tick bên trái, nút gửi dồn về phải.

   Nút chỉ rộng bằng chữ nó. Bản trước cho nút một cột bốn phần mười rồi kéo w-100, thành
   một thanh xanh dài gần nửa màn hình — nó hút mắt hơn cả ô đang nhập, trong khi việc của
   nó chỉ là kết thúc thao tác. Nút gửi cần dễ TÌM, không cần to. */
.pc-hang-nut {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem .9rem;
    margin-top: .15rem;
}

.pc-nut-luu {
    /* Đủ rộng để chữ không dính sát viền, và để hai nút "Phân trực" / "Lưu thay đổi" trông
       cùng một cỡ dù số chữ khác nhau. */
    min-width: 8.5rem;
    margin-left: auto;
}

@media (max-width: 575.98px) {
    /* Màn hình hẹp thì ngược lại: nút trải hết chiều ngang cho dễ bấm bằng ngón tay,
       và xuống hàng riêng bên dưới ô tick. */
    .pc-hang-nut { flex-direction: column; align-items: stretch; }
    .pc-nut-luu { margin-left: 0; width: 100%; }
}

/* Dòng giải thích trong biểu mẫu: nói VÌ SAO điền ô này, không chỉ nói ô này tên gì.
   Nhạt hơn nhãn để đọc lướt qua được khi đã biết. */
.pc-goi-y {
    font-size: .78rem;
    line-height: 1.45;
    color: #5a6570;
    background: #f5f8fc;
    border-left: 3px solid #cfdcf5;
    border-radius: .2rem;
    padding: .4rem .6rem;
}

/* Xác nhận sửa ngày đã qua: phải nổi hẳn lên. Đây là thao tác chạm vào chấm công và
   thanh toán trực, không được trông giống một ô tick tuỳ chọn bình thường. */
.pc-canh-bao-qua-khu {
    background: #fff8e6;
    border: 1px solid #f0ad4e;
    border-radius: .25rem;
    padding: .45rem .6rem .45rem 2rem;
}

@media (max-width: 575.98px) {
    .pc-o-ngay { flex: 0 0 100%; text-align: left; }
    .pc-mo { flex: 1 1 100%; }
    .pc-mo > summary { text-align: center; }
}

/* Khối hướng dẫn gấp lại: bốn hộp chữ liên tiếp trước bảng là bức tường phải
   vượt qua mỗi lần vào trang, dù người xếp lịch đã đọc chúng từ tháng trước. */
.pc-huong-dan > summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--tvu-primary);
}

.pc-huong-dan > summary:hover { text-decoration: underline; }
.pc-huong-dan[open] > summary { margin-bottom: .75rem; }


/* ============================================================================
   LOG VẬN HÀNH  (/Admin/LogVanHanh)
   ----------------------------------------------------------------------------
   Log đọc bằng mắt, không bằng máy: mức và nguồn phải bắt được trong một cái
   liếc, còn stack trace thì gấp lại vì nó dài gấp mười lần câu lỗi.
   ============================================================================ */

.log-ds {
    font-family: "Cascadia Mono", Consolas, "Courier New", monospace;
    font-size: .8rem;
    max-height: 70vh;
    overflow-y: auto;
}

.log-dong {
    padding: .35rem .75rem;
    border-bottom: 1px solid #eef1f5;
    border-left: 3px solid transparent;
}

.log-dong:last-child { border-bottom: 0; }

.log-dong.log-loi { background: #fff5f5; border-left-color: #dc3545; }
.log-dong.log-canh-bao { background: #fffaf0; border-left-color: #f0ad4e; }
.log-dong.log-mo { color: #868e96; }

.log-dau {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: baseline;
    margin-bottom: .1rem;
}

.log-gio { color: #6c757d; font-variant-numeric: tabular-nums; }

.log-muc {
    font-weight: 700;
    font-size: .7rem;
    letter-spacing: .05em;
}

.log-loi .log-muc { color: #b02a37; }
.log-canh-bao .log-muc { color: #b8860b; }

/* Tên lớp .NET dài loằng ngoằng; cắt bớt phần đầu và giữ phần đuôi có nghĩa. */
.log-nguon {
    color: #4c6ef5;
    font-size: .72rem;
    max-width: 22rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    direction: rtl;
    text-align: left;
}

.log-noi-dung { white-space: pre-wrap; word-break: break-word; }

.log-chi-tiet > summary {
    cursor: pointer;
    color: #6c757d;
    font-size: .72rem;
    margin-top: .2rem;
}

.log-chi-tiet pre {
    margin: .35rem 0 0;
    padding: .5rem .6rem;
    background: #f8f9fa;
    border: 1px solid #e9ecef;
    border-radius: .25rem;
    font-size: .72rem;
    max-height: 22rem;
    overflow: auto;
    white-space: pre;
}


/* ============================================================================
   ĐỔI TRẠNG THÁI TÀI KHOẢN  (/Admin/NguoiDung)
   ----------------------------------------------------------------------------
   Gấp trong <details>: mỗi hàng bày sẵn ba nút thì bảng thành rừng nút, và một
   nút "Khoá" đỏ nằm cạnh chuột là lời mời bấm nhầm.
   ============================================================================ */

.tt-doi { position: relative; display: inline-block; }

.tt-doi > summary { list-style: none; cursor: pointer; white-space: nowrap; }
.tt-doi > summary::-webkit-details-marker { display: none; }
.tt-doi > summary::after { content: " ▾"; }
.tt-doi[open] > summary::after { content: " ▴"; }

.tt-form {
    position: absolute;
    right: 0;
    z-index: 20;
    width: 16rem;
    margin-top: .35rem;
    padding: .75rem;
    background: #fff;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: .4rem;
    box-shadow: 0 .5rem 1.2rem rgba(0, 0, 0, .12);
}

@media (max-width: 575.98px) {
    /* Màn hình hẹp: thả về dòng thường, khỏi tràn ra ngoài mép bảng. */
    .tt-doi { display: block; }
    .tt-form { position: static; width: auto; box-shadow: none; }
}

/* ---------- Ma trận phân quyền (vai trò × quyền) ---------- */

/* Khung cuộn riêng: sticky chỉ dính trong khung cuộn gần nhất, nên hàng tiêu đề và cột đầu
   phải cuộn trong CÙNG một khung mới dính được cả hai chiều. */
.rbac-khung {
    max-height: 75vh;
    overflow: auto;
}

/* Cột "Quyền" dính bên trái khi cuộn ngang. Có sáu, bảy vai trò là bảng vượt bề rộng màn hình,
   mà cuộn tới cột thứ năm rồi quên mình đang tick quyền nào thì ma trận mất hết giá trị. */
.rbac th:first-child,
.rbac td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--bs-body-bg);
}

/* Hàng tên vai trò dính lên đầu khi cuộn dọc — cùng lý do, chỉ đổi trục. */
.rbac thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bs-body-bg);
}

/* Ô góc dính cả hai chiều nên phải nằm trên cả hai. */
.rbac thead th:first-child { z-index: 3; }

/* Viền của ô sticky bị cuộn qua dưới nội dung: viền vẽ theo ô, mà ô thì đang trôi. Dùng bóng
   đổ thay viền cho hai cạnh giáp phần cuộn. */
.rbac thead th { box-shadow: inset 0 -1px 0 var(--bs-border-color); }
.rbac th:first-child,
.rbac td:first-child { box-shadow: inset -1px 0 0 var(--bs-border-color); }
.rbac thead th:first-child {
    box-shadow: inset -1px 0 0 var(--bs-border-color), inset 0 -1px 0 var(--bs-border-color);
}

/* Hàng tiêu đề nhóm quyền cần nền riêng, nếu không phần dính bên trái đè lên nền của nó. */
.rbac tr.table-light th:first-child { background: var(--bs-tertiary-bg); }

/* Ô tick to hơn mặc định: đây là bảng để rà nhanh bằng mắt, ô 1rem quá nhỏ để nhắm trúng. */
.rbac .form-check-input { width: 1.15rem; height: 1.15rem; margin: 0; }

/* Mọi ô tiêu đề căn lên đầu.

   Các ô tên vai trò không cao bằng nhau: cột Quản trị bị khoá nên không có ô tick cả cột, thấp
   hơn hai cột kia đúng một dòng. Căn giữa mặc định làm ba cái tên nằm ở ba độ cao khác nhau —
   đọc như lỗi dựng trang chứ không như thiết kế. Nhãn "Quyền" cũng vậy: căn giữa đẩy nó xuống
   sát đáy, xa hẳn hàng tiêu đề nó đang gọi tên. */
.rbac thead th { vertical-align: top; }

/* ---------- Bề rộng cột, co theo màn hình ----------

   Trước đây hai bề rộng này viết thẳng bằng style="" trong Razor, nên KHÔNG co được: trên điện
   thoại, cột "Quyền" rộng 20rem dính bên trái đã chiếm gần trọn màn, các cột vai trò bị đẩy ra
   ngoài và ma trận thành một danh sách một cột. */
.rbac-cot-quyen  { min-width: 20rem; }
.rbac-cot-vaitro { min-width: 7.5rem; }

/* ---------- Mô tả quyền: gập lại ----------

   Đây là thay đổi có tác dụng lớn nhất. Vài mô tả dài năm, sáu dòng; nhân với hai mươi quyền thì
   bảng cao tới mức không còn "nhìn một cái thấy cả bức tranh" — mà đó chính là lý do bày dưới
   dạng ma trận thay vì danh sách. */
.rbac-mota > summary {
    cursor: pointer;
    color: var(--bs-secondary-color);
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0;
    user-select: none;
}

.rbac-mota > summary::-webkit-details-marker { display: none; }

/* Mũi tên tự vẽ: marker mặc định của trình duyệt mỗi nơi một kiểu và không đổi màu theo chủ đề. */
.rbac-mota > summary::before {
    content: "▸";
    display: inline-block;
    transition: transform 0.12s ease;
    font-size: 0.85em;
}

.rbac-mota[open] > summary::before { transform: rotate(90deg); }

.rbac-mota > summary:hover { color: var(--bs-body-color); }

.rbac-mota > div {
    padding: 0.35rem 0 0.15rem 0.9rem;
    border-left: 2px solid var(--bs-border-color);
    margin-top: 0.25rem;
    max-width: 34rem;      /* dòng quá dài thì mắt lạc hàng khi xuống dòng */
}

/* ---------- Màn hình hẹp ----------

   Dưới 768px, ma trận vẫn là ma trận — chỉ gọn lại. Đổi hẳn sang danh sách theo vai trò thì
   phải dựng hai bộ ô tick trong cùng một biểu mẫu, và bộ bị ẩn VẪN gửi lên khi bấm Lưu: ẩn bằng
   CSS không làm ô ngừng gửi. Đó là cách hỏng âm thầm, nên không làm. */
@media (max-width: 768px) {
    .rbac-cot-quyen  { min-width: 11rem; }
    .rbac-cot-vaitro { min-width: 5.25rem; }

    .rbac th,
    .rbac td { padding: 0.35rem 0.4rem; }

    .rbac-ten { font-size: 0.9rem; line-height: 1.25; }

    /* Mã quyền và mã vai trò là thứ tra khi cần, không phải thứ đọc mỗi lần — trên màn hẹp nó
       chiếm mất chỗ của chính cái tên. */
    .rbac-ma { display: none !important; }

    .rbac-ten-vaitro { font-size: 0.85rem; line-height: 1.2; }

    .rbac-khung { max-height: 70vh; }
}

/* Gợi ý cuộn ngang: khi bảng rộng hơn khung thì không có gì cho thấy điều đó — người dùng tưởng
   chỉ có hai vai trò vì hai cột kia nằm ngoài mép.

   Hiện/ẩn do JS quyết định theo bề rộng THẬT của bảng, không theo media query: bảng rộng hay
   hẹp là do số vai trò, mà số vai trò thì quản trị tự thêm. Treo vào một mốc pixel cố định là
   hoặc nói "vuốt ngang" khi bảng đã vừa màn (nói sai), hoặc im lặng khi có tám vai trò tràn ra
   ngoài trên màn rộng (bỏ sót đúng lúc cần nhất). */
.rbac-goi-y-cuon { display: flex; align-items: baseline; gap: 0.35rem; }

/* ---------- Menu Quản trị ---------- */

/* Icon rộng cố định để chữ của mọi mục thẳng hàng nhau. Emoji có bề rộng khác nhau — thả trực
   tiếp vào chữ thì mỗi dòng lệch một kiểu, và cái lệch đó đọc như lỗi chứ không như thiết kế. */
.menu-qt-icon {
    display: inline-block;
    width: 1.5rem;
    text-align: center;
    font-size: 0.95em;
}

/* Tiêu đề nhóm: đủ nổi để chia khối, đủ nhạt để không tranh chỗ với chính các mục menu. */
.menu-qt .dropdown-header {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    padding-bottom: 0.15rem;
}

/* Menu này dài nhất trong thanh điều hướng; canh lề để không tràn mép phải màn hình. */
.menu-qt { min-width: 15rem; }

/* ---------------------------------------------------------------------------
   Thay cho thuoc tinh style="" viet thang trong Razor.

   Trang Kho mat khau chay duoi Content-Security-Policy CHAT, khong cho
   style-src 'unsafe-inline'. Mot thuoc tinh style="" bat ky tren trang do —
   ke ca cua _Layout dung chung — se bi trinh duyet chan va bo cuc vo.
   Nen hai lop duoi day thay cho hai cho duy nhat con dung style="".
   --------------------------------------------------------------------------- */
.rong-toi-da-18 { max-width: 18rem; }
.rong-toi-da-16 { max-width: 16rem; }
