/* ============================================================
   VanThuan Holdings — tùy biến giao diện (đè lên theme DreamsPOS)
   Nạp sau build/css/style.css trong head-css.blade.php.
   NGUỒN: resources/css/app-custom.css (Git theo dõi) — vite-plugin-static-copy
   tự copy ra public/build/css/app-custom.css mỗi lần build (KHÔNG đặt thẳng vào
   public/build vì thư mục đó bị Vite xóa sạch khi build => sẽ mất file).
   ============================================================ */

/* ---- 1. Nhãn nhóm menu (submenu-hdr): IN HOA, cỡ ~gấp đôi mục menu ---- */
#sidebar-menu .submenu-hdr {
    text-transform: uppercase;
    font-size: 0.75rem;    /* ~12px — nhỏ gọn, đậm + IN HOA để phân biệt nhóm */
    font-weight: 700;
    letter-spacing: .4px;
    line-height: 1.3;
    color: #16191c;
    margin-top: .35rem;
    margin-bottom: .35rem;
}

/* Giữ mục menu con ở cỡ chuẩn để tương phản rõ với nhãn nhóm. */
#sidebar-menu ul li.submenu > a,
#sidebar-menu ul li a {
    font-size: .9rem;
}

/* ---- 2. Logo thương hiệu (ảnh VUÔNG nền đỏ VAN THUAN HOLDINGS) ----
   Khóa cứng tỉ lệ vuông (width = height) + object-fit: contain để KHÔNG bị
   theme kéo giãn méo. !important để đè rule width/height của theme. */

/* Sidebar mở rộng */
.sidebar-logo .logo-normal img,
.sidebar-logo .logo-white img {
    height: 46px !important;
    width: 46px !important;
    max-width: none !important;
    object-fit: contain;
    border-radius: 8px;
    vertical-align: middle;
}

/* Chữ thương hiệu "TAH-ERP" cạnh logo.
   Đặt ABSOLUTE so với thẻ logo (logo anchor giữ nguyên 46px như cũ) + pointer-events:none
   => KHÔNG làm rộng vùng logo và KHÔNG chặn click nút thu gọn #toggle_btn. */
.sidebar-logo .logo-normal,
.sidebar-logo .logo-white {
    position: relative;
}
.sidebar-logo .brand-text {
    position: absolute;
    left: calc(100% + 6px);    /* sát cạnh phải logo */
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;      /* để click xuyên qua, không chặn nút toggle */
    font-weight: 900;          /* đậm DÀY (bạn chốt 16/08/2026) — 800 còn mảnh so với logo */
    font-size: 1.05rem;        /* nhích lên chút cho cân với nét dày */
    letter-spacing: 0;         /* co sát khoảng cách ký tự */
    line-height: 1;
    color: #b3091a;            /* đỏ thương hiệu, hợp logo */
    white-space: nowrap;
}
.sidebar-logo .logo-white .brand-text {
    color: #f5d142;            /* nền tối: vàng kim cho nổi */
}
/* Chỉ ẩn chữ khi sidebar ở dạng icon (mini) VÀ KHÔNG đang hover-mở-rộng.
   Khi mini-sidebar được mở rộng ra (theme thêm .expand-menu) thì chữ hiện lại. */
.mini-sidebar:not(.expand-menu) .sidebar-logo .brand-text {
    display: none !important;
}
/* Sidebar thu gọn (mini) */
.sidebar-logo .logo-small img,
.sidebar-logo .logo-small-white img {
    height: 34px !important;
    width: 34px !important;
    max-width: none !important;
    object-fit: contain;
    border-radius: 6px;
}

/* Header trên cùng (topbar — hiển thị ở mobile/một số layout) */
.header-left .logo img {
    height: 38px !important;
    width: 38px !important;
    max-width: none !important;
    object-fit: contain;
    border-radius: 6px;
}

/* Trang đăng nhập / quên mật khẩu / 2FA — logo NGANG (có chữ thương hiệu) căn giữa.
   Khoá theo CHIỀU CAO và để chiều rộng tự co: ép ô vuông như trước sẽ làm logo ngang teo lại
   còn nửa khung, chữ "TAM AN HOLDINGS" nhỏ tới mức không đọc được. */
.login-logo img {
    height: 120px !important;
    width: auto !important;
    max-width: 300px !important;
    object-fit: contain;
}
.login-wrapper .login-content .login-userset .login-logo {
    text-align: center;
    margin-bottom: 1rem;
}

/* ---- 3. Hồ sơ nhân viên — trình bày card chuyên nghiệp ---- */
.profile-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: linear-gradient(135deg, #b3091a 0%, #e0334a 100%);
    color: #fff;
    font-weight: 700;
    font-size: 1.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 64px;
    text-transform: uppercase;
}
/* Card có tiêu đề icon (đồng bộ với card Sơ đồ tổ chức) */
.info-card .card-header {
    background: #fafbfc;
    border-bottom: 1px solid #eceef1;
    font-weight: 600;
}
/* Danh sách nhãn — giá trị gọn gàng */
.info-list {
    margin: 0;
}
.info-list li {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .6rem 0;
    border-bottom: 1px dashed #eef0f2;
}
.info-list li:last-child {
    border-bottom: 0;
}
.info-list .info-label {
    color: #6b7280;
    font-size: .875rem;
    white-space: nowrap;
}
.info-list .info-value {
    font-weight: 600;
    text-align: right;
    color: #16191c;
}

/* ---- 4. Bảng toàn hệ thống (bảng thường + DataTables) — định nghĩa MỘT chỗ ----
   Header nền = màu primary thật của template (#E04F16 = rgb(224,79,22), đúng màu nút
   "Thêm"), chữ trắng. Hover dòng = tint nhạt cùng màu (kiểu nền menu active). */
.table > thead > tr > th,
.table thead th,
table.dataTable > thead > tr > th,
table.dataTable thead th {
    background-color: rgb(224, 79, 22) !important;   /* = primary template (#E04F16) */
    color: #fff !important;
    border-color: rgb(224, 79, 22) !important;
    font-weight: 600;
    vertical-align: middle;
}
/* Bo góc nhẹ cho ô đầu/cuối hàng tiêu đề */
.table > thead > tr > th:first-child,
.table thead th:first-child {
    border-top-left-radius: 6px;
}
.table > thead > tr > th:last-child,
.table thead th:last-child {
    border-top-right-radius: 6px;
}
/* Icon sắp xếp DataTables giữ sáng để nổi trên nền cam */
table.dataTable > thead .sorting::before,
table.dataTable > thead .sorting::after,
table.dataTable > thead .sorting_asc::before,
table.dataTable > thead .sorting_asc::after,
table.dataTable > thead .sorting_desc::before,
table.dataTable > thead .sorting_desc::after {
    color: #fff !important;
    opacity: .55;
}
/* ═══════════════════════════════════════════════════════════════════════════════════════════════════
   RÊ CHUỘT LÊN MỘT DÒNG BẢNG — MỘT LUẬT DUY NHẤT CHO TOÀN DỰ ÁN (user chốt 18/08/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════════
   Áp cho MỌI bảng: `.table`, `.table-hover`, và bảng do DataTables dựng. Màn nào cũng dùng đúng một
   sắc độ, không màn nào tự khai màu rê chuột riêng.

   ⚠ `--vt-row-hover` là NƠI DUY NHẤT được đổi màu này. Ô DÍNH khi cuộn ngang (`.wt-act-sticky`,
     `.wt-sk`, `.wt-actions`) buộc phải khai lại nền vì nền trong suốt sẽ để chữ các cột khác chạy
     xuyên qua — và chúng PHẢI đọc cùng biến này. Trước 18/08 chúng khai cứng `#fcfcfd` trong khi luật
     chung là `#fdf7f3`: rê chuột lên một dòng thì phần giữa ra màu be còn cột thao tác ở mép phải ra
     màu xám trắng — CÙNG MỘT DÒNG HAI MÀU, và không ai để ý vì phải cuộn ngang mới thấy cạnh nhau.

   ⚠ Vì sao là màu SOLID chứ không phải `rgba(0,0,0,.075)` mặc định của Bootstrap: nền mờ đen chồng lên
     tông cam của theme cho ra sắc "xỉn", và chồng tiếp lên dòng đang chọn thì ra màu thứ ba.
   ⚠ `transition` đặt trên Ô (không phải trên `tr`): nền bảng nằm ở ô, đặt trên hàng thì không có gì đổi
     mềm cả. 120ms — đủ để thấy nó "mờ vào", chưa đủ lâu để thành lê thê khi lướt nhanh qua nhiều dòng.

   ★★★ 22/08/2026 — BẠN ĐẢO LẠI LUẬT MÀU: *"để màu background của row của bảng giống hệt màu của menu
   actived … áp dụng cho toàn row hover của dự án, chỉ khai một chỗ thôi"*.
   ⇒ Màu nay là **cam thương hiệu rất nhạt**, cùng tông với mục menu đang sáng. Chú thích cũ ở đây từng
     lập luận ngược lại ("giữ TRUNG TÍNH, màu ám cam đọc như tín hiệu trạng thái") — ⛔ lập luận ấy KHÔNG
     còn hiệu lực, giữ lại chỉ khiến người sau tưởng bản vá này là sơ suất.
   ⚠⚠ VÌ SAO SOLID `#fff7f0` CHỨ ⛔ KHÔNG `rgba(254,159,67,.08)` như sidebar, dù hai màu nhìn như một:
      biến này còn được **ô DÍNH khi cuộn ngang** dùng lại (`.wt-act-sticky`, `.wt-sk`, `.wt-actions`).
      Ô dính bắt buộc phải có nền ĐỤC — nền mờ sẽ để chữ của các cột trượt qua bên dưới **hiện xuyên
      qua nó**. `#fff7f0` chính là `rgba(254,159,67,.08)` sau khi chồng lên nền trắng, nên mắt không
      phân biệt được, mà ô dính vẫn an toàn.
   ⚠ MỘT BIẾN CHO CẢ HAI VIỆC (bạn yêu cầu "chỉ khai một chỗ"): rê chuột **và** vùng bung của dòng đều
     đọc `--vt-row-hover`. ⛔ Đừng đẻ thêm token thứ hai cho vùng bung. */
:root { --vt-row-hover: #fff7f0; }

/* ★★★ 25/08/2026 — VIỀN ẤM CỦA Ô SOẠN THẢO (anh Dũng: *"tất cả đường viền xung quanh luôn cả editor"*).
   Nền thanh công cụ nay là `--vt-row-hover` (tông CAM), nên viền xám LẠNH `#e3e6ec` bao quanh làm khung
   trông như hai mảnh của hai bộ giao diện khác nhau — đúng ba chỗ anh khoanh mũi tên: viền trái · viền
   phải · thanh kéo dưới.
   ⚠ KHAI MỘT TOKEN cho MỌI đường viền của khung soạn thảo — ⛔ đừng rải mã màu ở từng selector, lần đổi
     tông sau sẽ phải đi tìm đủ năm chỗ và chắc chắn sót một.
   ⚠ Đậm hơn `--vt-row-hover` vài nấc: viền phải THẤY ĐƯỢC trên nền trắng, ⛔ không được nhạt bằng nền
     thanh công cụ (nhạt bằng thì khung tan vào trang và ô soạn thảo mất đường bao). */
:root { --vt-editor-border: #f0ddcc; }

/* Vùng BUNG RA của một dòng bảng — cùng màu với dòng đang rê và với mục menu đang sáng (xem trên).
   ⚠ Khai lớp ở đây chứ ⛔ không nhét `style="background:…"` vào Blade: một mã màu chép tay trong view
     là chỗ không ai tìm thấy khi đổi theme. */
.vt-row-open { background: var(--vt-row-hover); }
.table > tbody > tr > *,
.table-hover > tbody > tr > * { transition: background-color .12s ease-in-out; }
.table > tbody > tr:hover,
.table-hover > tbody > tr:hover,
.table > tbody > tr:hover > *,
.table-hover > tbody > tr:hover > * {
    --bs-table-bg-state: var(--vt-row-hover);
    background-color: var(--vt-row-hover) !important;
}

/* Nút outline khi di chuột vào: chữ phải TRẮNG (theme đang để chữ trùng màu nền) */
.btn-outline-primary:hover, .btn-outline-primary:focus, .btn-outline-primary:active, .btn-outline-primary.active,
.btn-outline-secondary:hover, .btn-outline-secondary:focus, .btn-outline-secondary:active, .btn-outline-secondary.active,
.btn-outline-danger:hover, .btn-outline-danger:focus, .btn-outline-danger:active, .btn-outline-danger.active,
.btn-outline-success:hover, .btn-outline-success:focus, .btn-outline-success:active,
.btn-outline-info:hover, .btn-outline-info:focus, .btn-outline-info:active,
.btn-outline-dark:hover, .btn-outline-dark:focus, .btn-outline-dark:active {
    color: #fff !important;
}


/* ---- 5. Trang AUTH (đăng nhập / quên–đặt lại / ép đổi mật khẩu / 2FA) ----
   KHÔNG dùng ảnh nền: nền phẳng nhã nhặn; card canh GIỮA màn hình, cách đều 2 bên,
   responsive full. Bỏ panel 50% lệch trái + lớp kính mờ của theme. */
.login-wrapper,
.login-wrapper.bg-img {
    background-image: none !important;
    background: #f4f6fa !important;   /* nền phẳng, sạch, chuyên nghiệp */
}
.login-wrapper .login-content,
.login-wrapper .login-content.authent-content {
    width: 100% !important;            /* trải full, không còn lệch trái 50% */
    background: transparent !important;
    backdrop-filter: none !important;
    padding: 24px;
}
/* Form = thẻ (card) canh giữa, cách đều 2 bên nhờ margin auto + max-width */
.login-wrapper .login-content form {
    width: 100% !important;
    max-width: 484px;   /* to hơn ~10% so với 440px */
    margin-left: auto;
    margin-right: auto;
    background: #fff;
    border: 1px solid #eceef1;
    border-radius: 16px;
    padding: 2.5rem 2.25rem;
    box-shadow: 0 10px 30px rgba(16, 24, 40, .08);
}
/* Logo + tiêu đề canh giữa */
.login-wrapper .login-content .login-logo { text-align: center; }
.login-wrapper .login-content .login-userheading { text-align: center; margin-bottom: 1.5rem; }
@media (max-width: 575.98px) {
    .login-wrapper .login-content { padding: 16px; }
    .login-wrapper .login-content form { padding: 1.5rem 1.25rem; border-radius: 14px; }
}
.modal .close,
.modal .btn-close {

  width: 10px !important;
  height: 10px !important;
  font-weight: 700 !important;
}
.modal .modal-header .btn-close,
.modal .btn-close.btn-danger,
.modal .btn-close.bg-danger {
    --bs-btn-close-color: #fff;
    --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");
    --bs-btn-close-opacity: 1;
    --bs-btn-close-hover-opacity: 1;
    background-position: center center !important;
    background-size: 0.75em auto !important;
    background-repeat: no-repeat !important;
    opacity: 1;
    filter: none !important;
}

/* ===== Stepper biến động nhân sự (Lập đề nghị → Lãnh đạo duyệt → HR thực hiện) ===== */
.lc-stepper {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.lc-stepper .lc-step {
  flex: 1 1 0;
  text-align: center;
  position: relative;
}
.lc-stepper .lc-step::before,
.lc-stepper .lc-step::after {
  content: "";
  position: absolute;
  top: 18px;
  height: 3px;
  width: 50%;
  background: #e5e7eb;
  z-index: 0;
}
.lc-stepper .lc-step::before { left: 0; }
.lc-stepper .lc-step::after { right: 0; }
.lc-stepper .lc-step:first-child::before,
.lc-stepper .lc-step:last-child::after { display: none; }
.lc-stepper .lc-step.done::before,
.lc-stepper .lc-step.done::after,
.lc-stepper .lc-step.current::before { background: rgb(224, 79, 22); }
.lc-stepper .lc-step-circle {
  position: relative;
  z-index: 1;
  width: 38px;
  height: 38px;
  line-height: 38px;
  border-radius: 50%;
  background: #fff;
  border: 3px solid #e5e7eb;
  color: #9ca3af;
  font-weight: 700;
  margin: 0 auto;
}
.lc-stepper .lc-step.done .lc-step-circle {
  background: rgb(224, 79, 22);
  border-color: rgb(224, 79, 22);
  color: #fff;
}
.lc-stepper .lc-step.current .lc-step-circle {
  border-color: rgb(224, 79, 22);
  color: rgb(224, 79, 22);
}
.lc-stepper .lc-step-label { font-weight: 600; font-size: 0.85rem; margin-top: 0.4rem; }
.lc-stepper .lc-step-sub { color: #9ca3af; font-size: 0.72rem; }

/* ===== 6. SweetAlert2 — thu nhỏ tiêu đề thông báo/xác nhận =====
   Mặc định .swal2-title của SweetAlert2 là 1.875em (rất to, lấn át nội dung).
   Chuẩn hóa MỘT chỗ cho TOÀN hệ thống: tiêu đề gọn, dễ đọc; nội dung & nút giữ nguyên. */
.swal2-popup .swal2-title {
  font-size: 1.2rem;        /* ~19px thay vì ~30px */
  font-weight: 600;
  line-height: 1.4;
  padding: 0 1rem;
}
.swal2-popup .swal2-html-container {
  font-size: 0.95rem;
  line-height: 1.5;
}

/* ===== 6b. TOAST góc phải — DÁNG RIÊNG `.vt-toast` (user chốt 23/08/2026) ======================
   ★ User báo ba lượt: *"thời gian hiện hơi nhanh chưa kịp đọc"* → *"style đẹp hơn, rộng hơn, chữ
   nhỏ lại chứ giờ thô quá"* → mở màn thật xem thì *"vẫn xấu quá"*.

   🔴 HAI GỐC BỆNH đo được trên màn thật, ⛔ không phải suy đoán:
     ① `.swal2-popup .swal2-title` (khối §6 ngay trên) đặt chữ **1.2rem** cho MỌI popup — toast cũng
        là `.swal2-popup` nên ăn theo. Chữ 19px trong hộp hẹp ⇒ câu 50 ký tự vỡ dòng, lấn hết hộp.
     ② Biểu tượng mặc định của thư viện vẽ bằng vòng tròn + nét kẻ theo kích thước CỐ ĐỊNH. Thu nhỏ
        nó bằng `width/height` thì vòng tròn và dấu tích **méo và tràn ra ngoài** — đúng cái nhìn
        thấy trong ảnh: biểu tượng đè lên chữ. ⇒ ⛔ ĐỪNG cố bóp biểu tượng của thư viện.

   ⇒ CÁCH CHỮA: toast **tự dựng thân riêng** (`AppUtils.toast` truyền `html` + `customClass`), dùng
   biểu tượng phông chữ của theme (`ti ti-*`) thay cho biểu tượng vẽ tay của thư viện. Nhờ vậy dáng
   toast **không còn phụ thuộc** vào cách thư viện dựng hộp thoại, và ⛔ không đụng một chút nào tới
   ~100 lời gọi `Swal.fire` xác nhận đang chạy đúng.

   ⚠ Bốn màu lấy từ bảng màu dự án (cam chủ đạo `#E04F16` cho tin báo), khai bằng biến cục bộ để
     thân toast chỉ viết `var(--vt-toast-accent)` một lần — ⛔ đừng chép mã màu vào từng khối.
   ---------------------------------------------------------------------------------------------- */

/* Đệm mép: thư viện đặt toast sát góc màn hình, trông như bị cắt rời khỏi trang. */
.swal2-container.swal2-top-end,
.swal2-container.swal2-top-right { padding: 1rem 1.25rem; }

.swal2-container .vt-toast {
  width: auto;
  max-width: 420px;
  min-width: 260px;
  padding: 0;
  overflow: hidden;
  border: 1px solid #eaecf0;
  border-radius: 0.625rem;
  background: #fff;
  /* Bóng hai lớp: lớp rộng tạo độ nổi, lớp sát tạo cạnh — mềm hơn hẳn một lớp bóng đơn. */
  box-shadow: 0 0.75rem 1.75rem -0.375rem rgba(16, 24, 40, 0.18),
              0 0.25rem 0.5rem -0.25rem rgba(16, 24, 40, 0.08);
}
/* Thư viện chừa sẵn khoảng đệm cho phần thân; thân toast tự lo đệm nên phải dọn sạch, nếu không
   chữ bị đẩy lệch khỏi vạch màu bên trái. */
.swal2-container .vt-toast .swal2-html-container {
  margin: 0;
  padding: 0;
  font-size: inherit;
  line-height: inherit;
  text-align: left;
  overflow: visible;
}
.vt-toast__row {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  padding: 0.75rem 0.9rem;
  border-left: 3px solid var(--vt-toast-accent);   /* vạch màu = nhận biết loại tin trong nháy mắt */
}
.vt-toast__ico {
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.05rem;                              /* canh theo DÒNG ĐẦU, không canh giữa khối */
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
  background: var(--vt-toast-soft);
  color: var(--vt-toast-accent);
}
.vt-toast__text {
  font-size: 0.8125rem;      /* ~13px — cỡ chữ phụ của theme: đọc thoáng mà không lấn giao diện */
  font-weight: 500;
  line-height: 1.55;
  color: #344054;
  word-break: break-word;
}
/* Nút tắt (user chốt 23/08/2026: *"nên có nút tắt đi chứ nó hiện lâu quá"*) — mờ nhạt lúc thường,
   rõ lên khi rê chuột: nó là lối thoát, ⛔ không được tranh chỗ với nội dung thông báo. */
.vt-toast__close {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0.1rem -0.15rem 0 0.25rem;
  padding: 0;
  border: 0;
  border-radius: 0.25rem;
  background: transparent;
  color: #98a2b3;
  font-size: 0.875rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.vt-toast__close:hover { background: #f2f4f7; color: #475467; }
.vt-toast__close:focus-visible { outline: 2px solid var(--vt-toast-accent); outline-offset: 1px; }

.vt-toast--success { --vt-toast-accent: #12b76a; --vt-toast-soft: #e7f7ef; }
.vt-toast--error   { --vt-toast-accent: #d92d20; --vt-toast-soft: #fdecea; }
.vt-toast--warning { --vt-toast-accent: #f79009; --vt-toast-soft: #fef3e2; }
.vt-toast--info    { --vt-toast-accent: #e04f16; --vt-toast-soft: #fdeee7; }
/* Thanh đếm ngược: mảnh và nhạt — nó là DẤU HIỆU "sắp tắt, rê chuột vào để giữ lại", không phải
   một dải trang trí. ⛔ Bỏ nó đi là người dùng không biết mình có thể giữ toast lại. */
.swal2-container .vt-toast .swal2-timer-progress-bar {
  height: 0.1875rem;
  background: var(--vt-toast-accent);
  opacity: 0.3;
}

/* ===== 6c. TOOLTIP — dáng chung TOÀN HỆ THỐNG (user chốt 23/08/2026) ===========================
   ★ User báo: *"style của tooltip toàn hệ thống đừng để màu nền nó đen thế, làm cho nó đẹp hơn đi"*.

   Mặc định của khung giao diện là **đen tuyền** — trên nền trắng của theme nó nặng và thô, nhất là
   khi tooltip xuất hiện dày đặc ở các cột thao tác. Đổi sang xám đậm dịu `#344054` (cùng tông chữ
   với toast, xem §6b) + bóng nhẹ + bo góc mềm.

   ⚠ Khai HAI lớp cho chắc, ⛔ đừng bỏ lớp nào:
     · nhóm biến `--bs-tooltip-*` cho bản khung giao diện mới (nó đọc biến);
     · `.tooltip-inner` + mũi tên cho bản cũ (không có biến, chỉ nghe quy tắc trực tiếp).
   Chỉ khai một lớp thì tuỳ phiên bản mà tooltip đổi hoặc không, và không lỗi nào báo.

   ⚠ Mũi tên phải đổi màu CÙNG LƯỢT với thân: quên nó là ra một hộp xám gắn một mũi tên đen — trông
     còn tệ hơn để nguyên như cũ. Mũi tên vẽ ở `::before` cho cả bốn hướng.
   ---------------------------------------------------------------------------------------------- */
/* ⚠ MÀU: user chốt *"để màu nào nhạt hẳn hoặc giống màu của menu đang chọn"*. `#fff3ec` + viền
   `#ffd9c4` là đúng cặp màu cam nhạt đã dùng cho mục menu đang chọn và chip đang rê chuột (xem
   `.vt-bd-chip:hover` ở §sau) ⇒ chú giải nằm cùng bảng màu với phần còn lại, ⛔ không phải một tông
   xám lạc lõng. Chữ giữ `#344054` cho dễ đọc — chữ cam trên nền cam nhạt là mất tương phản. */
.tooltip {
  --bs-tooltip-bg: #fff3ec;
  --bs-tooltip-color: #344054;
  --bs-tooltip-opacity: 1;
  --bs-tooltip-border-radius: 0.5rem;
  --bs-tooltip-font-size: 0.78125rem;   /* ~12.5px — chữ chú giải, nhỏ hơn chữ thân trang */
  --bs-tooltip-padding-x: 0.625rem;
  --bs-tooltip-padding-y: 0.4rem;
  --bs-tooltip-max-width: 280px;
  /* 🔴🔴 CHÚ GIẢI PHẢI NẰM TRÊN CÙNG — anh Dũng bắt trên màn thật 28/08/2026, kèm ảnh: hộp chú giải của
     một dòng trong danh sách bung của Select2 chỉ **ló ra một dải hẹp bên phải**, phần còn lại biến mất
     sau danh sách; nhìn như chú giải "nhảy ra ngoài, sai chỗ".
     ★ ĐO ĐƯỢC (thao tác bằng chuột thật, không phải sự kiện giả): chú giải `z-index: 1080` (mặc định
       Bootstrap) còn `.select2-container--open` là **9999** — dự án đã nâng nó để danh sách nổi trên
       hộp thoại. Chú giải nằm ĐÚNG chỗ (ngay trên phần tử, `data-popper-placement="top"`), nó chỉ bị
       chính danh sách phủ lên.
     ⚠ Đây là bệnh CÓ SẴN của toàn hệ thống: mọi chú giải trên phần tử nằm trong danh sách Select2 đều
       bị che như vậy. Nó chỉ lộ ra khi có thứ đáng rê chuột ở trong đó.
     ⚠⚠ KHAI CẢ HAI DẠNG — cùng lý lẽ với khối màu ngay dưới: bản khung giao diện mới đọc biến
       `--bs-tooltip-zindex`, bản cũ ⛔ không có biến nào và chỉ nghe quy tắc trực tiếp. Khai một dạng thì
       tuỳ phiên bản mà chạy hoặc không, ⛔ và không lỗi nào báo.
     ⛔ Đừng hạ số này xuống dưới 9999 "cho gọn" — chú giải là lớp trên cùng theo đúng bản chất của nó. */
  --bs-tooltip-zindex: 10000;
  z-index: 10000;
}
.tooltip .tooltip-inner {
  background-color: #fff3ec;
  color: #344054;
  font-size: 0.78125rem;
  font-weight: 500;
  line-height: 1.5;
  padding: 0.4rem 0.625rem;
  border: 1px solid #ffd9c4;
  border-radius: 0.5rem;
  max-width: 280px;
  text-align: left;                     /* câu dài đọc theo lề trái, ⛔ không căn giữa kiểu khẩu hiệu */
  /* Nền sáng thì BÓNG là thứ duy nhất tách chú giải khỏi thẻ trắng bên dưới — ⛔ đừng bỏ. */
  box-shadow: 0 0.5rem 1.25rem -0.25rem rgba(16, 24, 40, 0.16),
              0 0.125rem 0.25rem rgba(16, 24, 40, 0.06);
}
.tooltip.show { opacity: 1; }
.tooltip .tooltip-arrow::before {
  border-top-color: #fff3ec;
  border-bottom-color: #fff3ec;
  border-left-color: #fff3ec;
  border-right-color: #fff3ec;
}

/* ---- MÀU NÚT hộp thoại — khai MỘT LẦN cho TOÀN dự án (12/08/2026, user chốt) ----------------
   Mặc định của thư viện là TÍM #7066e0 (nút xác nhận) và XANH #6e7881 (nút huỷ) — không thuộc bảng
   màu nào của dự án. Trước đây mỗi lời gọi `Swal.fire` phải tự truyền `confirmButtonColor`, nên chỗ
   nào quên là ra nút tím giữa giao diện cam. Không lỗi nào báo; chỉ mở màn thật mới thấy.

   ⚠ Vì sao CSS ĐÈ ĐƯỢC: màu tím đến từ style-sheet do thư viện tự chèn vào <head>, KHÔNG phải inline
   style — nên quy tắc ở đây (nạp sau) thắng ở cùng độ đặc hiệu. Còn `confirmButtonColor` truyền từ JS
   thì SweetAlert đặt INLINE, và inline luôn thắng CSS. Đó chính là hành vi mong muốn: khai ở đây là
   MẶC ĐỊNH, lời gọi nào cần khác vẫn tự quyết được.

   ⚠ ~100 lời gọi hiện có truyền sẵn `confirmButtonColor: '#d33'` cho hành động phá vỡ — chúng giữ
   nguyên inline nên KHÔNG đổi hình. Mã MỚI thì dùng lớp `.vt-swal-danger` bên dưới thay cho mã màu
   viết cứng: `customClass: { confirmButton: 'vt-swal-danger' }`.
   ---------------------------------------------------------------------------------------------- */
.swal2-styled.swal2-confirm {
  background-color: #E04F16;
  --swal2-action-button-focus-box-shadow: 0 0 0 3px rgba(224, 79, 22, 0.4);
}
.swal2-styled.swal2-cancel {
  background-color: #6b7280;
  --swal2-action-button-focus-box-shadow: 0 0 0 3px rgba(107, 114, 128, 0.4);
}
/* Nút phá vỡ (xoá · huỷ · trả lại · thu hồi · từ chối) — đỏ, cùng tông với `#d33` đang dùng. */
.swal2-styled.swal2-deny,
.swal2-styled.swal2-confirm.vt-swal-danger {
  background-color: #d33;
  --swal2-action-button-focus-box-shadow: 0 0 0 3px rgba(221, 51, 51, 0.4);
}

/* ---- Hiển thị nội dung NHẬP TỪ TEXTAREA giữ nguyên xuống dòng/khoảng trắng như lúc nhập.
   Dùng cho mọi nơi HIỂN THỊ (read-only) nội dung dài: mô tả, báo cáo, ghi chú, lý do…
   pre-wrap giữ cả xuống dòng lẫn khoảng trắng; kết hợp {{ }} (escaped) nên an toàn, không cần
   sanitize. word-break để chuỗi dài không tràn khung. ---- */
.vt-multiline {
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
}

/* ===== 7. SINH NHẬT — box trên trang Tổng quan + popup chúc mừng =====
   Màu accent lấy đúng cam thương hiệu đang dùng cho header bảng: rgb(224,79,22) → #fe9f43.
   Tiền tố .vt-bd-* để không đụng class nào của theme. */

.vt-bd-card .vt-bd-tabs .nav-link {
  padding: 0.15rem 0.6rem;
  font-size: 0.78rem;
  border-radius: 999px;
  color: #6b7280;
}
.vt-bd-card .vt-bd-tabs .nav-link.active {
  background: rgb(224, 79, 22);
  color: #fff;
}

/* Vùng cuộn: giữ box không kéo dài trang dù nhiều người sinh nhật. */
.vt-bd-scroll {
  max-height: 360px;
  overflow-y: auto;
}

/* ---- Khối HÔM NAY: điểm nhấn của cả box ---- */
.vt-bd-today {
  background: linear-gradient(135deg, rgb(224, 79, 22), #fe9f43);
  color: #fff;
  padding: 0.65rem 0.75rem 0.5rem;
}
.vt-bd-today-head {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  opacity: 0.95;
  margin-bottom: 0.4rem;
}
.vt-bd-today .vt-bd-sub { color: rgba(255, 255, 255, 0.85); }
.vt-bd-today .vt-bd-avatar { border-color: rgba(255, 255, 255, 0.85); }

/* ---- Dòng danh sách ---- */
.vt-bd-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid #f1f2f4;
}
.vt-bd-row:last-child { border-bottom: 0; }
.vt-bd-row-today { border-bottom-color: rgba(255, 255, 255, 0.25); }
.vt-bd-row-past { opacity: 0.55; }
.vt-bd-row-mark { background: #fff7f2; font-weight: 600; }

.vt-bd-info { flex: 1 1 auto; min-width: 0; }
.vt-bd-name {
  font-weight: 700;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vt-bd-name-sm {
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vt-bd-sub {
  font-size: 0.75rem;
  color: #8a94a6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vt-bd-when {
  flex: 0 0 auto;
  font-size: 0.75rem;
  color: #6b7280;
  white-space: nowrap;
}
.vt-bd-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgb(224, 79, 22);
}

/* ---- Ảnh đại diện (ảnh thật hoặc chữ cái đầu) ---- */
.vt-bd-avatar {
  flex: 0 0 auto;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
}
.vt-bd-avatar-text {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #ffe3d3;
  color: rgb(224, 79, 22);
  font-weight: 700;
  text-transform: uppercase;
}

.vt-bd-section-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: #9ca3af;
  padding: 0.55rem 0.75rem 0.2rem;
}
.vt-bd-greet, .vt-bd-done { flex: 0 0 auto; white-space: nowrap; }
.vt-bd-greet { font-size: 0.75rem; }

.vt-bd-empty {
  text-align: center;
  color: #9ca3af;
  padding: 2rem 1rem;
}
.vt-bd-empty i { font-size: 26px; display: block; margin-bottom: 0.4rem; }

/* Cột phải bám theo tầm mắt khi cuộn (chỉ trên màn rộng — mobile box tự xuống dưới).
   ★★ 10/08/2026 — CHUYỂN TỪ CARD LÊN CỘT. Trước đó quy tắc này nằm trên `.vt-bd-card`, hồi đó box Sinh
   nhật là card DUY NHẤT của cột nên không ai thấy vấn đề. Khi thêm box Bản tin nội bộ lên trên, Sinh nhật
   thành phần tử THỨ HAI: nó chỉ bắt đầu dính SAU KHI card trên đã cuộn khuất, để lại một khoảng trống rồi
   giật lên — hỏng thấy được bằng mắt mà không lỗi nào báo.
   ⚠ Nếu sau này cột cao hơn màn hình (thêm card thứ ba) thì phần dưới sẽ không bao giờ cuộn tới được —
   lúc đó GỠ HẲN sticky, tuyệt đối không quay lại kiểu "dính trên card thứ N". */
@media (min-width: 1200px) {
  .vt-side-sticky {
    /* ★★ `align-self: flex-start` BẮT BUỘC, không phải cho đẹp. `.row` của Bootstrap là flex container
       với `align-items: stretch` mặc định, nên cột con bị kéo cao BẰNG CẢ HÀNG. Một phần tử đã cao bằng
       vùng cuộn của nó thì `position: sticky` không có chỗ nào để dính — quy tắc vẫn áp dụng, trình duyệt
       vẫn báo `position: sticky`, mà cuộn thì không thấy gì xảy ra. Đây đúng là lý do quy tắc cũ đặt trên
       CARD (`.vt-bd-card`) thì chạy được: card nằm trong cột nên không bị stretch.
       Đo bằng mắt sau khi thêm dòng này (user báo 10/08: "chưa stick được"). */
    align-self: flex-start;
    position: sticky;
    top: 84px;
  }
}

/* ---- POPUP chúc mừng (THẢ TỪ TRÊN XUỐNG, giữa màn hình) ----
   Không đặt ở góc phải: trên trang Tổng quan, box sinh nhật nằm đúng cột phải nên popup sẽ che chính
   nội dung mà nó nhắc tới (đã thấy khi chạy thử). Giữa trên thì tránh cả sidebar lẫn box, và rơi
   xuống ngay tầm mắt. `top` chừa chỗ cho thanh tiêu đề. */
.vt-bd-popup {
  position: fixed;
  left: 50%;
  /* Căn giữa bằng margin âm chứ KHÔNG bằng translateX(-50%): animate__bounceInDown cũng dùng transform
     nên hai thứ đè nhau, popup sẽ nhảy ngang trong lúc rơi. */
  margin-left: -170px;
  top: 76px;
  /* ★ PHẢI thấp hơn SweetAlert2 (1060) và modal Bootstrap (1055): để 1080 như ban đầu thì popup đè lên
     chính hộp thoại "Gửi lời chúc" mà nó mở ra — hộp thoại trông như bị cắt mất. */
  z-index: 1035;
  width: 340px;
  border-radius: 16px;
  overflow: hidden;
  /* Nội dung dài (nhiều người sinh nhật) vẫn nằm gọn trong màn hình thay vì tràn ra ngoài. */
  max-height: calc(100vh - 100px);
  display: flex;
  flex-direction: column;
  box-shadow: 0 18px 40px rgba(224, 79, 22, 0.18), 0 4px 12px rgba(0, 0, 0, 0.08);
  background: #fff;
}
.vt-bd-popup-head {
  background: linear-gradient(135deg, rgb(224, 79, 22), #fe9f43);
  color: #fff;
  padding: 0.7rem 0.85rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 0 0 auto;
}
.vt-bd-popup-close {
  margin-left: auto;
  background: transparent;
  border: 0;
  color: #fff;
  opacity: 0.9;
  line-height: 1;
  transition: opacity 0.15s ease;
}
.vt-bd-popup-close:hover { opacity: 1; }
.vt-bd-popup-body {
  padding: 0.75rem 0.85rem;
  overflow-y: auto;       /* nhiều người sinh nhật ⇒ cuộn trong popup, không tràn màn hình */
}
.vt-bd-popup-body .vt-bd-row { padding-left: 0; padding-right: 0; }

/* Đóng popup: mờ dần + trôi nhẹ lên thay vì biến mất đột ngột. */
.vt-bd-popup.vt-bd-closing {
  opacity: 0;
  transform: translateY(-12px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

/* Ngày–tháng in cạnh tên. */
.vt-bd-date {
  font-weight: 500;
  font-size: 0.78rem;
  opacity: 0.75;
  margin-left: 0.25rem;
  white-space: nowrap;
}

/* Màn hẹp: trải gần hết bề ngang, bỏ căn giữa bằng margin âm. */
@media (max-width: 420px) {
  .vt-bd-popup {
    left: 16px;
    right: 16px;
    margin-left: 0;
    width: auto;
  }
}

/* Lớp pháo giấy phủ toàn màn, KHÔNG chặn thao tác chuột.
   z-index nằm NGAY DƯỚI SweetAlert2 (1060): pháo vẫn rơi rõ phía sau hộp "Đã gửi lời chúc" mà không
   che mất chữ trong hộp. */
.vt-bd-confetti {
  position: fixed;
  inset: 0;
  z-index: 1059;
  pointer-events: none;
}

/* Dòng "Cần tôi xử lý" — nền nhạt khi rê chuột. Đọc cùng biến với luật rê chuột dòng bảng: đây cũng là
   một DANH SÁCH DÒNG, chỉ khác nó không dựng bằng thẻ `<table>`. */
.vt-hover-soft:hover { background: var(--vt-row-hover); }

/* ---- Hộp thoại GỬI LỜI CHÚC (SweetAlert2 tuỳ biến) ----
   Hộp mặc định chỉ có tiêu đề + ô nhập trơ nên nhìn thô. Ở đây thêm ảnh + tên người nhận và vài lời
   chúc mẫu bấm-là-điền; nút cũng theo màu thương hiệu thay vì màu mặc định của thư viện. */
.swal2-popup.vt-bd-swal {
  width: 420px;
  max-width: calc(100vw - 32px);
  border-radius: 16px;
  padding: 0 0 1.1rem;
  overflow: hidden;
}
.vt-bd-swal .swal2-html-container { margin: 0; padding: 0; text-align: left; }

.vt-bd-swal-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.15rem;
  background: linear-gradient(135deg, rgb(224, 79, 22), #fe9f43);
  color: #fff;
  margin-bottom: 1rem;
}
.vt-bd-swal-who { min-width: 0; }
.vt-bd-swal-name {
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vt-bd-swal-sub { font-size: 0.8rem; opacity: 0.9; }

.vt-bd-swal-input {
  display: block;
  width: calc(100% - 2.3rem);
  margin: 0 1.15rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid #e3e6ea;
  border-radius: 10px;
  font-size: 0.92rem;
  line-height: 1.5;
  resize: vertical;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.vt-bd-swal-input:focus {
  border-color: #fe9f43;
  box-shadow: 0 0 0 3px rgba(254, 159, 67, 0.18);
}

.vt-bd-swal-hint {
  padding: 0.75rem 1.15rem 0.35rem;
  font-size: 0.75rem;
  color: #9ca3af;
}
.vt-bd-swal-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0 1.15rem;
}
.vt-bd-chip {
  background: #f6f7f9;
  border: 1px solid #eceef1;
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font-size: 0.75rem;
  color: #4b5563;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.vt-bd-chip:hover { background: #fff3ec; border-color: #ffd9c4; color: rgb(224, 79, 22); }
.vt-bd-chip.active { background: #ffe3d3; border-color: #ffc8a8; color: rgb(224, 79, 22); font-weight: 600; }

.vt-bd-swal-ok, .vt-bd-swal-cancel {
  border: 0;
  border-radius: 10px;
  padding: 0.5rem 1.15rem;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.vt-bd-swal-ok { background: rgb(224, 79, 22); color: #fff; margin-right: 0.5rem; }
.vt-bd-swal-ok:hover { filter: brightness(1.08); }
.vt-bd-swal-cancel { background: #f1f2f4; color: #4b5563; }
.vt-bd-swal-cancel:hover { background: #e6e8eb; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   KHO TÀI LIỆU (.vt-dl-*) — bố cục một cột kiểu Google Drive: thanh trên · lưới/danh sách · bảng
   thông tin bên phải. Dùng biến màu và bo góc của theme, không tự chế bảng màu riêng.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */

/* Hai khu ngang hàng: Tài liệu dùng chung ⇄ Tài liệu cá nhân */
.vt-dl-tabs { border-bottom: 1px solid #e9eaec; margin-bottom: 0.85rem; gap: 0.25rem; }
.vt-dl-tabs .nav-link {
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: #6b7280;
  font-weight: 600;
  padding: 0.55rem 1rem;
  background: transparent;
}
.vt-dl-tabs .nav-link:hover { color: rgb(224, 79, 22); }
.vt-dl-tabs .nav-link.active { color: rgb(224, 79, 22); border-bottom-color: rgb(224, 79, 22); background: transparent; }

.vt-dl-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.vt-dl-crumbs .breadcrumb { background: transparent; padding: 0; font-size: 0.95rem; }
.vt-dl-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.vt-dl-search { position: relative; min-width: 220px; }
.vt-dl-search .form-control { border-radius: 999px; padding-left: 2.3rem; }
.vt-dl-search-icon {
  position: absolute;
  left: 0.85rem;
  top: 50%;
  transform: translateY(-50%);
  color: #9ca3af;
  pointer-events: none;
  font-size: 1rem;
}

/* Cụm chuyển chế độ: nút đang chọn tô nền chính và hiện dấu tích (giống Drive). */
.vt-dl-modes { border-radius: 999px; overflow: hidden; border: 1px solid #e5e7eb; }
.vt-dl-modes .btn {
  border: 0;
  background: #fff;
  color: #6b7280;
  padding: 0.4rem 0.85rem;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.vt-dl-modes .btn:hover { background: #f3f4f6; }
.vt-dl-modes .btn.active { background: rgb(224, 79, 22); color: #fff; }
.vt-dl-mode-check { display: none; font-size: 0.85rem; }
.vt-dl-modes .btn.active .vt-dl-mode-check { display: inline-block; }
.vt-dl-info-btn {
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  background: #fff;
  color: #6b7280;
  padding: 0.4rem 0.7rem;
}
.vt-dl-info-btn:hover { background: #f3f4f6; color: rgb(224, 79, 22); }

/* Thân: nội dung + bảng thông tin */
.vt-dl-body { display: flex; align-items: flex-start; gap: 1rem; }
.vt-dl-main { flex: 1 1 auto; min-width: 0; }
.vt-dl-info { flex: 0 0 320px; max-width: 320px; position: sticky; top: 80px; }
.vt-dl-info-body { max-height: 70vh; overflow: auto; }
.vt-dl-info-head { display: flex; align-items: center; gap: 0.6rem; font-weight: 600; margin-bottom: 0.5rem; }
.vt-dl-info-head i { font-size: 1.6rem; color: rgb(224, 79, 22); }
.vt-dl-props { border-top: 1px solid #f1f2f4; }
.vt-dl-prop {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid #f1f2f4;
  font-size: 0.85rem;
}
.vt-dl-prop span { color: #6b7280; }
.vt-dl-shares { list-style: none; padding: 0; margin: 0; }
.vt-dl-shares li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid #f1f2f4;
  font-size: 0.85rem;
}
.vt-dl-activity { list-style: none; padding: 0; margin: 0; }
.vt-dl-activity li { padding: 0.5rem 0; border-bottom: 1px solid #f1f2f4; }

/* Lưới */
.vt-dl-section-title {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #9ca3af;
  margin: 0.5rem 0 0.6rem;
}
.vt-dl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}
.vt-dl-grid-files { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
/* ★ KHÔNG đặt `overflow: hidden` ở đây: menu ⋮ là con của thẻ, thẻ mà cắt nội dung thì menu bị xén
   mất một nửa. Việc bo góc ảnh xem trước để `.vt-dl-thumb` tự lo. */
.vt-dl-card {
  position: relative;
  background: #fff;
  border: 1px solid #e9eaec;
  border-radius: 12px;
  transition: box-shadow 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
  cursor: pointer;
}
.vt-dl-card:hover { border-color: #ffd9c4; box-shadow: 0 4px 14px rgba(17, 24, 39, 0.07); }
.vt-dl-card:focus-visible { outline: 2px solid rgb(224, 79, 22); outline-offset: 2px; }
.vt-dl-card-folder { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 0.8rem; }
.vt-dl-card-icon { font-size: 1.5rem; color: #f2b544; flex: 0 0 auto; }
.vt-dl-card-text { min-width: 0; flex: 1 1 auto; }
.vt-dl-card-name {
  font-weight: 600;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vt-dl-card-sub { font-size: 0.75rem; color: #9ca3af; }

/* Menu ⋮ — nút tròn nhạt, nổi rõ ở mọi dòng để người dùng biết thư mục nào cũng thao tác được. */
.vt-dl-card-menu { flex: 0 0 auto; }
.vt-dl-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  color: #6b7280;
  line-height: 1;
}
.vt-dl-menu-btn:hover,
.vt-dl-menu-btn[aria-expanded="true"] { background: #f3f4f6; color: rgb(224, 79, 22); }
/* Menu neo bằng chiến lược "fixed" (data-bs-strategy) nên thoát khỏi khung cuộn của bảng; nâng lớp
   để nó không chui xuống dưới thanh chọn nhiều hay bảng Thông tin. */
.vt-dl-main .dropdown-menu,
.vt-dl-table .dropdown-menu { z-index: 1056; }

/* Thẻ tệp có ảnh xem trước */
.vt-dl-card-file { display: flex; flex-direction: column; }
.vt-dl-file-head { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.7rem; }
.vt-dl-file-head > i { font-size: 1.1rem; }
.vt-dl-thumb {
  height: 150px;
  background: #f7f8fa;
  border-top: 1px solid #f1f2f4;
  border-bottom: 1px solid #f1f2f4;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* Trang đầu PDF lấp đầy khung và neo mép TRÊN (như Drive) — canvas A4 mà để "contain" thì bị
   chiều cao 150px bóp lại còn một dải hẹp giữa khung, nhìn trống trải. Ảnh thật thì giữ "contain"
   để không cắt mất nội dung. */
.vt-dl-thumb canvas { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.vt-dl-thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
.vt-dl-thumb-fallback { font-size: 2.4rem; color: #cbd0d6; }

/* Danh sách */
.vt-dl-table thead th { font-size: 0.8rem; color: #6b7280; white-space: nowrap; }
.vt-dl-sort { cursor: pointer; user-select: none; }
.vt-dl-sort:hover { color: rgb(224, 79, 22); }
.vt-dl-row { cursor: pointer; }

/* Trạng thái */
.vt-dl-empty { text-align: center; padding: 3rem 1rem; }
.vt-dl-empty i { font-size: 2.6rem; color: #cbd0d6; display: block; margin-bottom: 0.6rem; }
.vt-dl-skeleton { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.75rem; }
.vt-dl-skel-card {
  height: 76px;
  border-radius: 12px;
  background: linear-gradient(90deg, #f3f4f6 25%, #e9eaec 37%, #f3f4f6 63%);
  background-size: 400% 100%;
  animation: vt-dl-shimmer 1.3s ease-in-out infinite;
}
@keyframes vt-dl-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.vt-dl-selbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: #fff3ec;
  border: 1px solid #ffd9c4;
  border-radius: 10px;
  padding: 0.5rem 0.85rem;
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
}
.vt-dl-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border-top: 1px solid #f1f2f4;
  margin-top: 1rem;
  padding-top: 0.75rem;
  font-size: 0.8rem;
  color: #6b7280;
}
.vt-dl-footer:empty { display: none; }
/* Thanh phần trăm hạn mức kho cá nhân */
.vt-dl-quota { display: inline-flex; align-items: center; gap: 0.5rem; }
.vt-dl-quota-bar {
  display: inline-block;
  width: 120px;
  height: 6px;
  border-radius: 999px;
  background: #eef0f3;
  overflow: hidden;
}
.vt-dl-quota-bar i {
  display: block;
  height: 100%;
  background: rgb(224, 79, 22);
  transition: width 0.25s ease;
}

/* Vùng kéo thả tệp */
.vt-dl-drop {
  border: 2px dashed #e0e2e6;
  border-radius: 12px;
  padding: 1.5rem;
  text-align: center;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.vt-dl-drop i { font-size: 2rem; color: #cbd0d6; display: block; margin-bottom: 0.4rem; }
.vt-dl-drop-on { border-color: rgb(224, 79, 22); background: #fff7f3; }
.vt-dl-filelist { list-style: none; padding: 0; margin: 0.75rem 0 0; max-height: 160px; overflow: auto; }
.vt-dl-filelist li {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid #f1f2f4;
  font-size: 0.85rem;
}

/* Trình xem tài liệu */
.vt-dl-viewer .modal-header { gap: 0.75rem; padding-right: 1rem; }
/* Theme neo nút đóng ra góc bằng position:absolute nên nó ĐÈ lên nút "Tải về"; kéo về dòng chảy
   bình thường để hai nút đứng cạnh nhau. */
.vt-dl-viewer .modal-header .btn-close { position: static; margin: 0 0 0 0.25rem; flex: 0 0 auto; }
.vt-dl-viewer-body { background: #52565c; padding: 1rem; overflow: auto; }
.vt-dl-viewer-stage { display: flex; align-items: flex-start; justify-content: center; min-height: 100%; }

/* PDF hiển thị CUỘN LIÊN TỤC: các trang xếp dọc, canh giữa theo bề ngang. Ảnh và thông báo vẫn dùng
   `.vt-dl-viewer-stage` gốc (canh giữa cả hai chiều) nên lớp này chỉ thêm cho nhánh PDF. */
.vt-dl-viewer-stage-pdf { flex-direction: column; align-items: center; gap: 1rem; }
/* Khung của một trang: dựng trước khi vẽ để thanh cuộn đúng độ dài ngay lúc mở và không nhảy khi cuộn. */
.vt-dl-page {
  background: #fff;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
  border-radius: 4px;
  flex: 0 0 auto;
  max-width: 100%;
}
.vt-dl-page > canvas { display: block; max-width: 100%; height: auto; border-radius: 4px; }
.vt-dl-canvas, .vt-dl-viewer-img {
  max-width: 100%;
  background: #fff;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
  border-radius: 4px;
}
.vt-dl-viewer .vt-dl-empty { background: #fff; border-radius: 12px; width: min(520px, 92%); margin: auto; }

/* Màn hẹp: bảng thông tin trượt toàn màn, lưới co lại */
@media (max-width: 991.98px) {
  .vt-dl-body { flex-direction: column; }
  .vt-dl-info {
    position: fixed;
    inset: 0;
    z-index: 1045;
    max-width: none;
    flex: none;
    background: #fff;
    padding: 0.75rem;
    overflow: auto;
  }
  .vt-dl-search { min-width: 150px; flex: 1 1 auto; }
}
@media (max-width: 575.98px) {
  .vt-dl-grid, .vt-dl-grid-files { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .vt-dl-thumb { height: 110px; }
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════
   SỔ VĂN BẢN PHÁP LUẬT (.vt-legal-*)
   ══════════════════════════════════════════════════════════════════════════════════════════════════
   Chỉ 4 quy tắc, mỗi quy tắc vá một thứ theme KHÔNG có sẵn. Bố cục, thẻ, badge, lưới đều dùng lớp
   chuẩn của theme — không dựng lại. */

/* Theme đặt `white-space: nowrap` cho ô bảng ⇒ trích yếu dài (tới 1000 ký tự) kéo cột rộng ra và đẩy
   cột Thao tác khỏi tầm nhìn. Đây là cột nội dung, phải xuống dòng. */
.vt-legal-table td { white-space: normal; word-break: break-word; }
.vt-legal-table th { white-space: nowrap; }

/* Trích yếu ở màn chi tiết là tiêu đề DÀI (không phải một dòng ngắn như tên bản ghi thường). */
.vt-legal-title { line-height: 1.5; word-break: break-word; }

/* Bảng thuộc tính nhãn|giá trị: giãn dòng cho dễ đọc, và kẻ nhạt giữa các hàng như bản thiết kế. */
.vt-legal-props dt, .vt-legal-props dd { padding: 0.5rem 0; margin-bottom: 0; border-bottom: 1px solid var(--bs-border-color, #e9ecef); }
.vt-legal-props dt:last-of-type, .vt-legal-props dd:last-of-type { border-bottom: 0; }

/* Khối "Các văn bản khác": bỏ kẻ ở mục cuối để không thừa một đường sát đáy thẻ. */
.vt-legal-related:last-child { border-bottom: 0 !important; padding-bottom: 0 !important; margin-bottom: 0 !important; }

/* ══════════════════════════════════════════════════════════════════════════════════════════════════
   CHÂN TRANG (.vt-footer-wrap)
   ══════════════════════════════════════════════════════════════════════════════════════════════════
   `resources/js/script.js` của theme:

       $(window).resize(function () {
           if ($('.page-wrapper').length > 0) { $(".page-wrapper").css("min-height", $(window).height()); }
       });

   Nó gán chiều cao CẢ MÀN HÌNH cho MỌI `.page-wrapper`. Khối chân trang cũng mang class đó (bắt buộc,
   để hưởng `margin-left` né sidebar và tự co khi thu gọn sidebar), nên mỗi lần người dùng đổi kích thước
   cửa sổ thì chân trang phình lên một màn hình ⇒ trang dài gấp đôi, hở một mảng trắng lớn dưới chân
   trang. Đo được: trang 1800px trong khi nội dung chỉ 906px.

   ★ Khử ở ĐÂY chứ không sửa `script.js` — đó là tệp của template, sửa nó là đổi hành vi của mọi màn.
   ★ Phải có `!important`: JS ghi min-height dạng INLINE, quy tắc thường không thắng được.

   `margin-top`: theme đặt `.page-wrapper .content { padding: 24px; padding-bottom: 0 }` — cố ý bỏ đệm
   dưới vì trước đây layout KHÔNG có chân trang, mọi trang cụt ở đáy. Nay có chân trang thì nội dung
   chạm thẳng vào nó: đo được `content.bottom` = `chân trang.top` = cùng một toạ độ, nên dòng cuối của
   card (ví dụ "Dung lượng: 0 tài liệu · 0 MB" ở Tài liệu phòng ban) dính sát vạch chân trang, nhìn như
   bị đè lên nhau (user báo 08/08).
   Đặt 1.5rem = 24px cho khớp nhịp đệm 24px mà theme dùng cho ba phía còn lại của `.content`.
   ★ Đặt ở chân trang chứ không trả `padding-bottom` cho `.content`: `.content` là lớp của theme, dùng
   ở mọi màn; khối chân trang là phần MÌNH thêm nên sửa ở đây là phạm vi hẹp nhất. */
.vt-footer-wrap { min-height: 0 !important; margin-top: 1.5rem; }

/* ============================================================================
   NỘI DUNG CÓ ĐỊNH DẠNG (.vt-rich-view) — DÙNG CHUNG cho mọi nơi hiển thị HTML người dùng soạn
   ============================================================================
   Dùng ở: bản tin nội bộ (`.vt-bt-body`, tên cũ giữ lại để không phải sửa màn đang chạy) và mô tả nhóm
   công việc. Màn nào mở trình soạn thảo `vt-richtext` thì màn hiển thị PHẢI mang một trong hai lớp này —
   nếu không, danh sách gạch đầu dòng người dùng gõ hiện ra thành mấy dòng chữ rời (xem lý do ngay dưới).
   ★ Vì sao cần khối này: theme reset `ul, ol { list-style: none; padding-left: 0 }` cho toàn trang (nó
   dùng danh sách để dựng menu, không phải để trình bày văn bản). Hệ quả là danh sách người dùng gõ trong
   trình soạn thảo hiện ra như những dòng chữ rời — thấy được ngay trên bản tin đầu tiên có gạch đầu dòng.
   Trả lại kiểu mặc định CHỈ trong phạm vi `.vt-bt-body` để không đụng tới menu hay bất kỳ danh sách nào
   khác của theme.

   ⚠ Nội dung ở đây là HTML người dùng nhập, đã qua `App\Core\Security\Html\HtmlSanitizer` (danh sách
   TRẮNG). Danh sách thẻ được phép bên đó và các quy tắc dưới đây phải đi cùng nhau: mở thêm thẻ mà quên
   thêm kiểu là ra một thẻ hiển thị trần trụi. */
.vt-bt-body,
.vt-rich-view { line-height: 1.7; }
.vt-bt-body ul, .vt-bt-body ol,
.vt-rich-view ul, .vt-rich-view ol { list-style: revert; padding-left: 1.75rem; margin-bottom: 1rem; }
.vt-bt-body li,
.vt-rich-view li { margin-bottom: 0.25rem; }
.vt-bt-body p,
.vt-rich-view p { margin-bottom: 0.85rem; }
.vt-bt-body p:last-child,
.vt-rich-view p:last-child { margin-bottom: 0; }

/* ============================================================================
   NHÃN TRẠNG THÁI (.badge) — CHUẨN CHUNG CHO TOÀN HỆ THỐNG
   ============================================================================
   ★ Khai MỘT chỗ duy nhất, mọi phân hệ dùng chung. Sửa nhãn ở đâu đó khác là bắt đầu trôi lệch.

   Hai lỗi của theme sửa ở đây, cả hai đều lộ ra ngay trên tiêu đề phiếu giao việc:

   ① `font-size: 0.75em` — đơn vị `em` nên nhãn PHÌNH THEO cỡ chữ của thẻ chứa nó. Cùng một nhãn "Mới giao"
      hiện 10,5px trong bảng nhưng 13,5px khi đặt cạnh tiêu đề `h3` — to gần bằng chính tiêu đề, hút hết mắt
      người đọc về phía một thông tin phụ. Đổi sang `rem` để nhãn CÓ MỘT CỠ DUY NHẤT ở mọi chỗ.

   ② `text-transform: capitalize` — viết hoa chữ cái đầu của TỪNG TỪ. Với tiếng Anh thì vô hại, với tiếng
      Việt thì sai chính tả: "Mới giao" thành "Mới Giao", "Đang hoạt động" thành "Đang Hoạt Động". Nhãn đã
      được viết đúng sẵn trong `StatusCatalog`/`WorkTask::STATUSES`, việc của CSS là đừng đụng vào.

   Thêm `line-height: 1.35`: theme để `line-height` bằng đúng `font-size`, nên dấu mũ và dấu thanh tiếng Việt
   (ữ, ế, ộ) chạm sát mép trên của nhãn.

   ⚠ KHÔNG dùng `!important` — tệp này nạp sau `style.css` nên cùng độ ưu tiên là đã thắng. Các lớp tiện ích
   như `.rounded-pill` vẫn đè lại được bo góc, đúng như mong đợi cho nhãn đếm số. */
.badge {
    /* 9,6px — NHỎ HƠN HẲN chữ thường trong bảng (.75rem/12px). Nhãn là thông tin phụ đi kèm một dòng dữ
       liệu; để nó ngang cỡ chữ chính thì mắt đọc nhãn trước, đọc nội dung sau. Đây là ngưỡng dưới: nhỏ hơn
       nữa thì dấu tiếng Việt (ữ, ế, ộ) bắt đầu dính vào nhau ở màn hình không HiDPI. */
    font-size: 0.6rem;
    font-weight: 500;
    line-height: 1.35;
    padding: 0.15rem 0.4rem;
    border-radius: 0.3rem;
    text-transform: none;
    letter-spacing: 0;
    vertical-align: middle;
}

/* Nhãn đếm số (thông báo, số việc con): tròn đều, không kéo dài theo chữ. */
.badge.rounded-pill {
    padding: 0.15rem 0.4rem;
}

/* ---- TIÊU ĐỀ THẺ (.card-title) — cùng lỗi capitalize như .badge -------------
   Theme khai `.card .card-title { text-transform: capitalize }`, tức viết hoa chữ đầu của TỪNG TỪ.
   Quy tắc đó thuộc tiếng Anh; tiếng Việt chỉ viết hoa chữ đầu câu và tên riêng. Hệ quả thấy trên mọi
   màn hình: "Thể thức văn bản" hiện thành "Thể Thức Văn Bản", "Cơ quan ban hành" thành "Cơ Quan Ban
   Hành". Nhãn đã được viết ĐÚNG sẵn trong Blade — việc của CSS là đừng đụng vào.

   Đây là chỗ thứ ba sửa cùng một lỗi của theme, sau `.badge` (ngay trên) và `.fc-button` (nút lịch,
   "Hôm nay" → "Hôm Nay"). Ai gặp lại triệu chứng này ở một lớp khác thì thêm vào đây, đừng vá lẻ
   trong từng màn.

   ⚠ Phải khai ĐỦ CẢ HAI selector với đúng độ đặc hiệu của theme (`0,2,0` và `0,4,0`). Chỉ viết
   `.card-title { text-transform: none }` thì thua `.card .card-title` và không có gì báo lỗi.
   ⚠ KHÔNG cần `!important` — tệp này nạp sau `style.css`, cùng đặc hiệu là đã thắng. */
.card .card-title,
.card.custom-card .card-header .card-title {
    text-transform: none;
}

/* ---- Bảng màu nhãn trạng thái ----------------------------------------------
   Bộ `bg-soft-*` của theme có ba khuyết tật, thấy rõ nhất trên tiêu đề phiếu giao việc:

   ① `.bg-soft-secondary` nền `#B0BBC7` — xám ĐẶC, đậm hơn cả chữ xung quanh, nên nhãn trạng thái phổ biến
      nhất của hệ thống ("Mới giao", "Trung bình") trông như một mảng bê tông dán vào tiêu đề.
   ② Chữ nhạt hơn nền cần thiết: `.bg-soft-warning` để chữ `#FFCA18` trên nền `#FFF0CA` — vàng trên vàng,
      đọc được hay không tuỳ màn hình. `.bg-soft-success` cũng vậy (`#3EB780` trên `#CBEFD4`).
   ③ Chỉ có nền phẳng, không viền — nên nhãn nào cũng phải tô đậm nền mới "nhìn thấy được", và đó chính là
      thứ làm giao diện nặng.

   Cách chữa: nền TINT rất nhạt + chữ cùng tông nhưng ĐẬM (đủ tương phản để đọc) + viền 1px cùng họ màu.
   Viền gánh phần việc "tách nhãn khỏi nền" thay cho màu nền, nên nhãn nhẹ đi mà vẫn rõ. Bo tròn hẳn thành
   viên thuốc: cạnh vuông ở cỡ chữ 11px trông gãy gọn quá mức cho một thông tin phụ.

   ⚠ Giữ nguyên TÊN lớp của theme (`bg-soft-*`) — hàng trăm chỗ trong 12 phân hệ đang gọi chúng, và
   `StatusCatalog` sinh ra đúng những tên này. Chỉ đổi giá trị màu. */
.badge[class*="bg-soft-"] {
    border: 1px solid transparent;
    border-radius: 999px;
    padding: 0.1rem 0.5rem;
}

.badge.bg-soft-secondary { background-color: #F1F3F6; color: #59677A; border-color: #E0E5EC; }
.badge.bg-soft-primary   { background-color: #FFF3EA; color: #C25A11; border-color: #FADFC8; }
.badge.bg-soft-success   { background-color: #E9F7EF; color: #1E7F4F; border-color: #C6E9D5; }
.badge.bg-soft-danger    { background-color: #FDECEA; color: #C0201C; border-color: #F6D2CD; }
.badge.bg-soft-warning   { background-color: #FFF6E0; color: #8A6400; border-color: #F5E2AE; }
.badge.bg-soft-info      { background-color: #EBF2FE; color: #1553C7; border-color: #D2E0FA; }
.badge.bg-soft-orange    { background-color: #FDF0EA; color: #C2440F; border-color: #F6D8C8; }
.badge.bg-soft-pink      { background-color: #FDEEF5; color: #B31D75; border-color: #F7D2E5; }
.badge.bg-soft-indigo    { background-color: #EFEEFB; color: #37209E; border-color: #DAD6F4; }
.badge.bg-soft-skyblue   { background-color: #E6F8FD; color: #0E7490; border-color: #C6EDF7; }
.badge.bg-soft-light     { background-color: #F8F9FA; color: #646B72; border-color: #E9ECEF; }

/* Nhãn nền ĐẶC (đếm số, cảnh báo trên chuông): giữ nền đậm vì chúng cần đập vào mắt, chỉ hạ độ chói của
   đỏ nguyên chất `#FF0000` mà theme đang dùng — màu đó không có trong bảng nhận diện nào của dự án. */
.badge.bg-danger { background-color: #E5484D !important; }

/* ============================================================================
   KÉO ĐỔI BỀ RỘNG CỘT — CHO MỌI BẢNG BLADE TĨNH (`data-vt-col-resize`)
   ============================================================================
   ★★★ Anh Dũng chốt 30/08/2026: *"Không cần đóng băng cũng được vì nó ít cột, cho phép co dãn cột
     giống excel là được"*.

   ★ VÌ SAO KHAI Ở ĐÂY. Cơ chế kéo cột đã tồn tại trong dự án, nhưng bị khoá trong bảng ĐỘNG của màn
     *Việc của tôi* (`.wt-resizer` ở `work/tasks/_index-css`, gắn với `state.widths` của lưới JS). Mọi
     bảng Blade tĩnh — và có hàng chục bảng như thế — ⛔ không dùng lại được dòng nào.
   ⚠ NỢ ĐÃ BIẾT: sau bước này dự án có HAI bản cơ chế kéo cột. ⛔ Đừng để yên — việc gom bảng `wt-grid`
     về dùng chung partial `layout/partials/vt-col-resize` phải được trình thành một mốc riêng.

   ⚠ `table-layout:fixed` là BẮT BUỘC khi đã kéo: thiếu nó thì trình duyệt vẫn tự chia lại bề rộng theo
     nội dung và con số người dùng vừa kéo bị bỏ qua ngay khung hình sau.
   ⚠ Tay kéo `position:absolute` ⇒ ô tiêu đề phải có `position:relative`, khai kèm ngay dưới. */
table[data-vt-col-resize] > thead > tr > th { position: relative; }

.vt-col-resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    /* Vùng bấm 6px là hẹp với chuột; nới vùng NHẠY ra hai bên mà ⛔ không nới vệt nhìn thấy. */
    box-sizing: content-box;
}

.vt-col-resizer:hover,
.vt-col-resizing .vt-col-resizer { background: rgba(255, 255, 255, .45); }

/* Khi đang kéo, con trỏ phải giữ nguyên hình mũi tên ngang trên TOÀN TRANG — chuột đi ra ngoài ô tiêu
   đề giữa chừng là chuyện bình thường, và con trỏ nhảy về hình khác làm người dùng tưởng đã nhả. */
body.vt-col-resizing { cursor: col-resize; user-select: none; }

/* ============================================================================
   DẢI THÔNG BÁO NỀN NHẠT — `.alert-soft-*`
   ============================================================================
   🔴 VÌ SAO CÓ KHỐI NÀY (đo thật 30/08/2026). Anh Dũng nhìn màn *Báo cáo theo yêu cầu* và nói
   *"giao diện không giống ai"*. Đo `getComputedStyle` trên trình duyệt thật: **cả sáu** lớp
   `.alert-soft-info|warning|danger|success|primary|secondary` cho ra nền `rgba(0,0,0,0)` và chữ xám
   mặc định — tức **KHÔNG stylesheet nào định nghĩa chúng**. Theme chỉ có `bg-soft-*`, ⛔ không có
   `alert-soft-*`; ai đó đã suy ra tên lớp theo cảm tính và ⛔ không ai mở màn ra kiểm.

   ⇒ Hậu quả: **20 tệp Blade** ở 5 phân hệ (Công việc · Báo cáo · Nhân sự · Tài sản · Hệ thống) đang
   bày dải cảnh báo dưới dạng **chữ trần** — không nền, không viền, không màu, nên một lời cảnh báo
   quan trọng trông y hệt một đoạn văn lạc.

   ★ SỬA MỘT CHỖ, ⛔ KHÔNG SỬA 20 TỆP (anh Dũng chốt 30/08). Đổi tên lớp ở từng màn là 20 lượt sửa,
     và màn thứ 21 viết sau lại sai tiếp. Khai ở đây thì mọi nơi đã gọi đúng tên đều đẹp lại.
   ⚠ MÀU LẤY NGUYÊN từ bảng `.badge.bg-soft-*` ngay trên — hai thứ đứng cạnh nhau trên cùng một màn
     (nhãn trạng thái và dải thông báo), lệch tông là nhìn ra ngay. ⛔ Đừng đặt bảng màu thứ hai.
   ⚠ ⛔ KHÔNG dùng `!important`: `.alert-soft-*` phải nhường khi một màn cần đè, đúng như `.alert-*`
     của Bootstrap. Độ đặc hiệu ở đây đã đủ vì theme ⛔ không hề khai lớp này.
   ⚠ Dải cảnh báo ⛔ không bo tròn kiểu viên thuốc như badge — nó là một KHỐI văn bản, giữ `radius`
     mặc định của `.alert`. */
.alert[class*="alert-soft-"] { border: 1px solid transparent; }

.alert.alert-soft-secondary { background-color: #F1F3F6; color: #59677A; border-color: #E0E5EC; }
.alert.alert-soft-primary   { background-color: #FFF3EA; color: #C25A11; border-color: #FADFC8; }
.alert.alert-soft-success   { background-color: #E9F7EF; color: #1E7F4F; border-color: #C6E9D5; }
.alert.alert-soft-danger    { background-color: #FDECEA; color: #C0201C; border-color: #F6D2CD; }
.alert.alert-soft-warning   { background-color: #FFF6E0; color: #8A6400; border-color: #F5E2AE; }
.alert.alert-soft-info      { background-color: #EBF2FE; color: #1553C7; border-color: #D2E0FA; }

/* Chữ phụ bên trong dải phải ĂN THEO tông của dải, ⛔ không giữ xám mặc định của `.text-muted`: xám
   lạnh nằm trên nền vàng/xanh nhạt trông như chữ bị lỗi. Hạ độ đậm bằng `opacity` để một lần khai là
   đúng cho cả sáu tông — ⛔ không phải liệt kê sáu mã màu phụ. */
.alert[class*="alert-soft-"] .text-muted { color: inherit !important; opacity: .78; }

/* ============================================================================
   CỠ CHỮ BẢNG DỮ LIỆU — CHUẨN CHUNG CHO MỌI `.table` VÀ MỌI DATATABLE
   ============================================================================
   ★ Khai MỘT chỗ, áp cho toàn hệ thống. Trước 12/08/2026 mỗi màn tự đặt cỡ chữ cho bảng của mình, và không
   màn nào ăn: theme khai `.table > :not(caption) > * > * { font-size: 14px }` — tức đặt thẳng lên từng Ô,
   nên mọi khai báo ở cấp `<table>` đều bị kế thừa vượt qua. Màn công việc khai `.wt-grid { font-size:.75rem }`
   mà đo ra 14px đúng vì lý do đó: quy tắc trông có vẻ chạy, nhưng ô vẫn giữ cỡ của theme — hỏng im lặng.

   13px: đủ nhỏ để một màn hình chứa được nhiều dòng (bảng dữ liệu là để QUÉT, không phải để đọc từng câu),
   vẫn đủ lớn để dấu tiếng Việt không dính vào nhau. Đầu bảng cùng cỡ với ô, chỉ khác độ đậm.

   ⚠ Đừng khai lại cỡ chữ bảng trong từng màn. Muốn một bảng đặc biệt dày đặc hơn thì đặt lớp riêng cho
   bảng đó và nói rõ lý do — nếu không, mỗi màn sẽ trôi mỗi cỡ và không ai phát hiện vì không ai mở hai
   màn cạnh nhau. */
/* ⚠ Bộ chọn phải ĐỦ ĐẶC HIỆU. Theme khai `.table tbody tr td { font-size: 14px }` (ba phần tử + một lớp);
   viết gọn `.table > :not(caption) > * > *` là thua về độ ưu tiên và không có gì báo — đầu bảng đổi cỡ, ô
   dữ liệu thì không, mà nhìn thoáng qua tưởng đã xong. Đo bằng trình duyệt mới thấy. */
.table tbody tr td,
.table tbody tr th {
    font-size: 0.8125rem;
}
.table thead tr th {
    font-size: 0.8125rem;
    font-weight: 600;
}
/* Khối điều khiển của DataTables (ô tìm, "Hiện x trong y", phân trang) — cùng cỡ với bảng nó phục vụ. */
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
    font-size: 0.8125rem;
}

/* ============================================================================
   RUỘT THẺ CÔNG VIỆC — dùng chung cho MỌI bảng Kanban
   ============================================================================
   Hệ thống có hai bảng Kanban khác nhau về bố cục cột nhưng giống hệt nhau về nội dung một tấm thẻ:
   · "Tất cả công việc" — cột là NHÓM công việc, chỉ đọc, dựng bằng JS;
   · "Nhóm công việc"   — cột là trạng thái workflow, KÉO-THẢ được, dựng bằng Blade.

   Trước 12/08/2026 mỗi bên một kiểu thẻ: bên JS có dải tình trạng, chip hạn, avatar; bên Blade chỉ có tên
   và phần trăm — mở bảng ra không biết việc nào trễ. Gộp về đây để sửa một lần là cả hai cùng đổi.

   ⚠ Chỉ chứa RUỘT thẻ. Bố cục cột nằm riêng ở từng màn (`work/tasks/_index-css.blade.php` cho cột nhóm,
   `work/projects/show.blade.php` cho cột workflow) vì hai bên khác hẳn nhau. */

/* Avatar chữ cái — màu và chữ tắt do `App\Core\Support\AvatarInitials` sinh ra, cùng một người luôn cùng
   một màu ở mọi màn. */
.wt-ava {
    width: 22px; height: 22px; border-radius: 50%; color: #fff; font-size: .5625rem; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center; border: 2px solid #fff; flex: 0 0 auto;
    /* `position: relative` + `overflow: hidden`: ảnh thật nằm ĐÈ lên chữ cái trong cùng một thẻ tròn, và bị
       cắt theo đúng đường tròn ấy. Nhờ vậy fallback không cần JS — ảnh hỏng thì chữ cái lộ lại. */
    position: relative; overflow: hidden;
}
.wt-ava-more { background: #8a94a6; }

/* ═══ AVATAR ẢNH THẬT — dùng chung (partial `layout.partials.vt-avatar` + `VT.avatarEl`) ═══
   ⚠ `object-fit: cover` + `object-position: center` là thứ giữ cho MẶT NGƯỜI không bị méo và không bị cắt
   mất: ảnh chân dung thường cao hơn rộng, `contain` sẽ chừa hai dải trống hai bên, còn kéo giãn cho vừa thì
   mặt bị bóp. Cover cắt phần thừa ở rìa và giữ nguyên tỉ lệ. */
.wt-ava img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; object-position: center; border-radius: inherit; display: block;
}
/* Có ảnh thì giấu chữ cái đi (vẫn nằm trong DOM để `onerror` lộ lại được) và bỏ nền màu. */
.wt-ava-photo { background: #eef1f5 !important; }
.wt-ava-photo .wt-ava-chu { visibility: hidden; }

/* ═══ BA CỠ AVATAR DÙNG CHUNG ═══
   ⚠ Cỡ đi kèm cỡ CHỮ và độ dày viền, không chỉ width/height: giữ nguyên `font-size: .5625rem` cho một thẻ
   44px thì hai chữ cái nằm lọt thỏm giữa một vòng tròn lớn, trông như lỗi render. */
.wt-ava-md { width: 32px; height: 32px; font-size: .75rem; }
/* `wt-ava-lg` — cỡ riêng của PHÂN HỆ NHÂN SỰ (user chốt 18/08/2026: *"riêng nhân sự phải avatar thêm"*,
   rồi chốt 60px). Ở đó khuôn mặt là nội dung chính của dòng chứ không phải chi tiết phụ, và ô
   nhân sự cao bốn dòng chữ (tên · mã · chức danh–phòng · công ty) nên còn thừa chỗ. */
.wt-ava-lg { width: 60px; height: 60px; font-size: 1.25rem; border-width: 2px; }
.wt-ava-xl { width: 96px; height: 96px; font-size: 2rem; border-width: 3px; }

/* ═══ Ô NGƯỜI TRONG MỘT Ô BẢNG dựng bằng BLADE (`vt-avas-cell`) ═══
   Bảng dựng bằng JS đã có `.wk-meta` lo phần này; ô Blade thì không mượn được `.wk-meta` vì lớp đó còn
   mang `display:flex` + `margin-top` của dòng meta trong thẻ Kanban — đắp lên một `<td>` là lệch căn dòng.
   ⚠ Cỡ chữ phải khai THẲNG LÊN ĐÂY, không trông vào kế thừa: theme đặt `font-size` trực tiếp lên từng ô
   (`.table > :not(caption) > * > *`), nên quy tắc cấp `<table>` không bao giờ tới avatar. */
.vt-avas-cell .wt-ava { width: 32px; height: 32px; font-size: .75rem; vertical-align: middle; }
.vt-avas-cell .wt-ava + .wt-ava { margin-left: -10px; }

/* ═══ CỘT THAO TÁC DÍNH MÉP PHẢI cho bảng Blade trong `.table-responsive` (`wt-act-sticky`) ═══
   Bản dùng chung của luật đã chạy ở bảng "Tất cả công việc" (`.wt-actions` trong `work/tasks/_index-css`).
   Vì sao cần: bảng nhiều cột trong một khung hẹp thì cụm nút thao tác nằm ngoài tầm nhìn — muốn bấm một
   nút phải cuộn hết sang phải, xong lại cuộn về.
   ⚠ `position: sticky` bám vào KHUNG CUỘN gần nhất ⇒ bảng PHẢI nằm trong `.table-responsive` (hoặc một
     khung `overflow-x` khác). Không có khung cuộn thì quy tắc vẫn áp, trình duyệt vẫn báo `sticky`, mà
     cuộn thì không có gì xảy ra.
   ⚠ Nền phải ĐỤC: cột đứng yên trong khi các cột khác chạy qua BÊN DƯỚI nó — nền trong suốt thì chữ chồng
     lên nhau. Vì vậy phải khai lại nền cho cả trạng thái rê chuột, nếu không cột này trơ ra màu trắng giữa
     một dòng đã đổi màu.
   ⚠ Ranh giới vẽ THƯỜNG TRỰC, khác bảng "Tất cả công việc" (bên đó có JS đo xem còn nội dung bị che hay
     không rồi mới vẽ). Bảng Blade không có vòng đo ấy, và một nét kẻ mảnh khi đã cuộn hết vẫn đọc được như
     đường phân cột bình thường — thà thế còn hơn nhét thêm một vòng đo vào mỗi màn. */
.wt-act-sticky { position: sticky; right: 0; background: #fff; z-index: 2; border-left: 1px solid #eceef1; }
.table-hover > tbody > tr:hover > .wt-act-sticky { background: var(--vt-row-hover); }
/* ⚠⚠ MENU ⋮ BỊ Ô CỦA DÒNG DƯỚI VẼ ĐÈ LÊN — bẫy đã trả giá ở bảng công việc (17/08/2026), chép nguyên luật
   sang đây để bảng nào dùng lớp này cũng không dính lại. Gốc rễ là THỨ TỰ VẼ: `sticky` + `z-index` biến
   MỖI ô thao tác thành một tầng riêng, nên menu nằm trong ô dòng trên bị kẹt ở tầng đó, còn ô của các dòng
   DƯỚI cùng tầng nhưng đứng sau trong DOM nên vẽ chồng lên — bấm vào mục menu là trúng dòng khác.
   ⚠ Chỉ nâng KHI MENU ĐANG MỞ: nâng vĩnh viễn thì ô thao tác trồi lên che mất hàng tiêu đề lúc cuộn dọc.
   Khai hai bộ chọn cho hai lưới an toàn: `:has()` bắt đúng lúc menu mở, `:focus-within` phòng trình duyệt
   chưa hỗ trợ `:has()` (nút giữ focus suốt lúc menu mở). */
tbody > tr > .wt-act-sticky:focus-within,
tbody > tr > .wt-act-sticky:has(.dropdown-menu.show) { z-index: 20; }
/* Ô TIÊU ĐỀ mượn nền của chính hàng tiêu đề, ⛔ KHÔNG lấy trắng cứng: theme tô hàng tiêu đề màu xám nhạt,
   ép trắng là cột cuối trổ một mảng sáng lệch hẳn khỏi hàng. */
thead .wt-act-sticky { background: inherit; }

/* Dải tình trạng thời hạn trên đầu thẻ — thứ người dùng quét mắt tìm trước tiên. */
.wk-band { display: flex; align-items: center; gap: .25rem; padding: .2rem .5rem; font-size: .6875rem; font-weight: 600; }
.wk-b-late { background: #ffede9; color: #c0201c; }
.wk-b-soon { background: #fff0ca; color: #8a6a00; }
.wk-b-done { background: #cbefd4; color: #1f7a50; }

/* ⚠ `text-decoration: none` cả ở trạng thái rê chuột: tên việc là liên kết, mà theme gạch chân mọi `<a>`
   khi hover — cả một danh sách nhấp nháy gạch chân theo con trỏ. Cả dòng đã đổi nền khi rê rồi. */
.wk-title { display: block; font-size: .8125rem; font-weight: 600; color: #092c4c; line-height: 1.35; text-decoration: none; }
.wk-title:hover { color: #092c4c; text-decoration: none; }
/* Biến thể KHÔNG đậm — dùng cho danh sách dòng-nối-dòng, nơi mọi dòng đều là một cái tên. Đậm ở thẻ Kanban
   thì hợp (mỗi thẻ một khối riêng), đậm ở danh sách thì cả cột thành một mảng chữ đậm. */
.wk-title.wk-title-plain { font-weight: 400; }

/* Mũi chevron mở/thu gọn nhánh cây — KHÔNG phải nút, không gạch chân, không khung. */
.wp-toggle,
.wp-toggle-spacer { display: inline-flex; width: 18px; flex: 0 0 auto; justify-content: center; color: #8a94a6; line-height: 1.6; }
.wp-toggle { cursor: pointer; }
.wp-toggle:hover { color: #092c4c; }
.wp-toggle i { transition: transform .12s ease-in-out; }
.wp-toggle[aria-expanded="true"] i { transform: rotate(90deg); }
/* Việc hoàn thành: KHÔNG gạch ngang tên — dải "Hoàn thành" trên đầu thẻ đã nói rồi, gạch chữ chỉ làm tên
   việc khó đọc. Chỉ hạ nhẹ độ đậm để nó lùi lại sau những việc đang chạy. */
.wk-title.wk-done { color: #67748e; }

.wk-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem; margin-top: .45rem; font-size: .6875rem; color: #67748e; }
/* ★ CỘT NGƯỜI CỦA BẢNG/THẺ — 20px → 36px (user chốt 18/08/2026). Đây là cột người ta quét mắt để trả lời
   "việc này của ai", mà ở 20px ảnh thật không phân biệt nổi hai người cùng màu áo.
   ⚠ 36px là cỡ DÙNG CHUNG cho mọi chỗ hiện mặt người trong một dòng — cột người của bảng công việc, danh
   sách người thực hiện/giám sát (`wt-ava-md`), từng dòng của ô chọn người (`vt-people-opt`) và cột nhân sự
   của bảng hồ sơ. Ba cỡ khác nhau ở ba màn thì cùng một khuôn mặt lúc to lúc bé, nhìn không ra hệ thống.
   ⚠ Độ chồng mép (`margin-left` âm) phải giãn theo cỡ, giữ nguyên -7px thì ba avatar 36px che nhau quá nửa
   và cái ở giữa chỉ còn một vành trăng khuyết. */
.wk-meta .wt-ava { width: 32px; height: 32px; font-size: .75rem; }
.wk-meta .wt-ava + .wt-ava { margin-left: -10px; }
.wk-noone { color: #b9c0ca; }
.wk-due { display: inline-flex; align-items: center; gap: .2rem; }
.wk-due-late { color: #c0201c; font-weight: 600; }
.wk-due-soon { color: #8a6a00; font-weight: 600; }
.wk-due-none { color: #b9c0ca; }
.wk-kids { display: inline-flex; align-items: center; gap: .15rem; color: #8a94a6; }
.vt-bt-body h1, .vt-bt-body h2, .vt-bt-body h3,
.vt-bt-body h4, .vt-bt-body h5, .vt-bt-body h6,
.vt-rich-view h1, .vt-rich-view h2, .vt-rich-view h3,
.vt-rich-view h4, .vt-rich-view h5, .vt-rich-view h6 { margin: 1.25rem 0 0.6rem; font-weight: 600; }
.vt-bt-body blockquote,
.vt-rich-view blockquote {
  border-left: 3px solid #e5e7eb; padding: 0.25rem 0 0.25rem 1rem; margin: 0 0 1rem; color: #6b7280;
}
/* Bảng người dùng chèn từ trình soạn thảo không có class của theme ⇒ phải tự kẻ khung, nếu không nó ra
   một đám chữ không có đường phân cách. `overflow-x` để bảng rộng không đẩy vỡ cả trang trên màn hẹp. */
.vt-bt-body table { width: 100%; margin-bottom: 1rem; border-collapse: collapse; }
.vt-bt-body th,
.vt-bt-body td { border: 1px solid #e5e7eb; padding: 0.5rem 0.75rem; vertical-align: top; }
.vt-bt-body th { background: #f9fafb; font-weight: 600; }
.vt-bt-body img { max-width: 100%; height: auto; }

/* ---- BOX BẢN TIN NỘI BỘ trên trang Tổng quan ----
   Cùng nhịp với box Sinh nhật ngay dưới nó (`.vt-bd-*`): cùng chiều cao vùng cuộn, cùng cỡ chữ phụ, cùng
   kiểu empty state. Hai box cạnh nhau mà lệch nhịp thì cột phải trông như hai mảnh ghép rời. */
.vt-bt-scroll { max-height: 300px; overflow-y: auto; }

.vt-bt-row {
  display: block;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid #f1f2f4;
  color: inherit;
  text-decoration: none;
}
.vt-bt-row:last-child { border-bottom: 0; }
.vt-bt-row:hover { background: #fff7f2; }

.vt-bt-info { min-width: 0; }

/* Tiêu đề gói trong 2 dòng: tiêu đề bản tin dài (một câu thông báo đầy đủ) sẽ đẩy box cao gấp đôi và dồn
   box Sinh nhật xuống khỏi tầm mắt. */
.vt-bt-title {
  font-weight: 600;
  font-size: 0.875rem;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vt-bt-row:hover .vt-bt-title { color: rgb(224, 79, 22); }

/* Tóm tắt gói MỘT dòng — nó chỉ để liếc qua, muốn đọc đủ thì bấm vào. */
.vt-bt-sub {
  font-size: 0.78rem;
  color: #6b7280;
  margin-top: 0.15rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vt-bt-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.3rem;
  font-size: 0.72rem;
  color: #9ca3af;
}
/* Nhãn trong khối này lấy cỡ theo CHUẨN CHUNG ở cuối tệp — không khai riêng nữa. */

.vt-bt-empty {
  text-align: center;
  color: #9ca3af;
  padding: 1.75rem 1rem;
  font-size: 0.85rem;
}
.vt-bt-empty i { font-size: 24px; display: block; margin-bottom: 0.4rem; }

/* ============================================================================
   LỊCH (FullCalendar) — CHUẨN CHUNG CHO MỌI TỜ LỊCH TRONG HỆ THỐNG
   ============================================================================
   ★ Khai MỘT chỗ (12/08/2026). Trước đó màn "Tất cả công việc" khoá toàn bộ luật vào `#wt-calendar`, còn
   màn "Nhóm công việc" chỉ có bốn dòng của riêng nó — hai tờ lịch cùng một hệ thống mà nút một bên là
   viên thuốc bo tròn, một bên là nút vuông xanh mặc định của thư viện. Bỏ id đi, giữ nguyên các luật:
   lịch nào thêm sau cũng ra đúng dáng mà không phải chép lại gì.

   Cặp đôi với `VT.calendarOptions()` (vt-forms-init): tệp này lo DÁNG, hàm kia lo CHỮ. Sửa dáng ở đây,
   sửa chữ ở đó — đừng khai lại cỡ chữ hay màu nút trong từng màn.

   ⚠ Không đụng tới các luật `.fc-*` cũ trong `custom.css` của theme: chúng viết cho FullCalendar v3
   (`.fc-unthemed`, `.fc-widget-header`, `.fc-toolbar h2`) và không khớp một lớp nào của bản v6 đang chạy. */

/* TRẠNG THÁI RỖNG — dải nhắc mỏng NGAY TRÊN lưới (B3, S12/13-08-2026).
   Trước đợt này, Lịch là góc nhìn DUY NHẤT không có trạng thái rỗng ở cả hai màn có lịch: `events` rỗng thì
   vẫn `render()` ra một lưới tháng trắng trơn, không một dòng chữ giải thích — người dùng không phân biệt
   được "không có việc nào" với "màn hình hỏng".
   ⚠ Là DẢI CHÈN THÊM, không phải khối THAY THẾ như Kanban/Gantt: thanh chuyển tháng nằm trong chính lưới,
   thay lưới bằng dòng chữ là trạng thái rỗng khoá mất đúng cái thao tác dùng để thoát khỏi nó. */
.wt-cal-empty { background:#f7f8fa; border:1px solid #eceef1; border-radius:.5rem; color:#67748e;
    font-size:.8125rem; padding:.55rem .75rem; margin-bottom:.6rem; }

/* NÚT — ĐÚNG dáng chip lọc nhanh của thanh điều kiện (`.wt-chip`): viên thuốc bo tròn, nền trắng, viền
   mảnh; nút đang chọn thì nền cam nhạt, viền cam, chữ nâu đỏ — y như chip đang bật.

   ⚠⚠ PHẢI dùng `!important`, và đây là chỗ hiếm hoi nó đúng. Theme khai `.fc-button { border-radius:5px
   !important; padding:6px 12px !important; margin:0 3px !important; height:auto !important }` cùng
   `.fc .fc-button-primary { padding:2px 5px !important }`. Mọi luật THƯỜNG — kể cả luật khoá theo id như
   `#wt-calendar .fc .fc-button` từng dùng trước đây — đều bị nuốt sạch mà không có gì báo: các biến CSS
   `--fc-button-*` của thư viện cũng vô hiệu vì theme đè thẳng lên `background-color`/`border-color`.
   Đó là lý do suốt thời gian qua nút lịch vẫn là nút vuông xám/xanh navy của theme trong khi mã nguồn
   trông như đã đổi thành chip. Chỉ `!important` mới thắng `!important`.
   `text-transform:none` cũng bắt buộc: theme viết hoa chữ đầu mọi từ, "Hôm nay" thành "Hôm Nay". */
.fc {
    --fc-today-bg-color: #fff6ee;
}
.fc .fc-button,
.fc .fc-button-primary,
.fc .fc-button-primary:disabled {
    padding: 0.25rem 0.7rem !important;
    height: auto !important;
    margin: 0 !important;
    font-size: 0.75rem !important;
    font-weight: 400;
    line-height: 1.5;
    border-radius: 14px !important;
    border: 1px solid #e6eaed !important;
    background-color: #fff !important;
    color: #67748e !important;
    text-transform: none !important;
    box-shadow: none !important;
    opacity: 1;
}
.fc .fc-button-primary:hover:not(:disabled) {
    background-color: #f7f8fa !important;
    border-color: #c9d2dc !important;
    color: #092c4c !important;
}
/* Nút đang chọn (Tháng / Danh sách) — cùng bộ màu với chip đang bật. */
.fc .fc-button-primary:not(:disabled).fc-button-active,
.fc .fc-button-primary:not(:disabled):active {
    background-color: #fff6ee !important;
    border-color: #e04f16 !important;
    color: #b85c00 !important;
    font-weight: 600;
}
.fc .fc-button-primary:focus,
.fc .fc-button-primary:focus-visible { outline: none; box-shadow: none !important; }
/* "HÔM NAY" khi đang xem đúng khoảng chứa hôm nay: thư viện TỰ khoá nút (`disabled`) vì bấm cũng không đi
   đâu. Nếu để nó trắng như hai nút kia thì nó trông như một nút hỏng — bấm mãi không phản ứng. Tô như chip
   đang bật để nó nói đúng điều đang xảy ra: "bạn đang ở hôm nay". */
.fc .fc-today-button:disabled {
    background-color: #fff6ee !important;
    border-color: #e04f16 !important;
    color: #b85c00 !important;
    font-weight: 600;
    opacity: 1;
    cursor: default;
}
/* Hai mũi tên chuyển tháng: cùng dáng chip, chỉ hẹp hơn vì chỉ chứa một biểu tượng. */
.fc .fc-prev-button, .fc .fc-next-button { padding: 0.25rem 0.5rem !important; }
.fc .fc-icon { font-size: 1.05em; vertical-align: -1px; }
/* Khoảng cách giữa các nút do ĐÂY quyết định (theme đặt `margin:0 3px !important` cho mọi nút, kể cả nút
   dính liền trong nhóm — nhóm bị hở ra thành hai nút rời). */
.fc .fc-toolbar > * > :not(:first-child) { margin-left: 0.35rem !important; }
.fc .fc-button-group > .fc-button:not(:last-child) { margin-right: 0.25rem !important; }
.fc .fc-toolbar-title { font-size: 1rem; font-weight: 700; color: #092c4c; }

/* CỠ CHỮ — nhỏ như nhãn trạng thái. Mỗi ô lịch chỉ cao vài chục pixel mà chứa tới ba việc: cỡ chữ mặc
   định của thư viện làm tên việc bị cắt ngay từ chữ thứ ba. */
.fc { font-size: 0.75rem; }
.fc .fc-col-header-cell-cushion { font-size: 0.75rem; font-weight: 600; color: #67748e; padding: 0.35rem 0.25rem; }
.fc .fc-daygrid-day-number { font-size: 0.6875rem; color: #67748e; padding: 0.2rem 0.35rem; }
.fc .fc-daygrid-event { font-size: 0.6875rem; padding: 0.1rem 0.3rem; }
.fc .fc-daygrid-more-link { font-size: 0.625rem; color: #8a94a6; }
.fc .fc-list-event-title, .fc .fc-list-event-time { font-size: 0.75rem; }
.fc .fc-list-day-text, .fc .fc-list-day-side-text { font-size: 0.75rem; font-weight: 600; }
.fc .fc-day-today { background: #fff6ee !important; }

/* Việc vắt NHIỀU TUẦN đọc như một thanh liền: các đoạn giữa bỏ bo góc ở mép bị cắt, nếu không mỗi đoạn
   trông như một việc riêng. Mọi đoạn (kể cả đoạn nối tiếp) đều hiện đủ tên. */
.fc .fc-daygrid-block-event:not(.fc-event-start) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.fc .fc-daygrid-block-event:not(.fc-event-end) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.fc .fc-daygrid-block-event { padding-top: 1px; padding-bottom: 1px; }
.fc .fc-daygrid-block-event .fc-event-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }

/* ⚠ Chế độ DANH SÁCH vẽ tên việc trên nền TRẮNG nhưng vẫn lấy `textColor` của sự kiện — tức chữ trắng
   trên nền trắng, người dùng thấy một danh sách rỗng. Ép lại màu chữ tối cho riêng chế độ này; màu tình
   trạng vẫn còn nguyên ở chấm tròn đầu dòng.
   Rê chuột KHÔNG gạch chân tên việc — cả dòng đã đổi nền rồi (đồng nhất với bảng danh sách). */
.fc .fc-list-event-title a,
.fc .fc-list-event-time { color: #092c4c !important; }
/* ⚠ Gạch chân phải chặn ở CẢ DÒNG, không chỉ ở thẻ `<a>`. Thư viện khai
   `.fc .fc-list-event.fc-event-forced-url:hover a { text-decoration: underline }` — hover nằm trên DÒNG,
   nên rê chuột vào cột "Cả ngày" hay chấm màu (không phải chữ) vẫn kéo theo gạch chân ở tên việc, trong
   khi luật chỉ khoá `a:hover` thì không khớp. Cả dòng đã đổi nền rồi, không cần thêm nét nào. */
.fc .fc-list-event-title a:hover,
.fc .fc-list-event:hover a,
.fc .fc-list-event.fc-event-forced-url:hover a { text-decoration: none !important; }
.fc .fc-list-event:hover td { background: #fff6ee; }
.fc .fc-list-day-cushion { background: #f7f8fa; }
/* Ô của chế độ Danh sách căn TRÁI. Theme căn giữa mọi ô bảng, nên tên việc dạt về giữa cột và mỗi dòng
   bắt đầu ở một chỗ khác nhau — mắt không có mép nào để lần xuống. */
.fc .fc-list-table td, .fc .fc-list-table th { text-align: left; }

/* ============================================================================
   HÀNG TIÊU ĐỀ BẢNG DÍNH KHI CUỘN — CHUẨN CHUNG CHO MỌI BẢNG
   ============================================================================
   Bảng dữ liệu dài vài chục dòng mà cuộn xuống là mất tên cột: người đọc phải nhớ cột thứ tư là gì, hoặc
   cuộn ngược lên xem lại. Bảng công việc đã ghim được cột (số thứ tự + tên việc dính khi cuộn ngang) thì
   hàng tiêu đề cũng phải ghim khi cuộn dọc — hai chiều mới đủ.

   ⚠⚠ BẪY (mất nửa giờ đo mới ra): `position: sticky` bám vào KHUNG CUỘN GẦN NHẤT, mà `overflow: hidden`
   cũng tạo ra một khung cuộn — chỉ là khung không cuộn được. Mọi bảng dữ liệu đều nằm trong một vùng cuộn
   ngang (`.table-responsive` của Bootstrap, hay `.wt-scroll` của màn công việc), nên hàng tiêu đề bám vào
   vùng đứng yên đó và không bao giờ dính, dù luật `sticky` khai đúng. Đây là lý do
   `.wt-grid > thead > tr > th { position:sticky }` có từ lâu mà chưa bao giờ chạy.

   ⚠ `overflow-y: clip` KHÔNG cứu được: theo chuẩn, `clip` đi cùng một trục `auto` thì bị tính thành
   `hidden` (đo trên Chrome: khai `overflow-x:auto; overflow-y:clip` ⇒ computed trả `hidden`). Vùng vừa
   cuộn ngang vừa muốn tiêu đề dính theo TRANG là điều không làm được bằng CSS.

   ⇒ Cách đi: cho bảng CUỘN DỌC TRONG CHÍNH KHUNG CỦA NÓ (giới hạn chiều cao theo màn hình) và ghim tiêu đề
   ở mép trên khung đó. Bảng ít dòng không chạm trần nên không có gì đổi; bảng dài thì phần cuộn nằm gọn
   trong khung, tiêu đề luôn hiện, và thanh điều kiện phía trên không bị đẩy đi mất. */
:root {
    --vt-topbar-h: 65px;                       /* thanh tiêu đề trên cùng: fixed, cao 65px */
    /* Trần chiều cao vùng bảng cuộn — MỘT con số cho MỌI bảng trong hệ thống. Trừ cho thanh tiêu đề trên
       cùng (65), tiêu đề trang và thanh điều kiện (~185).
       ⚠ Đây là con số CỐ ĐỊNH, cố ý. Bản đo bằng JS đã thử ba cách và cách nào cũng có một đường hỏng
       riêng — phình vượt màn hình, hoặc teo dần còn sáu dòng — vì chiều cao trang lại phụ thuộc ngược vào
       chính chiều cao bảng, thành một vòng không hội tụ. Con số cố định thì luôn đoán trước được: mọi màn
       hình thường đều thấy 15–20 dòng, và hàng tiêu đề ghim ở mép trên khung. */
    --vt-table-max-h: calc(100vh - 250px);
    --vt-table-min-h: 320px;
}

.table-responsive:has(> table.vt-sticky-head) {
    max-height: var(--vt-table-max-h);
    min-height: var(--vt-table-min-h);
    overflow: auto;
}
.vt-sticky-head > thead > tr > th,
table.vt-sticky-head > thead > tr > th {
    position: sticky;
    top: 0;
    /* Dưới thanh tiêu đề trang (z-index 999) và dưới dropdown, nhưng trên mọi ô dữ liệu. */
    z-index: 3;
}

/* 🔴 25/08/2026 — HÀNG TIÊU ĐỀ VỠ THÀNH TỪNG MẢNG KHI CUỘN (anh Dũng gửi ảnh từ màn Báo cáo định kỳ).
   ⚠ Vỡ RẤT LẠ nên dễ đổ cho sai bố cục: vài ô ghim lại ở mép trên còn vài ô trôi đi cùng trang, nền cam
     đứt quãng, dòng dữ liệu đầu tiên lòi lên giữa các mảnh.

   NGUYÊN NHÂN (đo bằng cách đọc `getComputedStyle` từng ô, ⛔ không đoán): DataTables tự gắn
   `position: relative` cho ô tiêu đề **SẮP XẾP ĐƯỢC** để đặt mũi tên `::before/::after` —
       `table.dataTable thead > tr > th.sorting { position: relative }`  (dataTables.bootstrap5.min.css)
   Selector ấy đặc hiệu HƠN quy tắc ngay trên, nên chỉ những ô ấy mất `sticky`; ô `sorting_disabled`
   (STT, Thao tác…) vẫn dính. Header cùng một hàng mà hai nửa hành xử khác nhau ⇒ vỡ.
   ⚠ Vì thế lỗi CHỈ lộ khi bảng đủ dài để cuộn VÀ có ít nhất một cột sắp xếp được — đó là lý do nó sống
     sót qua nhiều đợt rà giao diện.

   ★ Sửa Ở ĐÚNG MỘT CHỖ NÀY cho TOÀN DỰ ÁN (anh Dũng chốt: *"nếu sửa css thì phải sửa 1 chỗ thì áp dụng
     toàn bộ project"*) — mọi bảng mang `.vt-sticky-head` đều được vá, kể cả bảng thêm sau này.
   ⚠ Thắng bằng cách LẶP CLASS (`.vt-sticky-head.vt-sticky-head`), ⛔ KHÔNG `!important` và ⛔ KHÔNG đổi
     thứ tự nạp — cùng quy ước đã dùng khi trùng khít selector của Summernote.
   ⛔ Đừng "dọn cho gọn" bằng cách gỡ `position: relative` của DataTables: mũi tên sắp xếp neo tuyệt đối
     vào chính ô ấy, gỡ đi là mũi tên văng ra góc trang. `sticky` cũng tạo containing block như `relative`
     nên mũi tên vẫn nằm đúng chỗ. */
table.vt-sticky-head.vt-sticky-head > thead > tr > th.sorting,
table.vt-sticky-head.vt-sticky-head > thead > tr > th.sorting_asc,
table.vt-sticky-head.vt-sticky-head > thead > tr > th.sorting_desc,
table.vt-sticky-head.vt-sticky-head > thead > tr > th.sorting_asc_disabled,
table.vt-sticky-head.vt-sticky-head > thead > tr > th.sorting_desc_disabled {
    position: sticky;
    top: 0;
}
/* Cụm cột dính bên trái phải nổi TRÊN hàng tiêu đề dính, nếu không ô giao nhau giữa hai vùng dính sẽ bị
   hàng tiêu đề đè lên khi vừa cuộn ngang vừa cuộn dọc. */
.vt-sticky-head > thead > tr > th.wt-sk { z-index: 5; }

/* THANH CUỘN CHỈ HIỆN KHI RÊ CHUỘT VÀO VÙNG ĐÓ
   Vùng cuộn nào cũng kèm một vệt xám chạy dọc/ngang, mà phần lớn thời gian người dùng chỉ đang đọc chứ
   không cuộn — mấy vệt đó cộng lại thành đường kẻ thừa trên mọi màn.
   ⚠ Làm trong suốt CON TRƯỢT chứ KHÔNG thu bề rộng thanh về 0: đổi bề rộng khi rê chuột sẽ đẩy nội dung
   dịch ngang vài pixel đúng lúc con trỏ vừa chạm vào — nhìn như trang bị giật. */
.wt-ap-scroll,
.wt-scroll,
.wg-left,
.wg-right,
.wk-body,
.wk-board,
.table-responsive:has(> table.vt-sticky-head) {
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}
.wt-ap-scroll:hover,
.wt-scroll:hover,
.wg-left:hover,
.wg-right:hover,
.wk-body:hover,
.wk-board:hover,
.table-responsive:has(> table.vt-sticky-head):hover {
    scrollbar-color: #c9d2dc transparent;
}
.wt-ap-scroll::-webkit-scrollbar,
.wt-scroll::-webkit-scrollbar,
.wg-left::-webkit-scrollbar,
.wg-right::-webkit-scrollbar,
.wk-body::-webkit-scrollbar,
.wk-board::-webkit-scrollbar,
.table-responsive:has(> table.vt-sticky-head)::-webkit-scrollbar { width: 8px; height: 8px; }
.wt-ap-scroll::-webkit-scrollbar-track,
.wt-scroll::-webkit-scrollbar-track,
.wg-left::-webkit-scrollbar-track,
.wg-right::-webkit-scrollbar-track,
.wk-body::-webkit-scrollbar-track,
.wk-board::-webkit-scrollbar-track,
.table-responsive:has(> table.vt-sticky-head)::-webkit-scrollbar-track { background: transparent; }
.wt-ap-scroll::-webkit-scrollbar-thumb,
.wt-scroll::-webkit-scrollbar-thumb,
.wg-left::-webkit-scrollbar-thumb,
.wg-right::-webkit-scrollbar-thumb,
.wk-body::-webkit-scrollbar-thumb,
.wk-board::-webkit-scrollbar-thumb,
.table-responsive:has(> table.vt-sticky-head)::-webkit-scrollbar-thumb { background: transparent; border-radius: 4px; }
.wt-ap-scroll:hover::-webkit-scrollbar-thumb,
.wt-scroll:hover::-webkit-scrollbar-thumb,
.wg-left:hover::-webkit-scrollbar-thumb,
.wg-right:hover::-webkit-scrollbar-thumb,
.wk-body:hover::-webkit-scrollbar-thumb,
.wk-board:hover::-webkit-scrollbar-thumb,
.table-responsive:has(> table.vt-sticky-head):hover::-webkit-scrollbar-thumb { background: #c9d2dc; }
.wt-ap-scroll:hover::-webkit-scrollbar-thumb:hover,
.wt-scroll:hover::-webkit-scrollbar-thumb:hover,
.wg-right:hover::-webkit-scrollbar-thumb:hover { background: #aab4c0; }

/* ============================================================================
   SELECT2 — VIỀN KHI ĐANG NHẬP (focus/mở), MỘT MÀU CHO MỌI DẠNG

   Ba màu cùng xuất hiện trên một ô chọn, đo bằng getComputedStyle:
     · dòng đang chọn trong danh sách thả xuống → `#E04F16` (màu chủ đạo dự án, cũng là nền đầu bảng);
     · viền focus của dạng chọn MỘT (theme, style.css:11580)  → `#FE9F43` (cam nhạt);
     · dạng chọn NHIỀU → KHÔNG có luật focus nào, rơi về viền mặc định của Select2 (xanh).
   Ba thứ này nằm cạnh nhau trong cùng một hộp thoại nên chênh sắc là nhìn ra ngay.

   ⇒ Chốt MỘT màu: `#E04F16`, đúng màu dòng đang chọn và đúng tông chủ đạo. Khai cho CẢ hai dạng — sửa
   riêng dạng chọn nhiều thì hai ô đứng cạnh nhau vẫn sáng lên hai màu khác nhau.

   ⚠ CHỈ đổi lúc focus/mở. Viền lúc thường vẫn là `#E6EAED` của theme — đè cả lúc thường là mọi ô chọn
   toàn hệ thống viền cam thường trực, rối mắt.
   ⚠ `!important` là bắt buộc cho dạng chọn MỘT: theme khai `border-color:#FE9F43` kèm `!important` ở
   `.select2-container--focus .select2-selection--single`, luật thường không thắng được.
   ============================================================================ */
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--multiple {
    border-color: #E04F16 !important;
}

/* ============================================================================
   Ô NGÀY TRONG MODAL — nở đúng bề rộng của cột, khai MỘT chỗ cho toàn hệ thống

   Mọi ô ngày nằm trong modal đều được `vt-forms-init` khởi tạo với `static: true` (bắt buộc, nếu không
   lịch bị z-index/định vị sai khi modal cuộn). Chế độ đó khiến Flatpickr BỌC ô trong một
   `<div class="flatpickr-wrapper">`, mà mặc định của nó là `display: inline-block` ⇒ hộp bọc co lại
   bằng bề rộng NỘI TẠI của ô (~220px, theo thuộc tính `size` mặc định), rồi `width:100%` của
   `.form-control` lại tính theo 220px ấy.

   Hậu quả đo được trên màn thật (13/08): ô "Ngày bắt đầu" rộng 220px trong khi cột chứa nó rộng 541px và
   ô Select2 bên cạnh nở đủ 541px ⇒ nhìn như ô ngày bị "thụt" vào so với các ô cùng hàng.

   Đây KHÔNG phải lỗi của một màn: nó đúng với MỌI ô ngày trong MỌI modal của hệ thống. Vì vậy sửa ở đây,
   không vá lẻ từng form. Ô ngày ngoài modal không có hộp bọc này nên không bị ảnh hưởng.
   ============================================================================ */
.flatpickr-wrapper {
    display: block;
    width: 100%;
}

/* ---- Lịch của ô ngày TRONG BẢNG việc con: phải NỔI LÊN TRÊN, không lọt vào giữa bảng ----------------
   Hai thứ phải cùng đúng thì lịch mới bung ra tử tế:

   1) Thẻ bọc bảng KHÔNG được là khung cuộn. Gỡ `.table-responsive` khỏi Blade là chưa đủ — theme chạy
      `$('.table').parent().addClass('table-responsive')` (`public/build/js/script.js:116`) nên cha của
      MỌI bảng bị gán lại lớp đó lúc trang tải xong, và `overflow:auto` cắt cụt lịch (đo được: lịch cao
      306px, chỉ hiện 163px). Selector hai lớp dưới đây đặc hiệu hơn `.table-responsive` nên thắng mà
      không cần `!important`.

   2) Lịch phải nằm TRÊN các dòng kế tiếp. Ô ngày ở dòng trên mà lịch chui xuống dưới nền dòng dưới thì
      người dùng thấy một mảng lịch bị các ô nhập che mất một nửa.
   ---------------------------------------------------------------------------------------------------- */
.wtc-kids-table.table-responsive { overflow: visible; }
.wtc-kids-table .flatpickr-wrapper { position: relative; }
.wtc-kids-table .flatpickr-calendar { z-index: 1060; }

/* Lịch trong bảng việc con MỞ NGƯỢC LÊN TRÊN.
   Ở chế độ `static` (bắt buộc khi ô nằm trong modal), Flatpickr KHÔNG tự lật hướng: `positionCalendar`
   thoát sớm nên lịch luôn thả xuống dưới ô. Bảng việc con lại luôn là khối CUỐI của hộp thoại ⇒ đo được
   lịch tràn 143px xuống dưới đáy vùng cuộn, người dùng phải cuộn mới thấy nửa dưới. Mở lên trên là hướng
   duy nhất luôn còn chỗ ở vị trí này.
   Selector đủ đặc hiệu để thắng `.flatpickr-calendar.static { top: calc(100% + 2px) }` của thư viện. */
.wtc-kids-table .flatpickr-calendar.static {
    top: auto;
    bottom: calc(100% + 2px);
}

/* ============================================================================
   Ô CHỌN NGƯỜI (`data-vt-avatar`) — avatar chữ cái + tên, dùng chung toàn hệ thống

   Cùng lớp `.wt-ava` và cùng luật màu với cột người của bảng công việc, để nhìn ô chọn và nhìn bảng ra
   cùng một người. Không kèm phòng ban (user chốt 13/08): trong cùng công ty gọi tên là nhận ra nhau.
   ============================================================================ */
.vt-people-opt {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-width: 0;
    max-width: 100%;
}
/* ★ TO HƠN MẶC ĐỊNH MỘT PHẦN BA (user chốt 18/08/2026): 22px → 30px. Ô chọn người là nơi phải NHẬN RA
   người trước khi kịp đọc tên, mà ở 22px thì khuôn mặt trong ảnh chỉ còn vài chục điểm ảnh — nhìn ra được
   màu áo chứ không ra người. Cỡ chữ đi theo, nếu không hai chữ cái lọt thỏm giữa vòng tròn.
   ⚠ 30px là TRẦN của Ô ĐÃ CHỌN, không phải lựa chọn thẩm mỹ: ô chọn căn theo `form-select-sm` cao ~31px,
     cho avatar 36px vào đây là nó đội cao cả hàng biểu mẫu và lệch với mọi ô khác cùng hàng. Danh sách bung
     không bị ràng buộc đó nên dùng đúng cỡ 36px dùng chung — khai ngay dưới. */
.vt-people-opt .wt-ava { flex: 0 0 auto; width: 30px; height: 30px; font-size: .75rem; }
.vt-people-name { white-space: nowrap; }

/* Trong Ô ĐÃ CHỌN: tên dài cắt có ba chấm, không được đẩy rộng ô hay tràn ra ngoài thẻ. */
.select2-selection .vt-people-name { overflow: hidden; text-overflow: ellipsis; }

/* Trong DANH SÁCH BUNG: ngược lại — hiện ĐỦ tên. Danh sách bám bề rộng ô (ô trong bảng việc con chỉ
   ~150px) thì mọi dòng đều cụt và không ai chọn đúng được người mình cần. `dropdownAutoWidth` lo phần
   nở theo nội dung; `min-width` lo trường hợp danh sách chỉ có vài tên ngắn, để nó không hẹp lại thành
   một dải mảnh nằm chơ vơ. */
.vt-people-dropdown { min-width: 260px; }
.vt-people-dropdown .vt-people-name { overflow: visible; text-overflow: clip; }

/* ★ TÊN DÀI PHẢI XUỐNG DÒNG TRONG DANH SÁCH BUNG (vá 17/08/2026, user chỉ ra trên màn thật).
   Luật `white-space: nowrap` ở trên viết ngày 13/08 cho hoàn cảnh khi đó: nhãn một dòng người CHỈ CÓ TÊN.
   Bộ chọn đích trình (17/08) thêm vào nhãn "· phòng · công ty  ⚠ chưa có quyền duyệt" — dài gấp hai đến ba
   lần — nên trong hộp thoại hẹp, dòng chữ không xuống dòng mà cũng không được cắt (`text-overflow: clip`)
   đã kéo dài 487px trong danh sách 260px: chữ bị che, danh sách mọc thanh cuộn ngang, và người chọn không
   đọc được mình đang chọn ai.
   ⚠ Chỉ áp cho DANH SÁCH BUNG. Ô ĐÃ CHỌN vẫn phải một dòng cắt ba chấm (luật ngay trên) — cho nó cao hai
     hàng là đẩy vỡ chiều cao của mọi hàng biểu mẫu đang căn theo `form-select-sm`.
   Avatar canh về ĐẦU dòng: khi tên xuống hai hàng mà avatar vẫn canh giữa thì nó trôi xuống giữa hai hàng
   chữ, trông như thuộc dòng dưới. */
.vt-people-dropdown .vt-people-name { white-space: normal; overflow-wrap: anywhere; }
.vt-people-dropdown .vt-people-opt { align-items: flex-start; }
/* ★ DANH SÁCH BUNG DÙNG ĐÚNG CỠ 36px DÙNG CHUNG — đây mới là lúc người ta nhìn mặt để chọn đúng người,
   và ở đây không có trần chiều cao nào như trong ô đã chọn. */
.vt-people-dropdown .vt-people-opt .wt-ava { margin-top: .1rem; width: 32px; height: 32px; font-size: .75rem; }

/* Thẻ người đã chọn (dạng chọn NHIỀU): Select2 canh chữ theo `line-height` mặc định của nó, avatar cao
   hơn nên phải kéo cả thẻ về canh giữa, nếu không chữ và avatar lệch nhau nửa dòng. */
.select2-container--default .select2-selection--multiple .select2-selection__choice { display: inline-flex; align-items: center; }

/* ★ DẤU × RA SAU TÊN (user chốt 17/08/2026: *"cái xấu 'x' xóa nó nằm đằng sau tên được không… cho hoàn
   thiện luôn sau này không động đến nó nữa"*).
   Select2 4.x đặt nút xoá là phần tử ĐẦU TIÊN trong thẻ, nên mặc định nó chen giữa mép thẻ và avatar —
   mắt đọc gặp dấu xoá trước cả người. ⛔ KHÔNG sửa bằng JS đổi thứ tự DOM: Select2 dựng lại thẻ mỗi lần
   chọn/bỏ chọn, mọi can thiệp DOM đều bị xoá ở lượt sau và phải gắn lại bằng observer. `order` của
   flexbox đổi được thứ tự HIỂN THỊ mà không đụng DOM, nên đúng một lần là xong.
   Áp cho MỌI ô chọn nhiều của toàn hệ thống — không riêng ô chọn người. */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
    gap: .25rem;
    padding-right: .35rem;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    order: 99;              /* đẩy xuống cuối hàng flex — sau avatar và sau tên */
    margin: 0 0 0 .1rem;    /* margin-right mặc định của Select2 nay thành lề TRÁI */
    padding: 0 .1rem;
    line-height: 1;
    opacity: .65;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    opacity: 1;
}

.select2-container--default .select2-selection--single .select2-selection__rendered { display: flex; align-items: center; }

/* Ô CHƯA CHỌN AI: hiện icon người-trống giống chỗ "chưa giao ai" của bảng/Kanban, để ô rỗng vẫn nói được
   nó là ô chọn người chứ không phải một ô nhập chữ. */
.vt-people-empty { display: inline-flex; align-items: center; gap: .35rem; color: #98a2b3; }

/* Khối nội dung trong hộp thoại XEM NHANH: hiện đủ, dài thì cuộn TRONG KHỐI. Không giới hạn thì một mô tả
   dài kéo hộp thoại vượt chiều cao màn hình, nút "Xem chi tiết" ở chân tụt khỏi tầm nhìn. */
.vt-quick-rich {
    max-height: 220px;
    overflow-y: auto;
}
.vt-quick-rich > .vt-rich-view > :last-child { margin-bottom: 0; }

/* ============================================================================
   MỤC TRONG MENU THẢ XUỐNG — một dáng duy nhất, bất kể thẻ <a> hay <button>

   Đo được trên menu ⋮ của bảng công việc (13/08): ba mục cạnh nhau mà lệch BA thứ cùng lúc, chỉ vì
   "Xem chi tiết" là thẻ <a> còn "Sửa"/"Thêm việc con" là <button>:
     · <a>      → đậm 500, màu #212B36, cỡ 14px
     · <button> → đậm 400, màu #646B72, cỡ 13px
   Một mục nổi hẳn lên giữa menu trông như mục đang được chọn hoặc mục quan trọng hơn — trong khi cả ba
   chỉ là ba lựa chọn ngang hàng.

   Chốt theo dáng của <button> (nhẹ, xám) vì đó là dáng của đa số mục trong hệ thống. Mục nào thật sự cần
   nổi bật (hành động phá vỡ) thì tự khai lớp riêng như `.text-danger`, không dựa vào việc nó là thẻ gì.
   ============================================================================ */
.dropdown-menu .dropdown-item {
    font-weight: 400;
    font-size: .8125rem;
    color: #646b72;
}

/* ============================================================================
   CHIP BUNG KHỐI PHỤ trong hộp thoại tạo/sửa công việc (`.wtc-chip`)

   Cùng dáng VIÊN THUỐC với chip lọc nhanh `.wt-chip` của thanh điều kiện: nền trắng, viền mảnh, bo tròn,
   chữ xám; đang bật thì nền cam nhạt + viền cam + chữ nâu đỏ.

   ⚠ Vì sao khai ở đây mà không dùng thẳng `.wt-chip`: `.wt-chip` nằm trong `work/tasks/_index-css`, chỉ nạp
   ở màn danh sách công việc — trong khi hộp thoại này dùng chung cho BA màn (danh sách, chi tiết phiếu,
   chi tiết nhóm việc). Đặt ở đây thì cả ba màn cùng một dáng.

   Trước đó chip mang `btn btn-link p-0` nên là chữ xanh không viền, và khi bật thì handler cũ gán nhầm
   `btn-primary` ⇒ năm nút cam đặc nằm liền nhau, đọc như năm lệnh nguy hiểm chứ không phải năm đường dẫn
   khai thêm thông tin.

   ⚠ Chip CỐ Ý không mang lớp `.btn`/`.btn-sm` của Bootstrap: để lẫn thì `.btn-sm` giành mất `padding`
   (đo được `4px 8px` thay vì `4px 11.2px`) — hai lớp cùng độ đặc hiệu nên ai nạp sau thắng, và cuộc tranh
   ấy đổi kết quả tuỳ thứ tự tệp CSS. Chip tự khai đủ dáng của nó, không mượn gì của Bootstrap.
   ============================================================================ */
.wtc-chip {
    display: inline-block;
    padding: .25rem .7rem;
    border-radius: 14px;
    font-size: .75rem;
    border: 1px solid #e6eaed;
    background: #fff;
    color: #67748e;
    white-space: nowrap;
    line-height: 1.5;
    text-decoration: none;
    cursor: pointer;
}
.wtc-chip:hover { border-color: #c9d2dc; color: #092c4c; background: #fff; }
.wtc-chip.active { background: #fff6ee; border-color: #e04f16; color: #b85c00; font-weight: 600; }

/* ============================================================================
   BỘ CHỌN ĐOẠN — `.vt-segment` (14/08/2026, user chốt: "làm CSS cho toàn hệ thống
   để sửa 1 chỗ và áp dụng ở nhiều nơi")
   ----------------------------------------------------------------------------
   Dùng cho những dải lựa chọn NGANG, LOẠI TRỪ NHAU mà người dùng đổi qua lại liên tục:
   dải kỳ báo cáo (Ngày · Tuần · Tháng · Quý · Năm · Đột xuất), bộ lọc khoảng thời gian,
   chuyển góc nhìn danh sách…

   ⚠ Vì sao KHÔNG dùng `btn-group` + `btn-outline-secondary` của Bootstrap: mỗi mục thành
   một cái NÚT có viền đậm, năm sáu nút dính nhau tạo thành một khối nặng chiếm hết vùng
   nhìn — trong khi đây chỉ là chỗ đổi góc nhìn, không phải sáu hành động ngang tầm quan
   trọng. Bộ chọn đoạn phẳng, không viền từng mục; chỉ mục ĐANG CHỌN nổi lên bằng nền
   trắng + màu chủ đạo, giống lối segmented control quen thuộc.

   ⚠ Cũng KHÔNG mang lớp `.btn` của Bootstrap — cùng lý do đã ghi ở `.wtc-chip`: `.btn-sm`
   giành mất `padding` và kết quả đổi theo thứ tự nạp tệp CSS.

   Cách dùng:
     <div class="vt-segment">
         <a class="vt-segment__item is-active" href="…">Tháng</a>
         <a class="vt-segment__item" href="…">Quý</a>
     </div>
   Dùng được cho cả `<a>` và `<button>`. Trạng thái chọn = `.is-active`
   (KHÔNG dùng `.active` — tránh đụng luật của `.nav-link.active`/`.btn.active` Bootstrap).
   ============================================================================ */
.vt-segment {
    display: inline-flex;
    align-items: center;
    /* Nền TRÙNG nền thẻ (user chốt 14/08/2026): dải này chỉ để đổi góc nhìn, không phải một khối điều
       khiển nặng — tô nền xám riêng là tự tách nó ra khỏi thẻ và kéo mắt về phía nó. Các mục dính liền
       nhau, ngăn bằng đúng một đường viền chung. */
    border: 1px solid #e6eaed;
    border-radius: 8px;
    overflow: hidden;
    background: transparent;
}
.vt-segment__item {
    display: inline-block;
    padding: .35rem .9rem;
    border: 0;
    border-left: 1px solid #e6eaed;
    background: transparent;
    color: #67748e;
    font-size: .8125rem;
    line-height: 1.5;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
}
.vt-segment__item:first-child { border-left: 0; }
.vt-segment__item:hover { color: #092c4c; background: #f7f9fb; }
.vt-segment__item.is-active {
    background: #fff6ee;
    color: #e04f16;
    font-weight: 600;
}

/* ══════════════════════════════════════════════════════════════════════════
   .vt-btn-soft — NÚT NHẸ, LẶP LẠI NHIỀU LẦN TRONG MỘT DANH SÁCH (S21, 26/08/2026)

   ★ VÌ SAO CÓ LỚP NÀY. Anh Dũng chỉ trên màn thật: nút "Nhắc" đang là `btn-warning`
     vàng ĐẶC, lặp lại chín lần dọc một bảng — chín vệt vàng chói kéo mắt khỏi chính
     thứ cần đọc là tên đơn vị và tiến độ. Nguyên văn: *"mầu ở nút nhắc hơi chéo nên
     để dạng bo và mầu nền giống actived menu chẳng hạn"*.

   ★ NGUYÊN TẮC NÚT của phân hệ (chốt 26/08) — dùng ĐÚNG một bảng cho mọi màn:
       · hành động CHÍNH của màn            → .btn-primary            (cam đặc)
       · hành động phụ TÍCH CỰC             → .btn-outline-primary
       · hành động TRUNG TÍNH               → .btn-outline-secondary
       · hành động CẢNH BÁO (trả lại)       → .btn-outline-warning
       · hành động PHÁ HUỶ (xoá)            → .btn-outline-danger
       · hành động NHẸ, LẶP LẠI trong bảng  → .vt-btn-soft            ← lớp này

   ⚠ Màu lấy NGUYÊN từ nền menu active của theme (#fff6ee / #e04f16) — cùng bảng màu
     với `.vt-segment__item.is-active` ngay trên. ⛔ Đừng chế màu mới: cả dự án chỉ có
     MỘT tông nhấn, thêm tông thứ hai là bắt người dùng học lại ý nghĩa màu.
   ⚠ Bo TRÒN HẲN (pill) để phân biệt với nút hành động vuông góc — hình dáng nói
     "đây là thao tác phụ" trước cả khi người ta đọc chữ trên nút.
   ⚠ Dùng cho <a> lẫn <button>; đi kèm `.btn .btn-sm` của Bootstrap để thừa kế cỡ chữ,
     ⛔ không khai lại padding/font-size ở đây. */
.vt-btn-soft {
    border-radius: 999px;
    background: #fff6ee;
    border: 1px solid #f3d3c0;
    color: #b85c00;
    font-weight: 600;
}
.vt-btn-soft:hover,
.vt-btn-soft:focus {
    background: #ffe9d9;
    border-color: #f0b48f;
    color: #93490b;
}
.vt-btn-soft:focus-visible { outline: 2px solid #e04f16; outline-offset: 1px; }
.vt-btn-soft:disabled, .vt-btn-soft.disabled { opacity: .55; }

/* .vt-btn-xs — NÚT PHỤ, BÉ HƠN `btn-sm` MỘT CẤP.

   ★ Anh Dũng 26/08: *"những nút chính nên để giống trên toolbar bạn đang làm, thế mới
     nhấn mạnh, còn các nút khác nên để bé"*. Bootstrap chỉ có `btn-sm` / `btn-lg`, nên
     mọi nút trên một thanh đều bằng nhau và ⛔ không nói được cái nào quan trọng hơn.
   ⇒ Phân cấp bằng HAI trục cùng lúc: MÀU (đặc = chính, viền = phụ) và CỠ (`btn-sm` =
     chính, `.vt-btn-xs` = phụ). Một trục thôi thì hoặc thanh nút trông đơn điệu, hoặc
     người dùng phải đọc chữ mới biết đâu là việc chính.
   ⚠ ⛔ KHÔNG dùng cho nút chính của màn — dùng rồi thì ⛔ không còn gì để nhấn mạnh. */
.vt-btn-xs {
    padding: .2rem .55rem;
    font-size: .75rem;
    line-height: 1.45;
}

/* ══════════════════════════════════════════════════════════════════════════
   .vt-meta-chips — DẢI THÔNG TIN MỎNG thay cho một card "Thông tin" ở cột phải.

   ★ VÌ SAO. Cột phải cũ giữ phạm vi · loại · kỳ · người lập · trạng thái · hạn nộp,
     và nó ăn ~1/3 bề ngang màn suốt cả trang — trong khi bảng đơn vị, khối việc đang
     kẹt và ô nhận định ở cột trái thì chật. Anh Dũng 26/08: *"bố trí ở đâu cho phù hợp
     để nội dung bên phải được hiển thị đủ rộng hơn"*.
   ⇒ Sáu dòng ấy là THÔNG TIN NHẬN DẠNG, đọc một lần rồi thôi — đúng dạng để nằm ngang
     thành một dải chip mỏng dưới tiêu đề, nhường trọn bề ngang cho phần phải làm việc.

   ⚠ `flex-wrap` chứ ⛔ không cuộn ngang: ở màn hẹp dải tự xuống dòng, ⛔ không giấu mất
     chip cuối — hạn nộp là thứ ⛔ không được phép khuất. */
.vt-meta-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .75rem;
    font-size: .8125rem;
}
.vt-meta-chips > span { display: inline-flex; align-items: center; gap: .3rem; }
.vt-meta-chips .vt-meta-chips__k { color: #8a94a6; }

.vt-segment-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid #e6eaed;
    border-radius: 8px;
    background: #fff;
    color: #67748e;
    text-decoration: none;
}
.vt-segment-nav:hover { border-color: #c9d2dc; color: #092c4c; }

/* ============================================================================
   THANH KÉO TỈ LỆ % — `.vt-range` (14/08/2026, user chốt)
   ----------------------------------------------------------------------------
   Dùng cho mọi ô nhập TỈ LỆ HOÀN THÀNH trong hệ thống. Ô số thuần bắt người dùng gõ rồi
   tự hình dung "70 là nhiều hay ít"; thanh kéo cho thấy ngay vị trí trên đoạn 0–100 và
   sửa nhanh bằng một cú kéo.

   Cách dùng — `<input type="range" class="vt-range">` kèm một ô hiện số:
     <div class="vt-range-wrap">
         <input type="range" class="vt-range" name="progress_proposed" min="0" max="100" step="5" value="30">
         <output class="vt-range-value">30%</output>
     </div>
   Phần cập nhật số khi kéo nằm trong `layout/partials/vt-forms-init` — dùng chung, KHÔNG
   viết lại handler ở từng màn.

   ⚠ Vệt đã đi qua tô màu chủ đạo bằng `background-size` theo `--vt-range-percent` (biến do
   handler đặt): dùng gradient tĩnh thì thanh lúc nào cũng đầy màu, mất luôn thông tin.
   ============================================================================ */
.vt-range-wrap {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding-top: .25rem;
}
/* Cột chứa thanh + hàng nhãn mốc, để hai đầu thang đo thẳng hàng với hai đầu thanh. */
.vt-range-track { flex: 1 1 auto; }
/* Nhãn MỐC hai đầu (`0` … `100%`) — user chốt 14/08/2026: không có mốc thì người dùng phải đoán
   thanh chạy từ đâu tới đâu, nhất là khi con trỏ đang nằm giữa. */
.vt-range-scale {
    display: flex;
    justify-content: space-between;
    margin-top: 1px;
    font-size: .6875rem;
    color: #8a94a6;
    line-height: 1;
}
.vt-range {
    display: block;
    width: 100%;
    -webkit-appearance: none;
    appearance: none;
    height: 14px;          /* vùng bấm; vệt màu do TRACK vẽ, cao 6px */
    background: transparent;
    outline: none;
    cursor: pointer;
    margin: 0;
}
/* ⚠ VỆT MÀU PHẢI VẼ TRÊN ::track, KHÔNG trên chính `input` (đã vấp 14/08/2026: đặt `background` lên
   input thì Chrome vẫn vẽ track mặc định ĐÈ LÊN, ra một thanh trắng trơn — nhìn như hỏng). Cùng công
   thức với vạch tiến độ ở sơ đồ Gantt và cột % của Bảng công việc: rãnh xám, phần đã đi qua tô màu
   chủ đạo. */
.vt-range::-webkit-slider-runnable-track {
    height: 6px;
    border-radius: 999px;
    background: #eef1f5;
    background-image: linear-gradient(#e04f16, #e04f16);
    background-repeat: no-repeat;
    background-size: var(--vt-range-percent, 0%) 100%;
}
.vt-range::-moz-range-track {
    height: 6px;
    border-radius: 999px;
    background: #eef1f5;
}
.vt-range::-moz-range-progress {
    height: 6px;
    border-radius: 999px;
    background: #e04f16;
}
/* KHÔNG có nút tròn (user chốt: "đừng để hình tròn chạy thế"). Con trượt bề rộng 0 — vẫn kéo/bấm được
   vì `input[type=range]` nhận thao tác trên toàn bộ rãnh; `display:none` thì Chrome/Firefox bỏ luôn
   khả năng kéo. */
.vt-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 0;
    height: 6px;
    border: 0;
    background: transparent;
}
.vt-range::-moz-range-thumb {
    width: 0;
    height: 6px;
    border: 0;
    background: transparent;
}
.vt-range:disabled { opacity: .55; cursor: default; }
.vt-range-value {
    min-width: 3.25rem;
    text-align: right;
    font-weight: 600;
    color: #092c4c;
    font-variant-numeric: tabular-nums;
}

/* ============================================================================
   THẺ MỘT ĐẦU VIỆC trên màn nhập báo cáo — `.vt-report-line` (14/08/2026, user chốt:
   "căn chỉnh để hình nó nổi lên và phân bổ cho cân đối")
   ----------------------------------------------------------------------------
   Trước đó mỗi dòng chỉ là `border rounded p-3`: mười đầu việc xếp liền nhau thành mười
   khung xám giống hệt, không biết một đầu việc bắt đầu và kết thúc ở đâu. Thẻ NỔI lên nền
   xám nhạt của trang bằng nền trắng + bóng mảnh, và có dải màu chủ đạo bên trái khi con
   trỏ đi qua để mắt bám được dòng đang thao tác.
   ============================================================================ */
.vt-report-line {
    position: relative;
    background: #fff;
    /* Cùng token dáng với `.vt-accordion-row` (user chốt: "các đầu việc trong trang báo cáo cũng để
       dạng này") — một hệ thống chỉ nên có MỘT dáng hàng danh sách. */
    border: 1px solid #eceff3;
    border-radius: 10px;
    padding: .7rem .85rem;
    margin-bottom: .5rem;
    transition: background .15s ease, border-color .15s ease;
}
.vt-report-line::before {
    content: "";
    position: absolute;
    left: 0;
    top: 12px;
    bottom: 12px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: transparent;
    transition: background .15s ease;
}
.vt-report-line:hover,
.vt-report-line:focus-within {
    border-color: #dfe5ec;
}
.vt-report-line:focus-within::before { background: #e04f16; }
/* Dòng ĐÃ GỬI trong kỳ — lùi về sau một bậc, để mắt rơi vào việc còn phải làm. */
.vt-report-line.is-done { background: #fbfcfd; }

/* Chip TRẢI HẾT HÀNG (`.wtc-chip--block`): dùng khi chip là đường bung duy nhất của một khối,
   như nút "Kết quả · Vướng mắc · …" trên thẻ đầu việc. Bấm dễ hơn hẳn một chip nhỏ nép trái,
   và nó tự trở thành đường ngăn giữa phần luôn hiện với phần mở thêm. */
.wtc-chip--block {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    width: 100%;
    border-radius: 8px;
    border-style: dashed;
    padding: .45rem .7rem;
    background: #fafbfc;
}
.wtc-chip--block:hover { background: #fff6ee; border-color: #f0b48f; color: #b85c00; }
.wtc-chip--block .js-mui-ten { transition: transform .15s ease; }

/* ============================================================================
   HÀNG GẬP — `.vt-accordion-row` (14/08/2026, user chỉ mẫu: khối "gom theo người,
   bấm để mở" của mockup)
   ----------------------------------------------------------------------------
   Một hàng đọc như mục danh sách: số thứ tự · tên mục · dấu hiệu phụ · mũi tên ở MÉP PHẢI.
   Bấm cả hàng để bung phần nội dung bên dưới.

   Dùng cho: các ô khai thêm trong hộp thoại báo cáo, khối "đã có báo cáo" gom theo người,
   và mọi chỗ cần xếp N mục cùng cấp mà chỉ mở một hai mục.

     <button class="vt-accordion-row js-mo-them" data-target="#x">
         <span class="vt-accordion-row__no">3.</span>
         <span class="vt-accordion-row__title">Kết quả đạt được</span>
         <i class="ti ti-chevron-down js-mui-ten"></i>
     </button>

   ⚠ Vì sao KHÔNG dùng lại `.wtc-chip--block`: chip là viên thuốc bo tròn, viền nét đứt —
   dáng của một "đường dẫn khai thêm", hợp khi có vài ba cái nằm rời. Xếp năm sáu chip nét
   đứt chồng lên nhau thì trông như biểu mẫu chưa hoàn thiện. Hàng gập là dáng danh sách.
   ============================================================================ */
.vt-accordion-row {
    display: flex;
    align-items: center;
    gap: .6rem;
    width: 100%;
    padding: .6rem .85rem;
    border: 1px solid #eceff3;
    border-radius: 10px;
    background: #fff;
    color: #092c4c;
    font-size: .8125rem;
    text-align: left;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.vt-accordion-row:hover { background: #fafbfc; border-color: #dfe5ec; }
.vt-accordion-row.active { border-color: #f0b48f; background: #fffaf6; }
.vt-accordion-row__no { color: #8a94a6; font-variant-numeric: tabular-nums; }
.vt-accordion-row__title { flex: 1 1 auto; font-weight: 500; }
.vt-accordion-row .js-mui-ten {
    color: #8a94a6;
    font-size: 1rem;
    transition: transform .15s ease;
}
.vt-accordion-row.active .js-mui-ten { color: #e04f16; }
/* HÀNG CẦN CHÚ Ý — đơn vị/cán bộ CHƯA NỘP báo cáo kỳ này (bản vẽ tô nền hồng nhạt cho đúng
   những hàng ấy, 23/08/2026). Nền chứ không phải viền: người lập quét dọc danh sách 9 hàng để
   tìm "ai còn thiếu", và một dải nền bắt mắt nhanh hơn hẳn một badge nằm giữa hàng.
   ⚠ Nền phải ĐỤC (không alpha) — hàng này dùng chung khuôn với `_block-row`, nơi cụm badge bên
     phải có thể nằm trên vùng cuộn ngang; nền trong suốt để lộ chữ chồng lên nhau khi cuộn.
   ⚠ Sắc rất nhạt, ⛔ không dùng đỏ cảnh báo thật: cả một danh sách đỏ rực thì mắt hết phân biệt
     được hàng nào là hàng đang quá hạn thật sự (badge "N quá hạn" mới mang nghĩa ấy). */
.vt-accordion-row--canh-bao { background: #fef6f4; border-color: #f6ddd5; }
.vt-accordion-row--canh-bao:hover { background: #fdf0ec; border-color: #f0c9bd; }

/* Chấm báo "mục này đã có nội dung" — thấy ngay mà không phải mở từng mục. */
.vt-accordion-row__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #22c55e;
    flex: 0 0 auto;
}

/* ============================================================================
   TIÊU ĐỀ MỤC trong một thẻ dài — `.vt-section-head` (14/08/2026, user chốt)
   ----------------------------------------------------------------------------
   Khi cả bản báo cáo nằm trong MỘT thẻ, các mục bên trong (A · Việc tôi trực tiếp làm ·
   B · Việc tôi giao · Đã gửi trong kỳ) phải tự tách ra khỏi phần nội dung ngay dưới nó —
   nếu không, dòng tiêu đề trôi lẫn vào danh sách và người đọc không biết mục nào bắt đầu
   ở đâu.

   Thiết kế PHẲNG: một dải nền xám rất nhạt + đường kẻ dưới, không bóng đổ.

     <div class="vt-section-head">
         <h6 class="mb-0">A · Việc tôi trực tiếp làm</h6>
         <span class="badge …">2 việc</span>
         <div class="ms-auto">…nút…</div>
     </div>
   ============================================================================ */
.vt-section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: 0 0 .45rem 0;
    margin: 1.5rem 0 .75rem;
    /* KHÔNG nền màu, nhưng CÓ một đường kẻ NGAY DƯỚI TIÊU ĐỀ (user chốt 14/08/2026, sau khi đã thử cả
       ba cách: nền xám — bác; kẻ ngăn giữa hai mục — bác; kẻ dưới tiêu đề — chọn). Đường kẻ chạy hết
       bề ngang, gạch chân cả dòng tiêu đề, nên nó đọc như đầu đề một chương chứ không phải vách ngăn. */
    border-bottom: 1px solid #eceff3;
}
.vt-section-head h6 {
    font-size: .9375rem;
    font-weight: 600;
    letter-spacing: -.01em;
}
/* Câu dẫn ngay dưới tiêu đề mục — trong cùng khối để không rời khỏi tiêu đề nó giải thích. */
.vt-section-head__note {
    flex: 1 0 100%;
    margin: .15rem 0 0;
    font-size: .8125rem;
    color: #8a94a6;
}

/* ============================================================================
   VÙNG NHẤN — `.vt-panel-accent` (14/08/2026, user chốt: "phải có vùng khoanh màu
   khác như này để phân biệt")
   ----------------------------------------------------------------------------
   Dùng cho khối KẾT LẠI của một màn nhập dài: phần người dùng phải điền sau cùng rồi mới
   gửi đi — "Nhận định chung của kỳ" ở màn báo cáo là ca mẫu.

   Vì sao cần: khi trên trang đã có năm bảy card trắng giống hệt nhau, khối quan trọng nhất
   chìm lẫn vào giữa và người dùng cuộn qua nó. Viền + nền tiêu đề màu chủ đạo nhạt tách nó
   ra khỏi phần liệt kê, mà không ồn như một `alert` đỏ.

     <div class="card vt-panel-accent">
         <div class="card-header">…tiêu đề…</div>
         <div class="card-body">…</div>
         <div class="card-footer">…nút hành động cuối…</div>
     </div>
   ============================================================================ */
.vt-panel-accent {
    border: 1px solid #f6d5c0;
    border-radius: 10px;
    overflow: hidden;
}
.vt-panel-accent__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    padding: .6rem .85rem;
    background: #fff6ee;
    border-bottom: 1px solid #f6d5c0;
}
.vt-panel-accent__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: .75rem .85rem;
    background: #fffaf6;
    border-top: 1px solid #f6d5c0;
}

/* ============================================================================
   THẺ MỘT CON SỐ — `.vt-stat` (21/08/2026, S21 C1)
   ----------------------------------------------------------------------------
   Vì sao cần: phân hệ Báo cáo đang có BA dáng thẻ số khác nhau trên bốn màn —
     · Dashboard: card + chip avatar màu + `h4`
     · Màn xem báo cáo: card + icon trần `fs-3` + `h5`
     · Khối B của "Báo cáo của tôi": ô viền, chữ giữa, KHÔNG icon
   Ba dáng cho cùng một loại thông tin làm người dùng phải học lại cách đọc ở mỗi màn, và
   khiến hai màn đặt cạnh nhau trông như hai sản phẩm. Một dáng, khai một chỗ.

     <div class="vt-stat">
         <span class="vt-stat__icon bg-soft-primary text-primary"><i class="ti ti-clipboard-list"></i></span>
         <div class="vt-stat__body">
             <div class="vt-stat__num">12</div>
             <div class="vt-stat__label">Tổng đầu việc</div>
         </div>
     </div>

   ⚠ Icon là TUỲ CHỌN — bỏ `.vt-stat__icon` thì con số tự dồn sang trái, không vỡ dáng.
   ⚠ Tự cao bằng nhau trong một hàng grid (`height: 100%`): nhãn dài ngắn khác nhau mà thẻ
     cao thấp lệch nhau là thứ đập vào mắt trước cả con số.
   ============================================================================ */
.vt-stat {
    display: flex;
    align-items: center;
    gap: .6rem;
    height: 100%;
    padding: .7rem .85rem;
    border: 1px solid #eceff3;
    border-radius: 10px;
    background: #fff;
}
.vt-stat__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: 8px;
    font-size: 1.125rem;
}
.vt-stat__body { min-width: 0; }
.vt-stat__num {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
    color: #092c4c;
    /* Cột số phải thẳng hàng giữa các thẻ — chữ số tỉ lệ làm "111" hẹp hơn "888". */
    font-variant-numeric: tabular-nums;
}
.vt-stat__label {
    font-size: .75rem;
    color: #8a94a6;
    line-height: 1.35;
}

/* ============================================================================
   TRẠNG THÁI RỖNG GỌN — `.vt-empty-slim` (22/08/2026, luồng 1 bước 1.4)
   ----------------------------------------------------------------------------
   Vì sao cần: bản vẽ gọi tên đây là vấn đề #11 — *"empty-state chiếm nửa màn"*. Khối rỗng
   cũ (`text-center py-4` + icon `fs-1`) vốn viết cho MÀN TRỐNG HOÀN TOÀN, nhưng đang bị
   dùng cho DANH SÁCH CON NẰM TRONG THẺ. Hệ quả thấy rõ trên ảnh bạn gửi: câu "Bạn đã báo
   cáo đủ mọi đầu việc" bày to gần nửa màn, ngay phía trên danh sách việc vừa gửi — một tin
   VUI chiếm nhiều chỗ hơn chính dữ liệu người dùng vào đây để xem.

     <div class="vt-empty-slim"><i class="ti ti-checkbox"></i>Không còn đầu việc nào</div>

   ⛔ HAI TÌNH HUỐNG KHÁC NHAU, ĐỪNG ĐỔI TUỐT:
     · Danh sách con bên trong thẻ đang có nội dung khác     ⇒ `.vt-empty-slim` (một dòng).
     · Cả thẻ trống và cần MỜI người dùng hành động (kèm nút
       "Sinh lại số liệu" / "Tổng hợp lại")                 ⇒ GIỮ khối lớn — ở đó khoảng
       trống là có ích, nó dẫn mắt tới đúng cái nút đáng bấm.

   ⚠ Viền ĐỨT chứ không liền: viền đứt nói "chỗ này trống", viền liền đọc như một thẻ dữ
     liệu thật và người dùng sẽ dừng lại tìm nội dung trong đó.
   ⚠ Màu lấy đúng bộ đang dùng khắp tệp này (`#8a94a6` chữ mờ · `#e6eaed` viền) — ⛔ không
     pha màu mới, thêm một sắc xám thứ tư là bắt đầu lệch giữa các màn.
   ============================================================================ */
.vt-empty-slim {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: .7rem;
    border: 1px dashed #e6eaed;
    border-radius: 8px;
    background: #fcfdfe;
    color: #8a94a6;
    font-size: .75rem;
    line-height: 1.5;
    text-align: center;
}
/* Icon là TUỲ CHỌN và luôn NẰM CÙNG DÒNG với chữ — đó chính là khác biệt với khối lớn, nơi
   icon `d-block` chiếm hẳn một dòng riêng. */
.vt-empty-slim > i { font-size: .95rem; opacity: .75; }

/* ============================================================================
   DẢI CÁC BƯỚC — `.vt-steps` (21/08/2026, S21 B2)
   ----------------------------------------------------------------------------
   Dùng cho màn có NHIỀU BƯỚC NẰM TRONG CÙNG MỘT TRANG: "Báo cáo của tôi" (chọn việc →
   soạn & gửi), và sau này là báo cáo đột xuất.

   Vì sao cần: hai bước trong cùng một URL thì không có gì trong khung trình duyệt nói cho
   người dùng biết họ đang ở đâu và còn mấy chặng nữa. Dải này trả lời cả hai, và bước đã
   qua bấm lại được để quay ngược — đó là lý do mỗi mục là `<button>` chứ không phải `<span>`.

     <div class="vt-steps">
         <button type="button" class="vt-steps__item is-active"><span class="vt-steps__no">1</span>Chọn việc</button>
         <button type="button" class="vt-steps__item"><span class="vt-steps__no">2</span>Soạn &amp; gửi</button>
     </div>

   Ba trạng thái: `.is-active` (đang đứng — nền màu chủ đạo) · `.is-done` (đã qua, bấm để
   quay lại — chữ xanh, số thành dấu tích) · mặc định (chưa tới — xám).
   ============================================================================ */
.vt-steps {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
}
.vt-steps__item {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .3rem .85rem;
    border: 1px solid #e6eaed;
    background: #f4f6f8;
    color: #8a94a6;
    font-size: .75rem;
    font-weight: 700;
    line-height: 1.5;
}
.vt-steps__item:first-child { border-radius: 999px 0 0 999px; }

/* ★ S21 V21 — BƯỚC CHƯA MỞ ĐƯỢC (chưa tick đầu việc nào ở bước 1).
   ⚠ MỜ ĐI chứ ⛔ KHÔNG ẩn: ẩn thì người dùng không biết bước 2 tồn tại và không hiểu vì sao
   màn dừng lại. `cursor: not-allowed` + `pointer-events` GIỮ NGUYÊN — vẫn bấm được để nhận
   câu giải thích bằng toast, vì một nút câm là thứ khó chịu hơn cả một nút bị chặn. */
.vt-steps__item.is-disabled {
    opacity: .5;
    cursor: not-allowed;
}
.vt-steps__item:last-child { border-radius: 0 999px 999px 0; }
.vt-steps__item:not(:first-child) { border-left: 0; }
.vt-steps__item.is-active {
    background: #e04f16;
    border-color: #e04f16;
    color: #fff;
}
.vt-steps__item.is-done { color: #17805a; }
.vt-steps__item.is-done:hover { background: #eaf5f0; }
.vt-steps__no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: #e6eaed;
    color: #8a94a6;
    font-size: .625rem;
}
.vt-steps__item.is-active .vt-steps__no { background: #fff; color: #e04f16; }
.vt-steps__item.is-done .vt-steps__no { background: #17805a; color: #fff; }

/* ============================================================================
   BẢNG BÀN LÀM VIỆC CỦA KỲ — `.vt-bench` (21/08/2026, S21 B2)
   ----------------------------------------------------------------------------
   Bảng "nhìn và cập nhật" đứng TRƯỚC form soạn báo cáo. Không dùng DataTables: dữ liệu là
   danh sách đầu việc của đúng một kỳ của đúng một người — vài dòng tới vài chục — mà lại
   cần ô tick, thanh kéo % và nút thao tác ngay trong ô, tức đúng những thứ khung
   server-side làm cho phức tạp thêm mà không đổi lại được gì.

   ⚠ Bọc trong `.vt-bench-wrap` để bảng tự cuộn ngang trên màn hẹp — 7 cột không ép vừa
     992px, mà để cả trang trượt ngang thì mất luôn thanh điều hướng.
   ============================================================================ */
.vt-bench-wrap { overflow-x: auto; }
.vt-bench { width: 100%; margin-bottom: 0; font-size: .8125rem; }
.vt-bench > thead > tr > th {
    padding: .5rem .6rem;
    background: #fbfcfd;
    border-bottom: 1px solid #eceff3;
    color: #67748e;
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    white-space: nowrap;
}
.vt-bench > tbody > tr > td {
    padding: .55rem .6rem;
    border-bottom: 1px solid #f1f3f6;
    vertical-align: middle;
}
/* Cùng token rê chuột với mọi bảng khác của dự án — xem `--vt-row-hover`. */
.vt-bench > tbody > tr:hover > td { background: var(--vt-row-hover); }
/* Dòng bị CHẶN (được giao mà chưa tiếp nhận): nền vàng rất nhạt, không phải `alert` đỏ —
   đây là việc còn phải làm một bước, không phải một lỗi. */
.vt-bench > tbody > tr.is-cho-nhan > td { background: #fffdf6; }
.vt-bench__name { color: #092c4c; }
.vt-bench__name:hover { color: #e04f16; }

/* ============================================================================
   TAB (nav-tabs) — TAB ĐANG MỞ MANG MÀU CHỦ ĐẠO (12/08/2026, user chốt)
   ----------------------------------------------------------------------------
   Bootstrap vẽ tab đang mở bằng viền XÁM `#dee2e6` giống hệt viền tab thường, chỉ khác chỗ mép dưới bị
   xoá đi. Trên nền trắng của card, hai tab cạnh nhau gần như một màu — phải nhìn kỹ mới biết mình đang
   đứng ở tab nào. Đây là thứ lặp ở mọi màn có tab (Việc của tôi, Trung tâm phê duyệt, Kho tài liệu…).

   ⇒ Tab đang mở: viền + chữ theo `#E04F16` — đúng màu chủ đạo dự án, cùng màu đầu bảng và dòng đang chọn
   trong Select2. Mép trên dày 2px để cái đang mở "nhô lên" khỏi hàng.

   ⚠ Khai MỘT chỗ ở đây cho `.nav-tabs` chung, KHÔNG vá trong từng màn: đã có hai bộ tab tự chế
   (`.vt-bd-tabs`, `.vt-dl-tabs`) đi trước — thêm bộ thứ ba là ba dáng tab trong cùng một sản phẩm.
   ⚠ Không đụng `.nav-pills` / `.nav-underline`: chúng có dáng riêng, đổi theo là gãy các màn dùng chúng.
   ============================================================================ */
/* Tab đang mở = một cái THẺ ĐỦ BỐN CẠNH màu chủ đạo, bo góc, nền trắng (user chốt 12/08/2026).
   ⚠ KHÔNG kẻ đường chân chạy suốt hàng tab: hàng tab để phẳng cho gọn — user chốt rõ. Cũng vì thế mà kiểu
   tab mặc định của Bootstrap (ba cạnh + đáy trắng "cắt" vào đường chân) không dùng được ở đây: không có
   đường chân thì cái đáy trắng đó thành một khe hở, nhìn như hộp mất chân. */
.nav-tabs { border-bottom: 0; }
.nav-tabs .nav-link { margin-bottom: 0; }
.nav-tabs .nav-link.active,
.nav-tabs .nav-item.show .nav-link {
    color: #E04F16;
    border: 1px solid #E04F16;
    /* 10px chứ không 6px (user chốt 13/08/2026): tab là một cái hộp cao hơn nút thường, bo 6px trên hộp
       cao đó vẫn đọc ra là góc vuông. */
    border-radius: 0.625rem;
    background: #fff;
    font-weight: 600;
}
/* ⚠ Theme có `.nav-tabs.nav-tabs-bottom li a.active { border-radius: 0 }` — ĐẶC HIỆU HƠN quy tắc chung ở
   trên, nên nếu chỉ khai `.nav-tabs .nav-link.active` thì góc bo được đặt rồi bị đè lại về vuông, im lặng.
   Phải khai đúng bộ chọn của theme mới thắng (cùng đặc hiệu, app-custom.css nạp sau). */
.nav-tabs.nav-tabs-bottom li a.active,
.nav-tabs.nav-tabs-bottom .nav-link.active {
    border-radius: 0.625rem;
    border: 1px solid #E04F16;
}
.nav-tabs .nav-link:not(.active):hover { color: #E04F16; border-color: transparent; }
/* Nhãn đếm trên tab đang mở đi theo màu tab — để nguyên xám thì con số trông như bị mờ đi đúng lúc cần đọc. */
.nav-tabs .nav-link.active .badge { background: rgba(224, 79, 22, .12); color: #E04F16; }


/* ═══════════════════════════════════════════════════════════════════════════════════════════════════
   8. THANH TÓM TẮT NEO DÍNH Ở TRANG CHI TIẾT (12/08/2026)
   Trang chi tiết một phiếu dài tới vài màn hình: cuộn xuống khối việc con hay khối thảo luận là mất hết
   ngữ cảnh — phiếu đang ở trạng thái nào, còn bao nhiêu phần trăm, hạn ngày nào, đang chờ ai, và nút cần
   bấm nằm đâu. Thanh này giữ đúng năm thứ đó ở mép trên, ngay dưới thanh tiêu đề cố định.

   ⚠ Điều kiện để `sticky` sống được (đã dính hai lần): KHÔNG tổ tiên nào của nó được có `overflow` khác
   `visible` — kể cả `hidden`, vì `hidden` cũng tạo khung cuộn. Đã kiểm `.page-wrapper` / `.content` sạch.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════ */
.vt-stickybar {
    position: sticky;
    top: var(--vt-topbar-h);
    z-index: 20;                                /* dưới thanh tiêu đề (999) và dropdown, trên nội dung */
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 1rem;
    padding: 9px 14px;
    background: #fff;
    border: 1px solid #e6e8eb;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(16, 24, 40, .06);
}
/* TÊN VIỆC CHỈ HIỆN KHI THANH ĐÃ DÍNH.
   Lúc chưa cuộn, tiêu đề trang nằm ngay phía trên thanh này — hiện thêm một lần nữa là hai cái tên giống
   hệt nhau nằm cách nhau vài chục pixel. Cuộn xuống thì tiêu đề trang khuất, lúc đó tên mới có việc để làm.
   Lớp `is-stuck` do `_js.blade.php` gắn (đo `getBoundingClientRect().top` mỗi lần cuộn) — CSS thuần không
   phát hiện được trạng thái "đang dính". */
.vt-stickybar .vt-sb-title {
    display: none;
    /* Tên hiện ĐỦ, không cắt ba chấm: cắt tên việc là lấy đi đúng thứ giúp người dùng biết mình đang ở đâu.
       Chữ nhỏ hơn một nấc và cho xuống dòng để vẫn vừa chỗ; `align-items:center` của thanh giữ mọi mục căn
       giữa theo chiều dọc kể cả khi tên chiếm hai dòng. */
    flex: 1 1 240px;
    min-width: 0;
    font-size: .8125rem;
    font-weight: 600;
    line-height: 1.35;
    white-space: normal;
}
.vt-stickybar.is-stuck .vt-sb-title { display: inline; }
/* Đã dính thì tách khỏi nền trang bằng bóng đổ rõ hơn — nếu không, thanh trắng trôi trên nền trắng trông
   như một mảnh nội dung bị kẹt lại. */
.vt-stickybar.is-stuck { box-shadow: 0 4px 14px rgba(16, 24, 40, .12); }
.vt-stickybar .vt-sb-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    color: #6b7280;
    white-space: nowrap;
}
.vt-stickybar .vt-sb-item b { color: #26282c; font-weight: 600; }
/* Vạch ngăn mảnh giữa các mục — nhẹ hơn dấu chấm giữa, và không bị hiểu nhầm là dấu câu của nhãn. */
.vt-stickybar .vt-sb-sep { width: 1px; align-self: stretch; background: #e6e8eb; }
.vt-stickybar .vt-sb-bar {
    width: 90px;
    height: 6px;
    border-radius: 4px;
    background: #edeff2;
    overflow: hidden;
}
.vt-stickybar .vt-sb-bar > i { display: block; height: 100%; border-radius: 4px; background: #E04F16; }
.vt-stickybar .vt-sb-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; }

/* Màn hẹp: bỏ tên việc (breadcrumb ngay trên đã nói) và các vạch ngăn, giữ lại đúng phần trạng thái + nút. */
@media (max-width: 767.98px) {
    .vt-stickybar .vt-sb-title,
    .vt-stickybar .vt-sb-sep { display: none; }
    .vt-stickybar { gap: 10px; }
}

/* Nháy sáng khối vừa được nút "đưa tới đúng chỗ" cuộn tới — không có dấu hiệu này thì người dùng bấm nút,
   trang trượt đi, và họ vẫn phải tự tìm xem mình cần làm gì trong khối vừa hiện ra. */
.vt-flash {
    animation: vt-flash-kf 1.6s ease-out 1;
}
@keyframes vt-flash-kf {
    0%   { box-shadow: 0 0 0 3px rgba(224, 79, 22, .55); }
    100% { box-shadow: 0 0 0 3px rgba(224, 79, 22, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .vt-flash { animation: none; box-shadow: 0 0 0 3px rgba(224, 79, 22, .45); }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   9. TRANG CHI TIẾT CÔNG VIỆC — thẻ thông tin · khối nội dung · card thảo luận (13/08/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   Ba thành phần của kiến trúc màn chi tiết đã được duyệt. Khai ở ĐÂY chứ không nhét <style> vào Blade:
   cùng bộ khối này còn dùng lại cho chi tiết nhóm việc và chi tiết báo cáo. */

/* 9.2 — Khối "Nội dung công việc": mỗi ý một dòng, ngăn bằng vạch mảnh, dòng cuối không kẻ. */
.vt-desc-row { padding: 11px 0; border-bottom: 1px solid #f0f1f3; }
.vt-desc-row:last-child { border-bottom: 0; }
.vt-desc-k { font-size: .7188rem; color: #8a8f98; margin-bottom: 3px; }
.vt-desc-v { font-size: .8125rem; color: #26282c; }

/* 9.3 — Card THẢO LUẬN ở cột phải: cao, cuộn trong CHÍNH NÓ, ô nhập luôn ở đáy.
   ⚠ `position: sticky` ở đây chỉ chạy vì KHÔNG tổ tiên nào của nó có `overflow` khác `visible` — cùng điều
   kiện đã cho thanh tóm tắt neo dính hoạt động. Thêm `overflow` vào `.content`/`.page-wrapper` là cả hai
   cùng chết lặng, không lỗi nào báo. */
.vt-chat-card {
    position: sticky;
    top: calc(var(--vt-topbar-h, 65px) + 62px);
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - var(--vt-topbar-h, 65px) - 92px);
}
.vt-chat-body {
    flex: 1 1 auto;
    min-height: 140px;
    overflow-y: auto;
    padding: 14px 16px;
}
.vt-chat-foot { border-top: 1px solid #f0f1f3; padding: 12px 16px; }

/* ── Đầu màn chi tiết công việc: ba dòng, ba vai khác nhau ──────────────────────────────────────────
   ① "Chi tiết công việc"  = TÊN CHỨC NĂNG (mỏ neo cố định, biết đang ở màn nào)
   ② breadcrumb            = đường đi tới đây
   ③ tên phiếu             = NỘI DUNG, dòng quan trọng nhất của trang

   ⚠ Đo được trước khi sửa: khoảng cách ①→② và ②→③ đều đúng **0px** — ba dòng dính thành một khối, mắt
     không tách được đâu là tên màn hình, đâu là tên việc. ① và ② phải sát nhau (chúng cùng là "bạn đang ở
     đâu", đúng mẫu `projects/show`), rồi CÁCH HẲN ra trước ③ vì ③ thuộc về một tầng khác. */
.page-header .page-title + .breadcrumb { margin-top: 2px; }
.wt-task-title {
    margin-top: 14px;
    font-size: 1.125rem; font-weight: 600; color: #092c4c; line-height: 1.35;
}

/* ── Gợi ý nhắc tên khi gõ `@` trong ô thảo luận ────────────────────────────────────────────────────
   Thả LÊN TRÊN ô nhập (`bottom: 100%`): chân card thảo luận nằm sát đáy khung nhìn, thả xuống dưới là
   danh sách lọt ra ngoài màn hình. Khung cha `.vt-chat-foot` đã có `position: relative`. */
.vt-mention-pop {
    position: absolute; bottom: calc(100% - 8px); left: 16px; right: 16px; z-index: 5;
    max-height: 232px; overflow-y: auto;
    background: #fff; border: 1px solid #e6e9ec; border-radius: .5rem;
    box-shadow: 0 8px 24px rgba(9, 44, 76, .12); padding: 4px;
}
.vt-mention-item {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 6px 8px; border: 0; border-radius: .375rem; background: transparent;
    font-size: .8125rem; color: #092c4c; text-align: left;
}
.vt-mention-item:hover, .vt-mention-item.active { background: #f4f6f8; }
.vt-mention-item .wt-ava { width: 22px; height: 22px; font-size: .625rem; flex: 0 0 auto; }
/* Màn hẹp (thảo luận đã rơi xuống dưới cột trái): thôi dính, và giới hạn chiều cao theo nội dung. */
@media (max-width: 1199.98px) {
    .vt-chat-card { position: static; max-height: none; }
    .vt-chat-body { max-height: 420px; }
}

/* 9.4 — Câu chú thích của tiêu đề khối: xuống HẲN dòng dưới, không chen ngang tên khối.
   Chen ngang thì chính cái tên khối bị bóp thành hai dòng, mà tên khối mới là thứ người ta quét mắt tìm. */
.vt-head-hint {
    display: block;
    margin-top: 2px;
    font-size: .75rem;
    font-weight: 400;
    color: #8a8f98;
}

/* 9.5 — DÒNG PHẦN VIỆC (người thực hiện / phối hợp): bốn tầng theo mockup đã duyệt.
   ⚠ Cụm nút phải là MỘT HÀNG RIÊNG ở dưới cùng. Bản cũ đặt nút cùng hàng với tên, và từ khi thảo luận chiếm
   cột phải thì cột trái hẹp lại: tên dài là nút bị đẩy xuống lẻ tẻ, mỗi dòng vỡ một kiểu. */
.wt-person-name { font-size: .875rem; color: #26282c; }
.wt-person-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin-top: 4px;
    font-size: .75rem;
    color: #8a8f98;
}
.wt-person-desc { font-size: .8125rem; margin-top: 6px; }
.wt-person-acts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* 12px chứ không 8px: 8px làm ba nút biểu tượng đọc ra thành một khối liền, bấm dễ trượt tay. */
    gap: 10px 12px;
    margin-top: 12px;
}
/* Đẩy cụm thao tác PHỤ (biểu tượng) hẳn sang phải, tách khỏi nút hành động chính. */
.wt-person-acts-grow { flex: 1 1 auto; }

/* 9.6 — Bảng ĐẦU VIỆC CON: hàng tiêu đề nền cam chữ trắng (mockup đã duyệt). Bảng này nằm lọt giữa những
   khối chữ, tiêu đề nhạt như mặc định thì đọc ra là bốn dòng chữ xám nữa chứ không ra một cái bảng. */
.vt-subtask-table thead th {
    background: #E04F16;
    color: #fff;
    font-weight: 600;
    font-size: .75rem;
    border-color: #E04F16;
    white-space: nowrap;
}
.vt-subtask-table tbody td { font-size: .8125rem; vertical-align: middle; }

/* 9.7 — Thảo luận: avatar chữ cái + bong bóng cho tin của CHÍNH mình (mockup đã duyệt). */
.vt-chat-msg { display: flex; gap: 8px; }
.vt-chat-av {
    width: 26px; height: 26px; flex: none;
    border-radius: 50%;
    background: rgba(224, 79, 22, .10);
    color: #E04F16;
    display: grid;
    place-items: center;
    font-size: .6875rem;
    font-weight: 600;
}
.vt-chat-who { font-size: .8125rem; font-weight: 600; color: #26282c; }
.vt-chat-when { font-size: .6875rem; color: #a3a8b0; margin-left: 6px; }
.vt-chat-txt { font-size: .8125rem; margin-top: 2px; }
.vt-chat-msg.mine .vt-chat-txt {
    background: rgba(224, 79, 22, .10);
    border-radius: 8px;
    padding: 7px 10px;
    display: inline-block;
}

/* 9.8 — Chú thích NGẮN của tiêu đề khối: nằm bên phải cùng hàng (mockup đã duyệt).
   Khác `.vt-head-hint` ở chỗ câu dài mới phải xuống dòng; câu ngắn xuống dòng chỉ làm khối cao thêm vô ích. */
.vt-head-note {
    margin-left: auto;
    font-size: .75rem;
    font-weight: 400;
    color: #8a8f98;
}

/* 9.9 — Vùng KÉO THẢ TỆP của khối "Tệp đính kèm" (mockup đã duyệt). */
.vt-dropzone {
    border: 1px dashed #d7dae0;
    border-radius: 10px;
    padding: 14px;
    text-align: center;
    font-size: .8125rem;
    color: #8a8f98;
    background: #fcfcfd;
    transition: border-color .15s ease, background .15s ease;
}
/* Kéo tệp tới trên vùng: đổi màu ngay. Không có phản hồi này thì người dùng không biết thả vào đâu mới ăn. */
.vt-dropzone.is-over {
    border-color: #E04F16;
    background: rgba(224, 79, 22, .06);
    color: #E04F16;
}

/* ============================================================================
   THANH TIẾN ĐỘ NHỎ TRONG DÒNG — `.wt-prog` (chuyển lên dùng chung 14/08/2026)
   ----------------------------------------------------------------------------
   Nguyên là dáng cột "% hoàn thành" của Bảng công việc, khai trong `work/tasks/_index-css`
   nên CHỈ nạp ở màn danh sách. Màn "Báo cáo của tôi" cần đúng dáng ấy (user chốt: "để thanh
   tiến trình ngắn vào mục đang thực hiện giống tiến độ trong sơ đồ Gantt"), nên định nghĩa
   sống ở đây — cùng lý do `.wtc-chip` đã chuyển: dáng dùng nhiều màn thì ở tệp dùng chung.

     <span class="wt-prog"><span class="wt-bar"><i style="width:70%"></i></span><span class="wt-pct">70%</span></span>

   ⚠ `.wt-bar` PHẢI là flex item của `.wt-prog` — nó là `<span>`, mà `width` không có tác dụng
   lên phần tử inline. Quên `display:inline-flex` ở lớp cha là thanh rộng đúng 0px và biến mất
   không dấu vết (đã vấp 14/08/2026).

   ⚠ `work/tasks/_index-css` vẫn giữ bản khai cũ (giá trị y hệt) — gỡ nó là việc dọn riêng,
   cần chạy lại bộ test màn danh sách trước, không làm lẫn vào đợt này.
   ============================================================================ */
.wt-prog { display: inline-flex; align-items: center; gap: .35rem; }
.wt-bar {
    height: 5px;
    background: #eef1f5;
    border-radius: 3px;
    overflow: hidden;
    flex: 0 0 56px;
    width: 56px;
}
.wt-bar i { display: block; height: 100%; background: #e04f16; border-radius: 3px; }
.wt-pct {
    font-size: .6875rem;
    color: #67748e;
    min-width: 26px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ============================================================================
   TRUNG TÂM BÁO CÁO — mô hình TOẢ NHÁNH `.vt-branch` (15/08/2026, user chốt)
   ----------------------------------------------------------------------------
   Một lõi ở giữa (chuỗi báo cáo + kỳ đang xem), các nhánh toả ra hai bên một thân
   dọc. Dùng ở đầu màn "Báo cáo của tôi"; đợt sau dùng lại nguyên dáng cho màn báo
   cáo đơn vị nên khai ở tệp dùng chung ngay từ đầu.

     <div class="vt-branch">
         <div class="vt-branch__tree">
             <div class="vt-branch__col">…nhánh trái…</div>
             <div class="vt-branch__trunk"></div>
             <div class="vt-branch__col">…nhánh phải…</div>
         </div>
     </div>

   🔴 KHỐI "LÕI" (`.vt-branch__core*`) ĐÃ GỠ KHỎI ĐÂY — 01/09/2026. Anh Dũng bỏ nó khỏi
      màn từ trước (*"bỏ vùng anh khoanh đỏ… thông tin lại thừa mà nó lại chơ vơ"*), nên
      năm quy tắc CSS của nó không còn phần tử nào khớp. Giữ lại là để một bản vẽ SAI
      trong tệp dùng chung: người sau đọc mẫu ở trên rồi dựng lại đúng thứ vừa bị bỏ.
      ⛔ ĐỪNG DỰNG LẠI — nhãn kỳ do dải chọn kỳ (`_center-period`) in, ngay phía trên và
         nằm cạnh nút chuyển kỳ. `WorkReportCenterTest` canh khối này ⛔ không quay lại.

   ⚠⚠ KHOẢNG CÁCH CỘT VÀ CHIỀU DÀI CUỐNG NHÁNH PHẢI BẰNG NHAU (--vt-branch-gap).
      Cuống là một `::after`/`::before` tuyệt đối dài đúng bằng nửa khe giữa hai cột;
      lệch một chút là nét kẻ hụt hoặc đâm xuyên qua thân dọc. Sửa khe thì sửa biến,
      đừng sửa số ở hai chỗ.

   ⚠⚠ FALLBACK XẾP DỌC LÀ BẮT BUỘC, không phải tuỳ chọn. Dáng toả nhánh không xếp nổi
      dưới ~768px: hai cột co lại thì tên nhánh xuống dòng từng chữ. Dưới ngưỡng đó
      thân dọc biến mất, cuống biến mất, các nhánh xếp thành một cột.
      ⚠ Playwright kẹp bề ngang CSS ở ~1521px nên KHÔNG tự kiểm được ngưỡng này —
        phải xem bằng mắt trên trình duyệt thật.
   ============================================================================ */
.vt-branch {
    --vt-branch-gap: 1.5rem;
    /* KHỐNG CHẾ BỀ NGANG (đo trên màn thật 1900px 15/08/2026): để tràn hết thẻ thì tên nhánh nằm mép
       trái còn con số nằm mép phải, cách nhau gần một mét mắt — người đọc phải quét ngang mới ghép được
       "cái gì" với "bao nhiêu". Sơ đồ là thứ để LIẾC, nên nó phải gọn trong một tầm nhìn. */
    max-width: 68rem;
    margin: 0 auto;
}
.vt-branch__tree {
    display: grid;
    grid-template-columns: 1fr 2px 1fr;
    column-gap: var(--vt-branch-gap);
    align-items: stretch;
}
.vt-branch__col { display: flex; flex-direction: column; gap: .6rem; }
.vt-branch__trunk { background: #e6e8eb; }

.vt-branch__node {
    position: relative;
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .75rem;
    border: 1px solid #e9edf2;
    border-radius: 10px;
    background: #fff;
    color: inherit;
    text-decoration: none;
}
a.vt-branch__node[href]:hover {
    border-color: #f0b48f;
    background: #fffaf6;
}
/* Cuống nhánh chạm đúng thân dọc: nửa khe + 1px nửa bề dày thân. */
.vt-branch__node::after {
    content: '';
    position: absolute;
    top: 50%;
    width: calc(var(--vt-branch-gap) / 2 + 1px);
    height: 2px;
    background: #e6e8eb;
}
.vt-branch__node--trai::after { right: calc(-1 * (var(--vt-branch-gap) / 2 + 1px)); }
.vt-branch__node--phai::after { left: calc(-1 * (var(--vt-branch-gap) / 2 + 1px)); }

.vt-branch__ico {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: #f4f6f8;
    color: #67748e;
}
.vt-branch__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.vt-branch__title { font-size: .8125rem; font-weight: 600; color: #26282c; }
.vt-branch__desc {
    font-size: .6875rem;
    color: #8a94a6;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.vt-branch__warn { font-size: .6875rem; color: #d9480f; margin-top: .1rem; }
.vt-branch__num {
    flex: 0 0 auto;
    text-align: right;
    line-height: 1.1;
    /* Số cùng bề rộng chữ ⇒ các nhánh xếp thẳng cột, mắt không phải căn lại từng dòng. */
    font-variant-numeric: tabular-nums;
}
.vt-branch__num b { display: block; font-size: 1.125rem; font-weight: 600; color: #67748e; }
.vt-branch__num em { display: block; font-size: .625rem; font-style: normal; color: #a3a8b0; }

/* Nhánh CÓ VIỆC PHẢI LÀM — nhấn bằng màu con số, không đổi nền: đổi nền cả ô thì ba bốn
   nhánh cùng sáng lên và không ô nào nổi hơn ô nào. */
.vt-branch__node.is-alert .vt-branch__num b { color: #d9480f; }
.vt-branch__node.is-alert .vt-branch__ico { background: #fff1e9; color: #d9480f; }

/* Nhánh THUỘC VAI nhưng chưa dựng xong. Nhạt đi nhưng vẫn đọc được — nó đang nói với người
   dùng "phần này có tồn tại, đang làm", nên không được mờ tới mức thành nhiễu. */
.vt-branch__node.is-soon { background: #fbfcfd; border-style: dashed; cursor: default; }
.vt-branch__node.is-soon .vt-branch__title,
.vt-branch__node.is-soon .vt-branch__ico { color: #a3a8b0; }
.vt-branch__soon {
    margin-left: .3rem;
    padding: .05rem .3rem;
    border-radius: 4px;
    background: #eef1f5;
    color: #8a94a6;
    font-size: .625rem;
    font-weight: 500;
}

@media (max-width: 767.98px) {
    /* XẾP DỌC: một cột, không thân, không cuống. Hai `.vt-branch__col` nối tiếp nhau nên thứ
       tự đọc vẫn là trái-trên-xuống rồi phải-trên-xuống — giữ đúng thứ tự ưu tiên của nhánh. */
    .vt-branch__tree { grid-template-columns: 1fr; row-gap: .6rem; }
    .vt-branch__trunk { display: none; }
    .vt-branch__node::after { display: none; }
}

/* ----------------------------------------------------------------------------
   BIẾN THỂ **CHIA KHỐI** `.vt-branch--blocks` (22/08/2026, bạn chốt)
   ----------------------------------------------------------------------------
   Dáng toả nhánh ở trên bày 11 ô thành hai cột PHẲNG — cạnh nhau mà không cùng
   loại. Bản vẽ đã duyệt chia sơ đồ thành BỐN KHU, mỗi khu một dải tiêu đề, đúng
   cách nhóm menu bên trái của bản vẽ.

     <div class="vt-branch vt-branch--blocks">
         <div class="vt-branch__block">
             <div class="vt-branch__group">Vùng làm việc cá nhân</div>
             <div class="vt-branch__grid">…các nhánh…</div>
         </div>
         …ba khối nữa…
     </div>

   ⚠ KHÔNG có thân dọc ⇒ cuống nhánh PHẢI tắt, nếu không nó chìa ra khoảng trống thành
     nét kẻ cụt. `_center-node` không truyền `$ben` nên cuống nhánh vốn đã không có lớp
     `--trai/--phai`; dòng dưới là chốt chặn thứ hai, cố ý để thừa: một lần include sót
     tham số cũng không làm vỡ dáng.

   ⚠ ĐÚNG HAI CỘT, không `auto-fit`. Bề ngang tối đa của sơ đồ là 68rem — `auto-fit`
     với ô tối thiểu 20rem sẽ nhảy sang BA cột trên màn rộng, và bản vẽ chỉ có hai.
   ---------------------------------------------------------------------------- */
.vt-branch--blocks .vt-branch__node::after { display: none; }

/* ============================================================================
   CỘT NỘI DUNG ✚ NHỊP KHOẢNG CÁCH — `.vt-report-center` (01/09/2026)
   ----------------------------------------------------------------------------
   Anh Dũng: *"trên dưới, trái phải nó đều nhau… vẽ nó đẹp hơn chuyên nghiệp hơn,
   nội dung giữ nguyên"*.

   ĐO ĐƯỢC TRƯỚC KHI SỬA (màn 1600px): thẻ 1693px · sơ đồ 1088px ⇒ lề ngang 303px
   trong khi lề dọc 20px. Cân theo từng cặp nhưng lệch nhau 15 lần, nên khối nội
   dung đọc như đang trôi giữa một hộp trắng rỗng.

   ⚠ THU THẺ, ⛔ KHÔNG NỚI SƠ ĐỒ. Bề rộng 68rem của `.vt-branch` là có chủ đích —
     xem chú thích tại chính lớp ấy: tràn hết thẻ thì tên nhánh ở mép trái, con số
     ở mép phải, "cách nhau gần một mét mắt". Nới ra là dựng lại đúng lỗi đã sửa.
   ⚠⚠ 71.5rem = 68rem (sơ đồ) + 2 × 1.75rem (đệm thẻ) ⇒ sơ đồ chạm ĐÚNG mép trong,
     lề bốn phía bằng nhau tuyệt đối. **Ba số này ràng buộc nhau** — đổi một số phải
     tính lại hai số kia, nếu không lề ngang lại phình ra so với lề dọc.
     (Bản đầu đặt 75rem: thừa 3.5rem ⇒ đo được lề ngang 55px trong khi lề dọc 28px.)

   MỘT THANG KHOẢNG CÁCH DUY NHẤT cho cả sơ đồ — trước đây mỗi chỗ một số rời
   (.6rem, 1.15rem, .35rem…) nên nhịp đọc gãy. Khai bằng biến để đổi một chỗ.
   ============================================================================ */
.vt-report-center {
    --vt-rc-o: .75rem;      /* khe giữa các ô nhánh   */
    --vt-rc-khoi: 1.5rem;   /* khe giữa hai khối      */
    --vt-rc-dem: 1.75rem;   /* đệm trong thẻ, bốn phía */
    /* ★★★ 01/09/2026 — ĐO BA LẦN MỚI RA. Anh Dũng: *"nhìn nó vẫn dại dại, không mềm mại"*.
       ① 68rem căn giữa  ⇒ trống 303px mỗi bên, khối trôi giữa hộp trắng;
       ② căn PHẢI        ⇒ dồn cả 460px trống sang trái, mà tiêu đề trang lại ở góc trái ⇒ nội dung
                            ĐỨT khỏi tiêu đề của chính nó — tệ hơn hẳn, đã chụp màn đối chứng;
       ③ căn TRÁI ở 71.5rem ⇒ biên trái đẹp, thẳng cột với tiêu đề — nhưng để lại **460px trống bên
            phải**, trang cụt hẳn một bên, và thẻ *Các kỳ đã báo cáo* bên dưới (full width) ⛔ KHÔNG
            thẳng hàng với nó ⇒ hai thẻ so le, còn khó nhìn hơn.
       ④ trải HẾT bề ngang ⇒ hết trống, hai thẻ thẳng hàng — nhưng ô nở tới ~800px, và ô lẻ trải trọn
            hàng thành **1290px cho một dòng chữ ngắn**: loãng, chữ dạt trái, phần còn lại rỗng.
       ⇒ ⑤ **NEO TRÁI Ở 94rem.** Đủ rộng để ⛔ không còn mảng trống lớn, đủ hẹp để ô giữ ~700px — mức mà
            tên nhánh và con số vẫn nằm trong một tầm liếc. Neo trái để khối thẳng cột với tiêu đề
            *"Báo cáo của tôi"*: mắt đi từ tiêu đề xuống nội dung theo **một đường biên duy nhất**, và
            khoảng thở dồn về phía phải — cùng phía với vùng trống tự nhiên của trang.

       ⚠ VẬY CÒN CẢNH BÁO "MỘT MÉT MẮT" Ở `.vt-branch`? Vẫn đúng, nhưng nó đo cảnh **một cột chạy hết
         màn 1900px** (ô ~1800px). Ở đây lưới **hai cột** nên ô chỉ bằng non nửa. ⛔ Đừng vì cảnh báo ấy
         mà kéo lưới về một cột. */
    max-width: 94rem;
    margin-left: 0;
    margin-right: auto;
}

.vt-report-center > .card > .card-body { padding: var(--vt-rc-dem); }

/* ⚠ GỠ TRẦN 68rem CỦA `.vt-branch` — CHỈ cho biến thể khối, ⛔ không đụng dáng toả nhánh gốc.
   Trần ấy sinh ra cho dáng MỘT CỘT chạy hết màn (ô ~1800px, "một mét mắt"). Ở đây lưới hai cột nên ô
   chỉ ~700px, mà giữ trần thì thẻ 1695px ôm một sơ đồ 1088px ⇒ lề ngang 303px so với lề dọc 28px. */
.vt-branch--blocks { max-width: none; }

.vt-branch__block + .vt-branch__block { margin-top: var(--vt-rc-khoi); }

/* NỀN KHỐI NHẠT — lớp phân cấp thị giác còn thiếu.
   Trước đây ô trắng nằm trên thẻ trắng, chỉ cách nhau một đường viền 1px: mười một ô
   "phẳng" như nhau, mắt ⛔ không biết nhìn đâu trước. Cho khối một nền ngà rất nhạt thì
   ô trắng NỔI LÊN trên nó, và bốn khối tự tách nhau mà ⛔ không cần thêm đường kẻ nào. */
.vt-branch--blocks .vt-branch__block {
    background: #fafbfc;
    border: 1px solid #f0f2f5;
    border-radius: 12px;
    padding: .85rem .9rem .9rem;
}

.vt-branch--blocks .vt-branch__grid { gap: var(--vt-rc-o); }

/* Ô LẺ TRẢI HẾT HÀNG — khối *Màn nền* có ba ô, ô thứ ba vốn nằm trơ nửa hàng.
   ⚠ Thuần CSS, ⛔ không đụng Blade: `:last-child:nth-child(odd)` chỉ đúng khi ô cuối
     đứng ở vị trí lẻ, tức tổng số ô là lẻ. Khối chẵn ô ⛔ không bị ảnh hưởng. */
.vt-branch--blocks .vt-branch__grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }

/* Ô nhánh trong biến thể khối: nền trắng để nổi trên nền khối, và phản hồi chạm rõ hơn —
   người dùng phải thấy ngay đây là thứ bấm được. */
.vt-branch--blocks .vt-branch__node {
    padding: .7rem .8rem;
    border-color: #e8ecf1;
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.vt-branch--blocks a.vt-branch__node[href]:hover {
    border-color: #f0b48f;
    background: #fff;
    box-shadow: 0 4px 14px rgba(224, 79, 22, .09);
    transform: translateY(-1px);
}

/* ⚠ Nhánh KHOÁ ⛔ không được nhấc lên khi rê chuột — nó ⛔ không bấm được, mà một ô tự nhấc
   lên là lời hứa suông. `is-locked` ⛔ không có `href` nên vốn đã ⛔ không khớp bộ chọn trên;
   dòng này là chốt chặn thứ hai, cố ý để thừa. */
.vt-branch--blocks .vt-branch__node.is-locked:hover { transform: none; box-shadow: none; }

/* Dòng "Luồng trình" ở chân: tách bằng một đường mảnh thay vì để trôi sát khối cuối. */
.vt-branch--blocks .vt-branch__note {
    margin-top: var(--vt-rc-khoi);
    padding-top: .9rem;
    border-top: 1px solid #f0f2f5;
}

@media (max-width: 991.98px) {
    /* Màn hẹp ⛔ không còn chỗ thừa hai bên ⇒ trả thẻ về full và giảm đệm cho đỡ chật. */
    .vt-report-center { --vt-rc-dem: 1.15rem; max-width: none; }
    .vt-branch--blocks .vt-branch__block { padding: .7rem .7rem .75rem; }
}

/* Dải tiêu đề khối — công thức nhóm menu: chữ hoa, cỡ nhỏ, giãn chữ, gạch chân mảnh.
   ⚠ Cùng thang với `.vt-section-head` đang dùng khắp phân hệ, ⛔ đừng đặt cỡ chữ riêng.

   ★ MÀU CHỦ ĐẠO + IN ĐẬM (bạn chỉ ra 22/08/2026 khi xem trên màn thật). Bản đầu để xám
     nhạt `#8a94a6` như chữ phụ: bốn dải chìm hẳn xuống, mắt lướt qua không thấy đâu là
     ranh giới khối — tức là mất đúng cái mà việc chia khối sinh ra để có. Dùng `#e04f16`,
     màu chủ đạo của theme, ⛔ không tự chế màu mới cho riêng chỗ này. */
.vt-branch__group {
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    font-weight: 700;
    color: #e04f16;
    padding: 0 .15rem .35rem;
    border-bottom: 1px solid #eceff3;
    margin-bottom: .6rem;
}

.vt-branch__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .6rem;
}

@media (max-width: 767.98px) {
    /* Cùng ngưỡng với dáng toả nhánh: dưới đây tên nhánh xuống dòng từng chữ.
       ⚠⚠ `minmax(0, 1fr)` chứ ⛔ KHÔNG `1fr`. Đo thật 01/09/2026 ở khung 483px: cột `1fr` lấy sàn là
          **min-content**, nên ô ⛔ không co xuống dưới bề rộng nội dung của nó ⇒ ô rộng 458px trong vùng
          cha 421px và **trang cuộn ngang**. Lỗi kinh điển của CSS Grid, và nó câm — ⛔ không quy tắc nào
          báo, chỉ lộ khi kéo hẹp màn thật. */
    .vt-branch__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================================
   Ô TÌM ĐẦU VIỆC TRÊN BÀN LÀM VIỆC — `.vt-bench-search` (S21 V19, 22/08/2026)
   ----------------------------------------------------------------------------
   Bạn yêu cầu: ô tìm đứng TRƯỚC header của bảng đầu việc và "chạy từ trái qua
   phải cho cân đối" — nên nó chiếm trọn bề ngang trong một hàng riêng, không
   chen vào hàng tiêu đề (hàng ấy đã có 5 badge + 4 nút lọc).

   ⚠ MÀU LẤY TỪ TOKEN CỦA THEME (`--bs-border-color`, `--bs-secondary-color`,
     `--bs-primary`), ⛔ KHÔNG tự chế mã màu: đổi theme là ô này phải đổi theo.
   ⚠ Icon và nút xoá đặt TUYỆT ĐỐI trong khung, còn `padding` của `input` chừa
     đúng chỗ cho chúng — ⛔ đừng dùng `input-group`: nó cắt ô thành ba khối có
     viền riêng, cao hơn và không còn liền mạch như một thanh tìm kiếm.
   ============================================================================ */
.vt-bench-search { position: relative; }

.vt-bench-search .form-control {
    padding-left: 2.25rem;
    padding-right: 2.25rem;
}

/* Bỏ dấu × mặc định của `input[type=search]` trên WebKit — ta có nút xoá riêng,
   để cả hai là hai dấu × cạnh nhau làm cùng một việc. */
.vt-bench-search .form-control::-webkit-search-cancel-button { display: none; }

.vt-bench-search__icon {
    position: absolute;
    left: .75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bs-secondary-color);
    pointer-events: none;   /* bấm xuyên qua icon vào ô nhập */
}

.vt-bench-search__clear {
    position: absolute;
    right: .5rem;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: transparent;
    color: var(--bs-secondary-color);
    line-height: 1;
    padding: .25rem;
    border-radius: 50%;
}

.vt-bench-search__clear:hover { color: var(--bs-body-color); background: var(--vt-row-hover); }

/* ============================================================================
   HÀNG ĐIỀU KHIỂN ĐẦU TRANG — `.vt-toolbar` (15/08/2026, user chỉ ra)
   ----------------------------------------------------------------------------
   Khi một hàng có nhiều loại điều khiển cạnh nhau — dải chọn đoạn, nút lùi/tiến,
   nút hành động — mỗi loại mang chiều cao riêng của nó và hàng trông so le. Đo được
   trên màn thật: `.btn` 35px · `.vt-segment` 32px · `.vt-segment-nav` 28px, ba mức
   khác nhau đứng cạnh nhau trên cùng một dòng.

   Lớp này ghim MỌI điều khiển trong hàng về một chiều cao. Đặt ở tệp dùng chung vì
   màn báo cáo đơn vị (đợt sau) có đúng hàng này.

     <div class="vt-toolbar">
         <div class="vt-segment">…</div>
         <a class="vt-segment-nav">…</a>
         <button class="btn btn-primary">…</button>
     </div>

   ⚠ Ghim bằng `height` + `inline-flex`, KHÔNG bằng `padding`: padding phải tính lại
   theo cỡ chữ của từng loại, và `.btn` của theme còn có `line-height` riêng — chỉnh
   padding là mỗi lần đổi theme lại lệch.
   ============================================================================ */
.vt-toolbar {
    /* Lấy theo chiều cao NÚT HÀNH ĐỘNG của theme (đo được 35px), làm tròn lên 38px cho thoáng — bạn chốt
       15/08/2026: "để nút Báo cáo kỳ này to như vậy cũng được, nên điều chỉnh thanh button ngày tuần…".
       Tức dải kỳ NÂNG LÊN cho bằng nút, không phải hạ nút xuống cho bằng dải. */
    --vt-toolbar-h: 38px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}
.vt-toolbar .vt-segment,
.vt-toolbar .vt-segment-nav,
.vt-toolbar .btn {
    height: var(--vt-toolbar-h);
}
.vt-toolbar .vt-segment__item {
    display: inline-flex;
    align-items: center;
    height: 100%;
}
.vt-toolbar .vt-segment-nav { width: var(--vt-toolbar-h); }
.vt-toolbar .btn {
    display: inline-flex;
    align-items: center;
    /* Nút trong hàng này luôn có icon + chữ; căn giữa theo trục dọc để icon không tụt
       xuống dưới đường chân chữ khi đã ghim chiều cao. */
    justify-content: center;
}

/* DẢI KỲ TRONG HÀNG ĐIỀU KHIỂN PHẢI NỔI LÊN (15/08/2026, bạn chỉ ra trên ảnh).
   `.vt-segment` bản gốc cố ý PHẲNG và nền trong suốt vì nó sống bên trong thẻ trắng — ở đó nó chỉ là
   chỗ đổi góc nhìn, không được kéo mắt. Nhưng trên hàng tiêu đề thì nền phía sau là nền XÁM của trang,
   nên đúng cái làm nó kín đáo trong thẻ lại làm nó chìm hẳn ở đây: viền nhạt trên nền xám gần như mất.

   ⇒ Chỉ trong `.vt-toolbar`: nền TRẮNG + viền đậm hơn để cả dải tách khỏi nền trang, và mục ĐANG CHỌN
     tô đặc màu chủ đạo — cùng tông với nút hành động đứng ngay cạnh, đọc ra ngay đang ở kỳ nào.
   ⚠ Không đụng `.vt-segment` gốc: nó còn dùng ở màn nhập báo cáo, bên trong thẻ trắng. */
.vt-toolbar .vt-segment {
    background: #fff;
    border-color: #d7dde5;
}
.vt-toolbar .vt-segment__item {
    color: #56637b;
    font-weight: 500;
    border-left-color: #e6eaed;
}
.vt-toolbar .vt-segment__item:hover { background: #f4f6f8; color: #092c4c; }
.vt-toolbar .vt-segment__item.is-active {
    background: #e04f16;
    color: #fff;
    font-weight: 600;
}
.vt-toolbar .vt-segment__item.is-active:hover { background: #c8450f; color: #fff; }
/* Nút lùi/tiến kỳ cũng phải đứng ngang hàng về độ đậm, nếu không nó lọt thỏm giữa dải và nút. */
.vt-toolbar .vt-segment-nav { border-color: #d7dde5; }

/* NHÁNH BỊ KHOÁ (chưa có quyền) — `.vt-branch__node.is-locked` (15/08/2026, bạn đảo luật: cây luôn hiện
   đủ mắt xích, không có quyền thì khoá chứ không ẩn).
   Mờ hơn "sắp có" một bậc và KHÔNG dùng viền nét đứt: nét đứt đã mang nghĩa "đang dựng", dùng lại cho
   "không có quyền" là hai tình huống khác hẳn nhau mà trông y hệt. */
.vt-branch__node.is-locked {
    background: #fbfcfd;
    border-color: #eef1f5;
    cursor: default;
}
.vt-branch__node.is-locked .vt-branch__title,
.vt-branch__node.is-locked .vt-branch__desc { color: #b6bcc6; }
.vt-branch__node.is-locked .vt-branch__ico { background: #f4f6f8; color: #c2c8d0; }

/* GHI CHÚ KẾT của sơ đồ — `.vt-branch__note` (15/08/2026, bạn chốt: chuyển xuống chân thẻ).
   Trong lõi nó chen giữa nhãn kỳ và các nhánh, đọc như phụ đề của kỳ. Ở chân thẻ, ngăn bằng một đường
   kẻ, nó thành câu chốt lại của cả sơ đồ. */
.vt-branch__note {
    margin-top: 1.35rem;
    padding-top: .8rem;
    border-top: 1px solid #eceff3;
    text-align: center;
    font-size: .75rem;
    color: #8a94a6;
}
.vt-branch__note i { font-size: .6875rem; opacity: .7; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════
   TRÌNH SOẠN THẢO (Summernote) — MỘT BỘ DÁNG CHO CẢ DỰ ÁN
   ═══════════════════════════════════════════════════════════════════════════════════════════════════
   ★ Bạn chốt 21/08/2026: *"nếu làm editor nên tạo style cho nó phẳng đẹp chuyên nghiệp… làm css 1 lần
     thì áp dụng toàn dự án, dùng editor ở đâu không phải định nghĩa lại"*.

   ⚠ Dáng mặc định của Summernote là bộ mặt Bootstrap 3: viền dày, nút nổi khối, thanh công cụ xám đục,
     bo góc to. Đặt cạnh `.form-control` phẳng của theme thì ô soạn thảo trông như một thành phần đi mượn
     — và đó chính là chỗ "hơi thô" mà bạn thấy.

   ★★★ NGUYÊN TẮC: ô soạn thảo phải trông như MỘT Ô NHẬP của theme, chỉ khác ở chỗ có thêm thanh công cụ.
     Mọi số đo dưới đây bám theo `.form-control` thật của theme, ⛔ đừng đặt lại ở từng màn.

   ⚠ Selector cố ý KHÔNG dùng `!important` — thêm nó là khoá mất khả năng một màn đặc thù ghi đè hợp lệ
     về sau.

   🔴🔴 ĐÍNH CHÍNH 25/08/2026 — CHÚ THÍCH CŨ Ở ĐÂY NÓI SAI, và cái sai ấy làm ba quy tắc chết lặng lẽ.
     Bản cũ viết: *"Summernote nạp CSS ở `<head>` còn tệp này nạp SAU nên bản sau thắng"*. Đo thật trên
     màn: **NGƯỢC LẠI**. `app-custom.css` nạp ở `head-css.blade.php`, còn `summernote-lite.min.css` nạp ở
     `layout/partials/vt-richtext.blade.php` — partial ấy đứng SAU ⇒ Summernote mới là bản thắng khi độ
     đặc hiệu bằng nhau.
     ⇒ Quy tắc nào TRÙNG KHÍT selector của Summernote (`.note-editor.note-frame` ·
       `.note-editor.note-frame .note-statusbar`) phải **NÂNG ĐỘ ĐẶC HIỆU** bằng cách **lặp class**
       (`.note-frame.note-frame`).
     ⚠ Quy tắc đã đặc hiệu cao hơn sẵn (ví dụ `.note-toolbar` của ta là 0,3,0 so với 0,1,0 của họ) thì
       ⛔ không cần động — nó vốn đang thắng nhờ đặc hiệu, ⛔ không phải nhờ thứ tự nạp.
     ⛔ ĐỪNG "sửa cho gọn" bằng cách đổi thứ tự nạp hai tệp: `vt-richtext` là partial nạp THEO NHU CẦU
       (chỉ màn nào dùng editor mới có), dời lên `<head>` là bắt MỌI màn tải thêm một bộ CSS+JS. */

.note-editor.note-frame.note-frame {
    border: 1px solid var(--vt-editor-border);
    border-radius: .5rem;
    box-shadow: none;
    margin-bottom: 0;                 /* khoảng cách để `.mb-3` của khối cha lo, tránh cộng dồn hai lần */
    background: #fff;
    transition: border-color .15s ease, box-shadow .15s ease;
}
/* Đang gõ ⇒ viền sáng lên đúng như ô nhập của theme. `focus-within` bắt được vì con trỏ nằm trong
   `.note-editable` (contenteditable), không nằm trên chính khung. */
.note-editor.note-frame.note-frame:focus-within {
    border-color: rgba(224, 79, 22, .55);
    box-shadow: 0 0 0 .18rem rgba(224, 79, 22, .1);
}

/* ── Thanh công cụ: phẳng, chỉ ngăn bằng một đường kẻ mảnh ─────────────────────────────────────── */
/* ★★★ 25/08/2026 — anh Dũng chốt: *"mầu của editor giống mầu của menu actived"*. Nền cũ `#fafbfc` là xám
   LẠNH, đặt giữa giao diện tông CAM thì thanh công cụ trông như mảnh đi mượn.
   ⚠ Dùng THẲNG `var(--vt-row-hover)`, ⛔ KHÔNG gõ lại `#fff7f0`: token ấy là NƠI DUY NHẤT giữ màu này. */
.note-editor.note-frame .note-toolbar {
    background: var(--vt-row-hover);
    border-bottom: 1px solid var(--vt-editor-border);
    border-radius: .5rem .5rem 0 0;
    padding: .3rem .4rem;
}
.note-editor.note-frame .note-toolbar .note-btn-group { margin: 0 .15rem 0 0; }
.note-editor.note-frame .note-toolbar .note-btn {
    background: transparent;
    border: 0;
    border-radius: .375rem;
    color: #5b6472;
    padding: .3rem .48rem;
    font-size: .8125rem;
    line-height: 1.2;
    transition: background-color .12s ease, color .12s ease;
}
.note-editor.note-frame .note-toolbar .note-btn:hover,
.note-editor.note-frame .note-toolbar .note-btn:focus {
    /* ⚠ Đậm hơn nền thanh MỘT NẤC, cùng tông ấm — xám lạnh cũ (`#eef1f5`) rê chuột vào là thấy một ô
       xám nhảy ra giữa dải cam. */
    background: #fbeadd;
    color: #26282c;
    box-shadow: none;
}
/* Nút đang bật (đậm/nghiêng/gạch chân đang áp dụng) — tô bằng màu chủ đạo ở mức nhạt, không tô đặc:
   thanh công cụ có tới ba nút loại này, tô đặc cả ba là một dải màu chói giữa form. */
.note-editor.note-frame .note-toolbar .note-btn.active {
    background: rgba(224, 79, 22, .1);
    color: #c2410c;
}
.note-editor.note-frame .note-toolbar .note-btn .note-icon-caret { margin-left: .18rem; opacity: .55; }
/* Ô thả (Kiểu chữ, Đoạn, Bảng) — bỏ dáng Bootstrap 3 */
.note-editor.note-frame .note-toolbar .dropdown-menu {
    border: 1px solid #e6e9ee;
    border-radius: .5rem;
    box-shadow: 0 6px 22px rgba(16, 24, 40, .1);
    padding: .3rem;
    font-size: .8125rem;
}
.note-editor.note-frame .note-toolbar .dropdown-menu > li > a,
.note-editor.note-frame .note-toolbar .dropdown-menu a { border-radius: .375rem; padding: .3rem .5rem; }

/* ── Vùng gõ: cùng cỡ chữ và cùng khoảng thở với `.form-control` ───────────────────────────────── */
.note-editor.note-frame .note-editing-area .note-editable {
    padding: .65rem .75rem;
    font-size: .875rem;
    line-height: 1.55;
    color: #26282c;
    background: #fff;
}
.note-editor.note-frame .note-editing-area .note-editable[contenteditable="false"] { background: #f7f8fa; }
/* Câu gợi ý phải nhạt bằng placeholder của ô nhập thường — mặc định của Summernote đậm hơn hẳn, đọc
   nhầm thành nội dung đã có. */
.note-editor.note-frame .note-placeholder { color: #a8afba; padding: .65rem .75rem; font-size: .875rem; }

/* Khoảng cách giữa các khối trong vùng gõ: mặc định của trình duyệt cho `<p>` là 1em trên–dưới, nên
   một đoạn ngắn trông như bị đẩy lệch xuống. */
.note-editor.note-frame .note-editable > :first-child { margin-top: 0; }
.note-editor.note-frame .note-editable > :last-child { margin-bottom: 0; }
.note-editor.note-frame .note-editable p { margin-bottom: .5rem; }
/* ★★★ TRẢ LẠI DẤU ĐẦU DÒNG TRONG VÙNG GÕ (đo trên màn thật 22/08/2026).
   Theme đặt `ul { list-style: none }` ở tầng reset toàn cục, và nó thấm cả vào `.note-editable`. Hệ quả:
   người dùng bấm nút "danh sách" trên thanh công cụ và **KHÔNG THẤY GÌ ĐỔI** — chữ chỉ thụt vào một chút,
   trông y hệt một đoạn văn. Họ bấm lại, bấm nút kia, rồi kết luận nút đó hỏng. Lưu xong mở màn xem thì
   dấu đầu dòng lại hiện (vì `.vt-rich-view` đã có `list-style: revert`), tức hai màn nói hai điều khác
   nhau về cùng một nội dung.
   ⚠ `revert` chứ không `disc`/`decimal` cứng: giữ đúng luật lồng nhau của trình duyệt (cấp 2 thành ô
     tròn rỗng, cấp 3 thành ô vuông) — cùng cách `.vt-rich-view` đang làm, để GÕ và XEM khớp nhau. */
.note-editor.note-frame .note-editable ul,
.note-editor.note-frame .note-editable ol { margin-bottom: .5rem; padding-left: 1.5rem; list-style: revert; }
.note-editor.note-frame .note-editable li { list-style: revert; margin-bottom: .15rem; }

/* ── Chân khung: thanh trạng thái + tay kéo ────────────────────────────────────────────────────── */
/* ⚠ LẶP CLASS `.note-statusbar.note-statusbar` — Summernote khai ĐÚNG selector này với cùng độ đặc hiệu
   và nạp SAU (xem đính chính ở đầu khối), nên bản không lặp class sẽ THUA trong im lặng. */
.note-editor.note-frame .note-statusbar.note-statusbar {
    background: var(--vt-row-hover);
    border-top: 1px solid var(--vt-editor-border);
    border-radius: 0 0 .5rem .5rem;
}
.note-editor.note-frame .note-statusbar .note-resizebar { padding: .18rem 0; height: auto; }
.note-editor.note-frame .note-statusbar .note-icon-bar { border-top-color: #d9bfa9; width: 18px; }

/* ── Hộp thoại của Summernote (chèn liên kết, bảng) ────────────────────────────────────────────── */
.note-modal .note-modal-content { border: 0; border-radius: .6rem; box-shadow: 0 12px 40px rgba(16, 24, 40, .16); }
.note-modal .note-modal-header { border-bottom: 1px solid #eef0f4; padding: .85rem 1rem; }
.note-modal .note-modal-footer { border-top: 1px solid #eef0f4; padding: .75rem 1rem; height: auto; }
.note-modal .note-form-control { border: 1px solid #e3e6ec; border-radius: .45rem; padding: .45rem .65rem; font-size: .875rem; }

/* ⚠ Ô soạn thảo TRONG MODAL: Summernote đo bề rộng lúc khởi tạo, mà modal lúc đó có thể chưa hiện.
   Ép 100% để ô không ra một vạch mảnh — cùng lớp bẫy với Select2 dựng trong `display:none`. */
.modal .note-editor.note-frame { width: 100%; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   ★★★★★ `.min-w-0` — MẢNH GHÉP THIẾU CỦA MỌI DÒNG CÓ CHỮ DÀI (khai 25/08/2026)

   🔴 BỆNH ĐO ĐƯỢC TRÊN MÀN THẬT (anh Dũng bắt): khối "Chờ tôi duyệt" ở Tổng quan — *"nếu mà tên tiêu đề
   dài là bị lòi ra mà không nằm trong card"*. Cùng một bệnh còn nằm ở 5 chỗ khác của hệ thống.

   VÌ SAO. Sáu view đang gắn class `min-w-0` cho cột chữ trong một hàng flex, rồi trông cậy vào
   `text-truncate` bên trong. Nhưng `min-w-0` là class của **TAILWIND** — dự án này chạy **BOOTSTRAP 5**,
   nơi class ấy ⛔ KHÔNG TỒN TẠI. Nó đi thẳng ra HTML mà không khớp luật CSS nào, và ⛔ không lỗi nào báo.
   Hệ quả: flex item giữ `min-width: auto` mặc định ⇒ ⛔ không co nhỏ hơn nội dung ⇒ `text-truncate` vô
   hiệu ⇒ tiêu đề dài **đẩy tràn cả thẻ**. Đúng loại hỏng tệ nhất: trông vẫn bình thường cho tới khi gặp
   dữ liệu thật đủ dài.

   ⇒ Khai đúng cái tên sáu view đang gọi, thay vì đi sửa sáu tệp — một nguồn, chữa hết một lượt.
   ⛔ ĐỪNG đổi tên class này: sáu nơi đang bám vào nó, đổi là phải sửa đủ sáu chỗ và sót một chỗ thì
     chỗ ấy lặng lẽ vỡ lại.
   ⚠ `!important` cần thật: nhiều tiện ích Bootstrap đặt `min-width` và thắng theo thứ tự khai báo.
   ▸ Nơi dùng: `workspace` (Chờ tôi duyệt) · `topbar` + `system/notifications` (danh sách thông báo) ·
     `work/projects/_view-list-row` · `work/tasks/partials/_comments` · `work/tasks/partials/_progress_history`.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */
.min-w-0 { min-width: 0 !important; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   `.vt-cols-list` — DANH SÁCH ĐÁNH SỐ, NHIỀU CỘT (khai 25/08/2026)

   🔴 BỆNH ANH DŨNG BẮT trên màn chi tiết báo cáo: khối "N đầu việc chưa có kết quả trong kỳ" nối tên
   việc bằng dấu `·` thành MỘT đoạn văn dài — nguyên văn *"rối như canh hẹ"*, và yêu cầu *"trình bày
   thành dạng list hoặc bảng cho dễ nhìn và chuyên nghiệp"*. Với 28 đầu việc thì mắt ⛔ không tách được
   đâu là hết tên này, đâu là bắt đầu tên kia — nhất là khi chính tên việc đã chứa dấu chấm, ngoặc kép
   và tên phòng ban.

   VÌ SAO PHẢI CÓ CSS chứ ⛔ không chỉ đổi sang `<ol>` trần:
   ⚠ `<ol class="row row-cols-*">` của Bootstrap biến mỗi `<li>` thành flex item ⇒ **dấu đánh số biến
     mất** (marker chỉ vẽ cho list-item). Danh sách mất số là mất luôn khả năng ĐẾM và ĐỌC DÒ — thứ duy
     nhất người duyệt cần ở khối này.
   ⚠ Tên việc dài xuống dòng thì dòng thứ hai phải THỤT NGANG với dòng đầu, nếu không nó trôi về sát lề
     và trông y hệt một mục mới. Đó chính là cảm giác "rối" mà đoạn văn cũ gây ra, chỉ nhẹ hơn.

   ⇒ Đánh số bằng CSS counter (chạy được cả khi `li` là flex item) + `padding-left` bù đúng bề rộng số.
   ▸ Dùng cùng `row row-cols-1 row-cols-lg-2 g-1` của Bootstrap: một cột ở màn hẹp, hai cột từ 992px.
   ⛔ Đừng thay bằng `columns` (CSS multi-column): nó cắt một mục làm đôi giữa hai cột khi mục ấy rơi
     đúng biên — đã thấy khi thử.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════ */
.vt-cols-list { counter-reset: vt-cols-list; list-style: none; padding-left: 0; }
.vt-cols-list > li {
    counter-increment: vt-cols-list;
    position: relative;
    padding-left: 26px;
}
.vt-cols-list > li::before {
    content: counter(vt-cols-list) ".";
    position: absolute;
    left: 0;
    top: 0;
    width: 22px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    opacity: .65;
}
