/* =============================================================================
   app.css — giao diện web quản lý "SecureNotepad Cloud".

   ═══ RÀNG BUỘC CỦA CSP (Api/WebStatic.cs) ═══

   style-src 'self'  ⇒ KHÔNG thuộc tính style= trong HTML, KHÔNG thẻ <style> nội tuyến.
                       Mọi thứ nhìn thấy được đều phải đi qua đúng tệp này.
   img-src  'none'   ⇒ KHÔNG background-image, KHÔNG data: URI, KHÔNG một tấm ảnh nào.
                       Mọi biểu tượng là SVG NỘI TUYẾN: app.js chèn một <svg class="sprite">
                       chứa các <symbol> vào đầu <body>, rồi mỗi icon là một
                       <svg class="ico"><use href="#i-..."> — không có lượt tải nào.
   font-src 'none'   ⇒ KHÔNG webfont, KHÔNG Google Fonts. Chỉ font sẵn có của máy.

   Hệ quả trực tiếp: bật/tắt hiển thị bằng lớp .hidden chứ không bằng el.style.display,
   và bề rộng thanh dung lượng là một lớp có sẵn (.w0 … .w100) chứ không phải style="width".

   ═══ HAI CHỦ ĐỀ, MỘT BỘ TOKEN ═══

   Mọi màu đều là biến ở :root. Chủ đề tối chỉ ĐỊNH NGHĨA LẠI các biến đó trong
   @media (prefers-color-scheme: dark) — không một luật bố cục nào phải viết hai lần. Nhờ
   vậy không tồn tại lớp lỗi "quên đổi một màu ở chủ đề kia", thứ luôn hiện ra dưới dạng
   chữ đen trên nền đen ở đúng một chỗ hiếm gặp.

   Bảng màu: nhấn PETROL (xanh mực pha lục) + dải trung tính lệch theo chính nó. Chọn có
   chủ đích — sản phẩm này bán sự chắc chắn, không bán sự phấn khích. Mọi cặp chữ/nền dưới
   đây đã đo và đều ≥ 4.5:1 (WCAG AA) ở CẢ HAI chủ đề; cặp thấp nhất là 5.68:1.

   ═══ TƯƠNG PHẢN PHI CHỮ (WCAG 2.1 mục 1.4.11) ═══

   --line-2 là màu viền của NÚT, Ô NHẬP, ô đánh dấu và số thứ tự các bước. Với ô nhập nó
   còn là RANH GIỚI DUY NHẤT: nền ô nhập dùng đúng var(--surface) của tấm panel bao ngoài,
   nên viền mờ đi là người thị lực thấp nhìn thấy một khoảng trắng phẳng lì và không biết
   phải gõ vào đâu. Vì vậy --line-2 phải đạt ≥ 3.0:1 với MỌI nền nó nằm cạnh, đo bằng
   công thức relative luminance của WCAG. Đã đo từng cặp có thật trong tệp này và trong
   mọi tệp .html (giá trị thấp nhất / giá trị cao nhất):

     sáng #798b8b — vs --surface #ffffff 3.57:1 · --surface-2 #f5f8f8 3.35:1 ·
                       --bg #eef1f2 3.15:1 · --danger-soft #fbeceb 3.11:1  (nút "Thử lại
                       ngay" trên .sysbar.err là chỗ duy nhất viền này nằm trên nền trạng thái)
     tối  #617372 — vs --surface #131d1c 3.44:1 · --surface-2 #1b2625 3.11:1 ·
                       --bg #0c1413 3.74:1 · --danger-soft #2c1614 3.41:1

   Giá trị cũ (#aabcbc / #455756) trượt ở CẢ HAI chủ đề trên MỌI cặp: cao nhất mới 2.44:1,
   thấp nhất 1.72:1. Hai màu mới là mức tối thiểu kèm một chút biên (≈3.5% trên ngưỡng) —
   cố ý KHÔNG đẩy đậm hơn nữa để viền không biến thành nét nặng.
   ============================================================================= */

:root {
  color-scheme: light dark;

  /* ── Nền và bề mặt ── */
  --bg: #eef1f2;
  --surface: #ffffff;
  --surface-2: #f5f8f8;
  --line: #ccd6d6;
  --line-2: #798b8b;   /* viền tương tác — xem "TƯƠNG PHẢN PHI CHỮ" ở đầu tệp */

  /* ── Chữ ── */
  --ink: #101f1e;
  --dim: #4d5f5e;

  /* ── Nhấn ── */
  --accent: #0a5f60;
  --accent-ink: #ffffff;
  --accent-soft: #dfebea;
  --accent-line: #97bfbd;

  /* ── Trạng thái ── */
  --danger: #a4231b;
  --danger-ink: #ffffff;
  --danger-soft: #fbeceb;
  --danger-line: #e3b3ae;

  --warn-ink: #5f4200;
  --warn-soft: #fdf4e0;
  --warn-line: #dfc07a;

  --ok: #116b41;
  --ok-soft: #e4f2ea;
  --ok-line: #9ccdb4;

  /* ── Hình khối ── */
  --r-sm: 6px;
  --r-md: 9px;
  --r-lg: 13px;
  --shadow: 0 1px 2px rgba(16, 31, 30, .06), 0 6px 18px rgba(16, 31, 30, .05);
  --shadow-lift: 0 10px 34px rgba(16, 31, 30, .18);
  --veil: rgba(8, 18, 17, .55);

  --font: "Segoe UI Variable Text", "Segoe UI", Roboto, system-ui, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", Consolas, "Segoe UI Mono", "Roboto Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0c1413;
    --surface: #131d1c;
    --surface-2: #1b2625;
    --line: #2c3a39;
    --line-2: #617372;   /* viền tương tác — xem "TƯƠNG PHẢN PHI CHỮ" ở đầu tệp */

    --ink: #e7edec;
    --dim: #9aacaa;

    --accent: #5ed3c8;
    --accent-ink: #04211f;
    --accent-soft: #14302e;
    --accent-line: #2f5b57;

    --danger: #ff9c92;
    --danger-ink: #2a0805;
    --danger-soft: #2c1614;
    --danger-line: #5c2d28;

    --warn-ink: #f0d79a;
    --warn-soft: #2a2313;
    --warn-line: #55461f;

    --ok: #5fd69b;
    --ok-soft: #14291f;
    --ok-line: #2c5340;

    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 18px rgba(0, 0, 0, .35);
    --shadow-lift: 0 10px 34px rgba(0, 0, 0, .6);
    --veil: rgba(0, 0, 0, .68);
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  min-height: 100vh;
}

::selection { background: var(--accent-soft); color: var(--ink); }

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

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Bỏ qua thanh điều hướng bằng bàn phím. Hiện ra khi và chỉ khi nhận tiêu điểm. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 50;
  background: var(--accent);
  color: var(--accent-ink);
  padding: 10px 16px;
  border-radius: 0 0 var(--r-md) 0;
}
.skip:focus { left: 0; }

/* ════════════════ Đầu trang ════════════════ */

header.top {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.topin {
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
  padding: 10px 18px;
}

/* ── Dấu hiệu thương hiệu: một ổ khóa SVG nội tuyến trên nền nhấn ──
   Nằm thẳng trong HTML (không qua sprite) để hiện được cả khi app.js chưa chạy. */
.brand { display: flex; align-items: center; gap: 10px; color: inherit; }
.brand:hover { text-decoration: none; }

.mark {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  padding: 5px;
  border-radius: 9px;
  background: var(--accent);
  color: var(--accent-ink);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.brandtext { display: flex; flex-direction: column; line-height: 1.15; }
.brandtext b { font-weight: 650; letter-spacing: -.01em; }
.brandsub {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}

nav.nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex: 1 1 auto;
}
nav.nav a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px 6px 10px;
  border-radius: 999px;
  color: var(--dim);
  white-space: nowrap;
}
nav.nav a .ico { width: 17px; height: 17px; opacity: .85; }
nav.nav a.here .ico { opacity: 1; }
nav.nav a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
nav.nav a.here {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 650;
}

.who {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--dim);
  font-size: 14px;
  min-width: 0;
}
.who > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.who > span > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}
.who .ico { color: var(--accent); }

/* ════════════════ Thanh trạng thái hệ thống ════════════════
   Đồng bộ · chỉ-đọc 507 · mất mạng. MỘT thành phần, đổi lớp để đổi nghĩa — người dùng
   học một chỗ để nhìn, và mọi thông điệp đều kèm hướng xử lý chứ không chỉ báo hỏng. */

.sysbar {
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--dim);
}
.sysbar .in {
  max-width: 1180px;
  margin: 0 auto;
  padding: 8px 18px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  font-size: 14px;
}
/* app.js chen mot <svg class="ico dot">; connect.js (trang cap quyen, khong co sprite) van
   chen <span class="dot"> - span thi ve thanh cham tron nhu cu. */
.sysbar .dot { flex: 0 0 auto; width: 17px; height: 17px; }
.sysbar span.dot { width: 9px; height: 9px; border-radius: 50%; background: currentColor; }
.sysbar.warn { background: var(--warn-soft); border-bottom-color: var(--warn-line); color: var(--warn-ink); }
.sysbar.err  { background: var(--danger-soft); border-bottom-color: var(--danger-line); color: var(--danger); }
.sysbar.ok   { background: var(--ok-soft); border-bottom-color: var(--ok-line); color: var(--ok); }
.sysbar b { font-weight: 650; }
.sysbar button { padding: 3px 10px; font-size: 13px; }

/* Nhịp thở nhẹ khi đang đồng bộ. Tôn trọng người đã tắt hiệu ứng chuyển động. */
.sysbar.busy .dot { animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .28; } }

/* ════════════════ Băng cố định: hai câu KHÔNG được gỡ khỏi trang nào ════════════════ */

.notice {
  background: var(--warn-soft);
  border-bottom: 1px solid var(--warn-line);
  color: var(--warn-ink);
}
.notice .in {
  max-width: 1180px;
  margin: 0 auto;
  padding: 11px 18px 11px 40px;
  position: relative;
  font-size: 14px;
}
/* Dấu chấm than vẽ bằng CSS — không emoji, không ảnh. */
.notice .in::before {
  content: "!";
  position: absolute;
  left: 18px;
  top: 13px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--warn-ink);
  color: var(--warn-soft);
  font-size: 12px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
.notice p { margin: 0 0 4px 0; }
.notice p:last-child { margin-bottom: 0; }
.notice strong { color: var(--danger); }

/* ════════════════ Khung nội dung ════════════════ */

main {
  max-width: 1180px;
  margin: 0 auto;
  padding: 22px 18px 56px 18px;
}

h1 {
  font-size: 24px;
  font-weight: 650;
  letter-spacing: -.015em;
  margin: 0 0 6px 0;
}
h2 {
  font-size: 16px;
  font-weight: 650;
  margin: 0 0 10px 0;
}
h3 { font-size: 15px; font-weight: 650; margin: 0 0 8px 0; }

.lede { color: var(--dim); margin: 0 0 20px 0; max-width: 74ch; }
p.note { color: var(--dim); margin: 8px 0; font-size: 14px; max-width: 82ch; }
p.note:last-child { margin-bottom: 0; }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 18px;
  box-shadow: var(--shadow);
  margin-bottom: 18px;
}
.panel:last-child { margin-bottom: 0; }
.panel > h2 { display: flex; align-items: center; gap: 8px; }
.panel > h2::before {
  content: "";
  width: 3px;
  height: 15px;
  border-radius: 2px;
  background: var(--accent);
}
.panel > h2.hasico::before { display: none; }
.panel > h2 .ico {
  width: 30px;
  height: 30px;
  padding: 6px;
  border-radius: 8px;
  background: var(--accent-soft);
  color: var(--accent);
}
h1.hasico { display: flex; align-items: center; gap: 10px; }
h1 .ico { width: 26px; height: 26px; color: var(--accent); }

/* ════════════════ Nút ════════════════ */

button {
  font: inherit;
  font-weight: 550;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  padding: 7px 14px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  vertical-align: middle;
}
button .ico { width: 17px; height: 17px; }
button.danger .ico { color: var(--danger); }
button:hover { background: var(--surface-2); border-color: var(--accent); }
button:disabled { opacity: .45; cursor: not-allowed; }
button:disabled:hover { background: var(--surface); border-color: var(--line-2); }

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
button.primary:hover { background: var(--accent); filter: brightness(1.12); }

button.danger { color: var(--danger); border-color: var(--danger-line); background: var(--surface); }
button.danger:hover { background: var(--danger-soft); border-color: var(--danger); }

/* Nút "trông như liên kết" — dùng trong ô Thao tác của bảng. */
button.link {
  border: 0;
  background: none;
  color: var(--accent);
  padding: 2px 3px;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}
button.link:hover { background: none; color: var(--accent); filter: brightness(1.15); }
button.link.danger { color: var(--danger); background: none; }
button.link.danger:hover { background: none; }

/* ════════════════ Ô nhập ════════════════ */

input[type=text], input[type=password], input[type=email], select {
  font: inherit;
  padding: 8px 11px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  min-width: 220px;
  max-width: 100%;
}
input::placeholder { color: var(--dim); opacity: .85; }
input:focus, select:focus { border-color: var(--accent); }

label { display: block; margin: 14px 0 5px 0; font-weight: 600; font-size: 14px; }

.field { margin-top: 14px; }
.field:first-child { margin-top: 0; }
.field label { margin-top: 0; }
.field input { width: 100%; }
.hint { color: var(--dim); font-size: 13px; margin: 5px 0 0 0; }

/* Hàng ô đánh dấu — vùng bấm rộng, viền rõ, không phải một ô 13px trần trụi. */
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  cursor: pointer;
  margin: 16px 0;
}
.check:hover { border-color: var(--accent); }

/* Bộ chọn phải mang [type=checkbox] chứ không phải `input` trần.
   Lý do là một luật khác trong tệp này: `.auth input { width: 100% }` (trang đăng nhập /
   đăng ký / cấp quyền cho ô nhập tràn hết bề ngang). Hai bộ chọn đó CÙNG độ đặc hiệu
   (0,1,1), nên cái đứng SAU trong tệp thắng — và `.auth` đứng sau. Hậu quả đã nhìn thấy
   trên ảnh chụp thật: ô đánh dấu phình ra 100% bề ngang, đẩy dòng chữ ra một cột dọc rộng
   một chữ nằm ngoài khung. Thêm [type=checkbox] nâng độ đặc hiệu lên (0,2,1) nên luật này
   thắng bất kể thứ tự. */
.check input[type=checkbox] {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  min-width: 0;
  margin: 2px 0 0 0;
  accent-color: var(--accent);
}
.check span { flex: 1 1 auto; min-width: 0; font-weight: 600; }

/* ════════════════ Bảng ════════════════ */

.tablewrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}
table { border-collapse: collapse; width: 100%; min-width: 520px; }
th, td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
thead th {
  background: var(--surface-2);
  color: var(--dim);
  font-size: 12px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .05em;
  white-space: nowrap;
}
tbody tr:hover td { background: var(--surface-2); }
td.name { word-break: break-word; min-width: 170px; max-width: 380px; font-weight: 550; }
td.time { white-space: nowrap; color: var(--dim); font-variant-numeric: tabular-nums; }
td.dev { white-space: nowrap; }
td.acts, th.acts { white-space: nowrap; width: 1%; }
th.acts { text-align: right; }
td.acts .actrow { display: flex; justify-content: flex-end; gap: 2px; }

/* Tên tệp / thư mục / thiết bị: icon nhỏ + chữ. Căn theo DÒNG ĐẦU chứ không căn giữa:
   td.name cố ý cho tên dài xuống dòng, và một icon căn giữa khối bốn dòng trông như thuộc
   về hàng khác. */
/* KHÔNG flex-wrap: bẻ dòng ở mức flex là đẩy cả khối chữ xuống DƯỚI icon (đã thấy trên ảnh).
   Chữ phải xuống dòng BÊN TRONG span của nó, nên span cần min-width:0 để được phép co. */
.fname { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.fname > span { min-width: 0; }
.fname .ico { flex: 0 0 auto; color: var(--dim); margin-top: 2px; }
.fname .sub { color: var(--dim); font-size: 12.5px; font-weight: 500; white-space: nowrap; }
.fname .ico.file { color: var(--accent); opacity: .9; }
.fname .ico.plat { width: 16px; height: 16px; }
tr.gone .fname .ico { color: var(--dim); }
td.num, th.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
tr.gone td { color: var(--dim); }

.empty { color: var(--dim); padding: 22px 4px; text-align: center; }
.empty.hasico { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.empty.hasico .ico { width: 36px; height: 36px; color: var(--line-2); stroke-width: 1.4; }

/* ════════════════ Trang Kho ════════════════ */

.kho { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
aside.tree { flex: 0 0 268px; max-height: 72vh; overflow: auto; padding: 12px; }
section.list { flex: 1 1 520px; min-width: 0; }

.tree ul { list-style: none; margin: 0; padding-left: 13px; }
.tree > ul { padding-left: 0; }
.tree button.node {
  border: 0;
  background: none;
  text-align: left;
  width: 100%;
  padding: 5px 8px;
  border-radius: var(--r-sm);
  font-weight: 500;
  word-break: break-word;
  justify-content: flex-start;
  gap: 8px;
}
.tree button.node .ico { color: var(--dim); }
.tree button.node.sel .ico { color: var(--accent); }
.tree button.node span { min-width: 0; }
.tree button.node:hover { background: var(--surface-2); border: 0; }
.tree button.node.sel {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 650;
}

.toolbar { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; align-items: center; }
.toolbar input { min-width: 0; flex: 1 1 170px; }
.toolbar .search { flex: 1 1 190px; min-width: 0; }
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  color: var(--dim);
  margin: 0 0 12px 0;
  word-break: break-word;
  font-size: 14px;
}
.crumbs > .ico { color: var(--accent); margin-right: 4px; }
.crumbs .ico.sep { width: 14px; height: 14px; opacity: .6; }
.crumbs b { color: var(--ink); }
.crumbs a { display: inline-flex; align-items: center; gap: 6px; }

/* Ô tìm kiếm: icon kính lúp nằm trong ô, không chiếm một nút riêng. */
.search { position: relative; display: block; }
.search .ico {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--dim);
  pointer-events: none;
}
.search input { width: 100%; padding-left: 34px; }

/* ════════════════ Thông báo nổi ════════════════ */

.toast {
  position: fixed;
  left: 50%;
  bottom: 20px;
  z-index: 40;
  transform: translateX(-50%);
  background: var(--ink);
  color: var(--bg);
  padding: 11px 18px;
  border-radius: var(--r-md);
  max-width: min(560px, 92vw);
  word-break: break-word;
  box-shadow: var(--shadow-lift);
  font-size: 14px;
}
.toast { display: flex; align-items: center; gap: 10px; }
.toast .ico { flex: 0 0 auto; }
.toast.err { background: var(--danger); color: var(--danger-ink); }

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

.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--veil);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.modal .box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px;
  width: 480px;
  max-width: 100%;
  max-height: 88vh;
  overflow: auto;
  box-shadow: var(--shadow-lift);
}
.modal h3 { margin: 0 0 10px 0; font-size: 17px; display: flex; align-items: center; gap: 9px; }
.modal h3 .ico { width: 22px; height: 22px; color: var(--accent); }
.modal h3.danger .ico { color: var(--danger); }
.modal .row { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; flex-wrap: wrap; }
.modal input, .modal select { width: 100%; min-width: 0; }

/* ════════════════ Trang xác thực: đăng nhập · đăng ký · cấp quyền ════════════════ */

.auth { max-width: 480px; margin: 4vh auto 0 auto; }
.auth.wide { max-width: 640px; }
.auth .panel { padding: 24px; }
.auth h1 { margin-bottom: 4px; }
.auth input { width: 100%; }

/* Nút chính CHIẾM HẾT bề ngang — nhưng chỉ khi nó là hành động duy nhất của thẻ, tức là
   con TRỰC TIẾP của .panel. Viết `.auth button.primary` trần thì luật này cũng tóm cả nút
   "Cho phép" nằm trong .rowbtns của trang cấp quyền, và nút "Từ chối" bên cạnh bị đẩy
   xuống dòng dưới — đã nhìn thấy trên ảnh chụp thật. */
.auth .panel > button.primary { width: 100%; margin-top: 18px; padding: 10px 14px; display: flex; }

.authfoot {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  color: var(--dim);
  font-size: 14px;
}
.authfoot p { margin: 6px 0; }

/* Hai thẻ chuyển giữa Đăng nhập và Tạo tài khoản trên trang cấp quyền. */
.tabs {
  display: flex;
  gap: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: 4px;
  border-radius: var(--r-md);
  margin-bottom: 18px;
}
.tabs button {
  flex: 1 1 0;
  border: 1px solid transparent;
  background: none;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  color: var(--dim);
}
.tabs button:hover { background: none; color: var(--ink); border-color: transparent; }
.tabs button.on {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
  font-weight: 650;
}

.err { color: var(--danger); margin-top: 12px; font-size: 14px; }
.ok { color: var(--ok); margin-top: 12px; font-size: 14px; }
.err:empty, .ok:empty { margin: 0; }

/* ════════════════ Mã: kết nối và khôi phục ════════════════ */

/* Mã kết nối XXXX-XXXX — phải đọc được từ xa để đối chiếu với màn hình ứng dụng. */
.bigcode {
  font-family: var(--mono);
  font-size: clamp(28px, 8.5vw, 44px);
  font-weight: 700;
  letter-spacing: .1em;
  text-align: center;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  padding: 14px 8px;
  margin: 0;
  word-break: break-all;
  font-variant-numeric: tabular-nums;
}

/* Mã khôi phục: 10 nhóm 5 ký tự. Lưới để chép tay không trượt dòng. */
.codegrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(86px, 1fr));
  gap: 8px;
  margin: 14px 0;
  padding: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.codegrid span {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 650;
  letter-spacing: .06em;
  text-align: center;
  padding: 7px 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-variant-numeric: tabular-nums;
  -webkit-user-select: all;
  user-select: all;
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; word-break: break-all; }

/* ════════════════ Danh sách nhãn — giá trị ════════════════ */

.kv { display: grid; grid-template-columns: max-content 1fr; gap: 9px 20px; margin: 0; }
.kv dt { color: var(--dim); font-size: 14px; }
.kv dd { margin: 0; font-weight: 600; word-break: break-word; }
.kv dd.num { font-variant-numeric: tabular-nums; }

/* ════════════════ Các bước ════════════════ */

.steps { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 18px 0; padding: 0; list-style: none; }
.steps li {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--dim);
  font-size: 13px;
  font-weight: 600;
}
.steps li i {
  width: 21px;
  height: 21px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  font-style: normal;
  font-size: 12px;
  line-height: 19px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.steps li.on { color: var(--accent); }
.steps li.on i { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.steps li.done { color: var(--ok); }
.steps li.done i { border-color: var(--ok); color: var(--ok); }

/* ════════════════ Chờ lâu: dấu hiệu quay ════════════════
   PBKDF2 600.000 vòng mất 1–5 giây và CHẶN luồng giao diện. Không có dấu hiệu này thì
   người dùng tưởng trang treo rồi bấm lại. */

.busyrow {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 15px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  color: var(--ink);
  margin: 16px 0;
  font-size: 14px;
}
.spin {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 2px solid var(--accent-line);
  border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .sysbar.busy .dot { animation: none; }
  .spin { animation-duration: 2.4s; }
}

/* ════════════════ Hộp nhấn mạnh ════════════════ */

.callout {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  background: var(--surface-2);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding: 13px 15px;
  margin: 16px 0;
  font-size: 14px;
}
.callout.warn { border-color: var(--warn-line); border-left-color: var(--warn-ink); background: var(--warn-soft); color: var(--warn-ink); }
.callout.danger { border-color: var(--danger-line); border-left-color: var(--danger); background: var(--danger-soft); color: var(--danger); }
.callout.ok { border-color: var(--ok-line); border-left-color: var(--ok); background: var(--ok-soft); color: var(--ok); }
/* Icon ở cột trái, MỌI đoạn văn xếp dọc ở cột phải. Dùng grid chứ không flex: flex sẽ đặt
   hai <p> đứng cạnh nhau thành hai cột chữ - đã thấy trên ảnh chụp trang Đăng ký. */
.callout.hasico { display: grid; grid-template-columns: 20px 1fr; column-gap: 12px; }
.callout.hasico > .ico { grid-row: 1 / span 99; margin-top: 2px; width: 20px; height: 20px; color: var(--accent); }
.callout.hasico > p { grid-column: 2; }
.callout.warn.hasico > .ico { color: var(--warn-ink); }
.callout.danger.hasico > .ico { color: var(--danger); }
.callout p { margin: 0 0 6px 0; }
.callout p:last-child { margin-bottom: 0; }
.callout strong { font-weight: 700; }

/* ════════════════ Icon ════════════════ */

/* Kho <symbol> — ẩn nhưng KHÔNG display:none (một số trình duyệt bỏ tham chiếu <use>
   tới symbol nằm trong cây bị display:none). */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.ico {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  vertical-align: -4px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Nút chỉ-icon trong ô Thao tác: vùng bấm 32px, nhãn nằm ở title + aria-label. */
.ib {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--dim);
  font-weight: 550;
  font-size: 13.5px;
  text-decoration: none;
  cursor: pointer;
}
.ib .ico { width: 18px; height: 18px; }
.ib:hover { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); text-decoration: none; }
.ib.danger { color: var(--danger); }
.ib.danger:hover { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }
.ib.text { width: auto; padding: 0 10px 0 8px; }
.ib:disabled { opacity: .45; cursor: not-allowed; }

.badge {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 650;
  line-height: 1.5;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  margin-left: 8px;
  vertical-align: 1px;
  white-space: nowrap;
}
.badge.ok { background: var(--ok-soft); color: var(--ok); }

/* Ba thẻ số liệu ở trang Tài khoản: con số to, nhãn nhỏ, bấm được. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin: 0 0 16px 0;
}
.stat {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: inherit;
}
.stat:hover { text-decoration: none; border-color: var(--accent-line); background: var(--accent-soft); }
.stat > .ico { width: 34px; height: 34px; padding: 7px; border-radius: 9px; background: var(--surface); color: var(--accent); }
.stat .stattext { display: flex; flex-direction: column; line-height: 1.15; }
.stat b { font-size: 21px; font-weight: 650; font-variant-numeric: tabular-nums; }
.stat .stattext > span { color: var(--dim); font-size: 13px; }

/* ════════════════ Khác ════════════════ */

.hidden { display: none !important; }

.bar {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  height: 11px;
  overflow: hidden;
  max-width: 340px;
  margin: 8px 0;
  padding: 0;
}
.bar > i { display: block; height: 100%; background: var(--accent); }

code {
  font-family: var(--mono);
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: .92em;
}

ul.plain, ol.plain { padding-left: 20px; margin: 8px 0; }
ul.plain li, ol.plain li { margin: 7px 0; }
ul.plain li::marker, ol.plain li::marker { color: var(--dim); }

.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 18px; margin-bottom: 18px; }
.grid2 .panel { margin-bottom: 0; }

/* Hàng nút ngang: chia đều bề ngang, nhưng KHÔNG bao giờ hẹp hơn 168px — dưới ngưỡng đó
   thì xuống dòng, để nhãn tiếng Việt không bị bẻ giữa từ trên màn hình 360px. */
.rowbtns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.rowbtns button, .rowbtns .btnlink { flex: 0 1 auto; min-width: 168px; padding: 9px 16px; }

/* Một liên kết trông và đo như nút — dùng cho scheme snp2cloud:// ở trang cấp quyền,
   nơi đích đến là một ứng dụng chứ không phải một đường của máy chủ. */
.btnlink {
  display: inline-block;
  text-align: center;
  font-weight: 550;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--accent-ink);
  border-radius: var(--r-sm);
  padding: 9px 16px;
}
.btnlink:hover { filter: brightness(1.12); text-decoration: none; }

footer.foot {
  max-width: 1180px;
  margin: 0 auto;
  color: var(--dim);
  padding: 6px 18px 34px 18px;
  font-size: 13px;
}

/* Cảnh báo "danh sách đã bị cắt bớt" — phải nổi hơn một dòng ghi chú thường, vì im lặng
   ở đây khiến người dùng tưởng ghi chú đã mất rồi đi tạo lại cái đang có. */
.trunc {
  color: var(--danger);
  font-weight: 600;
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  border-radius: var(--r-sm);
  padding: 9px 12px;
  max-width: none;
}

/* Bề rộng thanh dung lượng: CSP style-src 'self' cấm thuộc tính style=, nên bề rộng phải
   là một lớp có sẵn. Bước 5% đủ mịn cho một thanh dài 340px. */
.bar > i.w0 { width: 0%; }
.bar > i.w5 { width: 5%; }
.bar > i.w10 { width: 10%; }
.bar > i.w15 { width: 15%; }
.bar > i.w20 { width: 20%; }
.bar > i.w25 { width: 25%; }
.bar > i.w30 { width: 30%; }
.bar > i.w35 { width: 35%; }
.bar > i.w40 { width: 40%; }
.bar > i.w45 { width: 45%; }
.bar > i.w50 { width: 50%; }
.bar > i.w55 { width: 55%; }
.bar > i.w60 { width: 60%; }
.bar > i.w65 { width: 65%; }
.bar > i.w70 { width: 70%; }
.bar > i.w75 { width: 75%; }
.bar > i.w80 { width: 80%; }
.bar > i.w85 { width: 85%; }
.bar > i.w90 { width: 90%; }
.bar > i.w95 { width: 95%; }
.bar > i.w100 { width: 100%; }

/* ════════════════ Màn hình hẹp ════════════════
   Sàn thiết kế là 360px: người dùng thật mở trang này trên điện thoại. */

@media (max-width: 900px) {
  aside.tree { flex: 1 1 100%; max-height: 34vh; }
  section.list { flex: 1 1 100%; }
}

@media (max-width: 640px) {
  .topin { padding: 9px 13px; gap: 8px 12px; }
  .brandsub { display: none; }
  nav.nav { order: 3; flex: 1 1 100%; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 2px; }
  .who { margin-left: auto; }
  .who span { max-width: 128px; }
  main { padding: 16px 13px 44px 13px; }
  .sysbar .in { padding-left: 13px; padding-right: 13px; }
  .notice .in { padding-left: 32px; padding-right: 13px; }
  .notice .in::before { left: 13px; }
  h1 { font-size: 21px; }
  .panel { padding: 15px; border-radius: var(--r-md); }
  .auth { margin-top: 0; }
  .auth .panel { padding: 18px; }
  .kv { grid-template-columns: 1fr; gap: 0; }
  .kv dd { margin-bottom: 11px; }
  input[type=text], input[type=password], input[type=email], select { min-width: 0; width: 100%; }
  .toolbar button { flex: 1 1 auto; }
  .toolbar .search { flex: 1 1 100%; }
  .ib { width: 38px; height: 38px; }
  /* KHÔNG bẻ dòng hàng nút ở đây: cột Thao tác bị ép về 1% bề rộng nên bẻ dòng là xếp năm
     nút thành một cột dọc và mỗi hàng cao gấp bốn (đã thấy trên ảnh 390px). Để nguyên một
     hàng và cho .tablewrap cuộn ngang - đúng cách bảng này vốn được thiết kế. */
  td.acts { width: auto; }
  td.acts .actrow { flex-wrap: nowrap; }
  /* Trên điện thoại, hai nút cạnh nhau chỉ còn ~170px mỗi cái và nhãn tiếng Việt bị bẻ
     giữa từ. Xếp dọc, mỗi nút một dòng, vùng bấm rộng hết bề ngang. */
  .rowbtns button, .rowbtns .btnlink { flex: 1 1 100%; }
  .modal { padding: 10px; align-items: flex-start; padding-top: 6vh; }
}
