/* EOS Studio — vỏ: băng dừng khẩn, thanh bên, dải tiêu đề màn, dải điểm
   nhấn, khu nội dung. Chỉ phần KHUNG. Kiểu riêng của từng màn nằm trong
   `kieu/man.css`.

   ── BỐ CỤC 27/08/2026 ────────────────────────────────────────
   Dựng theo bộ bàn giao «AI Control Layout». Khung của cả 31 màn trong bộ ấy
   giống hệt nhau, nên nó nằm ở đây một lần chứ không lặp lại trong từng màn:

     ┌──────────── #bang-dung (chỉ khi cờ dừng bật) ─────────────┐
     ├─ #ben ─┬────────────── #dau-man (60px) ──────────────────┤
     │ 272px  ├────────────── #dai-nhan ────────────────────────┤
     │ /64px  │              #khu                               │
     └────────┴─────────────────────────────────────────────────┘

   Bản trước có `#dai` — một dải 34px chở bốn thứ khác loại. Xem chú thích
   trong `index.html` để biết bốn thứ ấy đi đâu, và vì sao. */

/* ── SỐ ĐO CỦA KHUNG, không phải bậc khoảng cách ─────────────
   Chiều cao thanh đáy ở khổ điện thoại. `#khu` phải chừa đúng chỗ ấy ở đáy,
   không thì dòng cuối chui xuống dưới thanh. Trước 29/08 con số 78 được CHÉP
   vào chỗ chừa chỗ — hai nơi giữ một quan hệ, và ngày thanh đổi cao thì chỉ
   một nơi biết.

   SỔ #235 (17/09/2026): biến ấy vẫn là một LỜI HỨA. Thanh đáy tự cao theo nội dung
   (Vier đo 57px ở 756×742) còn biến khai 78 — hai số cho một chiều cao. Nay thanh
   cao ĐÚNG bằng biến (`height` ở khối @media cuối tệp, nút căn giữa), biến hạ về 60
   cho sát nội dung, và thanh hành động dính đáy đứng TRÊN thanh ấy bằng cùng biến. */
:root {
  --cao-dai-duoi: 60px;
  /* Cỡ icon thanh bên — số của bản bàn giao (`ThanhBenDesktop.dc.html`). Nó là
     một SỐ ĐO, không phải một bậc khoảng cách, nên nó có tên riêng thay vì bị
     ép về thang. Có tên rồi thì chỗ nào cần thẳng hàng với chữ SAU icon sẽ
     TÍNH ra nó, thay vì chép lại con số. */
  --co-ico: 18px;
}

/* ── Băng DỪNG KHẨN ─────────────────────────────────────────
   Không tốn pixel nào khi cờ tắt, và không thể bỏ qua khi cờ bật. Đó là cả lý
   do nó thay cho một dải luôn hiện: một dải luôn nói "đang chạy" là câu trả
   lời cho câu hỏi không ai đặt ra, còn "đang dừng khẩn" thì phải hét lên.

   `position: sticky` chứ không `fixed`: nó là dòng ĐẦU của luồng, và mọi thứ
   dưới nó tự tụt xuống — không phải chừa chỗ bằng tay ở ba khối khác. */
#bang-dung {
  position: sticky; top: 0; z-index: var(--lop-khan);
  display: flex; align-items: center; gap: var(--k-3); flex-wrap: wrap;
  padding: var(--k-2) var(--k-5); font-size: var(--cs-ban);
  background: var(--nen-dung); color: var(--xau);
  border-bottom: 1px solid var(--vien-dung);
}
#bang-dung b { color: var(--xau); letter-spacing: .04em }
#bang-dung span { color: var(--chu) }
#bang-dung .nhat { color: var(--chu-nhat) }
#bang-dung[hidden] { display: none }

/* ── Vỏ ─────────────────────────────────────────────────────
   `min-width: 0` trên cột phải KHÔNG trang trí — nó chữa lỗi tràn ngang cho
   MỌI màn có bảng rộng. Grid item không khai `min-width` nhận kích thước tối
   thiểu tự động bằng min-content của CHÍNH NÓ, và giá trị ấy thắng
   `max-width:100%`; một bảng rộng nằm sâu bên trong kéo giãn được cả cột, rồi
   tới `body`, thành tràn trang (phát hiện 26/08/2026 ở Kịch bản ngắn). */
#vo { display: grid; grid-template-columns: 272px minmax(0, 1fr); min-height: 100vh }
:root[data-ben="gap"] #vo { grid-template-columns: 64px minmax(0, 1fr) }

#phu-menu { display: none }

/* ── Thanh bên ──────────────────────────────────────────────
   Dính theo cả chiều cao màn hình, tự cuộn phần danh sách bên trong. Mở hết
   các nhóm có thể cao hơn màn (laptop 1366×768 còn 734px, mở hết ~785px):
   cuộn một đoạn ngắn trong khung điều hướng là chuyện bình thường; mất bản đồ
   thì không. */
#ben {
  position: sticky; top: 0; align-self: start;
  height: 100vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--tam); border-right: 1px solid var(--vien);
}

#ben-dau { display: flex; align-items: center; gap: var(--k-2); padding: var(--k-4) var(--k-4) var(--k-3) }
/* Tên app là chữ ký của nhận diện: đậm hơn, to hơn một bậc so với nhãn thường. */
#ben-dau h1 {
  flex: 1; min-width: 0; margin: 0; font-size: var(--cs-de); font-weight: 600;
  color: var(--chu); letter-spacing: .02em; white-space: nowrap; overflow: hidden;
}
#nut-gap {
  width: 32px; height: 32px; flex: 0 0 32px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; color: var(--chu-nhat);
  border: 1px solid var(--vien); border-radius: var(--bo);
  font: inherit; font-size: var(--cs-ban); line-height: 1; cursor: pointer;
}
#nut-gap:hover { background: var(--nen-luot); color: var(--chu); border-color: var(--vien-sang) }
/* Nhãn nút gập do CSS quyết, không do JavaScript — cùng ba lý lẽ với nút đổi
   nền: đúng ngay khung hình ĐẦU TIÊN (đoạn mã đồng bộ trong `index.html` đã
   đặt `data-ben` trước lượt vẽ), và nhãn với bố cục cùng đọc MỘT điều kiện nên
   chúng không thể nói lệch nhau. Nút nói NƠI SẼ ĐẾN, không nói nơi đang đứng. */
#nut-gap::before { content: "\00AB" }
:root[data-ben="gap"] #nut-gap::before { content: "\00BB" }

/* ── Nhận diện DOANH NGHIỆP — 22/08/2026 ────────────────────
   Gạch NGANG phía trên tách nó khỏi tên app: hai thứ này là hai danh tính khác
   nhau (app của ai làm ra, và đang làm cho ai), và không có gạch thì mắt đọc
   chúng thành một khối bốn dòng vô nghĩa.

   Logo khách nạp có thể là tệp in ấn vài nghìn pixel. `max-height` + `width:
   auto` co nó về đúng khung bất kể tỉ lệ nào — logo ngang, vuông hay dọc đều
   vừa, không cái nào bị méo. */
#nhan-dien {
  border-top: 1px solid var(--vien);
  border-bottom: 1px solid var(--vien);
  margin: 0 var(--k-4) var(--k-3); padding: var(--k-3); text-align: center;
}
#nhan-dien .logo {
  display: block; margin: 0 auto var(--k-2);
  max-height: 56px; max-width: 100%; width: auto; object-fit: contain;
}
#nhan-dien .ten {
  font-family: var(--tieu-de); font-size: var(--cs-de); font-weight: 600;
  color: var(--chu); letter-spacing: .01em;
  /* Tên dài không được đẩy thanh bên rộng ra hay tràn sang menu. */
  overflow: hidden; text-overflow: ellipsis; white-space: break-space;
}
/* Bản nền tối chỉ hiện khi người dùng ĐÃ CHỌN nền tối. `nen.css` khai
   `color-scheme: light` cố định, nên cài đặt của máy không dự phần. */
#nhan-dien .logo.toi { display: none }
:root[data-nen="toi"] #nhan-dien .logo.sang { display: none }
:root[data-nen="toi"] #nhan-dien .logo.toi { display: block }
/* Chữ tắt của khách, chỉ dùng ở cột gập. Rỗng chỗ khác. */
#nhan-dien .tat { display: none }

#menu { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--k-3) var(--k-4) }

#ben a {
  display: flex; align-items: center; justify-content: space-between; gap: var(--k-2);
  text-decoration: none; color: var(--chu-nhat);
  padding: var(--k-2) var(--k-3); border-radius: var(--bo); margin-bottom: var(--k-0);
  font-size: var(--cs-ban); white-space: nowrap;
}
/* ── ICON — 18px, nét 1,5, theo bản bàn giao ─────────────────
 *
 * Cỡ nằm ở ĐÂY chứ không ở markup: một `width="18"` viết cứng trong thẻ `<svg>`
 * thì thang cỡ không với tới được, và ngày cỡ chữ thanh bên đổi thì hình đứng
 * lại một mình.
 *
 * `stroke: currentColor` (khai trong `icon.js`) làm icon lấy màu của chữ bên
 * cạnh, nên mục đang mở đổi cả chữ lẫn hình bằng một luật màu duy nhất — và
 * `test-mau` khỏi phải đo thêm một mặt phẳng.
 *
 * `.ten` nhận `flex: 1` để nó là thứ CO LẠI khi tên dài, không phải icon. Bản
 * bàn giao khai đúng thế (`nhanStyle`), và thiếu nó thì tên dài bóp méo hình.
 *
 * ── ĐỔI TÊN TỪ `.nhan` — 31/08/2026 ──────────────────────────
 * Tên cũ đụng `.nhan`, lớp HUY HIỆU ở `nen.css`: viền 1px, đệm, cỡ chữ 10px,
 * `font-weight: 600`. Luật ở đây chỉ khai BỐ CỤC — co giãn và cắt chữ — nên bốn
 * thuộc tính kia rơi xuống nguyên vẹn, và mọi nhãn trên thanh bên đội một khung
 * viền quanh mình. Chủ dự án chấm đúng chỗ ấy hôm nay: một mục điều hướng không
 * phải một cái huy hiệu.
 *
 * Chữa bằng `border: 0` thì gỡ được chỗ này và để nguyên cái bẫy cho chỗ sau.
 * Cùng lối chữa với `.tam.nhan` (28/08): ĐỔI TÊN, vì chính cái tên đang nói sai.
 * `.ten` là chữ vỏ này đã dùng cho «tên của một thứ» ở hai chỗ khác —
 * `#nhan-dien .ten` và `#khach .ten` — và cả ba đều bọc trong khu của mình, nên
 * không lớp nào với sang lớp nào. */
#ben a .ico { flex: 0 0 auto; width: var(--co-ico); height: var(--co-ico) }
#ben a .ten { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis }
#ben a:hover { background: var(--nen-luot); color: var(--chu) }
#ben a.dang { background: var(--thuong); color: var(--chu-tren-mau); font-weight: 600 }
#ben a .so { flex: 0 0 auto; opacity: .9; font-variant-numeric: tabular-nums }
/* Chữ đầu, chỉ dùng ở cột gập — `app.js` đặt qua `data-dau`. */
#ben a::before { content: none }

/* ── Khối người đang đăng nhập — D5 ─────────────────────────
   Nó là DANH TÍNH, không phải một chỗ để làm việc. Dùng chung `#ben a` thì mắt
   xếp nó cùng loại với Hậu kỳ hay Kịch bản, và nó ăn mất vị trí quý nhất của
   thanh bên. Mực đậm hơn + vai in hoa nhỏ + một gạch phân cách phía dưới
   (`.le`, do app.js chèn) là đủ để nó thành một tầng khác. */
#ben a.nguoi { color: var(--chu); font-weight: 600; font-size: var(--cs-ban); padding: var(--k-2) var(--k-3) }
#ben a.nguoi .so {
  font-size: var(--cs-nho); letter-spacing: .1em; text-transform: uppercase;
  color: var(--chu-mo); font-weight: 600; opacity: 1;
}
#ben a.nguoi.dang .so { color: var(--chu-tren-mau); opacity: .85 }

/* Khu Tài khoản ĐANG BUNG — dòng tên người là ĐẦU KHU, không phải mục đang mở.
   Tô nó bằng `--thuong` như một mục điều hướng thì hai khối màu đậm nằm chồng
   nhau (tên người + mục con đang mở), và mắt đọc ra hai thứ cùng cấp đang cùng
   được chọn. Nền mờ + mực đậm là đủ nói "anh đang ở trong khu này"; dấu chọn
   THẬT vẫn nằm ở mục con, đúng một chỗ. */
#ben a.nguoi.dang-khu { background: var(--nen-luot); color: var(--chu) }
#ben a.nguoi.dang-khu .so { color: var(--chu-nhat) }
#ben .le { border-top: 1px solid var(--vien); margin: var(--k-3) var(--k-1) }

/* ── Tiêu đề nhóm — D3 · D4 (21/08) ─────────────────────────
   D3: giãn 18px thay vì 8px. Ba nhóm đóng liền nhau ở bản cũ tạo thành một dãy
   ba khối cách nhau 10px — mắt đọc là BA MỤC. Nhóm phải tách nhau bằng khoảng
   trắng, không bắt người đọc chữ mới biết đó là một tầng khác.

   D4: mực `--chu-nhat` thay vì `--chu-mo`. Bản cũ mâu thuẫn: chữ nhạt nhất và
   nhỏ nhất nói "tôi chỉ là cái nhãn, đừng bấm", còn `cursor: pointer` và nền
   hover nói "bấm tôi đi". Nó VẪN là nút gập, nên cách giải là làm mạnh vế NÚT. */
#ben .nhom {
  font-size: var(--cs-nho); font-weight: 600; text-transform: uppercase;
  /* Khe TRÊN là `--k-5`, không phải `--k-4`: chốt D3 (28/08) đòi giãn ≥18px
     trước mỗi tiêu đề nhóm — nhóm phải tách nhau bằng khoảng trắng chứ không
     bắt người đọc phân biệt bằng chữ. Thang không có bậc 18, nên bậc đúng là
     bậc TRÊN nó. Đợt 6 từng làm tròn xuống 16 và `test-web` D3 bắt được ngay:
     làm tròn về bậc gần nhất là luật tốt cho phần lớn chỗ, nhưng ở đâu có một
     mức TỐI THIỂU đã chốt thì tròn xuống là phá chốt. */
  letter-spacing: .12em; color: var(--chu-nhat); margin: var(--k-5) 0 var(--k-0);
  padding: var(--k-1) var(--k-2); border-radius: var(--bo); cursor: pointer; user-select: none;
}
#ben .nhom:hover { background: var(--nen-luot); color: var(--chu) }
#ben .nhom .mui { display: inline-block; width: 13px }
/* nhóm đang ĐÓNG nhưng chứa màn đang mở — sáng lên, đừng để màn biến mất câm */
#ben .nhom.chua-dang { color: var(--chu) }

/* ── Con thụt lề THẬT — D2 ──────────────────────────────────
   Bản cũ: mục đệm trái 10px, tiêu đề nhóm đệm trái 8px — con thụt vào ĐÚNG
   2px. Toàn bộ quan hệ cha–con treo vào một mũi tên ở dòng đầu, và khi nhóm mở
   ra thì mũi tên cách mục cuối hàng trăm pixel: thứ bậc đọc được một lần rồi
   mất. Vạch dọc 1px chạy suốt nhóm trả lời "mục này thuộc nhóm nào" ở MỌI dòng. */
#ben .nhom-muc { display: none; margin-left: var(--k-2) }
#ben .nhom-muc.mo { display: block }
#ben .nhom-muc a { padding-left: var(--k-5) }

/* Mục «Hướng dẫn» ở đáy — nó là trợ giúp VỀ APP, không phải một việc, nên đứng
   ngoài mọi nhóm. Dòng phụ mang tên MÀN ĐANG MỞ và neo tới đúng mục hướng dẫn
   của màn ấy; màn khai `huongDan: null` thì dòng phụ không có. Bản trước để
   đường này thành một thẻ riêng trên dải trạng thái — hai chỗ cho cùng một
   việc, và chỗ kia thì lẫn vào chỗ của tín hiệu dừng khẩn. */
/* ── HAI DÒNG, NHƯNG DÒNG ĐẦU VẪN LÀ MỘT HÀNG ────────────────
 *
 * Mục này khai `display: block` từ 27/08 để chở được dòng phụ. Lúc ấy chưa có
 * icon nên không ai thấy gì; từ 29/08 thì thấy ngay — `block` giết hàng flex
 * của `#ben a`, nên `<svg>` 18px rơi về ĐƯỜNG CƠ CHỮ của dòng 13px và đứng
 * thấp hơn tên tab. Chủ dự án báo cùng ngày.
 *
 * Cách đúng không phải bỏ dòng phụ, mà là để hàng flex TỰ XUỐNG DÒNG: dòng đầu
 * là icon + tên, dòng phụ chiếm trọn bề ngang bên dưới. `align-items: center`
 * của `#ben a` nay lại có tác dụng, nên hình và chữ cùng một trục.
 *
 * Dòng phụ thụt vào đúng bề rộng icon cộng khe, để nó thẳng hàng với TÊN chứ
 * không thẳng hàng với hình — nó là chú thích của cái tên. */
#ben a.huong-dan { flex-wrap: wrap }
#ben a.huong-dan .ve-man {
  flex: 0 0 100%; padding-left: calc(var(--co-ico) + var(--k-2));
  margin-top: var(--k-0); font-size: var(--cs-nho); color: var(--chu-mo);
  overflow: hidden; text-overflow: ellipsis;
}
#ben a.huong-dan.dang .ve-man { color: var(--chu-tren-mau); opacity: .85 }

/* ── Thanh bên GẬP — cột 64px chỉ còn chữ đầu ────────────────
   Đổi VỊ TRÍ và BỀ RỘNG, không đổi NỘI DUNG: cùng một danh sách do cùng một
   hàm `veMenu()` vẽ ra, nên không có menu thứ hai nào phải giữ cho khớp. Chữ
   đầu đến từ `data-dau`, và `title` giữ nguyên tên đầy đủ nên trỏ chuột vào
   vẫn đọc được — cột gập không được biến thành một hàng chữ bí ẩn. */
:root[data-ben="gap"] #ben-dau { flex-direction: column; padding: var(--k-4) 0 var(--k-3) }
:root[data-ben="gap"] #ben-dau h1 { display: none }
:root[data-ben="gap"] #nhan-dien { margin: 0 var(--k-3) var(--k-3); padding: var(--k-2) 0 }
:root[data-ben="gap"] #nhan-dien .logo,
:root[data-ben="gap"] #nhan-dien .ten { display: none }
:root[data-ben="gap"] #nhan-dien .tat {
  display: block; font-family: var(--tieu-de); font-size: var(--cs-phu); font-weight: 600;
  color: var(--chu-nhat); letter-spacing: .06em;
}
/* Thanh cuộn ăn mất 15px của một cột 64px — đo 27/08: mục co còn 32px thay vì
   40px, tức là mất một phần tư bề rộng cho một thanh cuộn không ai kéo. Ẩn nó ở
   ĐÂY và chỉ ở đây; chế độ mở giữ thanh cuộn bình thường, vì ở đó danh sách là
   chữ và người ta có kéo thật. */
:root[data-ben="gap"] #menu { padding: 0 var(--k-2) var(--k-4); scrollbar-width: none }
:root[data-ben="gap"] #menu::-webkit-scrollbar { width: 0 }
:root[data-ben="gap"] #ben .nhom,
:root[data-ben="gap"] #ben a .ten,
:root[data-ben="gap"] #ben a.huong-dan .ve-man,
:root[data-ben="gap"] #ben a.nguoi .so { display: none }
:root[data-ben="gap"] #ben .nhom-muc { display: block; border-left: 0; margin-left: 0 }
:root[data-ben="gap"] #ben a {
  position: relative; justify-content: center;
  width: 40px; margin: 0 auto var(--k-1); padding: 0; height: 36px;
  border: 1px solid var(--vien); font-size: var(--cs-nho); font-weight: 600;
  letter-spacing: .04em;
}
:root[data-ben="gap"] #ben a.dang { border-color: var(--thuong) }
/* Cột gập bày ICON, không bày hai chữ cái — 29/08/2026.
 *
 * Bản 27/08 dựng chữ đầu (`data-dau`) vì lúc ấy app chưa có icon nào, và hai
 * chữ cái là thứ duy nhất phân biệt được 19 ô vuông 40px. Bản bàn giao thì cột
 * gập luôn là icon (`railList` trong `ThanhBenDesktop.dc.html`), và nay app có
 * đủ 19 hình.
 *
 * Chữ đầu KHÔNG bỏ khỏi markup: `data-dau` vẫn là `title` dự phòng, và tab mới
 * thêm mà chưa có icon thì `::before` dưới đây vẫn vẽ ra chữ cho nó — thiếu
 * hình thì mất đẹp, chứ không mất đường đi. */
:root[data-ben="gap"] #ben a:not(:has(.ico))::before { content: attr(data-dau) }
/* Huy hiệu số ở góc trên phải của ô. `position: relative` trên chính thẻ <a>
   ở trên KHÔNG trang trí: thiếu nó thì gốc toạ độ nhảy lên `#ben` (sticky, tức
   là đã được định vị) và mọi huy hiệu dồn về một chỗ ở đầu thanh bên. */
:root[data-ben="gap"] #ben a .so {
  position: absolute; top: -6px; right: -5px; padding: 0 var(--k-1);
  font-size: var(--cs-nho); font-weight: 600; line-height: 13px;
  color: var(--chu-tren-mau); background: var(--vien-chon); border-radius: var(--bo);
}
:root[data-ben="gap"] #ben a .so:empty { display: none }
:root[data-ben="gap"] #ben .le { margin: var(--k-3) var(--k-0) }

/* ── Dải tiêu đề màn ────────────────────────────────────────
   Dính theo màn hình cùng thanh bên: cuộn xuống cuối một bảng dài mà vẫn biết
   mình đang ở tab nào, và Bảng giá vẫn trong tầm tay ngay trước cú bấm tiêu
   tiền.

   ── CHIỀU CAO LÀ MỘT TOKEN, VÀ ĐÚNG DO CẤU TẠO — 28/08/2026 ─
   Mọi thứ dính đỉnh BÊN DƯỚI dải này phải trừ đúng chiều cao của nó. Một con
   số mà hai tệp cùng đoán là một con số sẽ lệch, và nó đã lệch ở hai chỗ:
   `th` (nen.css) còn dính ở 34px — chiều cao dải trạng thái CŨ mà đợt 1 đã
   bỏ — còn thanh lọc Media nguồn dính ở 0px. Cả hai nằm khuất HẲN dưới dải
   này, tức là dính vào một chỗ không ai nhìn thấy. Không lỗi nào báo: chúng
   vẫn «dính», chỉ là dính sai chỗ.

   `height` chứ không `min-height`: khai một token rồi để chiều cao thật do
   nội dung quyết là dựng lại đúng cái lệch vừa gỡ. Cả `#ten-man` lẫn
   `#phu-man` đều một dòng (`nowrap` + `ellipsis`), nên không có gì để tràn. */
:root {
  --cao-dau-man: 68px;
}
#dau-man {
  position: sticky; top: 0; z-index: var(--lop-dau-man);
  display: flex; align-items: center; gap: var(--k-4);
  height: var(--cao-dau-man); padding: var(--k-2) var(--k-6);
  background: var(--tam); border-bottom: 1px solid var(--vien);
}
#danh-man { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--k-3) }
#ten-man {
  margin: 0; font-size: var(--cs-tab); font-weight: 600; line-height: var(--dong-chat);
  letter-spacing: -.015em; color: var(--chu); white-space: nowrap;
}
#phu-man {
  min-width: 0; font-size: var(--cs-phu); color: var(--chu-nhat);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «đang làm cho ‹khách›». Một đường đi, không phải một ô chọn: chỗ ĐỔI doanh
   nghiệp vẫn duy nhất một, trong tab Tài khoản. */
/* ── BA THỨ CÙNG HÀNG THÌ CÙNG MỘT CHIỀU CAO — 08/09/2026 ────
 *
 * Chủ dự án báo dải này «xộc xệch», và đo ra ba con số khác nhau ở khổ 1536:
 * thẻ khách **52px**, `#nut-gia` 40px, `#nut-nen` 40px — ba mép trên ở ba chỗ.
 *
 * 52 không đến từ đệm hay cỡ chữ. Nó đến từ chữ «đổi»: markup viết
 * `class="doi"`, mà `.doi` là một lớp CHUNG ở `nen.css` nghĩa là «hàng
 * nhãn–giá trị có vạch trên» — `padding: var(--k-2) 0` cộng `border-top: 1px`.
 * Chữ ấy nhận trọn cả hai, cao 34px thay vì 17, và vẽ thêm một vạch ngang mảnh
 * không ai đặt. `app.js` nay viết `khach-doi`; đây là nửa CSS của cùng lượt vá.
 *
 * Và cả ba neo vào `--cao-dk`, như mọi điều khiển đứng thành hàng. Trước đó
 * không cái nào neo — chúng chỉ tình cờ bằng nhau khi đệm và cỡ chữ khớp, mà
 * cỡ chữ thì KHÔNG khớp: thẻ khách đọc `--cs-ban` (13px) còn hai nút đọc
 * `--cs-phu` (12px). Nay cùng `--cs-phu`: chúng cùng một vai — một cửa vào ở
 * dải đầu — nên chúng đọc cùng một cỡ. */
#khach {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--k-2);
  min-height: var(--cao-dk);
  padding: var(--k-2) var(--k-3); font-size: var(--cs-phu); text-decoration: none;
  color: var(--chu); border: 1px solid var(--vien-nut); border-radius: var(--bo);
  max-width: 260px; overflow: hidden;
}
#khach:hover { background: var(--nen-luot); border-color: var(--vien-sang) }
#khach .ten { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
#khach .khach-doi { flex: 0 0 auto; font-size: var(--cs-nho); color: var(--chu-mo) }
#khach[hidden] { display: none }

#nut-gia, #nut-nen {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--k-2);
  min-height: var(--cao-dk);
  background: none; color: var(--chu-nhat);
  border: 1px solid var(--vien-nut); border-radius: var(--bo);
  padding: var(--k-2) var(--k-3); font: inherit; font-size: var(--cs-phu); cursor: pointer;
  white-space: nowrap;
}
#nut-gia:hover, #nut-nen:hover { background: var(--nen-luot); color: var(--chu); border-color: var(--vien-sang) }
#nut-nen .hinh { font-size: var(--cs-ban); line-height: 1 }

/* Nhãn nút chuyển nền do CSS quyết, không do JavaScript ─────────
   Hai lý do. Một: nó đúng ngay khung hình ĐẦU TIÊN — `app.js` là module, tức
   là chạy sau khi trang đã vẽ, và một nút nhấp nháy sai nhãn là thứ người ta
   nhìn thấy. Hai: nhãn và bảng màu cùng đọc đúng MỘT điều kiện (`data-nen`),
   nên chúng KHÔNG THỂ nói lệch nhau.
   Nút nói NƠI SẼ ĐẾN, không nói nơi đang đứng — "☾ Nền tối" là *bấm để tối*. */
#nut-nen .hinh::before { content: "\263E" }
#nut-nen .chu::before  { content: "Nền tối" }
:root[data-nen="toi"] #nut-nen .hinh::before { content: "\2600" }
:root[data-nen="toi"] #nut-nen .chu::before  { content: "Nền sáng" }

/* Ẩn mặc định — chỉ hiện ở bề rộng điện thoại, xem @media cuối tệp. */
#nut-menu { display: none; flex: 0 0 auto; padding: var(--k-2) var(--k-3); font-size: var(--cs-de); line-height: 1 }
#nut-ngan-sach {
  display: none; flex: 0 0 auto; width: 32px; height: 32px; padding: 0;
  border-radius: 50%; font-size: var(--cs-nho); line-height: 1; color: var(--chu-nhat);
}

/* ── Dải điểm nhấn ──────────────────────────────────────────
   Chở thứ ĐANG CHẶN người dùng, chứ không phải mọi thứ đang có. Cùng mặt phẳng
   với dải tiêu đề (`--tam`) nhưng chân kẻ bằng một bậc của MÀU NHẤN, nên nó
   đọc ra một tầng riêng mà không phải tô thêm một mảng màu nào — đúng cách
   Nocturne dùng nhấn: một đường kẻ, không phải một vũng.

   Ô rỗng thì cả dải không vẽ gì (`:empty`): một dải kẻ chân mà không chữ nào
   bên trong là một vệt nhiễu suốt bề ngang. */
#dai-nhan {
  display: flex; align-items: stretch;
  background: var(--tam); border-bottom: 1px solid var(--vien-nhan);
  /* ── Khung đo của chính dải — đợt 2d, 28/08/2026 ───────────
     Dải nằm NGOÀI `#khu`, nên `@container khu` không với tới; còn `@media` thì
     đo cửa sổ chứ không đo cột nội dung — đúng lỗi đã đo được ở đợt 2a, và ở
     đây nó nặng hơn vì thanh bên ăn mất 272px trước khi dải được chia.

     Khung đo đặt lên CHÍNH dải chứ không lên `#chinh`: `container-type` kéo
     theo `contain: layout`, tức phần tử mang nó thành khối chứa cho mọi
     `position: fixed` bên trong. Đặt lên `#chinh` là ngăn kéo chi tiết của tab
     Media nguồn (`.ct`, `.ct-nen`) neo vào cột nội dung thay vì cửa sổ — một
     tab khác vỡ vì một luật của tab này. Dải thì không chứa gì `fixed`. */
  container-type: inline-size; container-name: dai;
}
#dai-nhan:empty { display: none }
#dai-nhan .o {
  flex: 0 0 auto; display: flex; gap: var(--k-3);
  padding: var(--k-4) var(--k-5); border-right: 1px solid var(--vien);
}
#dai-nhan .o.rong { flex: 1; min-width: 0; border-right: 0; justify-content: flex-end; align-items: center }
/* Ruột của ô cũng phải co được, không chỉ cái ô. Một ô flex không khai
   `min-width` nhận kích thước tối thiểu bằng min-content của CHÍNH NÓ, nên một
   ô đã `min-width: 0` vẫn bị ruột nó kéo giãn. Đo 28/08 ở khổ 768 với dải của
   tab Chuẩn thương hiệu — ô chở một đoạn prompt cần 286px trong 247px có. */
#dai-nhan .o > div { min-width: 0 }

/* ── Bốn vai ô của dải một màn — đợt 2d, 28/08/2026 ──────────
   Tên đặt theo VAI, không theo tab: sổ nợ của đợt 1 giao cho ô này đúng ba câu
   — «giá của cú bấm sắp tới · cảnh clip trả tiền · còn thiếu trước khi chạy» —
   và cả ba đều là câu của mọi tab tiêu tiền, không của riêng Kịch bản ngắn.
   Đặt tiền tố `kb-` ở đây là dựng lại đúng cái bẫy `bd-*` của đợt 2a.

   Bề rộng nằm ở CSS chứ không ở `style=` trong JS — chốt 23/08 còn nguyên. */
#dai-nhan .o.gia   { flex: 0 0 330px }
#dai-nhan .o.dem   { flex: 0 0 300px }
#dai-nhan .o.thieu { flex: 1; min-width: 0 }
#dai-nhan .o.lam {
  flex: 0 0 auto; border-right: 0;
  align-items: center; justify-content: flex-end; gap: var(--k-4);
}
/* Ô hành động rộng bằng đúng thứ nó chở, nên thứ nó chở phải NGẮN. Đo được
   28/08/2026 ở dải Phòng thử lúc vượt trần: một câu dặn hai dòng kèm đường dẫn
   đẩy ô này lên 559px, và ô `.thieu` — ô DUY NHẤT co được — tụt từ 155px cần
   thiết xuống 49px. Nó không tràn ra ngoài; nó bị cắt trong im lặng.

   Chữa bằng một trần bề rộng ở đây thì chỉ hạ được xuống 89px, vẫn thiếu. Nên
   luật là luật viết chứ không phải luật CSS: câu dặn thuộc về ô đã nói ra sự
   thật, không thuộc về ô chở cái nút. Xem `phong-thu-dai.js`. */

/* Ô «còn thiếu» là ô DUY NHẤT co được, nên nó trả giá cho mọi ô cố định đứng
   cạnh. Đo 28/08 ở khổ 1536×864 (màn của chủ dự án, 1920 ở 125%): thanh bên mở
   thì dải chỉ có 1264px và ô ấy còn 314px; ở 1366 thì còn 144px — không chở nổi
   một câu, và dải phồng lên 123px, tức gần một phần sáu chiều cao nhìn thấy.

   Nên dưới ngưỡng, ô ĐẾM đi trước. Nó là ô rẻ nhất để mất: con số ấy đã có ở
   cột «Clip trả tiền» của bảng danh sách và ở bảng ước tính, còn câu «còn thiếu
   trước khi chạy» thì không có chỗ thứ hai nào nói. */
@container dai (max-width: 1210px) {
  #dai-nhan .o.dem { display: none }
}
/* Vạch nhấn 3px đầu mỗi ô — dấu ngắn thì để đặc, đúng luật của hệ: đường kẻ
   dài mới nhoè hai đầu, dấu nhấn ngắn thì không. */
#dai-nhan .o > .vach { flex: 0 0 3px; border-radius: var(--bo-nho); background: var(--vien-chon) }
/* ── ĐỔI TÊN TỪ `.nhan` — 31/08/2026 ─────────────────────────
   Cùng cái bẫy với nhãn thanh bên ở trên, và ở đây nó ăn cả chiều ngược: luật
   này ĐÈ cỡ chữ với `text-transform` lên mọi thứ mang lớp `.nhan` bên trong
   dải, nên ngày một ô dải muốn bày một huy hiệu THẬT, huy hiệu ấy ra chữ in hoa
   giãn ly. Đặt tên riêng cho nhãn của ô thì hai họ thôi tranh nhau: nhãn là
   `.o-nhan`, huy hiệu vẫn là `.nhan` và vẫn trông ra huy hiệu. */
#dai-nhan .o-nhan {
  font-size: var(--cs-nho); letter-spacing: .14em; text-transform: uppercase;
  color: var(--chu-mo);
  /* `normal`, không `nowrap` — sửa 28/08/2026. Bốn nhãn đầu tiên của dải đều
     ngắn («GIÁ CỦA CÚ BẤM SẮP TỚI»), nên `nowrap` chưa từng lộ ra. Nhãn của tab
     Chuẩn thương hiệu dài hơn, và ở khổ 768 nó cần 238px trong 181px có — nó
     không xuống dòng, nó THÒ RA. Một nhãn hai dòng xấu hơn một nhãn một dòng;
     một nhãn tràn khỏi ô thì không đọc được, và đó mới là thứ phải chặn. */
  white-space: normal;
}
#dai-nhan .so {
  font-family: var(--tieu-de); font-size: var(--cs-so); font-weight: 600; line-height: var(--dong-chat);
  letter-spacing: -.015em; font-variant-numeric: tabular-nums; margin-top: var(--k-1);
}
#dai-nhan .hang { display: flex; align-items: baseline; gap: var(--k-2); margin-top: var(--k-1) }
#dai-nhan .hang .so { margin-top: 0 }
#dai-nhan .phu { font-size: var(--cs-phu); color: var(--chu-nhat); margin-top: var(--k-1) }
#dai-nhan a { color: var(--lien-ket) }

.thanh {
  display: block; width: 100%; max-width: 220px; height: 5px; margin-top: var(--k-2);
  background: var(--vien); border-radius: var(--bo-nho); overflow: hidden;
}
.thanh i { display: block; height: 100%; background: var(--tot) }
.thanh i.nong { background: var(--canh) }
.thanh i.qua  { background: var(--xau) }

#khu { padding: var(--k-5) var(--k-6); max-width: 100%; min-width: 0;
  /* Khung đo cho `.hai-cot` (nen.css). Khai Ở ĐÂY vì đây là chỗ #khu được
     định nghĩa — một phần tử có kích thước do hai tệp cùng quyết là một
     phần tử không ai đọc ra nổi bề rộng thật. */
  container-type: inline-size; container-name: khu;
}

/* ── Trang Đăng nhập: không điều hướng ───────────────────────
   Trước khi đăng nhập, MỌI đường trong thanh bên trả 401 và đá ngược về chính
   trang này. Bố cục cũ giấu bớt điều đó vì thanh bên chỉ là một hàng nút mỏng;
   bố cục mới dành cho nó 272px, tức là một phần năm màn hình toàn link chết.
   Dải nút đáy cũng vậy. Nút đổi nền thì ở lại — nó chạy được, và người ta chọn
   nền trước khi gõ mật khẩu cũng là chuyện thường. */
body[data-man="dang-nhap"] #vo { grid-template-columns: minmax(0, 1fr) }
body[data-man="dang-nhap"] #ben,
body[data-man="dang-nhap"] #dai-duoi,
body[data-man="dang-nhap"] #nut-menu,
body[data-man="dang-nhap"] #nut-gia,
body[data-man="dang-nhap"] #nut-ngan-sach { display: none }

/* Dải nút dưới đáy — rỗng và vô hình ở mọi bề rộng khác điện thoại. */
#dai-duoi { display: none }

/* ── Điện thoại ─────────────────────────────────────────────
   Thanh bên thành ngăn kéo, dải điểm nhấn gập vào sau một nút, và bảy đường
   hay dùng nhất tụt xuống dải đáy — trong tầm ngón cái, trượt ngang nên không
   tràn dòng.

   ĐỔI VỊ TRÍ CỦA #ben, KHÔNG ĐỔI NỘI DUNG — đây là lý do các quy tắc dưới đây
   chỉ nói `display`/`position`/`left`. Danh sách bên trong vẫn do đúng MỘT hàm
   `veMenu()` trong app.js vẽ ra như ở màn rộng. */
@media (max-width: 760px) {
  /* `minmax(0, 1fr)`, KHÔNG `1fr` — cùng lý lẽ đã ghi ở khai gốc, và ở đây nó
     là một lỗi đo được chứ không phải đề phòng. `1fr` cho cột một kích thước
     tối thiểu bằng min-content của CHÍNH NÓ, và min-content của `#dau-man` ở
     bề rộng điện thoại là 391px. Trên viewport 375px, cả trang cuộn ngang
     16px — ở MỌI tab, không riêng tab nào: đo 28/08 được Media nguồn 391 ·
     Tổng quan 395 · Kịch bản ngắn 453. Không lỗi nào báo; chỉ có một trang
     nhúc nhích sang ngang dưới ngón tay người đang cuộn dọc. */
  #vo { grid-template-columns: minmax(0, 1fr); position: relative }
  /* Cột gập vô nghĩa ở đây — ngăn kéo đã trả lại toàn bộ bề ngang rồi. Đè lại
     mọi luật của nó để một lời chọn ghi từ máy tính bàn không đi theo người
     dùng sang điện thoại và biến ngăn kéo thành một cột 64px. */
  :root[data-ben="gap"] #vo { grid-template-columns: minmax(0, 1fr) }

  #nut-menu { display: inline-flex; align-items: center; justify-content: center }

  #phu-menu { position: fixed; inset: 0; z-index: var(--lop-phu); background: var(--nen-phu) }

  #ben {
    position: fixed; top: 0; left: -288px; bottom: 0; z-index: var(--lop-ngan-keo);
    width: 288px; height: auto;
    transition: left .18s ease-out;
    /* Mục cuối (Hướng dẫn) nằm sát đáy danh sách, mà đáy điện thoại thật có
       thanh cử chỉ che một dải — trình duyệt di động không tự chừa chỗ cho nó
       trên một khối `position: fixed`. `env(...)` chừa đúng phần bị che; số
       cứng là chỗ dự phòng cho trình duyệt không hiểu `env()`. */
    padding-bottom: calc(var(--k-5) + env(safe-area-inset-bottom, 0px));
  }
  body[data-menu="mo"] #phu-menu { display: block }
  body[data-menu="mo"] #ben { left: 0 }

  /* Ngăn kéo luôn ở dáng ĐẦY ĐỦ, kể cả khi lời chọn đang là "gập". */
  :root[data-ben="gap"] #ben-dau { flex-direction: row; padding: var(--k-4) var(--k-4) var(--k-3) }
  :root[data-ben="gap"] #ben-dau h1 { display: block }
  :root[data-ben="gap"] #nhan-dien { margin: 0 var(--k-4) var(--k-3); padding: var(--k-3) }
  :root[data-ben="gap"] #nhan-dien .logo { display: block }
  :root[data-ben="gap"] #nhan-dien .ten { display: block }
  :root[data-ben="gap"] #nhan-dien .tat { display: none }
  :root[data-ben="gap"] #menu { padding: 0 var(--k-3) var(--k-4) }
  :root[data-ben="gap"] #ben .nhom { display: block }
  :root[data-ben="gap"] #ben a .ten { display: block }
  :root[data-ben="gap"] #ben a.huong-dan .ve-man { display: block }
  :root[data-ben="gap"] #ben a.nguoi .so { display: block }
  :root[data-ben="gap"] #ben .nhom-muc { display: none; border-left: 1px solid var(--vien); margin-left: var(--k-2) }
  :root[data-ben="gap"] #ben .nhom-muc.mo { display: block }
  /* `width` và `margin: 0 auto` là của cột 64px. Quên trả lại chúng ở đây thì
     mọi mục trong ngăn kéo 288px co về 40px và nằm giữa — đo được 27/08, và
     nó chỉ xảy ra với người đã gập thanh bên trên máy bàn. */
  :root[data-ben="gap"] #ben a {
    position: static; justify-content: space-between; padding: var(--k-2) var(--k-3);
    width: auto; height: auto; margin: 0 0 var(--k-0); border: 0;
    font-size: var(--cs-ban); font-weight: 400; letter-spacing: normal;
  }
  :root[data-ben="gap"] #ben .nhom-muc a { padding-left: var(--k-5) }
  :root[data-ben="gap"] #ben a.nguoi { font-weight: 600; font-size: var(--cs-ban); padding: var(--k-2) var(--k-3) }
  :root[data-ben="gap"] #ben a.dang { font-weight: 600 }
  :root[data-ben="gap"] #ben a::before { content: none }
  :root[data-ben="gap"] #ben a .so {
    position: static; padding: 0; font-size: inherit; font-weight: inherit;
    line-height: inherit; color: inherit; background: none; border-radius: 0;
  }
  :root[data-ben="gap"] #ben a .so:empty { display: inline }
  #nut-gap { display: none }

  /* Dải tiêu đề: hai dòng, vì một dòng không đủ chỗ cho tên tab cạnh tên khách.
     Tên khách tụt xuống làm dòng phụ — đúng chỗ thiết kế điện thoại đặt nó.

     Đổi TOKEN, không đổi `#dau-man`: bề rộng này dải cao 56px, và mọi thứ dính
     đỉnh bên dưới phải đi theo. Đặt lại chiều cao ở đây mà quên token là dựng
     lại đúng chỗ lệch mà token sinh ra để gỡ. */
  :root {
    --cao-dau-man: 56px;
  }
  #dau-man { gap: var(--k-3); padding: var(--k-2) var(--k-3) }
  #danh-man { display: block }
  #ten-man { font-size: var(--cs-de) }
  #phu-man { font-size: var(--cs-nho) }
  #khach { display: none }
  #nut-gia, #nut-nen .chu { display: none }
  #nut-nen { padding: var(--k-2) var(--k-2) }
  #nut-ngan-sach { display: inline-flex; align-items: center; justify-content: center }

  /* Dải điểm nhấn không đủ chỗ nằm ngang — gập lại sau nút tròn cạnh tiêu đề,
     xếp dọc khi mở. Vẫn là CÙNG một dải do cùng một hàm vẽ; chỉ chỗ đứng đổi. */
  #dai-nhan { display: none }
  body[data-ngansach="mo"] #dai-nhan { display: block }
  #dai-nhan .o { border-right: 0; border-bottom: 1px solid var(--vien); padding: var(--k-3) var(--k-4) }
  #dai-nhan .o.rong { display: none }
  /* Dải thành `display:block` ở đây, nên `flex-basis` của ba ô cố định không
     còn nghĩa và không ô nào tràn. Hai luật dưới là hai luật CÓ nghĩa:

     · ô ĐẾM hiện lại. Khối `@container` ở trên giấu nó vì ô «còn thiếu» phải
       nhường chỗ THEO CHIỀU NGANG; xếp dọc rồi thì không ai nhường ai, và giấu
       tiếp là mất một con số vì một lý do đã hết đúng.
     · ô HÀNH ĐỘNG thôi căn phải. Căn phải là để nút đứng ở mép ngoài cùng của
       một hàng; ở một cột dọc nó chỉ làm nút rời khỏi lề của mọi chữ bên trên. */
  #dai-nhan .o.dem { display: flex }
  #dai-nhan .o.lam { justify-content: flex-start; flex-wrap: wrap }
  .thanh { max-width: none }

  /* Đệm đáy = CHIỀU CAO thanh đáy, không phải một bậc khoảng cách. Có tên rồi
     thì đổi thanh là đổi một chỗ, thay vì nhớ có một con số 78 nằm đâu đó. */
  #khu { padding: var(--k-4) var(--k-3) calc(var(--cao-dai-duoi) + env(safe-area-inset-bottom, 0px)) }

  #dai-duoi {
    display: flex; align-items: center; box-sizing: border-box;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--lop-day-vo);
    height: calc(var(--cao-dai-duoi) + env(safe-area-inset-bottom, 0px));
    background: var(--tam); border-top: 1px solid var(--vien);
    padding: 0 0 env(safe-area-inset-bottom, 0px);
  }
  #dai-duoi .cuon {
    flex: 1; min-width: 0;
    display: flex; gap: var(--k-2); overflow-x: auto; scrollbar-width: none; padding: 0 var(--k-3);
  }

  /* ── THANH HÀNH ĐỘNG ĐỨNG TRÊN THANH ĐÁY — sổ #235, 17/09/2026 ──
     `.thanh-hanh-dong` (nen.css) dính `bottom: 0`, lớp 2; thanh đáy ở khổ này là
     `fixed` đáy, lớp 12 — nên nút «Lưu cảnh này» nằm ĐÚNG dưới thanh đáy: Vier bấm
     tâm nút ở 756×742 và `elementFromPoint` trả nút «Ngân sách». Dính cách đáy đúng
     bằng chiều cao thanh (cùng biến, cùng khối) thì năm tệp màn dùng lớp ấy hưởng
     chung. Trang Đăng nhập giấu thanh đáy nên giữ `bottom: 0`. */
  body:not([data-man="dang-nhap"]) .thanh-hanh-dong {
    bottom: calc(var(--cao-dai-duoi) + env(safe-area-inset-bottom, 0px));
  }
  #dai-duoi button {
    flex: 0 0 auto; padding: var(--k-2) var(--k-3); font-size: var(--cs-phu);
    background: none; border: 1px solid var(--vien-nut); border-radius: var(--bo);
    color: var(--chu-nhat); white-space: nowrap;
  }
  #dai-duoi button .so { font-variant-numeric: tabular-nums; color: var(--vien-chon) }
}

/* Máy nào xin bớt chuyển động thì thôi chuyển động — kể cả lúc đổi nền. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
      transition-duration: .01ms !important }
}
