/**
 * Giao diện bản web — bám theo app điện thoại.
 *
 * Mọi màu lấy nguyên từ `app/src/main/res/values/colors.xml`, không tự chọn lại: bản web và
 * app là hai mặt của cùng một sản phẩm, lệch tông là người dùng thấy ngay như hai phần mềm
 * khác nhau. Tên biến giữ đúng tên bên Android để còn đối chiếu được.
 */

:root {
  --app-background: #F4F6F8;
  --app-surface: #FFFFFF;
  --app-surface-subtle: #ECF1F5;
  --app-text-primary: #2D333A;
  --app-text-secondary: #98A2AB;
  --app-text-muted: #B7BFC7;
  --app-border: #D7DEE4;
  --app-divider: #E2E7EC;
  --app-accent: #43C993;
  --app-accent-dark: #2DBA84;
  --app-danger: #FF5E63;
  --app-warn: #E9A13B;

  /* Thẻ gradient của dashboard — app_card_green_*/
  app_card_blue_* */ --card-green-start: #62DA92;
  --card-green-end: #3BCB8D;
  --card-blue-start: #6AB7F7;
  --card-blue-end: #4F9EEB;

  /* Chip trạng thái — scanned_answer_results_* */
  --chip-ok-bg: #EAFBF4;
  --chip-ok-stroke: #43C99A;
  --chip-ok-text: #24B47E;

  --radius-card: 16px;
  --radius-field: 8px;
  --shadow-card: 0 2px 10px rgba(45, 51, 58, .08);
  --shadow-raised: 0 6px 18px rgba(45, 51, 58, .12);
}

* {
  box-sizing: border-box;
}

/* Thuộc tính `hidden` phải LUÔN thắng.
   Quy tắc của trình duyệt là `[hidden] { display: none }` — độ ưu tiên bằng 0, nên bất kỳ
   lớp nào khai `display` cũng vô hiệu hoá nó, và JS đặt `el.x.hidden = true` thành ra không
   làm gì cả. Đã có ba chỗ dính: `.tray`, `.cap-fly`, `.stage-banner` đều phải tự thêm
   `[hidden] { display: none }`, còn `.pending-bar` thì quên — nên dòng vàng "N bài đã quét
   nhưng CHƯA LƯU" nằm lại trên màn kỳ thi sau khi đã lưu, và `.fs-icon` làm nút đèn hiện cả
   trên máy không có đèn. Chốt một lần ở đây thay vì nhớ thêm từng chỗ. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  background: var(--app-background);
  color: var(--app-text-primary);
  font: 15px/1.5 system-ui, "Segoe UI", Roboto, sans-serif;
  /* Header dính trên + footer dính dưới, nội dung ở giữa cuộn — đúng khung của app. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

h1,
h2,
h3 {
  margin: 0;
}

/* ── Khung ngoài: header · nội dung · footer ─────────────────────────────── */

.appbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: var(--app-surface);
  box-shadow: 0 2px 4px rgba(45, 51, 58, .06);
  position: sticky;
  top: 0;
  z-index: 20;
}

.appbar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  flex: 1;
  transition: opacity 0.15s ease;
}

.appbar .brand:hover {
  opacity: 0.85;
}

.appbar .logo {
  width: 34px;
  height: 34px;
  object-fit: contain;
  border-radius: 6px;
}

.appbar .app-name {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.2px;
}

/* Chip tài khoản — bg_user_chip của app */
.user-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  border-radius: 20px;
  background: var(--app-surface-subtle);
  border: 1px solid var(--app-border);
  font-size: 13px;
  font-weight: 600;
  color: var(--app-text-primary);
  cursor: pointer;
  transition: all 0.15s ease;
}

.user-chip:hover {
  background: #e2e8f0;
  border-color: #cbd5e1;
}

.appmain {
  flex: 1;
  min-height: 0;
}

.appfooter {
  background: var(--app-surface);
  box-shadow: 0 -2px 6px rgba(45, 51, 58, .06);
  padding: 12px;
  text-align: center;
  font-size: 11px;
  color: var(--app-text-primary);
}

.appfooter div+div {
  margin-top: 2px;
}

/* Mỗi màn hình là một section; router chỉ bật một cái. */
.screen {
  display: none;
  padding: 16px;
  max-width: 1100px;
  margin: 0 auto;
}

.screen.on {
  display: block;
}

.screen.wide {
  max-width: 1400px;
}

/* ── Tiêu đề trang + hàng hành động ──────────────────────────────────────── */

.page-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 6px 0 14px;
}

.page-head h1 {
  flex: 1;
  font-size: 22px;
  font-weight: 700;
}

.page-head .sub {
  color: var(--app-text-secondary);
  font-size: 13px;
}

.crumb {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 4px 0;
  color: var(--app-accent-dark);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.crumb:hover {
  text-decoration: underline;
}

/* ── Nút ─────────────────────────────────────────────────────────────────── */

button,
select,
input[type=text],
input[type=number],
textarea {
  font: inherit;
  color: var(--app-text-primary);
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--radius-field);
  padding: 9px 12px;
}

button {
  cursor: pointer;
}

button:hover {
  border-color: var(--app-accent);
}

/* Nút chính: xanh lá đặc, bo tròn hẳn — MaterialButton + cornerRadius 20dp của app. */
.btn-primary {
  background: var(--app-accent);
  border-color: var(--app-accent);
  color: #fff;
  font-weight: 700;
  border-radius: 22px;
  padding: 10px 18px;
}

.btn-primary:hover {
  background: var(--app-accent-dark);
  border-color: var(--app-accent-dark);
}

.btn-primary:disabled {
  background: var(--app-text-muted);
  border-color: var(--app-text-muted);
  cursor: not-allowed;
}

/* Nút pill nhạt — "Mẫu phiếu & Đáp án" trong activity_exam_session_list. */
.btn-pill {
  background: var(--chip-ok-bg);
  border: 1px solid var(--chip-ok-stroke);
  color: var(--app-accent-dark);
  font-weight: 700;
  font-size: 13px;
  border-radius: 18px;
  padding: 8px 14px;
}

.btn-pill:hover {
  background: #DFF7EC;
}

.btn-danger {
  color: var(--app-danger);
  border-color: var(--app-border);
}

.btn-danger:hover {
  border-color: var(--app-danger);
  background: #FFF2F2;
}

.btn-ghost {
  background: none;
  border-color: transparent;
  color: var(--app-text-secondary);
}

.btn-ghost:hover {
  background: var(--app-surface-subtle);
  border-color: transparent;
}

.icon-btn {
  width: 38px;
  height: 38px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  border-radius: 50%;
  color: var(--app-danger);
  font-size: 17px;
  line-height: 1;
}

.icon-btn:hover {
  background: #FFF2F2;
}

/* FAB tạo mới — FloatingActionButton, luôn ở góc phải dưới của màn hình. */
.fab {
  position: fixed;
  right: 24px;
  bottom: 84px;
  z-index: 15;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 0;
  background: var(--app-accent);
  color: #fff;
  font-size: 28px;
  line-height: 1;
  box-shadow: var(--shadow-raised);
  display: grid;
  place-items: center;
}

.fab:hover {
  background: var(--app-accent-dark);
}

/* ── Thẻ ─────────────────────────────────────────────────────────────────── */

.card {
  background: var(--app-surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 16px;
  margin-bottom: 12px;
}

.card:last-child {
  margin-bottom: 0;
}

.card-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--app-text-secondary);
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: 10px;
}

.chip {
  display: inline-block;
  padding: 4px 8px;
  border-radius: var(--radius-field);
  background: var(--app-surface-subtle);
  border: 1px solid var(--app-border);
  font-size: 13px;
  font-weight: 700;
}

.chip-ok {
  background: var(--chip-ok-bg);
  border-color: var(--chip-ok-stroke);
  color: var(--chip-ok-text);
}

.chip-warn {
  background: #FFF6E8;
  border-color: #F0C177;
  color: #B87716;
}

.muted {
  color: var(--app-text-secondary);
  font-size: 13px;
}

.hint {
  color: var(--app-text-secondary);
  font-size: 12px;
  margin: 4px 0 8px;
}

code {
  background: var(--app-surface-subtle);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
}

.empty-state {
  text-align: center;
  color: var(--app-text-secondary);
  padding: 40px 20px;
  font-size: 15px;
  white-space: pre-line;
}

/* ── Thanh công cụ trang chủ ─────────────────────────────────────────────── */

.toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 4px 0 20px;
}

.toolbar h1 {
  flex: 1;
  font-size: 22px;
  font-weight: 700;
}

.toolbar select {
  border-radius: 20px;
  padding: 9px 14px;
}

/* Ô tìm kiếm có kính lúp bên trong — như thanh công cụ của Notebook. */
.search {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: 20px;
  padding: 0 12px;
  min-width: 220px;
}

.search:focus-within {
  border-color: var(--app-accent);
  box-shadow: 0 0 0 3px rgba(67, 201, 147, .18);
}

.search .ico {
  font-size: 14px;
  color: var(--app-text-secondary);
}

.search input {
  border: 0;
  background: none;
  padding: 9px 0;
  flex: 1;
  min-width: 0;
}

.search input:focus {
  outline: none;
}

.search .clear {
  border: 0;
  background: none;
  padding: 2px 4px;
  color: var(--app-text-secondary);
  font-size: 13px;
  line-height: 1;
}

.search .clear:hover {
  color: var(--app-text-primary);
}

.section-title {
  font-size: 16px;
  font-weight: 700;
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-title+.template-row,
.section-title+.session-list {
  margin-bottom: 26px;
}

/* ── Mẫu kỳ thi theo môn ─────────────────────────────────────────────────────
   Hàng cuộn ngang như "Featured notebooks": mỗi thẻ là một môn với cấu hình phần thi
   sẵn. Cuộn ngang chứ không xuống dòng — hàng mẫu là thứ để chọn nhanh, không nên đẩy
   danh sách kỳ thi thật xuống dưới màn hình. */
.template-row {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 6px;
  scroll-snap-type: x proximity;
}

.template-row::-webkit-scrollbar {
  height: 8px;
}

.template-row::-webkit-scrollbar-thumb {
  background: var(--app-border);
  border-radius: 4px;
}

.tpl {
  flex: 0 0 190px;
  scroll-snap-align: start;
  border-radius: var(--radius-card);
  border: 0;
  padding: 14px;
  min-height: 132px;
  text-align: left;
  color: #fff;
  display: flex;
  flex-direction: column;
  gap: 4px;
  box-shadow: var(--shadow-card);
  cursor: pointer;
}

.tpl:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-raised);
}

.tpl .ico {
  font-size: 22px;
}

.tpl .name {
  font-size: 16px;
  font-weight: 700;
}

.tpl .cfg {
  margin-top: auto;
  font-variant-numeric: tabular-nums;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: .04em;
}

.tpl .foot {
  font-size: 12px;
  opacity: .9;
}

/* Sáu tông cho các môn — cùng họ với app_card_green/blue của app. */
.tpl.c1 {
  background: linear-gradient(135deg, #62DA92, #3BCB8D);
}

.tpl.c2 {
  background: linear-gradient(135deg, #6AB7F7, #4F9EEB);
}

.tpl.c3 {
  background: linear-gradient(135deg, #F7A76A, #EE8B4F);
}

.tpl.c4 {
  background: linear-gradient(135deg, #A98BF0, #8A67E6);
}

.tpl.c5 {
  background: linear-gradient(135deg, #5ED0C5, #35B8AD);
}

.tpl.c6 {
  background: linear-gradient(135deg, #F1789A, #E4557E);
}

/* ── Thẻ kỳ thi — item_exam_session ─────────────────────────────────────── */

.session-list {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.session-card {
  background: var(--app-surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 16px;
  text-align: left;
  border: 1px solid transparent;
  width: 100%;
  display: block;
}

.session-card:hover {
  border-color: var(--app-accent);
  box-shadow: var(--shadow-raised);
}

.session-card .row1 {
  display: flex;
  align-items: center;
  gap: 8px;
}

.session-card .name {
  margin-top: 10px;
  font-size: 15px;
  font-weight: 700;
}

.session-card .meta {
  margin-top: 6px;
  font-size: 13px;
  color: var(--app-text-secondary);
}

/* ── Bảng ────────────────────────────────────────────────────────────────── */

.table-wrap {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

th,
td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--app-divider);
  white-space: nowrap;
}

th {
  color: var(--app-text-secondary);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
}

th.num,
td.num {
  text-align: right;
}

tbody tr:hover {
  background: var(--app-surface-subtle);
}

tbody tr.fresh {
  animation: flash 1.2s ease-out;
}

@keyframes flash {
  from {
    background: var(--chip-ok-bg);
  }

  to {
    background: transparent;
  }
}

td.score {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

td.score.high {
  color: var(--chip-ok-text);
}

td.score.low {
  color: var(--app-danger);
}

.warn-dot {
  color: var(--app-warn);
  cursor: help;
}

/* ── Danh sách đáp án mẫu ────────────────────────────────────────────────── */

.key-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

/* Thẻ đáp án phải KHÁC MÀU nền của thẻ chứa nó, không chỉ khác bằng viền.
   Trước đây thẻ trắng nằm trên thẻ "Đáp án mẫu" cũng trắng, phân cách duy nhất là bóng đổ
   alpha .08 — hai thẻ cạnh nhau đọc ra thành MỘT thẻ rộng có đường nối ở giữa. Thêm viền
   #E2E7EC vẫn chưa đủ: ở 100% zoom một đường 1px nhạt thế gần như không thấy, người dùng báo
   lại đúng một câu "vẫn dính". Nền xám nhạt thì không cần nhìn kỹ mới thấy ranh giới, và mấy
   nút trắng bên trong nhờ đó cũng nổi lên. */
.key-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--app-surface-subtle);
  border-radius: var(--radius-card);
  border: 1px solid var(--app-border);
  padding: 12px 14px;
  font-size: 14px;
}

.key-list .grow {
  flex: 1;
  min-width: 0;
}

.key-list .sub {
  color: var(--app-text-secondary);
  font-size: 12px;
}

.key-list button {
  padding: 6px 10px;
  font-size: 13px;
}

/* ── Form (tạo kỳ thi) ───────────────────────────────────────────────────── */

.field {
  display: block;
  margin-bottom: 14px;
}

.field>.lbl {
  display: block;
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 6px;
}

.field input[type=text],
.field input[type=number],
.field textarea,
.field select {
  width: 100%;
}

.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-color: var(--app-accent);
  box-shadow: 0 0 0 3px rgba(67, 201, 147, .18);
}

/* Chips chọn mẫu phiếu — chipGroupFormType */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chips button {
  border-radius: 18px;
  padding: 8px 14px;
  font-size: 13px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
}

.chips button.on {
  background: var(--chip-ok-bg);
  border-color: var(--app-accent);
  color: var(--app-accent-dark);
  font-weight: 700;
}

/* Ba phần I/II/III */
.part {
  border: 1px solid var(--app-border);
  border-radius: var(--radius-field);
  padding: 12px;
  margin-bottom: 10px;
}

.part.off {
  opacity: .55;
}

.part-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
}

.part-head input[type=checkbox] {
  width: 18px;
  height: 18px;
  accent-color: var(--app-accent);
}

.part-head .cap {
  flex: 1;
}

.part-body {
  display: flex;
  gap: 12px;
  margin-top: 10px;
}

.part-body label {
  flex: 1;
  font-size: 12px;
  color: var(--app-text-secondary);
}

.part-body input {
  width: 100%;
  margin-top: 4px;
}

/* Thang điểm Phần II theo số ý đúng — bốn ô nhỏ nằm trong khối Phần II. */
.p2-scale {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--app-border);
}

.p2-cap {
  font-size: 12px;
  font-weight: 700;
  color: var(--app-text-secondary);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 6px;
}

.p2-scale .part-body {
  margin-top: 0;
  gap: 8px;
}

.p2-hint {
  margin-top: 8px;
  font-size: 12px;
  color: var(--app-accent-dark);
  background: var(--chip-ok-bg);
  border-radius: var(--radius-field);
  padding: 6px 10px;
}

.p2-hint:empty {
  display: none;
}

.total-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--chip-ok-bg);
  border: 1px solid var(--chip-ok-stroke);
  border-radius: var(--radius-field);
  padding: 10px 12px;
  margin-bottom: 14px;
  color: var(--app-accent-dark);
  font-weight: 700;
}

/* ── Hộp thoại ───────────────────────────────────────────────────────────── */

dialog {
  width: min(560px, 94vw);
  max-height: 90vh;
  padding: 0;
  background: var(--app-surface);
  color: var(--app-text-primary);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-raised);
}

dialog.wide {
  width: min(1000px, 94vw);
}

dialog::backdrop {
  background: rgba(45, 51, 58, .45);
}

.dlg-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--app-divider);
  position: sticky;
  top: 0;
  background: var(--app-surface);
  z-index: 1;
}

.dlg-head h2 {
  flex: 1;
  font-size: 17px;
  font-weight: 700;
}

.dlg-body {
  padding: 18px;
  overflow: auto;
  max-height: calc(90vh - 128px);
}

.dlg-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 18px;
  border-top: 1px solid var(--app-divider);
  position: sticky;
  bottom: 0;
  background: var(--app-surface);
}

.dlg-error {
  color: var(--app-danger);
  font-size: 13px;
  margin-right: auto;
  align-self: center;
}

/* Chi tiết một bài / một đáp án */
.detail-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 18px;
}

@media (max-width: 780px) {
  .detail-body {
    grid-template-columns: 1fr;
  }
}

.detail-image img {
  width: 100%;
  border-radius: var(--radius-field);
  border: 1px solid var(--app-border);
  background: #000;
}

.part-block {
  margin-bottom: 20px;
}

.part-block h3 {
  font-size: 13px;
  color: var(--app-text-secondary);
  margin-bottom: 8px;
}

.q-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px;
}

.q-grid.wide {
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}

.q {
  border: 1px solid var(--app-border);
  border-radius: 7px;
  padding: 5px 8px;
  background: var(--app-surface);
  font-size: 12px;
  line-height: 1.35;
}

.q .qn {
  color: var(--app-text-secondary);
  font-size: 11px;
}

.q .ans {
  font-weight: 700;
  font-size: 13px;
}

.q .exp {
  color: var(--app-text-secondary);
}

.q.correct {
  border-color: var(--app-accent);
  background: var(--chip-ok-bg);
}

.q.wrong {
  border-color: var(--app-danger);
  background: #FFF2F2;
}

.q.partial {
  border-color: var(--app-warn);
  background: #FFF6E8;
}

.q.blank {
  border-style: dashed;
  color: var(--app-text-secondary);
}

.q.edit {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
}

.q.edit:hover {
  border-color: var(--app-accent);
}

.q.edit .ans {
  font-size: 15px;
}

.q.wide {
  padding: 7px 9px;
}

.sub-row {
  display: flex;
  gap: 4px;
  margin-top: 4px;
}

.sub-cell {
  flex: 1;
  padding: 4px 2px;
  font-size: 12px;
  border-radius: 5px;
  border: 1px solid var(--app-border);
  background: var(--app-surface);
  cursor: pointer;
}

.sub-cell:hover {
  border-color: var(--app-accent);
}

.sub-cell.correct {
  border-color: var(--app-accent);
  background: var(--chip-ok-bg);
}

.sub-cell.blank {
  border-style: dashed;
  color: var(--app-text-secondary);
}

.p3-input {
  width: 100%;
  margin-top: 4px;
  padding: 5px 8px;
  font-size: 16px;
  font-family: ui-monospace, Consolas, monospace;
  letter-spacing: .18em;
}

.key-dirty {
  color: var(--app-warn);
  font-size: 13px;
}

.warn-text {
  color: var(--app-warn);
}

textarea {
  width: 100%;
  resize: vertical;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 13px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   MÀN QUÉT — phần dưới đây là giao diện camera, giữ nguyên cấu trúc đã tinh
   chỉnh cho việc dò marker; chỉ đổi màu theo tông sáng của app.
   ═══════════════════════════════════════════════════════════════════════════ */

.scan-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  gap: 16px;
}

@media (max-width: 900px) {
  .scan-layout {
    grid-template-columns: 1fr;
  }

  .stage {
    aspect-ratio: 3 / 4;
  }

  .screen {
    padding: 12px;
  }

  .fab {
    bottom: 76px;
    right: 16px;
  }
}

/* Chọn bước — hai bước đánh số, quét đáp án mẫu là bước 1. */
.seg {
  display: flex;
}

.seg button {
  border-radius: 0;
  border-right-width: 0;
  font-size: 13px;
}

.seg button:first-child {
  border-radius: 18px 0 0 18px;
}

.seg button:last-child {
  border-radius: 0 18px 18px 0;
  border-right-width: 1px;
}

.seg button.on {
  background: var(--app-accent);
  border-color: var(--app-accent);
  color: #fff;
  font-weight: 700;
}

.stage {
  position: relative;
  background: #000;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
}

.stage video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Khung phủ đúng vùng ẢNH của video (object-fit:contain nên có viền đen).
   app.js đặt left/top/width/height theo pixel — xem layoutGuide(). */
.guide {
  position: absolute;
  pointer-events: none;
  display: none;
}

.guide.on {
  display: block;
}

/* Mỗi ô = 20% cạnh khung, dán vào góc — khớp omr_marker::kMarkerRoiPercent.
   Vàng = chưa thấy (như app), xanh = đã bắt được marker ở góc đó. */
.roi {
  position: absolute;
  width: 20%;
  height: 20%;
  border: 3px solid rgba(255, 209, 71, .75);
  transition: border-color .12s linear, background-color .12s linear;
}

.roi.tl {
  top: 0;
  left: 0;
}

.roi.tr {
  top: 0;
  right: 0;
}

.roi.br {
  bottom: 0;
  right: 0;
}

.roi.bl {
  bottom: 0;
  left: 0;
}

.roi.found {
  border-color: var(--app-accent);
  background: rgba(67, 201, 147, .16);
}

.roi.missing {
  border-color: var(--app-danger);
}

.guide-hint {
  position: absolute;
  left: 50%;
  bottom: 8px;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 12px;
  color: #fff;
  background: rgba(0, 0, 0, .55);
  padding: 4px 10px;
  border-radius: 20px;
}

/* Khi toàn màn hình, dòng trạng thái của thanh đáy đã nói ĐÚNG câu này (handleDetectResult
   ghép thẳng nội dung ô gợi ý vào), nên giữ cả hai chỉ là hai bản sao — mà bản dán ở đáy
   khung ảnh thì rơi trúng chỗ khay ảnh. Ngoài toàn màn hình thì ngược lại: thanh đáy ẩn,
   ô gợi ý là chỗ duy nhất nói ra thiếu góc nào. */
.stage:fullscreen .guide-hint {
  display: none;
}

.stage:-webkit-full-screen .guide-hint {
  display: none;
}

.stage.pseudo-fs .guide-hint {
  display: none;
}

/* ── Toàn màn hình ───────────────────────────────────────────────────────────
   Hai đường: Fullscreen API (Chrome/Firefox/Android) và lớp .pseudo-fs dựng bằng CSS
   cho iOS Safari — Safari chỉ cho `<video>` vào fullscreen thật, mà làm vậy thì trình
   duyệt tự vẽ giao diện phát video đè lên và 4 ô ngắm biến mất.

   Mỗi selector phải là một rule RIÊNG: gộp `:fullscreen` với `:-webkit-full-screen`
   trong một danh sách sẽ khiến trình duyệt không hiểu một selector rồi bỏ luôn cả rule. */
.stage:fullscreen {
  width: 100vw;
  height: 100vh;
  aspect-ratio: auto;
  border-radius: 0;
}

.stage:-webkit-full-screen {
  width: 100vw;
  height: 100vh;
  aspect-ratio: auto;
  border-radius: 0;
}

.stage.pseudo-fs {
  position: fixed;
  inset: 0;
  z-index: 1000;
  width: 100vw;
  height: 100dvh;
  aspect-ratio: auto;
  border-radius: 0;
}

body.fs-lock {
  overflow: hidden;
}

/* ── Thanh trên: ← thoát · bộ đếm · đèn · Lưu (n) ────────────────────────────
   MỌI nút của chế độ toàn màn hình nằm ở đây, không còn nút nào ở đáy. Hai lần trước đều
   thất bại vì đáy khung có tới ba thứ tranh nhau cùng một dải: khay ảnh, hàng nút, và dòng
   gợi ý ướm phiếu — cái nào vẽ sau thì cướp cú chạm của cái trước, mà khay thì cao thấp
   thay đổi theo số ảnh nên không có con số `bottom` nào đúng cho mọi lúc.

   Nút ở TRÊN, khay ở DƯỚI: hai vùng không bao giờ gặp nhau, và đáy khung chỉ còn những thứ
   chỉ-đọc (khay + dòng trạng thái) nên chúng có tràn thế nào cũng không chặn được nút. */
.fs-top {
  display: none;
}

.stage:fullscreen .fs-top,
.stage.pseudo-fs .fs-top {
  display: flex;
}

.stage:-webkit-full-screen .fs-top {
  display: flex;
}

.fs-top {
  position: absolute;
  z-index: 8;
  left: 0;
  right: 0;
  top: 0;
  align-items: center;
  gap: 8px;
  padding: calc(10px + env(safe-area-inset-top)) 12px 10px;
  background: linear-gradient(rgba(0, 0, 0, .72), transparent);
  /* Dải nền trải hết bề ngang khung — để nó bắt chạm thì thao tác ướm phiếu ở phần trên
     khung bị nó nuốt. Chỉ các nút và chữ bên trong mới nhận. */
  pointer-events: none;
}

.fs-top>* {
  pointer-events: auto;
}

/* Nút tròn 44px — cỡ tối thiểu bấm được bằng ngón tay. */
.fs-icon {
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 20px;
  line-height: 1;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  border-color: rgba(255, 255, 255, .35);
}

.fs-top .btn-primary {
  flex: none;
  min-height: 44px;
  padding: 8px 18px;
  font-weight: 700;
}

.fs-top button.on {
  background: var(--app-warn);
  border-color: var(--app-warn);
  color: #1b1200;
}

/* Bộ đếm nằm giữa và tự co: nó là thứ duy nhất được phép cắt bớt ở hàng này. */
.fs-count {
  flex: 1;
  min-width: 0;
  text-align: center;
  color: #fff;
  font-size: 13px;
  opacity: .9;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Cụm đáy: khay ảnh + dòng trạng thái, không có nút nào ─────────────────── */
.fs-dock {
  position: absolute;
  z-index: 6;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  pointer-events: none;
}

.tray,
.fs-bar {
  pointer-events: auto;
}

/* Đang xem lại ảnh phiếu thì khung xem lại chiếm trọn khung và tự mang thanh nút của nó. */
.stage.reviewing .fs-dock,
.stage.reviewing .fs-top {
  display: none;
}

.fs-bar {
  display: none;
}

.stage:fullscreen .fs-bar,
.stage.pseudo-fs .fs-bar {
  display: block;
}

.stage:-webkit-full-screen .fs-bar {
  display: block;
}

.fs-bar {
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  background: linear-gradient(transparent, rgba(0, 0, 0, .78) 45%);
}

/* Một dòng, cắt bằng ellipsis. Xuống dòng tự do sẽ đẩy khay lên giữa khung mỗi khi thông
   báo dài — khay nhảy chỗ giữa lúc quét là thứ rất khó chịu. */
.fs-status {
  display: block;
  color: #fff;
  font-size: 14px;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Trạng thái quyền camera ─────────────────────────────────────────────── */
.stage-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 4px;
  text-align: center;
  color: #fff;
  padding: 24px;
  background: rgba(20, 24, 28, .88);
}

.stage-empty.hidden {
  display: none;
}

.stage-empty p {
  margin: 0;
  max-width: 460px;
}

.stage-empty .sub {
  color: #cfd5e0;
  font-size: 13px;
}

.stage-empty button {
  margin-top: 12px;
}

.stage-empty button.big {
  padding: 12px 22px;
  font-size: 16px;
}

.url-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.url-list a {
  display: block;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: var(--radius-field);
  padding: 8px 12px;
  color: #eaf7f1;
  text-decoration: none;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 14px;
}

/* Xem lại ảnh phiếu vừa đọc — xếp CHỒNG thật (thẻ kết quả → ảnh → thanh nút), không phủ
   đè: chữ và nút phủ lên ảnh sẽ che đúng phần đầu phiếu (SBD, mã đề) và cuối Phần III —
   mà đó chính là chỗ người dùng mở khung này ra để soi. */
.stage-empty.preview {
  display: flex;
  flex-direction: column;
  padding: 0;
  background: #000;
}

.preview-img {
  flex: 1;
  min-height: 0;
  width: 100%;
  object-fit: contain;
  display: block;
}

.preview-card {
  flex: none;
  text-align: left;
  padding: calc(10px + env(safe-area-inset-top)) 14px 10px;
  background: var(--app-surface);
  border-bottom: 1px solid var(--app-divider);
  color: var(--app-text-primary);
}

.preview-title {
  color: var(--chip-ok-text);
  font-weight: 700;
  font-size: 14px;
}

.preview-title.bad {
  color: var(--app-danger);
}

.preview-warn {
  color: #B87716;
  font-size: 12px;
  margin-top: 2px;
}

.stage-empty.preview .sub {
  color: var(--app-text-secondary);
  font-size: 12px;
}

.stage-empty.preview button {
  margin-top: 0;
  min-height: 44px;
}

/* Một thanh hành động DUY NHẤT ở đáy. Nút chính chiếm trọn bề ngang và nằm thấp nhất —
   tầm ngón cái khi cầm một tay; nút phụ xếp hàng trên. */
.preview-bar {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: var(--app-surface);
  border-top: 1px solid var(--app-divider);
}

.preview-acts {
  display: flex;
  gap: 8px;
}

.preview-acts button {
  flex: 1;
}

.preview-bar>button.btn-primary {
  width: 100%;
}

@media (min-width: 901px) {
  .preview-bar {
    flex-direction: row;
    justify-content: flex-end;
    align-items: center;
  }

  .preview-acts {
    flex: none;
  }

  .preview-bar>button.btn-primary {
    width: auto;
  }
}

/* Đang xem lại thì KHÔNG còn thanh điều khiển của chế độ quay: nó cũng dán ở đáy nên hai
   thanh chồng lên nhau, và các nút của nó ("Bắt đầu quét") trùng nghĩa với "Quét tiếp".
   Phải khai báo SAU các rule `.stage:fullscreen .fs-bar { display: flex }` ở trên. */
.stage.reviewing .fs-bar {
  display: none;
}

/* ── Khay ảnh đã quét + hiệu ứng chụp ────────────────────────────────────────
   Bản web của rv_tray_images / item_tray_image.xml: ảnh nhỏ 56×72, viền xanh nhạt, số thứ
   tự góc trên-trái, nút xoá góc trên-phải, badge điểm ở đáy. Kích thước giữ đúng của app —
   đủ to để nhận ra tờ nào, đủ nhỏ để một dãy vẫn không ăn vào khung ngắm.

   Vị trí do `.fs-dock` quyết định (khay là con đầu của cột), nên ở đây KHÔNG có `position`
   hay `bottom` — đó chính là thứ từng làm khay đè lên thanh nút. Chiều cao tự tính từ ảnh,
   cộng thêm chỗ cho badge điểm tràn xuống dưới. */
.tray {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 10px 16px 14px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.tray[hidden] {
  display: none;
}

.tray::-webkit-scrollbar {
  display: none;
}

.tray-item {
  position: relative;
  flex: 0 0 auto;
  width: 56px;
  height: 72px;
  border: 2px solid #81D4FA;
  border-radius: 6px;
  background: #000;
  padding: 0;
  cursor: pointer;
}

.tray-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
  display: block;
}

.tray-item:hover {
  border-color: var(--app-accent);
}

.tray-idx {
  position: absolute;
  top: 2px;
  left: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: rgba(0, 0, 0, .7);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
}

.tray-del {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #fff;
  border: 1px solid var(--app-border);
  color: var(--app-danger);
  font-size: 11px;
  line-height: 1;
}

.tray-badge {
  position: absolute;
  bottom: -9px;
  left: 50%;
  transform: translateX(-50%);
  min-width: 24px;
  height: 18px;
  padding: 0 6px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Ba mức màu khớp scoreColor() của TrayImagesAdapter. */
.tray-badge.ok {
  background: #4CAF50;
}

.tray-badge.warn {
  background: #FFC107;
  color: #1b1200;
}

.tray-badge.bad {
  background: #F44336;
}

/* Ảnh vừa chụp, giữ giữa khung một nhịp rồi bay xuống khay. Căn giữa bằng inset+margin
   chứ KHÔNG bằng transform: transform là thứ animation sẽ ghi lên, dùng nó để căn giữa thì
   ảnh nhảy về góc ngay khung đầu của lượt bay. */
.cap-fly {
  position: absolute;
  z-index: 7;
  inset: 0;
  margin: auto;
  width: 46%;
  height: 62%;
  padding: 8px;
  border-radius: 16px;
  background: #000;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .55);
  pointer-events: none;
}

.cap-fly[hidden] {
  display: none;
}

.cap-fly img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* ── Băng cảnh báo trên khung camera ─────────────────────────────────────────
   Dán ở ĐỈNH khung: đáy đã có thanh nút và dòng gợi ý ướm phiếu, mà lúc cảnh báo nổi lên
   thì người dùng vẫn đang cầm phiếu trong khung — che mất chỗ đó là che đúng thứ họ cần
   nhìn. Nền đặc + viền màu để đọc được trên cả phiếu trắng lẫn mặt bàn tối. */
.stage-banner {
  position: absolute;
  z-index: 5;
  left: 12px;
  right: 12px;
  top: calc(12px + env(safe-area-inset-top));
  padding: 10px 14px;
  border-radius: 10px;
  border-left: 4px solid var(--app-warn);
  background: rgba(0, 0, 0, .82);
  backdrop-filter: blur(4px);
  color: #fff;
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
}

.stage-banner[hidden] {
  display: none;
}

/* Khi toàn màn hình thì đỉnh khung đã có thanh nút — băng phải tụt xuống dưới nó, không thì
   nó che đúng nút Lưu và nút thoát. */
.stage:fullscreen .stage-banner {
  top: calc(70px + env(safe-area-inset-top));
}

.stage:-webkit-full-screen .stage-banner {
  top: calc(70px + env(safe-area-inset-top));
}

.stage.pseudo-fs .stage-banner {
  top: calc(70px + env(safe-area-inset-top));
}

.stage-banner.bad {
  border-left-color: var(--app-danger);
}

.stage-banner .title {
  font-weight: 700;
}

.stage-banner .sub {
  color: #cfd5e0;
  font-size: 12px;
  margin-top: 2px;
}

.status {
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-field);
  font-size: 14px;
  border: 1px solid var(--app-border);
  background: var(--app-surface);
}

.status[data-tone="ok"] {
  border-color: var(--app-accent);
  color: var(--app-accent-dark);
  background: var(--chip-ok-bg);
}

.status[data-tone="warn"] {
  border-color: #F0C177;
  color: #B87716;
  background: #FFF6E8;
}

.status[data-tone="bad"] {
  border-color: var(--app-danger);
  color: var(--app-danger);
  background: #FFF2F2;
}

.cam-meta {
  margin-top: 8px;
  font-size: 12px;
  color: var(--app-text-secondary);
  font-variant-numeric: tabular-nums;
}

.fallback {
  margin-top: 12px;
}

.fallback summary {
  cursor: pointer;
  color: var(--app-text-secondary);
  font-size: 13px;
}

.file-btn {
  display: inline-block;
  margin-top: 6px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--radius-field);
  padding: 8px 12px;
  cursor: pointer;
  font-size: 14px;
}

.file-btn:hover {
  border-color: var(--app-accent);
}

/* ── Menu nguồn: "Tạo đáp án" / "Chấm bài" ───────────────────────────────────
   Không dùng <select>: các mục là HÀNH ĐỘNG, không phải một giá trị đang được chọn —
   sau khi bấm không có gì "đang chọn" để hiện lại. Menu cũng cho phép mỗi mục một biểu
   tượng riêng, thứ <select> trên di động không vẽ được. */
.menu {
  position: relative;
  display: inline-flex;
}

.menu-btn {
  font-size: 13px;
  font-weight: 700;
  border-radius: 18px;
  padding: 6px 12px;
}

.menu-btn.btn-primary {
  background: var(--app-accent);
  border: 1px solid var(--app-accent-dark);
  color: #fff;
}

.menu-btn.btn-primary:hover {
  background: var(--app-accent-dark);
  border-color: var(--app-accent-dark);
}

.menu-btn .caret {
  font-size: 10px;
  opacity: .75;
  margin-left: 2px;
}

.menu-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 220px;
  padding: 6px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: 12px;
  box-shadow: var(--shadow-raised);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.menu-pop[hidden] {
  display: none;
}

.menu-pop button {
  border: 0;
  background: none;
  text-align: left;
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--app-text-primary);
}

.menu-pop button:hover {
  background: var(--chip-ok-bg);
  color: var(--app-accent-dark);
}

/* ── Nhật ký nhập tệp ──────────────────────────────────────────────────────── */
#importProgress {
  width: 100%;
  height: 8px;
  margin-bottom: 12px;
}

.import-log {
  max-height: 46vh;
  overflow: auto;
  border: 1px solid var(--app-divider);
  border-radius: var(--radius-field);
  background: var(--app-surface-subtle);
}

.import-log .line {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 7px 12px;
  border-bottom: 1px solid var(--app-divider);
  font-size: 13px;
}

.import-log .line:last-child {
  border-bottom: 0;
}

.import-log .line .what {
  flex: 1;
  min-width: 0;
}

.import-log .line[data-tone="ok"] {
  color: var(--app-accent-dark);
}

.import-log .line[data-tone="warn"] {
  color: var(--app-warn);
}

.import-log .line[data-tone="bad"] {
  color: var(--app-danger);
}

.import-log .line[data-tone="idle"] {
  color: var(--app-text-secondary);
}

/* ── Dòng "N tờ chưa lưu" trên màn kỳ thi ────────────────────────────────────
   Vàng chứ không xanh: đây không phải một thông báo thành công mà là một việc CÒN DỞ. */
.pending-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 12px;
  background: #FFF7E8;
  border: 1px solid var(--app-warn);
  border-radius: var(--radius-card);
  color: #8A5A12;
  font-weight: 600;
  font-size: 14px;
}

.pending-bar .grow {
  flex: 1;
  min-width: 160px;
}

/* ── Lưới "Kết quả vừa quét" ───────────────────────────────────────────────── */
.review-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

.review-card {
  position: relative;
  overflow: hidden;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.review-card img {
  display: block;
  width: 100%;
  aspect-ratio: 1200 / 1697;
  object-fit: cover;
  object-position: top center;
  background: #000;
  cursor: zoom-in;
}

.review-card .body {
  padding: 10px 12px 12px;
}

.review-card .who {
  font-weight: 700;
  font-size: 14px;
}

.review-card .sub {
  color: var(--app-text-secondary);
  font-size: 12px;
  margin-top: 2px;
}

.review-card .warn {
  color: var(--app-warn);
  font-size: 12px;
  margin-top: 6px;
}

.review-card .score {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 4px 10px;
  border-radius: 12px;
  font-weight: 700;
  font-size: 13px;
  color: #fff;
}

.review-card .score.ok {
  background: var(--app-accent);
}

.review-card .score.warn {
  background: var(--app-warn);
}

.review-card .score.bad {
  background: var(--app-danger);
}

.review-card .drop {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 50%;
  background: rgba(45, 51, 58, .62);
  border: 0;
  color: #fff;
  font-size: 14px;
}

.review-card .drop:hover {
  background: var(--app-danger);
}

/* ── Thử dò tờ giấy ──────────────────────────────────────────────────────────
   Dùng lại .review-grid / .review-card của màn "Kết quả vừa quét": cùng một dạng nội dung
   (một lưới thẻ, mỗi thẻ một tấm phiếu), nên không có lý do để trông khác nhau. */
.detect-entry {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 18px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.detect-entry .muted {
  flex: 1;
  min-width: 220px;
}

.dd-fields {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.dd-fields .field {
  margin: 0;
}

.dd-fields .hint {
  margin: 4px 0 0;
}

.dd-stats {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 8px;
}

/* Tấm cắt được có tỉ lệ tuỳ tứ giác bắt được — KHÔNG ép khổ như thẻ kết quả chấm, vì dáng
   sai chính là dấu hiệu bắt nhầm mà màn này sinh ra để nhìn thấy. */
.dd-card img {
  aspect-ratio: auto;
  max-height: 420px;
  object-fit: contain;
  background: #20262c;
}

.dd-card .dd-src {
  margin-top: 10px;
  max-height: 200px;
  border-radius: var(--radius-field);
}

.dd-miss {
  opacity: .85;
}

.dd-miss .body {
  padding-top: 40px;
}

/* Nhãn đường dò trên thẻ kết quả — hai đường có độ tin cậy khác nhau, phải phân biệt được. */
.dd-engine {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  background: var(--app-surface-subtle);
  color: var(--app-text-secondary);
  border: 1px solid var(--app-border);
  cursor: help;
}

/* Khối "đọc thử" trên thẻ kết quả — tách hẳn khỏi phần dò bằng một đường kẻ, vì đây là
   KẾT QUẢ CỦA MỘT TẦNG KHÁC: dò tờ giấy đúng mà đọc phiếu vẫn có thể trượt. */
.dd-scan {
  margin-top: 10px;
  padding: 8px 10px;
  border-top: 1px solid var(--app-divider);
  font-size: 13px;
  font-weight: 700;
}

.dd-scan .sub {
  font-weight: 500;
  margin-top: 2px;
}

.dd-scan.ok {
  color: var(--app-accent-dark);
}

.dd-scan.warn {
  color: var(--app-warn);
}

.dd-scan.bad {
  color: var(--app-danger);
}

/* Lớp phủ tứ giác tờ giấy trong khung quét — phải không ăn cú chạm, nếu không nó che hết
   thanh điều khiển của <video> khi quét từ video. */
.quad-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
}

/* ── Khung quét ở chế độ NGUỒN VIDEO ─────────────────────────────────────────
   Khác camera ở hai điểm nhìn thấy được: <video> mang thanh điều khiển thật (tua lại đúng
   tờ bị bỏ sót là việc chỉ có ở đây), và không có 4 ô ngắm.

   Thanh điều khiển của trình duyệt nằm sát đáy khung — đúng chỗ khay ảnh và dòng trạng thái
   đang đứng. Nâng cả cụm đáy lên trên nó, nếu không thì mỗi ảnh vào khay là mất luôn thanh
   tua. Con số 48px là chiều cao thanh điều khiển của Chrome/Safari. */
.stage.video-src .fs-dock {
  bottom: 48px;
}

/* Khung cao hơn 4:3 khi nguồn là VIDEO: phần lớn video quay phiếu là video DỌC của điện
   thoại, nhồi vào ô 4:3 thì tờ giấy chỉ còn một dải hẹp ở giữa.

   `position: absolute` cho <video> là bắt buộc, không phải để trang trí: chiều cao của
   .stage do `aspect-ratio`/`height` quyết định, và `height: 100%` trên một phần tử thay thế
   nằm trong ô lưới như thế bị tính thành `auto` — đo được 901×1602 trong ô 901×676, tức
   video DỌC bị khung cắt mất đầu và chân. Tệ hơn: drawQuadOverlay() lấy clientHeight của
   <video> làm chiều cao ảnh canvas, nên tứ giác cũng bị bóp theo. Neo bằng inset:0 cho hộp
   một kích thước xác định, và cả hai lỗi mất cùng lúc. */
.stage.video-src {
  aspect-ratio: auto;
  height: min(72vh, 820px);
}

.stage.video-src video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Thẻ nguồn video ở cột phải: tên tệp · giây/thời lượng · thanh tiến trình.
   Tên tệp có thể dài hơn cả thẻ nên phải cắt, không được đẩy thẻ rộng ra. */
.vid-name {
  font-weight: 600;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vid-time {
  margin: 4px 0 6px;
  font-size: 12px;
  color: var(--app-text-secondary);
}

#videoProg {
  display: block;
  width: 100%;
  height: 6px;
  appearance: none;
  border: 0;
  border-radius: 3px;
  overflow: hidden;
  cursor: pointer;
}

#videoProg::-webkit-progress-bar {
  background: rgba(127, 127, 127, .25);
}

#videoProg::-webkit-progress-value {
  background: var(--app-accent);
}

#videoProg::-moz-progress-bar {
  background: var(--app-accent);
}

/* ── Màn phát trực tiếp ────────────────────────────────────────────────────
   Lớp phủ phải nằm ĐÚNG trên khung hình, nên video và canvas cùng một hộp và canvas được
   kéo phủ kín. `pointer-events: none` là bắt buộc: canvas che hết thanh điều khiển của
   <video>, không có nó thì không bấm được tạm dừng. */
.dd-live-stage {
  position: relative;
  display: inline-block;
  max-width: 100%;
}

.dd-live-stage video {
  display: block;
  max-width: 100%;
  max-height: 62vh;
  border-radius: var(--radius-field);
  background: #14181c;
}

.dd-live-stage canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.dd-live-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 10px;
}

.dd-live-bar .muted {
  flex: 1;
  min-width: 200px;
}

/* ── Hộp thoại Đăng nhập (Authentication Dialog) ── */
/* ── Màn hình Đăng nhập Toàn trang (screenLogin / Auth Guard) ── */
.screen.screen-auth {
  max-width: 1040px;
  margin: 0 auto;
  padding: 32px 16px;
  min-height: calc(100dvh - 110px);
}

.screen.screen-auth.on {
  display: flex;
  align-items: center;
  justify-content: center;
}

.auth-page-container {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 48px;
  align-items: center;
  width: 100%;
  max-width: 980px;
}

.auth-page-hero {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding-right: 12px;
}

.hero-brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.hero-logo {
  width: 52px;
  height: 52px;
  object-fit: contain;
  border-radius: 10px;
}

.hero-title {
  font-size: 32px;
  font-weight: 900;
  letter-spacing: -0.5px;
  color: #1A6FC4;
}

.hero-tagline {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  color: var(--app-text-primary);
  margin: 0;
}

.hero-features {
  list-style: none;
  padding: 0;
  margin: 10px 0 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.hero-features li {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--app-text-primary);
  box-shadow: 0 2px 8px rgba(45, 51, 58, 0.04);
}

.feat-icon {
  font-size: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.auth-page-card {
  position: relative;
  background: #ffffff;
  border: 1px solid var(--app-border);
  border-radius: 24px;
  padding: 36px 32px 28px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 16px 40px rgba(45, 51, 58, 0.08);
}

.auth-card-header {
  text-align: center;
  margin-bottom: 24px;
}

.auth-logo-mobile {
  display: none;
  width: 48px;
  height: 48px;
  object-fit: contain;
  margin: 0 auto 12px;
}

.auth-card-title {
  font-size: 24px;
  font-weight: 800;
  color: #1A6FC4;
  letter-spacing: -0.3px;
  margin: 0;
}

.auth-card-sub {
  font-size: 13px;
  color: var(--app-text-secondary);
  margin: 6px 0 0;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
}

.auth-field label {
  font-size: 13px;
  font-weight: 600;
  color: var(--app-text-primary);
}

.input-with-icon {
  position: relative;
  display: flex;
  align-items: center;
}

.input-with-icon .field-icon {
  position: absolute;
  left: 12px;
  font-size: 15px;
  pointer-events: none;
  opacity: 0.7;
}

.input-with-icon input {
  width: 100%;
  height: 44px;
  padding: 0 40px 0 38px;
  border: 1.5px solid #d1d5db;
  border-radius: 10px;
  font-size: 14px;
  color: var(--app-text-primary);
  background: #fff;
  transition: border-color 0.2s, box-shadow 0.2s;
  outline: none;
}

.input-with-icon input:focus {
  border-color: #1A6FC4;
  box-shadow: 0 0 0 3px rgba(26, 111, 196, 0.15);
}

.pwd-toggle {
  position: absolute;
  right: 10px;
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 14px;
  padding: 4px;
  opacity: 0.6;
}

.pwd-toggle:hover {
  opacity: 1;
}

.auth-error {
  background: #fee2e2;
  border: 1px solid #f87171;
  color: #b91c1c;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 13px;
  text-align: left;
}

.auth-submit-btn {
  width: 100%;
  height: 46px;
  background: linear-gradient(135deg, #1A6FC4 0%, #155ba4 100%);
  color: #fff;
  border: none;
  border-radius: 10px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.5px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
  transition: all 0.2s ease;
  box-shadow: 0 4px 12px rgba(26, 111, 196, 0.25);
}

.auth-submit-btn:hover {
  background: linear-gradient(135deg, #155ba4 0%, #0f4886 100%);
  box-shadow: 0 6px 16px rgba(26, 111, 196, 0.35);
}

.auth-submit-btn:active {
  transform: scale(0.99);
}

.btn-spinner {
  width: 18px;
  height: 18px;
  border: 2.5px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.auth-divider {
  display: flex;
  align-items: center;
  margin: 18px 0;
  text-align: center;
  color: var(--app-text-secondary);
  font-size: 12px;
}

.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  border-bottom: 1px solid #e5e7eb;
}

.auth-divider span {
  padding: 0 10px;
}

.google-btn-container {
  display: flex;
  justify-content: center;
  margin-bottom: 8px;
}

.google-btn-container:empty {
  display: none;
}

.auth-google-btn {
  width: 100%;
  height: 44px;
  background: #ffffff;
  color: #374151;
  border: 1.5px solid #d1d5db;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.auth-google-btn:hover {
  background: #f9fafb;
  border-color: #9ca3af;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}

.google-icon {
  width: 18px;
  height: 18px;
}

.auth-footer {
  margin-top: 24px;
  text-align: center;
  font-size: 12px;
  color: var(--app-text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.auth-footer a {
  color: #1A6FC4;
  text-decoration: none;
}

.auth-footer a:hover {
  text-decoration: underline;
}

.auth-footer-dot {
  opacity: 0.5;
}

@media (max-width: 860px) {
  .auth-page-container {
    grid-template-columns: 1fr;
    max-width: 440px;
  }

  .auth-page-hero {
    display: none;
  }

  .auth-logo-mobile {
    display: block;
  }

  .auth-page-card {
    padding: 28px 20px 22px;
  }
}

/* ── Popup User Info Dropdown ── */
.user-menu-container {
  position: relative;
  display: inline-block;
}

.user-popup-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 260px;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid var(--app-border);
  padding: 8px 0;
  z-index: 100;
  animation: popupFadeIn 0.15s ease-out;
}

@keyframes popupFadeIn {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.user-popup-menu.hidden {
  display: none;
}

.user-popup-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
}

.user-avatar-circle {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #EEF2F6;
  color: #1A6FC4;
  display: grid;
  place-items: center;
  font-size: 18px;
  flex-shrink: 0;
}

.user-info-text {
  min-width: 0;
  flex: 1;
}

.user-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--app-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.user-email {
  font-size: 12px;
  color: var(--app-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.user-popup-divider {
  margin: 4px 0;
  border: none;
  border-top: 1px solid var(--app-border);
}

.user-popup-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: transparent;
  border: none;
  color: var(--app-text-primary);
  font-size: 13.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s;
}

.user-popup-item:hover {
  background: var(--app-surface-subtle);
}

.user-popup-item.logout {
  color: #ef4444;
}

.user-popup-item.logout:hover {
  background: #fef2f2;
}

.item-icon {
  font-size: 16px;
}

/* ── Hộp thoại Góp ý / Báo lỗi (Feedback Dialog) ── */
.feedback-dialog {
  border: none;
  border-radius: 20px;
  padding: 0;
  background: transparent;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
  max-width: 460px;
  width: 92vw;
}

.feedback-dialog::backdrop {
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(4px);
}

.feedback-card {
  position: relative;
  background: #ffffff;
  border-radius: 20px;
  padding: 28px 24px 20px;
  display: flex;
  flex-direction: column;
}

.feedback-title {
  font-size: 18px;
  font-weight: 800;
  color: var(--app-text-primary);
  text-align: center;
  margin-bottom: 6px;
}

.feedback-source {
  font-size: 13px;
  color: var(--app-text-secondary);
  font-style: italic;
  margin-bottom: 16px;
  text-align: center;
}

.feedback-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.feedback-field textarea {
  width: 100%;
  min-height: 120px;
  padding: 12px;
  border: 1.5px solid #d1d5db;
  border-radius: 10px;
  font-size: 14px;
  font-family: inherit;
  color: var(--app-text-primary);
  background: #fff;
  resize: vertical;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
}

.feedback-field textarea:focus {
  border-color: #1A6FC4;
  box-shadow: 0 0 0 3px rgba(26, 111, 196, 0.15);
}

.feedback-attach-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.btn-pick-image {
  padding: 6px 14px;
  border-radius: 8px;
  border: 1.5px solid #d1d5db;
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.btn-pick-image:hover {
  background: #f3f4f6;
  border-color: #9ca3af;
}

.feedback-image-name {
  font-size: 13px;
  color: var(--app-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.btn-remove-image {
  background: #fee2e2;
  border: none;
  color: #b91c1c;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 12px;
  display: grid;
  place-items: center;
}

.feedback-preview-card {
  width: 100%;
  height: 140px;
  border-radius: 10px;
  overflow: hidden;
  border: 1.5px solid #e5e7eb;
  background: #f8fafc;
  display: flex;
  align-items: center;
  justify-content: center;
}

.feedback-preview-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.feedback-error {
  background: #fee2e2;
  border: 1px solid #f87171;
  color: #b91c1c;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  text-align: left;
}

.feedback-actions {
  display: flex;
  gap: 12px;
  margin-top: 6px;
}

.btn-feedback-cancel {
  flex: 1;
  height: 42px;
  border: 1.5px solid #d1d5db;
  border-radius: 10px;
  background: #fff;
  color: var(--app-text-primary);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}

.btn-feedback-cancel:hover {
  background: #f3f4f6;
}

.btn-feedback-submit {
  flex: 1;
  height: 42px;
  border: none;
  border-radius: 10px;
  background: #1A6FC4;
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background 0.2s, transform 0.1s;
}

.btn-feedback-submit:hover {
  background: #155ba4;
}

.btn-feedback-submit:active {
  transform: scale(0.99);
}

/* ── Hộp thoại Bộ đề thi từ máy chủ (Question Sets) ── */
.qsets-search-wrap {
  display: flex;
  align-items: center;
  position: relative;
  flex: 1;
  max-width: 380px;
  margin: 0 12px;
}

.qsets-search-wrap .search-icon {
  position: absolute;
  left: 10px;
  font-size: 13px;
  pointer-events: none;
  opacity: 0.6;
}

.qsets-search-wrap input {
  width: 100%;
  height: 36px;
  padding: 0 32px 0 30px;
  border-radius: 8px;
  border: 1.5px solid var(--app-border);
  font-size: 13.5px;
  color: var(--app-text-primary);
  background: var(--app-surface);
  outline: none;
  transition: border-color 0.15s;
}

.qsets-search-wrap input:focus {
  border-color: #1A6FC4;
}

.btn-refresh {
  padding: 6px 12px;
  border-radius: 8px;
  border: 1.5px solid var(--app-border);
  background: var(--app-surface);
  color: var(--app-text-primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s;
}

.btn-refresh:hover {
  background: var(--app-surface-subtle);
}

.qsets-body {
  min-height: 380px;
  max-height: 72vh;
  overflow-y: auto;
  padding: 16px;
}

.qsets-state-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 48px 16px;
  color: var(--app-text-secondary);
  font-size: 14px;
  text-align: center;
}

.qsets-state-box.error {
  color: #b91c1c;
}

.btn-spinner.large {
  width: 32px;
  height: 32px;
  border-width: 3px;
  border-color: #cbd5e1;
  border-top-color: #1A6FC4;
}

.qsets-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

.qset-card {
  background: #ffffff;
  border: 1.5px solid var(--app-border);
  border-radius: 14px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
  transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}

.qset-card:hover {
  border-color: #93c5fd;
  box-shadow: 0 6px 16px rgba(26, 111, 196, 0.08);
  transform: translateY(-2px);
}

.qset-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.qset-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--app-text-primary);
  line-height: 1.35;
}

.qset-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.qset-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--app-surface-subtle);
  color: var(--app-text-secondary);
}

.qset-badge.subject {
  background: #eff6ff;
  color: #1d4ed8;
}

.qset-badge.grade {
  background: #f0fdf4;
  color: #15803d;
}

.qset-badge.status {
  background: #fefce8;
  color: #a16207;
}

.qset-meta {
  font-size: 12.5px;
  color: var(--app-text-secondary);
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.qset-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.qset-actions button {
  flex: 1;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all 0.15s ease;
}

.btn-qset-save {
  background: #1A6FC4;
  color: #fff;
  border: none;
}

.btn-qset-save:hover {
  background: #155ba4;
}

.btn-qset-preview {
  background: #fff;
  border: 1.5px solid var(--app-border);
  color: var(--app-text-primary);
}

.btn-qset-preview:hover {
  background: var(--app-surface-subtle);
  border-color: #cbd5e1;
}

/* ── Hộp thoại Nhập đáp án từ Excel ─────────────────────────────────────── */
.excel-dialog {
  max-width: 820px;
  width: 95vw;
}

.excel-import-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-height: 68vh;
  overflow-y: auto;
  padding: 4px 0;
}

.excel-template-banner {
  background: linear-gradient(135deg, #f0fdf4 0%, #e0f2fe 100%);
  border: 1.5px solid #bae6fd;
  border-radius: 12px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.template-title {
  font-size: 14px;
  font-weight: 700;
  color: #0369a1;
}

.template-desc {
  font-size: 12.5px;
  color: #334155;
  margin-top: 2px;
}

.template-download-buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.btn-template-download {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: #ffffff;
  color: #0284c7;
  border: 1.5px solid #7dd3fc;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition: all 0.15s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.btn-template-download:hover {
  background: #f0f9ff;
  border-color: #0284c7;
  color: #0369a1;
  transform: translateY(-1px);
}

.excel-dropzone {
  border: 2px dashed #94a3b8;
  border-radius: 12px;
  padding: 24px 20px;
  text-align: center;
  background: #f8fafc;
  cursor: pointer;
  transition: all 0.2s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.excel-dropzone:hover,
.excel-dropzone.dragover {
  border-color: #1A6FC4;
  background: #eff6ff;
}

.dropzone-icon {
  font-size: 32px;
  line-height: 1;
}

.dropzone-text {
  font-size: 13.5px;
  color: #475569;
}

.dropzone-text strong {
  color: #0f172a;
}

.excel-error-box {
  background: #fef2f2;
  border: 1.5px solid #fecaca;
  border-radius: 10px;
  padding: 14px 16px;
  color: #991b1b;
}

.excel-error-title {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 8px;
}

.excel-error-list {
  font-size: 13px;
  line-height: 1.6;
  max-height: 160px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.excel-error-item {
  display: flex;
  gap: 6px;
}

.excel-error-item .row-badge {
  font-weight: 700;
  background: #fee2e2;
  color: #b91c1c;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
  height: fit-content;
}

.excel-preview-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.preview-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 2px;
}

.preview-summary {
  font-size: 14px;
  font-weight: 700;
  color: #1e293b;
}

.preview-filename {
  font-size: 12.5px;
  color: #64748b;
  background: #f1f5f9;
  padding: 3px 10px;
  border-radius: 6px;
  font-weight: 500;
}

.excel-keys-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  max-height: 280px;
  overflow-y: auto;
  padding: 2px;
}

.excel-key-card {
  background: #fff;
  border: 1.5px solid #e2e8f0;
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: all 0.15s ease;
}

.excel-key-card:hover {
  border-color: #94a3b8;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}

.excel-key-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.excel-key-code {
  font-size: 15px;
  font-weight: 700;
  color: #0f172a;
}

.excel-key-badge {
  font-size: 11.5px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 6px;
  background: #f0fdf4;
  color: #166534;
}

.excel-key-badge.exists {
  background: #fefce8;
  color: #854d0e;
}

.excel-key-meta {
  font-size: 12.5px;
  color: #64748b;
  display: flex;
  gap: 8px;
}

.excel-key-actions {
  display: flex;
  margin-top: 4px;
}

.btn-preview-key-card {
  width: 100%;
  padding: 6px 10px;
  background: #f8fafc;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: #334155;
  cursor: pointer;
  transition: all 0.15s;
}

.btn-preview-key-card:hover {
  background: #e2e8f0;
  color: #0f172a;
}

.excel-foot {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--app-border);
}

/* ── Kho Mẫu phiếu & Đáp án Excel (Template Gallery) ─────────────────────── */
.template-gallery-dialog {
  max-width: 960px;
  width: 95vw;
}

.gallery-head {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.gallery-head-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
}

.gallery-head-title {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.gallery-head-subtitle {
  font-size: 13px;
  color: #64748b;
}

.template-gallery-tabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.gallery-tab {
  padding: 6px 14px;
  border-radius: 20px;
  border: 1.5px solid #cbd5e1;
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  color: #475569;
  cursor: pointer;
  transition: all 0.15s ease;
}

.gallery-tab:hover {
  background: #f1f5f9;
  color: #0f172a;
}

.gallery-tab.active {
  background: #1A6FC4;
  border-color: #1A6FC4;
  color: #fff;
}

.template-gallery-body {
  max-height: 70vh;
  overflow-y: auto;
  padding: 8px 2px;
}

.template-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

.gallery-card {
  background: #fff;
  border: 1.5px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: all 0.2s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

.gallery-card:hover {
  transform: translateY(-2px);
  border-color: #94a3b8;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.gallery-card-thumb {
  position: relative;
  background: #f8fafc;
  height: 180px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #e2e8f0;
  cursor: pointer;
}

.gallery-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  transition: transform 0.3s ease;
}

.gallery-card-thumb:hover img {
  transform: scale(1.04);
}

.gallery-thumb-overlay {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  gap: 6px;
}

.gallery-card-thumb:hover .gallery-thumb-overlay {
  opacity: 1;
}

.gallery-excel-icon-box {
  width: 68px;
  height: 68px;
  border-radius: 16px;
  background: #f0fdf4;
  border: 2px solid #bbf7d0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  color: #16a34a;
}

.gallery-card-content {
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 8px;
}

.gallery-card-title {
  font-size: 14.5px;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.35;
}

.gallery-card-desc {
  font-size: 12.5px;
  color: #64748b;
  line-height: 1.45;
  flex: 1;
}

.gallery-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}

.gallery-tag {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 6px;
  background: #f1f5f9;
  color: #475569;
}

.gallery-tag.pdf {
  background: #fee2e2;
  color: #b91c1c;
}

.gallery-tag.excel {
  background: #f0fdf4;
  color: #15803d;
}

.gallery-card-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

.gallery-card-actions a,
.gallery-card-actions button {
  flex: 1;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.btn-gallery-preview {
  background: #f8fafc;
  border: 1.5px solid #cbd5e1;
  color: #334155;
}

.btn-gallery-preview:hover {
  background: #e2e8f0;
  color: #0f172a;
}

.btn-gallery-download {
  background: #1A6FC4;
  border: 1.5px solid #1A6FC4;
  color: #fff;
}

.btn-gallery-download:hover {
  background: #155ba4;
  border-color: #155ba4;
}

.btn-gallery-download.excel-btn {
  background: #16a34a;
  border-color: #16a34a;
}

.btn-gallery-download.excel-btn:hover {
  background: #15803d;
  border-color: #15803d;
}

/* ── Modal xem trước phóng to mẫu phiếu OMR ─────────────────────────────── */
.template-preview-dialog {
  max-width: 900px;
  width: 95vw;
  max-height: 92vh;
}

.preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.preview-head-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.template-preview-body {
  max-height: 80vh;
  overflow-y: auto;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #f8fafc;
  border-radius: 8px;
  padding: 12px;
}

.preview-img-container {
  width: 100%;
  display: flex;
  justify-content: center;
}

.preview-img-container img {
  max-width: 100%;
  max-height: 74vh;
  object-fit: contain;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  background: #fff;
}