:root{
  --paper:#EAEEF1; --panel:#FFFFFF; --panel-2:#F6F8FA;
  --ink:#17212C; --ink-soft:#5C6976; --ink-faint:#909AA6;
  --line:#DBE1E7; --line-soft:#E9EDF1;
  --accent:#1E5F74; --accent-2:#163F4D; --accent-soft:#E2ECF0;
  --seal:#B23A33;
  --hi:#2F9E6F; --hi-bg:#E7F4EC; --md:#BE8418; --md-bg:#F8EFD7; --lo:#C0463A; --lo-bg:#F8E5E2;
  --card:#FFFFFF; --hov:#FBFCFD; --line-hover:#C4CCD4;
  --hi-text:#1D6E4D; --md-text:#8A5F10; --lo-text:#9C352B;
  --toast-bg:#17212C; --toast-fg:#FFFFFF;
  --radius:14px; --radius-sm:9px;
  --shadow:0 1px 2px rgba(20,33,44,.04), 0 8px 28px -14px rgba(20,33,44,.22);
  --mono:'IBM Plex Mono',ui-monospace,Menlo,Consolas,monospace;
  --sans:'Be Vietnam Pro',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
}
/* ---------- giao diện tối (đặt trong trang Cài đặt; "auto" theo hệ điều hành,
   được đổi thành light/dark bằng đoạn script nhỏ ở <head> mỗi trang) ---------- */
:root[data-theme="dark"]{
  --paper:#10161D; --panel:#171F28; --panel-2:#1D2732;
  --ink:#E8EEF4; --ink-soft:#A7B4C0; --ink-faint:#75828F;
  --line:#2B3743; --line-soft:#242F3A;
  --accent:#3D96AF; --accent-2:#5FB3CC; --accent-soft:#173038;
  --seal:#D06158;
  --hi:#3EB584; --hi-bg:#14301F; --md:#D19A2F; --md-bg:#33290F; --lo:#E06457; --lo-bg:#3A201C;
  --card:#1B242E; --hov:#212C37; --line-hover:#3D4C5B;
  --hi-text:#7FD3AC; --md-text:#E4B75B; --lo-text:#F09A8F;
  --toast-bg:#2A3540; --toast-fg:#E8EEF4;
  --shadow:0 1px 2px rgba(0,0,0,.3), 0 8px 28px -14px rgba(0,0,0,.6);
  color-scheme:dark;
}
/* ---------- cỡ chữ (trang Cài đặt): phóng toàn trang, giữ nguyên bố cục ---------- */
html[data-font="small"] body{zoom:.88}
html[data-font="large"] body{zoom:1.12}
html[data-font="xlarge"] body{zoom:1.28}
*{box-sizing:border-box}
html,body{margin:0}
body{font-family:var(--sans);background:var(--paper);color:var(--ink);
  -webkit-font-smoothing:antialiased;line-height:1.5;font-size:15px}
button{font-family:inherit;cursor:pointer}
.mono{font-family:var(--mono)}

/* ---------- top bar ---------- */
.topbar{display:flex;align-items:center;gap:18px;padding:14px 22px;
  background:var(--panel);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:30}
/* Nhảy neo (#mục-nào-đó) không để mục ấy chui thẳng dưới thanh trên cùng dính. */
[id]{scroll-margin-top:84px}
.brand{display:flex;align-items:center;gap:12px;min-width:0}
.logo-wrap{width:42px;height:42px;flex:none;display:grid;place-items:center}
.logo{width:42px;height:42px;object-fit:contain;display:block}
.seal{width:40px;height:40px;flex:none;border-radius:50%;border:2px solid var(--seal);
  color:var(--seal);display:grid;place-items:center;transform:rotate(-7deg);
  font-weight:700;font-size:11px;letter-spacing:.06em;line-height:1;text-align:center;
  box-shadow:inset 0 0 0 2px var(--card), inset 0 0 0 3px rgba(178,58,51,.25)}
.brand h1{font-size:16px;font-weight:600;margin:0;letter-spacing:-.01em;white-space:nowrap}
/* Phụ đề LUÔN nằm gọn một dòng. Cho nó xuống dòng thì cả thanh trên cùng cao
   thêm một tầng — thanh này dính (position:sticky) nên tầng ấy ăn mất chỗ của
   nội dung ở mọi trang, suốt cả phiên. Câu này lại do người dùng tự đặt ở trang
   Cài đặt nên dài ngắn không biết đâu mà lường, vì thế cắt bằng "…" khi thanh
   chật; nguyên câu vẫn đọc được ở tooltip (xem title= trong các bản mẫu). */
.brand .sub{font-size:11.5px;color:var(--ink-faint);margin-top:1px;letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar .spacer{flex:1}
.lanpill{display:flex;align-items:center;gap:9px;background:var(--panel-2);
  border:1px solid var(--line);border-radius:999px;padding:6px 13px 6px 11px;font-size:12.5px;color:var(--ink-soft)}
.lanpill .dot{width:8px;height:8px;border-radius:50%;background:var(--hi);
  box-shadow:0 0 0 3px rgba(47,158,111,.18);animation:pulse 2.6s ease-in-out infinite}
@keyframes pulse{50%{box-shadow:0 0 0 6px rgba(47,158,111,0)}}
.lanpill .addr{font-family:var(--mono);color:var(--ink);font-size:12px}
.offline{font-size:11.5px;color:var(--ink-faint);display:flex;align-items:center;gap:6px}
.offline svg{width:14px;height:14px}
.iconbtn{display:grid;place-items:center;width:38px;height:38px;border-radius:10px;
  border:1px solid var(--line);background:var(--card);color:var(--ink-soft);flex:none;
  transition:all .14s}
.iconbtn:hover{border-color:var(--line-hover);color:var(--accent);transform:rotate(20deg)}
.iconbtn svg{width:19px;height:19px}

/* ---------- trang cài đặt ---------- */
.set-wrap{max-width:820px;margin:0 auto;padding:26px 22px 80px}
.set-head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin:4px 2px 18px}
.set-head h2{margin:0;font-size:22px;font-weight:600;letter-spacing:-.02em}
.set-head p{margin:0;color:var(--ink-soft);font-size:13px}
.set-head .back{margin-left:auto;font-size:13px;color:var(--ink-soft);text-decoration:none;
  padding:6px 4px}
.set-head .back:hover{color:var(--accent);text-decoration:underline}
.set-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);margin-bottom:18px;overflow:hidden}
.set-card > h3{margin:0;padding:14px 22px;font-size:13px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--accent);border-bottom:1px solid var(--line-soft);
  display:flex;align-items:center;gap:9px}
.set-card > h3 svg{width:16px;height:16px}
.set-body{padding:8px 22px 18px}
/* dòng giải thích đầu một thẻ cài đặt — nói rõ mục này ảnh hưởng tới ai */
.set-note{margin:10px 0 4px;padding:9px 12px;border-radius:var(--radius-sm);
  background:var(--panel-2);border:1px solid var(--line-soft);
  font-size:12px;color:var(--ink-soft);line-height:1.6}
.set-note a{color:var(--accent-2)}
.set-row{display:grid;grid-template-columns:240px 1fr;gap:16px;align-items:center;
  padding:12px 0;border-bottom:1px solid var(--line-soft)}
.set-row:last-child{border-bottom:none}
.set-row .k{font-size:13.5px;font-weight:600}
.set-row .k .sub{display:block;font-weight:400;font-size:11.5px;color:var(--ink-faint);margin-top:2px}
.set-row .k .restag{display:inline-block;font-size:10px;font-weight:600;color:var(--md-text);
  background:var(--md-bg);padding:1px 7px;border-radius:6px;margin-left:6px;vertical-align:middle}
.set-row select,.set-row input[type=text],.set-row input[type=password],.set-row input[type=number]{
  width:100%;box-sizing:border-box;font-family:var(--sans);font-size:13.5px;color:var(--ink);
  border:1px solid var(--line);border-radius:8px;padding:9px 11px;background:var(--panel-2)}
.set-row input.mono{font-family:var(--mono);font-size:12.5px}
/* Ba ngưỡng độ tin cậy: ô số hẹp lại để ba dòng xếp đều nhau, kèm một nhãn
   đúng màu mà bước 3 sẽ tô — thấy ngay con số vừa gõ ra màu gì. */
.nguong-row{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--ink-soft)}
.nguong-row + .nguong-row{margin-top:7px}
.nguong-row label{flex:none;width:118px;font-weight:600;color:var(--ink);font-size:12.5px}
.set-row .nguong-row input[type=number]{width:78px;flex:none;text-align:right;padding:7px 9px}
.nguong-vd{font-size:11px;font-weight:600;padding:2px 8px;border-radius:6px}
.nguong-vd.hi{background:var(--hi-bg);color:var(--hi-text)}
.nguong-vd.md{background:var(--md-bg);color:var(--md-text)}
.nguong-vd.lo{background:var(--lo-bg);color:var(--lo-text)}
.set-row .v .hint{font-size:11.5px;color:var(--ink-faint);margin-top:5px;line-height:1.5}
.set-row .v .hint .mono{font-size:11px}
.seg{display:flex;gap:6px;flex-wrap:wrap}
.seg button{border:1px solid var(--line);background:var(--card);color:var(--ink-soft);
  border-radius:8px;padding:8px 14px;font-size:13px;font-weight:600;transition:all .14s}
.seg button:hover{border-color:var(--line-hover)}
.seg button.on{background:var(--accent);border-color:var(--accent);color:#fff}
.keyrow{display:flex;gap:8px;align-items:center}
.keyrow input{flex:1;min-width:0}
/* nút vuông chỉ có biểu tượng (vd nút mở thư mục ở cuối dòng đường dẫn) */
.btn.icon{flex:0 0 auto;padding:8px 10px;line-height:0}
.btn.icon svg{width:17px;height:17px;display:block}

/* ---------- khối mô hình tải thêm (trang Cài đặt) ----------
   Một dòng gọn: đèn tình trạng • chữ • nút. Thanh tiến độ chỉ hiện lúc đang
   tải. Có cái đèn thì liếc một cái là biết máy đã có mô hình hay chưa, khỏi
   phải đọc chữ. */
.mh-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.mh-row .btn{padding:7px 13px;font-size:12.5px}
/* display:inline-flex ở .btn đè mất quy tắc mặc định của [hidden] */
.mh-row .btn[hidden]{display:none}
.mh-row .spacer{flex:1}
.mh-den{flex:none;width:9px;height:9px;border-radius:99px;background:var(--ink-faint)}
.mh-den.co{background:var(--hi-text)}
.mh-den.dang{background:var(--md-text);animation:mh-tho 1.1s ease-in-out infinite}
.mh-den.loi{background:var(--lo-text)}
.mh-tt{font-size:12.5px;color:var(--ink-soft)}
@keyframes mh-tho{0%,100%{opacity:1}50%{opacity:.25}}
.set-row .v .progress{margin-top:9px}
.set-row .v .progress[hidden]{display:none}

/* ---------- dòng đường dẫn thư mục (trang Cài đặt) ----------
   [Chọn thư mục…] [đường dẫn — chỉ đọc, chọn bằng hộp thoại] … [📂 mở] */
/* min-width:0 để đường dẫn DÀI bị cắt bằng "…" thay vì nong rộng cả dòng */
.set-row .v{min-width:0}
.pathrow{display:flex;gap:9px;align-items:center;min-width:0}
.pathrow .btn{flex:0 0 auto;padding:9px 13px;font-size:13px}
.pathrow .openDir{margin-left:auto}      /* luôn nằm sát mép phải của dòng */
.pathval{flex:1;min-width:0;font-family:var(--mono);font-size:12.5px;color:var(--ink);
  background:var(--panel-2);border:1px solid var(--line);border-radius:8px;padding:9px 11px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ---------- hộp thoại duyệt thư mục trên máy chủ ---------- */
.fb-bar{display:flex;gap:7px;align-items:center;flex-wrap:wrap;padding:12px 20px}
.fb-bar .btn{padding:6px 11px;font-size:12.5px}
.fb-chip{border:1px solid var(--line);background:var(--card);color:var(--ink-soft);
  border-radius:999px;padding:6px 12px;font-size:12.5px;white-space:nowrap}
.fb-chip:hover{border-color:var(--line-hover);color:var(--ink);background:var(--hov)}
.fb-list{max-height:44vh;overflow:auto;background:var(--panel-2);
  border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.fb-item{display:flex;gap:10px;align-items:center;width:100%;text-align:left;border:none;
  background:none;color:var(--ink);font-size:13.5px;padding:9px 20px}
.fb-item:hover{background:var(--hov)}
.fb-item svg{width:16px;height:16px;color:var(--ink-faint);flex:0 0 auto}
.fb-empty{padding:18px 20px;font-size:13px;color:var(--ink-faint)}
.fb-loc{padding:0 20px 12px}
.fb-loc input[type=search]{flex:1;min-width:120px;font-size:13px;padding:7px 11px;
  border:1px solid var(--line);border-radius:8px;background:var(--panel-2);color:var(--ink)}
.fb-loc .fb-an{display:flex;gap:6px;align-items:center;font-size:12.5px;
  color:var(--ink-soft);white-space:nowrap;cursor:pointer}
.fb-item.an{color:var(--ink-soft)}          /* thư mục ẩn — mờ hơn nhưng vẫn chọn được */
.fb-item.an svg{opacity:.55}
.fb-foot{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:16px 20px 18px}
/* Thanh nổi cuối trang: nút Lưu bên trái, "← Về trang chính" cuối bên phải.
   Màn hình hẹp thì xuống dòng thay vì tràn ngang; dòng "Lưu tại: …" co giãn
   lấp chỗ trống và tự ngắt, để đường dẫn dài không đẩy nút ra ngoài. */
.set-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center;position:sticky;bottom:0;
  padding:14px 4px;background:linear-gradient(transparent,var(--paper) 30%)}
.set-actions .note{flex:1 1 150px;min-width:0;text-align:right;overflow-wrap:anywhere;
  font-size:12px;color:var(--ink-faint)}
/* <a> kế thừa line-height của body, <button> thì không — cho cao bằng nút bên cạnh */
.set-actions a.btn{text-decoration:none;line-height:normal}
/* các nút chuyển trang đi cùng nhau: xuống dòng thì xuống cả nhóm, vẫn nằm bên phải */
.set-actions .set-nav{display:flex;flex-wrap:wrap;gap:inherit;margin-left:auto}
.restart-note{display:none;background:var(--md-bg);border:1px solid var(--md);color:var(--md-text);
  border-radius:var(--radius-sm);padding:11px 15px;font-size:13px;margin:0 0 14px}
.restart-note.show{display:block}
@media (max-width:700px){
  .set-row{grid-template-columns:1fr;gap:6px}
  /* màn hình hẹp: đường dẫn xuống dòng riêng, hai nút nằm dưới */
  .pathrow{flex-wrap:wrap}
  .pathval{order:-1;flex:1 0 100%}
  /* nút gọn lại để hai nút đầu vừa một dòng, thanh nổi bớt che nội dung */
  .set-actions{gap:8px;padding:10px 0}
  .set-actions .btn{padding:8px 12px}
}

/* ---------- shell ---------- */
/* Đáy 22px chứ không phải 64px: khung nội dung đo chỗ trống còn lại của màn hình
   rồi mới định chiều cao danh sách (xem syncChipsHeight), nên mỗi pixel đệm ở đây
   bị trừ thẳng vào chiều cao ấy. 22px vừa đủ để nút cuối trang không dính mép dưới
   — cũng đúng bằng lề của nút nổi .next-float. */
/* 1320 -> 1520: khung rộng hơn dồn gần hết phần thêm cho .canvas (cột trái ăn
   1.25fr trong 2fr nên lấy hơn nửa), mà đó đúng là cột đang chật — danh sách
   trường trên biểu mẫu vừa có ô đã ghép, vừa có dữ liệu mẫu, vừa có nút định
   dạng, chữ dài là dồn cục ngay. */
.shell{max-width:1520px;margin:0 auto;padding:26px 22px 22px;display:grid;
  grid-template-columns:236px 1fr;gap:26px;align-items:start}
/* Bước 3 (ghép trường): bảng cần bề ngang rộng nhất có thể để hai cột trường-mẫu/
   trường-nguồn đủ chỗ cân nhau mà khỏi cuộn ngang — bỏ hẳn giới hạn 1520px của
   khung khi đang ở bước này. go() bật/tắt lớp này lúc chuyển bước (xem app.js). */
body.step3-wide .shell{max-width:none}

/* stepper */
.stepper{position:sticky;top:96px;display:flex;flex-direction:column;gap:2px}
.stepper .lead{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);
  margin:0 0 12px 4px;font-weight:600}
.step{display:flex;gap:13px;align-items:flex-start;padding:12px 13px;border-radius:var(--radius-sm);
  border:1px solid transparent;text-align:left;background:none;width:100%;transition:background .15s,border-color .15s}
.step:hover:not(.active){background:var(--card)}
.step.active{background:var(--card);border-color:var(--line);box-shadow:var(--shadow)}
.step:disabled{cursor:not-allowed;opacity:.55}
.step .num{width:26px;height:26px;flex:none;border-radius:50%;display:grid;place-items:center;
  font-family:var(--mono);font-size:13px;border:1.5px solid var(--line);color:var(--ink-soft);background:var(--card);transition:all .15s}
.step.active .num{background:var(--accent);border-color:var(--accent);color:#fff}
.step.done .num{background:var(--hi-bg);border-color:var(--hi);color:var(--hi)}
.step .t{display:block;font-weight:600;font-size:14px;letter-spacing:-.01em}
.step .d{display:block;font-size:11.5px;color:var(--ink-faint);margin-top:2px}
.step.active .t{color:var(--accent)}

/* main card */
.main{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);min-height:560px;display:flex;flex-direction:column;overflow:hidden}
.main-head{padding:24px 28px 18px;border-bottom:1px solid var(--line-soft)}
/* margin-top 0: bỏ dòng "Bước n / 4" rồi thì tiêu đề là thứ đầu tiên trong khung,
   6px cũ vốn để tách nó khỏi dòng ấy nay chỉ làm lệch với lề trên của khung. */
.main-head h2{margin:0;font-size:22px;font-weight:600;letter-spacing:-.02em}
/* Không chặn bề ngang: phụ đề mỗi bước là MỘT câu hướng dẫn, đọc gọn trong một
   dòng thì mắt bắt được cả ý trong một lượt. Trần 62ch cũ bẻ đôi câu ngay giữa
   chừng dù khung còn thừa gần hai trăm điểm ảnh — nó vốn đặt cho thân trang hẹp
   thuở trước, nay thân đã rộng 1520px thì thành ra chỉ còn gây hại. Khung hẹp
   quá vẫn cho xuống dòng: cắt cụt chữ của một câu hướng dẫn thì tệ hơn nhiều so
   với để nó dài thêm một dòng. */
.main-head p{margin:6px 0 0;color:var(--ink-soft);font-size:13.5px}
.main-body{padding:16px 10px;flex:1}
.main-foot{display:flex;justify-content:space-between;align-items:center;gap:14px;
  padding:10px 16px;border-top:1px solid var(--line-soft);background:var(--panel-2)}
.foot-note{font-size:12px;color:var(--ink-faint)}

.panel{display:none;animation:rise .35s ease both}
.panel.show{display:block}
@keyframes rise{from{opacity:0;transform:translateY(8px)}}

/* buttons */
.btn{border:1px solid var(--line);background:var(--card);color:var(--ink);padding:10px 18px;
  border-radius:10px;font-weight:600;font-size:14px;transition:all .14s;display:inline-flex;gap:8px;align-items:center}
.btn:hover{border-color:var(--line-hover);background:var(--hov)}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.primary:hover{background:var(--accent-2);border-color:var(--accent-2)}
.btn.ghost{background:none;border-color:transparent;color:var(--ink-soft)}
.btn.ghost:hover{background:var(--card);color:var(--ink)}
.next-float{display:none;position:fixed;right:22px;bottom:22px;z-index:60;
  box-shadow:0 10px 30px rgba(0,0,0,.35)}
.next-float.show{display:inline-flex}
.btn svg{width:16px;height:16px}

/* Dòng đầu Bước 1: tình trạng kho dữ liệu. Đứng chỗ khung kéo-thả cũ nên giữ
   dáng một tấm thẻ, nhưng chỉ cao bằng một hàng con số. Nền thẻ là màu đường kẻ
   để khe 1px giữa các ô thành vạch ngăn, khỏi phải vẽ viền cho từng ô. */
.dbinfo{border:1px solid var(--line);border-radius:var(--radius);background:var(--line);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;overflow:hidden}
/* Kho rỗng thì chỉ còn một câu nhắc — bỏ lưới đi, không thì câu ấy bị ép vào
   một phần ba bề ngang của thẻ. */
.dbinfo.trong{display:block;background:var(--panel-2);border-style:dashed;
  padding:12px 16px;font-size:13.5px;color:var(--ink-faint)}
.db-num{background:var(--panel-2);padding:11px 16px;min-width:0}
.db-num b{display:block;font-family:var(--mono);font-size:19px;line-height:1.2;
  font-weight:600;color:var(--accent);font-variant-numeric:tabular-nums}
.db-num span{font-size:11.5px;color:var(--ink-soft)}
.db-num.thap b{color:var(--md-text)}

/* Thanh chọn/đổi kho dữ liệu — đứng NGAY TRÊN .dbinfo (kho ấy có gì), đọc như
   một dòng "đang ở đâu" trước khi đọc "ở đó có gì". Rộng hết hàng, dáng như
   một .btn nhưng cao & rõ hơn vì đây là quyết định ảnh hưởng tới cả trang. */
.khoinfo{display:flex;align-items:stretch;gap:10px}
.khoinfo:not(:empty){margin-bottom:10px}
.kho-sw{display:flex;align-items:center;gap:9px;flex:1;min-width:0;text-align:left;
  padding:10px 14px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel-2);font-family:var(--sans);font-size:13.5px;color:var(--ink);cursor:pointer}
.kho-sw:hover{background:var(--hov);border-color:var(--line-hover)}
.kho-sw .kho-ic{font-size:15px;line-height:1}
.kho-sw .kho-nm{font-weight:600}
.kho-sw .kho-more{color:var(--ink-faint);font-size:12px}
.kho-sw .kho-car{margin-left:auto;color:var(--ink-faint);font-size:11px}
/* Thay thế / Bổ sung — cùng hàng, sát phải thanh kho: hai nút liền nhau như một
   công tắc, nút đang chọn tô màu nhấn. Nút bị tắt (có người khác đang mở kho)
   mờ đi và gạch ngang để thấy ngay là không bấm được, không chỉ là chưa chọn. */
.che-do{display:flex;align-items:stretch;gap:8px;flex:none}
.che-do .cd-khac{align-self:center;font-size:12px;color:var(--md-text);background:var(--md-bg);
  border-radius:999px;padding:4px 9px;white-space:nowrap;cursor:help}
.che-do .cd-opt{position:relative;display:flex;align-items:center;
  padding:0 14px;border:1px solid var(--line);background:var(--panel-2);
  font-size:13px;color:var(--ink-soft);cursor:pointer;white-space:nowrap;user-select:none}
.che-do .cd-opt + .cd-opt{margin-left:-9px}
.che-do .cd-khac + .cd-opt, .che-do .cd-opt:first-child{border-radius:var(--radius-sm) 0 0 var(--radius-sm)}
.che-do .cd-opt:last-child{border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.che-do .cd-opt input{position:absolute;opacity:0;pointer-events:none}
.che-do .cd-opt:hover{background:var(--hov);border-color:var(--line-hover)}
.che-do .cd-opt:has(input:checked){background:var(--accent-soft);border-color:var(--accent);
  color:var(--accent-2);font-weight:600;z-index:1}
.che-do .cd-opt:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.che-do .cd-opt.tat{opacity:.5;cursor:not-allowed;text-decoration:line-through}
.che-do .cd-opt.tat:hover{background:var(--panel-2);border-color:var(--line)}
@media (max-width:640px){
  .khoinfo{flex-wrap:wrap}
  .che-do{width:100%;justify-content:flex-end}
  .che-do .cd-opt{padding:8px 14px}
}

/* dropzone + files */
.dz{border:1.5px dashed var(--line-hover);border-radius:var(--radius);background:var(--panel-2);
  padding:26px;text-align:center;color:var(--ink-soft);transition:all .15s}
.dz:hover{border-color:var(--accent);background:var(--card)}
.dz.drag{border-color:var(--accent);background:var(--card)}
.dz svg{width:30px;height:30px;color:var(--ink-faint);margin-bottom:6px}
.dz b{color:var(--ink);font-weight:600}
.dz .formats{margin-top:10px;font-size:12px;color:var(--ink-faint)}
.row-actions{display:flex;gap:10px;justify-content:center;margin-top:16px;flex-wrap:wrap}
#dzTpl{padding:22px}
/* Bước 2 lúc chưa có biểu mẫu thì khung kéo-thả là nhân vật chính, nạp xong rồi
   thì nó chiếm hơn 200px chỉ để nhắc lại một việc đã làm. Thu về một dòng: chữ
   hướng dẫn dài bỏ đi, chỉ giữ lối bấm chọn thêm tệp. */
#dzTpl.gon{display:flex;align-items:center;gap:12px;text-align:left;padding:10px 16px}
#dzTpl.gon svg{width:22px;height:22px;margin-bottom:0;flex:none}
#dzTpl.gon .formats{display:none}
#dzTpl.gon .row-actions{margin-top:0;margin-left:auto;flex:none}
#dzTpl.gon .btn{padding:7px 12px;font-size:12.5px}

.filelist{margin-top:22px;display:flex;flex-direction:column;gap:10px;
  border-radius:var(--radius);transition:box-shadow .15s}
/* Kéo tệp qua danh sách: viền sáng lên cho biết thả xuống đây là ăn. Dùng
   box-shadow chứ không đặt viền thật: viền làm khung rộng thêm 3px, cả danh
   sách giật một nhịp đúng lúc người dùng đang nhắm chỗ thả. */
.filelist.drag{box-shadow:0 0 0 2px var(--accent) inset}
.fl-empty{border:1.5px dashed var(--line-hover);border-radius:11px;background:var(--panel-2);
  padding:26px 16px;text-align:center;font-size:13px;color:var(--ink-faint)}
.fl-empty-big{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:6px}
.fl-empty-sm{max-width:440px;margin:0 auto 16px;line-height:1.5}
.fl-empty .btn.primary{padding:8px 18px;font-size:13px}

/* Dải cảnh báo Bước 1: máy chủ thiếu Tesseract/gói tiếng Việt/pdfium nên bản
   scan sẽ đọc ra chữ vô nghĩa hoặc mất dấu — nói ngay tại chỗ, trước khi người
   dùng nạp tệp và tự hỏi vì sao kết quả sai. */
.ocr-banner{display:flex;gap:12px;align-items:flex-start;background:var(--md-bg);
  border:1px solid var(--md);color:var(--md-text);border-radius:var(--radius-sm);
  padding:12px 15px;margin-bottom:14px}
/* display:flex ở trên đè mất quy tắc mặc định của [hidden] -> phải nói rõ,
   nếu không dải cảnh báo hiện ra rỗng khi không có vấn đề OCR gì để báo */
.ocr-banner[hidden]{display:none}
.ocr-ic{flex:none;font-size:16px;line-height:1}
.ocr-body{flex:1;min-width:0}
.ocr-t{font-weight:700;font-size:13.5px;color:var(--ink)}
.ocr-d{font-size:12.5px;margin-top:3px;line-height:1.45}
.ocr-act{display:flex;gap:8px;margin-top:9px}
/* Nút + thêm tệp: xanh lá như biểu tượng Excel trong chính danh sách bên dưới. */
.filelist-head .them-tep{padding:3px 8px;color:#1f8a55;border-color:var(--line)}
.filelist-head .them-tep svg{width:17px;height:17px;margin:0;display:block}
.filelist-head .them-tep:hover{color:#1f8a55;border-color:#1f8a55;background:var(--hi-bg)}
.fl-nut{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
/* Sổ biểu mẫu đối chiếu: nút xem sổ dùng chung màu tím với nhãn "Mẫu đối chiếu"
   trên mỗi dòng tệp, để người dùng nối được hai chỗ này là cùng một khái niệm. */
.mau-lib-btn{color:#6a4fb3;border-color:var(--line)}
.mau-lib-btn:hover{color:#6a4fb3;border-color:#6a4fb3;background:var(--hi-bg)}
/* Dòng tệp nay hai tầng: .file-main (ô chọn/tên/nút xóa, như trước) rồi tới
   .file-mt (ô chọn mẫu đối chiếu, chỉ có ở tệp Word/PDF) — .file chỉ còn lo
   xếp CHIỀU DỌC hai tầng ấy, còn xếp hàng ngang chuyển sang .file-main. */
.file{display:flex;flex-direction:column;gap:8px;padding:13px 15px;border:1px solid var(--line);
  border-radius:11px;background:var(--card)}
.file-main{display:flex;align-items:center;gap:14px}
.file .ic{width:38px;height:38px;flex:none;border-radius:9px;display:grid;place-items:center;
  font-family:var(--mono);font-size:11px;font-weight:600;color:#fff}
.ic.xlsx{background:#1f8a55}.ic.docx{background:#2a5699}.ic.pdf{background:#b33}.ic.scan{background:#7a5ea8}
.ic.csv{background:#1f8a55}.ic.file{background:#5C6976}
/* ảnh rời: cùng màu với .ic.scan — chụp lại một tờ khai thì cũng là một bản
   quét, đọc qua OCR y như nhau. Chữ bên trong là đuôi thật (JPG/PNG/WEBP…),
   dài nhất cũng chỉ 4 ký tự như XLSX nên dùng chung cỡ chữ của .file .ic */
.ic.anh{background:#7a5ea8}
.file .meta{flex:1;min-width:0}
.file .fn{font-weight:600;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.file .note{font-size:12px;color:var(--ink-soft);margin-top:2px;display:flex;gap:7px;align-items:center;flex-wrap:wrap}
.tag{font-size:11px;background:var(--accent-soft);color:var(--accent-2);padding:2px 8px;border-radius:6px;font-weight:500}
.tag.ok{background:var(--hi-bg);color:var(--hi-text)}
/* nhãn "(bố cục cố định)" đứng tận cùng bên phải tên mẫu ảnh/PDF scan trong
   mọi danh sách biểu mẫu trống — cùng màu tím với thẻ SCAN */
.tag.co-dinh{flex:none;background:rgba(107,79,160,.13);color:#6b4fa0;font-weight:600;white-space:nowrap}
:root[data-theme="dark"] .tag.co-dinh{background:#2e2542;color:#c9b8ea}
.file .rm{margin-left:auto;color:var(--ink-faint);background:none;border:none;font-size:18px;padding:4px 8px;border-radius:6px}
.file .rm:hover{background:var(--lo-bg);color:var(--lo)}
.filelist-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  flex-wrap:wrap;font-size:12px;color:var(--ink-faint);margin:2px 2px 4px}
.file.selectable{cursor:pointer;user-select:none}
.file.selectable:hover{border-color:var(--line-hover);background:var(--hov)}
.file.selectable.off{opacity:.5}
.file .fchk{flex:none;margin:0 2px 0 0}

/* preview table */
.tbl-wrap{margin-top:22px;border:1px solid var(--line);border-radius:11px;overflow:auto}
.tbl-cap{padding:9px 14px;background:var(--panel-2);border-bottom:1px solid var(--line);
  font-size:12px;color:var(--ink-soft);display:flex;align-items:center;gap:8px}
table{border-collapse:collapse;width:100%;font-size:13px}
th,td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--line-soft);white-space:nowrap}
thead th{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint);font-weight:600;background:var(--card);position:sticky;top:0}
thead th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
thead th.sortable:hover{color:var(--accent)}
thead th.active{color:var(--accent)}
thead th .caret{font-size:9px;opacity:.5;margin-left:2px}
thead th.active .caret{opacity:1}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--panel-2)}
td .mono{font-size:12px;color:var(--ink-soft)}

/* Ô tìm trên bảng xem trước Bước 1. Dùng lại .col-find của Bước 3 nên hai ô tìm
   trong cả ứng dụng trông và gõ giống hệt nhau; chỉ chỉnh lại lề cho khớp với
   khoảng cách 22px mà .tbl-wrap vốn chừa ra. */
/* Ô tìm và ba nút "làm gì tiếp" đứng chung một hàng ngay trên bảng: xong việc
   ở Bước 1 là nhìn vào bảng, mà trước đây nút "Tiếp tục" lại nằm tận cột
   bên trái, cách xa chỗ mắt đang đặt. Chật quá thì nút xuống hàng dưới ô tìm. */
.prev-head{display:flex;align-items:center;gap:12px;margin:22px 0 8px;flex-wrap:wrap}
.prev-head .prev-find{flex:1 1 240px;margin:0}
.prev-head .src-act{flex:0 1 auto;min-width:0;margin-left:auto;
  flex-wrap:wrap;justify-content:flex-end}
.prev-head .src-act .btn{flex:none}
.prev-head + .tbl-wrap{margin-top:0}
/* Đầu bảng xem trước là ô CHỌN cột chứ không phải nhãn chết — trông vẫn phải
   ra cái đầu bảng: không viền, không nền, chữ in hoa như mọi <th> khác. */
thead th select.prev-col{font-family:var(--sans);font-size:11px;letter-spacing:.04em;
  text-transform:uppercase;font-weight:600;color:var(--ink-faint);background:none;border:none;
  padding:0 2px 0 0;max-width:190px;cursor:pointer}
thead th select.prev-col:hover,thead th select.prev-col:focus{color:var(--accent);outline:none}
/* Nút bỏ cột: mờ đi cho tới khi rê chuột vào ô ấy. Luôn hiện rõ thì cả đầu
   bảng thành một hàng dấu × trông như bảng nào cũng đang chờ bị xóa; mà giấu
   hẳn (chỉ hiện khi hover) thì không ai biết là có nút. */
.th-col{display:inline-flex;align-items:center;gap:2px;max-width:100%}
.col-rm{flex:none;border:none;background:none;cursor:pointer;line-height:1;
  font-size:14px;color:var(--ink-faint);opacity:.35;padding:0 3px;border-radius:5px}
.th-col:hover .col-rm,.rec-full .rc:hover .col-rm{opacity:1}
.col-rm:hover{color:#fff;background:var(--lo);opacity:1}
.col-rm:focus-visible{opacity:1;outline:2px solid var(--accent);outline-offset:1px}
/* cột mũi tên hẹp: bấm vào dòng nào là mở đủ mọi cột của dòng ấy */
th.ix{width:26px;padding-left:12px;padding-right:0}
td.ix{width:26px;padding-left:12px;padding-right:0;color:var(--ink-faint);
  font-size:10px;user-select:none}
tbody tr.rec{cursor:pointer}
tbody tr.rec.mo>td{background:var(--panel-2);border-bottom-color:transparent}
tbody tr.rec.mo td.ix{color:var(--accent)}
/* dòng "khớp ở": cột khớp mà không nằm trong 6 cột đang hiện */
tbody tr.rec-hit>td{padding:0 13px 8px 38px;border-bottom:1px solid var(--line-soft);
  font-size:12px;color:var(--ink-soft);white-space:normal}
tbody tr.rec-hit b{color:var(--ink);font-weight:600}
.hit-lbl{color:var(--ink-faint)}
/* khối chi tiết một bản ghi: mọi cột, xếp thành lưới cho đỡ phải cuộn ngang */
tbody tr.rec-det>td{padding:0;background:var(--panel-2)}
.rec-full{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  gap:2px 18px;padding:11px 13px 13px 38px;max-height:290px;overflow:auto}
.rec-full .rc{display:flex;gap:8px;align-items:baseline;font-size:12.5px;
  padding:3px 0;border-bottom:1px solid var(--line-soft);white-space:normal}
.rec-full .rk{flex:0 0 42%;color:var(--ink-faint);font-size:11.5px;word-break:break-word}
.rec-full .rv{flex:1;min-width:0;color:var(--ink);word-break:break-word}
.rec-full .rv.trong{color:var(--ink-faint)}
.rec-full .rc .col-rm{font-size:13px}
.tbl-empty{color:var(--ink-faint);text-align:center;padding:20px 8px;white-space:normal}

/* template fields — mỗi trường một dòng, cả danh sách cuộn trong khung của nó
   để thanh chân trang (nút "Tiếp tục") không bị đẩy khuất khi biểu mẫu nhiều
   trường. Kiểu thẻ xếp lưới cũ đọc theo cột, mắt phải nhảy ngang mới dò được
   trường nào ở đâu; xếp dọc thì dò một mạch từ trên xuống. */
.field-list{margin-top:20px;overflow-y:auto;padding-right:4px}
/* Bước 2 đặt danh sách này làm khung bên phải, cạnh danh sách biểu mẫu: nó dùng
   chung viền/nền với khung tóm tắt Bước 1 (.fsum) nên lề trong chuyển vào ruột,
   còn margin trên phải bỏ — hai cột lệch nhau vài chục pixel là nhìn như đo hỏng. */
.src-col > .field-list{margin-top:0;padding-right:0}
.field-list .fld-wrap{padding:12px 14px}
/* Khung cao cố định thì tên biểu mẫu phải bám mép trên, không thì cuộn xuống
   giữa danh sách trường là quên mất đang xem trường của biểu mẫu nào. */
.field-list h4{position:sticky;top:0;z-index:1}
/* Nhắc "tích để sửa" nằm sát mép trên của phần trường, không phải một dòng rời */
.field-list .fld-hint{margin:0 0 10px;font-size:12px;color:var(--ink-faint)}
.fld.chi-xem{background:var(--panel-2)}
.field-list::-webkit-scrollbar{width:9px}
.field-list::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
.field-list::-webkit-scrollbar-thumb:hover{background:var(--line-hover)}
.fld-list{display:flex;flex-direction:column;gap:7px}
.fld{display:flex;align-items:center;gap:11px;flex-wrap:wrap;
  border:1px solid var(--line);border-radius:10px;padding:9px 13px;background:var(--card)}
.fld:hover{border-color:var(--line-hover)}
.fld .stt{flex:none;width:26px;text-align:right;font-family:var(--mono);font-size:11px;
  color:var(--ink-faint)}
.fld .fl{flex:1 1 220px;min-width:0;font-weight:600;font-size:13.5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fld .loc{flex:0 1 auto;min-width:0;font-size:11.5px;color:var(--ink-faint);
  display:flex;align-items:center;gap:6px;overflow:hidden;white-space:nowrap}
.fld .loc .dotline{flex:none}
/* Vị trí dài thì cắt ở chữ và thêm dấu "…", chứ cắt ngang thân chữ trông như lỗi.
   Còn cái thẻ loại trường thì giữ nguyên, nó là thứ ngắn mà đáng đọc nhất. */
.fld .loc .loctext{overflow:hidden;text-overflow:ellipsis;min-width:0}
.fld .loc .kindtag{flex:none}
.fld .editrow{flex-basis:100%;display:none}
.fld.editing .editrow{display:block;margin-top:2px}
.fld .editrow input{width:100%;font-family:var(--sans);font-size:12.5px;border:1px solid var(--line);
  border-radius:7px;padding:6px 8px;background:var(--panel-2);color:var(--ink)}
.fld .mini{flex:none;background:none;border:none;color:var(--ink-faint);font-size:15px;padding:0 2px;border-radius:6px;line-height:1}
.fld .mini:hover{color:var(--accent)}
/* Nút bỏ trường tô màu cảnh báo khi rê chuột, như mọi nút xóa khác — nó nằm
   ngay cạnh nút sửa nhãn nên phải nhìn ra được cái nào là cái lấy đi thứ gì. */
.fld .mini.bo:hover{color:var(--lo)}
/* Dòng "đã bỏ n trường · Khôi phục": chỉ hiện khi có trường bị bỏ, nên cho nó
   nổi hơn dòng gợi ý thường một chút để người dùng thấy mình đang xem một danh
   sách đã bị cắt bớt chứ không phải toàn bộ những gì máy dò được. */
.field-list .fld-hint.bo-hint{color:var(--ink-soft)}
.fld-hint .lnk{background:none;border:none;padding:0;font:inherit;color:var(--accent);
  text-decoration:underline;cursor:pointer}
.fld-hint .lnk:hover{color:var(--accent-2)}
/* Danh sách tên tệp trùng trong hộp thoại tải lên. Tên tệp đọc bằng phông đều
   thì dễ soi chỗ khác nhau giữa hai tên na ná nhau. Mỗi tên trùng một hàng "tên cũ → ô đặt tên mới". Tên cũ co lại nhường chỗ
   cho ô nhập vì đó mới là thứ người dùng đụng vào; cắt bằng dấu … chứ không
   xuống dòng, để hàng nào cũng cao bằng nhau và ô nhập thẳng cột. */
.trung-ds{margin:0 0 14px;max-height:170px;overflow:auto;
  display:flex;flex-direction:column;gap:7px}
.trung-d{display:flex;align-items:center;gap:8px;font-family:var(--mono);font-size:12.5px}
.trung-cu{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;color:var(--ink-soft)}
.trung-mui{flex:none;color:var(--ink-faint)}
.trung-moi{flex:1 1 45%;min-width:0;padding:5px 8px;font:inherit;color:var(--ink);
  background:var(--card);border:1px solid var(--line);border-radius:7px}
.trung-moi:focus{outline:none;border-color:var(--accent)}
.dotline{font-family:var(--mono);color:var(--ink-faint);letter-spacing:1px}
.kindtag{font-size:10.5px;font-weight:600;color:var(--accent-2);background:var(--accent-soft);padding:1px 7px;border-radius:6px}
.tpl-group{margin-top:18px}
.tpl-group:first-child{margin-top:10px}
.tpl-group-h{display:flex;align-items:center;gap:8px;font-weight:600;font-size:13px;color:var(--accent-2);
  margin:0 2px 10px;padding-bottom:7px;border-bottom:1px solid var(--line-soft)}
.tpl-group-h .ic{border-radius:6px;display:grid;place-items:center;color:#fff;font-family:var(--mono);font-weight:600}
.filetag{display:inline-block;font-size:10.5px;font-weight:600;color:var(--accent-2);background:var(--accent-soft);
  padding:1px 7px;border-radius:6px;margin-right:6px;vertical-align:middle;max-width:160px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* Trong nhãn trường của bảng ghép, .cl đã là hàng flex có gap nên thẻ tên tệp
   không cần lề riêng nữa; lề 6px của .filetag là để dùng ở chỗ khác (danh sách
   tệp xuất ra ở Bước 4). */
.mg-label .cl .filetag{margin-right:0}

/* ===== mapping (signature) ===== */
/* Hàng đầu Bước 3: ô chọn biểu mẫu bên trái, mấy nút cấu hình bên phải. Hàng
   rỗng (một biểu mẫu, ô chọn đang ẩn) vẫn còn mấy nút cấu hình nên không bị xẹp. */
.map-head{display:flex;gap:16px;margin:10px 2px 6px;font-size:12px;color:var(--ink-soft);
  flex-wrap:wrap;align-items:center;min-height:30px}
/* Ở hàng tiêu đề thì ô chọn phải nhỏ và cụt cho khỏi choán chỗ. */
.map-head .col-file{margin-left:0;max-width:min(420px,60%);padding:4px 9px;font-size:12px}
.cfg-actions{margin-left:auto;display:flex;gap:8px}
.cfg-actions .btn{padding:6px 12px;font-size:12.5px}
.cfg-row{display:flex;align-items:center;gap:12px;padding:11px 12px;border:1px solid var(--line);
  border-radius:10px;margin-bottom:8px;background:var(--card)}
.cfg-row .cfg-info{flex:1;min-width:0}
.cfg-name{font-weight:600;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cfg-sub{font-family:var(--mono);font-size:11px;color:var(--ink-faint);margin-top:2px}
.cfg-btns{flex:none;display:flex;gap:8px;align-items:center}
.cfg-btns .btn{padding:6px 14px;font-size:12.5px}

/* Hàng công cụ: ô tìm, nút đổi thứ tự và thanh định dạng đứng chung MỘT hàng
   ngay trên bảng ghép. Bảng chỉ còn một cột trường (không phải hai danh sách
   song song như bản cũ) nên không cần cân chiều cao hai tiêu đề nữa. */
.map-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:8px 2px 10px}
.map-toolbar .col-find{flex:1 1 220px;max-width:360px;margin-bottom:0}
.col-sort{flex:none;text-transform:none;letter-spacing:0;font-weight:500;font-size:11px;
  color:inherit;background:none;border:1px solid var(--line);border-radius:6px;
  padding:5px 10px;cursor:pointer;font-family:inherit}
.col-sort:hover{color:var(--accent);border-color:var(--accent)}
.col-file{text-transform:none;letter-spacing:0;font-weight:500;font-size:11px;
  color:inherit;background:var(--panel-2);border:1px solid var(--line);border-radius:6px;
  padding:1px 6px;line-height:1.25;margin-left:6px;cursor:pointer;font-family:inherit;
  max-width:150px}
.col-file:hover{color:var(--accent);border-color:var(--accent)}
.col-file[hidden]{display:none}
/* Ô tìm trường: một biểu mẫu có thể tới vài trăm trường, cuộn tay dò từng ô là
   việc nản nhất ở bước này. Số bên phải là "còn lại/tổng" cho biết đang lọc. */
.col-find{position:relative;display:flex;align-items:center;margin-bottom:10px}
.col-find input{flex:1;min-width:0;font-family:var(--sans);font-size:13px;color:var(--ink);
  background:var(--panel-2);border:1px solid var(--line);border-radius:8px;
  padding:7px 62px 7px 11px}
.col-find input:focus{outline:none;border-color:var(--accent);background:var(--card)}
.col-find .find-n{position:absolute;right:11px;font-family:var(--mono);font-size:11px;
  color:var(--ink-faint);pointer-events:none}
.chips-empty{font-size:12.5px;color:var(--ink-faint);text-align:center;padding:18px 8px}
/* .chip/.chips dùng chung với danh sách tên trùng ở Bước 1 (xem .fsum .chip.vang
   phía dưới) — đừng gắn thêm quy tắc riêng của Bước 3 vào thẳng đây. */
.chips{display:flex;flex-direction:column;gap:12px;position:relative;z-index:2;
  max-height:min(64vh,760px);overflow-y:auto;padding:4px 6px;margin:-4px -6px}
.chip{border:1px solid var(--line);border-radius:10px;background:var(--card);padding:11px 13px;transition:box-shadow .15s,border-color .15s}
/* Thanh định dạng, kiểu thanh Home của Word: tác động lên trường ĐANG CHỌN để
   định dạng (bấm nút "Aa" ở dòng của trường ấy — xem FMTSEL trong app.js),
   giống Word chỉ tác động lên đoạn đang bôi đen chứ không mở riêng một bảng cho
   mỗi dòng — biểu mẫu có tới hàng trăm trường, dòng nào cũng mở bảng bảy nút
   thì bảng ghép dài gấp đôi, cuộn mỏi tay. */
.fmtbar{display:flex;align-items:center;gap:4px;flex-wrap:nowrap;flex:1 1 320px;min-width:280px;
  padding:4px 6px;border:1px solid var(--line);border-radius:9px;
  background:var(--panel-2);text-transform:none;letter-spacing:0;font-weight:400}
/* .active = đang có một trường được chọn: viền sáng lên cho biết thanh này đang
   THẬT SỰ tác động lên một trường, không phải chỉ nằm đó cho có. */
.fmtbar.active{border-color:var(--line-hover);background:var(--card)}
.fmtbar .sfont{flex:1 1 118px;min-width:54px;width:auto;margin:0;padding:4px 5px;font-size:12px}
.fmtbar .sbtn{flex:none;width:24px;height:24px;border:1px solid var(--line);background:var(--card);border-radius:6px;
  font-size:13px;line-height:1;color:var(--ink-soft);padding:0;display:grid;place-items:center;cursor:pointer}
.fmtbar .sbtn:hover{border-color:var(--line-hover)}
.fmtbar .sbtn.on{background:var(--accent);border-color:var(--accent);color:#fff}
.fmtbar .ssize{flex:none;width:48px;margin:0;padding:4px 5px;font-size:12px}
.fmtbar .shl{flex:1 1 74px;min-width:48px;width:auto;margin:0;padding:4px 5px;font-size:12px}
.fmtbar [disabled]{opacity:.4;cursor:default;pointer-events:none}
.scolor-wrap{flex:none;width:26px;height:24px;border:1px solid var(--line);border-radius:6px;overflow:hidden;
  display:grid;place-items:center;cursor:pointer;padding:0}
.scolor-wrap:hover{border-color:var(--line-hover)}
.scolor{width:40px;height:40px;border:none;background:none;padding:0;cursor:pointer}
.sreset{flex:none;width:24px;height:24px;border:1px solid var(--line);background:var(--card);border-radius:6px;
  font-size:14px;color:var(--ink-faint);cursor:pointer;padding:0}
.sreset:hover{border-color:var(--lo);color:var(--lo)}
/* Huy hiệu tĩnh trên trường đã có định dạng riêng: nút mở bảng đã dồn vào cột
   Thao tác của từng dòng, nhưng vẫn cần một dấu để biết dòng nào đang khác định
   dạng mặc định mà không phải bấm thử từng dòng một. */
.fmt-badge{flex:none;font-size:10.5px;font-weight:700;color:var(--accent);
  border:1px solid var(--accent);border-radius:5px;padding:0 4px;line-height:1.5}

/* Dải nhãn lọc theo tình trạng (đếm sống, bấm để lọc bảng ghép — Bước 3). Tên
   lớp .fchip cố tình khác .chip ở trên (xem ghi chú tại đó) vì đây là một
   thành phần khác hẳn: một hàng nút nhỏ nằm ngang, không phải danh sách thẻ
   dọc của Bước 1. */
.chip-row{display:flex;flex-wrap:wrap;gap:6px;margin:2px 2px 10px}
.fchip{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);
  border-radius:999px;background:var(--card);color:var(--ink-soft);font:inherit;
  font-size:12px;font-weight:500;padding:5px 11px;cursor:pointer;transition:border-color .15s,color .15s}
.fchip:hover{border-color:var(--accent);color:var(--accent)}
.fchip.on{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-2)}
.fchip b{font-weight:700;font-family:var(--mono);font-size:11px}
.fchip.zero{opacity:.45;cursor:default}
.fchip.zero:hover{border-color:var(--line);color:var(--ink-soft)}
/* Thanh thao tác hàng loạt: chỉ hiện khi có dòng đang tích ở cột ☑ đầu bảng
   (xem BULKSEL trong app.js) — [hidden] tắt hẳn khỏi luồng, không chỉ ẩn màu. */
.bulk-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:2px 2px 10px;
  padding:8px 12px;border:1px solid var(--accent);border-radius:9px;background:var(--accent-soft)}
.bulk-bar[hidden]{display:none}
.bulk-bar #bulkN{font-size:12.5px;font-weight:600;color:var(--accent-2)}
.bulk-bar .btn{padding:5px 11px;font-size:12.5px}
.bulk-bar .btn:last-child{margin-left:auto}

/* ===== bảng ghép (Bước 3) ===== */
/* Một bảng duy nhất, mỗi dòng là một trường trên biểu mẫu — thay bố cục hai cột
   chip cũ (bấm ô này rồi bấm ô kia để ghép). Cột nguồn giờ mở bằng một nút bật
   lên (.src-pop bên dưới) nên không cần rãnh giữa hay đo/cân chiều cao hai cột
   như trước — bảng tự cuộn trong khung của nó. */
.grid-scroll{max-height:min(64vh,760px);overflow:auto;border:1px solid var(--line);
  border-radius:10px;margin-top:2px}
/* table-layout:fixed để cột trường-mẫu (.mg-label) và cột trường-nguồn (.mg-src)
   luôn bằng nhau, cột giá trị mẫu (.mg-sample) luôn bằng 38% bề rộng của chúng —
   không phụ thuộc nội dung dài ngắn của từng dòng. Bốn cột vừa đủ 100%, không
   còn cột "Thao tác" riêng (hai nút ▶/✕ đã dời vào .mg-label/.mg-src) nên bảng
   không còn tràn ngang phải cuộn. Cột ☑ (.mg-chk) thêm sau có bề rộng cố định
   bằng px chứ không phải %; ở table-layout:fixed, cột không khai width (.mg-conf)
   tự nhường đúng từng ấy px cho nó nên bốn cột kia không cần tính lại tỉ lệ. */
.map-grid{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12.5px}
.map-grid thead th{position:sticky;top:0;z-index:2;background:var(--panel-2);
  text-align:left;font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-faint);font-weight:600;padding:9px 10px;border-bottom:1px solid var(--line)}
.map-grid tbody td{padding:9px 10px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.map-grid tbody tr:last-child td{border-bottom:none}
.map-grid tbody tr:hover{background:var(--panel-2)}
.map-grid tbody tr.flag{box-shadow:inset 3px 0 0 var(--lo)}
.map-grid tbody tr.sel{background:var(--accent-soft)}
.map-grid tbody tr.sel:hover{background:var(--accent-soft)}
/* Dòng đã đánh dấu "cố ý không điền": nhạt đi để phân biệt với dòng chưa ai
   động tới, nhưng không dùng display:none — vẫn cần thấy để bấm ↺ quay lại. */
.map-grid tbody tr.excluded{opacity:.55}
.map-grid tbody tr.excluded:hover{opacity:.85}
.mg-chk{width:30px}
.map-grid thead th.mg-chk{padding:9px 0;text-align:center}
.mg-chk .mg-cell{justify-content:center}
.mg-chk input[type=checkbox],#chkAll{width:15px;height:15px;cursor:pointer;accent-color:var(--accent)}
/* .mg-label/.mg-src ở lại display:table-cell mặc định (KHÔNG bật flex trên chính
   <td> — flex trên một ô bảng làm nó rớt khỏi luồng bố cục bảng, lệch hàng với
   các ô khác). Thay vào đó mỗi ô có một .mg-cell bọc bên trong để xếp hàng ngang:
   nội dung (tên trường / nút cột nguồn) chiếm phần còn lại, nút ▶/✕ bị margin-left
   :auto đẩy hẳn ra MÉP PHẢI của ô — mọi dòng có nút thẳng một cột dọc, không còn
   chạy theo độ dài tên trường mỗi dòng một chỗ. */
/* Bốn cột cộng lại đúng 100%: .mg-conf không khai báo width nên ăn phần còn
   lại (9.52%), vừa đủ cho nhãn "Độ tin cậy" và điểm số không bị bóp. Cột
   "Giá trị mẫu" rộng bằng 60% cột "Trường dữ liệu nguồn" (20.88/34.8), phần
   nới thêm lấy từ hai cột trái chia đều chứ không lấy của cột độ tin cậy. */
.mg-label{width:34.8%;white-space:normal}
.mg-cell{display:flex;align-items:center;gap:8px}
.mg-cell>.mota{margin-left:auto}
.mg-label .cl{font-weight:600;display:inline-flex;flex-wrap:wrap;align-items:center;
  gap:8px;overflow-wrap:anywhere;vertical-align:middle;min-width:0}
.mg-src{width:34.8%;white-space:normal}
.mg-src .srcbtn{min-width:0}
.mg-sample{width:20.88%;color:var(--ink)}
.mg-conf{white-space:nowrap}
/* Nút mở bảng chọn cột nguồn: trông như ô đã ghép của bản cũ, nhưng là một
   <button> thật để mở popover — không còn là nửa cặp ô "bấm để chọn, bấm ô kia
   để ghép" như trước. */
.srcbtn{display:inline-flex;align-items:center;max-width:100%;padding:6px 9px;
  border:1px solid var(--line);border-radius:7px;background:var(--panel-2);
  font:inherit;font-size:12.5px;font-weight:600;color:var(--ink);cursor:pointer;
  overflow-wrap:anywhere;text-align:left}
.srcbtn:hover{border-color:var(--accent)}
.srcbtn.empty{font-weight:400;font-style:italic;color:var(--ink-faint)}
.srcbtn .mui{flex:none;color:var(--ink-faint);margin-right:5px;font-weight:400}
/* Giá trị mẫu của cột đã ghép: một giá trị THẬT của cột nguồn, xem thử cho yên
   tâm là ghép đúng cột, khỏi phải chờ tới lúc xuất tệp ra mới biết. */
.mapsample{display:inline-block;max-width:100%;padding:6px 9px;border:1px dashed var(--line);
  border-radius:7px;background:var(--panel-2);font-size:12.5px;color:var(--ink);
  line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle}
.mapsample.empty{font-style:italic;color:var(--ink-faint)}
.mg-sample .sdec{margin-left:8px;width:52px;text-align:center;font-size:12.5px;padding:5px 4px;
  border:1px solid var(--accent);border-radius:7px;background:var(--accent-soft);color:var(--ink);
  font-family:var(--sans);vertical-align:middle}
.conf{font-family:var(--mono);font-size:11px;font-weight:500;padding:2px 7px;border-radius:6px}
.conf.hi{background:var(--hi-bg);color:var(--hi-text)}
.conf.md{background:var(--md-bg);color:var(--md-text)}
.conf.lo{background:var(--lo-bg);color:var(--lo-text)}
/* Hai nút ▶ xem trước (bên .mg-label) và ✕ bỏ ghép (bên .mg-src) dùng chung
   khuôn nút tròn với nút "?" mô tả cột trong hộp chọn cột nguồn — cùng làm một
   việc "mở thêm một chức năng phụ cho dòng này" nên trông giống nhau. Đã bỏ cột
   "Thao tác" riêng (b7): hai nút này giờ nằm ngay trong ô của trường liên quan. */
.mg-label .mota,.mg-src .mota{flex:none;width:26px;height:26px;border-radius:50%;
  border:1px solid var(--line);background:var(--panel-2);color:var(--ink-faint);
  font-size:11px;font-weight:700;line-height:1;padding:0;cursor:pointer;
  display:inline-grid;place-items:center}
.mg-label .mota:hover,.mg-src .mota:hover{border-color:var(--accent);color:var(--accent)}
.mg-label .mota.play{font-size:9px;padding-left:1px;color:var(--accent)}
.mg-src .mota.mapclear:hover{border-color:var(--lo);color:var(--lo)}
/* ↺ quay về "chưa ghép": trái với ✕ bỏ ghép, đây không phải thao tác phá huỷ
   nên tô màu accent (giống mọi nút trung tính khác khi hover) thay vì đỏ --lo. */
.mg-src .mota.mapundo:hover{border-color:var(--accent);color:var(--accent)}
/* Huy hiệu "AI cố ý để trống": AI có thấy khớp nhưng nhường cho một trường
   khác khớp mạnh hơn (auto_skip ở backend) — màu vàng --md để phân biệt với
   .fmt-badge (accent, "có định dạng riêng") và cảnh báo bẫy .warn-badge (đỏ). */
.badge.auto-skip{flex:none;font-size:10.5px;font-weight:600;color:var(--md-text);
  background:var(--md-bg);border-radius:5px;padding:1px 6px;line-height:1.5}
/* Dấu ⚠ cho hai bẫy ENGINE.md (giá trị mẫu không khớp lựa chọn ô chọn, hoặc có
   dấu ";" trong ô nhiều dòng) — nằm ngay cạnh tên trường để thấy trước khi ghi
   thật, không phải đợi tới lúc xuất file mới biết ghi sai/ghi hỏng. */
.warn-badge{flex:none;font-size:11px;font-weight:700;color:var(--lo-text)}
/* Cả dòng bấm được để chọn/bỏ chọn cho thanh định dạng ở đầu bảng (xem
   setFmtSel trong app.js) — con trỏ tay báo trước dòng này bấm được, các nút
   riêng (▶/✕/nút cột nguồn) vẫn nổi lên trên nhờ con trỏ mặc định của nút. */
.map-grid tbody tr.mg-row{cursor:pointer}

/* Hộp thoại chọn cột dữ liệu nguồn, mở khi bấm .srcbtn — dùng chung khung
   .modal/.scrim với các hộp thoại khác của trang (đóng khi bấm ra ngoài/Esc,
   xem openSrcPop() trong app.js), chỉ riêng phần thân và chân hộp. */
.src-modal-body{padding:14px 20px 6px}
/* Ô tự gõ "giá trị cố định" (b8) — nằm TRÊN ô tìm cột, cho phép điền thẳng một
   giá trị không lấy từ cột nguồn nào thay vì phải chọn một cột. */
.src-fixed-box{display:flex;align-items:center;gap:8px;margin-bottom:12px;
  padding-bottom:12px;border-bottom:1px solid var(--line-soft)}
.src-fixed-box input{flex:1;min-width:0;font-family:var(--sans);font-size:13px;color:var(--ink);
  background:var(--panel-2);border:1px solid var(--line);border-radius:8px;padding:7px 11px}
.src-fixed-box input:focus{outline:none;border-color:var(--accent);background:var(--card)}
.src-fixed-box .btn{flex:none;padding:7px 12px;font-size:12.5px}
.src-modal-body .col-find{margin-bottom:10px}
.src-pop-list{max-height:50vh;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
.src-pop-item{border:1px solid var(--line);border-radius:8px;background:var(--panel-2);
  padding:7px 9px;cursor:pointer}
.src-pop-item:hover{border-color:var(--accent)}
.src-pop-item.sel{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.src-pop-item.unused{opacity:.6}
.src-pop-item .cn{font-weight:600;display:flex;align-items:center;gap:6px;overflow-wrap:anywhere}
/* Điểm tin cậy của từng cột nguồn: đẩy hẳn ra mép phải để mọi dòng thẳng một cột
   dọc, đọc lướt xuống là so được ngay cột nào khớp hơn cột nào. */
.src-pop-item .cn .conf{flex:none;margin-left:auto}
.src-pop-item .mota{flex:none;width:18px;height:18px;border-radius:50%;border:1px solid var(--line);
  background:var(--card);color:var(--ink-faint);font-size:10px;font-weight:700;line-height:1;
  padding:0;cursor:pointer;display:grid;place-items:center}
.src-pop-item .mota:hover{border-color:var(--accent);color:var(--accent)}
.src-pop-item .mota.on{background:var(--accent);border-color:var(--accent);color:#fff}
.src-pop-item .csub{margin-top:3px;font-size:12px;color:var(--ink-faint);font-style:italic;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.src-pop-item .cdesc{margin-top:6px;font-size:12px;line-height:1.5;color:var(--ink-soft);
  background:var(--card);border:1px solid var(--line);border-radius:7px;padding:6px 8px;
  overflow-wrap:anywhere;font-weight:400}
.src-modal-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 20px;border-top:1px solid var(--line-soft)}
.src-modal-foot .btn{padding:7px 14px;font-size:12.5px}

/* records / generate */
.rec-bar{display:flex;align-items:center;gap:14px;margin-bottom:14px;flex-wrap:wrap}
.fname-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px;
  font-size:13px;color:var(--ink-soft)}
.fname-row label{font-weight:600;color:var(--ink)}
.fname-row select{font-family:var(--sans);font-size:12.5px;border:1px solid var(--line);
  border-radius:7px;padding:6px 8px;background:var(--panel-2);color:var(--ink);max-width:280px}
.fname-eg{font-family:var(--mono);font-size:12px;color:var(--ink-faint)}
.rec-bar .count{font-size:13px;color:var(--ink-soft)}
.rec-bar .count b{color:var(--ink)}
.chk{width:17px;height:17px;accent-color:var(--accent);cursor:pointer}
.gen-wrap{margin-top:20px}
.progress{height:9px;background:var(--line-soft);border-radius:99px;overflow:hidden}
.progress > i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--accent),#2f86a0);
  border-radius:99px;transition:width .2s}
.gen-status{font-size:12.5px;color:var(--ink-soft);margin-top:9px;font-family:var(--mono)}
.outputs{margin-top:8px;display:flex;flex-direction:column;gap:9px}
.out{display:flex;align-items:center;gap:13px;padding:11px 14px;border:1px solid var(--line);
  border-radius:10px;background:var(--card);animation:rise .3s ease both}
.out .ic{width:32px;height:32px;border-radius:8px;background:#2a5699;color:#fff;display:grid;
  place-items:center;font-family:var(--mono);font-size:10px;font-weight:600;flex:none}
.out .ometa{flex:1;min-width:0}
.out .on{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.out .om{font-family:var(--mono);font-size:11px;color:var(--ink-faint);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.out .acts{margin-left:auto;display:flex;gap:8px;flex:none}
.out .acts .btn{padding:7px 12px;font-size:12.5px}
.done-head{display:flex;align-items:center;gap:10px;margin-bottom:14px;color:var(--hi-text);font-weight:600;font-size:14px}
.done-head svg{width:20px;height:20px}
.zip-row{margin:6px 0 14px;display:flex;justify-content:flex-end}

/* modal */
.scrim{position:fixed;inset:0;background:rgba(18,28,38,.5);backdrop-filter:blur(2px);
  display:none;place-items:center;z-index:50;padding:24px}
.scrim.show{display:grid}
.modal{background:var(--card);border-radius:14px;max-width:660px;width:100%;max-height:88vh;overflow:auto;box-shadow:0 30px 80px -20px rgba(0,0,0,.5)}
.modal-head{display:flex;align-items:center;justify-content:space-between;padding:15px 20px;
  border-bottom:1px solid var(--line-soft);position:sticky;top:0;background:var(--card)}
.modal-head .mt{font-weight:600;font-size:14px}
.modal-head .mt .mono{font-size:12px;color:var(--ink-faint);display:block;font-weight:400}
.modal-head button{background:none;border:none;font-size:22px;color:var(--ink-faint);padding:2px 8px;border-radius:7px}
.modal-head button:hover{background:var(--panel-2);color:var(--ink)}
.doc{padding:36px 44px;font-family:'Times New Roman',Georgia,serif;color:var(--ink)}
.doc h3{text-align:center;font-size:19px;margin:4px 0 18px;letter-spacing:.01em}
.doc .line{margin:11px 0;font-size:14.5px}
.doc .line .lbl{color:var(--ink-soft)}
.doc .val{border-bottom:1px dotted var(--ink-faint);padding:0 4px;font-weight:600}
.doc .val.from-low{background:var(--lo-bg)}
.doc .val.empty{color:var(--lo);font-weight:400;font-style:italic}
.doc .pv-note{margin-top:24px;font-family:var(--sans);font-size:11.5px;color:var(--ink-faint);
  border-top:1px solid var(--line-soft);padding-top:12px}

/* Sổ biểu mẫu đối chiếu: liệt kê mọi bản trống đã nạp vào máy chủ (dùng
   chung cho cả văn phòng) — chỉ để xem, không có nút xóa ở đây (xem app.js
   openMauTrongLib() để biết lý do). */
.mau-lib-body{padding:6px 12px 16px}
.mau-lib-row{display:flex;align-items:center;gap:12px;padding:11px 8px;
  border-bottom:1px solid var(--line-soft)}
.mau-lib-row:last-child{border-bottom:none}
.mau-lib-nm{flex:1;min-width:0;font-size:13px;font-weight:500;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.mau-lib-kind{flex:none;font-family:var(--mono);font-size:10.5px;font-weight:700;color:#fff;
  padding:3px 7px;border-radius:6px}
.mau-lib-kind.docx{background:#2a5699}.mau-lib-kind.pdf{background:#b33}
.mau-lib-kind.anh{background:#2e7d4f}.mau-lib-kind.scan{background:#6b4fa0}
.mau-lib-loai{font-weight:400;color:var(--ink-faint)}
/* mẫu bố cục cố định (ảnh/PDF scan): tên in đậm, tên tệp mờ đi phía sau */
.mau-lib-nm.co-dinh b{font-weight:700;color:var(--ink)}
.mau-lib-body .fsum-empty{padding:26px 18px;font-size:12.5px;color:var(--ink-faint);text-align:center}
/* hộp "Lưu danh sách trường" dùng lại khung của danh sách biểu mẫu */
.luu-truong-note{margin:4px 8px 12px;font-size:12.5px;line-height:1.55;color:var(--ink-soft);
  white-space:normal}
.luu-truong-khac{margin:16px 8px 4px;font-size:11.5px;letter-spacing:.04em;
  text-transform:uppercase;font-weight:600;color:var(--ink-faint)}

/* --- khung xem biểu mẫu (core/docxhtml.py dựng ra phần .docview) ---------
   Rộng hơn hộp thoại thường vì đây là cả một tờ khai, mà tờ khai nào cũng có
   bảng chục cột — ép vào 660px là bảng vỡ hết, xem cũng như không. */
.modal.wide{max-width:1080px}
/* Bảng chọn cột nguồn hẹp hơn các hộp .wide khác (80% của 1080px): danh sách
   cột chỉ có tên cột + dữ liệu mẫu ngắn nên kéo rộng hết cỡ chỉ tổ để trống,
   mà mắt lại phải quét ngang xa hơn giữa tên cột và điểm tin cậy bên phải. */
.modal.wide.src-modal{max-width:864px}
.mh-acts{display:flex;align-items:center;gap:8px;flex:none}
.btn.sm{padding:6px 13px;font-size:12px}
.docnote{display:flex;flex-wrap:wrap;align-items:center;gap:6px 15px;padding:9px 20px;
  border-bottom:1px solid var(--line-soft);background:var(--panel-2);
  font-family:var(--sans);font-size:11.5px;color:var(--ink-soft)}
.docnote span{display:flex;align-items:center;gap:5px}
.docnote .sw{width:11px;height:11px;border-radius:3px;border:1px solid rgba(0,0,0,.14);flex:none}
.docnote .sw.dien{background:#D6EFDC}
.docnote .sw.trong{background:#FFF3BF}
/* Xanh lơ = trường vừa bấm ▶. Chỉ có trên bản PDF: bản HTML viền thẳng vào thẻ
   <mark> được (mark.tf.soi) nên không cần thêm màu vào chú thích. */
.docnote .sw.soi{background:#AFEEEE}
.docnote .dn-n{font-family:var(--mono);color:var(--ink)}
.docnote .dn-w{color:var(--ink-faint);font-style:italic}
.docwait{padding:44px 0;text-align:center;font-family:var(--sans);font-size:13px;color:var(--ink-faint)}

/* Chữ giữ nguyên khoảng trắng: biểu mẫu chừa chỗ điền bằng dãy dấu chấm và
   khoảng trắng, mà HTML thì gộp khoảng trắng lại — không giữ thì mọi chỗ trống
   biến mất, đúng những chỗ cần nhìn nhất. */
.docview{padding:22px 26px;font-family:'Times New Roman',Georgia,serif;
  font-size:13.5px;line-height:1.5;color:var(--ink);overflow-x:auto}
.docview p.d{white-space:pre-wrap;margin:2px 0;min-height:1.1em;word-break:break-word}
.docview p.d.c-giua{text-align:center}
.docview p.d.c-phai{text-align:right}
.docview p.d.c-deu{text-align:justify}
.docview p.d.o-dien{margin-top:3px}
.docview table.bang{border-collapse:collapse;width:100%;margin:9px 0;table-layout:fixed}
.docview td.o{border:1px solid var(--line);padding:4px 6px;vertical-align:top}
.docview td.o.truong{background:var(--panel-2)}
/* Ba màu đánh dấu luôn lấy bộ SÁNG, kể cả khi giao diện đang để nền tối, và
   chốt luôn màu chữ: nền vàng nhạt mà chữ vẫn màu sáng thì vệt đánh dấu thành
   một ô mù. Bản .docx tải về cũng vậy — nó nằm trên giấy trắng. */
.docview mark.tf{background:#FFF3BF;color:#17212C;border-radius:3px;padding:0 3px}
.docview mark.tf.dien{background:#D6EFDC;font-weight:600}
.docview mark.tf.soi{outline:2px solid var(--accent);outline-offset:1px;
  box-shadow:0 0 0 6px var(--accent-soft)}
/* Đầu trang / chân trang: dựng thành khối riêng, kẻ nét đứt và ghi nhãn để
   không ai đọc nhầm thành một đoạn của phần thân. Có mặt ở đây là vì người dùng
   gõ được dấu {{…}} vào đầu trang, và họ cần nhìn thấy chỗ ấy được nhận. */
.docview .phu{border:1px dashed var(--line);border-radius:6px;
  padding:8px 12px 6px;margin:0 0 14px;background:var(--panel-2)}
.docview .phu:last-child{margin:14px 0 0}
.docview .phu-nhan{display:block;margin-bottom:4px;font-family:var(--sans);
  font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-faint)}

/* Máy chủ có LibreOffice thì khung xem nhúng thẳng bản PDF thay cho .docview —
   chiều cao cố định theo khung nhìn (chứ không theo nội dung) vì trình xem PDF
   của trình duyệt tự cuộn/tự phóng bên trong khung của chính nó. */
.docview-pdf{display:block;width:100%;height:74vh;border:none;background:var(--panel-2)}

/* giấy phép — nút cố định góc dưới trái */
.licbtn{position:fixed;left:18px;bottom:18px;z-index:40;
  display:flex;align-items:center;gap:8px;background:var(--panel);
  border:1px solid var(--line);border-radius:999px;padding:8px 14px 8px 11px;
  font-family:var(--sans);font-size:12.5px;font-weight:500;color:var(--ink-soft);
  box-shadow:var(--shadow);transition:all .14s}
/* display:flex ở trên đè mất quy tắc mặc định của [hidden] -> phải nói rõ,
   nếu không nút hiện ra rỗng trong lúc chờ /api/license trả lời */
.licbtn[hidden]{display:none}
.licbtn:hover{border-color:var(--line-hover);color:var(--ink);transform:translateY(-1px)}
.licbtn svg{width:15px;height:15px;flex:none;color:var(--hi)}
.licbtn .lic-n{font-family:var(--mono);font-size:11.5px;color:var(--ink);
  background:var(--panel-2);border-radius:999px;padding:2px 8px}
/* sắp hết hạn */
.licbtn.warn{border-color:#e3cf9a;background:var(--md-bg)}
.licbtn.warn svg{color:var(--md)}
.licbtn.warn .lic-n{background:var(--card);color:var(--md)}
/* hết hạn / chưa kích hoạt */
.licbtn.bad{border-color:#e6b3ab;background:var(--lo-bg);color:var(--lo)}
.licbtn.bad svg{color:var(--lo)}
.licbtn.bad .lic-n{background:var(--card);color:var(--lo)}
/* chưa nhúng khóa: chỉ là thông tin, không cảnh báo */
.licbtn.off svg{color:var(--ink-faint)}

/* bảng chi tiết trong hộp thoại */
.lic-rows{padding:18px 22px;display:grid;gap:11px}
.lic-row{display:flex;gap:14px;align-items:baseline;font-size:13.5px}
.lic-row .k{color:var(--ink-soft);min-width:120px;flex:none}
.lic-row .v{color:var(--ink);font-weight:600}
.lic-row .v.mono{font-family:var(--mono);font-weight:500;font-size:12.5px}
.lic-big{display:flex;align-items:baseline;gap:9px;padding:14px 16px;border-radius:var(--radius-sm);
  background:var(--hi-bg);color:var(--hi-text);margin-bottom:4px}
.lic-big b{font-size:26px;line-height:1;font-weight:700}
.lic-big.warn{background:var(--md-bg);color:var(--md-text)}
.lic-big.bad{background:var(--lo-bg);color:var(--lo)}
.lic-note{padding:0 22px 18px;font-size:12.5px;color:var(--ink-faint);line-height:1.55}
.lic-acts{display:flex;gap:10px;justify-content:flex-end;padding:0 22px 20px}

@media (max-width:860px){
  /* tránh đè lên nút "Quay lại" ở chân khung nội dung */
  .licbtn{left:12px;bottom:12px;padding:7px 11px 7px 9px;font-size:12px}
}

/* toast */
.toast{position:fixed;bottom:22px;left:50%;transform:translate(-50%,14px);opacity:0;
  background:var(--toast-bg);color:var(--toast-fg);padding:11px 18px;border-radius:10px;font-size:13px;z-index:80;
  transition:all .25s;box-shadow:0 12px 30px -10px rgba(0,0,0,.5);display:flex;gap:9px;align-items:center;max-width:90vw}
.toast.show{opacity:1;transform:translate(-50%,0)}
.toast .mono{font-size:12px;color:#9fd9c4}
/* toast tiến độ (Bước 1 đang trích xuất): phần trăm + thanh mảnh sát mép dưới */
.toast .pct{font-family:var(--mono);font-size:12.5px;font-weight:700;color:#9fd9c4;flex:none}
.toast .toast-bar{position:absolute;left:10px;right:10px;bottom:0;height:3px;border-radius:3px 3px 0 0;
  background:rgba(255,255,255,.12);overflow:hidden}
.toast .toast-bar i{display:block;height:100%;width:0;background:#9fd9c4;transition:width .3s}

.spin{display:inline-block;width:15px;height:15px;border:2px solid rgba(255,255,255,.4);
  border-top-color:#fff;border-radius:50%;animation:spin .7s linear infinite}
.btn:not(.primary) .spin{border:2px solid rgba(30,95,116,.3);border-top-color:var(--accent)}
@keyframes spin{to{transform:rotate(360deg)}}

@media (max-width:860px){
  .shell{grid-template-columns:1fr;gap:18px}
  .stepper{position:static;flex-direction:row;overflow-x:auto;gap:8px;padding-bottom:4px}
  .stepper .lead{display:none}
  .step{flex:none;width:auto;min-width:150px}
  .step .d{display:none}
  /* Bảng ghép co các cột rộng nhất lại thay vì ép cuộn ngang: cột nguồn/mẫu
     bớt bề rộng tối đa, cột giá trị mẫu bỏ luôn mức rộng tối thiểu — chữ dài
     bị cắt bằng dấu … (đã có sẵn ellipsis), bấm/trỏ chuột vào vẫn thấy đủ ở
     tooltip, còn hơn phải cuộn ngang mới xem hết cả bảng. */
  .mg-sample{min-width:0}
  .srcbtn,.mapsample{max-width:140px}
  .lanpill .addr{display:none}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}


/* ===========================================================================
   TÀI KHOẢN — trang đăng nhập, chip người dùng trên thanh trên, trang cá nhân
   =========================================================================== */
/* Trang đăng nhập: hẹp và đứng giữa, không có gì khác để phân tán — người dùng
   chỉ có đúng một việc phải làm ở đây. */
.dn-wrap{max-width:430px;margin:56px auto;padding:0 20px}
.dn-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
         box-shadow:var(--shadow);padding:28px 30px 30px}
.dn-card h2{margin:0 0 5px;font-size:20px;font-weight:600;letter-spacing:-.02em}
.dn-card p.lead{margin:0 0 20px;color:var(--ink-soft);font-size:13px;line-height:1.55}
.dn-lbl{display:block;font-size:12px;color:var(--ink-faint);text-transform:uppercase;
        letter-spacing:.07em;margin:16px 0 6px}
.dn-card input[type=text],.dn-card input[type=password]{width:100%;padding:10px 12px;
        border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--panel-2);
        color:var(--ink);font-size:14px;font-family:inherit}
.dn-card input:focus{outline:none;border-color:var(--accent)}
.dn-hint{margin-top:6px;font-size:11.5px;color:var(--ink-faint);line-height:1.55}
.dn-go{width:100%;margin-top:22px;background:var(--accent);color:#fff;border:0;
       border-radius:var(--radius-sm);padding:11px 20px;font-size:14.5px;font-weight:500;
       font-family:inherit}
.dn-go:hover{background:var(--accent-2)}
.dn-msg{margin:0 0 18px;padding:11px 14px;border-radius:var(--radius-sm);font-size:13px;
        line-height:1.55}
.dn-msg.bad{background:var(--lo-bg);color:var(--lo-text);border:1px solid rgba(192,70,58,.25)}
.dn-foot{margin-top:22px;padding-top:16px;border-top:1px solid var(--line-soft);
         font-size:12px;color:var(--ink-faint);line-height:1.6}

/* Chip người dùng trên thanh trên. Chữ cái đầu thay ảnh đại diện: ứng dụng chạy
   cục bộ, không có chỗ nào để tải ảnh về mà cũng không nên có. */
.userchip{display:flex;align-items:center;gap:9px;padding:5px 6px 5px 5px;border-radius:999px;
          border:1px solid var(--line);background:var(--card);color:var(--ink);
          text-decoration:none;font-size:12.5px;max-width:210px}
.userchip:hover{border-color:var(--line-hover);background:var(--hov)}
.userchip .avt,.tk-avt{flex:none;width:26px;height:26px;border-radius:50%;background:var(--accent);
          color:#fff;display:grid;place-items:center;font-size:12px;font-weight:600}
.userchip .who{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.userchip .adm{flex:none;font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
          color:var(--accent-2);background:var(--accent-soft);border-radius:4px;padding:2px 5px}
.logoutform{display:flex}
/* nút bánh răng xoay khi rê chuột là có chủ ý; mũi tên đăng xuất mà cũng xoay
   thì trông như hỏng, nên gỡ riêng hiệu ứng đó ở đây */
.logoutform .iconbtn:hover{transform:none}

/* Trang "Tài khoản của tôi" */
.tk-ai{display:flex;align-items:center;gap:11px;font-size:13.5px}
.tk-avt{width:34px;height:34px;font-size:14px}
.tk-ai .tk-u{display:block;font-size:11.5px;color:var(--ink-faint);margin-top:1px}
.tk-badge{display:inline-block;margin-top:4px;font-size:10px;font-weight:700;letter-spacing:.05em;
          text-transform:uppercase;color:var(--accent-2);background:var(--accent-soft);
          border-radius:4px;padding:2px 6px}
.tk-sw{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--ink-soft)}
.tk-sw input{width:16px;height:16px;accent-color:var(--accent)}

/* Bảng người dùng trong trang Cài đặt */
.nd-tbl{width:100%;border-collapse:collapse;font-size:13px}
.nd-tbl th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.06em;
           color:var(--ink-faint);font-weight:600;padding:0 10px 7px 0}
.nd-tbl td{padding:9px 10px 9px 0;border-top:1px solid var(--line-soft);vertical-align:middle}
.nd-tbl tr:first-child td{border-top:none}
.nd-tbl .nd-u{font-family:var(--mono);font-size:12px;color:var(--ink-faint)}
.nd-tbl .nd-act{text-align:right;white-space:nowrap}
.nd-tbl .btn{padding:5px 9px;font-size:12px}
.nd-toi{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
        color:var(--hi-text);background:var(--hi-bg);border-radius:4px;padding:2px 6px;margin-left:6px}
.nd-them{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:12px;
         padding-top:14px;border-top:1px solid var(--line-soft)}
.nd-them input[type=text],.nd-them input[type=password]{flex:1;min-width:140px}
.nd-them label{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--ink-soft)}
.nd-them label input{accent-color:var(--accent)}

/* Đang chờ máy chủ (ghép trường ở Bước 3). Đặt CHEN vào chỗ danh sách sắp hiện
   chứ không phủ lên cả trang: người dùng thấy ngay việc đang chạy ở đúng chỗ
   mình vừa bấm, và không có lớp mờ nào chặn nút Quay lại. */
.veil{display:flex;align-items:center;gap:13px;margin:14px 2px;padding:16px 18px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel-2);
  animation:rise .3s ease both}
.veil .spin{width:22px;height:22px;flex:none;border:2.5px solid var(--line);
  border-top-color:var(--accent)}
.veil b{font-size:13.5px}
.veil p{margin:3px 0 0;font-size:12.5px;color:var(--ink-soft)}
/* phần trăm ghép trường: số bên phải tiêu đề, thanh tiến độ + tên biểu mẫu đang ghép bên dưới */
.veil-body{flex:1;min-width:0}
.veil-pct{margin-left:9px;font-family:var(--mono);font-size:13px;font-weight:700;color:var(--accent)}
.veil-bar{height:5px;margin-top:9px;border-radius:3px;background:var(--line);overflow:hidden}
.veil-bar i{display:block;height:100%;width:0;background:var(--accent);border-radius:3px;transition:width .3s}
.veil small{display:block;margin-top:5px;font-size:12px;color:var(--ink-faint);min-height:1.2em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Bảng "Cần kiểm tra" ở Bước 1 — chỗ dữ liệu gộp về dễ sai nhất */
.kt-list{display:flex;flex-direction:column;gap:10px;padding:18px 22px 22px;
  max-height:min(62vh,560px);overflow:auto}
.kt-it{border:1px solid var(--line);border-radius:10px;padding:11px 13px;background:var(--card)}
.kt-it .kt-h{display:flex;align-items:baseline;gap:8px;font-size:12.5px;color:var(--ink-soft);
  flex-wrap:wrap}
.kt-it .kt-h .who{font-weight:600;color:var(--ink);font-size:13.5px}
.kt-it .kt-h .mono{font-family:var(--mono);font-size:11.5px;color:var(--ink-faint)}
.kt-kind{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  border-radius:4px;padding:2px 6px}
.kt-kind.xung_dot{background:var(--lo-bg);color:var(--lo-text)}
.kt-kind.gop{background:var(--hi-bg);color:var(--hi-text)}
.kt-kind.trung_ten,.kt-kind.tep_kem,.kt-kind.sua_danh_muc,.kt-kind.hiem_danh_muc{background:var(--md-bg);color:var(--md-text)}
.kt-kind.thieu_ten,.kt-kind.tep_loi,.kt-kind.tep_rong,.kt-kind.dinh_danh_kem{background:var(--lo-bg);color:var(--lo-text)}
.kt-detail{margin-top:7px;font-size:12px}
.kt-detail summary{cursor:pointer;color:var(--ink-faint)}
.kt-detail summary:hover{color:var(--ink-soft)}
.kt-detail code{display:block;margin-top:5px;padding:6px 8px;background:var(--panel-2);
  border-radius:6px;font-family:var(--mono);font-size:11.5px;color:var(--ink-soft);
  white-space:pre-wrap;word-break:break-word}
.kt-vals{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
.kt-val{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:9px;
  padding:6px 10px;background:var(--panel-2);font-size:13px;cursor:pointer;text-align:left}
.kt-val:hover{border-color:var(--accent);background:var(--hov)}
.kt-val.giu{border-color:var(--hi);background:var(--hi-bg)}
.kt-val .src{font-family:var(--mono);font-size:11px;color:var(--ink-faint)}
.kt-note{margin-top:7px;font-size:12.5px;color:var(--ink-soft)}
.kt-done{font-size:12.5px;color:var(--hi-text);font-weight:600;margin-top:8px}

/* ---- Bước 1: danh sách tệp + bảng tóm tắt của tệp đang xem --------------- */
/* Danh sách tệp dài hơn màn hình thì mọi nút phía dưới (thanh "Cần kiểm tra",
   bảng xem trước, nút Tiếp tục) bị đẩy khuất — người dùng phải cuộn cả trang
   mới thấy. Cho riêng danh sách cuộn trong khung của nó thì phần còn lại của
   bước 1 luôn nằm trong tầm mắt. */
/* Khoảng cách với khung kéo-thả đặt ở cả hai cột chứ không riêng danh sách:
   để margin trên .filelist thì khung tóm tắt bắt đầu cao hơn 22px, hai khung
   bằng nhau mà lệch nhau, nhìn như đo hỏng. */
.src-wrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;
  align-items:start;margin-top:22px}
.src-col{display:flex;flex-direction:column;gap:12px;min-width:0}
/* Đầu cột phải: nút "Trích xuất tệp" cùng hàng với hai nút sổ biểu mẫu trống,
   ngay trên khung tóm tắt #fileSum. Rỗng thì ẩn hẳn (chưa kịp vẽ bằng JS) để
   khỏi chừa một khoảng gap 12px vô nghĩa phía trên khung tóm tắt. */
.src-col-head{display:flex;align-items:center;justify-content:flex-start;gap:8px;
  flex-wrap:wrap;font-size:12px;color:var(--ink-faint)}
.src-col-head:empty{display:none}
/* Cột phải cao ĐÚNG bằng danh sách tệp (chiều cao do JS đo và đặt): hàng biểu
   mẫu trống cố định trên đầu, khung tóm tắt ăn hết phần thừa. Nhờ vậy ô chọn
   biểu mẫu đứng NGUYÊN MỘT CHỖ — tệp nào tóm tắt dài thì cuộn trong khung, chứ
   không đội cả hàng trên chạy lên chạy xuống theo. */
.src-col > .fsum{flex:1 1 auto;min-height:0}
.src-wrap > .filelist{margin-top:0}
.src-act{display:flex;gap:9px;flex:none}
.src-act .btn{flex:1;justify-content:center}
@media (max-width:1080px){ .src-wrap{grid-template-columns:1fr} }
.filelist-body{display:flex;flex-direction:column;gap:10px;
  max-height:min(48vh,430px);overflow-y:auto;padding:2px 4px 2px 2px}
/* Bước 2: hai khung cao CỐ ĐỊNH (chiều cao do coDanhSachBieuMau đo và đặt cho
   cả .filelist và cột phải), không co theo số biểu mẫu. Thư mục có 2 hay 200
   biểu mẫu thì nút "Tiếp tục" vẫn nằm nguyên một chỗ ở đáy trang, chứ không
   nhảy lên nhảy xuống mỗi lần thêm/xóa một tệp. Phần đầu danh sách đứng yên,
   chỉ ruột danh sách cuộn. */
/* Đầu danh sách bước 2 chỉ còn hai nút: space-between của .filelist-head sẽ
   đẩy chúng sang trái, mà chỗ cũ của chúng là mép phải — giữ nguyên mép phải. */
#tplFile .filelist-head{flex:none;justify-content:flex-end}
#tplFile .filelist-body{flex:1 1 auto;min-height:0;max-height:none}
.filelist-body::-webkit-scrollbar{width:9px}
.filelist-body::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
.filelist-body::-webkit-scrollbar-thumb:hover{background:var(--line-hover)}

.file .fchk-wrap{display:grid;place-items:center;padding:4px;margin:-4px;cursor:pointer}
/* .fn/.note là <span> nằm trong nút .body nên phải cho về khối, không thì cắt
   đuôi bằng ellipsis không ăn và phụ đề tràn ra một hàng với tên tệp */
.file .fn,.file .meta{display:block}
.file .note{display:flex}
.file .body{flex:1;min-width:0;display:flex;align-items:center;gap:14px;cursor:pointer;
  background:none;border:none;padding:0;text-align:left;color:inherit;font:inherit}
.file.dang-xem{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
.file .note .kem{background:var(--md-bg);color:var(--md-text)}
.file .note .ktnum{background:var(--lo-bg);color:var(--lo-text)}

/* Bảng tóm tắt của tệp đang xem */
/* Khung tóm tắt cao đúng bằng danh sách tệp bên trái (đo bằng JS ở
   coDanhSachTep) và tự cuộn bên trong. Không đặt overscroll-behavior:contain:
   cuộn hết khung rồi thì chuột phải lăn tiếp được cả trang, chứ đứng ở đây mà
   trang không nhúc nhích thì người dùng tưởng treo. */
.fsum{border:1px solid var(--line);border-radius:12px;background:var(--card);
  overflow-x:hidden;overflow-y:auto}
.fsum::-webkit-scrollbar{width:9px}
.fsum::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
.fsum::-webkit-scrollbar-thumb:hover{background:var(--line-hover)}
.fsum .fsum-empty{padding:26px 18px;font-size:12.5px;color:var(--ink-faint);text-align:center}
.fsum h4{margin:0;padding:12px 15px;border-bottom:1px solid var(--line);background:var(--panel-2);
  font-size:13px;font-weight:600;word-break:break-word;line-height:1.35;
  display:flex;align-items:flex-start;gap:10px}
.fsum h4 .htt{flex:1;min-width:0}
.fsum h4 .ext{font-family:var(--mono);font-size:10.5px;color:var(--ink-faint);
  display:block;margin-top:3px;font-weight:400}
/* Mức khớp với biểu mẫu trống — dùng cả ở góc trên khung tóm tắt lẫn ngay
   trong dòng tệp của danh sách bên trái, nên định nghĩa dùng chung. Không co
   (tên tệp dài thì cắt tên chứ đừng bóp con số xuống hai dòng) và mang tooltip
   nói rõ vì sao lại là con số ấy. */
.khop{flex:none;font-family:var(--mono);font-size:10.5px;font-weight:600;
  padding:3px 7px;border-radius:6px;white-space:nowrap;cursor:help;
  color:var(--hi-text);background:var(--hi-bg)}
.khop.thap{color:var(--md-text);background:var(--md-bg)}
/* Hàng đầu khung trường ở Bước 2: tên tệp bên trái, hai nút xem bên phải, một
   dòng. Tên tệp co được và cắt bằng ba chấm (tên đủ nằm ở tooltip), hai nút thì
   không co — nút là thứ có kích thước cố định, để nó co là chữ trong nút vỡ ra
   nhiều dòng và cả hàng cao gấp đôi. Trước đây hai nút nằm hẳn dòng dưới, tốn
   thêm một tầng chiều cao ngay trên danh sách trường vốn đã phải cuộn. Chỉ đổi
   riêng khung này: khung tóm tắt tệp ở Bước 1 cũng mang lớp .fsum nhưng tiêu đề
   của nó là tên tệp cộng một dòng phụ ở dưới, xếp ngang lại thành sai. */
.fsum.field-list h4{padding:10px 15px;word-break:normal;
  display:flex;align-items:center;gap:10px}
.fsum h4 .hten{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fsum h4 .hacts{flex:none;display:flex;gap:6px}
/* Lúc chờ dò trường thì chưa có nút nào để bấm, chỗ ấy đặt chữ “Đang nạp…”.
   Nhạt và nhỏ hơn tên tệp: nó là tin báo tạm, không phải một phần của tiêu đề. */
.fsum h4 .hnote{flex:none;font-weight:400;font-size:11.5px;color:var(--ink-faint)}
.fsum h4 .hacts .mini{background:var(--card);border:1px solid var(--line);border-radius:7px;
  padding:4px 10px;font-family:var(--sans);font-size:11.5px;font-weight:500;
  color:var(--ink-soft);line-height:1.45;cursor:pointer;transition:all .13s}
.fsum h4 .hacts .mini:hover{border-color:var(--accent);color:var(--accent)}
.fsum h4 .hacts .mini:disabled{opacity:.55;cursor:default}
.fsum .nums{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line);
  border-bottom:1px solid var(--line)}
.fsum .num{background:var(--card);padding:11px 13px}
.fsum .num b{display:block;font-size:19px;line-height:1.15;font-variant-numeric:tabular-nums}
.fsum .num span{font-size:11.5px;color:var(--ink-soft)}
.fsum .num.canh b{color:var(--md-text)}
.fsum .num.xau b{color:var(--lo-text)}
.fsum .sec{padding:12px 15px;border-bottom:1px solid var(--line-soft)}
.fsum .sec:last-child{border-bottom:none}
.fsum .sec>p{margin:0 0 7px;font-size:11px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-faint)}
.fsum .chips{display:flex;flex-wrap:wrap;gap:5px}
.fsum .chip{font-size:11.5px;background:var(--panel-2);border:1px solid var(--line);
  border-radius:6px;padding:2px 4px 2px 7px;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;display:inline-flex;align-items:center;gap:1px}
/* Tên trường co lại nhường chỗ cho dấu ×, chứ không đẩy nó ra khỏi thẻ. Cho nó
   giãn hết chỗ trống để dấu × nằm sát mép phải — mỗi thẻ một dòng, × so le theo
   độ dài tên thì mắt phải dò lại vị trí nút ở từng dòng. Giống khối chi tiết
   bản ghi (.rec-full .rc) cho quen tay. */
.fsum .chip .ct{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fsum .chip .col-rm{font-size:12px;padding:1px 4px}
.fsum .chip:hover .col-rm{opacity:1}
.fsum .chip.nut{cursor:pointer;color:var(--ink-soft);font-family:inherit}
.fsum .chip.nut:hover{border-color:var(--accent);color:var(--accent)}
.fsum .chip-note{margin-top:7px;font-size:11px;line-height:1.45;color:var(--ink-faint);
  white-space:normal}
.fsum .chip.vang{background:#fff4bf;border-color:#e6d075;color:#5b4a05}
:root[data-theme="dark"] .fsum .chip.vang{background:#4a3f10;border-color:#6d5c16;color:#f2e6b0}
.fsum .kt-mini{display:flex;gap:7px;align-items:baseline;font-size:12.5px;line-height:1.4;
  padding:5px 0;border-top:1px solid var(--line-soft)}
.fsum .kt-mini:first-of-type{border-top:none}
.fsum .kt-mini .kt-kind{flex:none}
/* Hàng biểu mẫu trống, ngay trong dòng của MỘT tệp Word/PDF (Bước 1): nhãn —
   ô chọn — nhãn phần trăm khớp. Ô chọn ăn hết phần thừa vì tên biểu mẫu dài,
   hai thứ còn lại cố định. Viền trên mảnh phân tầng với .file-main phía trên. */
.file-mt{display:flex;align-items:center;gap:8px;padding-top:8px;border-top:1px solid var(--line-soft)}
.mt-lb{flex:none;font-size:11.5px;letter-spacing:.03em;text-transform:uppercase;
  font-weight:600;color:var(--ink-faint)}
.mt-sel{flex:1 1 auto;min-width:0;font-family:var(--sans);font-size:12.5px;padding:6px 8px;
  border:1px solid var(--line);border-radius:7px;background:var(--panel-2);color:var(--ink)}
.mt-sel:focus{outline:none;border-color:var(--accent)}
.mt-sel:disabled{color:var(--ink-faint)}
/* mẫu bố cục cố định in đậm trong danh sách thả xuống, và trong ô khi đang chọn nó */
.mt-sel option.co-dinh,.mt-sel.co-dinh{font-weight:700}
/* Dòng cảnh báo LUÔN HIỆN (không chỉ trong tooltip) khi mẫu đã chọn không rút
   ra được gì để dùng — cùng màu với thẻ "kém chắc chắn" ở nơi khác trong app. */
.mt-warn{font-size:12px;color:var(--md-text);background:var(--md-bg);
  border-radius:7px;padding:6px 9px;line-height:1.4}

/* "?" trợ giúp tại chỗ: giải thích ngay cạnh thứ đang gây bí, kèm liên kết
   sang trang Hướng dẫn — thay vì bắt người dùng rời màn hình đi tìm dấu ?
   ở góc trên rồi tự đoán mục nào ứng với chỗ mình đang vướng. */
.help-q{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:15px;height:15px;border-radius:50%;background:var(--panel-2);
  border:1px solid var(--line);color:var(--ink-faint);font:700 10px/1 var(--sans);
  cursor:pointer;padding:0}
.help-q:hover{border-color:var(--accent);color:var(--accent)}
.help-pop{position:absolute;z-index:60;width:280px;max-width:calc(100vw - 24px);
  background:var(--card);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 12px 30px -10px rgba(0,0,0,.35);padding:12px 14px;
  font-size:12.5px;line-height:1.5;color:var(--ink)}
.help-pop b{display:block;margin-bottom:6px}
.help-pop a{color:var(--accent);font-weight:600;white-space:nowrap}
.fsum .fsum-act{padding:11px 15px;display:flex}
.fsum .fsum-act .btn{width:100%;justify-content:center;padding:7px 10px;font-size:12.5px}
.fsum .ghi{padding:0 15px 13px;font-size:12px;color:var(--ink-soft);line-height:1.45}


/* ==================== TRANG HƯỚNG DẪN (/huong-dan) ====================
   Trang toàn chữ, đọc từ trên xuống một lượt. Dùng lại khung .set-* của các
   trang phụ khác để không phải nuôi thêm một bộ khung nữa, chỉ thêm phần chữ:
   dòng dài hơn, dãn dòng rộng hơn — đây là trang để ĐỌC, không phải để bấm. */
.hd-wrap .set-body{padding:16px 22px 20px}
.hd-p{margin:0 0 11px;font-size:13.5px;line-height:1.75;color:var(--ink-soft)}
.hd-p:last-child{margin-bottom:0}

/* "Nên xem lại: …" — chỗ dễ sai nhất của mỗi bước, tách hẳn khỏi đoạn kể
   chuyện bằng vạch màu để người đang vội vẫn nhặt được. */
/* Vạch dùng --accent chứ không --accent-soft: bản "soft" là màu NỀN nhạt,
   đặt làm vạch thì nền tối gần như mất hẳn (#173038 trên thẻ #171F28). */
.hd-check{margin:10px 0 0;padding:8px 0 8px 13px;border-left:2px solid var(--accent);
  font-size:12.5px;line-height:1.7;color:var(--ink-soft)}

/* Lời trấn an / lời phân biệt, đặt cuối một mục */
.hd-note{margin:14px 0 0;padding:10px 13px;border-radius:var(--radius-sm);
  background:var(--panel-2);border:1px solid var(--line-soft);
  font-size:12.5px;line-height:1.7;color:var(--ink-soft)}

/* ---------- dải bốn chặng: tệp vào -> tệp ra ---------- */
.hd-flow{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:14px 0 2px}
.hd-flow-i{font-size:12px;font-weight:600;color:var(--ink-soft);background:var(--panel-2);
  border:1px solid var(--line-soft);border-radius:999px;padding:5px 12px;white-space:nowrap}
.hd-flow-a{color:var(--ink-faint);font-size:13px}
.hd-flow-end{color:var(--accent);border-color:var(--accent-soft)}

/* ---------- bốn bước ---------- */
.hd-step{display:grid;grid-template-columns:34px 1fr;gap:14px;padding:16px 0;
  border-bottom:1px solid var(--line-soft)}
.hd-step:first-child{padding-top:4px}
.hd-step:last-child{border-bottom:none;padding-bottom:2px}
.hd-num{width:28px;height:28px;border-radius:50%;background:var(--accent);color:#fff;
  font-size:13px;font-weight:700;display:grid;place-items:center;margin-top:1px}
.hd-body{min-width:0}
.hd-body h4{margin:0 0 8px;font-size:14.5px;font-weight:600;letter-spacing:-.01em}

/* tiêu đề phụ giữa thân một mục */
.hd-sub{margin:20px 0 8px;font-size:13.5px;font-weight:600;color:var(--ink)}

/* ---------- hai dạng tệp dữ liệu, đứng cạnh nhau ---------- */
.hd-two{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:12px 0 2px}
.hd-card{background:var(--panel-2);border:1px solid var(--line-soft);
  border-radius:var(--radius-sm);padding:12px 14px}
.hd-card h5{margin:0 0 6px;font-size:12.5px;font-weight:700;color:var(--accent);
  letter-spacing:.02em}
.hd-card p{margin:0;font-size:12.5px;line-height:1.7;color:var(--ink-soft)}

/* ---------- mẹo dùng & câu hỏi: cùng một kiểu, cùng một nhịp đọc ---------- */
.hd-tip,.hd-qa{padding:13px 0;border-bottom:1px solid var(--line-soft)}
.hd-tip:first-child,.hd-qa:first-child{padding-top:2px}
.hd-tip:last-child,.hd-qa:last-child{border-bottom:none;padding-bottom:2px}
.hd-tip h4,.hd-qa h4{margin:0 0 7px;font-size:13.5px;font-weight:600;letter-spacing:-.01em}
.hd-qa h4{color:var(--accent-2)}

/* Ví dụ gõ nguyên văn — chữ đơn cách, và KHÔNG dịch sang tiếng Anh: dịch cái
   này ra thì người dùng gõ theo bản dịch, mà biểu mẫu thì vẫn tiếng Việt. */
.hd-eg{margin:9px 0;padding:9px 12px;border-radius:var(--radius-sm);
  background:var(--panel-2);border:1px solid var(--line-soft);
  font-size:12.5px;color:var(--ink);overflow-x:auto;white-space:nowrap}

.hd-foot{margin:22px 2px 0;font-size:12.5px;line-height:1.7;color:var(--ink-faint);
  text-align:center}

@media (max-width:640px){
  .hd-two{grid-template-columns:1fr}
  .hd-step{grid-template-columns:26px 1fr;gap:11px}
  .hd-num{width:24px;height:24px;font-size:12px}
  .hd-wrap .set-body{padding:14px 16px 18px}
  .hd-flow-i{white-space:normal}
}
