/* Kiểu bố cục cho bảng điều khiển oPAM — thuần CSS, không nạp gì từ
 * ngoài (chạy được khi máy chủ không có Internet).
 *
 * TOKEN MÀU/FONT (biến `--chu`, `--nen`, `--nen-2`, `--vien`, `--chu-mau`,
 * `--nhan-mo`, `--canh-bao`, `--loi`, `--nhan`) đã CHUYỂN HẲN sang
 * `opam-theme.css` (đặc tả giao diện mục 2a) — tệp đó phải nạp TRƯỚC tệp
 * này trong `index.html`. Tệp này chỉ còn bố cục và tham chiếu `var(--…)`.
 *
 * FONT: đúng MỘT ngăn xếp cho mọi thứ, khai ở `opam-theme.css`, và mọi
 * khai báo font-family/font ở đây đều `var(--chu)` — không khai lại.
 *
 * Nhóm font chữ-có-chân và vài font hệ cũ THIẾU nhiều chữ Việt tổ hợp.
 * Đặt một font như vậy lên ĐẦU ngăn xếp thì trình duyệt phải rơi font
 * theo TỪNG KÝ TỰ, và chữ có dấu vẽ lệch chữ không dấu — trong khi byte
 * của tệp vẫn hoàn hảo. So byte không bao giờ thấy được lỗi đó; phải xét
 * PHẦN TỬ ĐẦU của ngăn xếp sau khi tách theo dấu phẩy. Danh sách tên bị
 * cấm dẫn đầu nằm ở `FONT_CAM_DUNG_DAU` trong
 * `uat/pm/ui/tests/test_ui_k2d_vo_spa.py` — cố ý KHÔNG chép tên chúng
 * vào đây, để chính tệp này cũng sạch. */

body {
  font-family: var(--chu);
  background: var(--nen);
  color: var(--chu-mau);
  margin: 0;
  padding: 2rem;
}

.opam-console {
  max-width: 72rem;
  margin: 0 auto;
}

.opam-console h1 {
  font-family: var(--chu);
  font-size: 1.25rem;
  margin-bottom: 1rem;
}

[data-console-login-shell] {
  max-width: 28rem;
}

[data-console-login-shell] label {
  display: block;
  margin-bottom: 0.75rem;
  font-size: 0.9rem;
}

[data-console-login-shell] input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 0.5rem;
  margin-top: 0.25rem;
  border-radius: 0.25rem;
  border: 1px solid var(--vien);
  background: var(--nen-2);
  color: var(--chu-mau);
  font-family: var(--chu);
}

[data-console-login-shell] button,
[data-console-logout] {
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
  border: 1px solid var(--vien);
  background: var(--nhan);
  color: var(--chu-tren-nhan);
  cursor: pointer;
  font-family: var(--chu);
}

/* V2 — "mat nhin" cua o mat khau.
 *
 * Luat ngay tren (`[data-console-login-shell] button`) co do rieng (0,1,1) va
 * se son cai nut nay thanh mot nut xanh dac y het nut "Dang nhap" — dung cai
 * loi da lam ca man hinh xanh o luot U1. Nen o day KHONG sua luat kia, ma
 * cham them mot bo chon HEP HON: (0,2,1) > (0,1,1), thang ma khong dong toi
 * ai. Bo `[data-console-hien-mat-khau]` khoi bo chon nay la nut xanh quay lai
 * ngay — do la can gat song trong chinh trang.
 */
.o-mat-khau {
  position: relative;
  display: block;
}

/* Chua cho con mat mot khoang, de chu mat khau go dai khong chui xuong duoi no. */
.o-mat-khau input {
  padding-right: 2.6rem;
}

[data-console-login-shell] button[data-console-hien-mat-khau] {
  position: absolute;
  right: 0.25rem;
  /* Nam giua chieu cao O NHAP, khong giua chieu cao ca nhan: nhan con mang
   * chu "Mat khau" o tren, lay giua ca nhan se day con mat len cho chu. */
  top: calc(0.25rem + 1px);
  height: calc(100% - 0.25rem - 2px);
  display: flex;
  align-items: center;
  padding: 0 0.5rem;
  border: 0;
  background: transparent;
  color: var(--nhan-mo);
  cursor: pointer;
}

[data-console-login-shell] button[data-console-hien-mat-khau]:hover,
[data-console-login-shell] button[data-console-hien-mat-khau]:focus-visible {
  color: var(--chu-mau);
}

/* Trang thai DANG HIEN phai nhin ra duoc ma khong can doc chu: mat khau dang
 * bay ra man hinh la mot trang thai nen thay ngay. */
[data-console-login-shell] button[data-console-hien-mat-khau][aria-pressed="true"] {
  color: var(--nhan);
}

[data-console-loi] {
  color: var(--loi);
  margin-top: 0.75rem;
  min-height: 1.2rem;
}

[data-console-menu][hidden],
[data-console-login-shell][hidden] {
  display: none;
}

/* -- vỏ SPA: thực đơn trái + panel phải ------------------------------- */

.opam-app {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
}

[data-console-menu-nav] {
  flex: 0 0 15rem;
  border-right: 1px solid var(--vien);
  padding-right: 1rem;
}

[data-console-menu] ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

[data-console-menu] li {
  margin-bottom: 0.5rem;
}

[data-console-menu] a {
  display: block;
  padding: 0.4rem 0.5rem;
  border-radius: 0.25rem;
  color: var(--chu-mau);
  text-decoration: none;
  font-family: var(--chu);
}

[data-console-menu] a[aria-current="page"] {
  background: var(--nen-2);
  font-weight: 600;
}

[data-console-panel] {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--chu);
}

[data-console-canh-bao] {
  font-size: 0.85rem;
  color: var(--canh-bao);
  margin-top: 0.5rem;
}

/* -- phần chung của năm màn ------------------------------------------- */

[data-man] h2 {
  font-family: var(--chu);
  font-size: 1.1rem;
  margin: 0 0 0.5rem;
}

[data-man-ghi-chu] {
  color: var(--nhan-mo);
  font-size: 0.85rem;
  margin: 0.25rem 0 0.75rem;
}

[data-man-trang-thai="chua-dang-nhap"],
[data-man-trang-thai="loi"] {
  color: var(--loi);
}

[data-man-trang-thai="chua-noi-backend"],
[data-man-trang-thai="rong"] {
  color: var(--canh-bao);
}

[data-man] table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.88rem;
  font-family: var(--chu);
}

[data-man] th,
[data-man] td {
  border: 1px solid var(--vien);
  padding: 0.35rem 0.5rem;
  text-align: left;
  vertical-align: top;
}

[data-man] th {
  background: var(--nen-2);
}

[data-man] tr[data-ma-task] {
  cursor: pointer;
}

[data-man-chi-tiet] {
  margin-top: 1rem;
  border: 1px solid var(--vien);
  border-radius: 0.25rem;
  padding: 0.75rem;
  background: var(--nen-2);
}

/* -- màn Trang chủ (lượt R4, dác-tá-vô-6-màn §2b) ---------------------
 * Ba khối: bốn thẻ số liệu, danh sách hoạt động gần đây, lưới sáu thẻ
 * chức năng. Mọi lớp bắt đầu bằng `opam-trang-chu-` theo chốt của R4;
 * `man-trang-chu.js` (R3) gắn đúng các tên này vào DOM.
 *
 * KHÔNG token màu nào MỚI được thêm ở đây — bốn cặp chữ/nền cần dùng
 * (`chu-mau`/`nen-2`, `loi`/`nen-2`, `canh-bao`/`nen-2`, `ok`/`nen-2`,
 * `nhan-mo`/`nen-2`) đã có sẵn trong `DANH_SACH_CAP` của
 * `do-tuong-phan.py` từ trước lượt này, đo lại xác nhận đủ 4.5:1 ở cả
 * hai theme (xem báo cáo). Vì vậy `do-tuong-phan.py` không cần cặp mới. */

.opam-trang-chu-tieu-de {
  font-family: var(--chu);
  font-size: 1.1rem;
  margin: 0 0 0.75rem;
}

/* Bốn thẻ số liệu — lưới co giãn, tối thiểu 9.5rem mỗi thẻ để không vỡ
 * trên màn hẹp mà vẫn đứng thành một hàng trên màn thường. */
.opam-trang-chu-so-lieu {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 1rem;
  margin: 0 0 1.5rem;
}

.opam-trang-chu-the {
  border: 1px solid var(--vien);
  border-radius: 0.5rem;
  padding: 1rem;
  background: var(--nen-2);
  box-shadow: 0 1px 3px var(--bong);
}

.opam-trang-chu-the-so {
  font-family: var(--chu);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--chu-mau);
}

.opam-trang-chu-the-nhan {
  font-family: var(--chu);
  font-size: 0.85rem;
  color: var(--nhan-mo);
  margin-top: 0.35rem;
}

/* `doi-phan-quyet` là nhóm CHẶN dự án — chủ dự án đòi "nổi nhất". Dùng
 * `--canh-bao` (đã có, nghĩa "cần chú ý") cho viền dày + số, KHÔNG dùng
 * `--loi` để không lẫn với thẻ `hong` — hai trạng thái khác nhau (một
 * cái đang CHỜ người quyết, một cái đã HỎNG) không được cùng màu. */
.opam-trang-chu-the--doi-phan-quyet {
  border-color: var(--canh-bao);
  border-width: 2px;
  background: var(--nen);
}

.opam-trang-chu-the--doi-phan-quyet .opam-trang-chu-the-so {
  color: var(--canh-bao);
}

/* `hong` dùng đúng token `--loi` theo hợp đồng R4. */
.opam-trang-chu-the--hong .opam-trang-chu-the-so {
  color: var(--loi);
}

/* Danh sách hoạt động gần đây — 5 dòng, không đánh số. */
.opam-trang-chu-hoat-dong {
  border: 1px solid var(--vien);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  margin: 0 0 1.5rem;
  background: var(--nen-2);
}

.opam-trang-chu-hoat-dong-ds {
  list-style: none;
  margin: 0;
  padding: 0;
}

.opam-trang-chu-hoat-dong-dong {
  font-family: var(--chu);
  font-size: 0.88rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--vien);
}

.opam-trang-chu-hoat-dong-dong:last-child {
  border-bottom: none;
}

/* Lưới sáu thẻ chức năng. */
.opam-trang-chu-chuc-nang {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
}

.opam-trang-chu-chuc-nang-the {
  border: 1px solid var(--vien);
  border-radius: 0.5rem;
  padding: 0.9rem;
  background: var(--nen-2);
}

.opam-trang-chu-chuc-nang-nhan {
  font-family: var(--chu);
  font-weight: 600;
}

.opam-trang-chu-chuc-nang-mota {
  font-family: var(--chu);
  font-size: 0.85rem;
  color: var(--nhan-mo);
  margin: 0.35rem 0 0.5rem;
}

/* Huy hiệu tình trạng backend — CHỮ màu, không nền chip, để không phải
 * mở cặp tương phản mới (chip nền `--ok`/`--canh-bao` với chữ trắng
 * chưa được đo, `--chu-tren-nhan` chỉ được đo trên nền `--nhan`). */
.opam-trang-chu-huy-hieu {
  font-family: var(--chu);
  font-size: 0.75rem;
  font-weight: 600;
}

.opam-trang-chu-huy-hieu--noi {
  color: var(--ok);
}

.opam-trang-chu-huy-hieu--chua-noi {
  color: var(--canh-bao);
}

/* -- thanh tab của màn Dự án giàu (lượt S2, dac-ta-dot-S.md mục 2 §S2) --
 * Tên lớp/thuộc tính ĐO ĐƯỢC từ `uat/pm/ui/proj-manager.html` (dòng
 * 134-146, 175): `<nav class="tabs" data-owner-tabs role="tablist">` bọc
 * các `<button>` con, nút đang chọn mang `aria-selected="true"`. Đây là
 * quy ước DUY NHẤT đã tồn tại cho thanh tab K1Z trong toàn kho mã — S1
 * dựng lại đúng DOM này trong vỏ (owner.js không tự vẽ thanh tab, chỉ
 * cấp dữ liệu qua TABS/khoiCuaTab). Không suy đoán tên lớp mới.
 *
 * Cặp chữ/nền: (`--nhan-mo`, `--nen-2`) cho nút thường và (`--chu-tren-nhan`,
 * `--nhan`) cho nút đang chọn — cả hai đã có sẵn trong `DANH_SACH_CAP` của
 * `do-tuong-phan.py`, đạt >= 4.5:1 ở cả hai theme; không cặp mới nào cần
 * đo thêm.
 *
 * Thẻ đang chọn không chỉ khác MÀU: thêm `font-weight: 700` và gạch chân
 * (`text-decoration: underline`) — hai dấu hiệu không phải màu, người mù
 * màu vẫn phân biệt được với nút chưa chọn.
 *
 * `overflow-x: auto` chỉ đặt trên `.tabs` (không phải trên `body`/`.opam-
 * console`), nên khi thanh tab hẹp lại nó tự cuộn ngang TRONG khung của
 * nó — trang bao quanh (có `.opam-console { max-width: 72rem }`) không bị
 * kéo cuộn ngang theo.
 *
 * V32 — chủ dự án chỉ ra ảnh chụp màn hình sản xuất: thanh tab bị đẩy
 * xuống, chừa khoảng trống lớn phía trên, không thẳng đỉnh với menu bên
 * trái (`[data-console-menu-nav]`, không có margin-top). `margin-top`
 * trước là `1.2rem`, cộng dồn với margin của `.status` ngay trên nó —
 * đổi về `0` (chỉ còn margin dưới `0` giữ nguyên, tách bởi `padding`) để
 * `.tabs` trồi sát lên khối `.status` đã thu hẹp (xem chú thích ở đó).
 * KHÔNG đổi lớp/thuộc tính nào khác của `.tabs` — bộ chọn giữ hẹp nhất,
 * lớp này chỉ dùng ở `man-du-an-day-du.js` trong console này (đo bằng
 * grep, không lớp `.tabs` nào khác trong `uat/pm/console/*.js`). */
.tabs {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.4rem;
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
  margin: 0;
  padding: 0 0 0.4rem;
  list-style: none;
  border-bottom: 1px solid var(--vien);
}

.tabs button {
  flex: 0 0 auto;
  font-family: var(--chu);
  font-size: 0.9rem;
  white-space: nowrap;
  cursor: pointer;
  padding: 0.5rem 1.05rem;
  border: 1px solid var(--vien);
  border-radius: 999px;
  background: var(--nen-2);
  color: var(--nhan-mo);
}

.tabs button[aria-selected="true"] {
  background: var(--nhan);
  color: var(--chu-tren-nhan);
  border-color: var(--nhan);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 0.2rem;
}

/* -- màn Dự án giàu, tám lớp còn thiếu kiểu dáng (lượt S6) ------------
 * `man-du-an-day-du.js` (lượt S4) dựng markup dùng chín lớp: `tabs` (đã
 * có ở trên, lượt S2) và tám lớp dưới đây, trước lượt này KHÔNG một quy
 * tắc nào trong tệp này chạm tới chúng. Nguồn của tám lớp là khối
 * `<style>` 152 dòng của `uat/pm/ui/proj-manager.html` — chủ dự án chốt
 * cách làm "dịch sang từ vựng oPAM": chép nguyên bố cục, chỉ đổi
 * `var(--<token màn cũ>)` sang token gốc `opam-theme.css` theo bảng ánh
 * xạ 1-1 mà 13 bí danh tự khai của proj-manager.html đã cho (không suy
 * đoán): --ink=--chu-mau, --muted=--nhan-mo, --line=--vien,
 * --panel=--nen-2, --panel-raised=--nen-2, --accent=--nhan,
 * --accent-soft=--nhan-mo, --accent-ink=--chu-tren-nhan,
 * --warning=--canh-bao, --danger=--loi, --background=--nen, --chu giữ
 * nguyên (đã có ở opam-theme.css).
 *
 * PHẠM VI ĐÃ THU HẸP so với "chép cả 152 dòng": khối gốc còn có các quy
 * tắc trên phần tử THUẦN không lớp — `body`, `main`, `h1, h2`, `p`,
 * `code`, `*`, `[hidden]` — và các lớp `.eyebrow`, `.lede`, `.table-wrap`,
 * `table`/`th, td`, `.empty`, `form[data-owner-form] ...`,
 * `.phan-quyet-form ...`, `.note`, `tr.task-noi-bat`. KHÔNG lớp/thuộc
 * tính nào trong nhóm đó nằm trong chín lớp mà `man-du-an-day-du.js` thật
 * sự dùng qua `class="..."` (đo bằng regex, xem bài kiểm) — và các bộ
 * chọn phần tử thuần (`body`, `h1, h2`, `main`, `code`, `p`, `*`,
 * `[hidden]`) sẽ ăn TOÀN CỤC lên mọi màn khác của console (Đăng nhập,
 * Trang chủ, …), không chỉ màn Dự án giàu — ví dụ `body` gốc đổi cả
 * `background`/bỏ `padding: 2rem` đang có ở đầu tệp này. Đó là đột biến
 * bố cục ngoài phạm vi "cho tám lớp CÓ kiểu dáng" của lượt này, nên
 * KHÔNG chép nhóm đó. Vì phạm vi thu hẹp còn lại không dùng đến
 * `var(--chu-may)` (chỉ bộ chọn `code` thuần dùng nó, đã loại ở trên),
 * lượt này KHÔNG cần quyết định cách bù `--chu-may` — không khai, không
 * dùng.
 *
 * `.tabs` / `.tabs button` / `.tabs button[aria-selected="true"]` của
 * khối gốc TRÙNG tên với ba quy tắc lượt S2 ngay phía trên (giá trị khác
 * nhau — ví dụ S2 có `overflow-x: auto`, bản màn cũ không có). Theo ràng
 * buộc #4 của lượt này: bỏ hẳn ba quy tắc trùng đó, không ghi đè. */

/* V32 — dòng chữ "Trạng thái backend" bên trong đã bị ẨN (`hidden`, xem
 * `man-du-an-day-du.js`); khối này giờ chỉ còn giữ nút "Tải lại". Bỏ margin
 * TRÊN (trước: `1.4rem 0`) để `.tabs` ngay dưới trồi lên gần đỉnh panel,
 * căn theo đỉnh menu bên trái (việc 4) — chỉ còn margin DƯỚI để tách khỏi
 * thanh tab. Bộ chọn giữ NGUYÊN `.status`, không mở rộng: lớp này chỉ dùng
 * trong markup của `man-du-an-day-du.js` ở console này. */
.status {
  display: flex;
  gap: 0.7rem;
  align-items: center;
  margin: 0 0 0.6rem;
  padding: 0.35rem 0.95rem;
  border: 1px solid var(--vien);
  border-radius: 999px;
  background: var(--nen-2);
  font: 0.92rem var(--chu);
}

/* V17 — nút "Tải lại" cạnh khối trạng thái backend (đẩy sang mép phải của
 * chính `.status`, vốn đã là flex row). Token: nền `--nen`, viền `--vien`,
 * chữ `--chu-mau` — cặp này đã dùng ở `.phan-quyet-form input` cùng tệp,
 * không mở cặp tương phản mới; hover đổi viền sang `--nhan` như `.tl-nut`. */
.lam-moi-nut {
  margin-left: auto;
  font-family: var(--chu);
  font-size: 0.85rem;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--vien);
  background: var(--nen);
  color: var(--chu-mau);
  cursor: pointer;
}
.lam-moi-nut:hover, .lam-moi-nut:focus-visible {
  border-color: var(--nhan);
}

.status[data-status="connected"] { color: var(--nhan); }
.status[data-status="unconnected"] { color: var(--canh-bao); }
.status[data-status="unauthorized"] { color: var(--loi); }
.status[data-status="unauthorized-nginx"] { color: var(--loi); }
.status[data-status="unauthorized-mo-ho"] { color: var(--loi); }

.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  margin-top: 1.4rem;
}

.panel {
  min-width: 0;
  padding: 1.15rem;
  border: 1px solid var(--vien);
  border-radius: 1rem;
  background: linear-gradient(160deg, var(--nen-2), var(--nen-2));
  box-shadow: 0 1rem 3rem var(--vien);
}

.panel-wide { grid-column: 1 / -1; }

.panel-head {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: baseline;
  margin-bottom: 0.9rem;
}

.badge { color: var(--nhan-mo); font: 0.78rem var(--chu); }

.owner-empty { color: var(--nhan-mo); font-style: italic; }

.send-result { margin-top: 0.5rem; font-size: 0.88rem; color: var(--nhan-mo); }

@media (max-width: 700px) {
  .grid { grid-template-columns: 1fr; }
  .panel-wide { grid-column: auto; }
}

/* -- màn Dự án giàu, bảy lớp do `owner.js` (markupTaskTong/markupTask/
 * markupHoiBang) tự sinh ra, còn thiếu kiểu dáng (lượt S7) --------------
 * Đo lại nguồn: `.note`, `.phan-quyet-form` (+ hai bộ chọn con) và
 * `tr.task-noi-bat > td` (+ `:first-child`) CÓ trong khối `<style>` của
 * `uat/pm/ui/proj-manager.html` — dịch nguyên bố cục, chỉ đổi biến theo
 * đúng bảng ánh xạ 13 bí danh (đã ghi ở khối S6 phía trên). BA lớp còn lại
 * — `.task-tong`, `.task-treo`, `.task-dang-loc` — và `.canh-bao-lech-
 * dong-ho` KHÔNG có trong khối đó (đã tìm bằng grep, không thấy); brief
 * S7 nói khối ấy "định nghĩa phần lớn" bảy lớp nhưng thực đo chỉ 3/7 —
 * BÁO LẠI trong báo cáo, không lặng lẽ đi vòng. Bốn lớp này dựng mới,
 * theo đúng khuôn các quy tắc lân cận đã có trong tệp này (`[data-man-
 * chi-tiet]`, `tr.task-noi-bat`, `[data-console-canh-bao]`) và CHỈ dùng
 * token đã khai ở `opam-theme.css` — không token mới, không màu cứng. */

.note { color: var(--nhan-mo); }

.phan-quyet-form { display: flex; gap: .5rem; margin-top: .4rem; flex-wrap: wrap; }
.phan-quyet-form input[type="text"] {
  flex: 1; min-width: 12rem; font-family: var(--chu); padding: .45rem .55rem;
  border-radius: .5rem; border: 1px solid var(--vien); background: var(--nen-2); color: var(--chu-mau);
}
.phan-quyet-form button {
  font-family: var(--chu); padding: .45rem .9rem; border-radius: .5rem; border: 0;
  background: var(--nhan); color: var(--chu-tren-nhan); font-weight: 700; cursor: pointer;
}

/* Nút lựa chọn: PHỤ, không được tranh chỗ với nút "Phán quyết".
 * `.phan-quyet-form button` là (0,1,1); bộ chọn dưới đây (0,2,0) nên thắng —
 * cùng độ ưu tiên thì nút lựa chọn sẽ mang nguyên nền đặc của nút chính và
 * hai thứ khác hẳn nhau trông y như nhau. */
.phan-quyet-form .lua-chon-nut {
  background: transparent;
  color: var(--nhan);
  border: 1px solid var(--vien);
  font-weight: 600;
}
.phan-quyet-form .lua-chon-nut:hover,
.phan-quyet-form .lua-chon-nut:focus-visible {
  border-color: var(--nhan);
}

/* `.table-wrap` — bọc cuộn ngang cho bảng.
 *
 * Lớp này đã được `veChoBody`/`veHoiBody` GÁN từ lâu (`body.className =
 * "table-wrap"`) nhưng `console.css` chưa bao giờ có quy tắc cho nó: một
 * lớp gán mà không có kiểu dáng thì bảng rộng đẩy cả trang trượt ngang.
 * `test_s6_01` chỉ thấy được lỗ này khi tên lớp lọt vào một chuỗi markup
 * (2026-09-04, lúc dựng tab Thiết lập) — nó quét chuỗi, không quét phép
 * gán `className`. Ghi lại để lần sau không ai tưởng đây là lớp mới.
 */
.table-wrap { overflow-x: auto; }

/* Xem tài liệu / bản thiết kế trong popup.
 *
 * `.tl-khung` là `<iframe sandbox="">` — nội dung `.html` do agent đẩy lên
 * chỉ được HIỆN, không được CHẠY. Cho nó chiều cao cố định vì trang bên
 * trong không tự đẩy được chiều cao ra ngoài khi bị cách ly. */
.tl-nut {
  font-family: var(--chu);
  font-size: .9rem;
  background: transparent;
  color: var(--nhan);
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}
.tl-nut:hover, .tl-nut:focus-visible { text-decoration: underline; }

.tl-van h1, .tl-van h2, .tl-van h3, .tl-van h4 { margin: 1rem 0 .4rem; }
.tl-van p, .tl-van li { font-size: .92rem; }
.tl-van pre {
  background: var(--nen);
  border: 1px solid var(--vien);
  border-radius: .5rem;
  padding: .6rem .8rem;
  overflow-x: auto;
}
.tl-bang { overflow-x: auto; }
.tl-bang table { border-collapse: collapse; width: 100%; font-size: .88rem; }
.tl-bang th, .tl-bang td {
  border: 1px solid var(--vien);
  padding: .3rem .5rem;
  text-align: left;
  vertical-align: top;
}

.tl-khung {
  width: 100%;
  height: 60vh;
  border: 1px solid var(--vien);
  border-radius: .5rem;
  background: var(--nen-2);
}

/* Danh sách của tab Kế hoạch. Không dùng dấu chấm đầu dòng mặc định: mỗi
 * dòng đã mở đầu bằng một <code> mã task, hai dấu hiệu chỉ đường cùng lúc
 * là thừa. */
.ke-hoach-ds {
  list-style: none;
  margin: .3rem 0 .9rem;
  padding: 0;
}
.ke-hoach-ds li {
  padding: .3rem 0;
  border-bottom: 1px solid var(--vien);
  font-size: .9rem;
}

tr.task-noi-bat > td {
  background: var(--nhan-mo);
  border-bottom-color: var(--nhan);
  font-weight: 700;
}
tr.task-noi-bat > td:first-child { box-shadow: inset .22rem 0 0 var(--nhan); }

/* Bốn lớp không có nguồn ở proj-manager.html — dựng theo khuôn lân cận. */

.task-tong {
  margin-top: 1rem;
  padding: .75rem 1rem;
  border: 1px solid var(--vien);
  border-radius: .5rem;
  background: var(--nen-2);
}

.task-tong p { margin: .25rem 0; }

.task-dang-loc {
  margin: 0 0 .75rem;
  padding: .5rem .75rem;
  border-radius: .5rem;
  background: var(--nen-2);
  color: var(--nhan-mo);
}

tr.task-treo > td { font-style: italic; }
tr.task-treo > td:first-child { box-shadow: inset .22rem 0 0 var(--canh-bao); }

.canh-bao-lech-dong-ho {
  color: var(--canh-bao);
  font-weight: 600;
}

/* -- màn Dự án giàu, LƯỚI Task + popup (lượt T2) -----------------------
 * Thay bảng 12 cột (`.task-tong`/`tr.task-noi-bat`/... ở trên, KHÔNG
 * đụng) bằng lưới co giãn (`repeat(auto-fill, minmax(...))` — mục a của
 * brief T2: màn hẹp xuống một cột, không thanh cuộn ngang cho cả trang)
 * cộng hai popup (`.task-popup`) cho "Thêm Task" và chi tiết một task.
 *
 * Chỉ dùng lại 12 token của `opam-theme.css`, KHÔNG hex/rgb mới (test
 * `test_s6_02_khong_co_mau_cung_moi` khoá đúng 1 màu cứng, nợ cũ dòng 69).
 * Nền mờ của popup dùng `opacity` trên `--chu-mau` thay vì một màu
 * rgba() mới — `opacity` là một THUỘC TÍNH, không phải giá trị màu, nên
 * không tính vào số màu cứng mà vẫn cho lớp nền tối đi kèm bán trong suốt.
 *
 * Trạng thái task phân biệt được KHÔNG CHỈ bằng màu (mục 7 ràng buộc
 * cứng): mỗi ô LUÔN in chữ tên trạng thái (`.task-o-badge`), và ba nhóm
 * `doi-phan-quyet`/`hong`/`xong` còn thêm một dấu hiệu HÌNH DẠNG (viền
 * dày, hoặc nét đứt) — đọc được cả khi không phân biệt màu. */

.task-loc-hang {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin: 0 0 .9rem;
}

.task-loc-nut {
  font-family: var(--chu);
  font-size: .85rem;
  padding: .35rem .75rem;
  border-radius: 999px;
  border: 1px solid var(--vien);
  background: var(--nen-2);
  color: var(--nhan-mo);
  cursor: pointer;
}

.task-loc-nut[aria-pressed="true"] {
  background: var(--nhan);
  color: var(--chu-tren-nhan);
  border-color: var(--nhan);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: .2rem;
}

.task-them-nut {
  font-family: var(--chu);
  padding: .45rem .9rem;
  border-radius: .5rem;
  border: 0;
  background: var(--nhan);
  color: var(--chu-tren-nhan);
  font-weight: 700;
  cursor: pointer;
}

.task-o-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .9rem;
  margin-top: .25rem;
}

.task-o {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  font-family: var(--chu);
  padding: .75rem .85rem;
  border: 1px solid var(--vien);
  border-radius: .6rem;
  background: var(--nen-2);
  color: var(--chu-mau);
  cursor: pointer;
}

.task-o:hover,
.task-o:focus {
  border-color: var(--nhan);
  outline: 2px solid var(--nhan);
  outline-offset: 2px;
}

/* Chặn (`doi-phan-quyet`) — viền dày, cùng tinh thần thẻ trang chủ. */
.task-o[data-task-trang-thai="doi-phan-quyet"] {
  border-color: var(--canh-bao);
  border-width: 2px;
}

.task-o[data-task-trang-thai="hong"] { border-color: var(--loi); }

/* `xong` — nét đứt, dấu hiệu HÌNH DẠNG (không chỉ màu) cho "đã xong". */
.task-o[data-task-trang-thai="xong"] { border-style: dashed; }

.task-o-dau {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .5rem;
  font-weight: 700;
}

.task-o-ma { font-family: var(--chu); }

.task-o-badge {
  font-family: var(--chu);
  font-size: .78rem;
  font-weight: 600;
  color: var(--nhan-mo);
}

.task-o-treo {
  font-family: var(--chu);
  font-size: .78rem;
  font-style: italic;
  color: var(--canh-bao);
}

.task-o-agent,
.task-o-phuthuoc,
.task-o-so,
.task-o-ke-hoach {
  font-family: var(--chu);
  font-size: .85rem;
  color: var(--nhan-mo);
}

/* V32 — `mo_ta` (task LÀM GÌ) đứng cạnh `tom_tat` (task ĐANG ĐẾN ĐÂU) trên
 * thẻ liệt kê; cùng mức nổi bật, dùng lại NGUYÊN VĂN kiểu của
 * `.task-o-tomtat` (không mở cặp màu mới). */
.task-o-mota,
.task-o-tomtat {
  font-family: var(--chu);
  font-size: .85rem;
  color: var(--chu-mau);
}

.task-popup {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
}

.task-popup[hidden] { display: none; }

.task-popup-backdrop {
  position: absolute;
  inset: 0;
  background: var(--chu-mau);
  opacity: .55;
}

/* Thẻ KHÔNG tự cuộn: nó là một cột dọc gồm đầu thẻ đứng yên và thân cuộn.
 * Trước đây cả thẻ `overflow: auto` còn nút đóng `position: absolute` — mà
 * absolute neo vào thẻ, nên cuộn xuống là nút và tiêu đề trôi khỏi tầm mắt.
 * Chủ dự án chỉ ra 2026-09-04. Trên điện thoại, mất nút đóng nghĩa là phải
 * cuộn ngược hết lên mới thoát ra được. */
.task-popup-box {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: 36rem;
  width: calc(100% - 2rem);
  max-height: 85vh;
  overflow: hidden;
  box-sizing: border-box;
  border: 1px solid var(--vien);
  border-radius: 1rem;
  background: var(--nen-2);
  box-shadow: 0 1rem 3rem var(--bong);
}

.task-popup-dau {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  padding: 1rem 1.2rem .7rem;
  border-bottom: 1px solid var(--vien);
  background: var(--nen-2);
}

.task-popup-dau h2 {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

.task-popup-than {
  flex: 1 1 auto;
  overflow: auto;
  padding: .8rem 1.2rem 1.2rem;
}

.task-popup-dong {
  flex: 0 0 auto;
  font-family: var(--chu);
  font-size: 1.1rem;
  line-height: 1;
  padding: .25rem .6rem;
  border-radius: .4rem;
  border: 1px solid var(--vien);
  background: var(--nen-2);
  color: var(--chu-mau);
  cursor: pointer;
}

/* Lưới 2 cột: trường NGẮN (trạng thái, agent, treo, các mốc giờ, tokens…)
 * nằm hai cái một hàng; trường DÀI (`--dai`, tóm tắt/phụ thuộc — nội dung
 * có thể nhiều dòng) chiếm cả hàng bằng `grid-column: 1 / -1`. Chủ dự án
 * chỉ ra 2026-09-04 rằng 13 dòng xếp dọc một cột quá cao. Màn hẹp (điện
 * thoại) rơi về một cột ở khối media query bên dưới. */
.task-chi-tiet {
  margin: .5rem 0 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 1rem;
}

.task-chi-tiet-dong {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .3rem 0;
  border-bottom: 1px solid var(--vien);
  font-family: var(--chu);
  font-size: .88rem;
  min-width: 0;
}

.task-chi-tiet-dong--dai {
  grid-column: 1 / -1;
}

.task-chi-tiet-dong dt {
  font-weight: 600;
  color: var(--nhan-mo);
  margin: 0;
}

.task-chi-tiet-dong dd {
  margin: 0;
  color: var(--chu-mau);
  overflow-wrap: anywhere;
}

@media (max-width: 30rem) {
  .task-chi-tiet {
    grid-template-columns: 1fr;
  }
}

.task-popup-lichsu-ds {
  list-style: none;
  margin: .5rem 0 0;
  padding: 0;
}

.task-popup-lichsu-ds li {
  padding: .3rem 0;
  border-bottom: 1px solid var(--vien);
  font-family: var(--chu);
  font-size: .85rem;
  color: var(--nhan-mo);
}

/* Form "Thêm Task" (lượt U1) — mỗi trường một hàng, nhãn thật (không chỉ
 * placeholder), `mo_ta` (textarea) chiếm trọn hàng và cao đủ vài dòng. Chỉ
 * dùng var(--token) — 0 màu cứng. */
form[data-owner-form="task"] {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

form[data-owner-form="task"] label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-family: var(--chu);
  font-size: 0.88rem;
  color: var(--nhan-mo);
}

form[data-owner-form="task"] input,
form[data-owner-form="task"] textarea {
  padding: 0.5rem 0.6rem;
  border-radius: 0.25rem;
  border: 1px solid var(--vien);
  background: var(--nen-2);
  color: var(--chu-mau);
  font-family: var(--chu);
  font-size: 0.95rem;
  width: 100%;
  box-sizing: border-box;
}

form[data-owner-form="task"] input[readonly] {
  background: var(--nen);
  color: var(--nhan-mo);
}

form[data-owner-form="task"] textarea {
  min-height: 6rem;
  resize: vertical;
}

@media (max-width: 700px) {
  .task-o-grid { grid-template-columns: 1fr; }
}
