/* Source Sans 3 — tự host trong app/static/fonts/.
   Trước đây dùng @import tới Google Fonts ngay dòng đầu file CSS: trình duyệt phải
   tải xong app.css rồi mới phát hiện ra còn phải tải thêm font, tức hai vòng chờ
   nối tiếp trước khi trang hiện chữ. Tự host bỏ được vòng chờ đó và không còn phụ
   thuộc vào một dịch vụ bên ngoài.

   Đây là font biến thiên: một file phủ toàn bộ độ đậm 400–800. Bản @import cũ chỉ
   tải tới 700 nên 15 chỗ khai font-weight:800 đang bị trình duyệt làm đậm giả. */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/static/fonts/source-sans-3-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/static/fonts/source-sans-3-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* ==========================================================================
   BẢNG MÀU "MỰC & CHÀM" — đợt nâng cấp giao diện 28/08/2026

   Đổi từ bảng slate-xanh mặc định sang hệ mực trung tính + chàm đậm. Bảng cũ
   pha xanh vào MỌI thứ (chữ #0f172a, viền #e2e8f0, nền #f8fafc đều là sắc
   xanh), nên cả trang một tông và con số không nổi lên khỏi nền. Hệ mới giữ
   nền/viền/chữ ở sắc trung tính, dành riêng màu cho ngữ nghĩa: chàm = thao
   tác, lục = xong, hổ phách = chờ, đỏ = cần xử lý.

   Mỗi màu ngữ nghĩa có đủ ba bậc — `-soft` (nền), `-line` (viền) và màu chữ.
   Trước đây mỗi chỗ tự pha một sắc nền riêng, nên cùng một trạng thái hiện ra
   ba màu khác nhau ở ba trang.

   Thang bán kính (`--radius-*`) GIỮ NGUYÊN: giá trị 14/18px là của mockup
   phase-1 và đã được chủ sở hữu duyệt riêng (xem docs/ui-ux/DESIGN.md).
   ========================================================================== */
:root {
  --bg: #F4F5F7;
  --surface: #ffffff;
  --surface-2: #F9FAFB;
  --surface-3: #F1F3F6;
  --line: #E4E7EC;
  --line-soft: #EFF1F5;
  --line-strong: #DFE3EA;
  --text: #15171C;
  --text-2: #3B414D;
  --muted: #737B8A;
  --primary: #2846D6;
  --primary-strong: #1E36AB;
  --primary-soft: #EEF1FE;
  --primary-line: #C6CFFA;
  --primary-tint: rgba(40, 70, 214, 0.07);
  --accent: #0B7268;
  --danger: #C02A24;
  --danger-soft: #FDECEB;
  --danger-line: #F5C7C4;
  --sidebar: #14161C;
  --sidebar-raise: #1B1E26;
  --sidebar-text: #A7AEBC;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 18px;
  --radius-xl: 20px;
  --radius-pill: 999px;
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 10px;
  --space-6: 12px;
  --space-7: 14px;
  --space-8: 16px;
  --space-9: 18px;
  --space-10: 20px;
  --space-11: 24px;
  --space-12: 32px;
  --space-13: 40px;
  /* Bóng xếp hai lớp: một lớp sát viền cho cạnh sắc, một lớp toả rộng cho độ
     nổi. Bản cũ chỉ có lớp toả nên panel trông như dán phẳng lên nền. */
  --shadow-xs: 0 1px 2px rgba(16, 18, 24, 0.05);
  --shadow-soft: 0 1px 2px rgba(16, 18, 24, 0.04), 0 6px 18px rgba(16, 18, 24, 0.05);
  --shadow-raise: 0 2px 4px rgba(16, 18, 24, 0.04), 0 12px 28px rgba(16, 18, 24, 0.07);
  --shadow-modal: 0 12px 24px rgba(16, 18, 24, 0.08), 0 32px 64px rgba(16, 18, 24, 0.14);
}

* { box-sizing: border-box; }
html { font-size: 16px; }
body {
  margin: 0;
  font-family: 'Source Sans 3', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  color: var(--text);
  background: var(--bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; }

.app-shell {
  min-height: 100vh;
  display: flex;
}

/* Sidebar: mực gần-đen phẳng thay cho dải gradient xanh navy. Gradient cũ đổi
   màu theo chiều dọc nên mục menu ở đáy nằm trên nền khác mục ở đỉnh, và
   trạng thái "đang chọn" đọc lệch tuỳ vị trí. */
/* Sidebar dính đỉnh, cao đúng một màn hình, và TỰ CUỘN.
   Trước đây chỉ có `min-height: 100vh` mà không có `overflow-y` — nghĩa là khi
   mở vài nhóm menu cùng lúc, phần menu dài quá màn hình bị đẩy ra ngoài vùng
   nhìn thấy và KHÔNG CÓ CÁCH NÀO cuộn tới. Cuộn trang cũng không giúp, vì
   sidebar cao theo nội dung chứ không theo trang. Đây mới là gốc của việc
   "không nhìn được hết", còn việc các nhóm không tự đóng chỉ làm nó xảy ra
   thường xuyên hơn. (Bản mobile đã có `overflow-y: auto` từ trước — chỉ desktop
   thiếu.) */
.sidebar {
  position: sticky;
  top: 0;
  align-self: flex-start;
  width: 232px;
  flex: 0 0 232px;
  display: flex;
  flex-direction: column;
  background: var(--sidebar);
  color: var(--sidebar-text);
  padding: var(--space-10) var(--space-7) var(--space-8);
  height: 100vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-right: 1px solid rgba(255,255,255,0.06);
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.18) transparent;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,0.16);
  background-clip: content-box;
}
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.28); background-clip: content-box; }

.sidebar-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
}
.brand {
  position: relative;
  padding: var(--space-1) 0 var(--space-1) var(--space-7);
  margin-bottom: var(--space-10);
}
.brand::before {
  content: '';
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(180deg, #8E9DF2, var(--primary));
}
.brand strong {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.02em;
}

/* Flex column thay cho grid, để `.nav-section-personal` đẩy được xuống đáy
   bằng `margin-top: auto` khi menu ngắn hơn màn hình. */
.sidebar-nav {
  display: flex;
  /* `flex: 1 0 auto`, KHÔNG phải `flex: 1`.
     `flex: 1` nghĩa là `1 1 0%` — chiều cao của nav được tính từ chiều cao của
     sidebar chứ không từ nội dung, nên mở thêm nhóm menu thì hộp nav vẫn y
     nguyên, `scrollHeight` của sidebar không tăng, và phần menu dôi ra lại
     không cuộn tới được — đúng lỗi mà cả thay đổi này sinh ra để sửa.
     `1 0 auto` cho phép nav giãn ra lấp chỗ trống khi menu ngắn (để
     `margin-top: auto` ghim được "Cá nhân" xuống đáy), nhưng cấm nó co lại
     dưới chiều cao nội dung khi menu dài. */
  flex: 1 0 auto;
  flex-direction: column;
  gap: var(--space-2);
}
/* Cấm các mục trong menu co lại. Mặc định flex item có `flex-shrink: 1`, nên
   khi menu dài hơn khung, trình duyệt BÓP từng nhóm cho vừa thay vì để nav cao
   ra — mà `.nav-section` lại có `overflow: hidden`, nên phần bị bóp biến mất
   không dấu vết và nút Đăng xuất rơi ra ngoài vùng cuộn. Bản `display: grid`
   trước đây không dính lỗi này vì hàng grid luôn cao theo nội dung. */
.sidebar-nav > * { flex: 0 0 auto; }

/* Nhóm liên kết phẳng (Tạo QR, Giao dịch chờ xử lý…) — trước đây là các mục
   trần dán ở đáy menu, nhấn mạnh bằng <strong> nên vừa hét vừa không cho biết
   chúng thuộc về đâu. Nay có nhãn nhóm như mọi nhóm khác, chỉ khác là không
   gập được vì chỉ có 2–4 mục. */
.nav-group-label {
  margin: var(--space-6) 0 var(--space-2);
  padding: 0 var(--space-6);
  color: #6F7686;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.nav-section {
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.nav-section[open] {
  background: var(--sidebar-raise);
  border-color: rgba(255,255,255,0.06);
}
.nav-section-title {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  color: #E7E9EE;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  user-select: none;
}
.nav-section-title:hover { background: rgba(255,255,255,0.04); }
.nav-section-title::-webkit-details-marker { display: none; }
.nav-section-title::after {
  content: '';
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid #6F7686;
  border-bottom: 1.5px solid #6F7686;
  transform: rotate(-45deg);
  transition: transform 0.18s ease;
}
.nav-section[open] > .nav-section-title::after { transform: rotate(45deg); }
.nav-section-items {
  display: grid;
  gap: var(--space-2);
  padding: 0 var(--space-4) var(--space-4);
}

.nav-item {
  position: relative;
  border-radius: var(--radius-sm);
  padding: var(--space-5) var(--space-6) var(--space-5) var(--space-7);
  font-size: 13px;
  font-weight: 500;
  color: var(--sidebar-text);
  display: flex;
  align-items: center;
  gap: var(--space-6);
  width: 100%;
  text-align: left;
  transition: color 0.16s ease, background 0.16s ease;
}
/* Icon mờ hơn chữ ở trạng thái thường, sáng bằng chữ khi đang chọn — icon là
   thứ để nhận dạng nhanh, không phải thứ để đọc, nên nó không được tranh độ
   tương phản với nhãn. */
.nav-icon {
  flex: 0 0 auto;
  opacity: 0.62;
  transition: opacity 0.16s ease;
}
.nav-item:hover .nav-icon { opacity: 0.85; }
.nav-item.active .nav-icon { opacity: 1; }
.nav-item > span { min-width: 0; }
.nav-item:hover {
  background: rgba(255,255,255,0.06);
  color: #F5F6F8;
}
/* Bỏ `transform: translateX(2px)` khi hover: mục menu nhích ngang làm cả cột
   điều hướng rung khi rê chuột dọc danh sách. Đổi nền là đủ phản hồi. */
.nav-item.active {
  background: rgba(40, 70, 214, 0.26);
  color: #fff;
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(142, 157, 242, 0.30);
}
.nav-item.active::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: var(--radius-pill);
  background: #8E9DF2;
}
/* Mục con trong nhóm thụt vào cho thẳng hàng icon với mục cấp một. */
.nav-section-items .nav-item { padding-left: var(--space-6); }
/* Ghim "Cá nhân" + Đăng xuất xuống đáy. Trước đây nó nằm lọt giữa danh sách,
   phía trên mấy liên kết hay dùng nhất — nên chỗ bấm Đăng xuất đổi vị trí tuỳ
   theo user có bao nhiêu nhóm menu.

   `margin-top: auto` đặt trên ĐƯỜNG KẺ chứ không trên nhóm: đường kẻ tự đẩy
   mình và mọi thứ sau nó xuống đáy. Làm bằng `::before` của chính nhóm thì
   vạch kẻ rơi vào bên trong khung nền của nhóm khi nhóm mở ra, trông như một
   nét thừa nằm giữa hộp. */
.nav-divider {
  flex: 0 0 auto;
  margin: auto var(--space-4) var(--space-5);
  height: 1px;
  background: rgba(255,255,255,0.07);
}
.nav-section-personal { margin-top: 0; }
.sidebar-logout-form { margin: 0; }
.sidebar-logout {
  border: 0;
  background: transparent;
  cursor: pointer;
}
.sidebar-close,
.mobile-menu-toggle,
.sidebar-overlay { display: none; }

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Topbar dính đỉnh ở mọi khổ màn hình. Trước đây chỉ dính ở mobile, nên trên
   desktop cuộn một bảng 500 dòng là mất luôn tên trang và ô tài khoản. */
.topbar {
  position: sticky;
  z-index: 700;
  top: 0;
  height: 62px;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-11);
}

.topbar-title {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.top-actions {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.user-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-5) var(--space-3) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
}
.user-pill-text strong {
  display: block;
  font-size: 13px;
  color: var(--text);
}
.user-pill-text span {
  font-size: 12px;
  color: var(--muted);
}

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(160deg, #4763E4, var(--primary-strong));
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
}

.page-body {
  padding: var(--space-11) var(--space-12);
  display: grid;
  gap: var(--space-10);
  align-content: start;
}
@media (max-width: 1280px) {
  .page-body { padding: var(--space-11); }
}

.page-body-banner-only {
  padding-bottom: 0;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-8);
}
.page-header h1 {
  margin: 0 0 var(--space-4);
  font-size: 28px;
  line-height: 1.15;
  letter-spacing: -0.04em;
}
.page-header p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

.page-header-compact {
  gap: var(--space-6);
  align-items: center;
}

.page-header-compact h1 {
  margin-bottom: var(--space-2);
  font-size: 24px;
}

.page-header-compact p {
  font-size: 13px;
}

/* --- Tiêu đề trang: chỉ hiện MỘT lần ------------------------------------
   Mọi trang chính đang nói tên mình ba lần: topbar "Sapo Bank", rồi `<h1>`
   "Sapo Bank", rồi tiêu đề panel "Dữ liệu Sapo Bank". Riêng khối `<h1>` ăn
   khoảng 34px chiều cao trước khi thấy dòng dữ liệu đầu tiên — trên laptop
   768px đó là phần đáng kể của vùng bảng.

   `<h1>` được giữ trong DOM (cấu trúc tiêu đề của tài liệu và trình đọc màn
   hình vẫn cần nó) nhưng ẩn khỏi mắt — và CHỈ khi topbar thật sự tìm được tên
   trang (`.has-page-title`, do `base.html` gắn). Trang không nằm trong bảng
   tên vẫn hiện `<h1>` bình thường, nên không trang nào bị mất tiêu đề. */
.has-page-title .page-body > .page-header > div > h1 {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
/* Bỏ `<h1>` rồi thì dòng mô tả tự lên làm dòng đầu — không cần khối tiêu đề
   cao như trước. */
.has-page-title .page-body > .page-header {
  align-items: center;
  min-height: 0;
}
.has-page-title .page-body > .page-header > div > p {
  margin: 0;
}
/* Khối tiêu đề chỉ còn `<h1>` bị ẩn thì không nên chiếm một ô lưới nào cả. */
.has-page-title .page-body > .page-header:not(:has(p)):not(:has(form)):not(:has(.btn)):not(:has(a)) {
  display: none;
}

.button-row {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
}

/* --- Tab trang: một điều khiển phân đoạn duy nhất -------------------------
   Bản cũ dựng mỗi tab thành một THẺ cao 52px có viền, bóng đổ và mũi tên "›",
   còn tab đang chọn thì thêm dòng chữ "ĐANG XEM" ở mép phải. Ba hệ quả:
   hai tab "Tiền vào / Tiền ra" chiếm gần 100px chiều cao trước khi thấy dòng
   dữ liệu đầu tiên; thẻ có viền + bóng trông y hệt nút bấm nên không ai biết
   đâu là tab đâu là hành động; và chữ "Đang xem" lặp lại thông tin mà nền
   xanh đã nói rồi.

   Nay là điều khiển phân đoạn: một rãnh xám, tab đang chọn là "viên" trắng
   nổi lên. Cao 40px thay vì 52px, và cùng một hình dạng ở mọi module. */
.page-tabs {
  display: inline-grid;
  grid-auto-flow: column;
  gap: var(--space-1);
  width: max-content;
  max-width: 100%;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}

.page-tab {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  min-height: 32px;
  padding: 0 var(--space-8);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.page-tab::after { content: none; }

.page-tab:hover { color: var(--text-2); }

.page-tab-label {
  display: block;
  line-height: 1.35;
}

.page-tab.active {
  background: var(--surface);
  border-color: transparent;
  color: var(--primary);
  box-shadow: var(--shadow-xs), inset 0 0 0 1px rgba(21, 23, 28, 0.05);
}

.page-tab-count {
  min-width: 22px;
  padding: 1px var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--muted);
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.page-tab.active .page-tab-count {
  background: var(--primary-soft);
  color: var(--primary);
}

/* ==========================================================================
   THANH BỘ LỌC DÙNG CHUNG — `.filterbar`

   Trước đợt này, cùng một ý niệm "lọc theo trạng thái kế toán" được dựng bằng
   BỐN điều khiển khác nhau ở bốn trang:

     Sapo Bank      <select> 4 mục      (tải lại trang)
     Pancake Bank   <select> 6 mục      (tải lại trang)
     ZeiJP Bank     3 nút .btn-secondary (lọc bằng JS)
     Khách buôn     chip bo tròn cam    (lọc bằng JS)

   Nhân viên kế toán dùng cả bốn trang trong một buổi làm việc, nên phải học
   lại chỗ bấm ở mỗi trang. Ba trang còn đặt bộ lọc ở ba vị trí khác nhau
   (trong panel-head, dưới panel-head, trên bảng).

   Luật chốt — áp cho toàn app:

     · Danh sách NGẮN và CỐ ĐỊNH (≤ 6 mục: Tất cả / Cần kiểm tra / Cần bổ sung
       mã …)  →  hàng `.chip`. Bấm một phát là xong, và chip mang được số
       lượng — thứ <select> không bao giờ hiện ra cho tới khi mở dropdown.
     · Danh sách DÀI hoặc MỞ (ngân hàng, ĐVVC, kênh bán, nhân viên, số
       dòng/trang, ngày, ô tìm kiếm)  →  `.field` bọc <select>/<input>.

   Chip có thể là <a href> (lọc phía máy chủ) hoặc <button> (lọc bằng JS) —
   hình dạng giống hệt nhau, vì với người dùng thì đó là cùng một thao tác.
   ========================================================================== */
.filterbar {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-9);
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
/* Khi đứng ngoài panel (trang không có .table-wrap bọc). */
.filterbar-standalone {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.filterbar-row {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--space-5) var(--space-6);
}
.filterbar-row + .filterbar-row {
  padding-top: var(--space-6);
  border-top: 1px solid var(--line);
}
/* Nhãn canh theo ĐÁY hàng chứ không theo giữa: một hàng có thể cao bằng chip
   (30px) hoặc bằng một `.field` vốn có nhãn riêng ở trên (~52px). Canh giữa
   thì nhãn trôi lên lơ lửng ngay khi hàng có thêm một ô nhập. */
.filterbar-label {
  flex: 0 0 auto;
  align-self: flex-end;
  padding-bottom: 7px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

/* --- Hàng chip ----------------------------------------------------------- */
.chipset {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  min-width: 0;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 30px;
  padding: 0 var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-2);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.chip:hover {
  border-color: var(--primary-line);
  background: var(--primary-soft);
  color: var(--primary-strong);
}
.chip.is-active {
  border-color: transparent;
  background: var(--primary);
  color: #fff;
  box-shadow: var(--shadow-xs);
}
.chip.is-active:hover { background: var(--primary-strong); color: #fff; }

/* 12px là SÀN, không phải gợi ý: DESIGN.md chốt 2026-07-26 sau khi đo trên
   trình duyệt — nâng từ 10–11px lên 12px làm dòng cao thêm 12% nhưng số dòng
   nhìn thấy trên một màn hình không đổi. Đừng hạ xuống 11px cho "gọn". */
.chip-count {
  min-width: 18px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.chip.is-active .chip-count {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}
/* Chip mang nghĩa "còn việc phải làm" được đánh dấu bằng chấm hổ phách, để
   người trực thấy ngay có tồn đọng mà không phải đọc con số. */
.chip-alert .chip-count { background: var(--warning-soft); color: #8A4A06; }
.chip-alert.is-zero .chip-count { background: var(--surface-3); color: var(--muted); }
.chip-alert.is-active .chip-count { background: rgba(255, 255, 255, 0.22); color: #fff; }

.chip-clear {
  padding: 0 var(--space-3);
  border: 0;
  background: transparent;
  color: var(--primary);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.chip-clear:hover { text-decoration: underline; }
.chip-clear[hidden] { display: none !important; }

/* --- Ô nhập trong thanh lọc ---------------------------------------------- */
.field {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
  flex: 0 1 auto;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
}
.field > input,
.field > select {
  min-width: 132px;
  min-height: 32px;
  padding: var(--space-3) var(--space-5);
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.field > select { padding-right: 28px; }
.field-search { flex: 1 1 220px; }
.field-search > input { width: 100%; min-width: 180px; }
.field-narrow > select,
.field-narrow > input { min-width: 84px; }

/* Biến thể lưới, cho hai trang Tổng quan có 12–13 ô lọc. Xếp flex thì hàng
   cuối lởm chởm và ô rộng hẹp khác nhau tuỳ độ dài nhãn; `auto-fill` cho các ô
   luôn thẳng cột và tự giảm số cột theo bề rộng màn hình — thay hẳn ba khối
   media query mà mỗi trang trước đây phải tự viết. */
.filterbar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  align-items: end;
  gap: var(--space-5) var(--space-6);
}
.filterbar-grid .field > input,
.filterbar-grid .field > select { min-width: 0; width: 100%; }
.filterbar-grid .filterbar-actions {
  grid-column: 1 / -1;
  justify-content: flex-end;
  margin-left: 0;
  padding-top: var(--space-2);
}

.filterbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-left: auto;
}
.filterbar-actions .btn { min-height: 32px; padding: 0 var(--space-7); font-size: 13px; }
/* Số bản ghi khớp bộ lọc — luôn nằm cuối thanh, mọi trang. */
.filterbar-meta {
  flex: 0 0 auto;
  align-self: center;
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 768px) {
  .filterbar { padding: var(--space-6); }
  .filterbar-row { align-items: stretch; }
  .filterbar-label { align-self: flex-start; }
  .chipset { width: 100%; }
  .chip { flex: 1 1 auto; justify-content: center; }
  .field { flex: 1 1 100%; }
  .field > input,
  .field > select { width: 100%; min-height: 40px; }
  .filterbar-actions { width: 100%; margin-left: 0; }
  .filterbar-actions .btn { flex: 1 1 0; min-height: 40px; }
}

.page-tabs-hint {
  margin-top: -8px;
  color: var(--muted);
  font-size: 12px;
}

.action-row {
  align-items: center;
}

.action-row-end {
  justify-content: flex-end;
}

.btn {
  border-radius: var(--radius-md);
  min-height: 38px;
  padding: var(--space-5) var(--space-8);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  white-space: nowrap;
  background: var(--primary);
  color: #fff;
  cursor: pointer;
  box-shadow: var(--shadow-xs);
}
/* Nút phụ trước đây là nền trắng trên nền panel cũng trắng, chỉ phân biệt bằng
   một đường viền 1px xám nhạt — gần như tàng hình trong bảng. Nền xám nhạt
   tách nó khỏi panel mà vẫn nhường độ tương phản cho nút chính. */
.btn-secondary {
  background: var(--surface-2);
  color: var(--text-2);
  border-color: var(--line-strong);
}
.btn-danger {
  background: var(--danger);
  color: #fff;
}
/* Hành động phụ trợ (xoá lọc, huỷ) — chữ, không phải nút đặc. */
.btn-ghost {
  background: transparent;
  color: var(--muted);
  border-color: transparent;
  box-shadow: none;
}
.btn-ghost:hover {
  background: var(--surface-3);
  color: var(--text-2);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-7);
}
.card-grid.single-column {
  grid-template-columns: 1fr;
}

.profile-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.profile-card {
  align-content: start;
}

.info-list {
  display: grid;
  gap: var(--space-6);
  margin: 0;
}

.info-list div {
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--line);
}

.info-list div:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.info-list dt {
  margin-bottom: var(--space-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.info-list dd {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

.compact-info-list {
  gap: var(--space-5);
}

.card,
.table-wrap,
.form-panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}

.card {
  padding: var(--space-9);
  display: grid;
  gap: var(--space-5);
}
.card h3 {
  margin: 0;
  font-size: 16px;
}
.summary-card {
  gap: var(--space-3);
}
.summary-label {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}
.summary-value {
  font-size: 34px;
  line-height: 1;
}
.dashboard-summary-grid {
  margin-bottom: var(--space-9);
}
.dashboard-link-card {
  gap: var(--space-7);
}
.dashboard-link-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}

/* Tổng quan: thẻ thống kê theo nền tảng (Sapo/Pancake). */
.platform-stats {
  display: grid;
  gap: var(--space-9);
  margin-top: var(--space-11);
}
.platform-card {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-top: 3px solid var(--platform-color, var(--primary));
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: var(--space-11) var(--space-11) var(--space-12);
}
.platform-card.pancake { --platform-color: var(--accent); --platform-tint: rgba(15, 118, 110, 0.09); }
.platform-card.sapo { --platform-color: var(--primary); --platform-tint: rgba(29, 78, 216, 0.08); }
.platform-head {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin-bottom: var(--space-10);
}
.platform-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--platform-tint, var(--primary-tint));
  color: var(--platform-color, var(--primary));
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.platform-head h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.platform-scope {
  margin-left: auto;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: var(--space-3) var(--space-6);
}
.stat-row {
  display: grid;
  grid-template-columns: 1.3fr 1.3fr 1fr;
}
.stat-cell {
  padding: var(--space-2) var(--space-11);
  border-left: 1px solid var(--line);
}
.stat-cell:first-child { border-left: none; padding-left: 0; }
.stat-cell:last-child { padding-right: 0; }
.stat-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-bottom: var(--space-5);
  white-space: nowrap;
}
.stat-eyebrow svg { color: var(--platform-color, var(--primary)); flex: 0 0 auto; }
.stat-hero {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.stat-hero-value { white-space: nowrap; }
.stat-sub {
  margin-top: var(--space-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}
.stat-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 700;
  vertical-align: middle;
}
.stat-delta-up { color: var(--success); background: #E1F5E8; }
.stat-delta-down { color: var(--danger); background: #FDECEB; }
.stat-breakdown {
  margin-top: var(--space-10);
  padding-top: var(--space-9);
  border-top: 1px solid var(--line);
  display: grid;
  gap: var(--space-6);
}
.breakdown-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-5);
}
.breakdown-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
  flex: 0 0 150px;
}
@media (max-width: 720px) {
  .stat-row { grid-template-columns: 1fr; gap: var(--space-8); }
  .stat-cell { border-left: none; padding: 0; }
  .breakdown-label { flex-basis: 100%; }
}
.card p,
.form-hint {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

.table-wrap {
  overflow: hidden;
}

.table-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.voucher-table-compact {
  font-size: 12px;
}

.voucher-table-compact th,
.voucher-table-compact td {
  padding: 8px 7px;
}

.voucher-table-compact th {
  white-space: nowrap;
  line-height: 1.15;
}

.voucher-table-compact .status-pill {
  padding: 3px 6px;
  font-size: 12px;
}

.pancake-progress-cell { min-width: 210px; }
.pancake-progress-steps,
.pancake-progress-reason { display: block; margin-top: 4px; line-height: 1.35; }
.pancake-progress-steps { color: var(--text-2); }
.pancake-progress-reason { color: var(--warning); font-weight: 600; }

/* Bảng dòng nguồn có 18 cột nên luôn tràn ngang. Năm cột chẩn đoán ở cuối hầu
   hết chỉ là dấu gạch ngang, nên chế độ rút gọn giấu chúng đi, còn ai cần thì
   bấm "Đầy đủ". Lựa chọn được nhớ lại cho lần sau. */
.voucher-table-density.is-compact .col-detail { display: none; }
.voucher-density-toggle { display: flex; gap: var(--space-2, 6px); }
.voucher-density-toggle .is-active { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }

/* Hàng tiêu đề dính lại khi kéo. Bảng dài trăm dòng mà mất tên cột thì mười ba
   cột số trông như nhau hết.

   Bắt buộc phải có chiều cao trần: `position: sticky` bám vào hộp cuộn gần nhất,
   và `.table-scroll` đã là hộp cuộn sẵn (khai `overflow-x: auto` thì trình duyệt
   cho `overflow-y` thành auto luôn). Hộp không tự cuộn dọc thì tiêu đề không có
   gì để dính vào — đây đúng là lý do nó chưa đi theo. Cùng cách làm với
   .sapo-bank-table-scroll và .wholesale-transaction-table-scroll. */
.voucher-rows-scroll {
  max-height: calc(100vh - 260px);
  overflow: auto;
}
.voucher-table-compact thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  /* Nền phải đục, không thì các dòng chạy xuyên qua chữ tiêu đề. */
  background: var(--surface-3);
  box-shadow: 0 1px 0 var(--line);
}

/* Vạch bên trái cho dòng có cảnh báo, có lý do bị bỏ, hoặc Pancake cần kiểm
   tra. Giấu cột chẩn đoán thì được, giấu việc phải làm thì không. */
.voucher-table-compact tbody tr.is-flagged > td:first-child {
  box-shadow: inset 3px 0 0 var(--warning);
}

/* Kỷ luật bề ngang: mã dài thì cắt bằng dấu ba chấm (chuột rê vẫn xem được đủ),
   tiền luôn một dòng và chữ số thẳng cột. */
.voucher-table-compact { table-layout: auto; }
.voucher-table-compact .col-code { max-width: 132px; }
.voucher-table-compact .col-code .truncate-text {
  display: block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.voucher-table-compact .col-money {
  white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums;
}
.voucher-table-compact td[data-label="Đơn/fulfillment liên kết"] { white-space: nowrap; }
.voucher-table-compact td[data-label="Lý do"],
.voucher-table-compact td[data-label="Cảnh báo"] { max-width: 200px; }

.sapo-wholesale-total-debt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-7);
  padding: var(--space-7) var(--space-9);
}
.sapo-wholesale-total-debt span { color: var(--muted); }
.sapo-wholesale-total-debt strong { color: var(--danger); font-size: 24px; }

.panel-head {
  padding: var(--space-8) var(--space-9);
  border-bottom: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-6);
}
.panel-head h4 {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.015em;
}
.panel-head span {
  color: var(--muted);
  font-size: 12px;
}

.panel-head-compact {
  padding: var(--space-6) var(--space-7);
}

.btn-compact {
  padding: var(--space-4) var(--space-6);
  font-size: 13px;
}

.btn-small {
  min-height: 40px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-sm);
  font-size: 12px;
  line-height: 1.2;
}

.bank-webhook-summary {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.bank-account-table {
  table-layout: auto;
}

.bank-account-holder-cell {
  width: 132px;
  max-width: 132px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bank-balance-cell {
  min-width: 150px;
}

.bank-balance-time {
  display: block;
  margin-top: var(--space-2);
  white-space: nowrap;
}

.bank-account-row-actions {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  white-space: nowrap;
}

.bank-account-row-actions > details,
.bank-account-row-actions > form {
  margin: 0;
  flex: 0 0 auto;
}

.bank-account-detail-grid {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(420px, 1.15fr);
  gap: var(--space-7);
}

.bank-account-detail-card {
  min-width: 0;
}

.bank-account-detail-card-body {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-7);
}

.bank-account-meta {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-3) var(--space-6);
  font-size: 13px;
}

.bank-account-meta span {
  color: var(--muted);
}

.bank-webhook-link input {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}

.bank-account-detail-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

@media (max-width: 1024px) {
  .bank-account-detail-grid { grid-template-columns: 1fr; }
}

.compact-table {
  font-size: 12px;
}

/* Mật độ dòng dùng chung cho MỌI bảng danh sách: 8px dọc / 10px ngang.
   Trước 28/08 cùng một class `.compact-table` cho ra ba mật độ khác nhau tuỳ
   rule của module nào thắng — 8/8 ở Sapo Bank và các trang đối soát, 10/10 ở
   hai trang Tổng quan, 8/10 ở khách buôn — nên cùng một loại bảng mà dòng cao
   48px ở trang này, 59px ở trang kia. Các rule ghi đè đó đã bị gỡ; muốn đổi
   mật độ thì đổi Ở ĐÂY, đừng thêm rule riêng cho từng module. */
.compact-table th,
.compact-table td {
  padding: var(--space-4) var(--space-5);
  vertical-align: top;
}

.compact-table th {
  white-space: nowrap;
}

.cell-nowrap {
  white-space: nowrap;
}

.col-transfer-content {
  min-width: 170px;
  max-width: 170px;
  width: 170px;
}

.truncate-text {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

.truncate-text-2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  white-space: normal;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
  max-height: calc(1.3em * 2);
}

.sapo-bank-wrap {
  overflow: hidden;
}

.pagination-meta,
.pagination-page-label {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.sapo-bank-table-scroll {
  max-height: calc(100vh - 260px);
  overflow: auto;
}

.sapo-bank-table {
  table-layout: auto;
  min-width: 1240px;
}

.sapo-bank-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

.col-reference-code {
  max-width: 84px;
  width: 84px;
}

.col-note-short {
  max-width: 120px;
  width: 120px;
}

.col-handler-short {
  max-width: 84px;
  width: 84px;
}

/* --- Hàng thao tác trong bảng -------------------------------------------
   Mọi nút của một dòng nằm trên MỘT hàng ngang, không xuống dòng. Trước đây
   ô này xếp nút chồng dọc (nút + form có ô nhập + <details>), nên dòng nào có
   quyền thao tác là cao gấp đôi dòng thường — bảng nhấp nhô, mắt phải dò lại
   từng dòng thay vì quét thẳng một cột. */
.row-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  white-space: nowrap;
}
.row-actions > form,
.row-actions-form { margin: 0; }
.row-actions .btn {
  flex: 0 0 auto;
  min-height: 28px;
  padding: 0 var(--space-5);
  font-size: 12px;
}
@media (max-width: 1024px) {
  /* Ở dạng thẻ xếp dọc trên mobile thì ngược lại: nút nên rộng hết thẻ. */
  .row-actions { flex-wrap: wrap; white-space: normal; }
  .row-actions .btn { flex: 1 1 auto; min-height: 38px; }
}

.pagination-controls {
  padding: var(--space-5) var(--space-7) var(--space-7);
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-5);
}

/* --- Phân trang dùng chung ----------------------------------------------
   Thay sáu khối "Trước / Sau" tự viết ở sáu trang. Bản cũ chỉ đi được từng
   bước một, nên với 317 trang thì tới trang 200 phải bấm 199 lần. */
.pager {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.pager-page,
.pager-step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.pager-page:hover,
.pager-step:hover {
  border-color: var(--primary-line);
  background: var(--primary-soft);
  color: var(--primary-strong);
}
.pager-page.is-current {
  border-color: transparent;
  background: var(--primary);
  color: #fff;
}
.pager-page.is-current:hover { background: var(--primary); color: #fff; }
.pager-step { font-size: 16px; line-height: 1; }
.pager-step.is-disabled {
  border-color: var(--line);
  background: var(--surface-2);
  color: #B4BAC6;
  cursor: not-allowed;
}
.pager-gap {
  padding: 0 var(--space-2);
  color: var(--muted);
  font-size: 13px;
}
.pager-meta {
  margin-left: var(--space-4);
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 768px) {
  .pager { width: 100%; justify-content: center; }
  .pager-meta { width: 100%; margin-left: 0; text-align: center; }
}

.pagination-controls .btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Một định nghĩa duy nhất cho pill trạng thái, sáu tông. Mỗi tông = nền nhạt +
   một vòng viền 1px cùng sắc: nền nhạt đơn thuần biến mất khi nằm trên hàng đã
   có nền (hàng khớp thanh toán, hàng chưa trả), vòng viền giữ cho pill vẫn là
   một vật thể tách khỏi hàng. */
.status-pill {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 3px var(--space-5);
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  white-space: nowrap;
  box-shadow: inset 0 0 0 1px rgba(21, 23, 28, 0.06);
}

.status-pill-success {
  background: var(--success-soft);
  color: #0D6234;
  box-shadow: inset 0 0 0 1px var(--success-line);
}

.status-pill-danger {
  background: var(--danger-soft);
  color: var(--danger);
  box-shadow: inset 0 0 0 1px var(--danger-line);
}

.status-pill-missing {
  background: var(--warning-soft);
  color: #8A4A06;
  box-shadow: inset 0 0 0 1px var(--warning-line);
}

.status-pill-default {
  background: var(--surface-3);
  color: var(--text-2);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
th, td {
  padding: var(--space-7) var(--space-8);
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: middle;
}
/* Chữ số cùng bề rộng, nên cột tiền xếp thẳng hàng mà không cần canh phải
   riêng từng bảng. Source Sans 3 mặc định dùng chữ số tỉ lệ — "1.111.111" hẹp
   hơn hẳn "8.888.888", đọc một cột 50 dòng là thấy răng cưa. */
td { font-variant-numeric: tabular-nums; }
/* Tiêu đề cột bỏ `text-transform: uppercase`. Tiếng Việt VIẾT HOA TOÀN BỘ mất
   hết dấu phụ phía trên ("ĐÃ ĐỐI SOÁT" so với "Đã đối soát") nên phải đọc từng
   chữ thay vì nhận dạng cả từ — đúng chỗ tệ nhất, vì tiêu đề cột là thứ mắt
   quét nhanh nhất trên trang. Chữ hoa nhỏ + letter-spacing giữ được sắc thái
   "nhãn" mà không phá mặt chữ. */
th {
  background: var(--surface-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  border-bottom: 1px solid var(--line);
}
tbody tr:last-child td { border-bottom: none; }
/* Hàng sẫm lên khi rê chuột: bảng 15 cột × 100 dòng thì mắt lạc dòng liên
   tục, đây là mỏ neo rẻ nhất. Dùng lớp phủ `inset box-shadow` chứ không đặt
   `background`: nhiều hàng đã có nền mang nghĩa (`.payment-match-row` xanh lá,
   `.sapo-wholesale-unpaid-row` hổ phách, `.is-selected-transaction` xanh) —
   ghi đè background là xoá mất thông tin đó ngay khi rê chuột qua. */
tbody tr:hover > td { box-shadow: inset 0 0 0 9999px rgba(21, 23, 28, 0.022); }

.form-panel {
  padding: 22px;
}
.transfer-qr-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, .85fr);
  gap: var(--space-8);
  align-items: start;
}
.transfer-qr-form-panel { max-width: none; }
.transfer-qr-preview {
  padding: 24px;
  text-align: center;
}
.transfer-qr-preview img {
  display: block;
  width: min(100%, 360px);
  aspect-ratio: 1;
  object-fit: contain;
  margin: 0 auto var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: #fff;
}
.transfer-qr-summary {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}
.transfer-qr-summary span { overflow-wrap: anywhere; }
.narrow-form {
  max-width: 720px;
}
.form-grid {
  display: grid;
  gap: var(--space-8);
}

.compact-form-grid {
  gap: var(--space-5);
}
.form-grid.two-col {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.form-section {
  display: grid;
  gap: var(--space-7);
  padding: var(--space-9);
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
}
.form-section h4 {
  margin: 0;
  font-size: 16px;
}
label {
  display: grid;
  gap: var(--space-4);
  font-weight: 600;
  font-size: 14px;
}
/* `label { display:grid }` overrides the browser's default [hidden] rule. */
.wallet-operation-form [hidden] {
  display: none !important;
}
input, select, textarea {
  width: 100%;
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text);
  font-size: 14px;
}
input:hover, select:hover, textarea:hover { border-color: #C6CBD5; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-tint);
}
input::placeholder, textarea::placeholder { color: #9AA1AE; }
/* Mũi tên riêng cho <select> — mũi tên mặc định của từng trình duyệt một kiểu,
   nên ô lọc trên Chrome và Firefox không cao bằng nhau. */
select {
  appearance: none;
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23737B8A' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
}
.alert {
  background: #FBE3E1;
  color: var(--danger);
  border: 1px solid rgba(185,28,28,.1);
  border-radius: var(--radius-md);
  padding: var(--space-6) var(--space-7);
  font-size: 14px;
}
.alert-success {
  background: #E1F5E8;
  color: #0D6234;
}
.alert-info {
  background: #EEF1FE;
  color: #2846D6;
  border: 1px solid rgba(29, 78, 216, 0.16);
}
.global-telegram-link-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
}
.global-telegram-link-banner strong {
  display: block;
  margin-bottom: var(--space-2);
}
.banner-subtext {
  color: #1E36AB;
}

.standalone-page {
  min-height: 100vh;
}
.standalone-card-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-11);
}
.standalone-card {
  width: min(560px, 100%);
}
.inline-form {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.inline-form input {
  min-width: 130px;
}
.inline-danger-form {
  margin: 0;
}
.ticket-form-body {
  padding: var(--space-9);
}
.ticket-form-panel {
  max-width: 920px;
}
.required-mark {
  color: var(--danger);
}
.ticket-checkbox-group {
  margin: 0;
  padding: var(--space-7) var(--space-8);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  display: grid;
  gap: var(--space-6);
}
.ticket-checkbox-group legend {
  padding: 0 var(--space-2);
  font-size: 14px;
  font-weight: 600;
}
.ticket-checkbox-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5) var(--space-7);
}
.ticket-checkbox-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  font-weight: 500;
}
.ticket-checkbox-item input {
  width: auto;
  margin-top: var(--space-1);
}
.ticket-meta-list {
  display: grid;
  gap: var(--space-3);
}
.ticket-meta-list a {
  color: var(--primary);
  text-decoration: underline;
}
.ticket-done-label {
  display: inline-flex;
  align-items: center;
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-pill);
  background: #E1F5E8;
  color: #0D6234;
  font-size: 12px;
  font-weight: 700;
}
.cell-note {
  margin-top: var(--space-3);
  color: var(--muted);
  font-size: 12px;
}
.empty-state {
  padding: var(--space-11);
}
.empty-state h3 {
  margin: 0 0 var(--space-3);
  font-size: 18px;
}
.empty-state p {
  margin: 0;
  color: var(--muted);
}

.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-11);
}
.simple-login-card {
  width: 100%;
  max-width: 420px;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-soft);
  padding: 28px;
  display: grid;
  gap: var(--space-9);
}
.simple-login-head h1 {
  margin: 0 0 var(--space-4);
  font-size: 28px;
  letter-spacing: -0.04em;
}
.simple-login-head p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}
.auth-actions {
  display: grid;
  gap: var(--space-6);
}
.full-width { width: 100%; }

@media (max-width: 1024px) {
  .app-shell { display: block; }
  .sidebar {
    position: fixed;
    z-index: 1001;
    inset: 0 auto 0 0;
    width: min(86vw, 320px);
    /* `inset` đã quyết định chiều cao; bỏ `height: 100vh` của bản desktop để
       trên di động không bị hụt phần thanh địa chỉ của trình duyệt. */
    height: auto;
    min-height: 0;
    padding: var(--space-10) var(--space-8);
    overflow-y: auto;
    transform: translateX(-102%);
    transition: transform 0.2s ease;
    box-shadow: 16px 0 40px rgba(15,23,42,0.24);
  }
  body.sidebar-open { overflow: hidden; }
  body.sidebar-open .sidebar { transform: translateX(0); }
  .sidebar-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: var(--radius-sm);
    background: rgba(255,255,255,0.05);
    color: #fff;
    font-size: 24px;
    cursor: pointer;
  }
  .mobile-menu-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    min-width: 44px;
    min-height: 44px;
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    padding: var(--space-5) var(--space-6);
    background: #fff;
    color: var(--text);
    font-weight: 600;
    box-shadow: 0 3px 10px rgba(15,23,42,0.06);
    cursor: pointer;
  }
  .sidebar-overlay {
    position: fixed;
    z-index: 1000;
    inset: 0;
    border: 0;
    background: rgba(15,23,42,0.48);
    cursor: pointer;
  }
  body.sidebar-open .sidebar-overlay { display: block; }
}
@media (max-width: 768px) {
  html { font-size: 15px; }
  .page-body {
    padding: var(--space-8);
  }
  .topbar {
    position: sticky;
    z-index: 800;
    top: 0;
    height: auto;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-5) var(--space-6);
    padding: var(--space-6) var(--space-8);
    box-shadow: 0 4px 14px rgba(15,23,42,0.04);
  }
  .topbar-title {
    font-size: 18px;
    min-width: 0;
  }
  .top-actions {
    grid-column: 1 / -1;
    width: 100%;
    align-items: stretch;
    flex-direction: column;
    gap: var(--space-5);
  }
  .top-actions form,
  .top-actions .btn {
    width: 100%;
  }
  .user-pill {
    width: 100%;
    padding: var(--space-5) var(--space-6);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: #fff;
  }
  .page-header {
    flex-direction: column;
  }
  .page-header h1 {
    font-size: 24px;
  }
  .panel-head {
    align-items: flex-start;
    flex-direction: column;
  }
  .card-grid,
  .profile-grid,
  .form-grid.two-col,
  .transfer-qr-layout,
  .ticket-checkbox-list {
    grid-template-columns: 1fr;
  }
  .dashboard-link-actions {
    flex-direction: column;
  }
  .dashboard-link-actions .btn {
    width: 100%;
  }
  .form-panel,
  .card,
  .form-section {
    padding: var(--space-8);
  }
  .button-row {
    display: grid;
    grid-template-columns: 1fr;
  }
  /* Ở mobile dải tab TỰ CUỘN NGANG trong chính nó, không chia đều các cột.
     Bản chia đều ép mỗi tab về 1fr, mà tab "Hoàn thành 14450" cần 135px trong
     khi ô chỉ được 102px — huy hiệu số không co được nên nó đẩy cả lưới rộng
     hơn màn hình, làm TRANG bị cuộn ngang 15px. Cuộn trong dải tab thì vẫn đọc
     đủ nhãn lẫn con số, và cuộn nằm gọn trong dải chứ không lan ra cả trang. */
  .page-tabs {
    display: flex;
    width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .page-tabs::-webkit-scrollbar { display: none; }
  .page-tab {
    flex: 0 0 auto;
    min-height: 36px;
    padding: 0 var(--space-6);
  }
  .page-tabs-hint {
    margin-top: -4px;
    margin-bottom: var(--space-1);
  }
  .button-row .btn,
  .button-row a.btn,
  .inline-form .btn {
    width: 100%;
  }
  .inline-form {
    flex-direction: column;
    align-items: stretch;
  }
  .inline-form input {
    min-width: 0;
  }
  .global-telegram-link-banner {
    flex-direction: column;
    align-items: stretch;
  }
  .global-telegram-link-banner .btn {
    width: 100%;
  }
  .responsive-table thead {
    display: none;
  }
  /* Ở khổ này bảng chuyển sang dạng thẻ và tiêu đề bị ẩn, nên khung cuộn có
     trần chiều cao chỉ tạo thêm một thanh cuộn lồng vô ích. Trả về cuộn trang. */
  .voucher-rows-scroll {
    max-height: none;
    overflow: visible;
  }
  .responsive-table,
  .responsive-table tbody,
  .responsive-table tr,
  .responsive-table td {
    display: block;
    width: 100%;
  }
  .responsive-table tr[hidden] {
    display: none !important;
  }
  .responsive-table tbody {
    display: grid;
    gap: var(--space-6);
    padding: var(--space-6);
  }
  .responsive-table tr {
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: #fff;
    overflow: hidden;
  }
  .responsive-table td {
    padding: var(--space-6) var(--space-7);
    border-bottom: 1px solid var(--line);
  }
  .responsive-table td:last-child {
    border-bottom: none;
  }
  .responsive-table td::before {
    content: attr(data-label);
    display: block;
    margin-bottom: var(--space-3);
    color: var(--muted);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
  }
  .responsive-table td[data-label=""]::before {
    display: none;
  }
  .responsive-table td form {
    margin: 0;
  }
  .simple-login-card {
    padding: 22px var(--space-9);
    border-radius: var(--radius-lg);
  }
  .simple-login-head h1 {
    font-size: 24px;
  }
}

/* Wholesale transaction management: isolated financial-dashboard treatment. */
.wholesale-transaction-panel {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
}
.wholesale-transaction-panel-head { min-height: 0; padding: var(--space-8) var(--space-9) var(--space-6); border-bottom: 1px solid var(--line); }
.wholesale-transaction-panel-head h4 { margin: var(--space-1) 0 var(--space-2); font-size: 17px; }
.wholesale-transaction-panel-head > div > span:last-child { color: var(--muted); font-size: 12px; }
.wholesale-transaction-eyebrow { color: var(--primary); font-size: 12px; font-weight: 800; letter-spacing: .06em; }
/* Tab "Nạp tiền / Rút tiền" từng là hai thẻ full-width có gradient và bóng
   riêng — kiểu thứ ba cho cùng khái niệm "tab" trong app. Nay dùng chung điều
   khiển phân đoạn `.page-tabs`, đặt trong dải `.panel-strip` để căn lề với
   panel bao ngoài. */
.wholesale-transaction-tab-card { padding: 0 var(--space-8); }
/* Dải ngang bên trong panel: chứa tab hoặc thanh công cụ, ăn hết chiều ngang
   panel và tự căn lề bằng padding của panel. */
.panel-strip { padding: var(--space-6) var(--space-9); border-bottom: 1px solid var(--line); background: var(--surface-2); }
.wholesale-transaction-focus-banner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-7); padding: var(--space-5) var(--space-9); border-bottom: 1px solid #C6CFFA; background: #EEF1FE; color: #1E36AB; font-size: 12px; }
.wholesale-transaction-focus-banner strong,
.wholesale-transaction-focus-banner span { display: block; }
.wholesale-transaction-focus-banner span { margin-top: var(--space-1); color: #3B5AC4; }
.wholesale-transaction-focus-banner a { flex: 0 0 auto; color: #2846D6; font-weight: 700; white-space: nowrap; }
.wholesale-transaction-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); padding: var(--space-6) var(--space-9); border-bottom: 1px solid var(--line); }
.wholesale-transaction-toolbar h5 { margin: 0 0 var(--space-2); font-size: 14px; }
.wholesale-transaction-toolbar > div > span { color: var(--muted); font-size: 12px; }
/* `.wholesale-transaction-filters` / `-filter-chip` / `-filter-clear` /
   `-bank-filter` đã bị gỡ: đó là bộ chip cam dựng riêng cho trang Khách buôn,
   không trùng với BẤT KỲ bộ lọc nào khác trong app. Nay trang này dùng
   `.filterbar` / `.chipset` / `.chip` / `.field` / `.chip-clear` dùng chung. */
.wholesale-transaction-bulk-bar { display: flex; align-items: center; gap: var(--space-5); padding: var(--space-5) var(--space-9); border-bottom: 1px solid var(--line); background: #F9FAFB; }
.wholesale-transaction-bulk-bar[hidden] { display: none !important; }
.wholesale-transaction-bulk-bar > span { color: #565D6B; font-size: 12px; font-weight: 700; }
.wholesale-transaction-bulk-bar [data-topup-bulk-confirm] { margin-left: auto; }
.wholesale-transaction-col-select { width: 42px; text-align: center; }
.wholesale-transaction-select { text-align: center; }
.wholesale-transaction-select input { width: 17px; height: 17px; cursor: pointer; accent-color: #2846D6; }
.wholesale-transaction-table [data-topup-select-column][hidden] { display: none !important; }
.wholesale-transaction-table tr[hidden] { display: none !important; }
.wholesale-transaction-summary { display: grid; grid-template-columns: auto auto; gap: var(--space-7); flex: 0 0 auto; padding: var(--space-4) var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; }
.wholesale-transaction-summary > div + div { padding-left: var(--space-7); border-left: 1px solid var(--line); }
.wholesale-transaction-summary span { display: block; margin-bottom: var(--space-1); color: var(--muted); font-size: 12px; font-weight: 700; }
.wholesale-transaction-summary strong { display: block; font-size: 15px; line-height: 1.2; white-space: nowrap; }
.wholesale-transaction-summary.is-topup strong:first-of-type { color: #0F7A3D; }
.wholesale-transaction-summary.is-withdrawal strong:first-of-type { color: var(--danger); }
.wholesale-transaction-table-scroll { max-height: calc(100vh - 270px); min-height: 320px; overflow: auto; }
.wholesale-transaction-table { min-width: 1040px; table-layout: fixed; }
.wholesale-transaction-table th { position: sticky; top: 0; z-index: 2; padding: var(--space-4) var(--space-5); background: #F9FAFB; box-shadow: 0 1px 0 var(--line); font-size: 12px; white-space: nowrap; }
.wholesale-transaction-table td { padding: var(--space-4) var(--space-5); font-size: 12px; vertical-align: middle; }
.wholesale-transaction-table tbody tr:hover { background: #F5F7FD; }
.wholesale-transaction-col-time { width: 125px; }
.wholesale-transaction-col-creator { width: 115px; }
.wholesale-transaction-col-info { width: 155px; }
.wholesale-transaction-col-customer { width: 150px; }
.wholesale-transaction-col-son { width: 100px; }
.wholesale-transaction-col-money { width: 115px; text-align: right; }
.wholesale-transaction-col-bank { width: 190px; }
.wholesale-transaction-col-proof { width: 72px; }
.wholesale-transaction-col-status { width: 170px; }
.wholesale-transaction-col-link { width: 145px; }
.wholesale-transaction-time { color: var(--muted); font-size: 12px !important; white-space: nowrap; }
.transaction-mobile-info { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); min-height: 20px; }
.transaction-mobile-info .wholesale-transaction-source-chip { margin-right: 0; }
.transaction-code { display: inline-block !important; margin: 0 !important; color: #15171C; font-size: 13px !important; font-weight: 800; line-height: 1.3; white-space: nowrap; }
.wholesale-transaction-time small { display: block; margin-top: var(--space-2); color: var(--muted); font-size: 12px; }
.wholesale-transaction-creator strong,
.wholesale-transaction-creator span,
.wholesale-transaction-customer strong,
.wholesale-transaction-customer small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wholesale-transaction-creator span,
.wholesale-transaction-customer small { margin-top: var(--space-1); color: var(--muted); font-size: 12px; }
.wholesale-transaction-customer strong { font-size: 13px; }
.wholesale-transaction-compact-info { min-width: 0; }
.wholesale-transaction-compact-info strong,
.wholesale-transaction-compact-info small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wholesale-transaction-compact-info strong { margin-top: var(--space-2); font-size: 12px; }
.wholesale-transaction-compact-info small { margin-top: var(--space-1); color: var(--muted); font-size: 12px; }
.wholesale-transaction-bank { min-width: 0; color: #3B414D; }
.wholesale-transaction-bank > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wholesale-transaction-proof .link-button { padding: 0; border: 0; background: transparent; color: #2846D6; font-size: 12px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.wholesale-proof-dialog { width: min(920px, calc(100vw - 32px)); max-height: min(90vh, 800px); padding: 0; border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: 0 16px 48px rgba(15, 23, 42, .18); }
.wholesale-proof-dialog::backdrop { background: rgba(15, 23, 42, .56); }
.wholesale-proof-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); padding: var(--space-6) var(--space-7); border-bottom: 1px solid var(--line); }
.wholesale-customer-dialog { width: min(460px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: 0 16px 48px rgba(15, 23, 42, .18); }
.wholesale-customer-dialog::backdrop { background: rgba(15, 23, 42, .56); }
.wholesale-customer-dialog .sapo-wholesale-form { display: grid; gap: var(--space-6); padding: var(--space-9); }
.wholesale-customer-dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-6); }
.wholesale-customer-dialog-head p { margin: var(--space-2) 0 0; color: #737B8A; font-size: 13px; }
.wholesale-proof-dialog > img { display: block; max-width: 100%; max-height: calc(90vh - 68px); margin: 0 auto; object-fit: contain; }
.wholesale-transaction-son strong,
.wholesale-transaction-son a { color: #3B414D; font-size: 12px; white-space: nowrap; }
.wholesale-transaction-son a { color: #2846D6; font-weight: 800; text-decoration: none; }
.wholesale-transaction-son a:hover { color: #2846D6; text-decoration: underline; }
.wholesale-transaction-money { text-align: right; font-size: 14px !important; font-weight: 800; white-space: nowrap; }
.wholesale-transaction-money.is-in { color: #0F7A3D; }
.wholesale-transaction-money.is-out { color: var(--danger); }
.wholesale-transaction-status form { margin: 0; }
.wholesale-transaction-status .btn { white-space: normal; }
/* `min-width: 166px` cộng 20px padding của ô là 186px, trong khi cột
   `.wholesale-transaction-col-status` chỉ rộng 170px — nên khối nút luôn thò
   ra khỏi ô 6px và đè sang cột bên cạnh. Bỏ min-width để nó co theo ô; các nút
   bên trong vốn đã `width: 100%`. */
.topup-action-panel { display: grid; gap: var(--space-4); min-width: 0; }
.topup-action-form { display: block; }
.topup-action-panel .btn,
.topup-action-edit { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-3); min-height: 34px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 700; line-height: 1.2; letter-spacing: -.01em; transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease, background .16s ease; }
.topup-action-panel .btn { width: 100%; }
.topup-action-panel .btn:hover,
.topup-action-edit:hover { transform: translateY(-1px); }
.topup-action-primary { color: #fff; border-color: #0D6234; background: linear-gradient(180deg, #189A55 0%, #0F7A3D 100%); box-shadow: 0 1px 2px rgba(22,101,52,.18), inset 0 1px 0 rgba(255,255,255,.18); }
.topup-action-primary:hover { background: linear-gradient(180deg, #189A55 0%, #0D6234 100%); box-shadow: 0 4px 10px rgba(22,101,52,.18), inset 0 1px 0 rgba(255,255,255,.16); }
.topup-action-danger { color: #B02821; border-color: #F5C7C4; background: #FFF8F8; box-shadow: 0 1px 2px rgba(127,29,29,.04); }
.topup-action-danger:hover { border-color: #EDA9A4; background: #FDECEB; }
.topup-action-edit { width: max-content; margin-top: var(--space-4); color: #565D6B; border-color: #D9DEE7; background: linear-gradient(180deg, #fff 0%, #F9FAFB 100%); box-shadow: 0 1px 2px rgba(15,23,42,.05); }
.topup-action-edit:hover { color: #252932; border-color: #BEC5D1; background: #F9FAFB; }
.topup-match-chip { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-3) var(--space-4); border: 1px solid #BFE5CB; border-radius: var(--radius-sm); color: #0D6234; background: #F0FAF3; font-size: 12px; line-height: 1.35; overflow-wrap: anywhere; }
.topup-match-chip > span:first-child { display: inline-grid; place-items: center; flex: 0 0 15px; width: 15px; height: 15px; border-radius: 50%; color: #fff; background: #189A55; font-size: 12px; font-weight: 800; }
.topup-match-select { display: grid; gap: var(--space-3); margin-bottom: var(--space-4); color: #565D6B; font-size: 12px; font-weight: 700; }
.topup-match-select select { min-width: 0; font-size: 12px; }
.wholesale-transaction-status-chip,
.wholesale-transaction-source-chip { display: inline-flex; align-items: center; width: max-content; max-width: 100%; padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill); font-size: 12px; font-weight: 800; line-height: 1.3; white-space: nowrap; }
.wholesale-transaction-status-chip { background: #E4E7EC; color: #3B414D; }
.wholesale-transaction-status-chip.is-success { background: #E1F5E8; color: #0D6234; }
.wholesale-transaction-status-chip.is-pending { background: #FDF3E4; color: #A45B08; }
.wholesale-transaction-status .confirmation-meta { display: block; margin-top: var(--space-2); color: var(--muted); font-size: 12px; line-height: 1.35; }
.wholesale-transaction-source-chip { margin-right: var(--space-3); background: #E2F0FB; color: #0B5A85; vertical-align: middle; }
.wholesale-transaction-source-chip.is-direct { background: #ede9fe; color: #5b21b6; }
.wholesale-transaction-note { min-width: 0; }
.wholesale-transaction-note .truncate-text { max-width: calc(100% - 92px); }
.wholesale-transaction-note a { display: block; margin-top: var(--space-2); font-size: 12px; font-weight: 700; }
.wholesale-transaction-link a { font-size: 12px; font-weight: 700; }

@media (max-width: 768px) {
  .wholesale-transaction-panel-head,
  .panel-strip,
  .wholesale-transaction-toolbar { padding-left: var(--space-6); padding-right: var(--space-6); }
  .wholesale-transaction-tab-card { padding: 0 var(--space-5); }
  .wholesale-transaction-focus-banner { align-items: flex-start; flex-direction: column; padding: var(--space-5) var(--space-6); }
  .wholesale-transaction-focus-banner a { white-space: normal; }
  .wholesale-transaction-toolbar { align-items: stretch; flex-direction: column; gap: var(--space-5); }
  .wholesale-transaction-bulk-bar { align-items: stretch; flex-wrap: wrap; padding: var(--space-5) var(--space-6); }
  .wholesale-transaction-bulk-bar [data-topup-bulk-confirm] { width: 100%; margin-left: 0; }
  .wholesale-transaction-summary { width: 100%; grid-template-columns: minmax(0, 1fr) auto; }
  .wholesale-transaction-table-scroll { max-height: none; min-height: 0; overflow: visible; }
  .wholesale-transaction-table { min-width: 0; table-layout: auto; }
  .wholesale-transaction-table tbody { gap: var(--space-4); padding: var(--space-4); }
  .wholesale-transaction-table td { min-width: 0; padding: var(--space-4) var(--space-5); }
  .wholesale-transaction-table td[data-label="Người tạo"] { display: none; }
  .wholesale-transaction-table .transaction-mobile-info { gap: var(--space-3); }
  .wholesale-transaction-table .transaction-code { font-size: 14px !important; }
  .wholesale-transaction-table .wholesale-transaction-money { font-size: 16px !important; text-align: left; }
  .wholesale-transaction-table .wholesale-transaction-status .btn { width: 100%; }
  .wholesale-transaction-table .wholesale-transaction-note .truncate-text { max-width: 100%; }
}

/* Wholesale customer detail: debt and wallet are grouped by financial meaning. */
.sapo-wholesale-account-overview { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); gap: var(--space-6); margin-bottom: var(--space-7); }
.sapo-wholesale-debt-card, .sapo-wholesale-wallet-card { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-md); padding: var(--space-8) var(--space-9); background: var(--surface); box-shadow: var(--shadow-soft); }
.sapo-wholesale-debt-card { border-left: 4px solid var(--danger); }
.sapo-wholesale-wallet-card { border-left: 4px solid #0F7A3D; }
.sapo-wholesale-overview-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); color: var(--muted); font-size: 12px; font-weight: 700; }
.sapo-wholesale-overview-card-head a { font-size: 12px; font-weight: 800; }
.sapo-wholesale-overview-source { padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill); background: #FBE3E1; color: #9E231E; font-size: 12px; letter-spacing: .02em; }
.sapo-wholesale-debt-value, .sapo-wholesale-wallet-value { display: block; margin: var(--space-4) 0 var(--space-2); font-size: clamp(24px, 3vw, 32px); line-height: 1.1; letter-spacing: -.03em; }
.sapo-wholesale-debt-value { color: var(--danger); }
.sapo-wholesale-wallet-value { color: #0F7A3D; }
.sapo-wholesale-wallet-caption { display: block; color: var(--muted); font-size: 12px; }
.sapo-wholesale-order-stats, .sapo-wholesale-wallet-breakdown { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-5); margin: var(--space-7) 0 0; padding-top: var(--space-6); border-top: 1px solid var(--line); }
.sapo-wholesale-order-stats span { color: var(--muted); font-size: 12px; }
.sapo-wholesale-order-stats strong { color: var(--text); font-size: 18px; }
.sapo-wholesale-wallet-breakdown div { min-width: 0; }
.sapo-wholesale-wallet-breakdown dt { color: var(--muted); font-size: 12px; }
.sapo-wholesale-wallet-breakdown dd { margin: var(--space-2) 0 0; color: var(--text); font-size: 14px; font-weight: 800; white-space: nowrap; }
@media (max-width: 768px) { .sapo-wholesale-account-overview { grid-template-columns: 1fr; gap: var(--space-5); } .sapo-wholesale-debt-card, .sapo-wholesale-wallet-card { padding: var(--space-7); } .sapo-wholesale-debt-value, .sapo-wholesale-wallet-value { font-size: 26px; } }

/* Transaction creation: tappable customer matches shown while typing a phone number. */
.transaction-customer-results { display: grid; gap: var(--space-4); max-height: 280px; overflow-y: auto; }
.transaction-customer-result { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); padding: var(--space-6) var(--space-7); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); color: var(--text); text-align: left; cursor: pointer; }
.transaction-customer-result:hover, .transaction-customer-result:focus-visible { border-color: var(--primary); background: #EEF1FE; outline: none; }
.transaction-customer-result strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.transaction-customer-result span { flex: 0 0 auto; color: var(--muted); font-weight: 700; }
.transaction-customer-result[hidden] { display: none !important; }

/* ==========================================================================
   NỀN CHUNG — bổ sung đợt đồng nhất giao diện (26/07/2026)

   Toàn bộ khối này là THÊM MỚI. Nó chỉ định nghĩa những class đang được dùng
   trong template nhưng chưa từng tồn tại trong CSS — nên chỗ nào đang vỡ sẽ
   lành, chỗ nào đang đúng không đổi.

   Giá trị màu lấy từ docs/ui-ux/DESIGN.md.
   ========================================================================== */

:root {
  /* Ba màu ngữ nghĩa spec đã định nghĩa nhưng chưa bao giờ được khai thành biến,
     nên màu xanh lá đang bị viết cứng ba sắc khác nhau ở ba chỗ khác nhau. */
  --success: #0F7A3D;
  --warning: #A45B08;
  --info: #1E36AB;

  /* neutral-100 của spec. Có trong mockup gốc nhưng bị mất khi port sang đây.
     Spec dùng nó cho cả nền tiêu đề bảng lẫn nút phụ. */
  --surface-soft: #F1F3F6;

  /* Ba chỗ trong template đang viết var(--border) — biến này chưa từng tồn tại,
     khiến khai báo border bị vô hiệu và mất viền hoàn toàn. */
  --border: #E4E7EC;

  /* Nền + viền cho từng màu ngữ nghĩa. Thiếu hai bậc này chính là lý do mỗi
     trang tự pha một sắc nền: pill "Cần kiểm tra" ở Sapo Bank, chip cảnh báo ở
     Khách buôn và banner ở phiếu đối soát từng là ba màu hổ phách khác nhau. */
  --success-soft: #F0FAF3;
  --success-line: #BFE5CB;
  --warning-soft: #FDF3E4;
  --warning-line: #F2D9AE;
  --info-soft: #EEF1FE;
  --info-line: #C6CFFA;
}

/* --- Khung panel ---------------------------------------------------------
   .panel được dùng 13 lần MỘT MÌNH (trang /bank, /admin/bank-accounts, khu
   khách buôn) nhưng chưa từng được định nghĩa, nên các khối đó đổ chữ trần
   lên nền xám, và đường kẻ của .panel-head bên trong thì lơ lửng. */
.panel {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}

/* --- Link quay lại -------------------------------------------------------
   CSS toàn cục đặt a { color: inherit; text-decoration: none }, mà .back-link
   chưa được định nghĩa — nên MỌI link "← Quay lại" trong app trông y hệt chữ
   thường và người dùng không biết là bấm được. */
.back-link,
.wallet-action-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
}
.back-link:hover,
.wallet-action-link:hover {
  text-decoration: underline;
}

/* --- Trạng thái: 5 loại, mỗi loại một màu -------------------------------
   Trước đây có hai tên cho cùng một ý niệm: -missing (14 chỗ, có màu) và
   -warning (15 chỗ, KHÔNG tồn tại nên trong suốt). Giờ cả hai cùng trỏ về
   một định nghĩa; -missing giữ lại để template cũ không phải sửa gấp. */
.status-pill-warning,
.status-pill-missing {
  background: var(--warning-soft);
  color: #8A4A06;
  box-shadow: inset 0 0 0 1px var(--warning-line);
}
.status-pill-info {
  background: var(--info-soft);
  color: var(--info);
  box-shadow: inset 0 0 0 1px var(--info-line);
}

/* --- Thông báo kết quả ---------------------------------------------------
   Ở trang Tổng quan Sapo, .flash-success và .flash-error đều không tồn tại nên
   báo thành công và báo lỗi hiện ra GIỐNG HỆT NHAU. */
.flash {
  padding: var(--space-6) var(--space-7);
  border: 1px solid;
  border-radius: var(--radius-md);
  font-size: 14px;
}
.flash-success {
  border-color: #BFE5CB;
  background: #F0FAF3;
  color: #0B4F2A;
}
.flash-error {
  border-color: #F5C7C4;
  background: #FDECEB;
  color: #9E231E;
}
.alert-error {
  border-color: rgba(185, 28, 28, 0.18);
  background: #FDECEB;
  color: #9E231E;
}

/* --- Chỉ dành cho trình đọc màn hình -------------------------------------
   .sr-only chưa được định nghĩa, nên chữ đáng lẽ chỉ để phần mềm đọc màn hình
   nghe thấy lại đang HIỆN RA giữa giao diện ("Sửa SON", "Chọn"). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Phản hồi khi chọn giao dịch ngân hàng -------------------------------
   Class này được JS gán khi người dùng chọn một giao dịch đối ứng, nhưng chưa
   có định nghĩa — nên thao tác đó không có phản hồi nào, dù nó âm thầm tắt
   yêu cầu đính kèm ảnh chứng từ. */
.transaction-customer-result.is-selected {
  border-color: var(--primary);
  background: #EEF1FE;
  box-shadow: inset 0 0 0 1px rgba(29, 78, 216, 0.35);
}

/* --- Chữ phụ và ô tiền --------------------------------------------------- */
.text-muted,
.muted,
.sapo-muted {
  color: var(--muted);
}
.text-warning {
  color: var(--warning);
  font-weight: 600;
}
.cell-money,
.sapo-wholesale-col-money {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.payment-match-row {
  background: #F0FAF3;
}

/* --- Hàng nút ------------------------------------------------------------
   .page-actions được dùng thay cho .button-row ở hai chỗ nhưng không tồn tại. */
.page-actions {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
}

/* --- .btn-primary ---------------------------------------------------------
   Được dùng 43 lần nhưng chưa từng tồn tại. Vô hại vì luôn đi kèm .btn (vốn đã
   là màu chính), nhưng khai ở đây để tên class không còn là lời hứa suông. */
.btn-primary {
  background: var(--primary);
  color: #fff;
}

/* --- Trạng thái tương tác của nút ---------------------------------------
   .btn trước đây không có :hover lẫn :disabled — bấm không có phản hồi, và nút
   đã bị khoá vẫn trông y hệt nút bấm được. */
.btn {
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.btn:hover {
  background: var(--primary-strong, #1E36AB);
}
.btn-secondary:hover {
  background: var(--surface-soft);
}
.btn-danger:hover {
  background: #9E231E;
}
.btn:disabled,
.btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  box-shadow: none;
}
.btn:disabled:hover,
.btn[disabled]:hover {
  background: var(--primary);
}

/* --- Nút đang chạy -------------------------------------------------------
   Lọc một bảng 15.000 đơn mất vài giây mà màn hình không đổi gì, nên người
   dùng bấm lại lần nữa. Vòng xoay chiếm chỗ của chữ (không đẩy layout) và
   `pointer-events: none` chặn bấm trùng. */
.btn.is-busy {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.btn.is-busy::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border: 2px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  color: #fff;
  animation: btn-spin 0.6s linear infinite;
}
.btn-secondary.is-busy::after,
.btn-ghost.is-busy::after { color: var(--text-2); }
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* Người dùng đã bật "giảm chuyển động" thì đứng yên, chỉ hiện dấu chấm. */
@media (prefers-reduced-motion: reduce) {
  .btn.is-busy::after { animation: none; border-top-color: currentColor; opacity: .5; }
}
/* Bảng mờ đi trong lúc chờ, để thấy rõ dữ liệu đang cũ. */
form[aria-busy="true"] { opacity: .85; }
.btn-secondary:disabled:hover,
.btn-secondary[disabled]:hover {
  background: #fff;
}

/* --- Viền focus khi dùng bàn phím ---------------------------------------
   Trước đây input:focus { outline: none } chỉ đổi màu viền rất nhạt, nên điều
   hướng bằng phím Tab gần như vô hình. Dùng :focus-visible nên người bấm chuột
   không thấy viền, chỉ người dùng bàn phím mới thấy. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  /* KHONG dat border-radius o day. Truoc 27/07 dong nay ep moi phan tu dang
     focus ve cung mot ban kinh, nen bam Tab vao .btn (14px) thi goc giat ve
     6px. Trinh duyet hien dai cho outline tu bam theo border-radius that cua
     chinh phan tu, nen bo di la dung nhat. */
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
  border-color: var(--primary);
}

/* --- Hộp thoại dùng chung ------------------------------------------------
   .zeijp-outgoing-confirm-dialog và .zeijp-id-edit-dialog không được style ở
   đâu cả nên hiện ra với kiểu mặc định của trình duyệt, khác hẳn các dialog
   khác trong app. */
.zeijp-outgoing-confirm-dialog,
.zeijp-id-edit-dialog {
  width: min(460px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
}
.zeijp-outgoing-confirm-dialog::backdrop,
.zeijp-id-edit-dialog::backdrop {
  background: rgba(15, 23, 42, 0.56);
}

/* --- Hàng form tìm kiếm / tải file ---------------------------------------
   Class này được dùng ở cả trang phiếu đối soát Sapo lẫn trang đối soát ZeiJP,
   nhưng trước đây chỉ được định nghĩa trong <style> nội bộ của template Sapo —
   nên form bên ZeiJP mất bố cục hai cột và các ô xếp chồng full-width. */
/* Lưới hai cột cũ (`minmax(0,1fr) auto`) chỉ đúng khi form có đúng hai phần tử.
   Trang Shopee/TikTok có thêm ô "Tên shop" là thành ba phần tử, ô thứ ba rơi
   xuống hàng hai và nút "Tải phiếu lên" bị kéo rộng cả nghìn pixel. Dùng flex
   để form tự xếp được với số ô bất kỳ, mọi đơn vị vận chuyển nhìn như nhau. */
.sapo-reconcile-upload {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: end;
  margin-bottom: var(--space-7);
}
.sapo-reconcile-upload label { margin: 0; flex: 1 1 240px; min-width: 0; }
/* Tên shop luôn ngắn, không cần rộng bằng ô chọn file. */
.sapo-reconcile-upload .field-shop { flex: 0 1 280px; }
.sapo-reconcile-upload > button { flex: 0 0 auto; }
/* Ô chọn tự đối soát: đứng cạnh nút tải, không giãn như ô chọn file. */
.sapo-reconcile-upload .sapo-reconcile-auto-toggle {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3);
  align-self: center; margin-bottom: 2px;
  color: var(--text-2); font-size: .85rem; white-space: nowrap; cursor: pointer;
}
.sapo-reconcile-auto-toggle input { width: 16px; height: 16px; margin: 0; accent-color: var(--primary); }
.sapo-reconcile-upload-hint {
  flex: 1 1 100%;
  margin: calc(var(--space-4) * -1) 0 0;
  color: var(--muted);
  font-size: 12px;
}
@media (max-width: 768px) {
  .sapo-reconcile-upload { flex-direction: column; align-items: stretch; }
  .sapo-reconcile-upload label,
  .sapo-reconcile-upload .field-shop { flex: none; }
}

/* --- Tong tien con phai quyet toan tren danh sach phieu doi soat ---------
   Dat ngay duoi tab dieu huong de ke toan thay so no cua don vi van chuyen
   truoc khi phai mo tung phieu. */
.settlement-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-4) var(--space-9);
  margin-bottom: var(--space-6);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
}
.settlement-banner-item { display: grid; gap: var(--space-2); }
.settlement-banner-label { font-size: 12px; color: var(--muted); }
.settlement-banner-value { font-size: 20px; font-weight: 700; white-space: nowrap; }
.settlement-banner-receive { color: var(--success); }
.settlement-banner-pay { color: var(--danger); }
.settlement-banner-note {
  flex: 1 1 100%;
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}
.settlement-direction {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--danger);
}
/* --- Thanh chuyen trang giua 7 don vi van chuyen -------------------------
   `.page-tabs` mac dinh la luoi 2 cot, the cao 52px — bay don vi thanh bon
   hang, an het mot phan tu man hinh truoc khi thay bang phieu. O day chi la
   dieu huong nen thu ve mot hang pill, dung ngon ngu voi
   `.sapo-reconcile-provider-filter` cua cung module. */
/* Bảy đơn vị vận chuyển không nhét vừa một điều khiển phân đoạn, nên đây là
   hàng chip xuống dòng được — dùng đúng hình dạng `.chip` của thanh bộ lọc,
   vì với người dùng thì "chọn ĐVVC" cũng là một thao tác lọc. */
.sapo-reconcile-carrier-tabs,
.sapo-reconcile-provider-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0 0 var(--space-6);
  padding: 0;
  border: 0;
  background: none;
  width: auto;
}
.sapo-reconcile-carrier-tabs .page-tab,
.sapo-reconcile-provider-filter .page-tab {
  min-height: 30px;
  padding: 0 var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 600;
  box-shadow: none;
}
.sapo-reconcile-carrier-tabs .page-tab:hover,
.sapo-reconcile-provider-filter .page-tab:hover {
  border-color: var(--primary-line);
  background: var(--primary-soft);
  color: var(--primary-strong);
}
.sapo-reconcile-carrier-tabs .page-tab::after,
.sapo-reconcile-provider-filter .page-tab::after { content: none; }
.sapo-reconcile-carrier-tabs .page-tab.active,
.sapo-reconcile-provider-filter .page-tab.active {
  border-color: transparent;
  background: var(--primary);
  color: #fff;
  box-shadow: var(--shadow-xs);
}
@media (max-width: 768px) {
  .sapo-reconcile-carrier-tabs,
  .sapo-reconcile-provider-filter { display: flex; }
  .sapo-reconcile-carrier-tabs .page-tab,
  .sapo-reconcile-provider-filter .page-tab { min-height: 30px; padding: 0 var(--space-5); }
}

/* Ô này giờ có hai dòng — tên chuẩn và tên file gốc — nên việc cắt bớt chuyển
   xuống từng dòng con; cắt ở ô cha thì chỉ dòng đầu được cắt đúng. Cột cũng
   rộng thêm được vì hai cột tên shop và kỳ báo cáo đã nhập vào tên chuẩn. */
.voucher-file-cell { max-width: 340px; }
.voucher-file-cell > .voucher-name,
.voucher-file-cell > .voucher-source-file {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Tên shop là handle của gian hàng, không bao giờ dài — cho phép cắt để cột
   không đẩy bảng tràn ngang khi sàn trả về tên dài bất thường. */
.voucher-shop-cell {
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 768px) {
  /* Bang doi sang the xep doc o mobile nen khong con ly do cat ten file. */
  .voucher-file-cell { max-width: none; white-space: normal; }
  .voucher-file-cell > .voucher-name,
  .voucher-file-cell > .voucher-source-file { white-space: normal; overflow: visible; }
  .voucher-shop-cell { max-width: none; white-space: normal; }
}

/* --- Cot chi hien o tab "Tien vao" --------------------------------------
   Bang giao dich ngan hang an bot cot khi xem tab "Tien ra". Truoc day viec
   an duoc lam bang danh sach :nth-child() dai trong <style> cua tung template,
   con class .outbound-hide gan tren <th> thi khong duoc CSS nao doc — hai co
   che song song, doi thu tu cot mot cai la lech ngay ma khong bao loi.

   Rule nay lam cho class co hieu luc that. Cot moi chi can gan .outbound-hide
   len ca <th> lan <td> la du. */
.outbound-view .outbound-hide { display: none; }

/* Inline styles moved from app/templates/modules/sapo_reconcile/dashboard.html — dot6. */
  .sapo-reconcile-tabs { margin-bottom: var(--space-7); }
  .sapo-reconcile-tab-count { min-width: 22px; padding: 1px var(--space-4); border-radius: var(--radius-pill); text-align: center; background: var(--surface-3); color: var(--muted); font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
  .sapo-reconcile-tabs .page-tab.active .sapo-reconcile-tab-count { color: var(--primary); background: var(--primary-soft); }
  .sapo-reconcile-table { font-size: 12px; }
  .sapo-reconcile-table .col-note { min-width: 120px; max-width: 170px; }
  .sapo-reconcile-table .col-provider { min-width: 110px; max-width: 150px; }
  .sapo-reconcile-table .col-code { min-width: 104px; max-width: 130px; }
  .sapo-reconcile-table .col-money { white-space: nowrap; }
  .sapo-reconcile-provider-filter { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: 0 0 var(--space-6); }
  .sapo-reconcile-provider-filter .page-tab { min-height: 32px; padding: var(--space-3) var(--space-5); font-size: 12px; }
  .sapo-reconcile-provider-filter .page-tab::after { content: none; }
  .sapo-reconcile-module-nav { margin-bottom: var(--space-8); }
  @media (max-width: 768px) {
    .sapo-reconcile-tabs { grid-template-columns: 1fr; }
    .sapo-reconcile-table { font-size: 12px; }
  }


/* Inline styles moved from app/templates/modules/sapo_reconcile/voucher_detail.html — dot6. */
  .voucher-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); margin-bottom: var(--space-7); }
  .voucher-summary div { padding: var(--space-5) var(--space-6); border: 1px solid var(--border); border-radius: var(--radius-sm); }
  .voucher-summary dt { color: var(--muted); font-size: 12px; }
  .voucher-summary dd { margin: var(--space-2) 0 0; font-weight: 700; }
  .voucher-summary-compact { grid-template-columns: repeat(5, minmax(120px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-5); }
  .voucher-summary-compact div { padding: var(--space-3) var(--space-5); }
  .voucher-summary-compact dd { margin-top: var(--space-1); font-size: 14px; line-height: 1.25; }
  .voucher-financial-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-5); margin-bottom: var(--space-7); }
  .voucher-financial-summary div { padding: var(--space-7) var(--space-8); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
  .voucher-financial-summary dt { color: var(--muted); font-size: 12px; }
  .voucher-financial-summary dd { margin: var(--space-3) 0 0; font-size: 20px; font-weight: 800; text-align: right; }
  .voucher-financial-summary-compact { grid-template-columns: repeat(5, minmax(135px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-5); }
  .voucher-financial-summary-compact div { padding: var(--space-4) var(--space-5); }
  .voucher-financial-summary-compact dd { margin-top: var(--space-1); font-size: 16px; line-height: 1.25; }
  .voucher-table { font-size: 12px; }
  .voucher-table th, .voucher-table td { padding: var(--space-4) var(--space-4); }
  .voucher-table .col-code { min-width: 108px; max-width: 140px; }
  .voucher-table .col-name { min-width: 130px; max-width: 180px; }
  .voucher-table .col-money { white-space: nowrap; text-align: right; }
  .voucher-table .money-negative, .voucher-financial-summary .money-negative { color: var(--success); font-weight: 700; }
  @media (max-width: 1024px) { .voucher-summary-compact, .voucher-financial-summary-compact { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 768px) { .voucher-summary, .voucher-financial-summary { grid-template-columns: 1fr; } }

  .voucher-platform-tabs { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-5); }
  .voucher-platform-tabs .btn { gap: var(--space-2); }
  .voucher-platform-tabs .is-active { border-color: var(--primary); color: var(--primary); background: #EEF1FE; }
  .voucher-resolution-kpis { margin-bottom: var(--space-5); }
  .voucher-table tr[hidden] { display: none !important; }
  .voucher-workspace { overflow: hidden; padding: 0; margin-bottom: var(--space-5); border-color: #D6DEF3; box-shadow: 0 8px 24px rgba(15, 23, 42, .045); }
  .voucher-overview-strip { display: grid; grid-template-columns: minmax(300px, .82fr) minmax(560px, 1.45fr); background: linear-gradient(135deg, #F5F7FD 0%, #EEF1FE 100%); border-bottom: 1px solid #D6DEF3; }
  .voucher-overview-meta, .voucher-overview-money { display: flex; align-items: stretch; min-width: 0; margin: 0; padding: var(--space-5) var(--space-6); }
  .voucher-overview-meta { background: rgba(255, 255, 255, .58); }
  .voucher-overview-meta div, .voucher-overview-money div { flex: 1 1 0; min-width: 0; padding: 0 var(--space-5); }
  .voucher-overview-meta div:first-child, .voucher-overview-money div:first-child { padding-left: 0; }
  .voucher-overview-meta div:last-child, .voucher-overview-money div:last-child { padding-right: 0; }
  .voucher-overview-meta div + div, .voucher-overview-money div + div { border-left: 1px solid rgba(148, 163, 184, .26); }
  .voucher-overview-meta dt, .voucher-overview-money dt { color: #737B8A; font-size: 12px; font-weight: 600; line-height: 1.2; }
  .voucher-overview-meta dd, .voucher-overview-money dd { margin: var(--space-2) 0 0; overflow: hidden; color: #252932; font-size: 14px; font-weight: 700; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
  .voucher-overview-money dd { color: #1E36AB; text-align: right; }
  .voucher-inline-note { margin: 0; padding: var(--space-3) var(--space-6); border-bottom: 1px solid var(--line); background: #fff; color: var(--muted); font-size: 12px; line-height: 1.35; }
  .voucher-inline-action { display: inline-block; margin: var(--space-4) 0 0 var(--space-6); }
  .voucher-inline-action .btn, .voucher-tool .btn { min-height: 32px; padding: var(--space-3) var(--space-5); font-size: 12px; }
  .voucher-receipt-quick-action { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); margin: var(--space-4) var(--space-6) 0; padding: var(--space-4) var(--space-5); border: 1px solid #C6CFFA; border-radius: var(--radius-sm); background: #EEF1FE; }
  .voucher-receipt-quick-action > div { min-width: 0; }
  .voucher-receipt-quick-action strong { display: block; color: #1E36AB; font-size: 14px; font-weight: 700; line-height: 1.25; }
  .voucher-receipt-quick-action span { display: block; margin-top: var(--space-1); color: #737B8A; font-size: 12px; line-height: 1.3; }
  .voucher-receipt-quick-action .btn { flex: 0 0 auto; min-height: 40px; padding: var(--space-4) var(--space-7); box-shadow: 0 4px 10px rgba(29, 78, 216, .18); font-size: 13px; font-weight: 600; }
  .voucher-receipt-dialog { position: relative; width: min(520px, calc(100vw - 24px)); max-height: min(88vh, 700px); padding: 0; overflow: hidden; border: 0; border-radius: 22px; background: rgba(255, 255, 255, .98); box-shadow: 0 32px 90px rgba(15, 23, 42, .28), 0 8px 28px rgba(15, 23, 42, .12); opacity: 0; transform: translateY(10px) scale(.985); transition: opacity .16s ease, transform .16s ease; }
  .voucher-receipt-dialog[open] { opacity: 1; transform: translateY(0) scale(1); }
  .voucher-receipt-dialog::before { content: ''; position: absolute; inset: 0 0 auto; z-index: 2; height: 3px; background: linear-gradient(90deg, #2846D6, #7C8DF5); }
  .voucher-receipt-dialog::after { content: ''; position: absolute; inset: 0; z-index: -1; border: 1px solid rgba(148, 163, 184, .28); border-radius: inherit; pointer-events: none; }
  .voucher-receipt-dialog::backdrop { background: rgba(15, 23, 42, .48); backdrop-filter: blur(5px); }
  .voucher-receipt-dialog [hidden] { display: none !important; }
  .voucher-receipt-dialog-shell { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; max-height: min(88vh, 700px); }
  .voucher-receipt-dialog-head { position: relative; padding: 26px 62px 18px 28px; border-bottom: 1px solid rgba(226, 232, 240, .78); background: linear-gradient(180deg, #fff 0%, #FCFCFD 100%); }
  .voucher-receipt-dialog-head h2 { margin: 0; color: #15171C; font-size: 22px; font-weight: 600; line-height: 1.2; letter-spacing: -.02em; }
  .voucher-receipt-dialog-meta { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; margin: var(--space-3) 0 0; color: #767E8C; font-size: 13px; line-height: 1.35; }
  .voucher-receipt-dialog-amount { color: #2846D6; font-size: 14px; font-weight: 700; line-height: inherit; }
  .voucher-receipt-dialog-close { position: absolute; top: 20px; right: 20px; display: grid; width: 38px; height: 38px; padding: 0; place-items: center; border: 0; border-radius: 12px; background: transparent; color: #98A0AE; font-size: 22px; line-height: 1; cursor: pointer; transition: background .15s ease, color .15s ease, transform .15s ease; }
  .voucher-receipt-dialog-close:hover { background: #F1F3F6; color: #3B414D; transform: scale(1.03); }
  .voucher-receipt-dialog-scroll { min-height: 0; padding: 22px 28px 24px; overflow-y: auto; background: #fff; }
  .voucher-receipt-methods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px; margin-bottom: 22px; padding: 3px; border: 1px solid #E4E7EC; border-radius: 13px; background: #F1F3F6; }
  .voucher-receipt-method { display: grid; min-width: 0; min-height: 38px; padding: 7px 14px; place-items: center; border: 0; border-radius: 9px; background: transparent; color: #767E8C; cursor: pointer; transition: background .15s ease, box-shadow .15s ease, color .15s ease; }
  .voucher-receipt-method:hover { color: #3B414D; }
  .voucher-receipt-method.is-active { background: #fff; color: #2846D6; box-shadow: 0 1px 3px rgba(15, 23, 42, .1), 0 4px 12px rgba(15, 23, 42, .04); }
  .voucher-receipt-method-label { font-size: 13px; font-weight: 600; }
  .voucher-receipt-form { display: grid; gap: 16px; }
  .voucher-receipt-primary-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  [data-receipt-cash-fields] .voucher-receipt-primary-fields { grid-template-columns: 1fr; }
  .voucher-receipt-form .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .voucher-receipt-form label { min-width: 0; color: #565D6B; font-size: 12px; font-weight: 600; }
  .voucher-receipt-form input, .voucher-receipt-form select { width: 100%; min-height: 42px; margin-top: 6px; border-color: #D9DEE7; border-radius: 11px; background-color: #F9FAFB; color: #252932; transition: border-color .15s ease, background .15s ease, box-shadow .15s ease; }
  .voucher-receipt-form input:hover, .voucher-receipt-form select:hover { border-color: #BEC5D1; background-color: #fff; }
  .voucher-receipt-form input:focus, .voucher-receipt-form select:focus { border-color: #8E9DF2; background-color: #fff; box-shadow: 0 0 0 3px var(--primary-tint); outline: none; }
  .voucher-receipt-amount-control { position: relative; display: block; }
  .voucher-receipt-amount-control input { padding-right: 38px; font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }
  .voucher-receipt-amount-control > span { position: absolute; right: 14px; bottom: 11px; color: #98A0AE; font-size: 13px; font-weight: 600; pointer-events: none; }
  .voucher-receipt-field-wide { grid-column: 1 / -1; }
  .voucher-receipt-bank-evidence { padding: 12px 14px; border: 1px solid #DDE3FC; border-radius: 12px; background: #F5F7FD; }
  .voucher-receipt-bank-empty { margin: 0; padding: 10px 12px; border-radius: 10px; background: #F9FAFB; color: #737B8A; font-size: 12px; line-height: 1.4; }
  .voucher-receipt-more { border-top: 1px solid #EFF1F5; }
  .voucher-receipt-more > summary { padding: 12px 2px 0; color: #737B8A; font-size: 12px; font-weight: 600; cursor: pointer; list-style: none; }
  .voucher-receipt-more > summary::-webkit-details-marker { display: none; }
  .voucher-receipt-more > summary::after { content: '＋'; float: right; color: #98A0AE; }
  .voucher-receipt-more[open] > summary::after { content: '−'; }
  .voucher-receipt-more .form-grid { margin-top: 14px; }
  .voucher-receipt-form-feedback { padding: 11px 13px; border: 0; border-radius: 11px; background: #EEF1FE; color: #3B5AC4; font-size: 12px; line-height: 1.45; }
  .voucher-receipt-form-feedback.is-error { background: #FDECEB; color: var(--danger); }
  .voucher-receipt-acknowledgement { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px; align-items: center; padding: 2px; color: #737B8A; font-size: 12px !important; font-weight: 500 !important; line-height: 1.4; cursor: pointer; }
  .voucher-receipt-acknowledgement input { width: 16px; height: 16px; margin: 0; accent-color: var(--primary); }
  .voucher-receipt-dialog-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 16px 28px 20px; border-top: 1px solid rgba(226, 232, 240, .78); background: #FCFCFD; }
  .voucher-receipt-dialog-actions > span { margin-right: auto; color: #98A0AE; font-size: 12px; line-height: 1.35; }
  .voucher-receipt-dialog-actions > div { display: flex; flex: 0 0 auto; gap: 10px; }
  .voucher-receipt-dialog-actions .btn { min-width: 84px; min-height: 40px; border-radius: 11px; }
  .voucher-receipt-dialog-actions .btn-primary { min-width: 176px; box-shadow: 0 6px 16px rgba(29, 78, 216, .18); }
  .voucher-receipt-dialog-actions .btn:disabled { cursor: not-allowed; box-shadow: none; opacity: .5; }
  /* Hai nút ghi dữ liệu là một cụm nút gọn tự co theo nhãn; câu giải thích nằm
     trong tooltip của nút nên không còn hai ô viền to choán nửa khung. */
  .voucher-action-stack { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-4); }
  .voucher-action-stack form { flex: 0 0 auto; margin: 0; }
  .voucher-action-stack form .btn { width: auto; white-space: nowrap; }
  .voucher-compact-tools { display: flex; align-items: stretch; margin: var(--space-4) var(--space-6); overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; }
  .voucher-tool { flex: 1 1 0; min-width: 0; background: var(--surface); }
  .voucher-compact-tools > .voucher-tool + .voucher-tool { border-left: 1px solid var(--line); }
  .voucher-tool > summary { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-2) var(--space-4); min-height: 54px; padding: var(--space-4) var(--space-5); cursor: pointer; list-style: none; transition: background .15s ease; }
  .voucher-tool > summary:hover { background: #F5F7FD; }
  .voucher-tool > summary::-webkit-details-marker { display: none; }
  .voucher-tool > summary::after { content: '⌄'; grid-row: 1 / span 2; grid-column: 2; color: #737B8A; font-size: 16px; line-height: 1; transition: transform .15s ease; }
  .voucher-tool[open] > summary { background: #F5F7FD; }
  .voucher-tool[open] > summary::after { transform: rotate(180deg); }
  .voucher-tool > summary span { min-width: 0; color: #252932; font-size: 13px; font-weight: 700; }
  .voucher-tool > summary small { grid-column: 1; overflow: hidden; color: #737B8A; font-size: 12px; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
  .voucher-tool-body { padding: var(--space-5); border-top: 1px solid var(--line); background: #F9FAFB; font-size: 12px; }
  .voucher-tool-body > p { margin: 0 0 var(--space-4); }
  /* Đối soát một phần phiếu là hợp lệ nhưng phải nhìn thấy được: người bấm cần
     biết mình đang bỏ lại bao nhiêu dòng trước khi xác nhận phát hành. */
  .voucher-partial-note { margin: 0 0 var(--space-4); padding: var(--space-4); border: 1px solid #F2D9AE; border-left: 3px solid #b5762a; border-radius: var(--radius-sm); background: #FEF9EE; color: #7a4f12; }
  .voucher-tool-kpis { display: flex; margin: 0 0 var(--space-4); overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; }
  .voucher-tool-kpis div { flex: 1 1 0; min-width: 0; padding: var(--space-4); }
  .voucher-tool-kpis div + div { border-left: 1px solid var(--line); }
  .voucher-tool-kpis dt { color: var(--muted); font-size: 10px; }
  .voucher-tool-kpis dd { margin: var(--space-1) 0 0; font-size: 13px; font-weight: 700; }
  .voucher-tool-heading { margin: var(--space-5) 0 var(--space-3); font-size: 13px; }
  .voucher-tool .data-table { font-size: 12px; }
  .voucher-tool .data-table th, .voucher-tool .data-table td { padding: var(--space-3) var(--space-4); }
  .voucher-workspace .voucher-resolution-summary { padding: var(--space-5) var(--space-6); border-top: 1px solid var(--line); background: #fff; }
  .voucher-platform-action-panel { margin: 0 var(--space-6) var(--space-5); overflow: hidden; border: 1px solid #C6CFFA; border-radius: var(--radius-sm); background: #fff; }
  .voucher-platform-action-panel[hidden] { display: none !important; }
  .voucher-platform-action-panel .voucher-tool { width: 100%; }
  .voucher-workspace .voucher-platform-tabs { margin-bottom: var(--space-4); }
  .voucher-workspace .voucher-platform-tabs .btn { min-height: 32px; padding: var(--space-3) var(--space-5); font-size: 12px; border-radius: var(--radius-pill); }
  .voucher-workspace .voucher-resolution-kpis { display: flex; gap: 0; margin-bottom: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-sm); background: #F9FAFB; }
  .voucher-workspace .voucher-resolution-kpis div { flex: 1 1 0; padding: var(--space-4) var(--space-5); border: 0; border-radius: 0; }
  .voucher-workspace .voucher-resolution-kpis div + div { border-left: 1px solid var(--line); }
  .voucher-workspace .voucher-resolution-kpis dd { font-size: 14px; }
  .voucher-workspace .voucher-status-kpis { margin-bottom: var(--space-4); }
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-success { background: #F0FAF3; }
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-success dt,
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-success dd { color: #0D6234; }
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-pending { background: #FEF6EC; }
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-pending dt,
  .voucher-workspace .voucher-status-kpis .voucher-status-kpi-pending dd { color: #A04212; }
  @media (max-width: 1200px) { .voucher-overview-strip { grid-template-columns: 1fr; } .voucher-compact-tools { display: grid; grid-template-columns: 1fr; } .voucher-compact-tools > .voucher-tool + .voucher-tool { border-left: 0; border-top: 1px solid var(--line); } }
  @media (max-width: 768px) { .voucher-overview-meta, .voucher-overview-money, .voucher-tool-kpis, .voucher-workspace .voucher-resolution-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } .voucher-overview-meta div, .voucher-overview-money div { padding: var(--space-3); } .voucher-overview-meta div + div, .voucher-overview-money div + div, .voucher-tool-kpis div + div, .voucher-workspace .voucher-resolution-kpis div + div { border-left: 0; } .voucher-receipt-quick-action { align-items: stretch; flex-direction: column; } .voucher-receipt-quick-action .btn { width: 100%; } .voucher-receipt-dialog-head { padding: 22px 56px 16px 20px; } .voucher-receipt-dialog-head h2 { font-size: 20px; } .voucher-receipt-dialog-amount { font-size: 14px; } .voucher-receipt-dialog-scroll { padding: 18px 20px 22px; } .voucher-receipt-primary-fields, .voucher-receipt-form .form-grid { grid-template-columns: 1fr; } .voucher-receipt-methods { grid-template-columns: repeat(2, minmax(0, 1fr)); } .voucher-receipt-field-wide { grid-column: auto; } .voucher-receipt-dialog-actions { align-items: stretch; flex-direction: column; padding: 14px 20px 18px; } .voucher-receipt-dialog-actions > span { display: none; } .voucher-receipt-dialog-actions > div { display: grid; grid-template-columns: .72fr 1.28fr; } .voucher-receipt-dialog-actions .btn { width: 100%; min-width: 0; } }


/* Inline styles moved from app/templates/modules/sapo_reconcile/generic_voucher_list.html — dot6. */
  .reconciliation-voucher-nav { margin-bottom: var(--space-8); }


/* Inline styles moved from app/templates/modules/zeijp_reconcile/dashboard.html — dot6. */
  .zeijp-reconcile-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); margin-bottom: var(--space-7); }
  .zeijp-reconcile-card { padding: var(--space-6) var(--space-7); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
  .zeijp-reconcile-card span { display: block; color: var(--muted); font-size: 12px; }
  .zeijp-reconcile-card strong { display: block; margin-top: var(--space-2); font-size: 18px; }
  .zeijp-reconcile-table { font-size: 12px; }
  .zeijp-reconcile-table .col-money { white-space: nowrap; text-align: right; }
  @media (max-width: 768px) { .zeijp-reconcile-summary { grid-template-columns: 1fr 1fr; } }


/* Inline styles moved from app/templates/modules/pancake_bank/sale_queue.html — dot6. */
  .pancake-sale-page { display: grid; gap: var(--space-9); }
  .pancake-sale-hero { display: flex; align-items: center; justify-content: space-between; gap: var(--space-9); }
  .pancake-sale-count { min-width: 150px; padding: var(--space-7) var(--space-9); text-align: right; }
  .pancake-sale-count strong { display: block; font-size: 28px; line-height: 1; }
  .pancake-sale-count span { color: var(--muted); font-size: 12px; }
  .pancake-sale-panel { overflow: hidden; }
  .pancake-sale-table-scroll { max-height: calc(100vh - 260px); overflow: auto; }
  .pancake-sale-table { min-width: 940px; table-layout: fixed; font-size: 12px; }
  .pancake-sale-table thead th { position: sticky; top: 0; z-index: 2; font-size: 12px; letter-spacing: .03em; white-space: nowrap; }
  .pancake-sale-table th, .pancake-sale-table td { padding: var(--space-5) var(--space-6); vertical-align: top; }
  .pancake-sale-table th:nth-child(1) { width: 230px; }
  .pancake-sale-table th:nth-child(2) { width: 125px; }
  .pancake-sale-table th:nth-child(3) { width: 260px; }
  .pancake-sale-table th:nth-child(4) { width: 325px; }
  .pancake-sale-transaction strong { display: block; margin-bottom: var(--space-3); font-size: 13px; overflow-wrap: anywhere; }
  .pancake-sale-meta { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); color: var(--muted); font-size: 12px; }
  .pancake-sale-money { font-size: 15px; font-weight: 700; white-space: nowrap; }
  .pancake-sale-content { color: #3B414D; line-height: 1.5; }
  .pancake-sale-note { margin-top: var(--space-4); padding: var(--space-4) var(--space-5); border-left: 3px solid #D08A17; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; background: #FEF9EE; color: #A45B08; font-size: 12px; }
  .pancake-pan-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-4); align-items: end; }
  .pancake-pan-form label { gap: var(--space-3); color: var(--muted); font-size: 12px; }
  .pancake-pan-form textarea { min-height: 72px; resize: vertical; font-size: 12px; }
  .pancake-pan-form .btn { min-height: 40px; white-space: nowrap; }
  .pancake-pan-hint { grid-column: 1 / -1; color: var(--muted); font-size: 12px; }
  .pancake-sale-empty { padding: 52px var(--space-9); text-align: center; }
  .pancake-sale-empty-icon { display: grid; place-items: center; width: 48px; height: 48px; margin: 0 auto var(--space-6); border-radius: 50%; background: #E1F5E8; color: #0D6234; font-size: 22px; font-weight: 700; }
  .pancake-sale-empty strong { display: block; margin-bottom: var(--space-3); }
  @media (max-width: 768px) {
    .pancake-sale-hero { align-items: stretch; flex-direction: column; }
    .pancake-sale-count { text-align: left; }
    .pancake-sale-table-scroll { max-height: none; overflow: visible; }
    .responsive-table.pancake-sale-table { min-width: 0; width: 100%; table-layout: fixed; }
    .responsive-table.pancake-sale-table thead { display: none; }
    .responsive-table.pancake-sale-table, .responsive-table.pancake-sale-table tbody, .responsive-table.pancake-sale-table tr, .responsive-table.pancake-sale-table td { display: block; width: 100%; }
    .responsive-table.pancake-sale-table tbody { display: grid; gap: var(--space-6); padding: var(--space-6); }
    .pancake-sale-row { border: 1px solid var(--line); border-radius: var(--radius-md); background: #fff; overflow: hidden; }
    .pancake-sale-row td { padding: var(--space-5) var(--space-6); border-bottom: 1px solid var(--line); }
    .pancake-sale-row td:last-child { border-bottom: 0; }
    .pancake-sale-row td::before { content: attr(data-label); display: block; margin-bottom: var(--space-3); color: var(--muted); font-size: 12px; font-weight: 700; letter-spacing: .04em; }
    .pancake-pan-form { grid-template-columns: 1fr; }
    .pancake-pan-form .btn { width: 100%; }
  }


/* Inline styles moved from app/templates/modules/pancake_overview/order_detail.html — dot6. */
.pancake-order-header{align-items:center}.pancake-order-sections{display:grid;gap:var(--space-5)}.pancake-order-section{border:1px solid var(--line);border-radius:var(--radius-sm);background:#fff;overflow:hidden}.pancake-order-section-head{display:flex;justify-content:space-between;gap:var(--space-4);padding:var(--space-5) var(--space-6);border-bottom:1px solid var(--line)}.pancake-order-section-head h3{margin:0;font-size:14px}.pancake-order-body{padding:var(--space-5) var(--space-6)}.pancake-order-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}.pancake-order-grid>div{padding:var(--space-4) var(--space-5);border-right:1px solid var(--line);border-bottom:1px solid var(--line)}.pancake-order-grid span{display:block;color:var(--muted);font-size:12px}.pancake-order-grid strong{font-size:12px;overflow-wrap:anywhere}.pancake-order-money{text-align:right;white-space:nowrap}.pancake-order-history{display:grid;gap:var(--space-3)}.pancake-order-history article{padding:var(--space-4);border:1px solid var(--line);border-radius:var(--radius-sm)}.pancake-order-links{display:flex;gap:var(--space-4);flex-wrap:wrap}@media(max-width:768px){.pancake-order-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:768px){.pancake-order-grid{grid-template-columns:1fr}}


/* Inline styles moved from app/templates/modules/sapo_overview/order_detail.html — dot6. */
  .sapo-order-detail-header { align-items: center; margin-bottom: var(--space-5); }
  .sapo-order-detail-header h1 { margin: var(--space-2) 0 0; font-size: 22px; }.sapo-order-detail-header p { display: none; }
  .sapo-order-sections { display: grid; gap: var(--space-5); }.sapo-order-section { border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; overflow: hidden; }
  .sapo-order-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-5); padding: var(--space-5) var(--space-6) var(--space-4); border-bottom: 1px solid var(--line); }.sapo-order-section-head h3 { margin: 0; font-size: 13px; }.sapo-order-section-head span { color: var(--muted); font-size: 12px; }
  .sapo-order-section-body { padding: var(--space-5) var(--space-6); }.sapo-order-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
  .sapo-order-kv { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }.sapo-order-kv > div { min-width: 0; padding: var(--space-3) var(--space-4); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }.sapo-order-kv > div:nth-child(3n) { border-right: 0; }.sapo-order-kv span { display: block; font-size: 12px; color: var(--muted); }.sapo-order-kv strong { display: block; margin-top: var(--space-1); font-size: 12px; line-height: 1.3; overflow-wrap: anywhere; }
  .sapo-order-overview { display: grid; grid-template-columns: minmax(260px, 1.35fr) minmax(350px, 1fr); gap: var(--space-6); align-items: stretch; }.sapo-customer { padding: var(--space-5) var(--space-6); border: 1px solid var(--line); border-radius: var(--radius-sm); background: #F9FAFB; }.sapo-customer-label { display: block; color: var(--muted); font-size: 12px; }.sapo-customer-name { display: block; margin: var(--space-1) 0; font-size: 15px; }.sapo-customer-meta { color: var(--muted); font-size: 12px; }.sapo-ellipsis { display: block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .sapo-status-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }.sapo-status-card { padding: var(--space-4) var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; }.sapo-status-card span { display: block; margin-bottom: var(--space-3); font-size: 12px; color: var(--muted); }.sapo-status-card .sapo-status { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sapo-order-meta { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-7); margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--line); font-size: 12px; }.sapo-order-meta > div { display: flex; min-width: 0; gap: var(--space-2); }.sapo-order-meta span { color: var(--muted); white-space: nowrap; }.sapo-order-meta strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.sapo-order-meta .meta-wide { flex: 1 1 260px; }
  .sapo-status { display: inline-flex; align-items: center; width: fit-content; padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill); font-size: 12px; font-weight: 700; }.sapo-status-success { color: #0F7A3D; background: #E1F5E8; }.sapo-status-warning { color: #A45B08; background: #FDF3E4; }.sapo-status-info { color: #2846D6; background: #EEF1FE; }.sapo-status-muted { color: #565D6B; background: #F1F3F6; }
  .sapo-payment-summary { margin-bottom: var(--space-5); }.sapo-payment-summary > div:nth-child(5) strong { color: #0F7A3D; }.sapo-payment-summary > div:nth-child(6) strong { color: #B02821; }
  .sapo-order-detail-table { min-width: 720px; font-size: 12px; }.sapo-order-detail-table th, .sapo-order-detail-table td { padding: var(--space-3) var(--space-4); }.sapo-order-detail-table .col-money { white-space: nowrap; text-align: right; }.payment-match-check { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; margin-left: var(--space-3); border-radius: 50%; color: #fff; background: #0F7A3D; font-size: 12px; font-weight: 800; line-height: 1; vertical-align: middle; }
  .sapo-fulfillment { border-top: 1px solid var(--line); }.sapo-fulfillment:first-child { border-top: 0; }.sapo-fulfillment-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-5); padding: var(--space-4) var(--space-6); background: #F9FAFB; }.sapo-fulfillment-head h4 { margin: 0; font-size: 13px; }.sapo-fulfillment-head span { font-size: 12px; }.sapo-fulfillment-body { padding: var(--space-5) var(--space-6); }.sapo-fulfillment .sapo-order-kv { margin-bottom: var(--space-4); }
  .sapo-reconciliation-proof { margin-top: var(--space-4); padding: var(--space-4); border: 1px solid #BFE5CB; border-radius: 10px; background: #F0FAF3; display: grid; gap: var(--space-2); color: #0D6234; }
  .sapo-reconciliation-proof span { font-size: 12px; }
  .sapo-reconciliation-proof a { color: #0D6234; font-weight: 700; text-decoration: underline; }
  @media (max-width: 768px) { .sapo-order-grid, .sapo-order-kv { grid-template-columns: repeat(2, minmax(0, 1fr)); }.sapo-order-kv > div:nth-child(3n) { border-right: 1px solid var(--line); }.sapo-order-kv > div:nth-child(2n) { border-right: 0; }.sapo-order-overview { grid-template-columns: 1fr; } }
  @media (max-width: 768px) { .sapo-order-detail-header h1 { font-size: 20px; }.sapo-order-section-head, .sapo-order-section-body, .sapo-fulfillment-head, .sapo-fulfillment-body { padding-left: var(--space-5); padding-right: var(--space-5); }.sapo-order-grid, .sapo-order-kv { grid-template-columns: 1fr; }.sapo-order-kv > div, .sapo-order-kv > div:nth-child(2n) { border-right: 0; }.sapo-status-grid { grid-template-columns: 1fr; }.sapo-order-meta { display: grid; grid-template-columns: 1fr; gap: var(--space-3); }.sapo-order-detail-table { min-width: 0; }.sapo-order-detail-table tbody { padding: var(--space-3); gap: var(--space-3); }.sapo-order-detail-table td { padding: var(--space-3) var(--space-4); }.sapo-fulfillment-head { align-items: flex-start; flex-direction: column; } }


/* Inline styles moved from app/templates/modules/pancake_overview/dashboard.html — dot6. */
  .pancake-overview-page-header, .pancake-overview-section { max-width: 1600px; margin-left: 0; margin-right: auto; }
  .pancake-overview-page-header { padding-bottom: var(--space-1); }
  .pancake-overview-header-copy { display: grid; gap: var(--space-2); }
  .pancake-overview-header-note { color: var(--muted); font-size: 12px; }
  .pancake-overview-summary { grid-template-columns: minmax(280px,1.1fr) minmax(230px,.9fr) minmax(400px,1.35fr) minmax(210px,.85fr); gap: var(--space-5); margin-bottom: 0; }
  .pancake-overview-summary .card { min-height: 156px; padding: var(--space-8); }
  .pancake-overview-summary .summary-card { display: flex; flex-direction: column; gap: var(--space-5); border-top: 2px solid var(--primary-line); }
  .pancake-overview-summary .summary-label { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .02em; }
  .pancake-overview-summary .summary-lines { display: grid; gap: var(--space-3); }
  .pancake-overview-summary .summary-lines-operational { grid-template-columns: repeat(2,minmax(0,1fr)); column-gap: var(--space-7); }
  .pancake-overview-summary .summary-line { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); font-size: 12px; color: var(--muted); }
  .pancake-overview-summary .summary-line strong { color: var(--text); font-size: 17px; letter-spacing: -.02em; }
  .pancake-overview-summary .summary-line.summary-total { grid-column: 1 / -1; margin: -1px 0 var(--space-1); padding-bottom: var(--space-4); border-bottom: 1px solid var(--line); color: var(--text); font-weight: 700; }
  .pancake-overview-summary .summary-line.summary-total strong { color: var(--primary); font-size: 24px; }
  .pancake-overview-summary .summary-line.money-line { gap: var(--space-9); }
  .pancake-overview-summary .summary-line.money-line strong { font-size: 17px; white-space: nowrap; }
  .pancake-overview-column-picker { position: relative; align-self: end; }
  .pancake-overview-column-picker > summary { list-style: none; }
  .pancake-overview-column-picker > summary::-webkit-details-marker { display: none; }
  .pancake-overview-column-picker > summary::before { content: '☷'; margin-right: var(--space-3); }
  .pancake-overview-column-menu { position: absolute; z-index: 5; right: 0; top: calc(100% + 6px); min-width: 210px; max-height: 360px; overflow: auto; padding: var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-md); background: #fff; box-shadow: var(--shadow-soft); }
  .pancake-overview-column-menu label { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-1); font-size: 12px; font-weight: 500; white-space: nowrap; }
  .pancake-overview-column-menu input { width: auto; margin: 0; }
  .pancake-overview-table { min-width: 1080px; table-layout: fixed; font-size: 12px; }
  .pancake-overview-table tbody tr:hover { background: #F5F7FD; }
  .pancake-overview-table [data-column="date"] { width: 92px; }
  .pancake-overview-table [data-column="order"] { width: 112px; }
  .pancake-overview-table [data-column="customer"] { width: 150px; }
  .pancake-overview-table [data-column="status"] { width: 145px; }

  .pancake-overview-table [data-column="partner"] { width: 150px; }
  .pancake-overview-table [data-column="reconciliation"] { width: 132px; }
  .pancake-overview-table [data-column="action"] { width: 92px; }
  .pancake-overview-table .pancake-overview-money { width: 112px; white-space: nowrap; text-align: right; }
  .pancake-overview-money-value { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--space-3); }
  .pancake-overview-paid-check { display: inline-grid; place-items: center; width: 17px; height: 17px; border-radius: var(--radius-pill); background: #E1F5E8; color: #0F7A3D; font-size: 12px; font-weight: 800; line-height: 1; }
  .pancake-overview-table .truncate-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .pancake-overview-table [data-column].is-hidden { display: none; }
  .pancake-overview-table.is-compact { min-width: 0; width: 100%; }
  .pancake-overview-order-code { display: block; max-width: 100%; color: var(--primary); font-weight: 700; text-decoration: none; letter-spacing: -.01em; }
  .pancake-overview-order-code:hover { text-decoration: underline; }
  .pancake-overview-subtext { display: block; margin-top: var(--space-2); color: var(--muted); font-size: 12px; }
  .pancake-overview-pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; padding: var(--space-6) var(--space-1) 0; }
  .pancake-overview-page-links { display: inline-flex; align-items: center; gap: var(--space-4); }
  .pancake-overview-message { max-width: 1600px; margin: 0 0 var(--space-5); padding: var(--space-5) var(--space-6); border: 1px solid #BFE5CB; border-radius: var(--radius-sm); background: #F0FAF3; color: #0D6234; }
  @media (max-width:1024px) {
    .pancake-overview-summary { grid-template-columns: minmax(280px,1.1fr) minmax(230px,.9fr) minmax(400px,1.35fr); }
    .pancake-overview-summary .summary-card:last-child { grid-column: 1 / -1; }
  }
  @media (max-width:768px) {
    .pancake-overview-summary { grid-template-columns: minmax(280px,1fr) minmax(470px,1.8fr); }
    .pancake-overview-summary .summary-card:last-child { grid-column: auto; }
  }
  @media (max-width: 768px) {
    .pancake-overview-summary { grid-template-columns: 1fr; gap: var(--space-4); }
    .pancake-overview-summary .card { min-height: 0; padding: var(--space-6); }
    .pancake-overview-summary .summary-label { font-size: 12px; }
    .pancake-overview-column-picker { grid-column: auto; }
    .pancake-overview-column-menu { left: 0; right: auto; min-width: 100%; }
    .pancake-overview-table { min-width: 0; }
    .pancake-overview-table tbody { gap: var(--space-4); padding: var(--space-4); }
    .pancake-overview-table td { padding: var(--space-4) var(--space-5); }
  }


/* Inline styles moved from app/templates/modules/sapo_overview/dashboard.html — dot6. */
  .sapo-overview-page-header, .sapo-overview-section { max-width: 1600px; margin-left: 0; margin-right: auto; }
  .sapo-overview-page-header { padding-bottom: var(--space-1); }
  .sapo-overview-summary { grid-template-columns: minmax(280px, 1.1fr) minmax(230px, .9fr) minmax(400px, 1.35fr) minmax(210px, .85fr); gap: var(--space-5); margin-bottom: 0; }
  .sapo-overview-summary .card { min-height: 156px; padding: var(--space-8); }
  .sapo-overview-summary .summary-card { display: flex; flex-direction: column; gap: var(--space-5); border-top: 2px solid var(--primary-line); }
  .sapo-overview-summary .summary-label { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .02em; }
  .sapo-overview-summary .summary-lines { display: grid; gap: var(--space-3); }
  .sapo-overview-summary .summary-lines-delivery { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-7); }
  .sapo-overview-summary .summary-line { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); font-size: 12px; color: var(--muted); }
  .sapo-overview-summary .summary-line strong { color: var(--text); font-size: 17px; letter-spacing: -.02em; }
  .sapo-overview-summary .summary-line.summary-total { grid-column: 1 / -1; margin: -1px 0 var(--space-1); padding-bottom: var(--space-4); border-bottom: 1px solid var(--line); color: var(--text); font-weight: 700; }
  .sapo-overview-summary .summary-line.summary-total strong { color: var(--primary); font-size: 24px; }
  .sapo-overview-summary .summary-line.money-line { gap: var(--space-9); }
  .sapo-overview-summary .summary-line.money-line strong { font-size: 17px; white-space: nowrap; }
  .sapo-overview-pagination { justify-content: flex-start; }
  /* Mặc định chỉ giữ các cột phục vụ xử lý chính; không ép thanh kéo ngang khi các cột phụ đang ẩn. */
  .sapo-overview-table { min-width: 1080px; table-layout: fixed; }
  .sapo-overview-table tbody tr:hover { background: #F5F7FD; }
  /* Khoá tỷ lệ cột: ưu tiên vùng trạng thái và nút thao tác, không dàn đều cột ít dữ liệu. */
  .sapo-overview-table [data-column="created"] { width: 94px; min-width: 94px; max-width: 94px; }
  .sapo-overview-table .col-code { width: 96px; min-width: 96px; max-width: 96px; }
  .sapo-overview-table .col-customer { width: 128px; min-width: 128px; max-width: 128px; }
  .sapo-overview-table [data-column="location"] { width: 112px; min-width: 112px; max-width: 112px; }
  .sapo-overview-table [data-column="payment"] { width: 132px; min-width: 132px; max-width: 132px; }
  .sapo-overview-table .col-money { width: 118px; min-width: 118px; max-width: 118px; white-space: nowrap; text-align: right; }
  .sapo-overview-table .col-status { width: 140px; min-width: 140px; max-width: 140px; }
  .sapo-overview-table .col-collation { width: 150px; min-width: 150px; max-width: 150px; }
  .sapo-overview-table [data-column="phone"] { width: 112px; min-width: 112px; max-width: 112px; }
  .sapo-overview-table [data-column="order-status"] { width: 122px; min-width: 122px; max-width: 122px; }
  .sapo-overview-table [data-column="channel"] { width: 116px; min-width: 116px; max-width: 116px; }
  .sapo-overview-table [data-column="source"] { width: 118px; min-width: 118px; max-width: 118px; }
  .sapo-overview-table [data-column="assignee"] { width: 130px; min-width: 130px; max-width: 130px; }
  .sapo-overview-table .col-detail { width: 104px; min-width: 104px; max-width: 104px; white-space: nowrap; }
  .sapo-overview-table .col-code, .sapo-overview-table .col-customer, .sapo-overview-table .col-status { overflow: hidden; text-overflow: ellipsis; }
  .sapo-overview-table .col-code { white-space: nowrap; }
  .sapo-overview-table .col-customer .truncate-text { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sapo-overview-table .col-status .status-pill { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sapo-overview-pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; padding: var(--space-6) var(--space-1) 0; }
  .sapo-overview-page-links { display: inline-flex; align-items: center; gap: var(--space-4); }
  .sapo-overview-status-note { margin-top: var(--space-2); color: var(--muted); font-size: 12px; white-space: nowrap; }
  .sapo-overview-column-picker { position: relative; }
  .sapo-overview-column-picker > summary { list-style: none; }
  .sapo-overview-column-picker > summary::-webkit-details-marker { display: none; }
  .sapo-overview-column-picker > summary::before { content: '☷'; margin-right: var(--space-3); }
  .sapo-overview-column-menu { position: absolute; z-index: 5; right: 0; top: calc(100% + 6px); min-width: 190px; padding: var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-md); background: #fff; box-shadow: var(--shadow-soft); }
  .sapo-overview-column-menu label { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-1); font-size: 12px; font-weight: 500; white-space: nowrap; }
  .sapo-overview-column-menu input { width: auto; margin: 0; }
  .sapo-overview-table [data-column].is-hidden { display: none; }
  .sapo-overview-table.is-compact { min-width: 0; width: 100%; }
  .sapo-overview-table.is-compact [data-column="created"] { width: 90px; min-width: 90px; max-width: 90px; }
  .sapo-overview-table.is-compact .col-code { width: 96px; min-width: 96px; max-width: 96px; }
  .sapo-overview-table.is-compact .col-customer { width: auto; min-width: 150px; max-width: none; }
  .sapo-overview-table.is-compact [data-column="location"] { width: 110px; min-width: 110px; max-width: 110px; }
  .sapo-overview-table.is-compact [data-column="payment"] { width: 126px; min-width: 126px; max-width: 126px; }
  .sapo-overview-table.is-compact .col-money { width: 116px; min-width: 116px; max-width: 116px; }
  .sapo-overview-table.is-compact .col-status { width: 136px; min-width: 136px; max-width: 136px; }
  .sapo-overview-table.is-compact .col-collation { width: 150px; min-width: 150px; max-width: 150px; }
  .sapo-overview-table.is-compact .col-detail { width: 104px; min-width: 104px; max-width: 104px; }

  @media (max-width: 1024px) {
    .sapo-overview-summary { grid-template-columns: minmax(280px, 1.1fr) minmax(230px, .9fr) minmax(400px, 1.35fr); }
    .sapo-overview-summary .summary-card:last-child { grid-column: 1 / -1; }
  }
  @media (max-width: 768px) {
    .sapo-overview-summary { grid-template-columns: minmax(280px, 1fr) minmax(470px, 1.8fr); }
    .sapo-overview-summary .summary-card:last-child { grid-column: auto; }

  }
  @media (max-width: 768px) {
    .sapo-overview-summary { grid-template-columns: 1fr; gap: var(--space-4); }
    .sapo-overview-summary .card { min-height: 0; padding: var(--space-6); }
    .sapo-overview-summary .summary-label { font-size: 12px; }
    .sapo-overview-summary .summary-line.money-line strong { font-size: 16px; }
    .sapo-overview-column-picker { grid-column: auto; }
    .sapo-overview-column-picker > summary { width: 100%; }
    .sapo-overview-column-menu { left: 0; right: auto; min-width: 100%; }
    .sapo-overview-table { min-width: 0; }
    .sapo-overview-table tbody { gap: var(--space-4); padding: var(--space-4); }
    .sapo-overview-table td { padding: var(--space-4) var(--space-5); }
    .sapo-overview-table .col-customer, .sapo-overview-table .col-status, .sapo-overview-table .col-collation { min-width: 0; max-width: none; }

    .sapo-overview-status-note { overflow: hidden; text-overflow: ellipsis; }
  }


/* Inline styles moved from app/templates/modules/zeijp_bank/confirm_orders.html — dot6. */
  .zeijp-confirm-summary {
    display: grid;
    gap: var(--space-2);
  }
  .zeijp-confirm-form {
    display: grid;
    gap: var(--space-4);
    min-width: 220px;
  }
  .zeijp-confirm-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6);
    align-items: center;
    justify-content: flex-end;
  }
  @media (max-width: 1024px) {
    .sapo-bank-table-scroll {
      max-height: none;
      overflow: visible;
    }
    .sapo-bank-table,
    .responsive-table.sapo-bank-table.compact-table {
      min-width: 0;
      width: 100%;
      table-layout: fixed;
    }
    .responsive-table thead {
      display: none;
    }
    .responsive-table,
    .responsive-table tbody,
    .responsive-table tr,
    .responsive-table td {
      display: block;
      width: 100%;
    }
    .responsive-table tbody {
      display: grid;
      gap: var(--space-6);
      padding: var(--space-6);
    }
    .responsive-table tr {
      border: 1px solid var(--line);
      border-radius: var(--radius-lg);
      background: #fff;
      overflow: hidden;
    }
    .responsive-table td {
      padding: var(--space-6) var(--space-7);
      border-bottom: 1px solid var(--line);
    }
    .responsive-table td:last-child {
      border-bottom: none;
    }
    .responsive-table td::before {
      content: attr(data-label);
      display: block;
      margin-bottom: var(--space-3);
      color: var(--muted);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.04em;
    }
    .responsive-table td[data-label=""]::before {
      display: none;
    }
    .zeijp-confirm-toolbar {
      width: 100%;
      align-items: stretch;
      justify-content: stretch;
    }
    .zeijp-confirm-toolbar .pagination-meta {
      text-align: left;
    }
    .zeijp-confirm-form {
      min-width: 0;
    }
    .zeijp-confirm-row {
      border-radius: var(--radius-md);
      overflow: hidden;
    }
    .zeijp-confirm-row td {
      padding: var(--space-5) var(--space-6);
    }
    .zeijp-confirm-row td::before {
      margin-bottom: var(--space-2);
      font-size: 12px;
    }
    .zeijp-confirm-row td:first-child {
      background: #F9FAFB;
      padding: var(--space-5) var(--space-6);
      font-weight: 700;
      color: #15171C;
    }
    .zeijp-confirm-row td:first-child::before {
      display: inline-block;
      margin: 0 var(--space-3) 0 0;
    }
    .zeijp-confirm-row td[data-label="ID"],
    .zeijp-confirm-row td[data-label="Ngày giờ"],
    .zeijp-confirm-row td[data-label="Số tiền"] {
      display: grid;
      grid-template-columns: 104px minmax(0, 1fr);
      gap: var(--space-4);
      align-items: start;
    }
    .zeijp-confirm-row td[data-label="ID"]::before,
    .zeijp-confirm-row td[data-label="Ngày giờ"]::before,
    .zeijp-confirm-row td[data-label="Số tiền"]::before {
      margin: 0;
    }
    .zeijp-confirm-row td[data-label="Mã GD"] {
      display: none;
    }
    .zeijp-confirm-row td[data-label="Mã TC"] .truncate-text {
      display: inline-block;
      max-width: 100%;
      font-size: 12px;
      line-height: 1.35;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .zeijp-confirm-row td[data-label="Nội dung CK"] .truncate-text,
    .zeijp-confirm-row td[data-label="Ghi chú"] .truncate-text {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      white-space: normal;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 100%;
      font-size: 12px;
      line-height: 1.35;
      max-height: calc(1.35em * 2);
      word-break: break-word;
    }
    .zeijp-confirm-row td[data-label="Nội dung CK"],
    .zeijp-confirm-row td[data-label="Ghi chú"] {
      padding-top: var(--space-4);
      padding-bottom: var(--space-4);
      overflow: hidden;
    }
    .zeijp-confirm-row td[data-label="Nội dung CK"] {
      color: #3B414D;
    }
    .zeijp-confirm-row td[data-label="Ghi chú"] {
      color: #565D6B;
    }
    .zeijp-confirm-form input,
    .zeijp-confirm-form button {
      width: 100%;
    }
  }


/* Inline styles moved from app/templates/modules/zeijp_bank/dashboard.html — dot6. */
  .zeijp-bank-balance-summary {
    display: grid;
    gap: var(--space-2);
  }
  .zeijp-bank-balance-summary-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--muted);
  }
  .zeijp-bank-balance-summary-value {
    font-size: 28px;
    line-height: 1.1;
    font-weight: 800;
    color: var(--text);
  }
  /* `.zeijp-order-filters` / `.zeijp-order-filter` đã bị thay bằng `.chipset` /
     `.chip` dùng chung — xem khối "THANH BỘ LỌC DÙNG CHUNG". Không còn khai
     báo riêng ở đây nữa; tab thì thừa hưởng nguyên điều khiển phân đoạn. */
  .zeijp-bank-tabs {
    margin-bottom: var(--space-2);
  }
  .zeijp-action-form {
    margin-top: var(--space-4);
    display: grid;
    gap: var(--space-4);
    min-width: 220px;
  }
  @media (max-width: 1024px) {
    .sapo-bank-table-scroll {
      max-height: none;
      overflow: visible;
    }
    .sapo-bank-table,
    .responsive-table.sapo-bank-table.compact-table {
      min-width: 0;
      width: 100%;
      table-layout: fixed;
    }
    .responsive-table thead {
      display: none;
    }
    .responsive-table,
    .responsive-table tbody,
    .responsive-table tr,
    .responsive-table td {
      display: block;
      width: 100%;
    }
    .responsive-table tbody {
      display: grid;
      gap: var(--space-6);
      padding: var(--space-6);
    }
    .responsive-table tr {
      border: 1px solid var(--line);
      border-radius: var(--radius-lg);
      background: #fff;
      overflow: hidden;
    }
    .responsive-table td {
      padding: var(--space-6) var(--space-7);
      border-bottom: 1px solid var(--line);
    }
    .responsive-table td:last-child {
      border-bottom: none;
    }
    .responsive-table td::before {
      content: attr(data-label);
      display: block;
      margin-bottom: var(--space-3);
      color: var(--muted);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.04em;
    }
    .responsive-table td[data-label=""]::before {
      display: none;
    }
    .zeijp-bank-balance-summary-value {
      font-size: 22px;
    }
    .zeijp-bank-row {
      border-radius: var(--radius-md);
      overflow: hidden;
    }
    .zeijp-bank-row td {
      padding: var(--space-5) var(--space-6);
    }
    .zeijp-bank-row td::before {
      margin-bottom: var(--space-2);
      font-size: 12px;
    }
    .zeijp-bank-row td:first-child {
      background: #F9FAFB;
      padding: var(--space-5) var(--space-6);
      font-weight: 700;
      color: #15171C;
    }
    .zeijp-bank-row td:first-child::before {
      display: inline-block;
      margin: 0 var(--space-3) 0 0;
    }
    .zeijp-bank-row td[data-label="ID"],
    .zeijp-bank-row td[data-label="Ngày giờ"],
    .zeijp-bank-row td[data-label="Số tiền"] {
      display: grid;
      grid-template-columns: 104px minmax(0, 1fr);
      gap: var(--space-4);
      align-items: start;
    }
    .zeijp-bank-row td[data-label="ID"]::before,
    .zeijp-bank-row td[data-label="Ngày giờ"]::before,
    .zeijp-bank-row td[data-label="Số tiền"]::before {
      margin: 0;
    }
    .zeijp-bank-row td[data-label="ID nộp tiền / Xác nhận"] {
      font-weight: 700;
      color: #15171C;
      word-break: break-word;
    }
    .zeijp-bank-row td[data-label="Mã GD"] {
      display: none;
    }
    .zeijp-bank-row td[data-label="Mã TC"] .truncate-text,
    .zeijp-bank-row td[data-label="ID nộp tiền / Xác nhận"] .truncate-text {
      display: inline-block;
      max-width: 100%;
      font-size: 12px;
      line-height: 1.35;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .zeijp-bank-row td[data-label="Nội dung CK"] .truncate-text,
    .zeijp-bank-row td[data-label="Ghi chú"] .truncate-text {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      white-space: normal;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 100%;
      font-size: 12px;
      line-height: 1.35;
      max-height: calc(1.35em * 2);
      word-break: break-word;
    }
    .zeijp-bank-row td[data-label="Nội dung CK"],
    .zeijp-bank-row td[data-label="Ghi chú"] {
      padding-top: var(--space-4);
      padding-bottom: var(--space-4);
      overflow: hidden;
    }
    .zeijp-bank-row td[data-label="Nội dung CK"] {
      color: #3B414D;
    }
    .zeijp-bank-row td[data-label="Ghi chú"] {
      color: #565D6B;
    }
    .zeijp-bank-row .status-pill {
      max-width: 100%;
      white-space: normal;
      line-height: 1.35;
    }
    .zeijp-action-form {
      min-width: 0;
    }
    .zeijp-action-form input,
    .zeijp-action-form button,
    .zeijp-bank-row details summary {
      width: 100%;
    }
    .zeijp-bank-row details summary {
      text-align: center;
    }
  }


/* Inline styles moved from app/templates/modules/pancake_bank/dashboard.html — dot6. */
  /* Bám đúng cách trình bày của Sapo Bank: một bảng phẳng, các PAN xếp thành dòng đồng bộ giữa các cột. */
  .pancake-bank-table.compact-table { min-width: 900px; table-layout: fixed; font-size: 12px; }
  .pancake-bank-table.compact-table th { font-size: 12px; letter-spacing: .02em; white-space: nowrap; }
  .pancake-bank-table.compact-table td { vertical-align: middle; }
  .pancake-bank-table-scroll { max-height: calc(100vh - 220px); overflow: auto; }
  .pancake-bank-table th:nth-child(1) { width: 48px; }
  .pancake-bank-table th:nth-child(2) { width: 58px; }
  .pancake-bank-table th:nth-child(3) { width: 82px; }
  .pancake-bank-table th:nth-child(4) { width: 130px; }
  .pancake-bank-table th:nth-child(5) { width: 82px; }
  .pancake-bank-table th:nth-child(6) { width: 82px; }
  .pancake-bank-table th:nth-child(7) { width: 98px; }
  .pancake-bank-table th:nth-child(8) { width: 92px; }
  .pancake-bank-table th:nth-child(9) { width: 95px; }
  .pancake-bank-table th:nth-child(10) { width: 105px; }
  .pancake-bank-table th:nth-child(11) { width: 68px; }
  .pancake-bank-table th:last-child, .pancake-bank-table td:last-child { padding-right: var(--space-7); }
  .pancake-reference { display: block; max-width: 100%; overflow: hidden; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
  .pancake-subtext { display: block; max-width: 100%; margin-top: var(--space-1); overflow: hidden; color: var(--muted); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
  .pancake-money { text-align: right; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
  .truncate-text-2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; font-size: 12px; line-height: 1.35; }
  /* --- Giới hạn số dòng con hiện sẵn ---------------------------------
     Một giao dịch Pancake có thể gồm tới 10 PAN. Hiện hết thì hàng đó cao gấp
     mười hàng thường (đo trên dữ liệu thật: 11,9% giao dịch có >1 PAN), bảng
     nát bét và không quét mắt được nữa.

     Cắt theo THỨ TỰ dòng con chứ không theo `max-height`: năm cột song song
     (PAN / Tổng tiền / Đã thanh toán / Còn phải thu / Vào tiền) đều bị cắt ở
     đúng dòng thứ ba, nên chúng vẫn thẳng hàng với nhau. Cắt bằng chiều cao
     thì lệ thuộc vào `line-height` thật của từng cột và rất dễ so le. */
  .pancake-bank-row:not(.is-stack-open) .son-stack-lines > .son-line:nth-child(n+3) { display: none; }
  /* Pill không được tràn khỏi cột. Bảng này dùng `table-layout: fixed`, còn
     `.status-pill` mặc định `white-space: nowrap` — nên nhãn dài như
     "Đã xử lý (OpenClaw)" (19 ký tự) chạy đè sang cột "Ghi chú Bot" bên cạnh
     vì cột chỉ rộng 95px. Cắt bằng dấu ba chấm; nội dung đầy đủ vẫn xem được ở
     "Chi tiết". Cùng cách đã dùng cho `.sapo-overview-table .col-status`. */
  .pancake-bank-table td .status-pill {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .stack-more {
    margin-top: var(--space-2);
    padding: 0 var(--space-4);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    color: var(--muted);
    font: inherit;
    font-size: 12px;
    font-weight: 700;
    line-height: 19px;
    white-space: nowrap;
    cursor: pointer;
  }
  .stack-more:hover { border-color: var(--primary-line); background: var(--primary-soft); color: var(--primary-strong); }

  .son-stack-lines { display: flex; flex-direction: column; gap: var(--space-2); }
  .son-line { display: flex; min-height: 27px; align-items: center; gap: var(--space-3); border-bottom: 1px solid #EFF1F5; }
  .son-line:last-child { border-bottom: 0; }
  .son-line .status-pill { max-width: 100%; }
  .pan-order-link { color: inherit; text-decoration: none; }
  .pan-order-link:hover { color: var(--primary); text-decoration: underline; }
  .pan-order-link::after { content: ' ↗'; font-size: 12px; }
  .pancake-bank-detail-row > td { padding: 0 !important; background: #F9FAFB; }
  .pancake-bank-detail-row[hidden] { display: none; }
  .pancake-bank-detail-grid { display: grid; grid-template-columns: repeat(4, minmax(130px, 1fr)); gap: var(--space-5) var(--space-8); padding: var(--space-6) var(--space-7); font-size: 12px; }
  .pancake-bank-detail-grid dt { margin-bottom: var(--space-1); color: var(--muted); font-size: 12px; font-weight: 700; }
  .pancake-bank-detail-grid dd { margin: 0; overflow-wrap: anywhere; }
  .pancake-detail-span-2 { grid-column: span 2; }
  .pancake-job-stack, .pancake-audit-list { display: grid; gap: var(--space-3); }
  .pancake-job { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
  .pancake-detail-actions { display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--space-4); }
  .pancake-detail-actions details > summary { cursor: pointer; list-style: none; }
  .pancake-detail-actions details > summary::-webkit-details-marker { display: none; }
  .pancake-inline-action { margin: 0; }
  .pancake-pan-edit-form { display: grid; min-width: 280px; gap: var(--space-4); margin-top: var(--space-4); }
  .pancake-pan-edit-form input { min-width: 280px; }
  .accounting-review-confirm form { display: grid; min-width: 280px; gap: var(--space-4); margin-top: var(--space-4); }
  .accounting-review-confirm label { display: grid; gap: var(--space-3); color: var(--text); font-weight: 700; }
  .accounting-review-confirm textarea { min-height: 76px; resize: vertical; font-weight: 400; }
  .pancake-allocation-form { display: grid; min-width: 260px; gap: var(--space-4); margin-top: var(--space-4); }
  .pancake-allocation-form textarea { min-height: 76px; resize: vertical; }
  .pancake-audit-list { max-height: 150px; margin-top: var(--space-4); padding-left: var(--space-5); overflow: auto; border-left: 2px solid var(--line); color: var(--muted); }
  .pancake-empty { padding: 36px var(--space-9); text-align: center; }
  /* Hai dòng này từng ghi đè định nghĩa pill chung ở phía trên chỉ vì nằm sau
     trong file, làm mất vòng viền của pill trên riêng trang Pancake Bank. Nay
     trỏ về đúng biến chung. */
  .status-pill-warning { background: var(--warning-soft); color: #8A4A06; box-shadow: inset 0 0 0 1px var(--warning-line); }
  .status-pill-info { background: var(--info-soft); color: var(--info); box-shadow: inset 0 0 0 1px var(--info-line); }
  /* Tiền ra chỉ giữ thông tin nhận diện và audit, giống Sapo Bank. */
  .pancake-bank-table.outbound-view th:nth-child(5),
  .pancake-bank-table.outbound-view td:nth-child(5),
  .pancake-bank-table.outbound-view th:nth-child(6),
  .pancake-bank-table.outbound-view td:nth-child(6),
  .pancake-bank-table.outbound-view th:nth-child(7),
  .pancake-bank-table.outbound-view td:nth-child(7),
  .pancake-bank-table.outbound-view th:nth-child(8),
  .pancake-bank-table.outbound-view td:nth-child(8),
  .pancake-bank-table.outbound-view th:nth-child(9),
  .pancake-bank-table.outbound-view td:nth-child(9),
  .pancake-bank-table.outbound-view th:nth-child(11),
  .pancake-bank-table.outbound-view td:nth-child(11) { display: none; }
  .pancake-bank-table.outbound-view { min-width: 680px; }
  .pancake-bank-table.outbound-view th:nth-child(4) { width: 260px; }
  .pancake-bank-table.outbound-view th:nth-child(10) { width: 180px; }
  @media (max-width: 1024px) {
    .pancake-bank-table-scroll { max-height: none; overflow: visible; }
    .pancake-bank-table, .responsive-table.pancake-bank-table.compact-table { min-width: 0; width: 100%; table-layout: fixed; }
    .responsive-table.pancake-bank-table thead { display: none; }
    .responsive-table.pancake-bank-table, .responsive-table.pancake-bank-table tbody, .responsive-table.pancake-bank-table tr, .responsive-table.pancake-bank-table td { display: block; width: 100%; }
    .responsive-table.pancake-bank-table tbody { display: grid; gap: var(--space-6); padding: var(--space-6); }
    .pancake-bank-row { overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-md); background: #fff; }
    .pancake-bank-row td { padding: var(--space-5) var(--space-6); border-bottom: 1px solid var(--line); }
    .pancake-bank-row td::before { content: attr(data-label); display: block; margin-bottom: var(--space-2); color: var(--muted); font-size: 12px; font-weight: 700; letter-spacing: .04em; }
    .pancake-bank-row td:first-child { background: #F9FAFB; font-weight: 700; }
    .pancake-bank-detail-row { border: 0 !important; }
    .pancake-bank-detail-row > td::before { display: none; }
    .pancake-bank-detail-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (max-width: 768px) {
    .pancake-bank-detail-grid { grid-template-columns: 1fr; }
    .pancake-detail-span-2 { grid-column: auto; }
  }


/* Inline styles moved from app/templates/modules/sapo_bank/dashboard.html — dot6. */
  /* Bảng chính ưu tiên quét nhanh; dữ liệu phụ mở theo từng giao dịch. */
  .sapo-bank-table.compact-table {
    font-size: 12px;
  }
  .sapo-bank-table.compact-table th {
    font-size: 12px;
    letter-spacing: .02em;
    white-space: nowrap;
  }

  .col-son-block {
    min-width: 104px;
    width: 104px;
  }
  .sapo-bank-detail-row > td {
    padding: 0;
    background: #F9FAFB;
  }
  .sapo-bank-detail-row[hidden] {
    display: none;
  }
  .sapo-bank-detail-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(130px, 1fr));
    gap: var(--space-5) var(--space-8);
    padding: var(--space-6) var(--space-7);
    font-size: 12px;
  }
  .sapo-bank-detail-grid dt {
    margin-bottom: var(--space-1);
    color: var(--muted);
    font-size: 12px;
    font-weight: 700;
  }
  .sapo-bank-detail-grid dd {
    margin: 0;
    overflow-wrap: anywhere;
  }
  @media (max-width: 1024px) {
    .sapo-bank-detail-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }
  @media (max-width: 768px) {
    .sapo-bank-detail-grid {
      grid-template-columns: 1fr;
    }
  }
  .col-son-block .status-pill {
    padding-inline: 8px;
  }
  .son-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }
  .accounting-review-confirm {
    margin-top: var(--space-4);
  }
  .accounting-review-confirm summary {
    cursor: pointer;
    list-style: none;
  }
  .accounting-review-confirm summary::-webkit-details-marker {
    display: none;
  }
  .accounting-review-confirm form {
    display: grid;
    gap: var(--space-4);
    margin-top: var(--space-4);
    min-width: 240px;
  }
  .accounting-review-confirm textarea {
    width: 100%;
    min-height: 72px;
    resize: vertical;
  }
  .sapo-bank-correction-dialog {
    max-width: 460px;
    width: min(460px, calc(100vw - 32px));
    border: 0;
    border-radius: var(--radius-sm);
    padding: 0;
    box-shadow: 0 16px 48px rgba(15, 23, 42, .28);
  }
  .sapo-bank-correction-dialog::backdrop {
    background: rgba(15, 23, 42, .42);
  }
  .sapo-bank-correction-form {
    display: grid;
    gap: var(--space-6);
    padding: var(--space-10);
  }
  .sapo-bank-correction-form label {
    display: grid;
    gap: var(--space-3);
    font-weight: 600;
  }
  .sapo-bank-correction-form textarea {
    min-height: 92px;
    resize: vertical;
  }
  .sapo-bank-correction-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-4);
  }
  .son-stack-lines {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }
  .son-line {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }
  /* Tiền ra chỉ giữ thông tin nhận diện chính: mã, ngày, tiền, nội dung, mã TC và ghi chú Bot. */
  .sapo-bank-table.outbound-view th:nth-child(5),
  .sapo-bank-table.outbound-view td:nth-child(5),
  .sapo-bank-table.outbound-view th:nth-child(6),
  .sapo-bank-table.outbound-view td:nth-child(6),
  .sapo-bank-table.outbound-view th:nth-child(7),
  .sapo-bank-table.outbound-view td:nth-child(7),
  .sapo-bank-table.outbound-view th:nth-child(9),
  .sapo-bank-table.outbound-view td:nth-child(9),
  .sapo-bank-table.outbound-view th:nth-child(10),
  .sapo-bank-table.outbound-view td:nth-child(10),
  .sapo-bank-table.outbound-view th:nth-child(11),
  .sapo-bank-table.outbound-view td:nth-child(11),
  .sapo-bank-table.outbound-view th:nth-child(13),
  .sapo-bank-table.outbound-view td:nth-child(13),
  .sapo-bank-table.outbound-view th:nth-child(14),
  .sapo-bank-table.outbound-view td:nth-child(14),
  .sapo-bank-table.outbound-view th:nth-child(15),
  .sapo-bank-table.outbound-view td:nth-child(15) {
    display: none;
  }
  @media (max-width: 1024px) {
    .sapo-bank-table-scroll {
      max-height: none;
      overflow: visible;
    }
    .sapo-bank-table,
    .responsive-table.sapo-bank-table.compact-table {
      min-width: 0;
      width: 100%;
      table-layout: fixed;
    }
    .responsive-table thead {
      display: none;
    }
    .responsive-table,
    .responsive-table tbody,
    .responsive-table tr,
    .responsive-table td {
      display: block;
      width: 100%;
    }
    .responsive-table tbody {
      display: grid;
      gap: var(--space-6);
      padding: var(--space-6);
    }
    .sapo-bank-row {
      border: 1px solid var(--line);
      border-radius: var(--radius-md);
      background: #fff;
      overflow: hidden;
    }
    .sapo-bank-row td {
      padding: var(--space-5) var(--space-6);
      border-bottom: 1px solid var(--line);
    }
    .sapo-bank-row td:last-child {
      border-bottom: none;
    }
    .sapo-bank-row td::before {
      content: attr(data-label);
      display: block;
      margin-bottom: var(--space-2);
      color: var(--muted);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: .04em;
    }
    .sapo-bank-row td:first-child {
      background: #F9FAFB;
      padding: var(--space-5) var(--space-6);
      font-weight: 700;
      color: #15171C;
    }
    .sapo-bank-row td:first-child::before {
      display: inline-block;
      margin: 0 var(--space-3) 0 0;
    }
    .sapo-bank-row td[data-label="Mã giao dịch"],
    .sapo-bank-row td[data-label="Ngày giờ"],
    .sapo-bank-row td[data-label="Số tiền"] {
      display: grid;
      grid-template-columns: 104px minmax(0, 1fr);
      gap: var(--space-4);
      align-items: start;
    }
    .sapo-bank-row td[data-label="Mã giao dịch"]::before,
    .sapo-bank-row td[data-label="Ngày giờ"]::before,
    .sapo-bank-row td[data-label="Số tiền"]::before {
      margin: 0;
    }
    .sapo-bank-row td[data-label="Nội dung CK"] .truncate-text,
    .sapo-bank-row td[data-label="Ghi chú Bot"] .truncate-text,
    .sapo-bank-row td[data-label="Ghi chú kế toán"] .truncate-text {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      white-space: normal;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 100%;
      font-size: 12px;
      line-height: 1.35;
      max-height: calc(1.35em * 2);
      word-break: break-word;
    }
    .sapo-bank-row .status-pill {
      max-width: 100%;
      white-space: normal;
      line-height: 1.35;
    }
    .sapo-bank-row .son-stack-lines {
      gap: var(--space-3);
    }
    .sapo-bank-row .son-line {
      min-width: 0;
      flex-wrap: wrap;
    }
    .sapo-bank-row td[data-label="Mã TC"],
    .sapo-bank-row td[data-label="NV xử lý"] {
      display: none;
    }
    .sapo-bank-row .son-edit-form {
      display: grid;
      gap: var(--space-4);
      width: 100%;
      margin-bottom: var(--space-4);
    }
    .sapo-bank-row .son-edit-form input,
    .sapo-bank-row .son-edit-form button {
      width: 100%;
      min-height: 40px;
    }
  }
/* Dot6 1.3 — neutral hooks and complete wholesale customer layout. */
.simple-auth-page { background: var(--bg); }
.mobile-menu-label { display: inline; }
.pancake-bank-wrap { overflow: hidden; }
.pancake-bank-detail-toggle,
.sapo-bank-detail-toggle { user-select: none; }
.pancake-audit { min-width: 0; }
.pancake-overview-row,
.sapo-overview-row,
.zeijp-bank-style-row { background: var(--surface); }
.is-selected-transaction { background: #EEF1FE; box-shadow: inset 3px 0 0 var(--primary); }
.wallet-operation-panel,
.customer-edit-panel { max-width: 920px; }
.wallet-action-row { align-items: center; }
.is-wallet { background: #E2F0FB; color: #0B5A85; }

.sapo-wholesale-result { overflow: hidden; }
.sapo-wholesale-lookup { display: grid; grid-template-columns: minmax(140px, auto) minmax(240px, 1fr); align-items: center; gap: var(--space-6); margin-bottom: var(--space-8); padding: var(--space-7) var(--space-9); }
.sapo-wholesale-lookup label { margin: 0; color: var(--muted); font-size: 13px; }
.sapo-wholesale-list-head { flex-direction: row; }
.sapo-wholesale-list-tools { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-6); flex-wrap: wrap; }
.sapo-wholesale-sort-form { display: flex; align-items: center; gap: var(--space-4); }
.sapo-wholesale-sort-form label { display: inline; color: var(--muted); font-size: 12px; white-space: nowrap; }
.sapo-wholesale-sort-form select { width: auto; min-width: 170px; padding: var(--space-4) var(--space-5); }
.sapo-wholesale-table { min-width: 920px; table-layout: fixed; }
.sapo-wholesale-col-customer { width: 22%; }
.sapo-wholesale-col-phone { width: 14%; }
.sapo-wholesale-col-count { width: 9%; }
.sapo-wholesale-col-order { width: 13%; }
.sapo-wholesale-col-actions { width: 22%; }
.sapo-wholesale-actions-heading { text-align: right; }
.sapo-wholesale-customer strong,
.sapo-wholesale-customer small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sapo-wholesale-customer small { margin-top: var(--space-1); color: var(--muted); }
.sapo-wholesale-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); flex-wrap: wrap; }
.sapo-wholesale-actions form { margin: 0; }
.sapo-wholesale-unpaid-row { background: #FEF9EE; }
.sapo-wholesale-summary,
.wallet-summary { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1); margin-bottom: var(--space-8); overflow: hidden; }
.sapo-wholesale-summary > div,
.wallet-summary > div { padding: var(--space-8) var(--space-9); background: var(--surface); }
.sapo-wholesale-summary span,
.wallet-summary span { display: block; color: var(--muted); font-size: 12px; }
.sapo-wholesale-summary strong,
.wallet-summary strong { display: block; margin-top: var(--space-2); font-size: 22px; }

@media (max-width: 768px) {
  .mobile-menu-label { display: none; }
  .sapo-wholesale-lookup { grid-template-columns: 1fr; padding: var(--space-6); }
  .sapo-wholesale-list-head,
  .sapo-wholesale-list-tools { align-items: stretch; flex-direction: column; }
  .sapo-wholesale-sort-form { justify-content: space-between; }
  .sapo-wholesale-sort-form select { min-width: 0; flex: 1; }
  .sapo-wholesale-table { min-width: 0; }
  .sapo-wholesale-actions { justify-content: stretch; }
  .sapo-wholesale-actions .btn,
  .sapo-wholesale-actions form { width: 100%; }
  .sapo-wholesale-summary,
  .wallet-summary { grid-template-columns: 1fr; }
}

/* Chuyen tu <style> noi bo cua modules/sapo_bank/dashboard.html (27/07).
   190/191 khai bao trong khoi do trung y het app.css; day la luat duy nhat
   chi ton tai o ban noi bo. */
.page-header-actions { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.page-header-actions form { margin: 0; }
.sapo-operational-filter { margin-bottom: 0; }
.sapo-operational-filter .filterbar-row { align-items: end; }
/* Nút "Xem báo cáo" đứng cạnh ô chọn tháng, không bị margin-left:auto đẩy ra mép phải. */
.sapo-operational-filter .filterbar-actions { margin-left: 0; }
.sapo-operational-freshness { margin: var(--space-4) 0 0; color: var(--muted); font-size: .875rem; }
.sapo-operational-total { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); margin-bottom: var(--space-8); background: var(--primary-soft); border-color: var(--primary-line); }
.sapo-operational-total span { display: block; color: var(--muted); font-weight: 600; }
.sapo-operational-total small { display: block; margin-top: var(--space-2); color: var(--muted); }
.sapo-operational-total strong { color: var(--primary); font-size: 2rem; }
.sapo-operational-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-8); }
.sapo-operational-flow-list { display: grid; gap: var(--space-8); }
.sapo-operational-card { display: flex; flex-direction: column; gap: var(--space-6); }
.sapo-operational-card-detail { padding: 0; overflow: hidden; }
.sapo-operational-card-detail > .sapo-operational-card-head,
.sapo-operational-card-detail > p,
.sapo-operational-card-detail > .summary-lines { margin-left: var(--space-8); margin-right: var(--space-8); }
.sapo-operational-card-detail > .sapo-operational-card-head { margin-top: var(--space-8); }
.sapo-group-detail { margin-top: var(--space-2); border-top: 1px solid var(--line); }
.sapo-group-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-6); padding: var(--space-7) var(--space-8); background: var(--surface-2); }
.sapo-group-detail-head h3 { margin: 0; font-size: 1rem; }
.sapo-group-detail-head span { color: var(--muted); font-size: .85rem; text-align: right; }
.sapo-carrier-list { display: grid; }
.sapo-carrier-detail { border-top: 1px solid var(--line); }
.sapo-carrier-detail:first-child { border-top: 0; }
.sapo-carrier-detail > summary { display: flex; align-items: center; justify-content: space-between; gap: var(--space-7); padding: var(--space-6) var(--space-8); cursor: pointer; list-style: none; }
.sapo-carrier-detail > summary::-webkit-details-marker { display: none; }
.sapo-carrier-detail > summary > span:first-child { display: grid; gap: var(--space-1); }
.sapo-carrier-detail > summary small { color: var(--muted); }
.sapo-carrier-detail[open] > summary { background: var(--primary-soft); }
.sapo-carrier-summary { color: var(--muted); font-size: .875rem; text-align: right; }
.sapo-carrier-summary b { color: var(--text); }
.sapo-operational-card-wide { grid-column: 1 / -1; }
.sapo-operational-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-8); }
.sapo-operational-card-head h2 { margin: var(--space-2) 0 0; font-size: 1.2rem; }
.sapo-operational-card-head > strong { color: var(--primary); font-size: 2rem; line-height: 1; }
.sapo-operational-step { color: var(--muted); font-size: .8rem; font-weight: 700; }
.sapo-operational-card > p { margin: 0; color: var(--muted); }
.sapo-operational-card > a { margin-top: auto; color: var(--primary); font-weight: 600; }
.sapo-operational-note { margin: var(--space-6) 0 0; color: var(--muted); font-size: .875rem; }
/* .page-body đã là grid có gap giữa các section; margin-top riêng chỉ làm khoảng cách nhân đôi. */
.sapo-operational-actions { margin-top: 0; }
.sapo-operational-actions .panel-head { margin-bottom: var(--space-6); }
/* Thẻ việc: 8 thẻ (7 nhóm + 1 cảnh báo đối soát) xếp lưới 4 cột thành hai
   hàng tròn trịa. Mỗi thẻ cùng một khung: tiêu đề + số trên một dòng, dòng
   phụ chỉ liệt kê mục KHÁC 0, tiền ghim đáy — mô tả dài chuyển vào tooltip. */
.sapo-operational-action-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); }
.sapo-action-card { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-6) var(--space-7); }
.sapo-action-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); }
.sapo-action-card-head h3 { margin: 0; font-size: .95rem; line-height: 1.35; }
.sapo-action-card-head strong { color: var(--primary); font-size: 1.55rem; line-height: 1; font-variant-numeric: tabular-nums; }
.sapo-action-parts { color: var(--muted); font-size: .8rem; line-height: 1.5; }
.sapo-action-card .sapo-action-money { margin-top: auto; padding-top: var(--space-2); }
.sapo-action-card-warning { border-color: var(--warning-line); background: var(--warning-soft); }
.sapo-action-card-danger { border-color: var(--danger-line); background: var(--danger-soft); }
.sapo-action-card-alert { border-color: var(--warning-line); background: var(--warning-soft); }
.sapo-action-card-alert .sapo-action-card-head strong { color: #8A4A06; }
.sapo-operational-breakdowns { margin-top: 0; }
.sapo-operational-breakdowns > .panel-head { margin-bottom: var(--space-6); }
.sapo-breakdown-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
.sapo-breakdown-card { min-width: 0; padding: 0; overflow: hidden; }
.sapo-breakdown-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-6); padding: var(--space-7) var(--space-8); border-bottom: 1px solid var(--line); }
.sapo-breakdown-head h3 { margin: 0; font-size: 1rem; }
.sapo-breakdown-head p { margin: var(--space-2) 0 0; color: var(--muted); font-size: .85rem; }
.sapo-breakdown-head > strong { color: var(--primary); font-size: 1.6rem; line-height: 1; }
.sapo-breakdown-table { min-width: 560px; }
.sapo-breakdown-table th:not(:first-child), .sapo-breakdown-table td:not(:first-child) { text-align: right; }
.sapo-marketplace-card { margin-top: var(--space-6); padding: 0; overflow: hidden; }
.sapo-marketplace-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); padding: var(--space-8); }
.sapo-marketplace-item { padding: var(--space-7); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); }
.sapo-marketplace-item > div { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); }
.sapo-marketplace-item span { font-weight: 700; }
.sapo-marketplace-item strong { color: var(--primary); font-size: 1.7rem; }
.sapo-marketplace-item p { margin: var(--space-4) 0; color: var(--text-2); }
.sapo-marketplace-item small { color: var(--muted); }
.sapo-operational-courier-lines { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4) var(--space-8); }

/* Báo cáo vận hành (bản đọc-10-giây) + trang Đơn cần xử lý */
.sapo-operational-headline { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-6); margin-bottom: 0; }
.sapo-headline-card { display: flex; flex-direction: column; gap: var(--space-2); text-decoration: none; color: inherit; }
.sapo-headline-card span { color: var(--muted); font-weight: 600; }
.sapo-headline-card strong { color: var(--primary); font-size: 2rem; line-height: 1.1; }
.sapo-headline-card small { color: var(--muted); }
a.sapo-headline-card:hover { border-color: var(--primary-line); }
.sapo-headline-card-warning { border-color: var(--warning-line); background: var(--warning-soft); }
.sapo-headline-card-warning strong { color: #8A4A06; }
.sapo-headline-card-success { border-color: var(--success-line, #B7E4C7); background: var(--success-soft, #F0FBF4); }
.sapo-headline-card-success strong { color: #2f9e44; }
.sapo-headline-card .sapo-headline-money { font-size: 1.45rem; line-height: 1.4; font-variant-numeric: tabular-nums; }
.sapo-action-money { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--text-2); }
a.sapo-action-card { text-decoration: none; color: inherit; }
a.sapo-action-card:hover { border-color: var(--primary-line); }
.sapo-action-card-empty { opacity: .55; }
a.sapo-operational-alert { text-decoration: none; color: inherit; }
.sapo-flow-card { padding: 0; margin-bottom: var(--space-6); }
.sapo-flow-table { width: 100%; }
/* .table-wrap gốc là overflow hidden; các bảng trong phần này rộng hơn màn
   điện thoại (min-width 560px) nên phải cuộn ngang được thay vì bị cắt cụt. */
.sapo-operational-breakdowns .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* .page-body là grid một cột: item mặc định không được co dưới min-content,
   nên bảng 560px trong section này từng banh CẢ TRANG ra 580px trên điện
   thoại — mọi section khác rộng theo. min-width: 0 trả bảng về cuộn trong
   .table-wrap thay vì kéo giãn trang. */
.sapo-operational-breakdowns { min-width: 0; }
.sapo-flow-detail { border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); margin-bottom: var(--space-6); overflow: hidden; }
.sapo-carrier-list-card { padding: 0; overflow: hidden; }
.sapo-carrier-list-head { border-bottom: 1px solid var(--line); }
.sapo-carrier-link { display: block; padding: var(--space-4) var(--space-8) var(--space-6); color: var(--primary); font-weight: 600; }
/* Tab việc: chip một kiểu, số đếm là huy hiệu; tab đang chọn tô đặc. */
.sapo-task-tabs { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.sapo-task-tab { display: inline-flex; align-items: center; gap: var(--space-3); padding: 5px 12px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); text-decoration: none; color: var(--text-2); font-size: 13px; font-weight: 600; }
.sapo-task-tab b { min-width: 22px; padding: 0 7px; border-radius: 999px; background: var(--surface-2); color: var(--text); font-variant-numeric: tabular-nums; text-align: center; font-size: 12px; line-height: 1.7; }
.sapo-task-tab:hover { border-color: var(--primary); color: var(--primary); }
.sapo-task-tab.is-active { border-color: var(--primary); background: var(--primary); color: #fff; }
.sapo-task-tab.is-active b { background: rgba(255, 255, 255, .25); color: #fff; }
.sapo-task-tab.is-empty { opacity: .5; }
/* Bộ lọc: một hàng thẳng, ô đối soát là nút bật/tắt cùng cỡ với các ô khác. */
.sapo-dcx-filter .field > input[type="month"] { width: 160px; }
.sapo-dcx-filter .field > select { min-width: 170px; }
.sapo-dcx-toggle { display: inline-flex; align-items: center; gap: var(--space-3); margin-bottom: 1px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); font-size: 13px; font-weight: 600; color: var(--text-2); cursor: pointer; white-space: nowrap; }
.sapo-dcx-toggle input { margin: 0; }
.sapo-dcx-toggle:has(input:checked) { border-color: var(--warning-line); background: var(--warning-soft); color: #8A4A06; }
/* Dòng tổng trên bảng: số bên trái, mốc đồng bộ mờ bên phải. */
.sapo-dcx-statline { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4) var(--space-8); flex-wrap: wrap; padding: var(--space-5) var(--space-9); border-bottom: 1px solid var(--line); }
.sapo-dcx-stats { margin: 0; font-size: .9rem; }
.sapo-dcx-stats small { color: var(--muted); font-weight: 400; }
.sapo-dcx-freshness { margin: 0; color: var(--muted); font-size: .8rem; }
/* Ô gộp hai tầng: dòng chính + dòng phụ mờ. */
.sapo-dcx-sub { margin-top: 2px; color: var(--muted); font-size: 12px; }
.sapo-dcx-warn { color: #B45309; font-weight: 600; }
.sapo-dcx-dim { color: var(--muted); }
.sapo-dcx-money { font-variant-numeric: tabular-nums; }
.sapo-dcx-paid { color: #2f9e44; font-weight: 600; }
.sapo-dcx-son { font-weight: 600; text-decoration: none; color: var(--primary); white-space: nowrap; }
.sapo-dcx-son:hover { text-decoration: underline; }
.sapo-days-pill { display: inline-block; padding: 0 var(--space-3); border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); font-weight: 600; white-space: nowrap; }
.sapo-days-pill-warning { background: var(--warning-soft); border-color: var(--warning-line); }
.sapo-days-pill-danger { background: var(--danger-soft); border-color: var(--danger-line); }
/* 8 cột gộp thay cho 12 cột cũ — bảng khóa layout để vừa màn 1280px,
   cột Khách hàng co giãn, phần dài cắt bằng ellipsis thay vì đẩy tràn ngang. */
.sapo-action-orders-table { table-layout: fixed; width: 100%; min-width: 960px; }
.sapo-action-orders-table td { vertical-align: top; overflow: hidden; }
.sapo-action-orders-table th:nth-child(1) { width: 92px; }
.sapo-action-orders-table th:nth-child(2) { width: 112px; }
.sapo-action-orders-table th:nth-child(4) { width: 156px; }
.sapo-action-orders-table th:nth-child(5) { width: 158px; }
.sapo-action-orders-table th:nth-child(6) { width: 122px; }
.sapo-action-orders-table th:nth-child(7) { width: 216px; }
.sapo-action-orders-table th:nth-child(8) { width: 96px; }
.sapo-action-orders-table .truncate-text { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sapo-action-orders-table .sapo-dcx-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sapo-action-orders-table th.col-money, .sapo-action-orders-table td.col-money { text-align: right; }
@media (max-width: 900px) { .sapo-operational-headline { grid-template-columns: 1fr; } }
/* Từ ≤1024px .responsive-table chuyển sang dạng thẻ xếp dọc; min-width của
   bảng desktop mà giữ lại thì cả chồng thẻ bị ép rộng 1180px và tràn ngang. */
@media (max-width: 1024px) {
  .sapo-action-orders-table { min-width: 0; width: 100%; }
  /* Ở dạng thẻ mọi ô canh trái cho đồng nhất. */
  .sapo-action-orders-table td.col-money { text-align: left; }
}

@media (max-width: 1024px) {
  .sapo-operational-action-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sapo-breakdown-grid { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
  .sapo-operational-grid, .sapo-operational-action-grid, .sapo-marketplace-grid { grid-template-columns: 1fr; }
  .sapo-operational-card-wide { grid-column: auto; }
  .sapo-operational-courier-lines { grid-template-columns: 1fr; }
  .sapo-operational-alert { align-items: flex-start; }
  .sapo-group-detail-head, .sapo-carrier-detail > summary { align-items: flex-start; flex-direction: column; }
  .sapo-group-detail-head span, .sapo-carrier-summary { text-align: left; }
}

@media (max-width: 560px) {
  .sapo-bank-detail-grid { grid-template-columns: 1fr; }
}


/* ==========================================================================
   Ở CHẾ ĐỘ THẺ, BỎ MỌI RÀNG BUỘC RỘNG CỘT CỦA BẢNG DESKTOP

   Từ ≤1024px, `.responsive-table` chuyển mỗi <td> thành một khối full-width
   (chế độ thẻ xếp dọc). Nhưng các quy tắc rộng cột dành cho bảng desktop —
   `.col-provider{max-width:150px}`, `.col-code{max-width:130px}`,
   `.col-note-short{width:120px}`, `.wholesale-transaction-col-*{width:…}` … —
   vẫn còn hiệu lực, nên vài ô bị cắt cụt còn 130–150px giữa một thẻ rộng
   370px. Biểu hiện: đường kẻ ngăn cách trong thẻ dài ngắn lô nhô.

   Rộng cột chỉ có nghĩa khi còn là bảng; ở dạng thẻ thì phải bỏ hết. Đã có
   tiền lệ xử lý lẻ cho `.voucher-file-cell` và `.voucher-shop-cell`; đây là
   bản áp cho toàn bộ.
   ========================================================================== */
@media (max-width: 1024px) {
  /* `td[class]` chứ không phải `td`: các quy tắc cần ghi đè có dạng
     `.sapo-reconcile-table .col-provider` — hai class, tức đặc hiệu (0,2,0),
     trong khi `.responsive-table td` chỉ là (0,1,1) nên thua. Thêm `[class]`
     (tính ngang một class) đưa selector này lên (0,2,1) và thắng, mà vẫn chỉ
     chạm đúng những ô CÓ class rộng cột. */
  .responsive-table td[class],
  /* Hai trang Tổng quan khoá rộng cột bằng `[data-column="…"]` lẫn bằng class,
     và bản `.is-compact` nâng cả hai lên (0,3,0) — nên cần (0,3,1) mới với
     tới. Bốn selector này phủ đủ bốn dạng đang tồn tại. */
  .responsive-table td[data-column],
  .responsive-table.is-compact td[data-column],
  .responsive-table.is-compact td[class] {
    width: auto;
    min-width: 0;
    max-width: none;
  }
}

/* Số dòng còn phải làm: huy hiệu trên thanh đơn vị vận chuyển và cột cùng nghĩa
   trong bảng phiếu. Nguồn số: app/modules/reconciliation_voucher_progress.py */
.carrier-tab-remaining {
  display: inline-block;
  margin-left: .4em;
  padding: 0 .45em;
  border-radius: 999px;
  background: #d9480f;
  color: #fff;
  font-size: .78em;
  font-weight: 600;
  line-height: 1.5;
}
.page-tab.active .carrier-tab-remaining { background: #fff; color: #d9480f; }
.voucher-remaining-pending { color: #d9480f; font-weight: 600; }
.voucher-remaining-done { color: #2f9e44; font-weight: 600; }

/* --- Tên gọi chuẩn của phiếu -------------------------------------------
   Tên chuẩn là thứ đọc trước; tên file gốc tụt xuống dòng phụ nhưng vẫn phải
   đọc được vì đó là căn cứ đối chiếu với chứng từ đã tải lên.
   ======================================================================== */
.voucher-name { display: block; line-height: 1.35; }
.voucher-source-file {
  display: block;
  margin-top: 2px;
  color: #868e96;
  font-size: .82em;
  line-height: 1.35;
  word-break: break-all;
}
.page-header .voucher-source-file { margin-top: 0; }

/* Ô lý do và nút duyệt ngoại lệ COD nằm cùng một hàng bảng, phải gọn để không
   đẩy bảng tràn ngang. */
.cod-exception-form { display: flex; gap: var(--space-3, 8px); align-items: center; flex-wrap: wrap; }
.cod-exception-form input[type="text"] { min-width: 180px; flex: 1 1 180px; }

/* --- Ba khung thao tác đối soát --------------------------------------------
   Mỗi nền tảng một khung, luôn hiện, không nấp sau bộ lọc dòng nữa. Khung nào
   đang có kết quả thì chiếm trọn hàng vì bảng kết quả cần bề ngang; các khung
   còn lại tự xếp lại quanh nó.
   ========================================================================== */
.voucher-action-grid {
  display: grid;
  /* Mặc định chia đôi: khi có khung trải rộng (is-wide chiếm trọn hàng đầu),
     auto-fit sẽ đẻ 4-5 cột ảo vì hàng đầu lấp đầy mọi track — hai khung còn lại
     bị ép vào cột 300px đứng cạnh khoảng trống lớn. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5, 16px);
  margin: var(--space-5, 16px) 0;
  align-items: start;
}
/* Không khung nào trải rộng thì ba khung vẫn đứng chung một hàng như cũ. */
.voucher-action-grid:not(:has(.voucher-action-card.is-wide)) {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.voucher-action-card {
  border: 1px solid #dee2e6;
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
}
.voucher-action-card.is-wide { grid-column: 1 / -1; }
.voucher-action-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3, 8px);
  padding: var(--space-3, 8px) var(--space-5, 16px);
  min-height: 48px;
  border-bottom: 1px solid #f1f3f5;
  background: #f8f9fa;
}
.voucher-action-card-head h4 { margin: 0; font-size: 1rem; }
.voucher-action-card-title { display: flex; align-items: baseline; gap: var(--space-3, 8px); min-width: 0; }
.voucher-action-card-count { color: #868e96; font-size: .85em; white-space: nowrap; }
/* Nút tiện ích (chỉ đọc / kiểm tra) sống trên header của khung. Chúng phải là
   nút gọn tự co theo nhãn — quy tắc nút full-width bên dưới chỉ dành cho thân
   khung, nơi các nút ghi dữ liệu cần ngang hàng nhau giữa ba khung. */
.voucher-card-head-actions {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-3, 8px); justify-content: flex-end;
}
.voucher-card-head-actions form { margin: 0; }
.voucher-card-head-actions .btn {
  width: auto; min-height: 30px; padding: var(--space-2, 6px) var(--space-5, 16px);
  font-size: 12px; white-space: nowrap;
}
/* Dòng ghi chú lần kiểm tra: chữ phụ, không viền không nền — trước đây mượn
   .voucher-inline-note (có viền dưới) nên trông như một thanh lạc chỗ. */
.voucher-check-meta {
  margin: 0 0 var(--space-4, 12px);
  color: var(--muted); font-size: .8rem; line-height: 1.55;
}
.voucher-action-card-body { padding: var(--space-5, 16px); }
/* Các đoạn giải thích trong khung là chữ phụ, đừng để chúng át nút bấm. */
.voucher-action-card-body > p { margin: 0 0 var(--space-4, 12px); color: #495057; font-size: .9em; }
.voucher-action-card-body > form { margin: 0 0 var(--space-4, 12px); }
.voucher-action-card-body > form:last-child,
.voucher-action-card-body > p:last-child { margin-bottom: 0; }
/* Tiêu đề phụ trong khung: nhỏ hơn tên khung, không được to bằng h4 mặc định. */
.voucher-action-card-body h5 {
  margin: 0 0 var(--space-2, 6px); color: var(--text-2);
  font-size: .82rem; font-weight: 600; letter-spacing: .01em;
}

/* Số liệu tóm tắt. Lớp này dùng ở cả khung Sapo lẫn Pancake nhưng chưa bao giờ
   có CSS, nên các ô dồn thành một khối chữ liền: "141Dòng Sapo đã kiểm tra". */
.voucher-summary-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 1px; margin: 0 0 var(--space-4, 12px);
  background: var(--line-soft); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden;
}
.voucher-summary-grid > div {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 12px; background: var(--surface);
}
.voucher-summary-grid strong {
  color: var(--text); font-size: 1.02rem; font-weight: 600;
  line-height: 1.25; font-variant-numeric: tabular-nums;
}
.voucher-summary-grid span { color: var(--muted); font-size: .76rem; line-height: 1.35; }

/* Kết quả chính của lần kiểm tra: một tỉ lệ đọc được ngay từ xa. */
.voucher-result-headline {
  margin: 0 0 var(--space-3, 8px); padding: 8px 14px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.voucher-result-figure {
  display: flex; align-items: baseline; gap: 6px; margin: 0;
  font-variant-numeric: tabular-nums;
}
.voucher-result-figure strong { color: var(--text); font-size: 1.3rem; font-weight: 650; line-height: 1.1; }
.voucher-result-figure span { color: var(--muted); font-size: .84rem; }
.voucher-result-caption { margin: 2px 0 0; color: var(--text-2); font-size: .82rem; }
.voucher-result-bar {
  margin-top: 6px; height: 4px; border-radius: 999px;
  background: var(--line-strong); overflow: hidden;
}
.voucher-result-bar > span { display: block; height: 100%; background: var(--primary); border-radius: inherit; }

/* Hai hàng kết quả lấp kín bề ngang khung thay vì dồn cục sang trái:
   hàng 1 — tỉ lệ chính + ba ô số phụ trợ đứng chung một dải;
   hàng 2 — cột lý do bên trái, hai ô hành động lấp phần còn lại.
   Trong khung hẹp (chưa có kết quả thì không render hai hàng này) flex-wrap
   tự xếp chồng nên không cần media query riêng. */
/* Trang Lịch sử đối soát: dòng phụ và dòng lỗi trong ô bảng. */
.voucher-history-sub { margin-top: 2px; color: var(--muted); font-size: .74rem; white-space: nowrap; }
.voucher-history-error {
  margin-top: 3px; max-width: 460px;
  color: #8A4A06; font-size: .75rem; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 3; -webkit-box-orient: vertical;
}

/* Lệch COD hiện ngay trên dòng nguồn: ghi chú nhỏ dưới số COD + form duyệt
   ngoại lệ trong ô Thao tác của chính dòng đó (bảng riêng trong khung Sapo đã bỏ). */
.voucher-cod-mismatch-note {
  display: block; margin-top: 2px;
  color: #8A4A06; font-size: .74rem; font-weight: 600; line-height: 1.35;
  white-space: nowrap;
}
/* Lý do "chưa vào lô" trong cột Đối soát thường là câu dài — cho xuống dòng,
   khác với ghi chú lệch COD ngắn ở cột tiền vẫn giữ một dòng. */
.voucher-table td[data-label="Trạng thái đối soát nền tảng"] .voucher-cod-mismatch-note {
  white-space: normal; max-width: 240px;
}
/* Ghi chú lặng (không phải cảnh báo): thông tin nên biết nhưng không phải việc
   phải làm — ví dụ Sapo ghi ĐVVC khác phiếu nhưng dòng vẫn chạy bình thường. */
.voucher-row-note { display: block; margin-top: 2px; color: var(--muted); font-size: .72rem; line-height: 1.35; }
.voucher-row-actions form { margin: 0; }
.voucher-row-actions form + form { margin-top: var(--space-2, 6px); }
.voucher-row-actions .status-pill { margin-bottom: var(--space-2, 6px); }
.voucher-row-actions .cod-exception-form input[type="text"] { min-width: 140px; flex: 1 1 140px; }
.voucher-result-columns {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: var(--space-4, 12px) var(--space-5, 16px); margin: 0 0 var(--space-4, 12px);
}
.voucher-result-columns .voucher-reason-list { flex: 1 1 380px; min-width: 0; margin: 0; }
.voucher-result-columns .voucher-reason-list dl > div { padding: 5px 12px; }
/* Cụm nút đứng cạnh cột lý do, tự đẩy về mép phải. Phải cho phép co (flex-shrink)
   và min-width 0: khung hẹp mà cụm giữ nguyên bề ngang nội dung thì nút tràn mép
   khung thay vì xuống dòng. */
.voucher-result-columns .voucher-action-stack { flex: 0 1 auto; min-width: 0; margin-left: auto; }
.voucher-run-state { margin: 0; align-self: center; }

/* Lý do bị loại: trước đây nối thành một câu dài ngăn bằng dấu chấm phẩy. */
.voucher-reason-list { margin: 0 0 var(--space-4, 12px); }
.voucher-reason-list-head { margin: 0 0 6px; color: var(--text-2); font-size: .82rem; font-weight: 600; }
.voucher-reason-list dl {
  margin: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden;
}
.voucher-reason-list dl > div {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 7px 12px; border-top: 1px solid var(--line-soft); background: var(--surface);
}
.voucher-reason-list dl > div:first-child { border-top: 0; }
.voucher-reason-list dt { margin: 0; color: var(--text-2); font-size: .8rem; line-height: 1.4; }
.voucher-reason-list dd {
  margin: 0; color: var(--text); font-size: .84rem; font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Ô chọn rà lại cả dòng đã xong: là lựa chọn phụ, đứng cạnh chữ giải thích. */
.voucher-action-recheck {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 var(--space-3, 8px); color: #495057; font-size: .9em; cursor: pointer;
}
.voucher-action-recheck input { width: 16px; height: 16px; margin: 0; accent-color: var(--primary); }

/* Nút trong ba khung Sapo / Pancake / Web Order phải bằng nhau. Trước đây mỗi
   nút tự co theo độ dài nhãn nên "Cập nhật Sapo" ngắn tũn nằm cạnh "Kiểm tra
   đơn Sapo đủ điều kiện" dài ngoẵng, và ba khung so le nhau theo chiều ngang.
   Cho tất cả chiếm trọn bề ngang khung: đều nhau, và bấm dễ hơn.

   Quy ước màu: nút đậm (btn-primary) chỉ dành cho thao tác THẬT SỰ ghi dữ liệu
   ra Sapo/Pancake; nút nhạt (btn-secondary) cho việc đọc và kiểm tra. Nhìn màu
   là biết bấm vào có sửa gì bên ngoài hay không. */
.voucher-action-card-body .btn {
  width: 100%;
  white-space: normal;
  text-align: center;
}
/* Nút trong bảng nhỏ bên trong khung thì không, chúng nằm cạnh ô nhập. */
.voucher-action-card-body table .btn,
.voucher-action-card-body .cod-exception-form .btn { width: auto; }

@media (max-width: 640px) {
  .voucher-action-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Tra vận đơn TNH — /tra-van-don-tnh (thêm 2026-08-30)

   Bản đầu dùng hai bảng chồng nhau cho mỗi đơn: một bảng 6 cột chỉ có ĐÚNG MỘT
   dòng cho thông tin đơn, và một bảng nữa cho hành trình. Bảng sinh ra để liệt
   kê nhiều dòng — nhét một dòng vào bảng thì vừa thừa khung vừa khó đọc, trên
   điện thoại còn tệ hơn. Nay: lưới nhãn–giá trị cho thông tin, dòng thời gian
   cho hành trình.

   Toàn bộ dùng token sẵn có, không viết cứng màu hay khoảng cách.
   ========================================================================== */

.tnh-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  margin: var(--space-9) 0 var(--space-8);
  color: var(--muted);
  font-size: 0.9rem;
}
.tnh-summary-strong { color: var(--text); font-weight: 650; }

/* Nhãn trạng thái. KHÔNG dùng lại .chip-alert: lớp đó thuộc bộ lọc chipset,
   nó có .chip-count bên trong và mang ngữ nghĩa "bộ lọc đang bật". */
.tnh-status {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 var(--space-6);
  border-radius: var(--radius-pill);
  background: var(--surface-soft);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 650;
}
.tnh-status-ok {
  background: var(--success-soft);
  box-shadow: inset 0 0 0 1px var(--success-line);
  color: var(--success);
}
.tnh-status-warn {
  background: var(--warning-soft);
  box-shadow: inset 0 0 0 1px var(--warning-line);
  color: var(--warning);
}
.tnh-status-bad {
  background: var(--danger-soft);
  box-shadow: inset 0 0 0 1px var(--danger-line);
  color: var(--danger);
}

/* Shop hiện thành nhãn riêng: một mã có thể thuộc Nhật Quang hoặc Mytrex, và
   người tra cần thấy ngay bằng mắt chứ không phải đọc dòng chữ nhỏ. */
.tnh-shop {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-sm);
  background: var(--primary-soft);
  color: var(--primary-strong);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Vạch màu bên trái để lướt nhanh tìm đơn có vấn đề trong danh sách dài. */
.tnh-card { border-left: 3px solid var(--line-strong); }
.tnh-card-warn { border-left-color: var(--warning); }
.tnh-card-bad { border-left-color: var(--danger); }

.tnh-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
}
.tnh-head-code { margin: 0; font-size: 1.05rem; font-weight: 680; }
.tnh-ids {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-7);
  margin-top: var(--space-4);
  color: var(--muted);
  font-size: 0.83rem;
}

.tnh-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-8);
  margin-top: var(--space-9);
  padding-top: var(--space-8);
  border-top: 1px solid var(--line-soft);
}
.tnh-field-label {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.tnh-field-value { margin-top: var(--space-2); color: var(--text); }
.tnh-field-wide { grid-column: 1 / -1; }
.tnh-money { font-variant-numeric: tabular-nums; font-weight: 650; }

/* Dòng thời gian, mốc mới nhất ở trên cùng. */
.tnh-timeline {
  margin: var(--space-9) 0 0;
  padding: var(--space-8) 0 0;
  border-top: 1px solid var(--line-soft);
  list-style: none;
}
.tnh-step {
  position: relative;
  margin-left: var(--space-3);
  padding: 0 0 var(--space-8) var(--space-9);
  border-left: 2px solid var(--line);
}
.tnh-step:last-child { padding-bottom: 0; border-left-color: transparent; }
.tnh-step::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 3px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
}
.tnh-step-now::before {
  background: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
.tnh-step-when {
  color: var(--muted);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}
.tnh-step-label { color: var(--text); font-weight: 600; }
.tnh-step-note { color: var(--muted); font-size: 0.82rem; }

/* ==========================================================================
   TỔNG QUAN — thẻ hàng chờ và khối theo vai (03/09/2026)

   Dựng cho dashboard_hub.html khi trang này chuyển từ "hai thẻ doanh thu cho
   Admin" sang "một trang cho mọi vai". Chỉ dùng biến màu ngữ nghĩa đã có ở
   trên; không pha sắc mới — đúng lý do mà khối biến đó tồn tại.
   ========================================================================== */

/* Nhịp dọc và tiêu đề section: khai báo DUY NHẤT ở đây. Trước 03/09/2026 hai
   quy tắc này được viết hai lần cách nhau hơn 200 dòng, bản sau âm thầm đè bản
   trước — đọc file không thể biết cái nào đang có hiệu lực. */
.dash-section + .dash-section { margin-top: var(--space-12); }
.dash-section-title {
  margin: 0 0 var(--space-6);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}
.dash-hint {
  margin: 0 0 var(--space-6);
  color: var(--muted);
  font-size: 14px;
}
/* Tiêu đề khối kèm con số tổng ở mép phải. Thay cho cách cũ là dựng hẳn một ô
   trên dải dẫn cho cùng con số đó: tổng và chi tiết của cùng một thứ thì nằm
   chung một khối, không tách làm hai. */
.dash-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin: 0 0 var(--space-6);
}
.dash-section-head .dash-section-title { margin: 0; }
.dash-section-total {
  font-size: 13px;
  color: var(--muted);
}
.dash-section-total strong {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.dash-section-total i { font-style: normal; }
.dash-section-total.is-late strong { color: var(--danger); }

/* Bảng chi phí cắt đôi theo chiều dọc rồi đặt cạnh nhau — 10 bộ phận xếp một
   cột chiếm hơn một phần ba chiều cao trang trong khi hai phần ba bề ngang bỏ
   trống. Dưới 900px quay lại một cột, để `.responsive-table` stack như cũ. */
.cost-split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
  align-items: start;
}
@media (max-width: 900px) {
  .cost-split { grid-template-columns: 1fr; }
}

/* Dòng Tổng dưới bảng chi phí: dài hết bề ngang, nặng hơn một dòng thường để
   mắt biết đây là chốt chứ không phải một bộ phận nữa. */
.cost-total {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: var(--space-11);
  flex-wrap: wrap;
  margin-top: var(--space-6);
  padding: var(--space-7) var(--space-9);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.cost-total-label {
  margin-right: auto;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}
.cost-total-cell {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
}
.cost-total-cell i {
  font-style: normal;
  font-size: 12px;
  color: var(--muted);
}
.cost-total-cell strong {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
  .cost-total { justify-content: space-between; }
  .cost-total-label { flex-basis: 100%; margin-bottom: var(--space-3); }
}

.queue-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: var(--space-6);
}

/* Thẻ hàng chờ vừa là số liệu vừa là liên kết. Dùng chung một lớp cho cả <a>
   và <div> để thẻ không-bấm-được (vd Lệnh chi, mở ở app khác) trông giống hệt
   thẻ bấm được — chỉ khác con trỏ và hiệu ứng di chuột. */
.queue-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  /* Dải màu trạng thái nằm trên đỉnh (::before), giống thẻ dải dẫn — nên viền
     trái để mảnh như ba cạnh còn lại, và padding trên chừa chỗ cho dải. */
  padding: var(--space-6) var(--space-9) var(--space-7);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  color: inherit;
  text-decoration: none;
  position: relative;
  overflow: hidden;
}
a.queue-card:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-soft);
}
a.queue-card:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.queue-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  line-height: 1.3;
  /* Chừa sẵn hai dòng. Nhãn dài ("Sapo Bank cần kiểm tra vào tiền") xuống dòng
     còn nhãn ngắn thì không, nên con số của các thẻ trong cùng một hàng nằm ở
     những độ cao khác nhau — nhìn như xếp ẩu. Chừa chỗ cố định thì mọi con số
     nằm trên cùng một đường. */
  min-height: calc(2 * 1.3em);
}
.queue-count {
  font-size: 22px;
  line-height: 1.05;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.queue-age {
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Ba mức: `is-open` = còn việc phải làm, `is-warn` = đã duyệt nhưng chưa xong,
   `is-note` = số tham khảo, không phải việc. Số 0 thì không tô gì — thẻ im
   lặng khi không có việc là chủ ý. */
.queue-card.is-open .queue-count { color: var(--primary); }
.queue-card.is-warn .queue-count { color: var(--warning); }

/* Tuổi hàng chờ quá một tuần: đây là thứ trang hàng chờ hiện KHÔNG nói, và là
   lý do một giao dịch nằm 29 ngày mà không ai thấy. */
.queue-age.is-late {
  color: var(--danger);
  font-weight: 600;
}

/* Chỗ để dành cho khối bấm công. Cố ý nhạt hơn thẻ thật để không ai nhầm nó
   là chức năng đã chạy. */
.slot-reserved {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-7);
  padding: var(--space-9) var(--space-10);
  background: var(--surface-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md);
}
.slot-reserved strong { font-size: 15px; }
.slot-reserved p {
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: 14px;
}

@media (max-width: 640px) {
  .queue-grid { grid-template-columns: 1fr; }
  .slot-reserved { flex-direction: column; align-items: stretch; }
}

/* Tổng quan — khối doanh số theo cá nhân và team (03/09/2026).
   Dùng lại .queue-label / .queue-age của thẻ hàng chờ để hai nhóm thẻ trên
   cùng một trang có chung nhịp chữ; chỉ con số là to hơn vì đây là tiền. */
.sales-grid {
  display: grid;
  /* Trần 460px để thẻ không bị kéo dài hết chiều ngang khi trong lưới chỉ còn
     MỘT thẻ — con số nằm lọt bên trái một thẻ dài 1600px trông như trang lỗi. */
  grid-template-columns: repeat(auto-fit, minmax(280px, 460px));
  justify-content: start;
  gap: var(--space-6);
}
.sales-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-9);
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
}
.sales-card.is-mine { border-left-color: var(--primary); }
.sales-value {
  font-size: 20px;
  line-height: 1.2;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-4);
}
.sales-todo {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-2);
}
.sales-table-wrap { margin-top: var(--space-9); }

@media (max-width: 640px) {
  .sales-grid { grid-template-columns: 1fr; }
}
.identity-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
}
.identity-form select { min-width: 240px; }
/* Số phiếu đứng cạnh số tiền trong bảng chi phí — nhỏ và nhạt để không tranh
   chỗ với con số tiền, vẫn cho biết tiền đó gồm mấy phiếu. */
.cost-count {
  display: block;
  color: var(--muted);
  font-size: 12px;
  font-weight: 400;
}
/* Chi tiết giao hàng trong bảng doanh số: dùng lại pill .sapo-status của các
   trang Sapo/Pancake nên trạng thái giống nhau hiện cùng một màu ở mọi trang. */
.delivery-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ==========================================================================
   TỔNG QUAN — dải dẫn và nhịp phân cấp (03/09/2026)

   Trang trước đó là một dải phẳng cao 5400px: mọi tiêu đề cùng cỡ, cùng màu
   xám, cùng sức nặng — không có gì dẫn mắt, và con số quan trọng nhất nằm lọt
   trong một dòng bảng ở giữa trang. Khối dưới đây thêm đúng hai bậc phân cấp
   (dải dẫn → section) mà không đổi bảng màu hay bán kính đã chốt trong
   docs/ui-ux/DESIGN.md.
   ========================================================================== */

.hero-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-6);
  margin-bottom: var(--space-11);
}

.hero-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-9) var(--space-10);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  color: inherit;
  text-decoration: none;
  position: relative;
  overflow: hidden;
}
/* Dải màu mỏng trên đỉnh thay cho viền trái: ở cỡ chữ này viền trái bị con số
   lấn át, còn dải trên đọc được ngay cả khi liếc nhanh. */
.hero-tile::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--line-strong);
}
.hero-tile.is-primary::before { background: var(--primary); }
.hero-tile.is-warn::before { background: var(--warning); }
.hero-tile.is-late::before { background: var(--danger); }

a.hero-tile:hover { box-shadow: var(--shadow-raise); }
a.hero-tile:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.hero-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.01em;
}
.hero-value {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-size: 23px;
  line-height: 1.1;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
}
.hero-unit { font-size: 15px; font-weight: 600; color: var(--text-2); }
.hero-sub { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.hero-tile.is-late .hero-sub { color: var(--danger); font-weight: 600; }


.queue-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--line-strong);
}
.queue-card.is-open::before { background: var(--primary); }
.queue-card.is-warn::before { background: var(--warning); }
.queue-card.is-note::before { background: var(--line-strong); }

/* Bảng trên Tổng quan: siết chiều cao dòng. Bảng chi phí 10 dòng ở giãn cách
   mặc định chiếm gần nửa màn hình cho thứ chỉ cần liếc qua. */
.dash-section .table-wrap td,
.dash-section .table-wrap th { padding-top: var(--space-5); padding-bottom: var(--space-5); }

/* Thanh tỉ trọng trong bảng chi phí: xếp hạng bằng mắt nhanh hơn đọc 10 con
   số. Vẽ bằng chính chiều rộng ô nên không cần thư viện biểu đồ. */
.cost-bar {
  display: block;
  height: 4px;
  margin-top: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--primary-line);
  min-width: 2px;
}
.hero-tile .sales-todo { margin-top: var(--space-2); }

/* Bảng dày cột trên màn hẹp: bỏ bớt cột phụ thay vì để mỗi hàng xếp thành 8
   dòng. Bảng doanh số 8 cột × 4 hàng biến trang giám đốc thành 15.000px trên
   điện thoại — vẫn đọc được, nhưng phải cuộn qua ba màn hình mới hết một bảng.
   Bốn cột giữ lại là bốn cột trả lời được câu "tháng này thế nào, còn gì tồn". */
@media (max-width: 900px) {
  .dash-section .responsive-table td[data-label="Hôm nay"],
  .dash-section .responsive-table td[data-label="Cùng kỳ tháng trước"],
  .dash-section .responsive-table td[data-label="Giao hàng tháng này"],
  .dash-section .responsive-table td[data-label="Chưa đối soát"] {
    display: none;
  }
  /* Bảng chi phí: giữ đủ hai tháng vì so sánh giữa chúng chính là nội dung. */
  .dash-section .cost-bar { display: none; }
}

/* Payment Control — mục duy nhất trong menu dẫn RA KHỎI quantri sang một app
   khác, nên là mục duy nhất màu xanh. Mọi mục còn lại là điều hướng nội bộ và
   dùng sắc chàm.

   VÌ SAO KHÔNG DÙNG THẲNG var(--accent) (#0B7268): nền sidebar là mực gần đen
   (#14161C), sắc lục đậm đó gần như không đọc được trên nền ấy. Giá trị dưới
   đây là chính --accent kéo sáng lên cho đủ tương phản, giữ nguyên tông lục-lam
   của bảng màu chứ không thêm màu mới. */
.nav-item-external {
  color: #4FBFA9;
  font-weight: 600;
}
.nav-item-external .nav-icon { opacity: 1; color: #4FBFA9; }
.nav-item-external:hover {
  color: #6FD3BE;
  background: rgba(79, 191, 169, 0.10);
}
.nav-item-external:hover .nav-icon { color: #6FD3BE; }
.nav-item-external:focus-visible {
  outline: 2px solid #4FBFA9;
  outline-offset: -2px;
}

/* ==========================================================================
   GIAO DỊCH CHỜ XỬ LÝ — bảng hàng chờ (03/09/2026)

   Trước đó cột "Xử lý" bị đẩy ra ngoài khung và nút bấm bị cắt mất: mã giao
   dịch của bản nhập sao kê dài 64 ký tự chiếm gần nửa chiều ngang. Đã rút gọn
   mã trong template; phần dưới đây ghim cột thao tác lại để dù bảng có phải
   cuộn ngang thì nút vẫn luôn nhìn thấy.
   ========================================================================== */

.cell-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  word-break: break-all;
}
.pending-copy-reference {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  margin-left: 6px;
  width: 27px;
  height: 27px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.pending-copy-reference svg { width: 16px; height: 16px; }
.pending-copy-reference[data-copy-state="success"] { color: #17803d; border-color: #17803d; }
.pending-copy-reference[data-copy-state="error"] { color: #b3261e; border-color: #b3261e; }
.pending-copy-reference:hover, .pending-copy-reference:focus-visible {
  border-color: var(--primary);
}

/* Cột thao tác dính mép phải khi bảng cuộn ngang — đây là cột DUY NHẤT có nút
   bấm, để nó trôi ra ngoài là trang mất chức năng chính. */
.compact-table th.col-action,
.compact-table td.col-action {
  position: sticky;
  right: 0;
  z-index: 1;
  background: var(--surface);
  border-left: 1px solid var(--line);
  min-width: 232px;
}
.compact-table th.col-action { background: var(--surface-3); }

/* Hai form (bổ sung mã / xác nhận không cần mã) xếp dọc, mỗi form một hàng gọn
   thay vì để ô nhập giãn theo chiều ngang còn lại. */
.col-action .inline-form {
  flex-wrap: nowrap;
  gap: var(--space-3);
}
.col-action .inline-form + .inline-form { margin-top: var(--space-4); }
.col-action .inline-form input {
  min-width: 0;
  flex: 1 1 auto;
  width: 100%;
}
.col-action .inline-form .btn { flex: 0 0 auto; white-space: nowrap; }

/* Nội dung chuyển khoản là chuỗi dài nhất còn lại; chặn nó lại để một dòng
   không đẩy cả bảng rộng ra. */
.compact-table td[data-label="Nội dung"] { max-width: 320px; }

@media (max-width: 900px) {
  /* Ở khổ thẻ, bảng không còn cuộn ngang nên sticky vô nghĩa và làm hỏng layout. */
  .compact-table th.col-action,
  .compact-table td.col-action { position: static; min-width: 0; border-left: 0; }
  .compact-table td[data-label="Nội dung"] { max-width: none; }
}

/* ==========================================================================
   .inline-form — MỘT cỡ cho ô nhập và nút đứng cạnh nhau (03/09/2026)

   Đo được trước khi sửa, trong cùng MỘT ô của bảng hàng chờ:
     ô nhập  14px / cao 43px      (quy tắc `input` toàn cục)
     nút     13px / cao 38px      (.btn-compact)
     chữ bảng 12px
   Ba cỡ chữ cạnh nhau, và hai phần tử cùng một hàng lệch nhau 5px chiều cao —
   đây chính là cảm giác "cái to cái nhỏ không đều".

   Gốc: `.btn` có bản thu nhỏ là `.btn-compact`, còn ô nhập thì KHÔNG có bản
   tương ứng nên rơi về cỡ mặc định. Sửa ở component `.inline-form` (dùng ở 8
   template) thay vì ở riêng trang hàng chờ — cùng một cặp ô-nhập-và-nút thì ở
   đâu cũng phải cùng cỡ. -#}
   ========================================================================== */

.inline-form input,
.inline-form select,
.inline-form .btn {
  font-size: 13px;
  min-height: 34px;
  line-height: 1.25;
}
.inline-form input,
.inline-form select {
  padding: var(--space-3) var(--space-6);
}
.inline-form .btn {
  padding: var(--space-3) var(--space-7);
}

/* ==========================================================================
   TỔNG QUAN — một thang chữ duy nhất (03/09/2026)

   Đo được trước khi sửa, trên cùng một trang:
     ô dữ liệu bảng   14px   <- to nhất trang, mà lại là chữ phụ
     tiêu đề bảng     12px   <- nhỏ hơn chính phần thân nó mô tả
     nhãn thẻ         13px
     ghi chú nhỏ      12px
     chữ đậm ô chấm công 15px
   Năm cỡ, và tiêu đề bảng nhỏ hơn thân bảng — đó là cảm giác "cái to cái nhỏ".

   Thang chốt lại còn BA bậc, cộng cỡ hiển thị cho con số lớn:
     12px  ghi chú, pill, đơn vị phụ
     13px  chữ thân, nhãn thẻ, ô dữ liệu bảng
     14px  tiêu đề khối
     22–23px  con số hiển thị

   Chỉ phạm vi `.dash-section` — quy tắc bảng toàn cục (th 12 / td 14) còn dùng
   ở nhiều trang chưa rà, đổi ở đó là đổi mù.
   ========================================================================== */

.dash-section .table-wrap td { font-size: 13px; }
.dash-section .table-wrap th { font-size: 12px; }
.dash-section .dash-hint { font-size: 13px; }

/* Ô chấm công là khối duy nhất còn lệch khỏi thang: chữ đậm 15px và nút cao
   43px trong khi mọi nút khác trên trang cao 34px. */
.slot-reserved strong { font-size: 14px; }
.slot-reserved p { font-size: 13px; }
.slot-reserved .btn {
  font-size: 13px;
  min-height: 34px;
  padding: var(--space-3) var(--space-7);
}

/* ==========================================================================
   THANG CHỮ DÙNG CHUNG TOÀN APP — chốt 03/09/2026

   Rà 24 trang bằng `getComputedStyle` trên trang thật. Kết quả trước khi sửa:

     h1        28px ×14 · 24px ×8 · 20px ×2
     h2        14px ×5  · 15px ×4 · 24px ×1
     h3        13px ×4  · 16px ×2 · 14px ×1 · 18px ×1
     h4        15px ×15 · 16px ×6 · 17px ×1
     ô bảng    12px ×10276 · 14px ×541 · 13px ×66
     nút       13px ×441 · 12px ×124 · 14px ×102
     ô nhập    14px ×125 · 13px ×58

   Và hệ thống nút TỰ MÂU THUẪN: `.btn` cao 38px, còn `.btn-compact` (không khai
   min-height nên kế thừa 38) và `.btn-small` (khai 40px) đều CAO BẰNG HOẶC HƠN
   nút thường — hai cái tên hứa nhỏ hơn mà thực tế không nhỏ. Cùng với việc
   `input` không có bản thu nhỏ tương ứng, đó là lý do nút và ô nhập cạnh nhau
   lệch tới 5px chiều cao ở gần như mọi trang.

   Thang chốt lại:
     22px  tiêu đề trang (h1)
     15px  tiêu đề khối trong trang
     13px  chữ điều khiển: nút, ô nhập, ô chọn — MỘT cỡ duy nhất
     12px  ô bảng và tiêu đề cột
   Chiều cao điều khiển: 34px cho tất cả.

   Vì sao bảng giữ 12px chứ không nâng lên: 12px đang chiếm 10276/10883 ô, là
   quy ước `.compact-table` đã được thống nhất từ 28/08 (xem ghi chú ở khối mật
   độ bảng phía trên). Hạ vài trang lẻ xuống 12px không có rủi ro tràn ngang;
   nâng cả vạn ô lên thì có.
   ========================================================================== */

/* --- Tiêu đề --------------------------------------------------------------- */
.page-header h1,
.page-header-compact h1 { font-size: 22px; }

.card h3,
.platform-head h2,
.panel-head h4,
.form-section h4,
.empty-state h3,
.wholesale-transaction-panel-head h4,
.dash-section-title { font-size: 15px; }

/* --- Điều khiển: một cỡ, một chiều cao ------------------------------------- */
/* `.btn-compact` và `.btn-small` giữ tên vì template đang dùng, nhưng nay trỏ
   về đúng cùng một kích thước — thà một cỡ nhất quán còn hơn ba cỡ mà cái tên
   không nói đúng cái nào to hơn. */
.btn,
.btn-compact,
.btn-small {
  font-size: 13px;
  min-height: 34px;
  padding: var(--space-3) var(--space-7);
}

input, select, textarea {
  font-size: 13px;
  min-height: 34px;
  padding: var(--space-3) var(--space-6);
}
/* Vùng nhập nhiều dòng không bị ép chiều cao một hàng. */
textarea { min-height: 72px; }

/* --- Bảng: một cỡ cho mọi bảng -------------------------------------------- */
main table th { font-size: 12px; }
main table td { font-size: 12px; }

/* Bốn chỗ còn lệch sau đợt chuẩn hoá, tìm bằng cách hỏi trình duyệt quy tắc nào
   đang thắng (không đoán từ ảnh chụp):

   1. `h4` không có class rơi về mặc định trình duyệt 16px — quy tắc trước chỉ
      liệt kê `.panel-head h4` / `.form-section h4`.
   2. `.row-actions .btn` khai 12px, cụ thể hơn nên thắng quy tắc nút chung.
      Nút trong hàng bảng nhỏ hơn nút chỗ khác đúng 1px là kiểu lệch khó chỉ tên
      mà mắt vẫn thấy.
   3. Ô bảng trên Tổng quan còn 13px do quy tắc riêng của tôi ở đợt trước.
   4. Nhãn form 14px, tức LỚN HƠN chính ô nhập 13px mà nó mô tả. Nhãn trong
      `.filterbar` giữ 12px — đó là quy ước riêng của thanh lọc, không đụng. */
main h4 { font-size: 15px; }
.row-actions .btn { font-size: 13px; }
.dash-section .table-wrap td { font-size: 12px; }
main label { font-size: 13px; }

/* ==========================================================================
   TỔNG QUAN — lượt chỉnh phân cấp 04/09/2026

   Không thêm màu, bán kính hay cỡ chữ mới: bảng màu "Mực & Chàm" và thang
   spacing trong docs/ui-ux/DESIGN.md là do chủ sở hữu chốt, còn thang cỡ chữ
   (12 · 13 · 14 · 22) đã được đo và chốt 03/09. Chỉ sửa đúng ba thứ khiến
   trang trông xếp ẩu: con số không thẳng hàng, section không có nhịp, và các
   ô ở dải dẫn kéo dãn hết bề ngang nên rỗng ruột.
   ========================================================================== */

/* 1. Mọi con số dùng chữ số đều bề ngang. Trong một cột số, chữ số tỉ lệ làm
      hàng đơn vị lệch nhau vài pixel mỗi dòng — mắt thấy "rung" mà không chỉ
      ra được vì sao. */
.queue-count,
.hero-value,
.dash-section .cell-money,
.stat-delta {
  font-variant-numeric: tabular-nums;
}

/* 2. Tuổi việc luôn nằm sát đáy thẻ, bất kể nhãn dài mấy dòng. Cùng với
      min-height của .queue-label ở trên, ba tầng chữ (nhãn · số · tuổi) của
      mọi thẻ trong một hàng nằm đúng trên ba đường ngang chung. */
.queue-card .queue-age { margin-top: auto; }
.queue-card { min-height: 116px; }

/* 3. Một vạch tóc dưới đầu khối. Trước đây các section chỉ cách nhau bằng
      khoảng trắng, nên khi cuộn nhanh không rõ khối nào hết ở đâu. Vạch dùng
      --line-soft, nhạt hơn viền thẻ, để phân nhịp chứ không kẻ ô. */
/* Vạch dưới tiêu đề đã chuyển vào `.dash-panel-head` (xem khối PANEL ở cuối
   file): mỗi khối giờ là một tấm liền, vạch là cạnh dưới của phần đầu tấm chứ
   không còn là một đường kẻ rời trên nền trang. */

/* 4. Dải dẫn không kéo dãn vô hạn. Với hai ô trên màn 1440px, mỗi ô rộng gần
      600px mà chỉ chứa một nhãn và một con số — phần lớn diện tích là khoảng
      trống bên trong khung, đọc như thẻ hỏng. Chặn bề rộng lại thì khoảng
      trống rơi ra NGOÀI thẻ, chỗ nó vốn nên ở. */
.hero-row {
  grid-template-columns: repeat(auto-fit, minmax(240px, 420px));
  justify-content: start;
}

/* 5. Con số dẫn trang to hơn nhãn một bậc rõ rệt. 22px giữa một thẻ 360px vẫn
      là con số, chưa phải tiêu đề — nâng lên đúng bậc "số hiển thị" mà thang
      chữ đã chừa sẵn (22–23px cho số, ở đây là ô lớn nhất trang). */
.hero-tile .hero-value { line-height: 1.1; }

@media (max-width: 640px) {
  .hero-row { grid-template-columns: 1fr; }
  .queue-card { min-height: 0; }
  .queue-label { min-height: 0; }
}

/* ==========================================================================
   TỔNG QUAN — hệ TẤM (panel), 04/09/2026

   Vì sao có khối này: trước đó mỗi khối chỉ là một tiêu đề rồi tới một đám thẻ
   rời nằm trên nền trang. Nhìn ra thì không thấy "một bảng", chỉ thấy các mảnh
   trôi nổi — chủ sở hữu nói đúng hai lần về chuyện đó. Giờ mỗi khối là MỘT tấm
   liền: đầu tấm (tiêu đề + số tổng) → thân tấm (các ô, ngăn nhau bằng vạch
   tóc) → chân tấm (dòng tổng). Không màu mới, không bán kính mới, không cỡ chữ
   mới — vẫn đúng docs/ui-ux/DESIGN.md.
   ========================================================================== */

.dash-panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  /* Cắt gọn mọi vạch của ô con thò ra ngoài mép tấm. */
  overflow: hidden;
}

.dash-panel-head {
  padding: var(--space-8) var(--space-10);
  border-bottom: 1px solid var(--line);
}
.dash-panel-head-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-6);
  flex-wrap: wrap;
}
.dash-panel-head .dash-section-title {
  margin: 0;
  padding: 0;
  border: 0;
}
.dash-panel-head .dash-hint { margin: var(--space-4) 0 0; }

.dash-panel-foot {
  padding: var(--space-7) var(--space-10);
  background: var(--surface-2);
  border-top: 1px solid var(--line);
}

/* ── Thẻ hàng chờ khi nằm trong tấm: hết là thẻ, thành Ô của một bảng ───────
   Bỏ viền/bo góc/đổ bóng riêng, chỉ giữ vạch phải và vạch dưới làm đường ngăn.
   Lưới kéo lệch 1px sang phải và xuống dưới để vạch của hàng/cột ngoài cùng
   chui đúng dưới viền tấm, nhờ `overflow: hidden` ở trên — cách này không để
   lại mảng xám ở những ô trống của hàng cuối như thủ thuật "gap ăn màu nền". */
.dash-panel .queue-grid {
  /* FLEX chứ không phải grid ở đây. Với grid, hàng cuối chỉ có 2 ô trong 5 cột
     để lại ba rãnh trống và một vạch dọc cụt lơ lửng giữa vùng trắng — nhìn
     như bảng vẽ dở. Flex-wrap cho các ô của hàng cuối GIÃN RA lấp kín, nên
     mọi hàng đều đầy và vạch nào cũng chạy tới mép tấm. */
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 0 -1px -1px 0;
}
.dash-panel .queue-card {
  flex: 1 1 200px;
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  padding: var(--space-8) var(--space-9);
}
/* Dải màu trên đỉnh từng thẻ không còn hợp khi các thẻ dính liền nhau: nó vỡ
   thành một hàng gạch đứt dưới đầu tấm. Trạng thái đã nằm ở màu con số và ở
   dòng tuổi màu đỏ, đủ để liếc. */
.dash-panel .queue-card::before { display: none; }
.dash-panel a.queue-card:hover {
  background: var(--surface-2);
  border-color: var(--line);
  box-shadow: none;
}

/* ── Bảng khi nằm trong tấm ─────────────────────────────────────────────── */
.dash-panel .table-wrap {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.dash-panel .cost-split { gap: 0; }
.dash-panel .cost-split > .table-wrap + .table-wrap {
  border-left: 1px solid var(--line);
}
@media (max-width: 900px) {
  .dash-panel .cost-split > .table-wrap + .table-wrap {
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}
/* Dòng tổng vừa là chân tấm vừa giữ cách xếp cũ của .cost-total. */
.dash-panel-foot.cost-total {
  margin-top: 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
}

/* ── Hai khối còn lại nằm trong tấm ─────────────────────────────────────── */
.dash-panel > .slot-reserved {
  border: 0;
  border-radius: 0;
  background: var(--surface-2);
}
.dash-panel > .sales-grid { padding: var(--space-9) var(--space-10); }
.dash-panel > .sales-table-wrap,
.dash-panel .sales-table-wrap { margin-top: 0; }

/* Các tấm cách nhau bằng khoảng trắng của .dash-section, không cần thêm gì. */

/* ==========================================================================
   Module Chatbot Mytrex — thay cho Google Sheet "Susumi Bot Config".
   Dải tab mô phỏng hàng tab dưới đáy Google Sheet: người dùng đã quen tìm tab
   theo tên, nên giữ nguyên tên và thứ tự, chỉ thêm số dòng và dấu khoá.
   Không có màu, bán kính hay cỡ chữ mới — toàn bộ lấy từ token sẵn có.
   ========================================================================== */

.chatbot-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--line);
}

.chatbot-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-7);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-2);
  text-decoration: none;
  font-size: 13px;
  white-space: nowrap;
}

.chatbot-tab:hover { background: var(--surface-3); }

.chatbot-tab.active {
  background: var(--primary-soft);
  border-color: var(--primary-line);
  color: var(--primary-strong);
  font-weight: 600;
}

.chatbot-tab-count {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 12px;
}

.chatbot-tab.active .chatbot-tab-count { color: var(--primary-strong); }

/* Tab do chatbot ghi: đánh dấu ngay trên dải tab để không ai mất công mở ra
   rồi mới phát hiện không sửa được. */
.chatbot-tab-lock,
.chatbot-col-lock,
.chatbot-col-key {
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--muted);
}

.chatbot-col-key { background: var(--primary-soft); color: var(--primary-strong); }

.chatbot-note {
  margin: 0 0 var(--space-8);
  color: var(--muted);
  font-size: 13px;
}

/* Các tab có số cột rất khác nhau. Cho bảng giữ bề rộng nội dung và cuộn trong
   khung riêng, thay vì để `.table-wrap { overflow: hidden }` cắt mất cột cuối. */
.chatbot-table-scroll {
  min-width: 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.chatbot-table {
  width: max-content;
  min-width: 100%;
}

.chatbot-table td { vertical-align: top; }

/* Ô nội dung dài: cắt bằng CSS thay vì cắt chuỗi trong template, để copy vẫn
   ra đủ chữ và title vẫn hiện toàn văn khi rê chuột. */
.chatbot-cell-long {
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatbot-cell-locked { color: var(--muted); }

.chatbot-actions-col { white-space: nowrap; }

.chatbot-pager {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  margin-top: var(--space-9);
}

.chatbot-pager-meta { color: var(--muted); font-size: 13px; }

.chatbot-crumb { margin-bottom: var(--space-7); }
.chatbot-crumb a { color: var(--muted); text-decoration: none; font-size: 13px; }
.chatbot-crumb a:hover { color: var(--primary); }

.chatbot-form-title {
  margin: 0 0 var(--space-9);
  font-size: 18px;
  display: flex;
  align-items: baseline;
  gap: var(--space-6);
}

.chatbot-form-id { color: var(--muted); font-size: 14px; font-weight: 400; }

.chatbot-form {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: var(--space-10);
  display: grid;
  gap: var(--space-9);
  max-width: 860px;
}

.chatbot-field { display: grid; gap: var(--space-4); }

.chatbot-field > label {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}

.chatbot-field input[type='text'],
.chatbot-field input[type='password'],
.chatbot-field textarea {
  width: 100%;
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}

.chatbot-field textarea { resize: vertical; min-height: 96px; }

.chatbot-field-locked input { background: var(--surface-3); color: var(--muted); }

.chatbot-hint { margin: 0; font-size: 12px; color: var(--muted); }

.chatbot-form-actions {
  display: flex;
  gap: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

.chatbot-delete {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  margin-top: var(--space-10);
  max-width: 860px;
}

@media (max-width: 900px) {
  .chatbot-cell-long { max-width: 180px; }
  .chatbot-form { padding: var(--space-8); }
}

/* Tab không có ô tìm/lọc (Config, BrandPrompts, Daily Report): thanh trên chỉ
   còn số dòng và nút Thêm, nên bỏ lưới đi cho khỏi thành một hộp trắng rỗng. */
.chatbot-bar-plain { display: flex; justify-content: flex-end; }
.chatbot-bar-plain .filterbar-actions { margin: 0; }

/* Checkbox trong form bị lưới kéo giãn hết chiều ngang trông như một mảng xanh;
   trả nó về đúng kích thước và neo về bên trái. */
.chatbot-field input[type='checkbox'] {
  width: 18px;
  height: 18px;
  justify-self: start;
  margin: var(--space-2) 0;
}
