/* ============================================================================
   Admin Panel — giao diện
   ----------------------------------------------------------------------------
   Lớp phủ lên Bootstrap 5.3, đặt lại các biến --bs-* rồi tinh chỉnh vài thành
   phần. Không sửa HTML, nên gỡ file này ra là quay về Bootstrap gốc.

   Ba nguyên tắc, và lý do:

   1. SỐ LIỆU PHẢI ĐỌC RA SỐ LIỆU. Đây là bảng điều khiển, không phải bài viết —
      ID, số lượng, mốc thời gian, mã rút gọn đều dùng chữ đơn cách với
      tabular-nums nên các cột số thẳng hàng và quét mắt được.

   2. KHÔNG PHỤ THUỘC MẠNG NGOÀI. Bản trước nạp Instrument Sans từ Google Fonts
      bằng @import — một request chặn hiển thị ở mọi trang, đổi lấy một khuôn chữ
      không khác system-ui bao nhiêu. Bỏ hẳn; system-ui phủ dấu tiếng Việt tốt và
      có sẵn.

   3. THÔNG TIN ĐỨNG YÊN. Viền 1px thay cho bo góc 1,1rem và bóng đổ dày. Bóng
      chỉ dùng ở chỗ có độ cao thật: modal và menu thả xuống.

   Bảng màu cùng họ với docs/quy-trinh-trang-nguon.html để tài liệu và ứng dụng
   trông như một sản phẩm.
   ========================================================================== */

:root {
  --mono: ui-monospace, "Cascadia Mono", "Cascadia Code", Consolas,
          "DejaVu Sans Mono", "Liberation Mono", monospace;

  /* nền giấy lạnh, lệch nhẹ về teal — chọn chứ không lấy xám trung tính */
  --paper:      #f1f4f3;
  --surface:    #ffffff;
  --surface-2:  #f7f9f8;
  --ink:        #101819;
  --ink-2:      #56646a;
  /* Đo thật: #8a979b chỉ cho tỷ lệ tương phản 3,01 trên nền trắng — dưới ngưỡng
     4,5. Đường dẫn dưới tên sản phẩm và tiêu đề cột dùng màu này, mà chúng là
     nội dung phải đọc chứ không phải trang trí. #657277 cho 4,97. */
  --ink-3:      #657277;
  --line:       #dce3e1;
  --line-soft:  #e8edeb;

  --accent:     #0b5563;
  --accent-2:   #0e6a7c;
  --accent-bg:  #e4eef0;
  --accent-line:#bcd6dc;

  --ok:      #16715a;
  --ok-bg:   #e6f2ee;
  --warn:    #9c5117;
  --warn-bg: #f6ece3;
  --bad:     #9e2b2b;
  --bad-bg:  #f7e8e8;
  --info:    #2a5c9a;
  --info-bg: #e8eef7;

  /* ---- Bootstrap ---- */
  --bs-body-font-family: system-ui, -apple-system, "Segoe UI", Roboto,
                         "Helvetica Neue", Arial, sans-serif;
  --bs-font-monospace: var(--mono);
  --bs-body-bg: var(--paper);
  --bs-body-color: var(--ink-2);
  --bs-emphasis-color: var(--ink);
  --bs-heading-color: var(--ink);
  --bs-secondary-color: var(--ink-3);
  --bs-border-color: var(--line);
  --bs-border-color-translucent: var(--line);
  --bs-tertiary-bg: var(--surface-2);
  --bs-secondary-bg: var(--surface-2);

  --bs-border-radius:    5px;
  --bs-border-radius-sm: 4px;
  --bs-border-radius-lg: 6px;
  --bs-border-radius-xl: 8px;

  --bs-primary: var(--accent);
  --bs-primary-rgb: 11, 85, 99;
  --bs-primary-text-emphasis: var(--accent);
  --bs-primary-bg-subtle: var(--accent-bg);
  --bs-primary-border-subtle: var(--accent-line);

  --bs-success: var(--ok);
  --bs-success-bg-subtle: var(--ok-bg);
  --bs-warning: var(--warn);
  --bs-warning-bg-subtle: var(--warn-bg);
  --bs-danger: var(--bad);
  --bs-danger-bg-subtle: var(--bad-bg);
  --bs-info: var(--info);
  --bs-info-bg-subtle: var(--info-bg);

  --bs-link-color: var(--accent);
  --bs-link-hover-color: var(--accent-2);
  --bs-link-color-rgb: 11, 85, 99;

  color-scheme: light;
}

/* Giao diện tối. Đặt qua thuộc tính data-bs-theme để chính Bootstrap cũng đổi
   theo, không chỉ riêng lớp phủ này — nếu không, các thành phần Bootstrap chưa
   được ghi đè ở dưới sẽ giữ nền sáng và chữ trắng nằm trên nền trắng. */
[data-bs-theme="dark"] {
  /* Nâng nền lên khỏi mức gần-đen: ở #10161a thì thẻ và nền dính vào nhau, mất
     hẳn cảm giác phân lớp. Viền cũng phải sáng hơn mới thấy được. */
  --paper:      #141c20;
  --surface:    #1c262b;
  --surface-2:  #232f35;
  --ink:        #e6edec;
  --ink-2:      #a3b5b9;
  /* 4,06 trên nền thẻ nhưng chỉ 3,61 trên nền phụ — chưa đạt. #8d9ea3 cho 5,55 / 4,94. */
  --ink-3:      #8d9ea3;
  --line:       #324248;
  --line-soft:  #27343a;

  --accent:     #63b3c4;
  --accent-2:   #7ec6d5;
  --accent-bg:  #14262b;
  --accent-line:#2d4a52;

  --ok:      #57bf9d;
  --ok-bg:   #142b26;
  --warn:    #d99a5f;
  --warn-bg: #2b2018;
  --bad:     #e08585;
  --bad-bg:  #2c1a1a;
  --info:    #7ba7e0;
  --info-bg: #16232f;

  --bs-primary-rgb: 99, 179, 196;
  --bs-link-color-rgb: 99, 179, 196;

  color-scheme: dark;
}

/* Ở giao diện tối, màu nhấn là teal SÁNG. Chữ trắng đặt lên đó gần như không
   đọc được — chữ phải tối lại theo nền nút. */
[data-bs-theme="dark"] .btn-primary {
  --bs-btn-color: #0d1417;
  --bs-btn-hover-color: #0d1417;
  --bs-btn-active-color: #0d1417;
}
[data-bs-theme="dark"] .btn-outline-primary:hover,
[data-bs-theme="dark"] .btn-outline-success:hover,
[data-bs-theme="dark"] .btn-outline-danger:hover,
[data-bs-theme="dark"] .btn-outline-warning:hover,
[data-bs-theme="dark"] .btn-outline-info:hover {
  color: #0d1417;
}
[data-bs-theme="dark"] .page-item.active .page-link { color: #0d1417; }
[data-bs-theme="dark"] .sidebar-brand { color: #0d1417 !important; }

/* ---------------------------------------------------------------- nền chung */

body {
  background: var(--paper);
  color: var(--ink-2);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  color: var(--ink);
  font-weight: 650;
  letter-spacing: -0.018em;
}
h4 { font-size: 1.32rem; }
h5 { font-size: 1.1rem; }

.fw-bold, .fw-semibold { color: var(--ink); }
.text-muted { color: var(--ink-3) !important; }

/* Mọi con số dùng chữ đơn cách và thẳng cột. Đây là thay đổi lớn nhất so với
   bản trước: bảng điều khiển sống bằng việc quét số, mà chữ tỷ lệ thì cột số
   không bao giờ thẳng. */
code, kbd, samp, pre, .font-monospace {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
code {
  color: var(--accent);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: 3px;
  padding: 0.08em 0.36em;
  font-size: 0.86em;
}

/* ------------------------------------------------------------------ sidebar */

.sidebar {
  background: var(--surface) !important;
  border-right: 1px solid var(--line);
}
.sidebar-brand {
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 5px;
  background: var(--accent);
  color: #fff !important;
  font-size: 1rem;
}
.sidebar a.fw-bold span:not(.sidebar-brand) { color: var(--ink) !important; }

.sidebar .nav-link {
  color: var(--ink-2);
  border-radius: 5px;
  padding: 0.5rem 0.7rem;
  font-weight: 550;
  font-size: 0.905rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border-left: 2px solid transparent;
  transition: background 0.12s ease, color 0.12s ease;
}
.sidebar .nav-link i {
  font-size: 1rem;
  width: 1.15rem;
  text-align: center;
  flex-shrink: 0;
  color: var(--ink-3);
  transition: color 0.12s ease;
}
.sidebar .nav-link:hover {
  color: var(--ink);
  background: var(--surface-2);
}
.sidebar .nav-link:hover i { color: var(--accent); }

/* Mục đang mở: thanh dọc bên trái, không tô nền rực. Trạng thái phải thấy được
   mà không cướp sự chú ý khỏi nội dung chính. */
.sidebar .nav-link.active {
  color: var(--ink);
  background: var(--accent-bg);
  border-left-color: var(--accent);
  border-radius: 0 5px 5px 0;
  font-weight: 620;
}
.sidebar .nav-link.active i { color: var(--accent); }

/* --------------------------------------------------------------- thanh trên */

.navbar {
  background: var(--surface) !important;
  border-bottom: 1px solid var(--line) !important;
  min-height: 3.25rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}
.navbar .fw-semibold {
  font-size: 1rem;
  letter-spacing: -0.012em;
}

/* ---------------------------------------------------------------------- thẻ */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: none;
}
.card-header {
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  font-weight: 620;
  color: var(--ink);
  padding: 0.7rem 1rem;
}
.card-footer {
  background: var(--surface-2);
  border-top: 1px solid var(--line);
}

/* --------------------------------------------------------------------- bảng */

.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--ink-2);
  color: var(--ink-2);
  font-size: 0.9rem;
  margin-bottom: 0;
}

/* Tiêu đề cột: chữ đơn cách, viết hoa, nhỏ và giãn — đọc ra ngay là nhãn chứ
   không phải nội dung, nên mắt bỏ qua được khi đang dò dữ liệu. */
.table thead th,
.table thead.table-light th {
  background: var(--surface-2);
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 0.695rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
  padding: 0.6rem 0.85rem;
  white-space: nowrap;
}
.table > tbody > tr > td {
  padding: 0.62rem 0.85rem;
  vertical-align: middle;
  border-bottom-color: var(--line-soft);
}
.table > :not(caption) > * > * { border-bottom-color: var(--line-soft); }
.table > tbody > tr:last-child > td { border-bottom: 0; }

.table-hover > tbody > tr:hover > * {
  background-color: var(--surface-2);
  color: var(--ink);
}

/* Giữ ô không xuống dòng để table-responsive cuộn ngang thật, thay vì trình
   duyệt bóp mọi cột xuống mức không đọc nổi. */
.table-responsive .table th,
.table-responsive .table td { white-space: nowrap; }

/* Bảng trong hộp thoại là bảng GIẢI THÍCH, không phải bảng dữ liệu: nó phải xuống
   dòng cho vừa khung. Không trừ ra thì `nowrap` ở trên bắt một câu giải thích nằm
   trên đúng một dòng — đo được 1033px trong hộp 467px, sinh thanh cuộn ngang ngay
   giữa hộp thoại và cắt mất nửa nội dung. */
.modal .table-responsive .table td,
.modal .table-responsive .table th { white-space: normal; }

/* Tên sản phẩm cũng là một CÂU chứ không phải giá trị ngắn — cùng loại với bảng
   giải thích ở trên. Để `nowrap` tự do thì một tiêu đề 84 ký tự chiếm 1.082px, đẩy
   bảng Liên Kết ra 1.048px trong khung 965px (đo ở cửa sổ 1.280px) và cột "Click"
   — thứ người ta vào trang này để xem — bị đẩy khuất, phải cuộn ngang mới thấy.
   Cắt bằng CSS chứ không cắt chuỗi trong PHP: giá trị đủ vẫn nằm trong DOM và
   trong tooltip, bôi đen chép ra vẫn nguyên. */
.cell-ten-sp,
.cell-ten-acc {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Ngưỡng co theo bề rộng cửa sổ. Một con số cố định thì hoặc phí chỗ trên màn
   rộng, hoặc vẫn đẩy cột "Click" ra ngoài trên màn hẹp — mà cột Click mới là thứ
   người ta vào trang này để xem. */
.cell-ten-sp  { max-width: 26rem; }
.cell-ten-acc { max-width: 14rem; }

@media (max-width: 1400px) {
  .cell-ten-sp  { max-width: 18rem; }
}

@media (max-width: 1100px) {
  .cell-ten-sp  { max-width: 12rem; }
  .cell-ten-acc { max-width: 9rem; }
}

/* Nhãn nền tảng là CHỮ, cho xuống dòng thay vì cắt: "Trực tiếp / Không rõ" chiếm
   138px trong cột 214px, thừa đúng 5px so với khung — vừa đủ sinh một thanh cuộn
   ngang trông như bảng hỏng, mà cắt đi thì mất nghĩa. Xuống dòng ở dấu cách là
   cách duy nhất vừa giữ đủ chữ vừa hết tràn. */
/* Phải viết đủ `.table-responsive .table td` ở đầu: luật `nowrap` toàn cục có độ
   đặc hiệu (0,2,1), một class trần chỉ (0,1,0) nên thua và `nowrap` vẫn thắng.
   Đã dính đúng bẫy này — class gắn đúng, CSS nạp đúng, mà chữ vẫn không xuống dòng. */
.table-responsive .table td.cell-nen-tang { white-space: normal; }

/* ----------------------------------------------------------------- biểu mẫu */

.form-control, .form-select {
  background-color: var(--surface);
  border-color: var(--line);
  color: var(--ink);
  font-size: 0.9rem;
}
.form-control:focus, .form-select:focus {
  background-color: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
  color: var(--ink);
}
.form-control::placeholder { color: var(--ink-3); }
.form-label {
  color: var(--ink);
  font-weight: 600;
  font-size: 0.84rem;
  margin-bottom: 0.3rem;
}
.form-text {
  color: var(--ink-3);
  font-size: 0.8rem;
}
input[type="number"], input[type="tel"] { font-family: var(--mono); }

/* -------------------------------------------------------------------- nút */

.btn {
  font-weight: 560;
  border-radius: 5px;
  font-size: 0.875rem;
  --bs-btn-box-shadow: none;
}
.btn:focus-visible { box-shadow: 0 0 0 3px var(--accent-bg); }
.btn-sm { font-size: 0.83rem; padding: 0.28rem 0.6rem; }

.btn-primary {
  --bs-btn-bg: var(--accent);
  --bs-btn-border-color: var(--accent);
  --bs-btn-hover-bg: var(--accent-2);
  --bs-btn-hover-border-color: var(--accent-2);
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  box-shadow: none;
}
.btn-outline-secondary {
  --bs-btn-color: var(--ink-2);
  --bs-btn-border-color: var(--line);
  --bs-btn-hover-bg: var(--surface-2);
  --bs-btn-hover-color: var(--ink);
  --bs-btn-hover-border-color: var(--line);
}
.btn-outline-primary {
  --bs-btn-color: var(--accent);
  --bs-btn-border-color: var(--accent-line);
  --bs-btn-hover-bg: var(--accent);
  --bs-btn-hover-border-color: var(--accent);
}
.btn-outline-success { --bs-btn-color: var(--ok);   --bs-btn-border-color: var(--ok); }
.btn-outline-danger  { --bs-btn-color: var(--bad);  --bs-btn-border-color: var(--bad); }
.btn-outline-warning { --bs-btn-color: var(--warn); --bs-btn-border-color: var(--warn); }
.btn-outline-info    { --bs-btn-color: var(--info); --bs-btn-border-color: var(--info); }
.btn-outline-dark    { --bs-btn-color: var(--ink);  --bs-btn-border-color: var(--line); }

/* --------------------------------------------------------------------- nhãn */

.badge {
  font-weight: 600;
  border-radius: 3px;
  font-size: 0.72rem;
  padding: 0.28em 0.5em;
  letter-spacing: 0.01em;
}
/* Nhãn mang con số thì dùng chữ đơn cách — chúng hay nằm chồng cột nhau. */
.badge.bg-info, .badge.bg-primary, .badge.bg-secondary {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.badge.bg-info      { background: var(--info-bg) !important; color: var(--info) !important; }
.badge.bg-success   { background: var(--ok-bg)   !important; color: var(--ok)   !important; }
.badge.bg-danger    { background: var(--bad-bg)  !important; color: var(--bad)  !important; }
.badge.bg-warning   { background: var(--warn-bg) !important; color: var(--warn) !important; }
.badge.bg-secondary { background: var(--surface-2) !important; color: var(--ink-3) !important; }
.badge.bg-dark      { background: var(--ink) !important; color: var(--surface) !important; }
.badge.bg-success-subtle { background: var(--ok-bg) !important; color: var(--ok) !important; }

/* -------------------------------------------------------------- thông báo */

.alert {
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: 5px;
  font-size: 0.9rem;
  padding: 0.7rem 0.95rem;
  /* Thông báo hay chứa thứ KHÔNG có dấu cách nào để ngắt dòng: refresh token,
     URL dài, chuỗi proxy. Không có dòng này thì một token 400 ký tự kéo cả trang
     rộng ra 3041px trong khi khung nhìn chỉ 1841px — trang sinh thanh cuộn ngang
     và mọi bảng lệch hết. Đã gặp thật ở nút "Xem mã bí mật". */
  overflow-wrap: anywhere;
}

/* Khối hiện mã bí mật: mỗi thứ một dòng, chữ đơn cách để đọc và chép cho chính
   xác — nhồi tất cả vào một dòng ngăn bằng dấu | thì không ai dò nổi đâu là
   token đâu là mật khẩu. */
.alert-secret {
  white-space: pre-wrap;
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.6;
}
.alert-success { background: var(--ok-bg);   border-left-color: var(--ok);   color: var(--ok); }
.alert-danger  { background: var(--bad-bg);  border-left-color: var(--bad);  color: var(--bad); }
.alert-warning { background: var(--warn-bg); border-left-color: var(--warn); color: var(--warn); }
.alert-info    { background: var(--info-bg); border-left-color: var(--info); color: var(--info); }

/* ------------------------------------------------- modal, menu thả xuống */

/* Bóng chỉ dùng ở đây, nơi có độ cao thật. */
.modal-content {
  border-radius: 7px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.16);
}
.modal-header, .modal-footer { border-color: var(--line); }
.modal-title { font-size: 1.05rem; }

.dropdown-menu {
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  background: var(--surface);
  padding: 0.25rem;
  font-size: 0.885rem;
}
.dropdown-item {
  border-radius: 4px;
  padding: 0.42rem 0.6rem;
  color: var(--ink-2);
}
.dropdown-item:hover, .dropdown-item:focus {
  background: var(--surface-2);
  color: var(--ink);
}
.dropdown-item.text-danger:hover { background: var(--bad-bg); color: var(--bad); }

/* Tiêu đề nhóm phải THẲNG HÀNG với các mục cấp trên, mục con mới thụt vào.
   Bootstrap để `.dropdown-header` padding trái 1rem còn `.dropdown-item` ở đây
   là 0.6rem, nên tiêu đề nhóm bị đẩy vào trong hơn cả những thứ nó đang gom
   lại — đọc lướt thì tưởng chính nó mới là mục con. Thụt lề phải nói đúng
   quan hệ trên–dưới, không thì nó chỉ là nhiễu. */
.dropdown-header {
  padding: 0.5rem 0.6rem 0.3rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-3, var(--ink-2));
  text-transform: none;
}
.dropdown-item.muc-con { padding-left: 1.5rem; }

.dropdown-divider { border-top-color: var(--line-soft); margin: 0.25rem 0; }
/* Nút bên trong menu là form riêng, không được kéo giãn hàng. */
.dropdown-menu form { margin: 0; }
.dropdown-menu .dropdown-item { width: 100%; text-align: left; border: 0; background: none; }

/* ------------------------------------------------- hộp thoại: giữ chỗ cuộn */

/* Mở một modal là cả trang nhấp nháy dịch ngang.
   Bootstrap khoá cuộn bằng `overflow: hidden` trên body — thanh cuộn biến mất,
   trang rộng thêm đúng bề ngang của nó (~15px) — rồi bù lại bằng `padding-right`
   nhét thẳng vào thuộc tính style. Hai việc đó không xảy ra cùng một khung hình,
   nên mắt kịp thấy nội dung giật sang phải rồi giật về.
   Chữa từ gốc: giữ chỗ thanh cuộn LUÔN LUÔN, kể cả khi nó ẩn. Không còn chênh
   lệch bề ngang thì không còn gì để bù, nên phần bù của Bootstrap phải gỡ đi —
   để lại là nó đẩy ngược sang bên kia. Nó viết inline nên phải `!important`. */
html { scrollbar-gutter: stable; }
body.modal-open { padding-right: 0 !important; }
.modal, .modal-open .fixed-top, .modal-open .sticky-top { padding-right: 0 !important; }

/* --------------------------------------------------------------- phân trang */

.pagination { --bs-pagination-font-size: 0.85rem; }
.page-link {
  background: transparent;
  border-color: var(--line);
  color: var(--ink-2);
  border-radius: 4px;
  margin: 0 0.1rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.page-link:hover { background: var(--surface-2); color: var(--ink); }
.page-item.active .page-link {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.page-item.disabled .page-link { background: transparent; color: var(--ink-3); }

/* ----------------------------------------------------------------- lặt vặt */

.progress {
  background: var(--surface-2);
  border-radius: 2px;
}
.progress-bar { background: var(--accent); }

.spinner-border { border-width: 0.15em; }

.form-switch .form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}

hr { border-color: var(--line); opacity: 1; }

a { text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* Vùng bôi đen dùng màu nhấn ĐẶC, chữ đảo màu. Bản cũ dùng --accent-bg — gần như
   trùng nền trang (#e4eef0 trên #f7f9f8, #14262b trên #1c262b ở chế độ tối) và
   trùng luôn nền dòng/menu đang chọn, nên bôi đen xong không thấy gì (30/09/2026).
   Tương phản chữ/nền: sáng ~8:1, tối ~8:1. */
::selection { background: var(--accent); color: #fff; }
[data-bs-theme="dark"] ::selection { color: #0d1417; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ==========================================================================
   Bảng thu gọn khi hết chỗ
   --------------------------------------------------------------------------
   Ẩn cột là việc ĐO, không phải việc đoán. Bản trước ẩn ưu tiên 3 ở mọi kích
   thước và ưu tiên 2 dưới 992px — nghĩa là một bảng 6 cột trên màn hình 1745px
   vẫn giấu cột rồi bắt bấm nút Chi tiết, trong khi nửa màn hình còn trống.

   Nay responsive-table.js đo bề rộng bảng thực sự cần rồi so với chỗ đang có,
   và chỉ khi thiếu chỗ mới gắn .rt-an-3, thiếu tiếp mới gắn .rt-an-2. CSS vẫn
   là nơi duy nhất biết CÁCH ẩn; JS quyết định KHI NÀO.
   ========================================================================== */

.rt.rt-an-3 .pri-3 { display: none; }
.rt.rt-an-2 .pri-2 { display: none; }
/* Thứ tự ẩn từng cột (data-an) — xem responsive-table.js. */
.rt .rt-cot-an { display: none; }

/* Không giấu cột nào thì nút Chi tiết chẳng có gì để mở — bỏ hẳn cột đó đi cho
   khỏi chiếm chỗ và khỏi mời người ta bấm vào một hộp thoại rỗng. */
.rt:not(.rt-an-2):not(.rt-an-3):not(.rt-an-le) .rt-more { display: none; }

/* Lúc đo: bung bảng về bề rộng nó muốn, kẹp ô dài lại để một cột chữ dài không
   tự nó đòi 3000px rồi kéo cả bảng vào diện "hết chỗ". Bỏ cột nút ra ngoài phép
   đo vì nếu mọi thứ vừa thì cột đó cũng biến mất. */
.rt.rt-dang-do { width: max-content !important; table-layout: auto !important; }
.rt.rt-dang-do th, .rt.rt-dang-do td { max-width: 260px; }
.rt.rt-dang-do .rt-more { display: none !important; }

.rt .rt-more { width: 1%; text-align: right; padding-left: 0; white-space: nowrap; }

/* Nút Chi tiết đứng ngay cạnh nút Hành động trên cùng một dòng, nên phải CÙNG
   kích thước. Trước đây nó bị ép min-height/min-width 38px cho dễ bấm bằng ngón
   tay, nhưng cạnh một nút .btn-sm thì nó thành một khối vuông to lệch hẳn. Để
   nguyên số đo của .btn-sm là hai nút bằng nhau, mà vẫn đủ tầm ngón tay.
   Nhãn chữ hiện từ 576px trở lên, dưới đó chỉ còn biểu tượng. */
.rt .rt-more-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
}
/* Mobile + máy tính bảng (<992px): nút Chi tiết và nút Hành động chỉ còn biểu
   tượng — chữ chiếm chỗ của đúng những cột người ta đang cố giữ lại. */
.rt .rt-more-btn .rt-more-label { display: none; }
@media (min-width: 992px) {
  .rt .rt-more-btn .rt-more-label { display: inline; }
}
.btn-act .bi { display: none; }
@media (max-width: 991.98px) {
  .btn-act .act-label { display: none; }
  .btn-act .bi { display: inline; }
  .btn-act.dropdown-toggle::after { display: none; }
}

/* Màn hình nhỏ: cho chữ xuống dòng và bóp đệm lại. Việc ẩn cột KHÔNG còn nằm
   ở đây — đo mới biết, mà cùng một bề rộng màn hình thì bảng 5 cột và bảng 14
   cột cần hai cách xử lý khác nhau. */
@media (max-width: 991.98px) {
  /* `white-space: normal` thôi là chưa đủ: email, token, chuỗi proxy đều KHÔNG có
     dấu cách nào để ngắt, nên chúng vẫn giữ nguyên một dòng dài và đẩy bảng tràn
     ra khỏi hộp cuộn (đo được 382px trong hộp 342px, nút Chi tiết bị cắt mất).
     `anywhere` cho phép ngắt giữa chữ — xấu hơn một chút nhưng đọc được, còn hơn
     là không bấm được nút. */
  .table-responsive .rt th,
  .table-responsive .rt td { white-space: normal; overflow-wrap: anywhere; }
  .rt > tbody > tr > td { padding: 0.6rem; }
  .rt thead th { padding: 0.55rem 0.6rem; }
}

/* Danh sách nhãn–giá trị trong modal chi tiết */
.rt-detail { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 0.55rem 1rem; align-items: baseline; }
.rt-detail dt {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.rt-detail dd { margin: 0; color: var(--ink); font-size: 0.9rem; overflow-wrap: anywhere; }
.rt-detail dd .small, .rt-detail dd small { color: var(--ink-3); }

@media (max-width: 480px) {
  .rt-detail { grid-template-columns: 1fr; gap: 0.15rem; }
  .rt-detail dd { margin-bottom: 0.5rem; }
}

/* ==========================================================================
   Màu thương hiệu của sàn
   --------------------------------------------------------------------------
   Nhãn và nút của mỗi nền tảng mang đúng màu sàn đó, để nhận ra bằng màu trước
   khi kịp đọc chữ. Khai báo trong SOURCE_DRIVERS, định nghĩa ở đây.
   ========================================================================== */

/* WooCommerce — tím #7F54B3 (màu thương hiệu hiện hành) */
.badge.plat-woo { background: #7f54b3 !important; color: #fff !important; }
.btn-woo {
  --bs-btn-bg: #7f54b3;
  --bs-btn-border-color: #7f54b3;
  --bs-btn-color: #fff;
  --bs-btn-hover-bg: #6d459c;
  --bs-btn-hover-border-color: #6d459c;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #603c89;
  --bs-btn-active-border-color: #603c89;
  --bs-btn-active-color: #fff;
}
.btn-woo:focus-visible { box-shadow: 0 0 0 3px rgba(127, 84, 179, 0.3); }

/* Nền tối cần sắc tím sáng hơn mới đủ tách khỏi nền, và chữ tối lại theo. */
[data-bs-theme="dark"] .badge.plat-woo { background: #a986d6 !important; color: #1b1226 !important; }
[data-bs-theme="dark"] .btn-woo {
  --bs-btn-bg: #a986d6;
  --bs-btn-border-color: #a986d6;
  --bs-btn-color: #1b1226;
  --bs-btn-hover-bg: #ba9ce0;
  --bs-btn-hover-border-color: #ba9ce0;
  --bs-btn-hover-color: #1b1226;
  --bs-btn-active-bg: #ba9ce0;
  --bs-btn-active-color: #1b1226;
}

/* Phân trang dùng chung — render_pagination() trong app/pagination.php.
   Trước đây mỗi trang một kiểu, và ba trang in ra TOÀN BỘ số trang; với bảng
   một triệu dòng thì đó là hơn năm mươi nghìn thẻ <a> trong một trang HTML. */
.pagination-sep .page-item { margin: 0 2px; }
.pagination-sep .page-link { border-radius: 4px; min-width: 2.1rem; text-align: center; }
.pagination-sep .page-item.disabled .page-link { opacity: 0.55; }

/* Nhãn bước trong hộp thoại Thay Cửa Hàng */
.eyebrow-step {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.eyebrow-step strong { color: var(--ink-2); font-weight: 600; }

/* ==========================================================================
   Ô email kèm nút mở hộp thư
   --------------------------------------------------------------------------
   Đây là cột rộng nhất của bảng Pinterest, mà mọi địa chỉ đều kết thúc bằng
   cùng một đuôi (@hotmail.com) — cắt đuôi không mất thông tin nào, còn giá trị
   đầy đủ vẫn nằm trong tooltip.

   Dùng flex thay vì để nút trôi theo dòng chữ: với inline, một địa chỉ dài sẽ
   đẩy nút xuống dòng dưới và làm cả hàng cao gấp đôi. Nút giữ nguyên bề rộng
   (flex-shrink: 0), chỉ phần chữ co lại.
   ========================================================================== */

.cell-mail { max-width: 15rem; }

/* Flex phải nằm ở lớp bọc BÊN TRONG, tuyệt đối không đặt lên chính <td>.
   `display: flex` ghi đè `display: table-cell`, và ô đó lập tức rơi khỏi bố cục
   bảng: không còn giãn theo chiều cao hàng (đo được 45px trong khi các ô khác
   51px), mất luôn `vertical-align: middle`. Nhìn ra ngay bằng mắt — chữ trong ô
   email lệch lên so với cả hàng. */
.cell-mail-in {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.cell-mail-dc {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Liên kết trong ô bảng: giữ nguyên màu chữ, chỉ hiện ra khi rê chuột.
   Ba mươi dòng email và proxy mà tô xanh hết thì cả bảng thành một mảng màu và
   những liên kết THẬT SỰ quan trọng (tên tài khoản, tên miền) chìm nghỉm. Cái
   cần báo ở đây là "bấm được", không phải "hãy bấm tôi". */
.lk-o {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.lk-o:hover, .lk-o:focus-visible {
  color: var(--accent);
  text-decoration: underline;
}

/* Nút chỉ có biểu tượng: bỏ hết đệm của .btn để nó không đội ô cao lên, nhưng
   vẫn giữ vùng bấm 24px — nhỏ hơn nữa là khó trúng trên màn hình cảm ứng. */
.btn-mail {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--ink-3);
  line-height: 1;
  transition: color 0.12s ease, background-color 0.12s ease;
}

.btn-mail:hover,
.btn-mail:focus-visible {
  color: var(--accent);
  background: var(--accent-bg);
}

.btn-mail i { font-size: 0.95rem; }

/* ---- Hộp thoại hộp thư ---------------------------------------------------
   Tóm tắt thư của Graph dài tới 255 ký tự và giữ nguyên xuống dòng của thư gốc,
   nên để tự do thì mỗi mục cao vài trăm pixel và cả danh sách 25 thư không còn
   lướt được. Kẹp 2 dòng: đủ để đọc mã xác minh hay câu đầu, mà vẫn nhìn được
   nhiều thư cùng lúc. */

.mail-item { padding: 0.6rem 0; border-bottom: 1px solid var(--line-soft); }
.mail-item:last-child { border-bottom: 0; }

.mail-tieude { font-weight: 600; line-height: 1.35; }
.mail-chuadoc .mail-tieude { color: var(--ink); }

.mail-tomtat {
  margin-top: 0.25rem;
  color: var(--ink-2);
  font-size: 0.82rem;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Xuống dòng của thư gốc giữ nguyên, nhưng gộp khoảng trắng thừa lại — thư
     tự động thường có hàng chục dòng trống liên tiếp. */
  white-space: pre-line;
}

.mail-meta { font-size: 0.75rem; color: var(--ink-3); }

/* ---- Tiêu đề cột bấm được để sắp xếp -------------------------------------
   Kế thừa y nguyên kiểu chữ của <th> (đơn cách, viết hoa, giãn) để nhìn vẫn là
   tiêu đề chứ không phải một liên kết lạc vào bảng. Chỉ khác ở con trỏ chuột và
   màu khi rê — đủ để biết bấm được, không đủ để gây ồn. */
.sort-th {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.sort-th:hover { color: var(--accent); }
.sort-th-on { color: var(--ink); }

/* Bấm vào dòng thư để mở toàn văn — con trỏ phải nói ra điều đó, không thì không
   ai biết là bấm được. */
.mail-dong { cursor: pointer; }
.mail-item:hover .mail-tieude { color: var(--accent); }

/* Mở rồi thì bỏ kẹp 2 dòng ở phần tóm tắt: giữ nó lại là vừa có tóm tắt cụt vừa
   có toàn văn ngay dưới, đọc rất khó chịu. */
.mail-mo .mail-tomtat { display: none; }

.mail-than:not(:empty) { margin-top: 0.5rem; }

/* Khung cách ly cho thân thư. Nền trắng cố định: thư là HTML do bên khác soạn,
   phần lớn giả định nền sáng, thả vào giao diện tối thì chữ đen trên nền đen. */
.mail-khung {
  width: 100%;
  height: 220px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: #fff;
  display: block;
}

/* Ô tích chỉ để đọc (cột Profile). Không dùng `disabled` vì Bootstrap làm mờ nó
   xuống 0.5 — trông như hỏng chứ không như "đã có". Chặn chuột và phím Tab thay
   cho việc tắt hẳn, còn cursor giữ mũi tên để khỏi mời người ta bấm. */
.tick-doc {
  pointer-events: none;
  cursor: default;
  margin: 0;
}

/* Ô chưa tick mà lấy màu viền mặc định thì trên nền tối gần như biến mất — bỏ
   chữ "Chưa có" đi rồi thì ô trống vô hình đọc thành "cột này rỗng", không phải
   "chưa có profile". Dùng màu chữ mờ để nó vẫn nhạt hơn ô đã tick nhưng nhìn ra. */
.tick-doc:not(:checked) {
  border-color: var(--ink-2);
}

/* Bootstrap dựng modal cuộn được với giả định .modal-header/.modal-body/.modal-footer
   là con TRỰC TIẾP của .modal-content. Các hộp thoại ở đây bọc cả ba trong một thẻ
   <form> (cần thế để bấm Lưu là gửi được), nên chuỗi flex đứt ngay ở đó: .modal-body
   không bị ép chiều cao, nó dài ra bao nhiêu tùy nội dung và đẩy nút Lưu xuống dưới
   đáy màn hình — không cuộn tới được vì .modal-content đang overflow:hidden.

   Cho thẻ form kế thừa đúng vai trò đó thì mọi thứ về như Bootstrap định. min-height:0
   là bắt buộc: mục flex mặc định min-height:auto, tức không co xuống dưới chiều cao
   nội dung, và đó chính là thứ đang chặn. */
.modal-dialog-scrollable .modal-content > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  max-height: 100%;
}

/* Cột "Tài khoản dùng" bên Quản Lý Proxy: đóng lại là một dòng nhãn tròn có
   icon, cùng lối với cột "Liên kết" bên Quản Lý Email; bung ra mới hiện danh
   sách email kèm nút gỡ.

   Mũi tên mặc định của <summary> nằm ở đầu dòng và đẩy cả cụm nhãn thụt vào,
   nên tự vẽ lấy: bỏ marker gốc rồi thêm một dấu ‣ nhỏ, xoay 90° khi mở. Đặt
   `display:flex` cũng là cách ẩn marker trên Safari/WebKit — nó không nghe
   `list-style`. */
.proxy-accs > summary {
  cursor: pointer;
  list-style: none;
}
.proxy-accs > summary::-webkit-details-marker {
  display: none;
}
.proxy-accs > summary::after {
  content: "\203A";           /* › */
  color: var(--ink-2);
  font-size: .95rem;
  line-height: 1;
  transition: transform .12s ease;
}
.proxy-accs[open] > summary::after {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .proxy-accs > summary::after { transition: none; }
}

/* ------------------------------------------------------- menu trái thu gọn */
/* Lớp .sb-thu trên <html>, bật bằng nút ở thanh trên, nhớ bằng localStorage.
   Chỉ áp từ 992px: dưới đó menu đã là offcanvas trượt ra, không chiếm chỗ. */
@media (min-width: 992px) {
  .sidebar { transition: width .15s ease, flex-basis .15s ease; }
  html.sb-thu .sidebar { width: 72px; flex-basis: 72px; padding-left: .75rem !important; padding-right: .75rem !important; }
  html.sb-thu .sidebar .nav-text { display: none; }
  html.sb-thu .sidebar .nav-link { justify-content: center; text-align: center; padding-left: 0; padding-right: 0; }
  html.sb-thu .sidebar .nav-link i { margin-right: 0; }
  html.sb-thu .sidebar a.fw-bold { justify-content: center; }
}

/* Menu con (vd Pinterest Analytics dưới Thống Kê): thụt vào, chữ nhỏ hơn. */
.sidebar .nav-link.nav-con { padding-left: 2rem; font-size: .875rem; }
@media (min-width: 992px) {
  html.sb-thu .sidebar .nav-link.nav-con { padding-left: 0; }
}
