/* Bài tập ảnh chứng minh — giao diện dùng cho lớp học, ưu tiên đọc nhanh trên
   màn hình rộng (admin) và ngón tay trên điện thoại (học viên).

   Chủ đạo: trắng + xanh nước biển. Mọi cặp màu chữ/nền dưới đây đã được tính
   tỉ lệ tương phản, đạt tối thiểu 4.5:1 cho chữ nhỏ và 3:1 cho viền ô nhập —
   đổi số hex thì phải tính lại, đừng ước lượng bằng mắt. */

:root {
  /* Chrome/Samsung trên Android có chế độ "tự đổi web sang tối". Không khai báo
     thì nó đảo màu theo phỏng đoán và làm nhoè hết các badge/alert (vốn dựa vào
     cặp nền nhạt + chữ đậm). Một dòng này là cách từ chối. */
  color-scheme: light;

  /* Xanh nước biển: 6.94:1 với chữ trắng nên nút bấm và link dùng chung một màu. */
  --accent: #0a5c9c;
  --accent-hover: #084b80;
  /* Thanh điều hướng và vùng nhấn mạnh — trắng trên nền này đạt 10.93:1. */
  --accent-deep: #083f68;
  --accent-soft: #e3effa;
  --accent-soft-2: #f1f7fd;

  --ink: #0e1a26;
  --ink-2: #3a5568;
  /* Màu của mọi tiêu đề cột, mốc thời gian, và ghi chú phân biệt hai bạn trùng
     tên. Phải đọc được cả trên nền nhạt của badge (5.25:1) chứ không chỉ trên trắng. */
  --ink-3: #4f6578;

  /* Viền trang trí: đường phân cách, viền thẻ. Không phải thành phần tương tác
     nên không cần 3:1. */
  --line: #cfe0ec;
  --line-2: #e7f0f7;
  /* Viền Ô NHẬP LIỆU là thành phần giao diện -> cần 3:1 trên nền trắng (3.11:1),
     nếu không thì người mắt kém không thấy đâu là chỗ gõ. */
  --line-input: #7896aa;

  --bg: #f3f8fc;
  --card: #ffffff;

  --ok: #177a4a;
  --ok-soft: #e6f5ed;
  --warn: #8a5600;
  --warn-soft: #fcf1dc;
  --bad: #b3261e;
  --bad-soft: #fdeceb;

  --radius: 10px;
  /* Bóng pha sắc xanh thay vì xám trung tính, để hoà với nền. */
  --shadow: 0 1px 2px rgb(8 63 104 / 6%), 0 4px 16px rgb(8 63 104 / 6%);
  --shadow-lg: 0 8px 32px rgb(8 63 104 / 16%);
  --mono: ui-monospace, "Cascadia Mono", Consolas, monospace;
}

* { box-sizing: border-box; }

/* Thuộc tính hidden phải thắng mọi display của class (.row là display:flex,
   nếu không có dòng này thì [hidden] vô tác dụng trên các element đó). */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font: 15px/1.55 "Segoe UI", system-ui, -apple-system, "Noto Sans", sans-serif;
  color: var(--ink);
  background: var(--bg);
}

h1, h2, h3 { line-height: 1.25; margin: 0; font-weight: 650; }
h1 { font-size: 1.35rem; color: var(--accent-deep); }
h2 { font-size: 1.1rem; color: var(--accent-deep); }
h3 { font-size: 0.95rem; }

a { color: var(--accent); }

/* ------------------------------------------------------------------ layout */

.topbar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 22px;
  /* Thanh xanh đậm làm mảng màu chủ đạo, phần còn lại của trang giữ nền sáng. */
  background: var(--accent-deep);
  border-bottom: 1px solid var(--accent-deep);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 20;
  flex-wrap: wrap;
  /* Chừa sẵn chiều cao để nội dung không nhảy khi JS vẽ thanh này. */
  min-height: 53px;
}

.topbar .brand {
  font-weight: 680;
  letter-spacing: -0.01em;
  margin-right: auto;
  display: flex;
  align-items: center;
  gap: 2px;
  color: #fff;
  text-decoration: none;
}
.topbar .brand:hover { color: #fff; opacity: 0.88; }

.topbar nav { display: flex; gap: 4px; flex-wrap: wrap; }

.topbar nav a {
  padding: 6px 11px;
  border-radius: 7px;
  text-decoration: none;
  /* 7.62:1 trên nền xanh đậm. */
  color: rgb(255 255 255 / 80%);
  font-weight: 550;
}
.topbar nav a:hover { background: rgb(255 255 255 / 14%); color: #fff; }
.topbar nav a[aria-current="page"] { background: #fff; color: var(--accent-deep); }

/* Nút trên thanh xanh phải đảo màu, nút trắng mặc định sẽ chìm mất.
   Cần .topbar button.ghost (không chỉ .topbar button) vì .ghost khai báo sau và
   có cùng độ ưu tiên — sẽ thắng nếu không nâng độ cụ thể ở đây. */
.topbar button,
.topbar button.ghost {
  background: rgb(255 255 255 / 12%);
  border-color: rgb(255 255 255 / 34%);
  color: #fff;
}
.topbar button:hover:not(:disabled),
.topbar button.ghost:hover:not(:disabled) {
  background: rgb(255 255 255 / 24%);
  border-color: rgb(255 255 255 / 55%);
  color: #fff;
}
.topbar :focus-visible { outline-color: #fff; }

main { max-width: 1240px; margin: 0 auto; padding: 22px; }
main.narrow { max-width: 620px; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow);
}
.card + .card { margin-top: 16px; }
.card > header {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding-bottom: 12px;
  /* Gạch chân xanh nhạt phân tách tiêu đề với nội dung. */
  border-bottom: 1px solid var(--line-2);
}
.card > header h2 { margin-right: auto; }
.card > header h1 { margin-right: auto; }

.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row.tight { gap: 6px; }
.spread { display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.grow { flex: 1 1 auto; min-width: 0; }
.stack > * + * { margin-top: 12px; }

.muted { color: var(--ink-3); }
.small { font-size: 0.86rem; }
.mono { font-family: var(--mono); font-size: 0.88em; }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------------------- forms */

label { display: block; font-weight: 550; font-size: 0.9rem; margin-bottom: 5px; }

input[type="text"], input[type="password"], input[type="search"],
input[type="datetime-local"], input[type="number"], textarea, select {
  width: 100%;
  padding: 9px 11px;
  font: inherit;
  color: var(--ink);
  background: var(--card);
  /* Viền đậm hơn viền trang trí: ô nhập là chỗ người dùng phải tìm ra để bấm vào. */
  border: 1px solid var(--line-input);
  border-radius: 8px;
}
input:hover:not(:disabled), textarea:hover, select:hover { border-color: var(--accent); }
textarea { min-height: 120px; resize: vertical; font-family: inherit; }

input:focus-visible, textarea:focus-visible, select:focus-visible,
button:focus-visible, a:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

input[type="file"] {
  width: 100%;
  padding: 14px;
  border: 1.5px dashed var(--line-input);
  border-radius: 8px;
  background: var(--accent-soft-2);
  cursor: pointer;
}
input[type="file"]:hover { border-color: var(--accent); background: var(--accent-soft); }

/* Ô sửa tại chỗ trong bảng: viền rất nhạt khi nghỉ để biết là sửa được, đậm lên
   khi trỏ vào. Cần input.inline-edit chứ không chỉ .inline-edit — quy tắc chung
   dùng input[type="text"] có độ ưu tiên cao hơn class đơn. */
input.inline-edit {
  border-color: var(--line);
  background: transparent;
  padding: 5px 7px;
}
input.inline-edit:hover { border-color: var(--accent); background: var(--card); }
input.inline-edit:focus { border-color: var(--accent); background: var(--card); }

button {
  font: inherit;
  font-weight: 570;
  padding: 9px 15px;
  border-radius: 8px;
  border: 1px solid var(--line-input);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
}
button:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent); }
button:disabled { opacity: 0.55; cursor: not-allowed; }

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
button.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

button.danger { color: var(--bad); border-color: #f0cdca; background: var(--bad-soft); }
button.danger:hover:not(:disabled) { background: #fbdedc; border-color: var(--bad); }

button.ghost { border-color: transparent; background: transparent; color: var(--ink-2); }
button.ghost:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent); }

button.small, .small button { padding: 5px 10px; font-size: 0.85rem; }
button.big { padding: 14px 20px; font-size: 1.02rem; width: 100%; }

/* <a> trông như nút. Trước đây là <button> lồng trong <a>: HTML không hợp lệ,
   trình đọc màn hình đọc thành 2 điều khiển, và Enter khi focus vào nút bên trong
   thì không đi theo link. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-weight: 570;
  padding: 9px 15px;
  border-radius: 8px;
  border: 1px solid var(--line-input);
  background: var(--card);
  color: var(--accent);
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--accent-soft); border-color: var(--accent); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.small { padding: 5px 10px; font-size: 0.85rem; }
/* <a> không có thuộc tính disabled như <button>, phải tự làm. */
.btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Chừa chỗ cho thanh điều hướng trước khi JS vẽ nó, để nội dung không nhảy. */
.topbar-placeholder { height: 53px; background: var(--accent-deep); }
@media (max-width: 720px) { .topbar-placeholder { height: 84px; } }

/* ------------------------------------------------------------------ tables */

/* border-collapse: separate là BẮT BUỘC khi header sticky: với collapse, viền do
   table vẽ chứ không do cell, nên viền dưới của header không đi theo header khi
   cuộn và các dòng trông như dính liền vào tiêu đề. */
table { width: 100%; border-collapse: separate; border-spacing: 0; }
th, td {
  text-align: left;
  padding: 9px 10px;
  box-shadow: inset 0 -1px 0 var(--line-2);
  vertical-align: middle;
}
th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
  font-weight: 650;
  box-shadow: inset 0 -1px 0 var(--accent);
  position: sticky;
  top: 0;
  /* Nền nhạt màu xanh để khi cuộn, hàng chữ không dính vào tiêu đề. */
  background: var(--accent-soft-2);
  z-index: 1;
}
tbody tr:hover { background: var(--accent-soft-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap {
  overflow: auto;
  max-height: 74vh;
  margin: 0 -18px;
  padding: 0 18px;
}
.table-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Ô mã PIN trong hộp thoại Link & QR. */
.pin-box {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--accent-soft-2);
}
.pin-value {
  font-family: var(--mono);
  font-size: 1.3rem;
  font-weight: 650;
  letter-spacing: 0.22em;
  color: var(--accent-deep);
}

/* ------------------------------------------------------ chọn nhiều dòng */

/* Cột checkbox: hẹp, không co lại khi bảng chật. */
.check-col { width: 34px; padding-right: 0; }
.check-col input[type="checkbox"] {
  width: 17px;
  height: 17px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
  display: block;
}

tbody tr.row-selected { background: var(--accent-soft); }
tbody tr.row-selected:hover { background: #d8e8f8; }

/* Thanh hành động cho các dòng đã chọn. Dính dưới thanh điều hướng để khi cuộn
   danh sách dài vẫn thấy số lượng đang chọn và nút xoá. */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 9px 12px;
  margin-bottom: 10px;
  border: 1px solid var(--accent);
  border-radius: 8px;
  background: var(--accent-soft);
  color: var(--accent-deep);
  position: sticky;
  top: 53px;
  z-index: 3;
}
@media (max-width: 720px) {
  /* Trên điện thoại thanh điều hướng cao 2 dòng. */
  .bulk-bar { top: 84px; }
}

/* ------------------------------------------------------------------- chips */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 100px;
  font-size: 0.79rem;
  font-weight: 600;
  white-space: nowrap;
}
/* Nhãn dài là câu, không phải nhãn: nowrap khiến nó không xuống dòng được và
   đẩy tràn cả thẻ card trên điện thoại. */
.badge.long { white-space: normal; text-align: left; border-radius: 8px; }
.badge.pending  { background: var(--warn-soft); color: var(--warn); }
.badge.approved { background: var(--ok-soft);   color: var(--ok); }
.badge.rejected { background: var(--bad-soft);  color: var(--bad); }
.badge.missing  { background: var(--line-2);    color: var(--ink-3); }
.badge.late     { background: var(--bad-soft);  color: var(--bad); }
.badge.info     { background: var(--accent-soft); color: var(--accent); }
/* auto-fit thay vì flex: ở ~768px thì 5 ô vừa một hàng và ô thứ 6 kéo dài hết
   chiều ngang một mình, trông như lỗi. */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 10px; }
.stat {
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--accent-soft-2);
  /* Vạch xanh bên trái để khối số liệu đọc thành một nhóm. */
  border-left: 3px solid var(--accent);
}
.stat b {
  display: block;
  font-size: 1.5rem;
  font-weight: 640;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  color: var(--accent-deep);
}
.stat span { font-size: 0.82rem; color: var(--ink-3); }

/* ------------------------------------------------------------------ alerts */

.alert {
  padding: 11px 14px;
  border-radius: 8px;
  border: 1px solid;
  font-size: 0.92rem;
}
.alert.err  { background: var(--bad-soft);  border-color: #f2d3d1; color: #8c1e17; }
.alert.ok   { background: var(--ok-soft);   border-color: #c9e7d7; color: #0f5c37; }
.alert.warn { background: var(--warn-soft); border-color: #f0dfba; color: #7a4d00; }
.alert.info { background: var(--accent-soft); border-color: #cfe0fa; color: #164a9f; }
.alert:empty { display: none; }

/* ----------------------------------------------------------- autocomplete */

.combo { position: relative; }
.combo-list {
  /* position:fixed do JS đặt (xem attachCombo): danh sách nằm trong .table-wrap
     có overflow:auto sẽ bị CẮT MẤT, z-index không cứu được. */
  position: absolute;
  inset-inline: 0;
  top: calc(100% + 4px);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgb(16 20 30 / 14%);
  max-height: 268px;
  overflow: auto;
  z-index: 60;
  list-style: none;
  margin: 0;
  padding: 4px;
}
.combo-list[hidden] { display: none; }
.combo-list li {
  padding: 9px 11px;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  gap: 8px;
  align-items: baseline;
}
.combo-list li[aria-selected="true"], .combo-list li:hover { background: var(--accent-soft); }
.combo-list li .note {
  font-size: 0.82rem;
  color: var(--ink-3);
  margin-left: auto;
  /* Ghi chú là dấu phân biệt duy nhất giữa hai bạn trùng tên -> không cho nó bị
     ngắt dòng thành từng chữ khi ô nhập hẹp. */
  white-space: nowrap;
  flex: 0 0 auto;
}
/* Dòng thông báo (đang tìm / không thấy / lỗi mạng) không phải lựa chọn. */
.combo-list li.msg { cursor: default; display: block; color: var(--ink-2); font-size: 0.88rem; }
.combo-list li.msg:hover { background: none; }
.combo-list li.msg.err { color: var(--bad); }

/* ------------------------------------------------------------------ toasts */

#toast-host {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 99;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: stretch;
  width: min(520px, calc(100vw - 28px));
}
.toast {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  box-shadow: 0 4px 20px rgb(16 20 30 / 18%);
}
.toast button { flex: 0 0 auto; padding: 0 6px; line-height: 1.4; }

/* ------------------------------------------------------------------ dialogs */

dialog.modal {
  border: none;
  border-radius: 10px;
  padding: 0;
  max-width: 480px;
  width: 94vw;
  max-height: 90dvh;
  overflow: auto;
  box-shadow: 0 12px 48px rgb(16 20 30 / 22%);
}
dialog.modal::backdrop { background: rgb(12 14 20 / 45%); }
dialog.modal .modal-body { border: none; box-shadow: none; margin: 0; }
.modal-preview {
  max-width: 100%;
  max-height: 220px;
  object-fit: contain;
  border: 1px solid var(--line);
  border-radius: 8px;
  align-self: center;
}

/* Danh sách tên sắp bị xoá. Cuộn được để hộp thoại không dài vô hạn khi chọn 40 bạn. */
.modal-list {
  margin: 0;
  padding: 9px 11px;
  max-height: 34vh;
  overflow: auto;
  font: inherit;
  font-size: 0.88rem;
  white-space: pre-wrap;
  background: var(--accent-soft-2);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* Chỉ đọc bằng trình đọc màn hình, không hiện ra. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ images */

.thumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.thumb {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--line-2);
  line-height: 0;
}
/* Nút bọc quanh ảnh để mở xem to được bằng bàn phím; <img> có onclick thì không
   focus vào được. */
.thumb .zoom {
  display: block;
  padding: 0;
  border: none;
  background: none;
  border-radius: 0;
  cursor: zoom-in;
}
.thumb img { display: block; width: 132px; height: 132px; object-fit: cover; }
/* Chỉ làm mờ ẢNH, không mờ cả nhãn "lần 2" — mờ nhãn thì chữ trắng trên nền đen
   62% tụt xuống ~2:1, không đọc được. */
.thumb.old img { opacity: 0.45; }
.thumb .del {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 6px;
  background: rgb(255 255 255 / 92%);
  line-height: 1;
  font-size: 17px;
}
.thumb .tag {
  position: absolute;
  bottom: 0;
  inset-inline: 0;
  padding: 2px 6px;
  font-size: 0.72rem;
  background: rgb(0 0 0 / 62%);
  color: #fff;
  line-height: 1.4;
}

dialog.lightbox {
  border: none;
  padding: 0;
  background: transparent;
  max-width: 96vw;
  max-height: 96vh;
}
dialog.lightbox::backdrop { background: rgb(12 14 20 / 82%); }
dialog.lightbox img { max-width: 96vw; max-height: 86vh; display: block; border-radius: 8px; }
dialog.lightbox .cap { color: #e8eaee; font-size: 0.86rem; padding: 8px 2px; text-align: center; }
dialog.lightbox .close {
  position: sticky;
  top: 0;
  margin-left: auto;
  display: block;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 8px;
  background: rgb(255 255 255 / 92%);
  font-size: 18px;
  line-height: 1;
}

/* Ô xem ảnh mở ra: nền xanh nhạt + vạch bên trái để thấy rõ nó thuộc dòng trên. */
.detail-cell {
  background: var(--accent-soft-2);
  border-left: 3px solid var(--accent);
}

/* --------------------------------------------------------- bulk upload grid */

/* KHÔNG overflow ở đây: danh sách gợi ý tên nằm trong bảng, overflow:auto sẽ cắt
   mất nó — mà gán tên là thao tác chính của trang này. */
.grid-wrap { margin: 0 -18px; padding: 0 18px; }

.drop-zone { border-radius: 9px; transition: background 0.15s, outline-color 0.15s; outline: 2px dashed transparent; }
.drop-zone.dragging {
  background: var(--accent-soft);
  outline-color: var(--accent);
  outline-offset: 6px;
}

.match-row td { vertical-align: middle; }
/* Dòng chưa gán tên để màu vàng nhạt — giữa nền xanh thì nó nổi hẳn lên, đúng ý
   nghĩa "chỗ này còn phải làm". */
.match-row.unassigned { background: var(--warn-soft); }
.match-row.unassigned:hover { background: #f9e8c4; }
.match-row img.preview { width: 62px; height: 62px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line); display: block; }
.match-row .fname { font-size: 0.84rem; color: var(--ink-2); max-width: 260px; }

.progress {
  height: 7px;
  border-radius: 100px;
  background: var(--line-2);
  overflow: hidden;
}
.progress i { display: block; height: 100%; background: var(--accent); transition: width 0.2s; }

/* -------------------------------------------------------------- utilities */

.spinner {
  width: 15px; height: 15px;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2s; }
  * { transition: none !important; }
}

.empty { padding: 34px 16px; text-align: center; color: var(--ink-3); }

details.raw summary { cursor: pointer; color: var(--ink-2); font-size: 0.88rem; }

@media (max-width: 720px) {
  main { padding: 14px; }
  .card { padding: 14px; }
  .table-wrap { margin: 0 -14px; padding: 0 14px; }
  .thumb img { width: 104px; height: 104px; }

  /* Thanh trên: brand + đăng xuất hàng 1, menu hàng 2 — chủ động 2 hàng thay vì
     để nó tự gãy thành 3 hàng với nút đăng xuất trơ một mình. */
  .topbar { gap: 10px; padding: 8px 14px; min-height: 0; }
  .topbar .brand { font-size: 0.95rem; }
  .topbar nav { order: 3; flex: 1 1 100%; flex-wrap: nowrap; overflow-x: auto; }
  .hide-sm { display: none; }

  /* Bảng 5 cột thành thẻ: cuộn ngang thì kéo sang phải là mất cột tên, giáo viên
     phải kéo qua kéo lại từng dòng để biết đang xem bài của ai. */
  .cards-sm .table-wrap { max-height: none; overflow: visible; }
  .cards-sm thead { display: none; }
  .cards-sm table, .cards-sm tbody, .cards-sm tr, .cards-sm td { display: block; }
  .cards-sm tr {
    border: 1px solid var(--line);
    border-radius: 9px;
    margin-bottom: 8px;
    padding: 10px 12px;
  }
  .cards-sm tbody tr:hover { background: none; }
  .cards-sm td {
    box-shadow: none;
    padding: 3px 0;
    display: flex;
    gap: 10px;
    align-items: baseline;
  }
  .cards-sm td::before {
    content: attr(data-label);
    color: var(--ink-3);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex: 0 0 76px;
  }
  /* Ô đầu tiên của thẻ (tên) không cần nhãn; các ô sau lấy nhãn từ data-label.
     Dùng .name-cell thay vì :first-child vì cột đầu giờ là checkbox. */
  .cards-sm td.name-cell { padding-bottom: 6px; }
  .cards-sm td.name-cell::before { content: none; }
  .cards-sm td:first-child:not(.check-col) { padding-bottom: 6px; }
  .cards-sm td:first-child:not(.check-col)::before { content: none; }
  .cards-sm td.num, .cards-sm th.num { text-align: left; }

  /* Ở dạng thẻ, checkbox đưa lên góc phải để bấm được bằng ngón tay mà không đẩy
     tên xuống dòng. */
  .cards-sm tr { position: relative; padding-right: 44px; }
  .cards-sm td.check-col {
    position: absolute;
    top: 10px;
    right: 10px;
    width: auto;
    padding: 0;
  }
  .cards-sm td.check-col::before { content: none; }
  .cards-sm td.check-col input[type="checkbox"] { width: 22px; height: 22px; }
  /* Dòng chi tiết (ảnh + nút duyệt) trải hết chiều ngang thẻ. */
  .cards-sm td[colspan] { display: block; }
  .cards-sm td[colspan]::before { content: none; }
  .grid-wrap { margin: 0; padding: 0; }
}

/* Học viên dùng điện thoại: chữ và nút to hơn. Nền trắng để ảnh xem trước nổi rõ. */
body.student { background: var(--card); }
body.student main { max-width: 540px; padding: 18px 16px 60px; }
body.student h1 { font-size: 1.35rem; color: var(--accent-deep); }
body.student .card { box-shadow: none; }
body.student input, body.student button { font-size: 1rem; }
body.student input[type="text"], body.student input[type="search"] { padding: 12px 13px; }
/* Dải xanh trên đỉnh để trang nộp bài nhìn cùng một bộ với trang admin. */
body.student::before {
  content: "";
  display: block;
  height: 5px;
  background: var(--accent);
}
