/* Slate Frame — giao diện tối lấy cảm hứng từ Frame.io */
:root {
  /* Đường cong chuyển động dùng chung (Emil Kowalski): ease-out mạnh cho vào/ra, drawer kiểu iOS cho sheet */
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --ease-drawer: cubic-bezier(.32, .72, 0, 1);
  --bg: #0d0e12;
  --bg-1: #14161c;
  --bg-2: #1b1e26;
  --bg-3: #242833;
  --line: #2b2f3b;
  --line-soft: #23262f;
  --txt: #e8eaf0;
  --txt-2: #9aa1b1;
  --txt-3: #6a7183;
  --accent: #5b53ff;
  --accent-hi: #6f68ff;
  --ok: #2fbf71;
  --warn: #f5a623;
  --danger: #ef4b5a;
  --radius: 10px;
  --header-h: 56px;
  --shadow: 0 12px 40px rgba(0, 0, 0, .55);
  /* Vạch home của iPhone — mọi thanh dính đáy phải kê lên trên nó */
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* Tai thỏ và mép cong: chỉ lớp phủ tràn hết màn hình (chế độ vẽ) mới cần tới */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  /* Sàn vùng chạm: 44px theo Apple HIG */
  --tap: 44px;
  /* Bàn phím che mất bao nhiêu phía dưới layout viewport — JS đo bằng visualViewport
     rồi gán vào đây (xem createDrawPanel trong thread.js). Safari iOS không tự co
     100dvh theo bàn phím như co theo thanh địa chỉ, nên .panel dính đáy màn hình
     (position:fixed) không tự trồi lên theo bàn phím — phải tự bù khoảng hở này. */
  --kb-inset: 0px;
}

* { box-sizing: border-box; }

/* Thuộc tính hidden phải thắng mọi display của class (vd .gate dùng display:grid),
   nếu không phần tử đã ẩn vẫn hiện đè lên giao diện. */
[hidden] { display: none !important; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--txt);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
::selection { background: var(--accent); color: #fff; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; border: 2px solid var(--bg); }
::-webkit-scrollbar-track { background: transparent; }

/* ---------- primitives ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 14px;
  background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 8px; cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s, opacity .12s;
}
@media (hover: hover) and (pointer: fine) { .btn:hover { background: var(--bg-3); } }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
@media (hover: hover) and (pointer: fine) { .btn.primary:hover { background: var(--accent-hi); } }
.btn.ghost { background: transparent; border-color: transparent; color: var(--txt-2); }
@media (hover: hover) and (pointer: fine) { .btn.ghost:hover { background: var(--bg-2); color: var(--txt); } }
.btn.danger { border-color: #55232a; color: var(--danger); background: transparent; }
@media (hover: hover) and (pointer: fine) { .btn.danger:hover { background: rgba(232, 149, 154, .1); } }
.btn.copy-done {
  border-color: rgba(47, 191, 113, .38); color: var(--ok);
  background: rgba(47, 191, 113, .12);
}
@media (hover: hover) and (pointer: fine) { .btn.copy-done:hover { border-color: rgba(47, 191, 113, .55); background: rgba(47, 191, 113, .17); } }
.btn.sm { height: 28px; padding: 0 10px; font-size: 13px; }
.btn.icon { width: 34px; padding: 0; justify-content: center; }
#btnMore { font-size: 18px; font-weight: 400; line-height: 1; }

.input, textarea.input, select.input {
  width: 100%; height: 36px; padding: 0 12px;
  background: var(--bg-1); border: 1px solid var(--line);
  border-radius: 8px; outline: none;
}
textarea.input { height: auto; padding: 9px 12px; resize: vertical; min-height: 76px; line-height: 1.5; }
.input:focus { border-color: var(--accent); }
.input::placeholder { color: var(--txt-3); }

label.field { display: block; margin-bottom: 14px; }
label.field > span { display: block; margin-bottom: 6px; color: var(--txt-2); font-size: 12.5px; }

.row { display: flex; align-items: center; gap: 10px; }
.spacer { flex: 1; }
.muted { color: var(--txt-2); }
.dim { color: var(--txt-3); }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 8px; border-radius: 6px;
  background: var(--bg-3); font-size: 11.5px; color: var(--txt-2);
}
.chip.ok { background: rgba(47, 191, 113, .15); color: var(--ok); }
.chip.warn { background: rgba(245, 166, 35, .15); color: var(--warn); }
.chip.acc { background: rgba(145, 132, 217, .18); color: var(--ink); }

/* ---------- topbar ---------- */
.topbar {
  /* .topbar tự tạo stacking context riêng; giữ z-index đủ cao để popover thông báo và
     hàng đợi chuyển mã luôn nổi trên nội dung đang cuộn phía dưới. */
  position: sticky; top: 0; z-index: 60;
  isolation: isolate;
  height: var(--header-h); display: flex; align-items: center; gap: 14px;
  padding: 0 18px; border-bottom: 1px solid var(--line-soft);
}
/* Nền mờ tách thành lớp riêng thay vì đặt background/backdrop-filter thẳng lên .topbar:
   backdrop-filter biến chính phần tử mang nó thành containing block cho MỌI hậu duệ
   position:fixed bên trong nó — sheet dán đáy (#notifDrop, #jobsPop) sẽ bị kẹt ngay dưới
   thanh trên thay vì thoát ra bám đáy viewport. ::before không nằm trong chuỗi tổ tiên
   của các sheet đó (nó không phải phần tử cha thật) nên tránh được vấn đề này. */
.topbar::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: rgba(22, 24, 38, .88);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
}
/* Lớp kính ở z-index:0 chỉ lọc nội dung phía sau topbar. Toàn bộ chữ, icon và
   popover được vẽ ở lớp riêng phía trên nên Safari iOS không rasterize chúng
   chung với backdrop-filter. Không dùng transform để các sheet fixed vẫn bám viewport. */
.topbar > * { position: relative; z-index: 1; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 650; letter-spacing: .2px; }
.brand .dot {
  width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;
  background: linear-gradient(140deg, #9aa3d8, var(--accent)); font-size: 11px; font-weight: 800; color: #fff;
}

/* Logo Slate Frame: icon 3 thanh chéo + wordmark 2 màu — nền app tối nên chữ "Slate" để sáng màu */
.logo-icon { border-radius: 7px; flex: none; display: block; }
.wordmark {
  font-family: 'Poppins', -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  font-weight: 700; letter-spacing: -.01em; font-size: 15px;
}
.wordmark .w-slate { color: var(--txt); }
.wordmark .w-frame { color: var(--accent); }
.crumb { color: var(--txt-2); }
.crumb b { color: var(--txt); font-weight: 600; }
.crumb .cr-ws { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; cursor: pointer; vertical-align: middle; }
.crumb .cr-ws-icon { flex: none; color: var(--txt-3); }
.crumb .cr-ws-name { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
@media (hover: hover) and (pointer: fine) { .crumb .cr-ws:hover { color: var(--txt); } }
@media (hover: hover) and (pointer: fine) { .crumb .cr-ws:hover .cr-ws-icon { color: var(--txt-2); } }
.crumb .sep { margin: 0 8px; color: var(--txt-3); }

/* ---------- layout ---------- */
.wrap { max-width: 1400px; margin: 0 auto; padding: 22px 18px 80px; }
.page-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; }
.page-head h1 { margin: 0; font-size: 21px; font-weight: 650; }
/* Số đếm cạnh tiêu đề phải căn theo ĐƯỜNG CHỮ, không phải giữa hộp: align-items:center của
   .page-head căn giữa hai hộp cao khác nhau (h1 line-height 31.5px, số đếm 21px), làm baseline
   chữ nhỏ nhô cao hơn baseline h1 ~2px — nhìn như bị lệch lên trên. Chỉ đổi 2 phần tử chữ này,
   các nút trong .page-head vẫn căn giữa như cũ. */
.page-head h1, .page-head #pjCount, .page-head #trCount { align-self: baseline; }
.workspace-collab { flex: none; }
/* Bọc h1+chip số lượng để mobile xếp cột (tiêu đề + phụ đề sát nhau) mà desktop giữ
   nguyên hàng ngang cũ — display:contents khiến 2 con nằm thẳng trong flex .page-head. */
.ph-title { display: contents; }

.toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 0; border-bottom: 1px solid var(--line-soft); margin-bottom: 18px;
}

/* ---------- project cards ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 18px; }
.card {
  background: var(--bg-1); border: 1px solid var(--line-soft);
  border-radius: 12px; overflow: hidden; cursor: pointer;
  transition: transform .14s, border-color .14s;
}
@media (hover: hover) and (pointer: fine) { .card:hover { transform: translateY(-2px); border-color: var(--line); } }
.card .thumb {
  aspect-ratio: 16/10; background: var(--bg-2) center/cover no-repeat;
  display: grid; place-items: center; color: var(--txt-3);
}
.card .meta { padding: 11px 13px 13px; }
.card .meta h3 { margin: 0 0 5px; font-size: 14.5px; font-weight: 600; }
.card .meta .sub { font-size: 12px; color: var(--txt-3); display: flex; gap: 6px; flex-wrap: wrap; }
.project-card-stats { margin-top: 7px; }
.project-stat {
  display: inline-flex; align-items: center; gap: 4px; min-height: 24px; padding: 3px 7px;
  border: 1px solid var(--line-soft); border-radius: 7px; background: rgba(255, 255, 255, .025);
  color: var(--txt-3); font-size: 11px; line-height: 1; white-space: nowrap;
}
.project-stat svg {
  width: 12px; height: 12px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.project-stat b { color: var(--txt-2); font-weight: 600; }
.project-stat-link { border-color: rgba(145, 132, 217, .25); background: rgba(145, 132, 217, .09); color: var(--ink); }
.project-stat-link b { color: var(--ink); }
.project-stat-comment { border-color: rgba(245, 166, 35, .24); background: rgba(245, 166, 35, .085); color: #e9b767; }
.project-stat-comment b { color: #ffd187; }
.project-created {
  display: flex; align-items: center; min-width: 0; gap: 3px; margin-top: 9px;
  color: var(--txt-3); font-size: 10.75px; line-height: 1.35;
}
.project-created time { color: var(--txt-2); white-space: nowrap; }
.project-created span { min-width: 0; overflow: hidden; color: var(--txt-2); text-overflow: ellipsis; white-space: nowrap; }

/* ---------- tab "Được chia sẻ" (nội dung từ workspace của người khác) ---------- */
.shared-section + .shared-section { margin-top: 26px; }
.shared-title {
  margin: 0 0 12px; color: var(--txt-3); font-size: 10.5px; font-weight: 600;
  letter-spacing: .045em; text-transform: uppercase;
}
.shared-badges { margin-top: 7px; }
.shared-links { display: grid; gap: 8px; }
.shared-link {
  display: flex; align-items: center; gap: 12px; min-width: 0; padding: 10px 12px;
  border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg-1);
  cursor: pointer; transition: border-color .14s;
}
@media (hover: hover) and (pointer: fine) { .shared-link:hover { border-color: var(--line); } }
.shared-link-thumb {
  width: 44px; height: 44px; flex: none; display: grid; place-items: center;
  border-radius: 8px; overflow: hidden; background: var(--bg-2); color: var(--txt-3);
}
.shared-link-thumb img { width: 100%; height: 100%; object-fit: cover; }
.shared-link-main { display: grid; gap: 2px; min-width: 0; flex: 1; }
.shared-link-name {
  font-size: 13.5px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.shared-link-meta { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shared-link-time { flex: none; font-size: 11.5px; }
@media (max-width: 640px) { .shared-link-time { display: none; } }

/* ---------- thùng rác ---------- */
.card.trash { cursor: default; }
@media (hover: hover) and (pointer: fine) { .card.trash:hover { transform: none; border-color: var(--line-soft); } }
.card.trash .thumb { filter: grayscale(1) brightness(.6); }
.card-actions { display: flex; gap: 8px; padding: 0 13px 13px; }
.card-actions .btn { flex: 1; }

/* ---------- vòng tròn chuyển mã (desktop) ---------- */
.jobs-wrap { position: relative; }
.jobs-spin {
  width: 18px; height: 18px; border-radius: 6px; display: block;
  border: 2px solid rgba(245, 166, 35, .25); border-top-color: var(--warn);
  animation: wahspin .9s linear infinite;
}
.jobs-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 250; width: 320px; max-height: 360px;
  overflow-y: auto; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow); padding: 12px; animation: popin .15s var(--ease-out); transform-origin: top right;
}
.jobs-pop-head { font-size: 12.5px; color: var(--warn); margin-bottom: 10px; }
.jobs-pop .jp-row { margin-bottom: 10px; }
.jobs-pop .jp-row:last-child { margin-bottom: 0; }
.jobs-pop .jp-top { display: flex; justify-content: space-between; font-size: 12px; color: var(--txt-2); margin-bottom: 4px; }
.jobs-pop .jp-bar { height: 5px; border-radius: 6px; background: rgba(255, 255, 255, .1); overflow: hidden; }
.jobs-pop .jp-bar > i { display: block; height: 100%; width: 0; background: var(--accent-hi); transition: width .6s linear; }

/* ---------- thông báo ---------- */
.notif-wrap { position: relative; }
/* Huy hiệu neo vào chính nút chuông chứ không vào .notif-wrap: trên điện thoại
   .notif-wrap phải chuyển sang position:static để .notif-drop dán được đáy màn hình,
   lúc đó huy hiệu mất mốc và văng lên góc phải thanh trên. */
#btnNotif, #guestNotifBtn { position: relative; }
.notif-badge {
  position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: #ff4d5e; color: #fff; font-size: 10px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}
/* Chấm nhỏ báo "đang dùng thử Pro" trên chuông — thay cho banner to chắn ngang màn hình
   trước đây (phản hồi: banner cũ quá thô). Không tranh chỗ với .notif-badge (số chưa đọc):
   badge ưu tiên góc trên-phải, chấm này nép sang góc dưới-phải. */
.notif-dot {
  position: absolute; bottom: max(-2px, calc(50% - 12px)); right: max(-2px, calc(50% - 12px)); width: 9px; height: 9px;
  border-radius: 3px; background: var(--warn); border: 2px solid var(--bg-1);
}
.notif-drop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 250; width: 340px; max-height: 420px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; overflow: hidden; min-width: 0;
}
.notif-head {
  display: flex; align-items: center; justify-content: space-between;
  flex: none;
  padding: 12px 14px; border-bottom: 1px solid var(--line-soft); font-size: 13px; font-weight: 600;
}
.notif-head .link { font-weight: 500; font-size: 12px; color: var(--accent); cursor: pointer; }
.notif-filters {
  display: flex; gap: 5px; padding: 8px 10px; overflow-x: auto;
  flex: none;
  border-bottom: 1px solid var(--line-soft); scrollbar-width: none;
}
.notif-filters::-webkit-scrollbar { display: none; }
.notif-filters button {
  flex: none; border: 0; border-radius: 6px; padding: 5px 9px;
  background: transparent; color: var(--txt-3); font: inherit; font-size: 11.5px; cursor: pointer;
}
.notif-filters button.on { background: var(--bg-3); color: var(--txt-1); }
.notif-list {
  flex: 1 1 auto; min-width: 0; min-height: 0; overflow-x: hidden; overflow-y: auto;
  overscroll-behavior-y: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y;
}
.notif-item {
  display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 12px; width: 100%; /* 12px: chừa chỗ cho huy hiệu .notif-ev-badge thò ra góc */
  min-width: 0; box-sizing: border-box; overflow: hidden;
  text-align: left; padding: 10px 14px; border: none; background: none;
  cursor: pointer; border-bottom: 1px solid var(--line-soft); color: inherit; font: inherit;
}
@media (hover: hover) and (pointer: fine) { .notif-item:hover { background: var(--bg-3); } }
.notif-item.unread { background: rgba(145, 132, 217, .07); }
.notif-item .ntitle { min-width: 0; font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; overflow-wrap: anywhere; }
.notif-item .ntitle .dot { width: 6px; height: 6px; border-radius: 2px; background: var(--accent); flex: none; }
.notif-item .nbody { display: block; min-width: 0; font-size: 12.5px; color: var(--txt-2); margin-top: 3px; overflow-wrap: anywhere; }
.notif-item .ntime { display: block; min-width: 0; font-size: 11px; color: var(--txt-3); margin-top: 4px; overflow-wrap: anywhere; }
/* Ô avatar thông báo (kiểu "C2", 2026-10-10 — xem notifAvatarHtml trong admin.js): người làm ở ô lớn
   (ảnh, hoặc chữ cái đầu trên nền xám) + huy hiệu màu góc dưới phải = loại việc; thông báo không gắn
   với 1 người thì .is-event = 1 ô icon tô nhạt theo tông. Ảnh bị cắt bằng bo góc của chính <img>
   (không overflow:hidden ở ô) để huy hiệu được thò ra ngoài góc. */
.notif-avatar {
  position: relative; flex: none; width: 34px; height: 34px; border-radius: 7px; display: grid; place-items: center;
  background: var(--bg-3); color: var(--txt-2); font-size: 13px; font-weight: 600;
}
.notif-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.notif-avatar.has-img { background: none; }
.notif-avatar { --tone: var(--accent); }
.notif-avatar .tone-accent, .notif-avatar.tone-accent { --tone: var(--accent); }
.notif-avatar .tone-ok, .notif-avatar.tone-ok { --tone: var(--ok); }
.notif-avatar .tone-warn, .notif-avatar.tone-warn { --tone: var(--warn); }
.notif-avatar .tone-danger, .notif-avatar.tone-danger { --tone: var(--danger); }
.notif-avatar.is-event { background: color-mix(in srgb, var(--tone) 16%, transparent); color: var(--tone); }
.notif-ev-badge {
  position: absolute; right: -5px; bottom: -5px; width: 18px; height: 18px; border-radius: 6px;
  display: grid; place-items: center; background: var(--tone); color: var(--bg-1);
  box-shadow: 0 0 0 2px var(--bg-1);
}
/* dòng ghim báo dùng thử Pro, đầu danh sách thông báo — nhạt hơn .notif-item.unread thường
   để không lẫn với thông báo thật, không có chấm "chưa đọc" vì đây không phải sự kiện rời rạc */
.notif-item.notif-trial { background: rgba(255, 199, 102, .06); }
@media (hover: hover) and (pointer: fine) { .notif-item.notif-trial:hover { background: rgba(255, 199, 102, .12); } }
.notif-main { display: block; min-width: 0; max-width: 100%; overflow: hidden; }
.notif-actions { display: flex; gap: 6px; margin-top: 9px; }
.notif-actions .btn { min-height: 30px; padding: 4px 10px; }
.notif-empty { padding: 24px 14px; text-align: center; color: var(--txt-3); font-size: 13px; }
.notif-settings { flex: none; border-top: 1px solid var(--line-soft); }
.notif-settings summary {
  padding: 9px 14px; color: var(--txt-2); font-size: 12px; cursor: pointer; user-select: none;
}
.notif-settings-grid { display: grid; gap: 8px; padding: 2px 14px 12px; }
.notif-settings-grid label { display: flex; align-items: center; gap: 8px; color: var(--txt-2); font-size: 12.5px; }
.notif-settings-grid input { accent-color: var(--accent); }
.notif-push {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 11px 14px;
  border: none; border-top: 1px solid var(--line-soft); background: none; color: var(--txt-2);
  font: inherit; font-size: 12.5px; cursor: pointer; text-align: left; flex: none;
}
@media (hover: hover) and (pointer: fine) { .notif-push:hover { background: var(--bg-3); color: var(--txt); } }
.notif-push.on { color: var(--accent-hi); }
.notif-push svg { flex: none; }
.modal.account-settings-modal { width: min(760px, 100%); }
.modal.account-settings-modal .m-body {
  height: min(570px, calc(100dvh - 190px)); max-height: none; padding: 0; overflow: hidden;
}
.account-settings-shell {
  display: grid; grid-template-columns: 174px minmax(0, 1fr); height: 100%; min-height: 0;
}
.account-settings-nav {
  display: flex; flex-direction: column; gap: 5px; padding: 16px 12px;
  border-right: 1px solid var(--line-soft); background: rgba(255, 255, 255, .012);
}
.account-settings-nav button {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; padding: 9px 11px;
  border: 0; border-radius: 9px; background: transparent; color: var(--txt-2);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer; transition: background .14s, color .14s;
}
@media (hover: hover) and (pointer: fine) { .account-settings-nav button:hover { background: var(--bg-2); color: var(--txt); } }
.account-settings-nav button.on { background: rgba(145, 132, 217, .15); color: #b4b0ff; }
.account-settings-nav svg {
  width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.account-settings-content { min-width: 0; min-height: 0; padding: 22px; overflow-y: auto; }
.account-panel { display: none; }
.account-panel.on { display: block; animation: fadein .14s ease; }
.account-panel-head { margin-bottom: 16px; }
.account-panel-head h3 { margin: 0 0 4px; color: var(--txt); font-size: 17px; font-weight: 650; }
.account-panel-head p { margin: 0; color: var(--txt-3); font-size: 12.5px; line-height: 1.45; }
.settings-card {
  margin-bottom: 12px; padding: 16px; border: 1px solid var(--line-soft);
  border-radius: 12px; background: var(--bg-1);
}
.account-profile-card { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; align-items: center; gap: 14px; }
#acctDlgAvatar { width: 64px; height: 64px; font-size: 21px; }
#acctDlgAvatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.account-profile-copy { display: grid; gap: 3px; min-width: 0; }
.account-profile-copy strong, .account-profile-copy span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-profile-copy strong { color: var(--txt); font-size: 15px; font-weight: 600; }
.account-profile-copy span { color: var(--txt-3); font-size: 12px; }
.account-form-card { display: grid; gap: 14px; }
.account-form-card .field { margin: 0; }
.account-name-row { display: flex; gap: 8px; }
.account-name-row .input { flex: 1; min-width: 0; }
.account-plan-card {
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(120deg, rgba(145, 132, 217, .13), rgba(145, 132, 217, .035));
}
.account-plan-icon {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none; border-radius: 10px;
  background: rgba(145, 132, 217, .18); color: var(--ink); font-size: 13px;
}
.account-plan-card small { color: var(--ink); font-size: 10.5px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; }
.account-plan-card p { margin: 3px 0 0; color: var(--txt-2); font-size: 12.5px; line-height: 1.45; }
.account-security-card { display: grid; gap: 10px; }
.account-security-card .btn { justify-self: start; margin-top: 2px; }

.account-notif-grid { display: grid; padding: 0; overflow: hidden; }
.account-notif-grid label {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px;
  padding: 0 14px; border-bottom: 1px solid var(--line-soft); color: var(--txt-2);
  font-size: 12.5px; cursor: pointer;
}
.account-notif-grid label:last-child { border-bottom: 0; }
.account-notif-grid input {
  order: 2; appearance: none; -webkit-appearance: none; position: relative; width: 36px; height: 21px;
  flex: none; margin: 0; border: 1px solid var(--line); border-radius: 6px; background: var(--bg-3);
  cursor: pointer; transition: background .16s, border-color .16s;
}
.account-notif-grid input::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
  border-radius: 4px; background: var(--txt-2); transition: transform .16s, background .16s;
}
.account-notif-grid input:checked { border-color: var(--accent); background: var(--accent); }
.account-notif-grid input:checked::after { transform: translateX(15px); background: #fff; }
.account-notif-grid input:disabled { opacity: .55; cursor: wait; }
.account-notif-grid .account-notif-wide { align-items: center; min-height: 62px; }
.account-notif-wide span { flex: 1; min-width: 0; }
.account-notif-wide b, .account-notif-wide small { display: block; }
.account-notif-wide b { color: var(--txt); font-size: 12.5px; }
.account-notif-wide small { margin-top: 2px; color: var(--txt-3); font-size: 11.5px; }
.notif-push.account-notif-push {
  min-height: 48px; margin-top: 10px; border: 1px solid var(--line-soft); border-radius: 10px;
  background: var(--bg-1);
}
@media (hover: hover) and (pointer: fine) { .notif-push.account-notif-push:hover { background: var(--bg-2); } }

/* Chuông + avatar của khách dùng lại ngôn ngữ thị giác của studio nhưng gọn hơn để
   không tranh chỗ với tên project trên topbar share. */
#guestNotifBtn, #guestAccountBtn { width: 36px; height: 36px; padding: 0; }
#guestAvatar { width: 28px; height: 28px; font-size: 11px; }
#guestAvatar img, #guestSettingsAvatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
#guestNotifDrop { right: 0; }
.guest-account-menu { width: 256px; }
.guest-account-menu .ctx-head { padding: 10px 12px 7px; font-size: 12.5px; }
.guest-account-menu .ctx-item svg { flex: none; }
.guest-account-menu .ctx-item .ci-lb { flex: 1; min-width: 0; }
.guest-account-menu .ctx-item .ci-hint { flex: none; color: var(--txt-3); font-size: 12px; }
.guest-account-note { color: var(--txt-3); font-size: 12px; margin-top: 4px; }
.mention { color: var(--accent); font-weight: 600; }

/* ---------- thanh tìm kiếm + chuyển chế độ xem ---------- */
/* flex-wrap: để .search-collapse (flex-basis 100%) xuống hàng riêng khi mở, không bị
   bóp chung hàng với các nút lọc/sắp xếp/chuyển chế độ xem. */
.fbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 14px 0; }
.fbar .input { flex: 1; max-width: 360px; }
/* Wrapper thu gọn ô tìm kiếm — bấm nút kính lúp mới hiện, dựng thành dải riêng dưới
   thanh lọc thay vì nằm ngay trong hàng (giống hệt cách mọi menu ⋯ khác đã làm),
   trên mọi cỡ màn hình. */
.search-collapse {
  flex: 1 1 100%; overflow: hidden; max-height: 0; opacity: 0;
  transition: max-height .22s ease, opacity .18s ease; order: 5;
}
.search-collapse.open { max-height: 58px; opacity: 1; margin-bottom: 14px; }
.search-collapse .input { height: 44px; font-size: 16px; max-width: 380px; }
/* Lọc/sắp xếp: hai select này chỉ còn là nguồn dữ liệu, luôn ẩn — thay bằng nút mở
   sheet/dropdown (#btnFilterSheet/#btnSortSheet), dựng thành danh sách chọn một
   giống mọi menu ⋯ khác, không phải dropdown gốc trình duyệt, trên mọi cỡ màn hình. */
#rFilter, #rSort { display: none; }
/* Trang quản trị: cùng cách trên — #pjSort/#dFilter/#dSort vẫn là nguồn sự thật,
   luôn ẩn, thay bằng #btnPjSort/#btnDFilter/#btnDSort mở sheet/dropdown. */
#pjSort, #dFilter, #dSort { display: none; }
/* Nhãn chữ trên nút Lọc/Sắp xếp/Hiển thị của lưới tệp — chỉ hiện ở máy tính (xem khối ≥1024px) */
.fb-label, .fb-caret, .fb-count { display: none; }
.viewtoggle { display: flex; border: 1px solid var(--line-soft); border-radius: 8px; overflow: hidden; flex: none; }
.appearance-wrap { position: relative; flex: none; margin-left: auto; }
.appearance-btn { width: 34px; padding: 0; justify-content: center; }
.appearance-pop {
  position: absolute; z-index: 80; top: calc(100% + 8px); right: 0; width: 310px;
  padding: 10px; border: 1px solid var(--line); border-radius: 13px;
  background: #202330; box-shadow: 0 14px 36px rgba(0,0,0,.42); color: var(--txt);
}
.appearance-pop[hidden] { display: none; }
.appearance-title { padding: 2px 5px 9px; font-size: 13px; font-weight: 650; }
.appearance-row { min-height: 42px; display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 4px 5px; font-size: 13px; }
.appearance-row > span { color: var(--txt-2); white-space: nowrap; }
.appearance-seg { min-width: 148px; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; padding: 3px; border-radius: 9px; background: var(--bg-2); }
.appearance-seg button { height: 30px; padding: 0 10px; border: 0; border-radius: 7px; background: transparent; color: var(--txt-2); cursor: pointer; font: inherit; }
.appearance-seg button.on { background: var(--accent); color: #fff; }
.appearance-seg button > svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: middle; }
.appearance-select { width: 124px; height: 32px; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 10px 0 12px; border: 0; border-radius: 8px; background: var(--bg-3); color: var(--txt); cursor: pointer; font: inherit; font-size: 13px; text-align: left; }
@media (hover: hover) and (pointer: fine) { .appearance-select:hover { background: #3b4051; } }
.appearance-select > svg { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.appearance-select[aria-expanded="true"] > svg { transform: rotate(180deg); }
.appearance-options {
  width: 148px; margin: -3px 5px 6px auto; padding: 4px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--bg-2);
}
.appearance-options[hidden] { display: none; }
.appearance-options button {
  position: relative; width: 100%; height: 34px; padding: 0 10px 0 32px;
  border: 0; border-radius: 7px; background: transparent; color: var(--txt);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .appearance-options button:hover { background: var(--bg-3); } }
.appearance-options button.on { color: #c2bdff; }
.appearance-options button.on::before { content: '✓'; position: absolute; left: 11px; top: 7px; }
.ratio { display: inline-block; border: 1.7px solid currentColor; border-radius: 2px; vertical-align: middle; }
.ratio.landscape { width: 17px; height: 10px; }.ratio.square { width: 14px; height: 14px; }.ratio.portrait { width: 10px; height: 17px; }
.appearance-switch { appearance: none; width: 38px; height: 22px; margin: 0; padding: 2px; border: 0; border-radius: 6px; background: #454a5c; cursor: pointer; transition: background .15s; }
.appearance-switch::after { content: ''; display: block; width: 18px; height: 18px; border-radius: 4px; background: #fff; transition: transform .15s; }
.appearance-switch:checked { background: var(--accent); }.appearance-switch:checked::after { transform: translateX(16px); }
.appearance-pop.list-mode .grid-setting { opacity: .4; pointer-events: none; }
.vt-btn {
  padding: 7px 10px; background: var(--bg-1); border: none; color: var(--txt-3);
  cursor: pointer; display: flex; align-items: center;
}
.vt-btn.on { background: var(--bg-3); color: var(--txt); }
@media (hover: hover) and (pointer: fine) { .vt-btn:hover { color: var(--txt); } }

/* ---------- chế độ xem danh sách ---------- */
/* cột cố định theo thứ tự: chọn · ảnh · Tên · Ngày · Người tải · Comment · Rating · Dung lượng · Ghi chú.
   Tên không còn là 1fr (trước đây nó nuốt hết chỗ trống, đẩy các cột khác ra rìa) — giờ cố định,
   Ghi chú giãn theo chỗ còn lại; hàng có min-width riêng nên thiếu chỗ thì cuộn ngang thay vì bị bóp méo. */
.flist { border: 1px solid var(--line-soft); border-radius: 10px; overflow: hidden; }
.frow-scroll { overflow-x: auto; }
.frow {
  display: grid;
  grid-template-columns: 34px 46px 260px 150px 140px 90px 110px 90px minmax(220px, 1fr);
  min-width: 1230px;
  align-items: center; gap: 10px; padding: 6px 12px; border-bottom: 1px solid var(--line-soft);
  cursor: pointer; user-select: none;
}
.frow:last-child { border-bottom: none; }
@media (hover: hover) and (pointer: fine) { .frow:hover { background: var(--bg-2); } }
.frow.picked { background: rgba(145, 132, 217, .08); }
.frow-head {
  cursor: default; font-size: 11px; color: var(--txt-3); text-transform: uppercase;
  letter-spacing: .02em; background: var(--bg-2);
}
@media (hover: hover) and (pointer: fine) { .frow-head:hover { background: var(--bg-2); } }
.fl-check { display: flex; justify-content: center; }
.fl-check .checkbox {
  position: static; width: 19px; height: 19px; border-radius: 5px; border: 1.5px solid var(--line);
  display: grid; place-items: center; background: transparent; color: transparent; cursor: pointer; font-size: 12px;
}
.frow.picked .fl-check .checkbox { background: var(--accent); border-color: var(--accent); color: #fff; }
.fl-thumb { width: 42px; height: 42px; border-radius: 6px; overflow: hidden; background: var(--bg-2); flex: none; }
.fl-thumb img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .2s; }
.fl-thumb img.on { opacity: 1; }
.fl-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.fl-status, .fl-date, .fl-uploader, .fl-cmt, .fl-size {
  font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--txt-3);
}
.fl-cmt { text-align: center; }
.fl-rate { display: flex; align-items: center; }
.fl-note { min-width: 0; }
.fl-note-input {
  width: 100%; background: transparent; border: 1px solid transparent; border-radius: 6px;
  padding: 5px 7px; font: inherit; font-size: 12.5px; color: var(--txt-2); transition: border-color .12s, background .12s;
}
@media (hover: hover) and (pointer: fine) { .fl-note-input:hover { border-color: var(--line-soft); } }
.fl-note-input:focus { outline: none; border-color: var(--accent); background: var(--bg-2); color: var(--txt); }

/* Trang khách: ít cột hơn admin (không có Người tải / Ghi chú — hai thứ đó chỉ studio dùng) */
.frow.frow-guest { grid-template-columns: 34px 46px 1fr 150px 90px 110px 90px; min-width: 930px; }

/* Danh sách project dạng list — không có ô chọn, cột khác hẳn cột của ảnh trong project */
.frow.frow-project { grid-template-columns: 46px 1fr 110px 90px 90px 90px; min-width: 640px; }

/* ---------- grid ảnh ---------- */
.grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(var(--tile, 220px), 1fr)); }
/* Lưới ảnh chính (không phải lưới thư mục #gridF/#dGridF): cỡ ô rời rạc S/M/L qua
   sheet/dropdown thay cho phóng to/thu nhỏ liên tục — số cột do share.js/admin.js tính
   theo bề ngang màn hình. */
#grid { grid-template-columns: repeat(var(--cols, 6), minmax(0, 1fr)); }
#dGrid { grid-template-columns: repeat(var(--dcols, 6), minmax(0, 1fr)); }
/* Thư mục 1.000+ tệp cuộn giật (2026-09-28): ô nằm ngoài màn hình bỏ qua dựng bố cục/vẽ.
   `auto` nhớ kích thước thật sau lần vẽ đầu nên cuộn ngược lên không bị nhảy; 280px chỉ là ước
   lượng cho ô chưa từng hiện. Trình duyệt chưa hỗ trợ thì bỏ qua dòng này, không hỏng gì. */
#dGrid > .tile { content-visibility: auto; contain-intrinsic-size: auto 280px; }
.tile {
  position: relative; background: var(--bg-1); border: 1px solid var(--line-soft);
  border-radius: 10px; overflow: hidden; cursor: pointer;
  transition: border-color .12s;
  /* không cho bôi đen chữ khi giữ Shift chọn nhiều ảnh */
  user-select: none; -webkit-user-select: none;
}
@media (hover: hover) and (pointer: fine) { .tile:hover { border-color: var(--line); } }
.tile.sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.tile .ph { position: relative; aspect-ratio: 1/1; background: var(--bg-2); display: block; overflow: hidden; }
#viewProject[data-card-aspect="landscape"] .tile:not(.folder) .ph { aspect-ratio: 4/3; }
#viewProject[data-card-aspect="portrait"] .tile:not(.folder) .ph { aspect-ratio: 3/4; }
#viewProject[data-thumb-scale="fit"] .tile:not(.folder) .ph img { object-fit: contain; }
#app[data-card-aspect="landscape"] #grid .tile .ph { aspect-ratio: 4/3; }
#app[data-card-aspect="portrait"] #grid .tile .ph { aspect-ratio: 3/4; }
#app[data-thumb-scale="fit"] #grid .tile .ph img { object-fit: contain; }
/* phủ màu lên ô đang chọn để nhìn lướt cả lưới vẫn thấy ngay */
.tile.picked .ph::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: rgba(145, 132, 217, .32);
  box-shadow: inset 0 0 0 2px var(--accent);
}
.tile .ph img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity .25s; }
.tile .ph img.on { opacity: 1; }
/* tệp không phải ảnh: server trả về tờ giấy màu theo nhóm (fileIconSvg() ở src/images.js),
   hình vuông cùng nền với ô nên lấp đầy ô như ảnh */
.tile .ph.isfile { display: grid; place-items: center; background: #1c2030; }
.tile .ph.isfile img { width: 100%; height: 100%; object-fit: contain; }
/* PDF: trang giấy phải thấy trọn, cắt cúp kiểu ảnh thì chẳng đọc được gì */
.tile .ph.isdoc { background: #fff; display: grid; place-items: center; }
.tile .ph.isdoc img { width: 100%; height: 100%; object-fit: contain; }
#tabPhotos.drag-over, #viewProjects.drag-over { outline: 2px dashed var(--accent); outline-offset: 10px; border-radius: 12px; }
.tile .cap {
  display: flex; align-items: center; gap: 6px; flex-wrap: nowrap;
  padding: 7px 9px; font-size: 12px; color: var(--txt-2);
  border-top: 1px solid var(--line-soft);
}
.tile .cap .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#viewProject.hide-card-info .tile:not(.folder) .cap,
#viewProject.hide-card-info .tile:not(.folder) .tile-rate-row,
#viewProject.hide-card-info .tile:not(.folder) .by { display: none; }
#app.hide-card-info #grid .tile .cap,
#app.hide-card-info #grid .tile > .stars,
#app.hide-card-info #grid .tile > .tile-rate-row,
#app.hide-card-info #grid .tile .by { display: none; }
/* mọi thứ còn lại trong dòng đều không được xuống hàng */
.tile .cap > :not(.nm) { flex: none; white-space: nowrap; }
.tile .cap .cmt-n { display: inline-flex; align-items: center; gap: 3px; }
/* ---------- sao đánh giá ---------- */
.stars { display: flex; gap: 1px; line-height: 1; }
.stars .star { color: var(--line); cursor: pointer; font-size: 13px; transition: color .1s, transform .1s; }
@media (hover: hover) and (pointer: fine) { .stars .star:hover { transform: scale(1.15); } }
.stars .star.on { color: var(--txt); }
/* Đệm bên PHẢI để 0 — sát ngay nút thẻ màu kế bên (khoảng cách đã có `.tile-rate-row`'s gap lo),
   đệm cũ 9px hai bên từng cộng dồn với đệm-trái 9px của .ctag-btn.tile-ctag thành gần 24px "chết"
   giữa 2 khối dù trông như cùng 1 hàng — xem bug thật ở .tile-rate-row bên dưới. */
.tile .stars.tile-stars { padding: 3px 0 6px 9px; }
.tile .stars.tile-stars .star { font-size: 14px; }
/* Hàng chứa sao đánh giá + nút ⋯ (điện thoại) — đặt cạnh nhau, không đè lên nhãn version
   ở góc ảnh nữa (xem .tile-menu trong khối @media (max-width: 640px) bên dưới). */
.tile-rate-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px; }
/* BUG THẬT đã sửa 3 lần (2026-09-23):
   1) TRƯỚC ĐÂY `.stars.tile-stars` có `flex:1; min-width:0` nhưng KHÔNG `overflow:hidden` — ô cỡ
      M/S hẹp thì khung `.stars` bị ép nhỏ hơn nội dung (đúng ý `min-width:0`), nhưng 5 ngôi sao
      bên trong (glyph cố định, không tự co) TRÀN ra khỏi khung, đè lên nút thẻ màu kế bên.
   2) Sửa vội bằng `flex:none` cho cả hai (giữ nguyên kích thước tự nhiên) — hết đè nhau, nhưng ô
      hẹp thật sự (đo thật: hàng chỉ có ~97px, riêng 5 sao đã cần ~92px, thẻ màu cần thêm ~31px)
      thì `justify-content:space-between` đẩy hẳn nút thẻ màu ra NGOÀI mép `.tile-rate-row`, bị
      `.tile`/lưới cắt mất — biến mất hoàn toàn, người dùng report "bị ẩn luôn color picker".
   3) Sửa cho phép `.stars` co + `overflow:hidden` (không đè, không ẩn) — nhưng ở trang QUẢN TRỊ,
      hàng này còn có thêm nút ⋯ `.tile-menu` (điện thoại, xem @media bên dưới) — 3 khối cùng hàng
      trên điện thoại (đo thật: cỡ ô "S" chỉ ~92px cho riêng phần nội dung, cần tới ~116px) khiến
      `.stars` bị co MẠNH tới mức chỉ còn thấy 2-4/5 sao — ĐÚNG số liệu sai lệch, không chỉ chật,
      người dùng report "bị còn 4 sao và 2 sao". `.tile-menu` không có ở trang khách (share.js).
   Sửa đúng bài lần 3: gộp sao+thẻ màu vào `.tile-marks` (khối riêng, xem HTML ở admin.js), để
   `.tile-menu` (điện thoại) tự XUỐNG DÒNG khi không đủ chỗ (`flex-wrap:wrap` + `margin-left:auto`
   căn phải trên dòng riêng, xem @media bên dưới) — quyết định xuống dòng của flexbox dựa theo
   KÍCH THƯỚC TỰ NHIÊN của `.tile-marks` (không phải kích thước sau khi co), nên luôn đủ chỗ cho
   sao+thẻ màu ở kích thước bình thường trên dòng của chúng, `overflow:hidden` chỉ còn là lưới an
   toàn cho màn cực hẹp chứ không phải đường xử lý chính nữa. */
.tile-marks { display: flex; align-items: center; gap: 4px; flex: 1 1 auto; min-width: 0; }
.tile-rate-row .stars.tile-stars { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.tile-rate-row .ctag-btn.tile-ctag { flex: none; }
#albStars.lb-stars, .lb-stars { display: flex; gap: 2px; }
.lb-stars .star { font-size: 16px; }

/* ---------- thẻ màu Capture One (chỉ trang khách link Live, xem gateInfo.is_live) ----------
 * Mỗi chỗ chỉ hiện MỘT nút chấm tròn (màu hiện tại, rỗng nếu chưa gắn thẻ) — bấm mở popover
 * dùng chung .ctag-pop (7 màu) để chọn, thay vì nhồi cả dải 7 chấm vào chỗ chật. */
.ctag-btn {
  border: none; background: none; padding: 3px; margin: 0; cursor: pointer; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.ctag-dot {
  display: block; width: 13px; height: 13px; border-radius: 4px;
  background: var(--ctag-color); box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .5);
  transition: transform .1s;
}
.ctag-dot:not(.on) { background: transparent; box-shadow: inset 0 0 0 1.5px var(--line); }
@media (hover: hover) and (pointer: fine) { .ctag-btn:hover .ctag-dot { transform: scale(1.15); } }

/* Chấm thẻ màu trên ô lưới: nằm CÙNG HÀNG với sao đánh giá (trong .tile-rate-row, đẩy sát
   mép phải nhờ justify-content:space-between của hàng đó) — không đè lên ảnh nữa (trước đây
   đặt tuyệt đối ở góc ảnh, người dùng phản hồi thấy vướng ảnh). */
.tile .ctag-btn.tile-ctag { padding: 3px 9px 3px 3px; }

.fl-rate .ctag-btn.row-ctag { margin-left: 2px; }

/* Popover chọn 1 trong 7 màu — cùng kiểu position:fixed + toạ độ JS tính với .ver-pop/.dl-pop.
   z-index PHẢI cao hơn .lb (100, khung xem toàn màn hình) — bấm nút thẻ màu trong lightbox mở
   popover nhưng bị đè khuất phía sau nền khung xem nếu z-index thấp hơn, không bấm chọn được
   dù popover vẫn có mặt trong DOM (bug thật, người dùng report "không pick chỉnh được ở lightbox"). */
.ctag-pop {
  position: fixed; z-index: 300; display: flex; gap: 8px;
  padding: 8px; border-radius: 12px; background: var(--bg-2); border: 1px solid var(--line-soft);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}
.ctag-sw {
  width: 20px; height: 20px; border-radius: 5px; cursor: pointer; background: var(--ctag-color);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2); transition: transform .1s;
}
@media (hover: hover) and (pointer: fine) { .ctag-sw:hover { transform: scale(1.15); } }
.ctag-sw.on { box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 3.5px var(--ctag-color); }

/* Popover lọc theo sao/thẻ màu — CHỌN NHIỀU (tham khảo bảng lọc Capture One), thay cho dropdown
 * kiểu radio cũ. Cùng kiểu position:fixed + z-index với .ctag-pop, KHÔNG tự đóng khi bấm chip
 * bên trong (khác .sheet-item vốn đóng ngay) vì mỗi chip tự bật/tắt độc lập. */
.mf-pop {
  position: fixed; z-index: 300; display: flex; flex-direction: column; gap: 12px;
  padding: 12px 14px; border-radius: 12px; background: var(--bg-2); border: 1px solid var(--line-soft);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35); min-width: 230px;
}
.mf-sec-title {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--txt-3); margin-bottom: 7px;
}
.mf-row { display: flex; gap: 7px; flex-wrap: wrap; }
.mf-star {
  min-width: 26px; height: 26px; padding: 0 4px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--line-soft); background: var(--bg-3); color: var(--txt-2); font-size: 12.5px;
}
@media (hover: hover) and (pointer: fine) { .mf-star:hover { border-color: var(--line); } }
.mf-star.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.mf-tag {
  width: 22px; height: 22px; border-radius: 6px; cursor: pointer; padding: 0; border: none; /* vuông bo góc như .ctag-dot */
  background: var(--ctag-color); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2); transition: transform .1s;
}
.mf-tag-none { background: transparent; box-shadow: inset 0 0 0 1.5px var(--line); }
@media (hover: hover) and (pointer: fine) { .mf-tag:hover { transform: scale(1.12); } }
.mf-tag.on { box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 3.5px var(--ctag-color, var(--txt-2)); }
.mf-clear {
  align-self: flex-start; border: none; background: none; color: var(--txt-2); font-size: 12.5px;
  cursor: pointer; padding: 0; text-decoration: underline;
}
@media (hover: hover) and (pointer: fine) { .mf-clear:hover { color: var(--txt); } }
.mf-toggle-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding-top: 2px; border-top: 1px solid var(--line-soft); font-size: 13px; color: var(--txt-2);
  cursor: pointer;
}

/* dòng "ai đưa lên • lúc nào", ngay dưới tên tệp */
.tile .by {
  padding: 0 9px 8px;
  font-size: 11.5px; color: var(--txt-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Huy hiệu bình luận: nằm dưới ảnh, góc trái — không đè lên ảnh nữa để khỏi giẫm chân
   nhau với ô tích/nhãn version ở góc trên. */
/* Huy hiệu bình luận: đè lên ảnh, góc dưới-trái — đối xứng với thời lượng video (.vdur)
   ở góc dưới-phải, tránh góc trên vì đã có ô tích/nhãn version. */
.tile .badges { position: absolute; left: 7px; bottom: 7px; z-index: 2; display: flex; gap: 5px; }

/* Tag "v3" của version stack — góc trên-phải, tách khỏi cụm badge bình luận/trạng thái ở
   góc trên-trái (giống Frame.io). z-index thấp hơn .checkbox để không đè khi hover chọn ảnh. */
.tile .ver-tag {
  position: absolute; top: 7px; right: 7px; z-index: 2;
  padding: 2px 6px; border-radius: 6px; font-size: 11px; font-weight: 700;
  background: rgba(0, 0, 0, .62); color: #fff;
}
/* PSD/PSB đã có preview như ảnh thường, nhưng vẫn cần nhận ra đây là file thiết kế gốc.
   Đặt góc dưới-phải để không đụng ô chọn/version ở trên và bình luận ở dưới-trái. */
.format-badge {
  position: absolute; right: 7px; bottom: 7px; z-index: 2;
  padding: 3px 7px; border: 1px solid rgba(255, 255, 255, .28); border-radius: 6px;
  background: rgba(10, 12, 17, .82); color: #fff;
  font-size: 10px; line-height: 1.2; font-weight: 800; letter-spacing: .08em;
}
/* Ô audio: góc dưới-phải đã có thời lượng (.vdur) — nhãn MP3/WAV sang dưới-trái */
.format-badge.is-audio { right: auto; left: 7px; }
/* Kéo 1 tệp thả đè lên đúng ô ảnh này = tạo phiên bản mới — viền + lớp phủ chỉ hiện khi
   đang kéo tới đúng ô (xem dragHasCompatibleFile()/renderGrid() trong admin.js). */
.tile .ver-drop-hint {
  position: absolute; inset: 0; z-index: 4; display: none;
  align-items: center; justify-content: center; text-align: center; padding: 8px;
  font-size: 12px; font-weight: 600; color: #fff;
  background: rgba(145, 132, 217, .55);
}
.tile.ver-drop-target { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.tile.ver-drop-target .ver-drop-hint { display: flex; }

/* Kéo thả sắp xếp tay (sắp xếp "Tuỳ chỉnh", window.makeReorderable() trong thread.js) — ô đang
   được kéo nổi hẳn lên trên (position:fixed, z-index đặt tại chỗ). Rê vào GIỮA 1 ô khác (chỉ ở
   admin.js, xem `onStack`) tái dùng nguyên .ver-drop-target/.ver-drop-hint ở trên — cùng 1 cử chỉ
   thị giác với kéo TỆP THẬT thả đè lên ô để tạo phiên bản mới, cho nhất quán. */
.tile.reordering { box-shadow: 0 8px 24px rgba(0, 0, 0, .35); opacity: .92; cursor: grabbing; }
/* Kéo cả nhóm đã Shift/Cmd chọn nhiều (2026-09-27, xem getGroupIds trong thread.js) — ô đang nhấn
   nổi lên theo con trỏ như bình thường, PHÍA SAU nó có thêm 1-2 thẻ giả (.reorder-stack-card, tạo
   trong lift()/theo dõi vị trí trong followDrag() ở thread.js) xoay lệch nhẹ như 1 xấp ảnh thật
   — người dùng báo bản đầu (chỉ tô mờ tại chỗ, không có gì "bay theo" tay) nhìn như tính năng
   không chạy. Các ô còn lại trong nhóm (.reordering-member, gán trong lift()) CỐ Ý không đổi kiểu
   dáng gì cả — người dùng yêu cầu giữ nguyên như đang đứng yên, khỏi cảm giác "xáo trộn cả lưới"
   trong lúc còn đang kéo (chưa thả); vẫn cần class này để loại chúng khỏi mục tiêu thả, xem
   inGroup(). Số đếm hiện qua ::after đọc từ data-group-count (đặt trong lift()) — đặt NGAY GIỮA
   ô đang kéo (không phải góc trên-phải như bản đầu) cho thật dễ thấy, người dùng yêu cầu
   2026-09-27. */
.tile.reordering[data-group-count]:not([data-group-count=""])::after {
  content: attr(data-group-count);
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 501;
  min-width: 34px; height: 34px; padding: 0 8px; border-radius: 17px;
  background: var(--accent); color: var(--on-accent, #fff);
  font-size: 16px; font-weight: 700; display: grid; place-items: center;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .4);
}
.reorder-stack-card {
  position: fixed; border-radius: 10px; background: var(--bg-2);
  border: 1px solid var(--line); box-shadow: 0 4px 14px rgba(0, 0, 0, .3);
  pointer-events: none; transition: none;
}
/* Vạch dọc báo chèn trước/sau — phần tử RIÊNG, gắn vào <body> (không phải con của .tile, tile có
   overflow:hidden sẽ cắt mất phần vạch thò ra ngoài mép ô), toạ độ do JS tự tính theo mép ô đang
   rê tới. Đậm + có quầng sáng cho thật rõ, giống Frame.io — trước đây chỉ viền mờ 1 cạnh ô nên
   người dùng báo "không thấy đường chỉ di chuyển đi đâu". */
.reorder-line {
  position: fixed; width: 3px; border-radius: 2px; background: var(--accent);
  z-index: 600; pointer-events: none;
}
.reorder-line[hidden] { display: none; }
/* Ảnh bên trong ô (ảnh bìa thư mục, ảnh xem trước) không tự kéo riêng được — kéo luôn do ô xử lý
   (kéo HTML5 để chuyển, hoặc makeReorderable để đổi thứ tự). Trước đây ở "Tuỳ chỉnh" ô tắt draggable
   nên ấn đúng ảnh bìa là trình duyệt kéo ẢNH đi (lỗi thật 2026-10-11). */
#dGrid .tile img, #dGridF .tile img, .drv-it img { -webkit-user-drag: none; user-drag: none; }  /* chỉ trang quản trị — khách vẫn kéo ảnh ra máy được */
/* Ô vừa thả (phương án A, 2026-10-11 — window.flipReorder trong thread.js): viền màu nhấn sáng rồi mờ dần */
.drop-flash { animation: drop-flash 1.1s ease-out; }
@keyframes drop-flash {
  0% { box-shadow: 0 0 0 2px var(--accent), 0 0 0 6px color-mix(in srgb, var(--accent) 35%, transparent); }
  100% { box-shadow: 0 0 0 2px transparent, 0 0 0 10px transparent; }
}

/* Kéo ô ảnh/thư mục thả vào ô thư mục = di chuyển vào đó — cùng kiểu viền + lớp phủ với
   ver-drop-target ở trên, khác nội dung chữ (xem drop trong renderGrid() trong admin.js). */
.tile.folder .folder-drop-hint {
  position: absolute; inset: 0; z-index: 4; display: none;
  align-items: center; justify-content: center; text-align: center; padding: 8px;
  font-size: 12px; font-weight: 600; color: #fff;
  background: rgba(145, 132, 217, .55);
}
.tile.folder.drop-target { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.tile.folder.drop-target .folder-drop-hint { display: flex; }

/* Ô tích chọn của người quản trị — góc phải, tách biệt với huy hiệu của khách ở góc trái */
.tile .checkbox {
  position: absolute; top: 7px; right: 7px; width: 22px; height: 22px;
  border-radius: 6px; border: 1.5px solid rgba(255, 255, 255, .6);
  background: rgba(0, 0, 0, .55);
  display: grid; place-items: center; color: #fff; font-size: 13px;
  opacity: 0; transition: opacity .12s; cursor: pointer; z-index: 3;
}
.tile:hover .checkbox, .tile.picked .checkbox { opacity: 1; }
.tile.picked .checkbox { background: var(--accent); border-color: var(--accent); }
.tile:not(.picked) .checkbox { color: transparent; }
.tile.picked { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
/* Trang khách: góc phải đã có nút đánh dấu của khách, nên ô tích chọn nằm góc trái */
#grid .tile .checkbox { left: 7px; right: auto; }
/* Trang quản trị: chuyển ô tích chọn sang góc trái để khỏi đè lên nhãn version (v2, v3...)
   ở góc phải. Áp dụng cả #dGridF (ô thư mục) để dùng chung 1 kiểu với ô ảnh (#dGrid). */
#dGrid .tile .checkbox, #dGridF .tile .checkbox { left: 7px; right: auto; }

/* Vòng xoay trong lúc chờ hình đại diện — ẩn ngay khi ảnh tải xong */
.spin { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.spin::before {
  content: ''; width: 26px; height: 26px; border-radius: 6px;
  border: 2px solid rgba(255, 255, 255, .16); border-top-color: var(--txt-2);
  animation: wahspin .9s linear infinite;
}
@keyframes wahspin { to { transform: rotate(360deg); } }

/* Đang tải khi mở dự án / đổi thư mục (dự án + My Drive): vào trang ngay, nội dung cũ ẩn đi, vòng
   xoay giữa vùng nội dung — setLoading() trong admin.js / drive.js. Hiện chậm 120ms để mạng nhanh
   không bị nháy. */
.sf-loader { display: none; }
.is-loading:not(#tabPhotos) > :not(.sf-loader) { display: none !important; }
#tabPhotos.is-loading > .sec, #tabPhotos.is-loading > .dropzone, #tabPhotos.is-loading > .selbar { display: none !important; }
.is-loading > .sf-loader {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  min-height: 50vh; color: var(--txt-3); font-size: 13px;
  animation: fadein .2s ease .12s both;
}
#viewProject.is-loading > .sf-loader { min-height: calc(100vh - 120px); }
.sf-loader-ring {
  width: 28px; height: 28px; border-radius: 6px;
  border: 2px solid rgba(128, 128, 140, .25); border-top-color: var(--txt-2);
  animation: wahspin .8s linear infinite;
}
.drv-loading #drvCount, .drv-loading #drvQuota { visibility: hidden; }
.tile .ph img.on + .spin { display: none; }
.tile .cap .working { color: var(--txt-3); font-size: 11.5px; }

/* Vòng tròn phần trăm khi đang chuyển mã video */
.ring {
  position: absolute; inset: 0; z-index: 3;
  display: grid; place-items: center; pointer-events: none;
}
.ring svg { width: 58%; max-width: 96px; aspect-ratio: 1; grid-area: 1/1; }
.ring rect { fill: none; stroke-width: 2.6; stroke-linecap: round; }
.ring .rbg { stroke: rgba(255, 255, 255, .12); }
.ring .rfg { stroke: var(--accent-hi); transition: stroke-dashoffset .6s linear; }
.ring .rpct {
  grid-area: 1/1; font-size: 19px; font-weight: 600; color: var(--txt-1);
  letter-spacing: -.5px;
}
.ring .rpct i { font-style: normal; font-size: 11px; color: var(--txt-3); margin-left: 1px; }
/* Chưa biết % (mới xếp hàng): một đoạn viền chạy quanh khung thay vì đứng im ở 0% (animation thắng
   strokeDashoffset inline do applyProgress gán) */
.ring.indeterminate .rfg { stroke-dasharray: 24 76; animation: sfTraceDash 1.1s linear infinite; }
@keyframes sfTraceDash { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -100; } }
/* đang xử lý thì giấu nút play; có phần trăm rồi thì thay luôn vòng xoay */
.tile.busy .playicon, .tile.busy .vdur { display: none !important; }
.tile.pct .ph img { opacity: .25 !important; }
.tile.pct .spin { display: none; }
.tile.busy .cap .working { color: var(--accent-hi); }

/* Rê chuột ngang ô video để xem nhanh khung hình.
   Ảnh dải gồm 10 ô vuông, trượt bằng left nên không lệ thuộc tỉ lệ khung hình. */
.scrub {
  position: absolute; inset: 0; overflow: hidden; z-index: 1;
  opacity: 0; transition: opacity .1s; pointer-events: none;
}
.scrub.on { opacity: 1; }
.tile .ph .scrub img {
  position: absolute; top: 0; left: calc(var(--i, 0) * -100%);
  width: 1000%; height: 100%; max-width: none;
  object-fit: fill; opacity: 1; display: block;
}
.scrub .playline { position: absolute; top: 0; bottom: 0; width: 2px; background: #ff3b30; }

/* Ảnh chưa tải xong thì chỉ có vòng xoay, đừng chồng thêm nút play và thời lượng */
.tile:not(.loaded) .playicon,
.tile:not(.loaded) .vdur { display: none; }

/* dấu hiệu ô là video */
.tile .playicon {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 42px; height: 42px; border-radius: 8px; pointer-events: none;
  background: rgba(0, 0, 0, .55);
  display: grid; place-items: center; color: #fff; z-index: 2;
}
/* Ô nhạc: thumbnail có tên bài ở giữa (xem waveSvg() trong src/video.js) — nút play chỉ hiện khi
   rê chuột để khỏi đè chữ; máy cảm ứng không rê được thì vẫn hiện như cũ */
@media (hover: hover) {
  .tile .ph.isaudio .playicon { opacity: 0; transition: opacity .15s; }
  .tile:hover .ph.isaudio .playicon { opacity: 1; }
}
.tile .vdur {
  position: absolute; right: 7px; bottom: 7px; z-index: 2;
  padding: 1px 6px; border-radius: 5px; pointer-events: none;
  background: rgba(0, 0, 0, .65); color: #fff; font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.badge-dot {
  width: 20px; height: 20px; border-radius: 6px; display: grid; place-items: center; color: #fff;
  /* Không dùng backdrop-filter: mỗi ô có nhận xét thành 1 lớp làm mờ riêng → cuộn lưới hàng
     trăm ô rất nặng. Nền đặc hơn một chút thay cho hiệu ứng mờ. */
  font-size: 10px; font-weight: 700; background: rgba(0, 0, 0, .68);
}

/* Huy hiệu góp ý: icon kèm luôn số lượng nên phải nới ra thành huy hiệu chữ nhật */
.badge-cmt {
  width: auto; min-width: 20px; padding: 0 6px; border-radius: 6px;
  display: inline-flex; align-items: center; gap: 3px; font-size: 11px;
}

/* ---------- lightbox ---------- */
.lb { position: fixed; inset: 0; z-index: 100; background: #08090c; display: none; }
/* minmax(0,1fr) để hàng ảnh không bị content đẩy tràn ra ngoài màn hình.
   Cột cũng phải khai báo: cột ngầm là "auto", nó nở tới max-content của ô rộng nhất —
   tên file dài trong thanh trên kéo cả trình xem rộng hơn màn hình, nút ⋯ bị đẩy ra
   ngoài rìa phải. minmax(0,1fr) ghim cột đúng bề ngang khung nhìn. */
.lb.open {
  display: grid;
  grid-template-rows: var(--header-h) minmax(0, 1fr) auto;
  grid-template-columns: minmax(0, 1fr);
}
.lb-head {
  display: flex; align-items: center; gap: 12px; padding: 0 14px;
  border-bottom: 1px solid var(--line-soft); background: var(--bg-1);
}
/* Ô tên file: tên dài phải cắt bằng "…". Không có min-width:0 thì kích thước tối thiểu
   của nó bằng cả tên file (tên file không có dấu cách nên không ngắt được), đủ sức đẩy
   các nút hành động ra khỏi thanh. */
.lb-head > div:not(.spacer):not(.lb-acts) {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ✕ và ⋯ giữ nguyên cỡ, phần phải co là ô tên file */
.lb-head > .btn.icon { flex: none; }
/* Hàng 2 (auto) dành cho .vscrub — chỉ chiếm đúng cột của .stage (cột 1), không lấn
   sang cột panel. Ảnh tĩnh thì .vscrub ẩn hẳn ([hidden]), hàng 2 tự co về 0, .stage
   lấy lại trọn khung như cũ. */
.lb-body {
  display: grid; grid-template-columns: minmax(0, 1fr) 0; grid-template-rows: minmax(0, 1fr) auto;
  min-height: 0;
}
.lb-body.with-panel { grid-template-columns: minmax(0, 1fr) 340px; }
.stage {
  grid-column: 1; grid-row: 1;
  position: relative; min-width: 0; min-height: 0; overflow: hidden; touch-action: none;
}
/* Không đặt will-change: transform ở đây. Nó đẩy ảnh sang một lớp GPU riêng,
   trình duyệt vẽ ảnh đúng một lần ở cỡ vừa khung rồi kéo giãn lớp đó khi zoom —
   ảnh nạp bao nhiêu megapixel cũng vẫn mờ. zoom.js đổi kích thước thật thay vì scale. */
.stage img {
  position: absolute; inset: 20px; margin: auto;
  max-width: calc(100% - 40px); max-height: calc(100% - 40px);
  width: auto; height: auto; object-fit: contain;
  user-select: none; -webkit-user-drag: none; border-radius: 4px;
}
.viewer-image-spin { z-index: 3; }
.viewer-format-badge {
  position: absolute; left: 24px; top: 24px; z-index: 4; pointer-events: none;
  padding: 5px 9px; border: 1px solid rgba(255, 255, 255, .32); border-radius: 7px;
  background: rgba(10, 12, 17, .78); color: #fff; backdrop-filter: blur(6px);
  font-size: 12px; line-height: 1.2; font-weight: 800; letter-spacing: .09em;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}
.stage canvas {
  position: absolute; pointer-events: none; z-index: 1;
  border-radius: 4px;
}
/* Video trong khung xem: cùng cách căn với ảnh, nhưng giữ thanh điều khiển riêng */
.stage video {
  position: absolute; inset: 20px; margin: auto;
  max-width: calc(100% - 40px); max-height: calc(100% - 40px);
  width: auto; height: auto; border-radius: 4px; background: #000; z-index: 1;
}
/* Không dùng control mặc định của trình duyệt (đã có .vs-play riêng) nhưng Safari/Chrome
   vẫn tự vẽ nút play tròn to giữa khung mỗi khi video tạm dừng — ẩn hẳn, cả admin lẫn khách
   vì cùng dùng chung .stage video này. */
.stage video::-webkit-media-controls-start-playback-button,
.stage video::-webkit-media-controls-overlay-play-button {
  display: none !important;
  -webkit-appearance: none;
}
/* Sóng âm audio: cùng khung với video nhưng lấp đầy hình chữ nhật (không theo tỉ lệ khung
   hình), bấm/kéo trên sóng để tua — xem createWaveform() trong waveform.js. Phía trên chừa
   chỗ cho khối ảnh bìa + tên bài (.wave-cover). */
#lbWave, #albWave {
  inset: 20px; top: 184px; width: calc(100% - 40px); height: calc(100% - 204px);
  background: rgba(0, 0, 0, .35); cursor: ew-resize; pointer-events: auto;
  touch-action: none; user-select: none; -webkit-user-select: none;
}
#lbWave.scrubbing, #albWave.scrubbing { cursor: grabbing; }
.wave-cover {
  position: absolute; left: 20px; top: 20px; right: 20px; z-index: 2;
  display: flex; align-items: flex-end; gap: 16px; pointer-events: none;
}
.wave-cover[hidden] { display: none; }
.wave-art {
  width: 148px; height: 148px; flex: none; border-radius: 10px; overflow: hidden;
  background: #1c2030; color: rgba(146, 151, 214, .9);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .06);
}
/* thắng rule .stage img chung (ảnh đang xem căn giữa tuyệt đối trong khung) */
.stage .wave-art img {
  position: static; inset: auto; margin: 0; max-width: none; max-height: none; transform: none;
  width: 100%; height: 100%; object-fit: cover; border-radius: 0; display: none;
}
.stage .wave-art.has-img img { display: block; }
.wave-art.has-img .wave-art-ico { display: none; }
.wave-meta { min-width: 0; padding-bottom: 4px; }
.wave-kind { font-size: 11px; color: rgba(255, 255, 255, .5); margin-bottom: 4px; }
.wave-title {
  font-size: 18px; font-weight: 600; color: #fff; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wave-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.wave-chips span {
  font-size: 11px; color: rgba(255, 255, 255, .6); padding: 2px 7px; border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, .12); font-variant-numeric: tabular-nums;
}
.wave-tip {
  position: absolute; z-index: 3; transform: translate(-50%, calc(-100% - 6px));
  background: #fff; color: #0b0d14; font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 4px 6px; border-radius: 4px; pointer-events: none; white-space: nowrap;
}
.wave-tip[hidden] { display: none; }
@media (max-width: 640px) {
  #lbWave, #albWave { top: 112px; height: calc(100% - 132px); }
  .wave-art { width: 76px; height: 76px; border-radius: 8px; }
  .wave-title { font-size: 15px; }
  .wave-chips { margin-top: 6px; }
}
/* Vòng xoay trong lúc giải mã sóng âm (createWaveform() trong waveform.js) — đè lên trên
   canvas nền đen mờ ở trên, để khỏi trông như màn hình treo lúc chưa có dữ liệu vẽ. */
#lbWaveSpin, #albWaveSpin { z-index: 2; }
/* Thẻ tệp chưa xem trước được giữa khung xem (createFileCard() trong thread.js) */
.file-card {
  position: absolute; inset: 0; z-index: 2; margin: auto; padding: 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; color: #e6e8f0;
}
.file-card[hidden] { display: none; }
.stage .file-card .fc-art {
  position: static; inset: auto; margin: 0; max-width: none; max-height: none; opacity: 1;
  width: 168px; height: 168px; border-radius: 10px; object-fit: contain;
}
.file-card .fc-name {
  margin-top: 14px; max-width: min(520px, 100%); font-size: 17px; font-weight: 600;
  overflow-wrap: anywhere; line-height: 1.35;
}
.file-card .fc-meta { margin-top: 4px; font-size: 12.5px; color: rgba(230, 232, 240, .6); }
.file-card .fc-note { margin: 14px 0 16px; font-size: 12.5px; color: rgba(230, 232, 240, .45); }
.file-card .fc-actions { display: flex; gap: 8px; }
.file-card .fc-actions .btn { display: inline-flex; align-items: center; gap: 6px; }
.file-card .fc-actions .btn[hidden] { display: none; }
@media (max-width: 640px) {
  .stage .file-card .fc-art { width: 120px; height: 120px; }
  .file-card .fc-name { font-size: 15px; }
}
.lb.audio-mode .zoombar > :not(.filmstrip-trigger) { display: none; }
/* tệp chưa xem trước được / PDF / audio: không vẽ, không ghim (người dùng yêu cầu 2026-09-29);
   tệp và PDF còn không zoom (PDF tự cuộn dọc — createPdfPages() trong thread.js) */
.lb.file-mode .zoombar > :not(.filmstrip-trigger),
.lb.pdf-mode .zoombar > :not(.filmstrip-trigger),
.lb.file-mode #penBtn, .lb.file-mode #aPenBtn,
.lb.pdf-mode #penBtn, .lb.pdf-mode #aPenBtn,
.lb.audio-mode #penBtn, .lb.audio-mode #aPenBtn,
.lb.file-mode .viewer-format-badge, .lb.pdf-mode .viewer-format-badge { display: none !important; }

/* Trình xem PDF cuộn dọc */
.pdf-scroll {
  position: absolute; inset: 0; z-index: 2; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch; touch-action: pan-y pinch-zoom;
}
.pdf-scroll[hidden] { display: none; }
.pdf-pages {
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  padding: 20px 20px 72px; width: 100%; box-sizing: border-box;
}
.pdf-page {
  position: relative; width: 100%; max-width: 1100px; background: #fff; border-radius: 2px;
  box-shadow: 0 2px 14px rgba(0, 0, 0, .45); overflow: hidden;
}
.pdf-page:not(.on)::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, #eceef3 0%, #f7f8fa 50%, #eceef3 100%); background-size: 200% 100%;
  animation: pdfShimmer 1.2s linear infinite;
}
.pdf-page.err::after { animation: none; background: #eceef3; }
@keyframes pdfShimmer { to { background-position: -200% 0; } }
.stage .pdf-page img {
  position: static; inset: auto; margin: 0; max-width: none; max-height: none; transform: none;
  width: 100%; height: 100%; display: block; object-fit: contain; border-radius: 0; opacity: 0; transition: opacity .2s;
}
.stage .pdf-page.on img { opacity: 1; }
.pdf-pg-n {
  position: absolute; right: 8px; bottom: 8px; z-index: 1; font-size: 11px; color: #fff;
  background: rgba(16, 17, 27, .6); border-radius: 4px; padding: 1px 6px; font-variant-numeric: tabular-nums;
}
.pdf-bar {
  position: sticky; bottom: 14px; margin: -58px auto 14px; width: max-content; z-index: 3;
  display: flex; align-items: center; gap: 10px; padding: 5px 12px;
  background: rgba(16, 17, 27, .9); border: 1px solid rgba(255, 255, 255, .12); border-radius: 6px;
  color: #e6e8f0; font-size: 12px; font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) { .pdf-pages { padding: 10px 8px 64px; gap: 10px; } }

/* Bộ chọn chất lượng phát và trạng thái đang chuyển mã */
/* Góc dưới phải khung xem: vòng xoay "đang xử lý" nằm ngay bên trái ô chất lượng */
.qwrap {
  position: absolute; right: 16px; bottom: 16px; z-index: 3;
  display: flex; align-items: center; gap: 8px;
}
.qspin {
  flex: none; width: 15px; height: 15px; border-radius: 4px;
  border: 2px solid rgba(255, 255, 255, .16); border-top-color: var(--txt-2);
  animation: wahspin .9s linear infinite;
}
.qbar {
  height: 30px; padding: 0 8px; cursor: pointer;
  background: rgba(22, 24, 38, .88); border: 1px solid var(--line);
  border-radius: 9px; color: var(--txt-2); font-size: 12.5px;
  backdrop-filter: blur(8px);
}
@media (hover: hover) and (pointer: fine) { .qbar:hover { color: var(--txt); } }
.prepping {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 3;
  padding: 14px 18px; border-radius: 12px; font-size: 13px; text-align: center;
  min-width: 260px; max-width: 80%;
  background: rgba(22, 24, 38, .9); border: 1px solid var(--line); color: var(--txt-2);
}
.prepping .prep-bar {
  height: 5px; margin: 12px 0 7px; border-radius: 6px;
  background: rgba(255, 255, 255, .1); overflow: hidden;
}
.prepping .prep-bar > i { display: block; height: 100%; width: 0; background: var(--accent-hi); transition: width .6s linear; }
.prepping .prep-eta { font-size: 12px; color: var(--txt-3); }

/* Mốc thời gian trong góp ý video */
.tc {
  display: inline-flex; align-items: center; height: 19px; padding: 0 7px;
  margin-right: 6px; border-radius: 5px; cursor: pointer;
  background: rgba(145, 132, 217, .2); color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px;
}
@media (hover: hover) and (pointer: fine) { .tc:hover { background: var(--accent); color: #fff; } }
.tcbtn {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  border: 1px solid var(--line); background: var(--bg-3); border-radius: 8px;
  cursor: pointer; font-size: 12.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.tcbtn.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.tcbtn.range { white-space: nowrap; }
.tcbtn .tc-x { margin-left: 2px; font-size: 14px; line-height: 1; opacity: .75; }
.tcbtn.range:hover .tc-x { opacity: 1; }

/* Đường dẫn trong thanh trên, kiểu Frame.io: "PROJECT / thư-mục-con / tên tệp" —
   thay cho mỗi tên tệp trơ trọi như trước, giúp biết đang xem ảnh của project nào. */
.lb-crumb {
  display: flex; align-items: baseline; gap: 6px; font-size: 14px; line-height: 1.3; min-width: 0;
}
/* Tên project là phần PHỤ, co/cắt bớt trước tiên khi chật chỗ — tên tệp đang xem mới là
   phần quan trọng, luôn được ưu tiên giữ (flex-grow + sàn min-width riêng bên dưới). */
.lb-crumb .cr-root {
  color: var(--txt-2); text-transform: uppercase; letter-spacing: .02em; font-size: 12px;
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lb-crumb .cr-sep { color: var(--txt-3); flex: none; }
.lb-crumb .cr-file {
  color: var(--txt); font-weight: 600; flex: 1 1 auto; min-width: 60px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Pill "v3" ngay cạnh tên tệp, mở popover chọn phiên bản — kiểu Frame.io, thay cho <select>
   trước đây nằm lẫn trong cụm nút bên phải (xa tên tệp, dễ bị bỏ sót). */
.ver-pick { flex: none; }
.ver-pill {
  display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 8px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 6px;
  color: var(--txt-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .ver-pill:hover { color: var(--txt); } }
.ver-pill svg { flex: none; transition: transform .15s ease; }
.ver-pick.open .ver-pill svg { transform: rotate(180deg); }
.ver-pop {
  /* fixed + toạ độ do JS tính (xem placeVerPop()) — giống #ctxMenu, để không lệ thuộc stacking
     context của .lb-head/.lb-body (2 grid item ngang hàng trong .lb.open). */
  position: fixed; z-index: 300; width: 280px; max-height: 360px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; overflow: hidden;
}
.ver-pop-list { overflow-y: auto; padding: 6px; }
.ver-row {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 8px; border-radius: 8px;
  border: none; background: none; cursor: pointer; text-align: left; color: inherit; font: inherit;
}
@media (hover: hover) and (pointer: fine) { .ver-row:hover { background: var(--bg-3); } }
.ver-row .ver-thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; flex: none; background: var(--bg-3); }
.ver-row .ver-tag {
  flex: none; min-width: 24px; height: 20px; padding: 0 6px; border-radius: 6px; background: var(--bg-3);
  display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--txt-2);
}
.ver-row .ver-info { min-width: 0; flex: 1 1 auto; }
.ver-row .ver-name { font-size: 13px; color: var(--txt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ver-row .ver-by { font-size: 11.5px; color: var(--txt-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ver-row .ver-check { flex: none; color: var(--accent); }
.ver-pop-hist {
  display: flex; align-items: center; justify-content: center; width: 100%; padding: 11px 14px;
  border: none; border-top: 1px solid var(--line-soft); background: none; color: var(--txt-2);
  font: inherit; font-size: 12.5px; cursor: pointer; flex: none;
}
@media (hover: hover) and (pointer: fine) { .ver-pop-hist:hover { background: var(--bg-3); color: var(--txt); } }

/* Hộp "Quản lý phiên bản" (versionHistoryDialog) — mỗi dòng kéo-thả được bằng tay cầm (≡)
   để đổi thứ tự, xem render()/dragstart-drop trong versionHistoryDialog(). */
.ver-hist-list { display: flex; flex-direction: column; gap: 2px; max-height: 60vh; overflow-y: auto; }
.ver-hist-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-radius: 8px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .ver-hist-row:hover { background: var(--bg-3); } }
.ver-hist-row .vh-handle { flex: none; display: flex; color: var(--txt-3); cursor: grab; }
.ver-hist-row .vh-handle:active { cursor: grabbing; }
.ver-hist-row .ver-tag {
  flex: none; min-width: 24px; height: 20px; padding: 0 6px; border-radius: 6px; background: var(--bg-3);
  display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--txt-2);
}
.ver-hist-row .vh-thumb { width: 44px; height: 44px; border-radius: 6px; object-fit: cover; flex: none; background: var(--bg-3); }
.ver-hist-row .vh-info { min-width: 0; flex: 1 1 auto; }
.ver-hist-row .vh-name { font-size: 13.5px; color: var(--txt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ver-hist-row .vh-meta { font-size: 12px; color: var(--txt-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ver-hist-row .vh-rename { flex: none; color: var(--txt-3); }
@media (hover: hover) and (pointer: fine) { .ver-hist-row .vh-rename:hover { color: var(--txt); } }
.ver-hist-row .vh-del { flex: none; color: var(--txt-3); }
@media (hover: hover) and (pointer: fine) { .ver-hist-row .vh-del:hover { color: var(--danger); } }

/* Điều hướng ảnh trước/sau: trước đây là 2 nút tròn đè lên góc ảnh/video, giờ dồn thành
   một cụm nhỏ trên thanh đầu (giống Frame.io) — khỏi che mất nội dung đang xem. */
.lb-nav {
  display: flex; align-items: center; gap: 0; flex: none;
  height: 28px; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 7px; padding: 0 1px;
}
.lb-nav .nav-btn {
  width: 22px; height: 24px; border-radius: 5px; border: none; background: transparent;
  color: var(--txt-2); cursor: pointer; display: grid; place-items: center; font-size: 15px;
  line-height: 1; transition: background .12s, color .12s;
}
@media (hover: hover) and (pointer: fine) { .lb-nav .nav-btn:hover { background: var(--bg-3); color: var(--txt); } }
.lb-nav .nav-idx {
  font-size: 11.5px; line-height: 1; color: var(--txt-2); padding: 0 4px; white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* grid-row 1/3: trùm cả 2 hàng của .lb-body — panel cao đủ như cũ, không bị .vscrub
   (chỉ nằm ở cột .stage) ăn bớt chiều cao. */
.panel {
  grid-column: 2; grid-row: 1 / 3;
  border-left: 1px solid var(--line-soft); background: var(--bg-1); display: flex; flex-direction: column; overflow: hidden;
}
.panel .p-head { padding: 12px 14px; border-bottom: 1px solid var(--line-soft); font-weight: 600; }
.panel .p-body { flex: 1; overflow-y: auto; padding: 12px 14px; }
.panel .p-foot { border-top: 1px solid var(--line-soft); padding: 10px 12px; }

/* Tabs Nhận xét / Thông tin trong viewer, theo mô hình panel của Frame.io. */
.panel .viewer-panel-head { padding: 8px 10px; }
.viewer-panel-tabs {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px; padding: 2px;
  background: var(--bg-2); border-radius: 9px;
}
.viewer-panel-tabs button {
  height: 30px; padding: 0 10px; border: 0; border-radius: 7px;
  background: transparent; color: var(--txt-3); cursor: pointer; font: inherit; font-size: 12px;
}
@media (hover: hover) and (pointer: fine) { .viewer-panel-tabs button:hover { color: var(--txt); } }
.viewer-panel-tabs button.on { background: var(--bg-3); color: var(--txt); box-shadow: 0 1px 2px rgba(0,0,0,.2); }
.asset-info-panel { display: flex; flex-direction: column; gap: 10px; background: var(--bg-1); }
.asset-info-panel[hidden] { display: none; }
.asset-info-card { flex: none; padding: 12px; border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg-2); }
.asset-info-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; color: var(--txt); }
.asset-info-created { margin-top: 7px; color: var(--txt-3); font-size: 11.5px; }
.asset-info-primary { display: grid; grid-template-columns: 1fr 1fr; margin: 12px -12px -12px; border-top: 1px solid var(--line-soft); }
.asset-info-primary > div { min-width: 0; padding: 10px 8px 11px; text-align: center; }
.asset-info-primary > div + div { border-left: 1px solid var(--line-soft); }
.asset-info-primary span { display: block; margin-bottom: 4px; color: var(--txt-3); font-size: 9.5px; letter-spacing: .04em; }
.asset-info-primary b { display: block; overflow: hidden; text-overflow: ellipsis; font-size: 12.5px; font-weight: 500; white-space: nowrap; }
.asset-info-section-title { margin-bottom: 8px; color: var(--txt-2); font-size: 12px; font-weight: 600; }
.asset-info-section-title span { color: var(--txt-3); font-weight: 500; }
.asset-info-rows { display: grid; gap: 7px; }
.asset-info-rows > div { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 10px; font-size: 11.5px; }
.asset-info-rows span { color: var(--txt-3); }
.asset-info-rows b { min-width: 0; overflow-wrap: anywhere; color: var(--txt-2); font-weight: 500; text-align: right; }
.asset-seen-list { display: flex; flex-wrap: wrap; gap: 6px; }
.asset-seen-person { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 3px 8px 3px 3px; border-radius: 6px; background: var(--bg-3); color: var(--txt-2); font-size: 11px; }
.asset-seen-person > span:last-child { overflow: hidden; max-width: 105px; text-overflow: ellipsis; white-space: nowrap; }
.asset-seen-person .avatar { width: 22px; height: 22px; font-size: 8px; }
.asset-view-count { display: flex; align-items: baseline; gap: 6px; color: var(--txt-3); font-size: 11.5px; }
.asset-view-count b { color: var(--txt); font-size: 20px; font-weight: 600; }
.asset-info-empty { color: var(--txt-3); font-size: 11.5px; }

/* Composer hai hàng, tối giản theo nhịp Frame.io: nội dung ở trên, công cụ + gửi ở dưới.
   .cmp-cmts-compose là ô soạn trong khung so sánh phiên bản (dựng bằng JS ở thread.js,
   nằm ngoài .panel) — dùng chung y hệt bố cục này để hai nơi không lệch nhau. */
.panel .comment-composer,
.cmp-cmts-compose.comment-composer {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px;
  padding: 9px 12px 10px; background: var(--bg-1);
}
/* Mọi phần của ô soạn chiếm trọn bề ngang; riêng hàng công cụ (.drawbar, cột trái) và cụm
   Hiển thị + Gửi (.compose-actions, cột phải) đứng CHUNG 1 hàng — hết cảnh hàng công cụ bị đẩy
   xuống 2 dòng vì phải chừa chỗ cố định cho cụm Gửi nằm đè (position:absolute) như trước. */
.comment-composer > * { grid-column: 1 / -1; }
.comment-composer .reply-to { order: 0; }
.comment-composer .compose-input { position: relative; order: 1; }
/* Khung so sánh dựng ô soạn bằng JS nên danh sách tệp đính kèm ở đó là class chứ không
   phải id — không khớp thêm thì nó rơi về order 0, nhảy lên TRÊN ô nhập. */
.comment-composer > [id$="AttachList"],
.comment-composer > .cmp-attach-list { order: 2; }
.comment-composer .drawbar {
  order: 3; grid-column: 1; min-width: 0; min-height: 30px; margin: 6px 0 0; gap: 2px; flex-wrap: wrap;
}
/* Đang vẽ: cụm Gửi ẩn đi (xem :has(.drawbar.drawing) phía dưới) → thanh công cụ vẽ lấy trọn hàng */
.comment-composer .drawbar.drawing { grid-column: 1 / -1; }
.comment-composer .drawbar > .spacer { display: none; }
.comment-composer textarea.input {
  display: block; width: 100%; min-height: 42px; max-height: 120px; padding: 4px 3px;
  resize: none; border: 0; border-radius: 0; background: transparent; box-shadow: none;
  font-size: 14px; line-height: 1.45;
}
.comment-composer textarea.input:focus { outline: none; border: 0; box-shadow: none; }
.comment-composer .compose-actions {
  order: 3; grid-column: 2; align-self: end; position: relative; z-index: 6;
  margin: 6px 0 0; gap: 4px; min-height: 30px; align-items: center;
}
.comment-composer .compose-actions > .dim { display: none; }
.comment-composer .pen,
.comment-composer .drawbar > .btn {
  width: 30px; height: 30px; min-width: 30px; padding: 0; border: 0; border-radius: 7px;
  display: inline-grid; place-items: center; background: transparent; color: var(--txt-3);
}
@media (hover: hover) and (pointer: fine) { .comment-composer .pen:hover,
.comment-composer .drawbar > .btn:hover { background: var(--bg-3); color: var(--txt); } }
.comment-composer .pen.on { background: rgba(145, 132, 217, .2); color: var(--ink); }
.comment-composer .pen { position: relative; }
.comment-composer .pen.has-draw::after {
  position: absolute; top: -7px; right: -8px; margin: 0;
  z-index: 2; pointer-events: none;
}
/* Nút Vẽ: icon trơn như các công cụ khác (không nhãn, không nổi bật) — chỉ sáng lên khi đang
   bật chế độ vẽ (.on). Khung so sánh dùng .cmp-pen-btn, cùng quy tắc. */
.comment-composer .pen .pen-label { display: none; }
.comment-composer .pen.on,
.comment-composer .cmp-pen-btn.on { background: var(--accent); color: #fff; }
/* Chip mốc thời gian: đứng đầu dòng nhập (JS chuyển vào .compose-input) như Frame.io — viên tím
   nhạt khi đang gắn mốc, tắt thì chữ mờ không nền. Khung so sánh vẫn để chip trong hàng công cụ
   (order:-1 đưa lên đầu hàng). */
.comment-composer .compose-input:has(> .tcbtn:not([hidden])) { display: flex; align-items: flex-start; gap: 6px; }
.comment-composer .compose-input > textarea.input { flex: 1 1 auto; min-width: 0; }
.comment-composer .tcbtn {
  order: -1; flex: none; height: 24px; margin: 2px 0 0; padding: 0 7px; gap: 5px; border: 0; border-radius: 6px;
  background: transparent; color: var(--txt-3); font-size: 12px; white-space: nowrap;
}
.comment-composer .tcbtn.on { background: rgba(145, 132, 217, .16); color: #d6ccff; }
.comment-composer .tcbtn svg { width: 14px; height: 14px; }
.comment-composer .vis-pick > .btn { height: 30px; padding: 0 8px; border: 0; background: var(--bg-2); }
.comment-composer .vis-pick > .btn svg:first-child {
  width: 17px; height: 17px; flex: none; margin-right: 5px !important;
}
.comment-composer .compose-send {
  width: 32px; height: 30px; padding: 0; border-radius: 8px; display: grid; place-items: center;
}

/* ---------- video: thanh chạy dưới khung ----------
   Dải riêng không đè lên video, không lấn sang panel (xem
   grid-row của .lb-body/.panel ở trên). */
.vscrub {
  grid-column: 1; grid-row: 2;
  display: flex; flex-direction: column;
  padding: 6px 14px calc(8px + var(--safe-b));
  background: var(--bg-1); border-top: 1px solid var(--line-soft);
}
/* margin ngang chừa chỗ cho avatar ở mốc 0%/100% không bị cắt mất một nửa */
.vs-track {
  position: relative; height: 4px; margin: 16px 11px 12px;
  border-radius: 6px; background: rgba(255, 255, 255, .2); cursor: pointer;
  touch-action: none;   /* tự lo kéo bằng Pointer Events, không để trình duyệt cuộn trang */
}
/* Vạch nhìn thấy mảnh 4px nhưng vùng chạm thật rộng hơn hẳn — ::before không vẽ gì
   (không background) nhưng vẫn là một phần của .vs-track nên bấm/kéo trong đó vẫn
   nổi bọt lên đúng listener gắn trên .vs-track, dễ bắt trúng ngón tay hơn nhiều. */
.vs-track::before {
  content: ''; position: absolute; left: 0; right: 0; top: -14px; bottom: -14px;
}
.vs-fill { position: relative; display: block; height: 100%; width: 0; border-radius: 6px; background: var(--accent); pointer-events: none; }
/* Đầu phát: vạch trắng 2×6px nhô nhẹ khỏi thanh 4px — đúng kiểu Frame.io */
.vs-fill::after { content: ''; position: absolute; z-index: 3; right: -1px; top: -1px; width: 2px; height: 6px; border-radius: 1px; background: #fff; }
.vs-marks { position: absolute; inset: 0; }
/* Hàng avatar góp ý RIÊNG ngay dưới thanh tua, đo theo Frame.io: avatar 16px cách thanh ~6px, TÂM
   avatar nằm đúng timecode (thẳng hàng với đầu phát khi tua tới), viền 1px tím; không vạch nối.
   Hàng không nhận chuột (bấm chỗ trống vẫn rơi xuống vùng tua của .vs-track), chỉ avatar nhận. */
.vs-track .vs-marks { top: calc(100% + 4px); bottom: auto; height: 20px; pointer-events: none; }
.vs-track .vs-marks .vs-mark { pointer-events: auto; }
.vs-track.vs-track:has(.vs-marks > *) { margin-bottom: 32px; }
.vs-mark {
  position: absolute; top: 50%; transform: translate(-50%, -50%); z-index: 1;
  padding: 0; border: 0; background: none; cursor: pointer; line-height: 0;
}
.vs-mark .avatar { width: 16px; height: 16px; font-size: 7.5px; box-shadow: 0 0 0 1px #aa8aff; }
@media (hover: hover) and (pointer: fine) { .vs-mark:hover .avatar { box-shadow: 0 0 0 1px #c9b6ff; } }
/* Góp ý đang chọn: viền trắng, nổi lên trên — góp ý khác nằm trong cùng vùng I/O vẫn tách bạch */
.vs-mark.on, .vs-mark.hover { z-index: 3; }
.vs-mark.on .avatar { box-shadow: 0 0 0 1px #fff; }
/* Góp ý theo đoạn: vạch 2px tím chạy từ MÉP PHẢI avatar (tâm + 8px) tới điểm Out (JS trừ sẵn 8px) */
.vs-mark-span { position: absolute; top: 50%; height: 1px; margin: -0.5px 0 0 8px; pointer-events: none; background: #aa8aff; opacity: .55; }
.vs-mark-span.on { opacity: .9; }
/* Đoạn In/Out đang chọn (phím I/O, hoặc vừa bấm vào góp ý theo đoạn) — tô ngay TRÊN thanh tua
   4px bằng tím sáng, 2 vạch mảnh nhô nhẹ ở In/Out, đúng như Frame.io. .open = mới có In. */
.vs-range {
  position: absolute; top: 0; height: 100%; pointer-events: none; z-index: 1;
  background: #8f7dff; border-radius: 1px;
}
.vs-range::before, .vs-range::after {
  content: ''; position: absolute; top: -1px; width: 2px; height: 6px; border-radius: 1px; background: #d6ccff;
}
.vs-range::before { left: -1px; }
.vs-range.open::after { display: none; }
.vs-range::after { right: -1px; }
.vs-range.open { background: none; }
/* Rê chuột qua avatar góp ý theo đoạn (chưa chọn): gợi ý nhạt trên thanh, không vạch */
.vs-range.peek { background: rgba(143, 125, 255, .45); }
.vs-range.peek::before, .vs-range.peek::after { display: none; }
.vs-track.has-range .vs-fill { background: rgba(255, 255, 255, .32); }
/* 2 tay nắm In/Out kéo được (thread.js paintHandles) — nhìn mảnh 8×14, vùng chạm rộng hơn (::before) */
.vs-handle {
  position: absolute; top: 50%; z-index: 4; width: 8px; height: 14px; margin: -7px 0 0 -4px; padding: 0;
  border: 1.5px solid #8f7dff; border-radius: 3px; background: #fff; cursor: ew-resize; touch-action: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .45); transition: transform .1s;
}
.vs-handle[hidden] { display: none; }
/* vùng bắt chuột/ngón tay: chuột cần ít (8px mỗi bên), cảm ứng rộng hơn (~36px) cho dễ trúng */
.vs-handle::before { content: ''; position: absolute; left: -8px; right: -8px; top: -8px; bottom: -8px; }
@media (pointer: coarse) { .vs-handle::before { left: -14px; right: -14px; top: -12px; bottom: -14px; } }
.vs-handle:hover, .vs-handle.dragging { transform: scale(1.15); }
.vs-handle:focus-visible { outline: 2px solid #d6ccff; outline-offset: 2px; }
.vs-handle-tip {
  position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); pointer-events: none;
  padding: 2px 6px; border-radius: 5px; background: #fff; color: #14151f; white-space: nowrap;
  font: 500 11px ui-monospace, Menlo, monospace;
}
.vs-handle-tip[hidden] { display: none; }
/* Menu của chip mốc thời gian ở ô soạn (Mốc này / Chọn đoạn / Không gắn mốc) — thread.js openTcMenu */
.tc-menu {
  position: fixed; z-index: 400; min-width: 190px; padding: 4px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--bg-2); box-shadow: var(--shadow);
}
.tc-menu button {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px; border: 0; border-radius: 7px;
  background: none; color: var(--txt); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.tc-menu button:hover, .tc-menu button:focus-visible { background: var(--hover); outline: none; }
.tc-menu button.on { color: #d6ccff; }
.tc-menu-title { padding: 6px 10px 4px; font-size: 12px; color: var(--txt-3); }
.tc-menu.with-check button.on { color: var(--txt); }
.tc-menu .tc-tick { margin-left: auto; width: 15px; height: 15px; color: #aa8aff; }
.tc-menu svg { width: 15px; height: 15px; flex: none; color: var(--txt-2); }
.tcbtn .tc-caret { width: 10px; height: 10px; margin-left: 1px; opacity: .7; }
@media (max-width: 640px) { .tc-menu button { padding: 11px 12px; font-size: 14px; } }
/* Popup xem nhanh 1 góp ý ngay tại avatar mốc — chỉ dùng khi đang toàn màn hình (bảng nhận xét
   ở panel bị ẩn hẳn lúc đó, xem #albBody:fullscreen .panel phía trên), xem createVideoBar()
   trong thread.js. position:fixed + toạ độ do JS tính (placeCmtPop()), giống .ver-pop — nhưng
   phải là CON của root (.vscrub, vốn đã nằm trong fsTarget) chứ không phải document.body, không
   thì Fullscreen API không vẽ ra được (phần tử ngoài cây con toàn màn hình bị ẩn tuyệt đối). */
.vs-cmt-pop {
  position: fixed; z-index: 20; width: 300px; max-width: calc(100vw - 16px);
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow);
  padding: 12px; display: flex; flex-direction: column; gap: 10px;
}
.vs-cmt-pop .cmt { margin-bottom: 0; }
.vs-cmt-pop .cmt .body { max-height: 160px; overflow-y: auto; }
/* Mặc định chỉ hiện link "Trả lời" cho gọn — bấm vào mới lộ .vs-cmt-pop-reply (xem
   createVideoBar() trong thread.js). Không dùng .cmt-acts (chỉ hiện khi hover) vì popup này
   luôn phải bấm được ngay, kể cả trên cảm ứng (không có trạng thái hover). */
.vs-cmt-pop-actions .act { font-size: 11.5px; color: var(--txt-3); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .vs-cmt-pop-actions .act:hover { color: var(--txt); } }
.vs-cmt-pop-reply { display: flex; flex-direction: column; gap: 8px; }
.vs-cmt-pop-reply textarea { resize: none; }
.vs-cmt-pop-reply .btn { align-self: flex-end; }
.vs-row { display: flex; align-items: center; gap: 8px; }
.vs-play, .vs-loop, .vs-mute, .vs-fs {
  flex: none; width: 36px; height: 36px; padding: 0; border: none; cursor: pointer;
  background: transparent; color: #fff; border-radius: 8px;
  display: grid; place-items: center;
}
.vs-play svg, .vs-mute svg, .vs-fs svg { width: 22px; height: 22px; }
@media (hover: hover) and (pointer: fine) { .vs-play:hover, .vs-loop:hover, .vs-mute:hover, .vs-fs:hover { background: var(--bg-3); } }
/* Nút lặp lại: tắt thì mờ, bật thì tím sáng (như Frame.io) */
.vs-loop svg { width: 18px; height: 18px; }
.vs-loop { color: rgba(255, 255, 255, .55); }
.vs-loop.on { color: #aa8aff; }
.vs-time {
  min-width: 84px;   /* HH:MM:SS:FF — giữ chỗ cố định để số khung hình chạy không làm nhảy layout */
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; color: #fff;
  font-variant-numeric: tabular-nums; text-align: center;
}
/* Máy tính/iPad: timecode nằm chính giữa thanh điều khiển (như Frame.io); điện thoại hàng chật nên để nối tiếp */
/* Ô thời gian bấm được (menu Định dạng thời gian): không khung, chữ to, mũi tên nhỏ; nền chỉ hiện khi trỏ vào */
.vs-timebtn {
  flex: none; display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 4px 0 6px;
  border: 0; border-radius: 8px; background: transparent; color: #fff; cursor: pointer; font: inherit;
}
@media (hover: hover) and (pointer: fine) { .vs-timebtn:hover { background: var(--bg-3); } }
.vs-timebtn .vs-time { font-size: 15px; min-width: 0; }
.vs-time-caret { width: 12px; height: 12px; opacity: .55; flex: none; transition: transform .15s; }
.vs-timebtn.menu-open { background: var(--bg-3); }
.vs-timebtn.menu-open .vs-time-caret, .tcbtn.menu-open .tc-caret { transform: rotate(180deg); }
.tcbtn .tc-caret { transition: transform .15s; }
.vs-timebtn.no-fmt { cursor: default; background: transparent; }
.vs-timebtn.no-fmt .vs-time-caret { display: none; }
.vs-time-sep { margin: 0 5px; color: rgba(255, 255, 255, .35); }
.vs-time-total { color: rgba(255, 255, 255, .5); }
/* Căn giữa theo BỀ RỘNG THẬT của hàng nút (container query) chứ không theo màn hình — iPad/cửa sổ hẹp
   hay khung xem có panel nhận xét thì hàng có thể hẹp, căn giữa sẽ đè lên nút Phát/Lặp/Tốc độ.
   Container đặt ở .vs-row chứ KHÔNG ở .vscrub: container-type kéo theo layout containment, mọi con
   position:fixed (vd .vs-cmt-pop gắn trong .vscrub) sẽ tính toạ độ theo nó thay vì màn hình. */
.vs-row { position: relative; container-type: inline-size; container-name: vscrub; }
@container vscrub (min-width: 560px) {
  .vs-timebtn { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
}
/* thanh hẹp: chữ nhỏ lại, bỏ phần tổng + mũi tên cho vừa hàng; chạm vào số vẫn mở menu */
@container vscrub (max-width: 559px) {
  .vs-timebtn { padding: 0 2px; }
  .vs-timebtn .vs-time { font-size: 13px; }
}
@container vscrub (max-width: 420px) {
  .vs-time-caret, .vs-time-sep, .vs-time-total { display: none; }
}
/* select chất lượng nằm chung hàng với play/time thay vì tự neo góc màn hình như trước */
.vs-row .qwrap { position: static; }
/* Ô chất lượng trong thanh điều khiển: viền mảnh 1px, nền trong suốt, bo 8px như các nút khác
   (nền chỉ hiện khi trỏ vào). Kiểu có khung .qbar gốc vẫn dùng khi nổi trên ảnh. */
.vs-row .qbar {
  height: 30px; padding: 0 24px 0 10px; border: 1px solid var(--line); border-radius: 8px; backdrop-filter: none;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='.6' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 7px center / 12px 12px;
  -webkit-appearance: none; appearance: none;
  color: #fff; font: inherit; font-size: 13px; font-variant-numeric: tabular-nums;
}
@media (hover: hover) and (pointer: fine) { .vs-row .qbar:hover { background-color: var(--bg-3); border-color: var(--line-strong, var(--line)); } }
.vs-row .qbar:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.vs-row .qbar option { background: var(--bg-2); color: var(--txt); }
/* Tốc độ phát kiểu Frame.io: nút "1.0x" nền xám → bảng nổi phía trên có thanh trượt nấc (thread.js) */
.vs-speed-wrap { position: relative; flex: none; }
.vs-speed {
  height: 30px; min-width: 46px; padding: 0 9px; border: 0; border-radius: 8px; cursor: pointer;
  background: var(--bg-3); color: var(--txt-2); font: inherit; font-size: 13px; font-variant-numeric: tabular-nums;
}
.vs-speed:hover, .vs-speed.open { color: var(--txt); background: var(--hover-strong, var(--bg-3)); filter: brightness(1.15); }
.vs-speed.changed { color: var(--txt); }
.vs-speed-pop {
  position: absolute; left: -8px; bottom: calc(100% + 10px); z-index: 20; width: 300px;
  padding: 12px 16px 16px; border-radius: 10px; border: 1px solid var(--line); background: var(--bg-2);
  box-shadow: var(--shadow); color: var(--txt); cursor: default;
}
.vs-speed-pop[hidden] { display: none; }
.vsp-title { font-size: 13px; color: var(--txt-2); margin-bottom: 10px; }
.vsp-labels { display: flex; justify-content: space-between; margin: 0 -8px 8px; }
.vsp-labels button {
  flex: 1 1 0; min-width: 0; padding: 2px 0; border: 0; background: none; cursor: pointer;
  color: var(--txt-3); font: inherit; font-size: 11.5px; font-variant-numeric: tabular-nums; text-align: center;
}
@media (hover: hover) and (pointer: fine) { .vsp-labels button:hover { color: var(--txt); } }
.vsp-labels button.on { color: var(--txt); font-weight: 500; }
.vsp-track {
  position: relative; height: 4px; margin: 0 11px; border-radius: 6px; background: rgba(255, 255, 255, .16);
  cursor: pointer; touch-action: none; outline: none;
}
.vsp-track::before { content: ''; position: absolute; left: -11px; right: -11px; top: -12px; bottom: -12px; }
.vsp-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 6px; background: var(--accent); pointer-events: none; }
.vsp-tick { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: rgba(255, 255, 255, .22); pointer-events: none; }
.vsp-thumb {
  position: absolute; top: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 4px;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); pointer-events: none; transition: left .08s;
}
.vsp-track:focus-visible .vsp-thumb { box-shadow: 0 0 0 3px rgba(145, 132, 217, .5); }
/* Fullscreen API chỉ set kích thước mặc định cho element được yêu cầu — .lb-body vốn dùng
   grid co theo cha, cần ép 100% rõ ràng để video lấp đầy đúng màn hình vật lý (xem
   fsTarget trong createVideoBar(), thread.js). .panel là CON của #albBody/#lbBody (không
   phải sibling như .lb-head) nên Fullscreen API vẫn hiện nó ra — phải ép ẩn tay + đưa cột
   grid về 1 cột full width (ghi đè cả .with-panel đang mở, !important vì đang đấu specificity
   với class đó). Hàng thứ 2 (vốn dành riêng cho .vscrub) cũng bỏ luôn — .vscrub chuyển sang
   position:absolute đè lên đáy .stage (như Vimeo/YouTube) thay vì chiếm hẳn 1 hàng, không thì
   video bị đẩy lên trên, chừa khoảng trống dưới cho thanh — xem quy tắc .vscrub bên dưới. */
#albBody:fullscreen, #lbBody:fullscreen,
#albBody:-webkit-full-screen, #lbBody:-webkit-full-screen {
  width: 100%; height: 100%; background: #000; position: relative;
  grid-template-columns: minmax(0, 1fr) 0 !important;
  grid-template-rows: minmax(0, 1fr) !important;
}
#albBody:fullscreen .panel, #lbBody:fullscreen .panel,
#albBody:-webkit-full-screen .panel, #lbBody:-webkit-full-screen .panel {
  display: none !important;
}
/* Không cho zoom khi toàn màn hình (khoá thật ở zoom.setEnabled(false), xem admin.js/share.js)
   nên nút +/-/% cũng ẩn theo, đỡ hiện nút bấm vô tác dụng. */
#albBody:fullscreen .zoombar, #lbBody:fullscreen .zoombar,
#albBody:-webkit-full-screen .zoombar, #lbBody:-webkit-full-screen .zoombar {
  display: none !important;
}
/* Ảnh/video sát viền màn hình thật (không còn margin 20px cố định của chế độ xem thường) —
   letterbox còn lại chỉ do đúng tỉ lệ khung hình gốc, giống mọi trình phát toàn màn hình chuẩn. */
#albBody:fullscreen .stage img, #lbBody:fullscreen .stage img,
#albBody:-webkit-full-screen .stage img, #lbBody:-webkit-full-screen .stage img,
#albBody:fullscreen .stage video, #lbBody:fullscreen .stage video,
#albBody:-webkit-full-screen .stage video, #lbBody:-webkit-full-screen .stage video {
  inset: 0; max-width: 100%; max-height: 100%; border-radius: 0;
}
/* Thanh điều khiển thành lớp phủ bán trong suốt đè lên đáy video, không chiếm không gian
   riêng trong layout nữa — video luôn lấp đầy trọn khung hình toàn màn hình. Nền mờ dần lên
   trên để chữ/nút vẫn đọc được trên nền video sáng, tự ẩn theo scheduleIdle() trong thread.js. */
#albBody:fullscreen .vscrub, #lbBody:fullscreen .vscrub,
#albBody:-webkit-full-screen .vscrub, #lbBody:-webkit-full-screen .vscrub {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5; border-top: none;
  padding: 44px 16px 14px;
  background: linear-gradient(to top, rgba(0, 0, 0, .82) 0%, rgba(0, 0, 0, .5) 60%, transparent 100%);
}
/* Tự ẩn thanh điều khiển sau vài giây không rê chuột khi đang toàn màn hình (xem
   wakeControls()/scheduleIdle() trong createVideoBar(), thread.js) — pointer-events: none để
   lớp đã mờ hẳn không còn chặn click xuyên xuống video/lớp vẽ bên dưới. */
.vscrub { transition: opacity .25s ease; }
.vscrub.vs-idle { opacity: 0; pointer-events: none; }
.vs-cursor-idle, .vs-cursor-idle * { cursor: none !important; }

.cmt { margin-bottom: 18px; border-radius: 8px; transition: background-color .3s; }
.cmt.flash { background-color: rgba(145, 132, 217, .18); }
.cmt .who {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; column-gap: 9px; margin-bottom: 7px;
}
.cmt .who > .avatar { grid-column: 1; }
.cmt-author {
  grid-column: 2; min-width: 0; display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.cmt-author b { min-width: 0; line-height: 1.3; overflow-wrap: anywhere; }
.cmt-author .chip { flex: none; }
.cmt .who > .when { grid-column: 3; text-align: right; white-space: nowrap; }
.edited-tag { font-style: italic; }
.avatar {
  width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;
  font-size: 11px; font-weight: 700; background: var(--accent); color: #fff; flex: none;
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.cmt .body {
  white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
  background: var(--bg-2); padding: 8px 10px; border-radius: 8px;
}
.cmt .body a.lnk { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .cmt .body a.lnk:hover { color: #fff; } }
.cmt .when { font-size: 11.5px; color: var(--txt-3); }
/* Nhận xét nội bộ — chỉ studio thấy được (đã lọc từ server), viền vàng nhạt cho dễ
   nhận ra giữa các nhận xét công khai khi lướt nhanh danh sách. */
.cmt.internal .body { border-left: 2px solid var(--warn); }

.filmstrip {
  display: flex; gap: 6px; overflow-x: auto; padding: 8px 12px;
  border-top: 1px solid var(--line-soft); background: var(--bg-1);
}
.filmstrip img {
  height: 54px; width: 54px; object-fit: cover; border-radius: 5px;
  border: 2px solid transparent; cursor: pointer; opacity: .55; flex: none;
}
.filmstrip img.cur { border-color: var(--accent); opacity: 1; }
.lb:not(.strip-on) .filmstrip { display: none; }
.viewer-toggle {
  width: 34px; min-width: 34px; padding: 0; display: inline-grid; place-items: center;
  color: var(--txt-3);
}
.filmstrip-trigger { display: inline-flex; align-items: center; justify-content: center; }
.filmstrip-trigger svg { display: block; flex: none; margin: 0; transform: none; }
.viewer-toggle.on { color: var(--ink); background: rgba(145, 132, 217, .16); }
/* ---------- thanh zoom ---------- */
.zoombar {
  position: absolute; left: 16px; bottom: 16px; z-index: 3;
  display: flex; align-items: center; gap: 2px; padding: 4px;
  background: rgba(22, 24, 38, .88); border: 1px solid var(--line);
  border-radius: 10px; backdrop-filter: blur(8px);
}
.zoombar button {
  width: 26px; height: 26px; border: none; background: transparent;
  border-radius: 6px; cursor: pointer; color: var(--txt-2); font-size: 15px; line-height: 1;
}
@media (hover: hover) and (pointer: fine) { .zoombar button:hover { background: var(--bg-3); color: var(--txt); } }
.zoombar .pct {
  min-width: 46px; text-align: center; font-size: 12px;
  color: var(--txt-2); cursor: pointer; user-select: none;
}
@media (hover: hover) and (pointer: fine) { .zoombar .pct:hover { color: var(--txt); } }

/* ---------- bút vẽ đánh dấu ---------- */
.drawbar { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
.swatch {
  width: 20px; height: 20px; border-radius: 6px; cursor: pointer;
  border: 2px solid transparent; box-shadow: 0 0 0 1px rgba(255, 255, 255, .18) inset;
}
.swatch.on { border-color: #fff; }
.pen {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  border: 1px solid var(--line); background: var(--bg-3); border-radius: 8px;
  cursor: pointer; font-size: 12.5px;
}
.pen.on { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Chọn kiểu vẽ (Bút/Vuông/Tròn/Mũi tên) — bấm nút bút mở bảng chọn nhỏ, giống chọn cọ */
.tool-pick { position: relative; }
/* outline mặc định của trình duyệt di động khi chạm vào nút khiến nó trông như đang
   "chọn" giống ô màu bên cạnh — tắt hẳn, viền tím chỉ nên hiện ở lựa chọn đang bật
   trong bảng chọn kiểu vẽ (.tool-pop button.on), không phải ở chính nút bấm mở bảng. */
/* .btn.sm (2 class) ưu tiên cao hơn .tbtn (1 class) nếu chỉ viết ".tbtn" suông —
   padding 0 10px của nó đè mất, ép icon vào khung còn vài px. Viết ".btn.tbtn" cho
   ngang độ ưu tiên, thắng nhờ đứng sau trong file. */
.btn.tbtn { padding: 0; width: 28px; justify-content: center; outline: none; -webkit-tap-highlight-color: transparent; }
.tool-pop {
  position: absolute; left: 0; bottom: 36px; z-index: 10;
  display: flex; gap: 2px; padding: 4px;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
}
.tool-pop button {
  display: grid; place-items: center; width: 28px; height: 28px;
  border: none; background: transparent; border-radius: 6px; cursor: pointer; color: var(--txt-2);
  outline: none; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) { .tool-pop button:hover { background: var(--bg-3); } }
.tool-pop button.on { background: var(--accent); color: #fff; }

/* Thanh công cụ vẽ mở — chia thành 3 cụm rõ ràng thay vì popup chồng lên composer:
   kiểu nét | màu | lịch sử. Các nút hình luôn hiện ngay khi người dùng bật Vẽ. */
.draw-tool-group, .draw-color-group, .draw-history-group {
  display: inline-flex; align-items: center; justify-content: center; gap: 3px;
}
.draw-color-group { gap: 5px; }
.draw-separator { width: 1px; height: 22px; flex: none; background: var(--line); }
.tool-pop.tool-inline {
  position: static; display: inline-flex; gap: 2px; padding: 0;
  border: 0; border-radius: 0; background: transparent; box-shadow: none;
}
.tool-pop.tool-inline button { width: 28px; height: 28px; border-radius: 7px; }
.draw-history-group .btn {
  width: 28px; height: 28px; min-width: 28px; padding: 0;
  display: inline-grid; place-items: center; border-radius: 7px;
}

/* Vẽ dùng chung một hàng với đính kèm/emoji, và bảng màu không nằm ở đây: bấm Vẽ là
   chuyển hẳn sang lớp phủ toàn khung, JS bê nguyên cụm .dtools sang đó. Nằm trong
   thanh soạn nhận xét thì cụm này luôn ẩn. */
.drawbar .dtools { display: none; }
/* Desktop vẽ tại chỗ: bảng màu hiện ngay trong thanh soạn, không có lớp phủ nào cả.
   Trên điện thoại lúc đang vẽ thì cả khung nhận xét bị ẩn nên luật này không đụng tới. */
.drawbar.drawing .dtools { display: flex; align-items: center; gap: 8px; }

/* Mở chế độ vẽ: thanh công cụ trượt vào nhẹ, các cụm nối tiếp nhau vài chục ms.
   Chỉ animate opacity/transform để không làm đổi kích thước canvas hay lệch nét vẽ. */
@keyframes draw-tools-in {
  from { opacity: 0; transform: translateX(-8px) scale(.985); }
  to { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes draw-control-in {
  from { opacity: 0; transform: translateY(4px) scale(.92); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.drawbar.drawing .dtools,
.drawmode:not([hidden]) .dm-tools .dtools {
  transform-origin: left center;
  animation: draw-tools-in .24s var(--ease-out) both;
}
.drawbar.drawing .dtools > *,
.drawmode:not([hidden]) .dm-tools .dtools > * {
  animation: draw-control-in .2s var(--ease-out) both;
}
.drawbar.drawing .dtools > :nth-child(2),
.drawmode:not([hidden]) .dm-tools .dtools > :nth-child(2) { animation-delay: 35ms; }
.drawbar.drawing .dtools > :nth-child(3),
.drawmode:not([hidden]) .dm-tools .dtools > :nth-child(3) { animation-delay: 70ms; }
.drawbar.drawing .dtools > :nth-child(4),
.drawmode:not([hidden]) .dm-tools .dtools > :nth-child(4) { animation-delay: 105ms; }
.comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn {
  animation: draw-control-in .18s var(--ease-out) both;
}
@media (prefers-reduced-motion: reduce) {
  .drawbar.drawing .dtools,
  .drawbar.drawing .dtools > *,
  .drawmode:not([hidden]) .dm-tools .dtools,
  .drawmode:not([hidden]) .dm-tools .dtools > *,
  .comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn,
  .comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn { animation: none; }
}

/* Chế độ Vẽ là một trạng thái tập trung như Frame.io: ô nhập vẫn ở trên, còn hàng dưới
   chỉ có kiểu nét, màu, hoàn tác và huỷ. Nút Vẽ, ghim, tệp, emoji, quyền xem và Gửi
   tạm ẩn; thoát chế độ vẽ thì toàn bộ composer tự trở lại như cũ. */
.comment-composer .drawbar.drawing:has(.tool-inline) {
  width: 100%; min-height: 32px; margin-right: 0;
  display: flex; align-items: center; flex-wrap: nowrap;
}
.comment-composer .drawbar.drawing .dtools:has(.tool-inline) {
  display: flex; flex: 1 1 auto; min-width: 0; align-items: center; justify-content: flex-start;
  gap: 3px; flex-wrap: nowrap;
}
.comment-composer .drawbar.drawing .draw-tool-group,
.comment-composer .drawbar.drawing .draw-color-group,
.comment-composer .drawbar.drawing .draw-history-group {
  height: 32px; padding: 0; border: 0; border-radius: 0; background: transparent;
}
.comment-composer .drawbar.drawing .draw-separator { display: block; height: 22px; }
.comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn {
  display: inline-grid; flex: none; width: 28px; min-width: 28px; height: 32px; padding: 0;
  border: 0; background: transparent; box-shadow: none; color: var(--txt-2);
}
@media (hover: hover) and (pointer: fine) { .comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn:hover,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn:hover {
  background: var(--bg-3); color: var(--txt); box-shadow: none; transform: none;
} }
.comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn svg,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn svg,
.comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn .pen-label,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn .pen-label { display: none; }
.comment-composer .drawbar.drawing:has(.tool-inline) > #aPenBtn::before,
.comment-composer .drawbar.drawing:has(.tool-inline) > #penBtn::before {
  content: ''; width: 8px; height: 8px; margin-left: 3px;
  border-left: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
}
.comment-composer .drawbar.drawing:has(.tool-inline) > .pen.has-draw::after { display: none; }
.comment-composer .drawbar.drawing .tool-pop.tool-inline button,
.comment-composer .drawbar.drawing .draw-history-group .btn {
  width: 26px; min-width: 26px; height: 28px;
}
.comment-composer .drawbar.drawing > .pen:not(#aPenBtn):not(#penBtn),
.comment-composer .drawbar.drawing > #aAttachBtn,
.comment-composer .drawbar.drawing > #attachBtn,
.comment-composer .drawbar.drawing > #aEmojiBtn,
.comment-composer .drawbar.drawing > #emojiBtn,
.comment-composer .drawbar.drawing > .tcbtn { display: none; }
.comment-composer:has(.drawbar.drawing) .compose-actions,
.comment-composer:has(.drawbar.drawing) > [id$="AttachList"] { display: none; }

/* Nét đã vẽ xong đang chờ gửi kèm: nút Vẽ đổi màu + gắn số nét cho khỏi quên */
.pen.has-draw { border-color: var(--accent); color: var(--ink); }
.pen.has-draw::after {
  content: attr(data-n); margin-left: 2px; min-width: 15px; height: 15px; padding: 0 4px;
  border-radius: 6px; background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 700; display: grid; place-items: center;
}

/* ---------- emoji + tệp đính kèm ---------- */
.emoji-pop {
  position: absolute; left: 0; bottom: 36px; z-index: 10;
  width: 268px; max-height: 210px; overflow-y: auto; padding: 8px;
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
}
.emoji-pop span {
  display: grid; place-items: center; height: 28px;
  font-size: 18px; border-radius: 6px; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .emoji-pop span:hover { background: var(--bg-3); } }

/* Chọn Công khai/Nội bộ khi gửi nhận xét — bảng rớt lên trên
   dưới nút, giống tool-pop/emoji-pop nhưng rộng hơn để chứa mô tả từng lựa chọn. */
.vis-pop {
  position: absolute; right: 0; bottom: 34px; z-index: 10;
  width: 260px; padding: 6px;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
}
.vis-opt {
  display: flex; align-items: flex-start; gap: 9px; width: 100%;
  padding: 8px; border: none; background: transparent; border-radius: 8px;
  cursor: pointer; color: var(--txt-1); text-align: left;
}
@media (hover: hover) and (pointer: fine) { .vis-opt:hover { background: var(--bg-3); } }
.vis-opt svg:first-child { flex: none; margin-top: 2px; color: var(--txt-2); }
.vis-txt { flex: 1; display: flex; flex-direction: column; gap: 1px; font-size: 13px; }
.vis-txt .dim { font-size: 11px; }
.vis-check { flex: none; margin-top: 2px; opacity: 0; color: var(--accent); }
.vis-opt.on .vis-check { opacity: 1; }

.mention-pop {
  position: absolute; left: 0; right: 0; bottom: 100%; margin-bottom: 6px; z-index: 10;
  max-height: 180px; overflow-y: auto; padding: 4px;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
}
.mention-pop .mi {
  padding: 6px 9px; border-radius: 6px; font-size: 13px; cursor: pointer;
}
.mention-pop .mi.on, .mention-pop .mi:hover { background: var(--bg-3); }

.file-chip {
  display: flex; align-items: center; gap: 7px; margin-top: 6px;
  padding: 5px 8px; background: var(--bg-2); border: 1px solid var(--line-soft);
  border-radius: 8px; font-size: 12px;
}
.file-chip .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-chip .rm { cursor: pointer; color: var(--txt-3); padding: 0 2px; }
@media (hover: hover) and (pointer: fine) { .file-chip .rm:hover { color: var(--danger); } }
.file-chip.up { opacity: .55; }
@media (hover: hover) and (pointer: fine) { a.file-chip:hover { border-color: var(--line); background: var(--bg-3); } }

/* Bàn tay đồng nhất cho mọi góp ý khi rê chuột, có đánh dấu/mốc thời gian hay không —
   trước đây chỉ .seekable (có nét vẽ hoặc mốc thời gian) mới có cursor:pointer, góp ý
   thường (không mốc/không nét vẽ) rơi về cursor mặc định "auto", trình duyệt tự hiện
   con trỏ chữ (I-beam) khi rê qua đoạn text trong .body — trông như đang có 2 kiểu trỏ
   khác nhau tuỳ góp ý, không đồng nhất. */
.cmt { cursor: pointer; }
.cmt.has-draw .body { border-left: 2px solid var(--accent); }
.cmt.showing .body { background: var(--bg-3); }
.draw-tag { font-size: 11px; color: var(--txt-3); margin-top: 3px; }

.cmt.reply { margin-left: 22px; padding-left: 10px; border-left: 1px solid var(--line-soft); }
.avatar.studio { background: linear-gradient(140deg, #ff7a45, var(--accent)); }

/* Sửa nhận xét tại chỗ: khối gọn, hành động và chế độ hiển thị nằm cùng một hàng. */
.cmt .body.cmt-editing {
  padding: 8px; border: 1px solid var(--line); background: var(--bg-2);
  white-space: normal;
}
.cmt-editing .cmt-edit-box {
  display: block; width: 100%; min-height: 48px; max-height: 120px; padding: 7px 9px;
  resize: vertical; border-color: var(--line-soft); background: var(--bg-1);
}
.cmt-edit-footer { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.cmt-edit-vis {
  display: inline-flex; padding: 2px; border: 1px solid var(--line-soft);
  border-radius: 8px; background: var(--bg-1);
}
.cmt-edit-vis button {
  border: 0; padding: 5px 8px; border-radius: 6px; background: transparent;
  color: var(--txt-3); font-size: 11.5px; cursor: pointer;
}
.cmt-edit-vis button.on { background: var(--bg-3); color: var(--txt-1); }
.cmt-edit-acts { display: flex; justify-content: flex-end; gap: 6px; margin-left: auto; }
.cmt-edit-acts .btn { min-height: 28px; padding: 4px 9px; }

/* Đã đánh dấu hoàn thành — phương án A (2026-10-11): bỏ vạch xanh trước nội dung (dễ lẫn với vạch
   "có nét vẽ"); dấu ✓ xanh LUÔN hiện ở góc phải hàng tên (.cmt-resolve-btn.on, xem bên dưới) + nội
   dung mờ nhẹ. Chưa xử lý: góc đó trống, rê chuột mới hiện ô tích; màn cảm ứng thì hiện mờ sẵn. */
.cmt.resolved .body { color: var(--txt-2); }

/* Hàng nút "Thêm cảm xúc" / "Đánh dấu hoàn thành" — chỉ hiện khi rê chuột vào góp ý,
   trừ nút đánh dấu hoàn thành khi ĐANG ở trạng thái .on thì luôn hiện (không cần rê chuột)
   để còn thấy được góp ý nào đã xong khi lướt nhanh cả danh sách. */
.react-wrap { position: relative; display: inline-flex; }
.cmt-react-btn, .cmt-resolve-btn {
  width: 22px; height: 22px; padding: 0; border: none; background: transparent; border-radius: 6px;
  color: var(--txt-3); cursor: pointer; display: grid; place-items: center;
  opacity: 0; transition: opacity .12s, color .12s, background-color .12s;
}
.cmt:hover .cmt-react-btn, .cmt:hover .cmt-resolve-btn { opacity: 1; }
@media (hover: hover) and (pointer: fine) { .cmt-react-btn:hover, .cmt-resolve-btn:hover { background: var(--bg-3); color: var(--txt); } }
.cmt-resolve-btn.on { opacity: 1; color: var(--ok); }
@media (hover: hover) and (pointer: fine) { .cmt-resolve-btn.on:hover { background: rgba(47, 191, 113, .14); color: var(--ok); } }
.cmt-emoji-pop { top: 24px; bottom: auto; right: 0; left: auto; }

/* Chip cảm xúc đã thả lên góp ý — nhóm theo emoji, viền tím nếu chính mình đã thả cái đó */
.cmt-reactions { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.reaction-chip-wrap { position: relative; display: inline-flex; }
.react-chip {
  display: flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 6px;
  background: var(--bg-2); border: 1px solid var(--line-soft); font-size: 12.5px; line-height: 1.6;
  color: var(--txt-2); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .react-chip:hover { border-color: var(--line); } }
.react-chip.mine { border-color: var(--accent); background: rgba(145, 132, 217, .12); color: var(--txt); }
.react-chip > span { font-size: 11px; color: var(--txt-3); }
.reaction-people-pop {
  display: none; position: absolute; left: 0; bottom: calc(100% + 7px); z-index: 40;
  min-width: 190px; max-width: 260px; padding: 8px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--bg-3); box-shadow: var(--shadow); color: var(--txt-1);
}
.reaction-chip-wrap:hover .reaction-people-pop,
.reaction-chip-wrap:focus-within .reaction-people-pop,
.reaction-chip-wrap.show .reaction-people-pop { display: block; }
.reaction-people-pop > b { display: block; padding: 2px 4px 7px; font-size: 12px; }
.reaction-person { display: flex; align-items: center; gap: 8px; padding: 4px; font-size: 12.5px; }
.reaction-avatar {
  width: 24px; height: 24px; border-radius: 6px; overflow: hidden; flex: none;
  display: grid; place-items: center; background: var(--accent); color: #fff;
  font-size: 9px; font-weight: 700;
}
.reaction-avatar img { width: 100%; height: 100%; object-fit: cover; }

.reply-to {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  padding: 5px 9px; background: var(--bg-2); border-left: 2px solid var(--accent);
  border-radius: 0 8px 8px 0; font-size: 12px; color: var(--txt-2);
}
.reply-to .x { cursor: pointer; color: var(--txt-3); }
@media (hover: hover) and (pointer: fine) { .reply-to .x:hover { color: var(--txt); } }

/* ---------- tổng hợp phản hồi ---------- */
.feedback-sort { display: flex; align-items: center; gap: 8px; margin-left: auto; color: var(--txt-3); font-size: 12px; }
.feedback-sort .input { width: 174px; height: 36px; padding-block: 0; }
.feedback-list { display: grid; gap: 14px; padding: 14px 0 28px; }
.feedback-card {
  display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: 12px;
  padding: 12px; background: var(--bg-1); border: 1px solid var(--line-soft);
  border-radius: 12px;
}
.fb-media {
  /* Khung vuông 1:1, ảnh hiện vừa khung (không cắt) — giống lưới tệp ở chế độ Tỷ lệ vuông + Vừa khung */
  position: relative; align-self: start; width: 116px; aspect-ratio: 1 / 1; padding: 0;
  overflow: hidden; border: 1px solid var(--line-soft); border-radius: 10px;
  background: var(--bg-2); cursor: pointer; color: #fff;
}
.fb-thumb { display: block; width: 100%; height: 100%; object-fit: contain; transition: transform .18s, opacity .18s; }
.fb-open-hint {
  position: absolute; left: 50%; bottom: 8px; transform: translate(-50%, 4px);
  padding: 4px 8px; border-radius: 6px; background: rgba(10, 11, 15, .78);
  font-size: 11px; font-weight: 600; white-space: nowrap; opacity: 0; transition: opacity .18s, transform .18s;
}
.fb-media:hover .fb-thumb { transform: scale(1.025); opacity: .82; }
.fb-media:hover .fb-open-hint { opacity: 1; transform: translate(-50%, 0); }
.fb-main { min-width: 0; }
.fb-card-head { display: flex; align-items: center; gap: 12px; padding: 1px 0 8px; }
.fb-title-wrap { min-width: 0; display: grid; gap: 3px; }
.fb-open {
  max-width: 100%; padding: 0; border: 0; background: none; color: var(--txt);
  font: inherit; font-weight: 650; text-align: left; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) { .fb-open:hover { color: var(--ink); } }
.fb-path { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--txt-3); font-size: 11.5px; }
.fb-summary { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 5px; }
.fb-chip {
  display: inline-flex; align-items: center; gap: 4px; min-height: 22px; padding: 2px 7px;
  border: 1px solid var(--line-soft); border-radius: 6px; background: var(--bg-2);
  color: var(--txt-2); font-size: 11px; white-space: nowrap;
}
.fb-chip svg { width: 12px; height: 12px; }
.fb-chip.marked { width: 24px; padding: 2px; justify-content: center; }
.fb-chip.pending { border-color: rgba(255, 176, 72, .28); color: var(--warn); }
.fb-chip.done { border-color: rgba(47, 191, 113, .28); color: var(--ok); }
.fb-chip.marked { border-color: rgba(145, 132, 217, .36); color: var(--ink); }
.fb-comments { display: grid; }
.fb-comment { margin: 0; padding: 9px 0; border: 0; border-top: 1px solid var(--line-soft); border-radius: 0; background: transparent; }
.fb-comment .who { margin-bottom: 5px; }
.fb-comment .avatar { width: 25px; height: 25px; }
.fb-comment .body { padding: 0; background: transparent; border-radius: 0; color: var(--txt-1); }
.fb-comment.resolved { opacity: .76; }
.fb-comment.resolved .body, .fb-comment.internal .body, .fb-comment.has-draw .body { border-left: 0; }
.fb-who { min-width: 0; display: grid; gap: 1px; }
.fb-who b, .fb-who span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-who span { color: var(--txt-3); font-size: 10.5px; }
.fb-timecode {
  padding: 2px 6px; border-radius: 5px; background: rgba(145, 132, 217, .14);
  color: var(--ink); font: 11px ui-monospace, SFMono-Regular, Menlo, monospace;
}
.fb-comment-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 7px; color: var(--txt-3); font-size: 10.5px; }
.fb-comment-meta > span { display: inline-flex; align-items: center; gap: 4px; }
.fb-comment-meta svg { width: 12px; height: 12px; }
.fb-comment-meta .resolved-tag { color: var(--ok); }
.fb-comment-meta .pending-tag { color: var(--warn); }
.fb-comment-meta .internal-tag { color: #ffd48a; }
.fb-comment .who > .resolved-tag {
  display: grid; place-items: center; width: 20px; height: 20px; border-radius: 6px;
  background: rgba(47, 191, 113, .12); color: var(--ok); font-size: 11px; cursor: help;
}
.feedback-empty {
  min-height: 220px; display: grid; place-content: center; justify-items: center; gap: 5px;
  padding: 30px; border: 1px dashed var(--line); border-radius: 14px; color: var(--txt-3); text-align: center;
}
.feedback-empty b { color: var(--txt-1); font-size: 14px; }
.feedback-empty span { font-size: 12px; }

/* ---------- modal ---------- */
/* z-index phải LỚN HƠN .cmp-overlay (200, xem so sánh phiên bản) — bằng nhau thì phần tử
   nào append vào body SAU thắng, mà .cmp-overlay luôn append sau (JS dựng lúc mở compare)
   nên hộp thoại (vd "Tạo link chia sẻ" mở từ nút trong .lb-head lúc đang so sánh) sẽ bị
   compare đè lên, mở ra coi như vô hình — bug thực tế đã gặp. */
.mask { position: fixed; inset: 0; background: rgba(4, 5, 8, .72); display: none; place-items: center; z-index: 210; padding: 20px; }
.mask.open { display: grid; }
.modal {
  width: min(520px, 100%); background: var(--bg-1); border: 1px solid var(--line);
  border-radius: 14px; box-shadow: var(--shadow); overflow: hidden;
}
.modal.wide { width: min(860px, 100%); }
.modal h2 { margin: 0; padding: 16px 18px; font-size: 16px; border-bottom: 1px solid var(--line-soft); }
.modal .m-body { padding: 18px; max-height: 65vh; overflow-y: auto; }
.modal .m-foot { padding: 12px 18px; border-top: 1px solid var(--line-soft); display: flex; gap: 10px; justify-content: flex-end; }
.comment-identity-form { display: grid; gap: 12px; }
.comment-identity-form p { margin: 0; line-height: 1.5; }
.comment-identity-form .input { height: 44px; font-size: 15px; }

/* Góp ý / Báo lỗi (menu tài khoản) — gửi thẳng cho người vận hành, kèm ảnh chụp màn hình. */
.modal.feedback-modal { width: min(560px, 100%); }
.fb-lead { margin: 0 0 16px; line-height: 1.5; font-size: 12.5px; }
.fb-kind { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px; }
.fb-kind-btn {
  display: block; padding: 10px 12px; text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg-2); color: var(--txt-2);
}
.fb-kind-btn b { display: block; font-size: 13px; font-weight: 600; }
.fb-kind-btn small { display: block; margin-top: 2px; color: var(--txt-3); font-size: 11px; }
.fb-kind-btn.on { border-color: var(--accent); background: var(--bg-3); color: var(--txt); }
.fb-field { margin-bottom: 14px; }
.fb-field > span { display: block; margin-bottom: 6px; color: var(--txt-2); font-size: 12.5px; }
.fb-field > span small { margin-left: 5px; font-size: 10.5px; }
.fb-files { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 9px; }
.fb-files[hidden] { display: none; }
.fb-file { position: relative; width: 74px; height: 74px; border-radius: 9px; overflow: hidden; border: 1px solid var(--line); }
.fb-file img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fb-file-x {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; border: 0; cursor: pointer;
  border-radius: 6px; background: rgba(8, 9, 12, .78); color: #fff; font-size: 11px; line-height: 1;
}
.fb-pick-row { display: flex; align-items: center; gap: 9px; }
.fb-paste-hint { font-size: 11px; }
@media (max-width: 640px) {
  .fb-kind { grid-template-columns: 1fr; }
  .fb-paste-hint { display: none; }
}

/* Thành viên dự án — thứ bậc gọn, tách danh sách hiện tại khỏi thao tác mời. */
.modal.invite-modal { width: min(600px, 100%); }
.invite-dialog { display: grid; gap: 20px; }
.invite-context {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding-bottom: 16px; border-bottom: 1px solid var(--line-soft);
}
.invite-context-label {
  flex: none; padding: 3px 8px; border-radius: 6px; background: var(--bg-2);
  color: var(--txt-3); font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
}
.invite-context strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 600; }
.invite-section { display: grid; gap: 9px; }
.invite-section-title { color: var(--txt-2); font-size: 12px; font-weight: 600; }
.invite-empty { padding: 10px 0; color: var(--txt-3); font-size: 13px; }
.invite-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; }
.invite-form .field { min-width: 0; margin: 0; }
.invite-email { flex: 1 1 220px; }
.invite-role { flex: 1 1 150px; }
.invite-form .field > span { color: var(--txt-3); font-size: 11.5px; }
.invite-form .input, .invite-submit { height: 38px; }
.invite-submit { flex: 0 0 auto; white-space: nowrap; }
.invite-help { margin: -1px 0 0; color: var(--txt-3); font-size: 11.5px; line-height: 1.45; }
.modal.invite-modal .m-foot { padding: 10px 18px; }

/* Thành viên Workspace — hộp thoại cộng tác riêng, không trộn cài đặt và thanh toán. */
.modal.workspace-members-modal { width: min(700px, 100%); }
.workspace-members-dialog { gap: 18px; }
.workspace-members-dialog .invite-context { padding-bottom: 14px; }
.workspace-members-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.workspace-members-title .chip { color: var(--txt-2); }
.workspace-members-dialog #wsMembers .tbl { table-layout: fixed; }
.workspace-members-dialog #wsMembers .tbl td:first-child { width: 44%; }
.workspace-members-dialog #wsMembers .tbl td:nth-child(2) { width: 26%; }
.workspace-members-dialog #wsMembers .tbl td:last-child { width: 30%; text-align: right; }
.workspace-members-dialog #wsMembers .tbl td { vertical-align: middle; }
.workspace-members-dialog #wsMembers .chip { white-space: nowrap; }
.pending-invite-actions { display: flex; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }
/* Dòng lời mời chưa được nhận — nhạt hơn thành viên thật để phân biệt ngay từ xa. */
.pending-invitation-row .ws-avatar { color: var(--txt-3); }
.pending-invitation-row .ws-avatar svg { width: 14px; height: 14px; }
.workspace-members-dialog #wsMembers .tbl tr:last-child td { border-bottom: 0; }
.modal.workspace-members-modal .m-foot { padding: 10px 18px; }

/* Chia sẻ — phân tách ngữ cảnh, thông tin liên kết và quyền truy cập để dễ quét. */
.modal.share-modal { width: min(560px, 100%); }
.modal.share-modal .m-body { padding: 0; max-height: calc(100dvh - 160px); }
.share-dialog { display: grid; }
.share-scope {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  margin: 18px; padding: 12px 14px; border: 1px solid var(--line-soft);
  border-radius: 10px; background: var(--bg-2);
}
.share-scope-icon {
  width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  border-radius: 9px; background: rgba(145, 132, 217, .16); color: var(--ink);
}
.share-scope-icon svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.share-scope > div { min-width: 0; display: grid; gap: 2px; }
.share-scope span:not(.share-scope-icon) { color: var(--txt-3); font-size: 11px; font-weight: 600; letter-spacing: .045em; text-transform: uppercase; }
.share-scope strong { color: var(--txt); font-size: 13.5px; font-weight: 600; overflow-wrap: anywhere; }
.share-section { padding: 0 18px 18px; }
.share-section + .share-section { padding-top: 18px; border-top: 1px solid var(--line-soft); }
.share-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.share-section-head strong { font-size: 13px; font-weight: 600; }
.share-section-head > span { color: var(--txt-3); font-size: 11.5px; text-align: right; }
.share-dialog label.field { margin-bottom: 12px; }
.share-dialog label.field > span { color: var(--txt-2); font-size: 12px; }
.share-dialog label.field > span small { margin-left: 5px; color: var(--txt-3); font-size: 10.5px; font-weight: 400; }
.share-dialog .input { height: 40px; }
.share-field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.share-field-grid label.field { margin: 0; }
.share-modal #sExp { appearance: textfield; -moz-appearance: textfield; }
.share-modal #sExp::-webkit-inner-spin-button,
.share-modal #sExp::-webkit-outer-spin-button { margin: 0; appearance: none; -webkit-appearance: none; }
.share-options { overflow: hidden; border: 1px solid var(--line-soft); border-radius: 10px; }
.share-option {
  min-height: 58px; padding: 10px 12px; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  cursor: pointer; background: rgba(255, 255, 255, .012);
}
.share-option + .share-option { border-top: 1px solid var(--line-soft); }
@media (hover: hover) and (pointer: fine) { .share-option:hover { background: var(--bg-2); } }
.share-option > span { min-width: 0; display: grid; gap: 2px; }
.share-option b { color: var(--txt); font-size: 12.5px; font-weight: 500; }
.share-option small { color: var(--txt-3); font-size: 11px; line-height: 1.35; }
.share-option input[type="checkbox"] { width: 18px; height: 18px; flex: none; accent-color: var(--accent); }
.modal.share-modal .m-foot { padding: 11px 18px; }
.modal.share-modal:has(.share-min) { width: min(440px, 100%); }
/* Hộp thoại chia sẻ tối giản (2026-09-27): phạm vi · email · 3 công tắc · "Mật khẩu & thời hạn" thu gọn */
.share-min { padding: 18px; gap: 16px; }
.share-min .share-scope { margin: 0; }
.share-min label.field { margin: 0; }
.share-toggles { display: grid; }
.share-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 10px 0; cursor: pointer; font-size: 13.5px; color: var(--txt);
}
.share-toggle + .share-toggle { border-top: 1px solid var(--line-soft); }
.share-toggle .appearance-switch { flex: none; }
.share-more summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 6px;
  color: var(--txt-2); font-size: 13px; user-select: none;
}
.share-more summary::-webkit-details-marker { display: none; }
.share-more summary::before {
  content: ''; width: 6px; height: 6px; border: solid currentColor; border-width: 0 1.5px 1.5px 0;
  transform: rotate(-45deg); transition: transform .15s; margin-right: 2px;
}
.share-more[open] summary::before { transform: rotate(45deg); }
@media (hover: hover) and (pointer: fine) { .share-more summary:hover { color: var(--txt); } }
.share-more .share-field-grid { margin-top: 12px; }

/* ---------- gate (màn hình nhập mật khẩu) ---------- */
.gate { min-height: 100dvh; display: grid; place-items: center; padding: 24px; }
.gate-language { position: fixed; z-index: 120; top: max(16px, env(safe-area-inset-top)); right: 18px; }
.language-select {
  min-width: 116px; height: 38px; padding: 0 32px 0 12px; border: 1px solid var(--line); border-radius: 9px;
  color: var(--txt-1); font: inherit; cursor: pointer;
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background: var(--bg-1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12' fill='none' stroke='%239aa1b1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center;
  background-size: 12px 12px;
}
.gate-box { width: min(400px, 100%); background: var(--bg-1); border: 1px solid var(--line); border-radius: 16px; padding: 30px; box-shadow: var(--shadow); }
.gate-box .brand { justify-content: center; margin-bottom: 6px; font-size: 16px; }
.gate-box h1 {
  text-align: center; font-size: 19px; margin: 12px 0 4px;
  /* tên file dài không được tràn ra khỏi hộp */
  overflow-wrap: anywhere; word-break: break-word;
}
.gate-box p.sub { text-align: center; color: var(--txt-2); margin: 0 0 22px; }
.gate-box .link { color: var(--accent); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .gate-box .link:hover { text-decoration: underline; } }
.err { color: var(--danger); font-size: 13px; min-height: 18px; margin-top: 4px; }

/* ---------- đăng nhập bằng Google (gate + trang quản trị) ---------- */
.g-greet {
  display: flex; align-items: center; gap: 8px; justify-content: center;
  margin: -8px 0 18px; color: var(--txt-2); font-size: 13.5px;
}
.g-greet img { width: 22px; height: 22px; border-radius: 6px; object-fit: cover; flex: none; }
.gate-or {
  display: flex; align-items: center; gap: 10px; margin: 16px 0;
  color: var(--txt-3); font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
}
.gate-or::before, .gate-or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.g-btn-wrap { display: flex; justify-content: center; }
.g-btn-wrap:empty { display: none; }

/* ---------- thư mục con trong project ---------- */
.crumbs { display: flex; align-items: center; gap: 6px; margin-bottom: 14px; font-size: 13px; flex-wrap: wrap; }
.crumbs .cr { color: var(--txt-2); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .crumbs .cr:hover { color: var(--txt); } }
.crumbs .cr.cur { color: var(--txt); cursor: default; }
.crumbs .sep { color: var(--txt-3); }
/* Hộp thoại "Chuyển tới…" (moveDialog trong admin.js): đường dẫn + danh sách thư mục con bấm để đi vào */
.movepick-crumbs { margin-bottom: 10px; }
.movepick-list {
  display: flex; flex-direction: column; max-height: min(46vh, 360px); overflow-y: auto;
  border: 1px solid var(--line-soft); border-radius: var(--radius); background: var(--bg-1);
}
.movepick-row {
  display: flex; align-items: center; gap: 10px; min-height: 42px; padding: 0 12px;
  color: var(--txt); font-size: 14px; cursor: pointer; transition: background .12s;
}
.movepick-row + .movepick-row { border-top: 1px solid var(--line-soft); }
@media (hover: hover) and (pointer: fine) { .movepick-row:hover { background: var(--bg-2); } }
.movepick-row .fic { flex: none; color: var(--txt-2); }
.movepick-row > span:not(.chev) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.movepick-row .chev { flex: none; color: var(--txt-3); font-size: 18px; line-height: 1; }
.movepick-empty { padding: 18px 12px; color: var(--txt-3); font-size: 13px; text-align: center; }

/* Ô thư mục: ghép tối đa 3 ảnh đầu thành preview */
.tile.folder .ph { position: relative; background: var(--bg-2); }
.mosaic { position: absolute; inset: 0; display: grid; gap: 2px; }
.mosaic.n1 { grid-template-columns: 1fr; }
.mosaic.n2 { grid-template-columns: 2fr 1fr; }
.mosaic.n3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; }
.mosaic.n3 > :first-child { grid-row: span 2; }
/* Selector phải đủ mạnh để thắng `.tile .ph img { opacity: 0 }` của ô ảnh lazy-load,
   nếu không mosaic sẽ tải xong mà vẫn trong suốt. */
.tile.folder .ph .mosaic img {
  width: 100%; height: 100%; object-fit: cover; display: block; opacity: 1;
}
/* ô đại diện cho thư mục con nằm trong mosaic — luôn là ô nhỏ cuối cùng (xem subFolderCell()),
   icon + tên thư mục con đầu tiên + "+N thư mục" */
.mcell-folder {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 6px; min-width: 0; overflow: hidden; text-align: center;
  background: #2f3345; color: var(--txt-2);
}
.mcell-folder .mf-name {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11px; font-weight: 600; color: var(--txt);
}
.mcell-folder .mf-more { font-size: 10px; color: var(--txt-3); white-space: nowrap; }
.mosaic.n1 .mcell-folder .mf-name { font-size: 13px; }
/* tờ trên cùng của thư mục trống/chưa có preview — tối hơn ô thư mục con một chút, icon mờ */
.mcell-folder.mcell-empty { background: #2a2d3d; color: var(--txt-3); }
html[data-theme="light"] .mcell-folder { background: #f1f3f4; }
html[data-theme="light"] .mcell-folder.mcell-empty { background: #e8eaed; }
/* Thư mục có cả ảnh và thư mục con: dải tên thư mục con đè đáy mosaic (xem subFolderStrip()) */
.tile.folder .sub-strip {
  position: absolute; left: 14px; right: 14px; bottom: 12px; z-index: 2;
  display: flex; align-items: center; gap: 6px; padding: 7px 10px;
  border-radius: 0 0 7px 7px; background: rgba(12, 14, 20, .84); color: #fff;
  font-size: 11.5px; pointer-events: none; min-width: 0;
}
.tile.folder .sub-strip .fic { position: static; flex: none; color: #fff; filter: none; }
.tile.folder .sub-strip .mf-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600;
}
.tile.folder .sub-strip .mf-more { flex: none; margin-left: auto; color: rgba(255, 255, 255, .6); white-space: nowrap; }
.tile.folder .mcell-folder .fic { position: static; color: inherit; filter: none; }
.tile.folder .fic {
  position: absolute; left: 8px; top: 8px; z-index: 2; color: #fff;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .8));
}
.tile.folder .ph.empty { display: grid; place-items: center; }
/* Ô thư mục có hình xem trước (nhất là chỉ 1 tệp — ảnh hay thẻ nhạc) dễ bị nhầm là 1 tệp:
   thu hình vào trong như tờ trên cùng của 1 chồng, 2 tờ phía sau ló lên ở mép trên
   (::before + bóng đổ lệch của chính nó — ::after đã dùng cho viền "đã chọn"),
   kèm icon thư mục trước tên ở dòng dưới */
.tile.folder .ph:not(.empty) .mosaic {
  inset: 24px 14px 12px; border-radius: 7px; overflow: hidden; z-index: 1;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .45);
  /* khe 2px giữa các ô ghép phải là 1 màu đồng nhất — trong suốt thì lộ tờ giấy sáng phía sau
     (chỉ cao nửa ô) thành đường chia lúc sáng lúc tối */
  background: #12141c;
}
html[data-theme="light"] .tile.folder .ph:not(.empty) .mosaic { background: #fff; }
.tile.folder .ph:not(.empty)::before {
  content: ''; position: absolute; left: 22px; right: 22px; top: 17px; height: 50%;
  border-radius: 7px; background: #3a3e52;
  box-shadow: 0 -14px 0 -7px #2c2f3f;
}
/* số tờ phía sau = số thứ bên trong: 1 thứ không xếp chồng, 2 thứ chỉ 1 tờ (xem stackDepth()) */
.tile.folder .ph.stack-0::before { content: none; }
.tile.folder .ph.stack-1::before { box-shadow: none; }
.tile.folder .cap-fic .fic { position: static; color: inherit; filter: none; display: block; }
.tile.folder .cap-fic { flex: none; display: flex; color: var(--txt-2); margin-right: 6px; }
.tile.folder .ph.empty .fic { position: static; color: var(--txt-3); filter: none; }
/* Thư mục trống: không có gì để xếp chồng — khung nét đứt, icon mờ + chữ "Trống" */
.tile.folder .ph.empty { grid-auto-flow: row; align-content: center; gap: 6px; }
.tile.folder .ph.empty::before {
  content: ''; position: absolute; inset: 24px 14px 12px; border-radius: 7px;
  border: 1.5px dashed rgba(255, 255, 255, .12);
}
.tile.folder .ph.empty .fic { opacity: .7; }
.tile.folder .ph.empty .empty-lbl { font-size: 12px; color: var(--txt-3); text-align: center; }
html[data-theme="light"] .tile.folder .ph.empty::before { border-color: rgba(28, 29, 41, .16); }
.tile.ctx-on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }

/* Dải phân vùng giữa thư mục và ảnh */
.sec-head {
  display: flex; align-items: center; gap: 8px;
  margin: 4px 0 12px; font-size: 12.5px; color: var(--txt-2);
}
.sec-head .caret {
  width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: 5px; cursor: pointer; color: var(--txt-3);
  transition: transform .15s;
}
@media (hover: hover) and (pointer: fine) { .sec-head .caret:hover { background: var(--bg-2); color: var(--txt); } }
.sec-head .caret.closed { transform: rotate(-90deg); }
.sec { margin-bottom: 26px; }

.dropzone {
  margin-top: 18px; padding: 40px 20px; text-align: center;
  border: 1px dashed var(--line); border-radius: 12px; color: var(--txt-3);
}
.dropzone.over { border-color: var(--accent); color: var(--txt-2); background: rgba(145, 132, 217, .06); }

/* ---------- menu chuột phải ---------- */
.ctxmenu {
  position: fixed; z-index: 300; min-width: 200px; padding: 5px;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
}
.ctx-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px;
}
@media (hover: hover) and (pointer: fine) { .ctx-item:hover { background: var(--bg-3); } }
.ctx-item.danger { color: var(--danger); }
@media (hover: hover) and (pointer: fine) { .ctx-item.danger:hover { background: rgba(232, 149, 154, .1); } }
.ctx-switch {
  position: relative; flex: none; width: 34px; height: 20px; margin-left: auto;
  border: 1px solid #444958; border-radius: 6px; background: #292d37;
  transition: background .16s ease, border-color .16s ease;
}
.ctx-switch > span {
  position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 4px; background: #969cab; box-shadow: 0 1px 2px rgba(0,0,0,.35);
  transition: transform .16s ease, background .16s ease;
}
.ctx-switch.on { border-color: var(--accent); background: var(--accent); }
.ctx-switch.on > span { transform: translateX(14px); background: #fff; }
.ctx-sep { height: 1px; margin: 5px 6px; background: var(--line-soft); }
.ctx-head {
  padding: 7px 10px 5px; font-size: 11.5px; color: var(--txt-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 240px;
}
.ctx-ws-summary {
  display: block; width: calc(100% - 8px); margin: 2px 4px 6px; padding: 10px;
  border: 1px solid var(--line-soft); border-radius: 8px; background: var(--bg-1);
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .ctx-ws-summary:hover { border-color: var(--line); background: var(--bg-2); } }
.ctx-ws-summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctx-ws-plan, .ctx-ws-storage {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.ctx-ws-plan { margin-bottom: 9px; color: var(--txt-2); font-size: 12px; }
.ctx-ws-plan strong {
  padding: 3px 7px; border-radius: 6px; color: #b7b2ff;
  background: rgba(145, 132, 217, .16); font-size: 11px; font-weight: 600;
}
.ctx-ws-storage { margin-bottom: 6px; color: var(--txt-3); font-size: 11px; }
.ctx-ws-storage strong { color: var(--txt-2); font-weight: 500; white-space: nowrap; }
.ctx-ws-progress { height: 4px; overflow: hidden; border-radius: 6px; background: var(--bg-3); }
.ctx-ws-progress i { display: block; height: 100%; border-radius: inherit; background: var(--accent); }

/* ---------- chọn ảnh bìa project — nằm gọn trong cột ảnh bìa hẹp của Project Settings ---------- */
.ps-cover-picker { margin-top: 8px; }
.cover-src-choice { display: flex; flex-direction: column; gap: 6px; }
.cover-src-choice .btn { justify-content: center; }
.cover-pick {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)); gap: 6px;
  max-height: 260px; overflow-y: auto; margin-top: 8px;
}
.cover-pick-item {
  width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; cursor: pointer;
  border: 2px solid transparent; transition: border-color .12s;
}
@media (hover: hover) and (pointer: fine) { .cover-pick-item:hover { border-color: var(--accent); } }

/* ---------- Project Settings ---------- */
.modal.project-settings-modal { width: min(780px, 100%); }
.modal.project-settings-modal .m-body { max-height: min(660px, calc(100dvh - 170px)); padding: 0; }
.psettings { display: grid; grid-template-columns: 210px minmax(0, 1fr); min-height: 520px; }
.ps-cover-panel {
  min-width: 0; padding: 20px; border-right: 1px solid var(--line-soft);
  background: rgba(255, 255, 255, .012);
}
.ps-panel-label {
  margin-bottom: 10px; color: var(--txt-3); font-size: 10.5px; font-weight: 650;
  letter-spacing: .055em; text-transform: uppercase;
}
.ps-cover {
  width: 100%; aspect-ratio: 1; border-radius: 12px; background: var(--bg-2) center/cover no-repeat;
  border: 1px solid var(--line-soft); display: flex; align-items: center; justify-content: center;
  color: var(--txt-3); touch-action: none; user-select: none; overflow: hidden;
}
.ps-cover > svg { width: 28px; height: 28px; }
.ps-cover.has-cover { cursor: grab; }
.ps-cover.has-cover.dragging { cursor: grabbing; }
.ps-cover-hint { margin-top: 7px; font-size: 10.5px; line-height: 1.4; text-align: center; }
.ps-cover-change { width: 100%; min-height: 38px; justify-content: center; margin-top: 10px; }
.ps-cover-change svg { width: 15px; height: 15px; }
.ps-cover-picker .btn { width: 100%; justify-content: center; }
.ps-project-origin {
  display: flex; align-items: center; gap: 9px; min-width: 0; margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--line-soft);
}
.ps-project-origin > span {
  display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  border-radius: 8px; background: rgba(145, 132, 217, .13); color: var(--ink);
}
.ps-project-origin svg { width: 15px; height: 15px; }
.ps-project-origin > div { min-width: 0; display: grid; gap: 2px; }
.ps-project-origin small { color: var(--txt-3); font-size: 9.5px; text-transform: uppercase; letter-spacing: .04em; }
.ps-project-origin strong { overflow: hidden; color: var(--txt-2); font-size: 11.5px; font-weight: 550; text-overflow: ellipsis; white-space: nowrap; }
.ps-fields { display: flex; flex-direction: column; gap: 12px; min-width: 0; padding: 20px; }
.ps-card {
  min-width: 0; padding: 15px; border: 1px solid var(--line-soft); border-radius: 12px;
  background: rgba(27, 30, 38, .42);
}
.ps-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 13px; }
.ps-card-icon {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none;
  border-radius: 9px; background: rgba(145, 132, 217, .14); color: var(--ink);
}
.ps-card-icon svg { width: 16px; height: 16px; }
.ps-card-head > div { min-width: 0; display: grid; gap: 2px; }
.ps-card-head strong { color: var(--txt); font-size: 13px; font-weight: 600; }
.ps-card-head small { color: var(--txt-3); font-size: 10.75px; line-height: 1.35; }
.ps-form-grid { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(145px, 1fr); gap: 10px; }
.ps-form-grid .field { min-width: 0; margin: 0; }
.ps-form-grid .field > span { color: var(--txt-3); font-size: 11px; }
.ps-form-grid .input { height: 39px; }
.ps-toggle-card { padding: 0; overflow: hidden; }
.ps-row {
  display: flex; align-items: center; gap: 12px; font-size: 13px; cursor: pointer;
}
.ps-switch-row { min-height: 63px; padding: 11px 14px; }
.ps-switch-row + .ps-switch-row { border-top: 1px solid var(--line-soft); }
.ps-switch-row > span { flex: 1; min-width: 0; display: grid; gap: 3px; }
.ps-switch-row b { color: var(--txt); font-size: 12.5px; font-weight: 600; }
.ps-switch-row input[type="checkbox"] {
  order: 2; appearance: none; -webkit-appearance: none; position: relative; width: 38px; height: 22px;
  flex: none; margin: 0; border: 1px solid var(--line); border-radius: 6px; background: var(--bg-3);
  cursor: pointer; transition: background .16s, border-color .16s;
}
.ps-switch-row input[type="checkbox"]::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 4px; background: var(--txt-2); transition: transform .16s, background .16s;
}
.ps-switch-row input[type="checkbox"]:checked { border-color: var(--accent); background: var(--accent); }
.ps-switch-row input[type="checkbox"]:checked::after { transform: translateX(16px); background: #fff; }
.ps-row.disabled { opacity: .55; }
.ps-row .dim { font-size: 10.75px; line-height: 1.4; }
.ps-members-card { padding-bottom: 14px; }
.ps-member-form { display: grid; grid-template-columns: minmax(0, 1fr) 145px auto; gap: 8px; margin-top: 11px; }
.ps-member-form .input, .ps-member-form .btn { min-width: 0; height: 38px; }
.ps-member-form .btn { justify-content: center; }
.ps-static {
  display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-radius: 8px;
  background: var(--bg-2); border: 1px solid var(--line-soft); color: var(--txt-2); font-size: 13px;
}
.ps-static svg { flex: none; opacity: .7; }

/* ---------- workspace settings: thanh dung lượng, danh sách thành viên ---------- */
.usage-bar { height: 6px; border-radius: 3px; background: var(--bg-2); overflow: hidden; margin: 6px 0 4px; }
.usage-fill { height: 100%; background: var(--accent); border-radius: 3px; }
.usage-fill.warn { background: var(--warn); }
.usage-fill.danger { background: var(--danger); }
.ws-member { display: flex; align-items: center; gap: 10px; }
.ws-member-copy { min-width: 0; overflow-wrap: anywhere; }
.ws-avatar {
  width: 26px; height: 26px; border-radius: 6px; flex: none; object-fit: cover;
  background: var(--bg-3); display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--txt-2);
}

/* Cài đặt Workspace — thông tin quan trọng được gom thành thẻ tổng quan, thành viên
   chuyển sang hộp thoại cộng tác riêng để không lặp nội dung. */
.workspace-settings { display: grid; gap: 16px; min-width: 0; }
.ws-settings-card,
.ws-overview-section {
  padding: 16px; border: 1px solid var(--line-soft); border-radius: 12px;
  background: rgba(27, 30, 38, .42);
}
.ws-settings-heading,
.ws-overview-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ws-settings-heading { justify-content: flex-start; }
.ws-settings-icon {
  width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  border-radius: 9px; color: var(--ink); background: rgba(145, 132, 217, .14);
}
.ws-settings-icon svg { width: 17px; height: 17px; }
.ws-settings-heading > div,
.ws-overview-head > div { display: grid; gap: 1px; }
.ws-settings-heading > div > span,
.ws-overview-head > div > span {
  color: var(--txt-3); font-size: 10.5px; font-weight: 600;
  letter-spacing: .045em; text-transform: uppercase;
}
.ws-settings-heading strong,
.ws-overview-head strong { font-size: 13.5px; font-weight: 600; }
.ws-name-form { display: flex; gap: 8px; margin-top: 12px; }
.ws-name-form .input { width: auto; min-width: 0; flex: 1; height: 40px; }
.ws-name-form .btn { height: 40px; white-space: nowrap; }
.ws-overview-grid { display: grid; grid-template-columns: 1.25fr 1fr 1fr; gap: 10px; margin-top: 12px; }
.ws-overview-card {
  min-width: 0; min-height: 112px; padding: 13px; display: flex; flex-direction: column;
  align-items: flex-start; text-align: left; color: inherit; font: inherit;
  border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg-1);
}
.ws-overview-label { color: var(--txt-3); font-size: 11px; font-weight: 500; }
.ws-overview-card strong { margin-top: 8px; font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.ws-overview-card small { margin-top: auto; color: var(--txt-3); font-size: 10.5px; line-height: 1.35; }
.ws-overview-card .usage-bar { width: 100%; margin: 9px 0 6px; }
.ws-members-shortcut { cursor: pointer; transition: border-color .15s, background .15s; }
@media (hover: hover) and (pointer: fine) { .ws-members-shortcut:hover { border-color: var(--line); background: var(--bg-2); } }
.ws-members-shortcut small { color: var(--ink); }
.workspace-settings > .billing-shell { min-width: 0; margin-top: 0; }
.modal.workspace-settings-modal .m-foot { padding: 10px 18px; }

/* ---------- workspace billing ---------- */
.billing-shell {
  margin-top: 2px; padding: 18px; border: 1px solid var(--line); border-radius: 14px;
  background: linear-gradient(145deg, rgba(145, 132, 217, .09), rgba(22, 24, 38, .5) 38%);
}
.billing-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.billing-head .ps-sec-head { margin-bottom: 3px; color: #8d87ff; }
.billing-head h3 { margin: 0; font-size: 17px; letter-spacing: -.01em; }
.billing-secure {
  flex: none; padding: 5px 9px; border: 1px solid rgba(47, 191, 113, .28); border-radius: 6px;
  background: rgba(47, 191, 113, .08); color: var(--ok); font-size: 11.5px;
}
.billing-status {
  display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
  margin: 8px 0 14px; color: var(--txt-2); font-size: 13px;
}
.billing-status > strong { color: var(--txt); font-size: 13px; font-weight: 600; }
.billing-status > small { color: var(--txt-3); font-size: 11.5px; }
.billing-state {
  padding: 3px 7px; border-radius: 6px; background: var(--bg-2);
  color: var(--txt-2); font-size: 10.5px; line-height: 1.35;
}
.billing-state.ok { background: rgba(47, 191, 113, .12); color: var(--ok); }
.billing-state.warn { background: rgba(245, 166, 35, .13); color: var(--warn); }
.billing-manage { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-bottom: 9px; }
.billing-manage .btn { height: 40px; justify-content: center; }
.billing-edit-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 2px 0 12px; padding-bottom: 11px; border-bottom: 1px solid var(--line-soft);
}
.billing-edit-head strong { font-size: 13px; font-weight: 600; }
.billing-edit-head .btn { height: 32px; padding-inline: 9px; }
.billing-cycle {
  width: max-content; display: flex; padding: 3px; margin-bottom: 14px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg-2);
}
.billing-cycle button {
  height: 32px; padding: 0 13px; border: 0; border-radius: 7px; background: transparent;
  color: var(--txt-2); cursor: pointer;
}
.billing-cycle button.active { background: var(--bg-3); color: var(--txt); box-shadow: 0 2px 8px rgba(0, 0, 0, .22); }
.billing-cycle button span { margin-left: 5px; color: #8fd9ae; font-size: 10.5px; }
.billing-layout { display: grid; grid-template-columns: minmax(0, 1fr) 270px; gap: 14px; align-items: stretch; }
.billing-options { min-width: 0; }
.billing-plan-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.billing-plan {
  min-width: 0; padding: 14px; text-align: left; color: inherit; border: 1px solid var(--line);
  border-radius: 12px; background: rgba(22, 24, 38, .8); cursor: pointer; transition: .15s ease;
}
@media (hover: hover) and (pointer: fine) { .billing-plan:hover { border-color: var(--line); transform: translateY(-1px); } }
.billing-plan.active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent), 0 8px 24px rgba(145, 132, 217, .12); }
.billing-plan span { display: block; }
.billing-plan-top { display: flex !important; align-items: center; justify-content: space-between; gap: 8px; }
.billing-plan-top strong { font-size: 16px; }
.billing-plan-top em {
  padding: 2px 6px; border-radius: 6px; background: rgba(145, 132, 217, .16);
  color: var(--ink); font-size: 10px; font-style: normal; text-transform: uppercase; letter-spacing: .04em;
}
.billing-plan-price { margin-top: 14px; }
.billing-plan-price b { font-size: 18px; letter-spacing: -.02em; }
.billing-plan-price small { margin-left: 4px; color: var(--txt-3); }
.billing-plan-copy { margin-top: 10px; color: var(--txt-2); font-size: 12.5px; }
.billing-plan-feature { margin-top: 3px; color: var(--txt-3); font-size: 11.5px; }
.billing-addon {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin-top: 10px; padding: 12px 13px; border: 1px solid var(--line-soft); border-radius: 11px; background: rgba(22, 24, 38, .55);
}
.billing-addon > span { display: flex; flex-direction: column; flex: none; }
.billing-addon strong { font-size: 12.5px; }
.billing-addon small { color: var(--txt-3); font-size: 11px; }
.billing-addon .input { max-width: 245px; background-color: var(--bg-2); }
.billing-summary {
  display: flex; flex-direction: column; padding: 15px; border: 1px solid var(--line);
  border-radius: 12px; background: #111319;
}
.billing-summary-kicker { color: var(--txt-3); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; }
.billing-summary > strong { margin: 3px 0 13px; font-size: 15px; }
.billing-summary-line { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0; color: var(--txt-2); font-size: 12px; }
.billing-summary-line b { color: var(--txt); font-weight: 500; }
.billing-summary-line .billing-tax { color: var(--ok); }
.billing-summary-total {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 10px;
  margin-top: 9px; padding-top: 12px; border-top: 1px solid var(--line-soft); font-size: 12px;
}
.billing-summary-total div { text-align: right; }
.billing-summary-total b { display: block; font-size: 21px; line-height: 1.1; letter-spacing: -.03em; }
.billing-summary-total small { color: var(--txt-3); }
.billing-pay { width: 100%; height: 42px; justify-content: center; margin-top: 14px; font-weight: 600; }
.billing-summary p { margin: 9px 0 10px; color: var(--txt-3); font-size: 10.5px; text-align: center; }
.billing-trust { display: flex; justify-content: space-between; gap: 8px; color: var(--txt-3); font-size: 10.5px; }
.billing-account-actions { display: grid; grid-template-columns: 1fr; gap: 9px; margin-top: 9px; }
.billing-portal { width: 100%; height: 40px; justify-content: center; }

@media (max-width: 700px) {
  .ws-settings-card, .ws-overview-section { padding: 13px; }
  .ws-name-form { align-items: stretch; flex-direction: column; }
  .ws-name-form .input { width: 100%; }
  .ws-name-form .btn { width: 100%; padding-inline: 12px; justify-content: center; }
  .ws-overview-head { align-items: flex-start; }
  .ws-overview-grid { grid-template-columns: 1fr 1fr; }
  .ws-overview-card:first-child { grid-column: 1 / -1; min-height: 104px; }
  .ws-overview-card { min-height: 96px; }
  .billing-shell { padding: 14px; }
  .billing-head { align-items: flex-start; flex-direction: column; }
  .billing-head > div { min-width: 0; }
  .billing-secure { max-width: 100%; white-space: normal; text-align: left; }
  .billing-status > small { flex: 1 1 100%; }
  .billing-layout { grid-template-columns: 1fr; }
  .billing-manage { grid-template-columns: 1fr; }
  .billing-account-actions { grid-template-columns: 1fr; }
  .billing-plan-grid { grid-template-columns: 1fr; }
  .billing-addon { align-items: flex-start; flex-direction: column; }
  .billing-addon .input { max-width: none; }
  .billing-summary { margin-top: 2px; }
}

/* ---------- misc ---------- */
.warnbox {
  padding: 11px 14px; border-radius: 10px; font-size: 13px;
  background: rgba(245, 166, 35, .12); border: 1px solid rgba(245, 166, 35, .35);
  color: var(--warn);
}
.warnbox b { color: #ffd899; }
.warnbox.danger {
  background: rgba(255, 90, 90, .12); border-color: rgba(255, 90, 90, .35); color: var(--danger);
}
.warnbox.danger b { color: #ffb3ba; }

.empty { text-align: center; padding: 80px 20px; color: var(--txt-3); }
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 20px);
  background: var(--bg-3); border: 1px solid var(--line); padding: 10px 16px;
  border-radius: 10px; box-shadow: var(--shadow); opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s; z-index: 500;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }
.toast-cancel {
  pointer-events: auto; margin-left: 12px; padding: 0; border: none; background: transparent;
  font: inherit; font-weight: 600; color: var(--accent-hi); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .toast-cancel:hover { text-decoration: underline; } }

/* Khung tiến độ tải lên (uploadPanel trong js/admin.js): góc dưới phải, nhiều lần tải cùng lúc thì
   xếp chồng. Thanh tiến độ có sọc chạy khi đang gửi, chạy qua lại (không rõ %) khi đang kiểm tra/
   đối chiếu/lưu; màu đổi theo trạng thái: thử lại = vàng, xong = xanh, lỗi = đỏ. */
.up-dock {
  position: fixed; right: 20px; bottom: 20px; z-index: 490; width: min(380px, calc(100vw - 20px));
  display: flex; flex-direction: column; gap: 10px; pointer-events: none;
}
.up-card {
  pointer-events: auto; background: var(--bg-1); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 12px 14px 13px; animation: slideup .22s var(--ease-out);
  --up-c: var(--accent);
}
.up-card.is-warn { --up-c: var(--warn, #d9a441); }
.up-card.is-ok { --up-c: var(--ok, #3fb37a); }
.up-card.is-err { --up-c: var(--danger, #e0565f); }
.up-card.is-idle { --up-c: var(--txt-3); }
.up-card.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity .25s, transform .25s; }
.up-head { display: flex; align-items: center; gap: 10px; }
.up-ic { width: 18px; height: 18px; flex: none; color: var(--up-c); display: grid; place-items: center; }
.up-ic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.up-ic .up-spin { animation: wahspin .9s linear infinite; }
.up-acts { display: flex; gap: 14px; flex: none; }
.up-title { flex: 1; min-width: 0; font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.up-act {
  flex: none; border: 0; background: transparent; color: var(--txt-2); font: inherit; font-size: 13px;
  padding: 3px 6px; margin: -3px -6px -3px 0; border-radius: 6px; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .up-act:hover { background: var(--hover); color: var(--txt); } }
.up-act.primary { color: var(--accent-hi); font-weight: 600; }
.up-bar { position: relative; height: 6px; margin: 11px 0 9px; border-radius: 6px; background: var(--bg-3); overflow: hidden; }
.up-bar > i {
  position: absolute; inset: 0 auto 0 0; width: 0; border-radius: inherit; background-color: var(--up-c);
  transition: width .35s ease-out, background-color .2s;
}
.up-card.is-active .up-bar > i {
  background-image: linear-gradient(45deg, rgba(255,255,255,.22) 25%, transparent 25%, transparent 50%,
    rgba(255,255,255,.22) 50%, rgba(255,255,255,.22) 75%, transparent 75%);
  background-size: 16px 16px; animation: up-stripes .8s linear infinite;
}
.up-bar.indet > i { width: 34% !important; animation: up-indet 1.3s ease-in-out infinite; transition: none; }
@keyframes up-stripes { to { background-position: 16px 0; } }
@keyframes up-indet { 0% { left: -34%; } 100% { left: 100%; } }
/* khung tải xuống chưa rõ dung lượng (zip): thanh trượt qua lại trong lòng rãnh */
.up-bar.indet.bounce > i { animation: up-bounce 1.1s ease-in-out infinite alternate; }
@keyframes up-bounce { 0% { left: 0; } 100% { left: 66%; } }
.up-meta { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--txt-2); font-variant-numeric: tabular-nums; }
.up-meta > span:last-child { color: var(--txt-3); text-align: right; }
.up-sub { margin-top: 5px; font-size: 12.5px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.up-card.is-warn .up-sub, .up-card.is-err .up-sub { color: var(--up-c); }
.up-sub:empty, .up-meta:empty { display: none; }
/* Hộp thoại của luồng tải lên (askExistingUploads, showUploadReport): đầu có biểu tượng + 1 câu, danh
   sách tệp lỗi gom theo lý do. Tiêu đề h2 chuẩn của .modal ẩn đi vì đầu hộp thoại tự dựng (.up-mhead,
   có role="heading"). */
.modal.up-modal { width: min(500px, 100%); }
/* hộp thoại tải lên nằm TRÊN khung tiến độ (dock, z 490) — không để khung tiến độ che nút trên điện thoại */
#mask.open:has(.modal.up-modal) { z-index: 500; }
.modal.up-modal > h2 { display: none; }
.modal.up-modal .m-body { padding: 22px 22px 18px; }
.modal.up-modal .m-foot { border-top: 0; padding-top: 0; padding-bottom: 18px; }
.up-mhead { display: flex; gap: 14px; align-items: flex-start; }
.up-mic { width: 38px; height: 38px; border-radius: 11px; flex: none; display: grid; place-items: center; background: var(--tint); color: var(--accent-hi); }
.up-mic.danger { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.up-mic svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.up-mtitle { font-size: 16px; font-weight: 600; margin: 1px 0 5px; }
.up-msub { color: var(--txt-2); font-size: 14px; line-height: 1.5; }
.up-opts { display: grid; gap: 8px; margin: 14px 0 0 52px; }
.up-opt { display: flex; gap: 12px; align-items: center; width: 100%; text-align: left; padding: 10px 13px; border-radius: 12px;
  border: 1px solid var(--line, rgba(255,255,255,.1)); background: transparent; color: inherit; font: inherit; cursor: pointer; transition: background .15s, border-color .15s; }
.up-opt:hover, .up-opt:focus-visible, .up-opt.on { background: var(--tint); border-color: var(--accent-hi); outline: none; }
.up-rd { width: 16px; height: 16px; border-radius: 4px; flex: none; border: 1.5px solid var(--txt-3); position: relative; }
.up-opt.on .up-rd { border-color: var(--accent-hi); }
.up-opt.on .up-rd::after { content: ''; position: absolute; inset: 3px; border-radius: 4px; background: var(--accent-hi); }
.up-otx { display: grid; gap: 2px; min-width: 0; }
.up-otx b { font-size: 14px; font-weight: 600; }
.up-otx small { font-size: 12.5px; line-height: 1.4; color: var(--txt-3); }
.up-pill { font-style: normal; font-size: 11px; font-weight: 500; margin-left: 6px; padding: 1px 6px; border-radius: 5px; background: var(--tint); color: var(--accent-hi); }
.up-cmp { display: grid; grid-template-columns: 1fr auto 1fr; gap: 8px; align-items: center; margin: 14px 0 0 52px; padding: 10px; border-radius: 12px; background: color-mix(in srgb, var(--txt-3) 10%, transparent); }
.up-cs { display: flex; gap: 9px; align-items: center; min-width: 0; font-size: 12px; color: var(--txt-3); }
.up-cs > span:last-child { display: grid; min-width: 0; }
.up-cs b { font-size: 12.5px; font-weight: 600; color: var(--txt-1, inherit); }
.up-th { width: 46px; height: 36px; border-radius: 7px; flex: none; overflow: hidden; display: grid; place-items: center; background: var(--tint); color: var(--accent-hi); }
.up-th img { width: 100%; height: 100%; object-fit: cover; }
.up-th svg, .up-arrow svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.up-arrow { color: var(--txt-3); display: grid; }
.up-files2 { margin: 14px 0 0 52px; border: 1px solid var(--line, rgba(255,255,255,.1)); border-radius: 12px; overflow: hidden; }
.up-fr { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 7px 12px; font-size: 12.5px; border-top: 1px solid var(--line, rgba(255,255,255,.08)); }
.up-fr:first-child { border-top: 0; }
.up-fn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: grid; }
.up-fn small, .up-fd { color: var(--txt-3); font-size: 12px; white-space: nowrap; }
.up-more { color: var(--accent-hi); }
.up-lnk { background: none; border: 0; padding: 0; font: inherit; font-size: 12.5px; color: var(--accent-hi); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .up-lnk:hover { text-decoration: underline; } }
.up-seg { display: inline-flex; flex: none; border: 1px solid var(--line, rgba(255,255,255,.12)); border-radius: 9px; overflow: hidden; }
.up-seg button { border: 0; background: transparent; color: inherit; font: inherit; font-size: 12px; padding: 5px 9px; cursor: pointer; }
.up-seg button.on { background: var(--accent-hi); color: var(--bg, #14142a); font-weight: 600; }
.up-warn { display: flex; gap: 8px; align-items: center; margin: 10px 0 0 52px; font-size: 12.5px; color: var(--warn, #e9a94b); }
.up-warn svg { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.up-foot2 { margin: 12px 0 0 52px; }
.up-hint { margin: 14px 0 0 52px; font-size: 12.5px; line-height: 1.5; color: var(--txt-3); }
.up-list { margin: 16px 0 0 52px; max-height: 40vh; overflow: auto; }
.up-reason { font-size: 12.5px; color: var(--txt-3); line-height: 1.45; margin: 12px 0 4px; }
.up-reason:first-child { margin-top: 0; }
.up-files { margin: 0; padding: 0; list-style: none; }
.up-files li { font-size: 13px; line-height: 1.7; word-break: break-all; }
.up-files li.up-more { color: var(--txt-3); }
@media (max-width: 480px) {
  .up-hint, .up-list, .up-opts, .up-cmp, .up-files2, .up-warn, .up-foot2 { margin-left: 0; }
  .up-cmp { grid-template-columns: 1fr; }
  .up-fr:has(.up-seg) { flex-wrap: wrap; }
  .up-fr:has(.up-seg) .up-fn { flex: 1 0 100%; }
  .up-fr:has(.up-seg) .up-seg { width: 100%; }
  .up-fr:has(.up-seg) .up-seg button { flex: 1; }
  .up-arrow { transform: rotate(90deg); justify-self: center; }
}
/* Thẻ gợi ý cài app "đúng lúc" (offerInstall trong js/admin.js) — nằm chung chồng .up-dock với khung tải lên */
.inst-card {
  pointer-events: auto; position: relative; background: var(--bg-1); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 14px; animation: slideup .22s var(--ease-out);
}
.inst-card.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity .25s, transform .25s; }
.inst-x {
  position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; border: 0; border-radius: 6px; padding: 0;
  background: transparent; color: var(--txt-3); display: grid; place-items: center; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .inst-x:hover { background: var(--hover); color: var(--txt); } }
.inst-x svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.inst-head { display: flex; gap: 11px; align-items: center; padding-right: 22px; }
.inst-logo { width: 34px; height: 34px; flex: none; border-radius: 9px; overflow: hidden; box-shadow: 0 0 0 1px var(--line-soft, var(--line)); }
.inst-logo svg { width: 100%; height: 100%; display: block; }
.inst-head b { display: block; font-size: 14px; font-weight: 600; }
.inst-head p { margin: 1px 0 0; font-size: 12.5px; color: var(--txt-2); }
.inst-list { list-style: none; margin: 11px 0 0; padding: 0; display: grid; gap: 6px; }
.inst-list li { display: flex; gap: 9px; align-items: flex-start; font-size: 13px; color: var(--txt); }
.inst-list svg, .inst-chip svg {
  width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.inst-list svg { color: var(--accent-hi); margin-top: 2px; }
.inst-acts { display: flex; justify-content: flex-end; gap: 6px; margin-top: 13px; }
.inst-steps { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 9px; counter-reset: inst; }
.inst-steps li { display: flex; gap: 10px; align-items: center; font-size: 13.5px; counter-increment: inst; }
.inst-steps li > span { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; }
.inst-steps li::before {
  content: counter(inst); width: 21px; height: 21px; flex: none; border-radius: 6px; display: grid; place-items: center;
  background: var(--tint); color: var(--accent-hi); font-size: 11.5px; font-weight: 700;
}
.inst-chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: 7px; white-space: nowrap;
  background: var(--bg-2); border: 1px solid var(--line); font-size: 12.5px; font-weight: 600;
}
.inst-chip svg { color: #2f7cf6; }
.inst-note { margin: 11px 0 0; font-size: 12px; color: var(--txt-3); }
@media (max-width: 640px) {
  .up-dock { left: 10px; right: 10px; width: auto; bottom: calc(16px + var(--safe-b)); }
}
@media (prefers-reduced-motion: reduce) { .inst-card { animation: none; } }
@media (prefers-reduced-motion: reduce) {
  .up-card { animation: none; }
  .up-card.is-active .up-bar > i, .up-ic .up-spin { animation: none; }
  .up-bar.indet > i, .up-bar.indet.bounce > i { animation: none; left: 0; width: 100% !important; opacity: .45; }
}
.selbar {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); z-index: 60;
}
.tabs { display: flex; gap: 4px; }
.tab { padding: 6px 12px; border-radius: 8px; cursor: pointer; color: var(--txt-2); font-size: 13px; }
.tab.on { background: var(--bg-3); color: var(--txt); }
/* Số đếm cạnh nhãn tab (Link chia sẻ/Phản hồi) — huy hiệu tròn thay vì số mờ trong
   ngoặc, đỡ trông như phụ chú rời rạc. Rỗng thì ẩn hẳn (project mới chưa có link/feedback). */
.tab .dim {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 5px; margin-left: 3px;
  border-radius: 6px; background: rgba(145, 132, 217, .18); color: var(--ink); font-size: 10.5px;
}
.tab .dim:empty { display: none; }

table.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
table.tbl th, table.tbl td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
table.tbl th { color: var(--txt-3); font-weight: 500; font-size: 12px; }

/* Danh sách liên kết có nhiều cột: desktop hẹp giữ nguyên cấu trúc bảng và cuộn ngang,
   thay vì ép từng cột co đến mức chữ vỡ thành nhiều dòng. */
#tabLinks {
  max-width: 100%; overflow-x: auto; padding-bottom: 6px;
  overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
#tabLinks::-webkit-scrollbar { height: 8px; }
#tabLinks::-webkit-scrollbar-thumb { border-radius: 6px; background: var(--line); }

/* ============================================================
   MOBILE — trang khách trên điện thoại
   Mọi thứ dưới đây nằm trong media query, desktop không đổi.
   ============================================================ */

@keyframes sheetup { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }

/* Hiện chỉ trên điện thoại / chỉ trên desktop.
   Quy tắc ẩn nằm trong media query của phía ĐỐI DIỆN, không phải một rule
   `display: ... !important` dùng chung — nếu không nó sẽ đè lên mọi quy tắc
   trạng thái bên dưới và bật sáng cùng lúc mọi thanh (thanh chọn, dải hành động…). */
@media (min-width: 641px) { .mob-only { display: none !important; } }
@media (max-width: 640px) { .tb-desktop { display: none !important; } }

/* Thanh trên của chế độ chọn — chỉ hiện khi thật sự đang chọn */
.tb-sel { display: none; }

/* Nhóm hành động trong lightbox: ở desktop nó chỉ là một cụm nút trong thanh trên. */
.lb-acts { display: flex; align-items: center; gap: 12px; }
.lb-head > .lb-acts { order: 1; }
/* Bản sao cụm sao trên hàng metadata — chỉ dùng trên điện thoại (xem @media bên dưới),
   ẩn ở desktop vì sao đã có sẵn trong .lb-acts. Cùng lý do cho #albColorTagTop. */
#albStarsTop, #albColorTagTop { display: none; }
/* Icon + huy hiệu số + placeholder dài của nút Nhận xét: chỉ dùng cho dạng thanh pill
   trên điện thoại (xem .compose-trigger trong @media bên dưới) — desktop vẫn là nút
   chữ ngắn "Nhận xét" như cũ. */
.panel-ic, .cmt-count, .cmt-chevron { display: none; }

/* Công tắc panel trên desktop: icon mô tả đúng bố cục khung nội dung + sidebar,
   thay cho nút chữ dài. Trạng thái bật dùng màu accent sẵn có của .btn.primary. */
.lb-acts .panel-toggle {
  width: 34px; padding: 0; justify-content: center;
  color: var(--txt-2);
}
.panel-toggle .panel-ic { display: block; flex: none; }
.panel-toggle .panel-label,
.panel-toggle .cmt-count,
.panel-toggle .cmt-chevron { display: none; }

/* Sheet — dropdown neo theo điểm bấm trên desktop, trượt từ đáy trên điện thoại
   (media query bên dưới ghi đè lại left/right/bottom). */
.sheet-mask { position: fixed; inset: 0; z-index: 300; background: transparent; }
.sheet {
  position: absolute; width: 220px; max-height: 70vh; overflow-y: auto;
  padding: 5px; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow);
  animation: popin .15s var(--ease-out); transform-origin: top left;
}
@keyframes slideup { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
/* menu/popover: mọc ra từ phía nút bấm (transform-origin đặt ở từng khối), không bắt đầu từ scale(0) */
@keyframes popin { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
.sheet-title {
  padding: 7px 10px 5px; font-size: 11.5px; color: var(--txt-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sheet-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px;
}
@media (hover: hover) and (pointer: fine) { .sheet-item:hover { background: var(--bg-3); } }
.sheet-item:active { background: var(--bg-3); }
.sheet-item .si-ic { width: 16px; flex: none; display: grid; place-items: center; color: var(--txt-2); }
.sheet-item .si-lb { flex: 1; min-width: 0; }
.sheet-item .si-hint { flex: none; color: var(--txt-3); font-size: 12.5px; }
.sheet-sep { height: 1px; margin: 5px 6px; background: var(--line-soft); }
.sheet-close { justify-content: center; color: var(--txt-2); }
@media (min-width: 721px) {
  .sheet > .sheet-sep, .sheet > .sheet-close { display: none; }
}

@media (max-width: 720px) {
  /* Khi sheet thông báo mở, cố định trang phía sau tại đúng vị trí hiện tại. Danh sách
     bên trong vẫn cuộn độc lập; tránh iOS/Safari đôi lúc chuyển gesture sang body. */
  body.notif-open-mobile {
    position: fixed; left: 0; right: 0; width: 100%; overflow: hidden;
    overscroll-behavior: none;
  }
  .wrap { padding: 16px 12px 120px; }
}

@media (max-width: 640px) {
  /* Khoá pinch/double-tap zoom của cả giao diện trên điện thoại. Trình xem media
     vẫn tự xử lý pinch riêng vì .stage/.cmp-slider-ui dùng touch-action:none. */
  html, body {
    touch-action: pan-x pan-y;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }

  /* ---------- thanh trên: 2 tầng ---------- */
  .topbar {
    height: auto; min-height: calc(60px + var(--safe-t));
    padding: calc(10px + var(--safe-t)) 12px 6px;
    flex-wrap: wrap; column-gap: 8px; row-gap: 0;
  }
  .topbar .spacer { display: none; }
  .topbar .brand { flex: none; }
  .topbar .crumb {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px;
  }
  .tab { flex: none; padding: 8px 13px; font-size: 13.5px; white-space: nowrap; }
  #albMore { width: var(--tap); height: var(--tap); font-size: 19px; padding: 0; }

  /* Sheet: trên điện thoại trượt từ đáy toàn bộ chiều ngang thay vì dropdown neo điểm bấm */
  .sheet-mask { background: rgba(4, 5, 8, .55); animation: fadein .15s ease; }
  .sheet {
    left: 10px !important; right: 10px; top: auto !important; bottom: calc(16px + var(--safe-b));
    width: auto; max-height: 76dvh; border-radius: 14px;
    padding: 6px;
    animation: sheetup .22s var(--ease-drawer);
  }
  .sheet-title { padding: 9px 12px 7px; }
  .sheet-item { min-height: 48px; padding: 8px 12px; border-radius: 9px; font-size: 14.5px; }
  .sheet-item .si-ic { width: 20px; }

  /* thanh trên thay thế khi đang chọn nhiều ảnh */
  body.sel-mode .topbar:not(.tb-sel) { display: none; }
  body.sel-mode .tb-sel { display: flex; }
  .tb-sel { height: 50px; padding: 0 8px; gap: 6px; flex-wrap: nowrap; }
  .tb-sel .btn { height: var(--tap); padding: 0 10px; font-size: 13.5px; }
  .tb-sel-label { flex: 1; text-align: center; font-size: 13.5px; font-weight: 600; }
  .tb-sel-all { color: var(--ink); }

  /* ---------- thanh lọc dùng chung trang khách + Admin ---------- */
  .fbar { flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
  .fbar .spacer { display: none; }
  #btnSearch, #btnFilterSheet, #btnSortSheet,
  #btnPjSearch, #btnPjSort, #btnPjFilter,
  #btnDSearch, #btnDFilter, #btnDSort, #btnDView, #btnPjView, #btnPjNew {
    position: relative; width: var(--tap); height: var(--tap); padding: 0; justify-content: center;
    flex: none; background: var(--bg-1); border-color: var(--line-soft); color: var(--txt-2);
  }
  .pj-new-btn { margin-left: auto; }
  .pj-new-btn svg { display: block; flex: none; }
  .pj-appearance-btn { margin-left: 0; }
  body.in-project #btnPjNew, body.in-trash #btnPjNew { display: none; }
  #btnSearch.active, #btnPjSearch.active, #btnDSearch.active {
    background: var(--bg-3); color: var(--txt);
  }
  /* chỉ sáng màu khi thật sự đang lọc theo sao — nút sắp xếp không có trạng thái bật/tắt */
  #btnFilterSheet.active, #btnDFilter.active, #btnPjFilter.active {
    background: var(--bg-3); color: var(--ink);
  }
  .filter-dot { position: absolute; top: 6px; right: 6px; width: 7px; height: 7px; border-radius: 2px; background: var(--accent); }
  /* Nút Giao diện bám mép phải giống desktop. Ba công cụ Tìm/Lọc/Sắp xếp
     vẫn đứng thành cụm bên trái; mobile chọn trực tiếp bằng ô tick trên thẻ. */
  .appearance-wrap { flex: none; margin-left: auto; }
  .appearance-btn { width: var(--tap); height: var(--tap); padding: 0; justify-content: center; }
  .appearance-pop { position: fixed; left: 10px; right: 10px; top: auto; bottom: calc(16px + var(--safe-b)); width: auto; max-height: 76dvh; overflow: auto; }

  /* ---------- lưới ảnh ---------- */
  .grid { gap: 8px; }
  /* Thư mục luôn 2 cột — phải !important vì .grid ở trên cũng !important,
     specificity cao hơn không thắng được nếu bên kia có !important còn bên này thì không. */
  #gridF { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; --tile: none; }

  .tile .cap { padding: 7px 9px; }
  /* dòng "ai đưa lên • lúc nào" chiếm chỗ mà ít ai đọc trên điện thoại */
  .tile .by { display: none; }
  /* BUG THẬT đã sửa (2026-09-23, người dùng report trên iPhone "chỉ còn 2 sao/4 sao" — mất luôn
     thông tin thật, không chỉ là chật): ở trang quản trị, `.tile-rate-row` có tới BA khối cạnh
     nhau (sao + thẻ màu + nút ⋯ `.tile-menu`, riêng trang khách share.js không có `.tile-menu`
     nên không dính) — cỡ ô "S" trên điện thoại không đủ chỗ cho cả ba ở kích thước bình thường,
     `.stars` (khối duy nhất được co, xem `.tile-rate-row .stars.tile-stars`) bị co MẠNH, chỉ còn
     thấy 2-4/5 sao — ĐÚNG số liệu sai lệch chứ không chỉ chật. Sửa tận gốc bằng cách gộp sao+thẻ
     màu vào `.tile-marks` (xem HTML ở admin.js) rồi cho `.tile-menu` tự XUỐNG DÒNG RIÊNG khi
     không đủ chỗ (`.tile-rate-row{flex-wrap:wrap}` ở trên + `margin-left:auto` bên dưới để căn
     phải trên dòng riêng đó) — quyết định xuống dòng của flexbox dựa theo kích thước TỰ NHIÊN
     (chưa co) của `.tile-marks`, nên sao+thẻ màu luôn đủ chỗ ở kích thước bình thường trên dòng
     của chúng, không cần co nữa trong trường hợp thường gặp. */
  .tile .stars.tile-stars { padding: 0; }
  .tile .stars.tile-stars .star { font-size: 14px; padding: 3px 0; }
  /* Padding của hàng sao chuyển sang .tile-rate-row để canh cùng lúc với nút ⋯ bên cạnh
     (xem .tile-menu bên dưới) — sao và nút phải cùng gióng theo mép ô ảnh. */
  .tile-rate-row { padding: 0 9px 9px; gap: 3px; }

  /* Mobile: ô tích luôn chờ sẵn. Chạm đúng ô để chọn/bỏ chọn; chạm phần còn lại vẫn mở viewer. */
  #grid .tile .checkbox {
    opacity: 1; pointer-events: auto;
    width: 32px; height: 32px; border-radius: 8px; top: 8px; left: 8px; right: auto; font-size: 15px;
  }
  /* Chấm thẻ màu: giữ đúng cỡ desktop (13px) — trước đây to hơn (17px) "cho dễ chạm" nhưng đó là
     nguyên nhân chính khiến sao bị cắt, xem chú thích ở .tile .stars.tile-stars phía trên. */
  .tile .ctag-btn.tile-ctag { padding: 3px 0; }

  /* ---------- danh sách: mỗi dòng thành một thẻ dọc ---------- */
  .frow-scroll { overflow-x: visible; }
  .frow.frow-guest.frow-head { display: none; }
  .frow.frow-guest {
    min-width: 0;
    grid-template-columns: 64px auto auto 1fr 32px;
    gap: 3px 8px; padding: 10px 12px; min-height: 88px; align-items: center;
  }
  .frow-guest .fl-thumb {
    grid-column: 1; grid-row: 1 / 4;
    width: 64px; height: 64px; border-radius: 6px; align-self: center;
  }
  .frow-guest .fl-name {
    grid-column: 2 / 5; grid-row: 1;
    white-space: normal; font-size: 13.5px; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .frow-guest .fl-rate { grid-column: 2 / 5; grid-row: 2; }
  .frow-guest .fl-rate .stars { gap: 5px; }
  .frow-guest .fl-rate .star { font-size: 18px; }
  /* dòng phụ: dung lượng · góp ý · ngày */
  .frow-guest .fl-size   { grid-column: 2; grid-row: 3; }
  .frow-guest .fl-cmt    { grid-column: 3; grid-row: 3; text-align: left; }
  .frow-guest .fl-date   { grid-column: 4; grid-row: 3; }
  .frow-guest .fl-size,
  .frow-guest .fl-cmt, .frow-guest .fl-date { font-size: 11.5px; }
  .frow-guest .fl-check { grid-column: 5; grid-row: 1 / 4; justify-self: end; }
  .frow-guest .fl-check .checkbox { width: 32px; height: 32px; border-radius: 8px; font-size: 15px; }

  /* ---------- thanh thao tác hàng loạt ---------- */
  .selbar {
    left: 10px; right: 10px; bottom: calc(16px + var(--safe-b));
    transform: none; flex-wrap: wrap; gap: 8px;
    padding: 10px 12px 12px; border-radius: 14px;
  }
  .selbar > .dim { display: none; }
  #selCount { flex: 1 1 100%; font-size: 13px; color: var(--txt-2); }
  #selDl { flex: 1 1 auto; height: var(--tap); justify-content: center; }
  #selClear { display: inline-flex; height: var(--tap); }
  /* thanh thao tác cao 2 tầng, chừa chỗ để ảnh cuối cùng không bị nó che */
  body.sel-mode .wrap { padding-bottom: 215px; }

  /* ---------- lightbox ---------- */
  /* 100dvh thay cho inset:0 — thanh địa chỉ iOS co giãn sẽ không cắt mất đáy */
  .lb { height: 100dvh; }
  .lb.open {
    grid-template-rows: auto minmax(0, 1fr) auto;
    padding-bottom: calc(56px + var(--safe-b));
  }
  /* Chạm ảnh để ẩn/hiện thanh là thao tác rất thường xuyên: không animate chiều cao (dàn trang
     lại ảnh lớn ở mỗi khung hình). Thanh chỉ mờ dần; khung ảnh đổi cỡ đúng 1 lần — lúc ẩn thì
     đợi mờ xong (.18s) mới đổi, lúc hiện thì đổi ngay. */
  .lb.open.chrome-off { padding-bottom: 0; transition: padding-bottom 0s .18s; }
  /* Sheet nhận xét che mất nửa dưới khung ảnh. Chèn đúng chiều cao sheet vào đáy .lb
     để hàng ảnh (minmax(0,1fr)) co lại — ảnh/video bị đẩy hẳn lên phần còn trống thay
     vì nằm khuất sau sheet. --sheet-h do JS đo bằng ResizeObserver, sheet cao thấp
     theo số nhận xét nên không thể đặt cứng trong CSS. */
  /* +var(--kb-inset): sheet giờ tự trồi lên theo bàn phím (xem .panel bên dưới), nên
     ảnh cũng phải chừa thêm đúng ngần ấy, không thì đúng khoảng bàn phím đẩy sheet lên
     đó sẽ lộ ra ảnh/dải phim tĩnh phía sau (chúng không tự trồi theo bàn phím). */
  .lb.open.panel-on { padding-bottom: calc(var(--sheet-h, 60px) + var(--kb-inset, 0px)); }

  .lb-head {
    height: calc(48px + var(--safe-t));
    padding: var(--safe-t) 8px 0; gap: 6px;
    background: rgba(15, 17, 22, .9);
    transition: opacity .18s ease;
  }
  /* Mobile ưu tiên đúng một thông tin: tên file đang xem. Breadcrumb dự án đã có ở màn
     danh sách nên bỏ khỏi topbar để tránh cắt tên file và dồn các nút thao tác. */
  .lb-head .lb-crumb .cr-root, .lb-head .lb-crumb .cr-sep { display: none; }
  .lb-head .lb-crumb { min-width: 0; font-size: 13px; gap: 0; }
  .lb-head .lb-crumb .cr-file { min-width: 0; font-weight: 600; }
  /* Không dùng overflow:hidden để giấu thanh trên. .lb-acts nằm bên trong thanh này
     nhưng lại định vị tuyệt đối theo .lb — overflow của thanh trên không cắt được nó,
     nên phải giấu bằng opacity + visibility (cả hai cùng ẩn, đúng ý đồ). */
  .lb.chrome-off .lb-head {
    height: 0; opacity: 0; visibility: hidden;
    border-bottom-width: 0;
    transition: opacity .18s ease, visibility 0s .18s, height 0s .18s, min-height 0s .18s,
      padding 0s .18s, border-bottom-width 0s .18s;
  }
  .lb-head { flex-wrap: wrap; }
  /* Thanh trên có flex-wrap để chứa hàng sao riêng trên điện thoại. Ô tên file để flex-basis:auto thì
     kích thước giả định của nó rộng bằng cả tên file — không vừa dòng 1 nên bị đẩy hẳn
     xuống dòng riêng, bỏ ✕ đứng một mình ở dòng trên. flex:1 1 0 ép nó co lại nhường chỗ
     cho ✕ và ⋯ để cả ba luôn nằm chung một dòng. */
  .lb-head > div:not(.spacer):not(.lb-acts):not(.ver-pick):not(.lb-meta-row) { flex: 1 1 0; }
  /* .spacer thừa khi tên file đã tự giãn — giữ lại thì nó chiếm chỗ và lại đẩy ⋯ xuống dòng */
  .lb-head > .spacer { display: none; }
  /* ✕ và ⋯: ô chạm 44px, glyph to lên cho dễ nhắm (cỡ chữ .btn mặc định quá nhỏ) */
  #lbClose, #albClose {
    width: 36px; height: 36px; min-width: 36px; border-radius: 11px; font-size: 19px;
  }
  .lb-head .ver-pill {
    height: 34px; min-width: 34px; padding: 0 7px; border-radius: 11px; justify-content: center;
    background: var(--bg-2); border-color: var(--line-soft);
  }
  /* Không để lại một nút mũi tên vô nghĩa trong lúc dữ liệu phiên bản đang tải hoặc
     API cũ chưa trả được số phiên bản. Khi nhãn v2/v3 có giá trị, pill tự hiện lại. */
  #lbVerPick:has(#lbVerLabel:empty) { display: none; }
  /* Trình xem của studio có bản sao sao đánh giá trên điện thoại — #albMore đứng
     lại dòng 1 nhờ order thấp hơn. #albStarsTop đồng bộ với #albStars
     (đã ẩn trên điện thoại) qua data-aid — xem paintViewer() trong admin.js. */
  #albMore { order: 1; }
  .lb-meta-row {
    order: 5; flex: 1 1 100%; display: flex; align-items: center;
    justify-content: flex-end; gap: 8px; min-width: 0;
  }
  #albStarsTop { display: block; flex: none; }
  #albStarsTop .stars { gap: 7px; }
  #albStarsTop .star { font-size: 20px; }
  #albColorTagTop { display: inline-flex; flex: none; padding: 8px; }
  #albColorTagTop .ctag-dot { width: 15px; height: 15px; }
  /* Cụm sao gốc trong .lb-acts đã có bản sao ở hàng trên (trang quản trị) — ẩn đi để khỏi
     lặp lại dưới thanh dưới cùng. Chỉ áp dụng cho #alb — trang khách (#lb) không có bản
     sao này nên vẫn giữ nguyên cụm sao trong .lb-acts như cũ. Cùng lý do cho #albColorTag. */
  #alb .lb-acts #albStars, #alb .lb-acts #albColorTag { display: none !important; }
  /* Không ghi đè mất safe-area của .lb-head: trên iPhone thật phần này phải nằm dưới
     đồng hồ/Dynamic Island, kể cả khi Admin có thêm hàng metadata thứ hai. */
  #alb .lb-head {
    height: auto; min-height: calc(52px + var(--safe-t));
    padding: calc(6px + var(--safe-t)) 8px 6px;
  }
  #alb.chrome-off .lb-head { height: 0; min-height: 0; padding-top: 0; padding-bottom: 0; }

  /* nhóm hành động tụt xuống thành thanh dưới */
  .lb-acts {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 6;
    height: calc(56px + var(--safe-b));
    padding: 6px 10px calc(6px + var(--safe-b));
    gap: 8px; background: var(--bg-1); border-top: 1px solid var(--line-soft);
    -webkit-backdrop-filter: none; backdrop-filter: none;
    overflow: hidden; transition: opacity .18s ease;
  }
  /* .lb-acts thừa hưởng opacity/visibility của thanh trên, chỉ cần co chiều cao về 0 */
  .lb.chrome-off .lb-acts { height: 0; padding-bottom: 0; border-top-width: 0;
    transition: opacity .18s ease, height 0s .18s, padding-bottom 0s .18s, border-top-width 0s .18s; }
  /* Sheet nhận xét đã mở thì thanh pill khỏi hiện song song nữa — đóng sheet bằng tay
     kéo/vuốt trên .p-head (xem admin.js/share.js), không cần bấm lại thanh này. */
  .lb.panel-on .lb-acts { height: 0; padding-bottom: 0; border-top-width: 0; opacity: 0; pointer-events: none; }
  .lb-acts #lbStars { flex: 1 1 0; min-width: 0; }
  .lb-acts .stars { justify-content: center; gap: 4px; }
  .lb-acts .stars .star { font-size: 20px; padding: 4px 1px; }
  .lb-acts .ctag-btn.lb-ctag { padding: 8px; }
  .lb-acts .ctag-btn.lb-ctag .ctag-dot { width: 15px; height: 15px; }
  .lb-acts .btn { height: var(--tap); padding: 0 10px; font-size: 13px; flex: none; }
  /* Tải về và Chia sẻ đã chuyển vào menu ⋯ */
  .lb-acts #lbDl, .lb-acts #albDl, .lb-acts #albShare { display: none !important; }

  /* Công tắc panel trên điện thoại: phẳng hoàn toàn trên thanh đáy, chỉ giữ icon,
     số bình luận và chevron. Không dùng pill/bóng/hiệu ứng dịch tạo cảm giác 3D. */
  .lb-acts .compose-trigger {
    flex: 1.15 1 0; min-width: 0; height: 40px; padding: 0 12px; gap: 7px;
    display: flex; align-items: center; justify-content: center;
    background: transparent !important; border: 0; border-radius: 0; box-shadow: none;
  }
  @media (hover: hover) and (pointer: fine) { .lb-acts .compose-trigger:hover { background: transparent !important; } }
  .lb-acts .compose-trigger:active { transform: none; background: transparent !important; }
  .compose-trigger .panel-ic { display: block; flex: none; color: var(--txt-3); }
  .compose-trigger .panel-label { display: none; }
  .compose-trigger .cmt-count {
    display: block; flex: none; font-size: 14px; font-weight: 600; color: var(--txt-2);
  }
  .compose-trigger .cmt-chevron { display: block; flex: none; color: var(--txt-3); }

  /* khung ảnh: lấy lại 24px mỗi chiều */
  .stage img, .stage video { inset: 8px; max-width: calc(100% - 16px); max-height: calc(100% - 16px); }
  /* đã có vuốt để chuyển ảnh, cụm nút này thừa và chật chỗ trên thanh đầu vốn đã hẹp */
  .lb-nav { display: none; }
  .zoombar { display: none; }
  .qbar { height: 38px; font-size: 13px; }
  /* thanh chạy video: to tay hơn, chữ số/icon lớn hơn cho dễ bấm/dễ đọc trên điện thoại */
  .vs-track { margin: 18px 11px 14px; }
  .vs-track::before { top: -18px; bottom: -18px; }
  .vs-play, .vs-mute { width: var(--tap); height: var(--tap); }
  /* thêm ô tốc độ phát: thu gọn hàng điều khiển để 2 ô 1x/720p không tràn khỏi màn hình 375px */
  .vs-row { gap: 4px; }
  .vs-row .qbar { height: 34px; padding: 0 20px 0 8px; background-position: right 5px center; font-size: 12.5px; }
  .vs-mute { width: 36px; }
  .vs-loop { width: 30px; }
  .vs-play svg, .vs-mute svg { width: 25px; height: 25px; }
  .vs-time { font-size: 13px; }

  /* dải ảnh nhỏ: ẩn mặc định, bật từ menu ⋯ */
  .lb .filmstrip { display: none; }
  .lb.strip-on:not(.chrome-off) .filmstrip { display: flex; }

  /* ---------- panel góp ý thành sheet trượt lên ---------- */
  .lb-body, .lb-body.with-panel { grid-template-columns: minmax(0, 1fr); }
  .panel {
    /* Trồi lên đúng bằng --kb-inset khi bàn phím mở, để mép dưới sheet luôn chạm sát
       mép trên bàn phím — không thì sheet vẫn dính đáy MÀN HÌNH THẬT (khuất sau bàn
       phím), còn --kb-inset trước đây chỉ đẩy NỘI DUNG bên trong (.p-foot) lên bằng
       padding chứ khung sheet đứng yên: max-height vẫn tính theo 62dvh tĩnh (không co
       theo bàn phím) nên sheet không cao thêm để bù, hở hẳn 1 khoảng giữa khung soạn
       và bàn phím lộ ra trang phía sau (bug người dùng chụp lại được). Dời cả khung
       lên thì phần ảnh phía sau cũng phải chừa thêm đúng ngần đó (xem .lb.open.panel-on
       phía trên) không thì tới lượt ẢNH bị lộ ra ở đúng khoảng vừa hở. */
    position: fixed; left: 0; right: 0; bottom: var(--kb-inset, 0px); z-index: 95;
    /* var(--panel-max-h) do JS tính từ visualViewport.height (đã trừ bàn phím) — 62dvh
       chỉ còn là giá trị dự phòng trước khi JS chạy lần đầu, vì dvh không tự co theo
       bàn phím nên dùng riêng nó sẽ lại dính đúng bug max-height không theo kịp. */
    max-height: var(--panel-max-h, 62dvh); border-left: none; border-top: 1px solid var(--line);
    border-radius: 18px 18px 0 0; box-shadow: 0 -12px 40px rgba(0, 0, 0, .6);
    transform: translateY(101%); transition: transform .24s var(--ease-drawer);
  }
  .lb-body.with-panel .panel { transform: translateY(0); }
  /* tay nắm kéo ở mép trên sheet — bấm vào đây cũng đóng sheet lại */
  .panel .p-head { position: relative; padding-top: 18px; cursor: pointer; }
  .panel .p-head::before {
    content: ''; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
    width: 40px; height: 4px; border-radius: 6px; background: #3a3f4d;
  }
  /* Không cộng thêm --kb-inset ở đây nữa: giờ CẢ KHUNG .panel đã tự trồi lên theo
     bàn phím (xem .panel), .p-foot chỉ còn cần chừa safe-area đáy màn hình như bình
     thường — cộng thêm nữa sẽ đẩy ô Gửi lên cao dư một khoảng bằng đúng --kb-inset. */
  .panel .p-foot { padding: 10px 12px calc(12px + var(--safe-b)); }
  /* Sheet vừa mở ra: chỉ hiện đúng ô nhập để XEM bình luận trước cho gọn, không lộ cả
     cụm Vẽ/đính kèm/emoji/Gửi ngay — chạm vào ô mới hiện đủ (bỏ class này, xem JS
     admin.js/share.js). Không tự động focus ô khi mở sheet nữa (trước đây có) vì mở
     sheet giờ là để xem trước, không phải để gõ ngay. */
  .panel .p-foot.compose-collapsed .drawbar, .panel .p-foot.compose-collapsed .row { display: none; }
  .panel .p-foot.compose-collapsed textarea.input { min-height: 44px; }
  /* Composer mới luôn giữ hàng công cụ tối giản như Frame.io; không còn trạng thái mở rộng
     thành ba hàng sau khi focus. */
  .panel .p-foot.comment-composer.compose-collapsed .drawbar { display: flex; }
  .panel .p-foot.comment-composer.compose-collapsed .compose-actions { display: flex; }
  .panel .comment-composer { padding: 9px 10px calc(10px + var(--safe-b)); }
  .comment-composer .drawbar { gap: 2px; }
  .comment-composer .pen, .comment-composer .drawbar > .btn { width: 34px; height: 34px; min-width: 34px; }
  .comment-composer .vis-pick > .btn {
    height: 34px; max-width: 104px; padding: 0 8px; font-size: 13px;
  }
  .comment-composer .vis-pick > .btn svg:first-child {
    width: 20px; height: 20px; margin-right: 6px !important;
  }
  #cmtSend.compose-send, #aCmtSend.compose-send { width: 36px; height: 34px; padding: 0; }

  /* ---------- ô nhập & vùng chạm trong góp ý ---------- */
  /* 16px là bắt buộc: nhỏ hơn thì iOS tự phóng to cả trang khi khách bấm vào ô */
  input.input, textarea.input { font-size: 16px; }
  /* Specificity cao hơn rule composer 14px và !important để CSS tuỳ biến/project
     không vô tình bật lại auto-zoom khi Safari focus ô nhận xét. */
  .comment-composer textarea.input { font-size: 16px !important; }
  .gate-box .input { height: 46px; }
  .gate-box .btn.primary { height: 48px; }
  .drawbar { flex-wrap: wrap; gap: 8px; }
  .swatch { width: 28px; height: 28px; }
  .pen { height: 36px; padding: 0 12px; }
  .drawbar .btn.sm { height: 36px; min-width: 40px; justify-content: center; }
  /* nút chọn kiểu vẽ bị JS chuyển ra khỏi .drawbar khi vào chế độ vẽ toàn màn hình
     (xem setDrawMode trong thread.js), nên phải tự có kích thước, không dựa vào rule trên */
  .btn.tbtn { width: 36px; height: 36px; }
  .emoji-pop {
    position: static; flex: 1 1 100%; width: 100%;
    grid-template-columns: repeat(6, 1fr); max-height: 132px;
  }
  .emoji-pop span { height: 36px; font-size: 20px; }
  .tool-pop button { width: 36px; height: 36px; }
  .tbtn svg, .tool-pop svg { width: 22px; height: 22px; }
  /* ---------- kê mọi thứ dính đáy lên trên vạch home ---------- */
  .toast { bottom: calc(26px + var(--safe-b)); }
  .modal .m-foot { padding-bottom: calc(12px + var(--safe-b)); }
  .modal .m-foot .btn { height: var(--tap); }

  /* ============================================================
     TRANG QUẢN TRỊ
     Thanh trên gọn còn một tầng: logo · tên đang xem · chuông · tài khoản.
     Thao tác dự án nằm trong nút ⋯ ở hàng tiêu đề dự án.
     ============================================================ */

  /* logo bấm được để về trang chủ; chữ SlateFrame nhường chỗ khi đã vào project */
  .topbar .brand { gap: 8px; }
  .topbar .brand .wordmark { font-size: 15px; }
  body.in-project .topbar .brand .wordmark { display: none; }
  #btnMore, #btnNotif, #btnJobs, #albMore { width: var(--tap); height: var(--tap); padding: 0; }
  #btnNotif svg { width: 18px; height: 18px; }
  /* Nút chuông giãn ra 44px cho dễ chạm, huy hiệu phải thụt vào để bám lấy hình cái
     chuông — treo ở góc nút thì nó lấn lên mép trên thanh và bị màn hình cắt mất. */
  #btnNotif .notif-badge { top: 3px; right: 3px; }
  /* ⋯ trong tiêu đề dự án: cỡ chữ .btn mặc định hơi mảnh so với ô chạm 44px */
  #btnMore { font-size: 21px; }
  /* Nút Chia sẻ ở hàng tiêu đề dự án: trên điện thoại chỉ còn icon, đứng cạnh ⋯ */
  .page-head #btnShare { order: 1; width: var(--tap); height: var(--tap); padding: 0; justify-content: center; }
  .page-head #btnShare span { display: none; }

  /* tabs của project nằm ở tầng 2 của thanh trên — dạng segmented control chia đều
     3 ô thay vì hàng chữ rời rạc, đỡ trống trải trên màn hẹp. */
  #viewProject .pj-hero > .tabs {
    margin: 0 0 14px; gap: 2px;
    background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: 10px; padding: 3px;
    overflow-x: auto; scrollbar-width: none;
  }
  #viewProject .pj-hero > .tabs::-webkit-scrollbar { width: 0; height: 0; }
  #viewProject .pj-hero > .tabs .tab {
    flex: 1 1 0; display: flex; align-items: center; justify-content: center;
  }
  #viewProject .pj-hero > .tabs .tab.on { font-weight: 500; }

  /* ---------- tiêu đề trang ---------- */
  .page-head { gap: 8px 10px; margin-bottom: 14px; }
  .page-head #btnBack, .page-head #btnTrashBack {
    order: 1; height: var(--tap); padding: 0 10px; margin-left: -10px; font-size: 13.5px;
  }
  /* #btnInvite mặc định order:0 nên trước đây nhảy lên trước cả nút back (thứ tự
     DOM > order khai báo) — ép cùng order với back rồi đẩy sang mép phải bằng
     margin-left:auto để 2 nút chia đúng 1 hàng, thay vì icon lạc lõng ở góc trên. */
  .page-head #btnInvite { order: 1; margin-left: auto; width: var(--tap); height: var(--tap); }
  #viewProjects .page-head h1 { order: 2; flex: 0 1 auto; }
  #viewProjects .page-head #pjCount { order: 2; }
  #viewProjects .page-head #btnWorkspaceMembers {
    order: 2; margin-left: auto; width: var(--tap); height: var(--tap);
  }
  .page-head #btnMore { order: 1; }
  /* Tiêu đề + số lượng file xếp cột, sát nhau như 1 khối — .ph-title chuyển từ
     display:contents (desktop) sang flex column thật ở đây. */
  .ph-title { display: flex; flex-direction: column; gap: 2px; order: 2; flex: 1 1 100%; }
  /* Trang không dùng .ph-title (VD tiêu đề "Thùng rác") vẫn cần h1 tự xuống hàng riêng
     như cũ; bên trong .ph-title thì h1 chỉ là dòng đầu của khối cột nên bỏ flex/order đó. */
  .page-head h1 { font-size: 21px; flex: 1 1 100%; order: 2; }
  .ph-title h1 { flex: none; order: 0; }
  .page-head .dim { order: 3; }
  .page-head #dCount {
    background: none; padding: 0; height: auto; font-size: 12.5px; color: var(--txt-2);
  }
  .page-head .spacer { display: none; }
  /* Nút tìm/lọc/sắp xếp của Admin dùng chung kích thước và trạng thái với trang khách
     ở khối .fbar phía trên để hai giao diện không lệch nhau khi thay đổi về sau. */
  /* ô tìm kiếm thu gọn: chữ 16px bắt buộc trên điện thoại, không thì iOS tự phóng to trang */
  .search-collapse .input { height: var(--tap); font-size: 16px; }
  /* ---------- thẻ project: một cột ---------- */
  .cards { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  /* Cỡ ô lưới project đổi được qua sheet (S/M/L) — thùng rác giữ nguyên 1 cột, không đổi. */
  #cards { grid-template-columns: repeat(var(--pcols, 1), minmax(0, 1fr)); }
  .card .meta .sub { align-items: center; }
  /* card-actions (mob-only) của thẻ project được thay bằng nút ⋯ nổi trên bìa — xem .card-menu.
     Thùng rác vẫn dùng .card-actions y nguyên (2 nút Khôi phục/Xoá vĩnh viễn, không mob-only). */
  .card-actions { gap: 8px; }
  .card-actions .btn { height: var(--tap); font-size: 13px; justify-content: center; }
  .card .thumb { position: relative; }
  .card-menu {
    position: absolute; top: 8px; right: 8px; z-index: 2;
    width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .62); border: 1px solid rgba(255, 255, 255, .35); border-radius: 8px;
    color: #fff; font-size: 17px; line-height: 1; cursor: pointer; backdrop-filter: blur(4px);
  }

  /* ---------- danh sách project → thẻ dọc ---------- */
  .frow.frow-project.frow-head { display: none; }
  .frow.frow-project {
    min-width: 0;
    grid-template-columns: 64px minmax(0, 1fr) var(--tap);
    grid-template-rows: auto auto;
    gap: 3px 10px; padding: 10px 12px; min-height: 76px;
  }
  .frow-project .fl-thumb { grid-area: 1 / 1 / 3 / 2; width: 64px; height: 64px; border-radius: 6px; align-self: center; }
  .frow-project .fl-name {
    grid-area: 1 / 2 / 2 / 3;
    white-space: normal; font-size: 13.5px; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* ba ô số gộp thành một dòng phụ */
  .frow-project .fl-cmt, .frow-project .fl-rate, .frow-project .fl-size {
    grid-row: 2; font-size: 11.5px; text-align: left;
  }
  .frow-project .fl-cmt { grid-column: 2; justify-self: start; }
  .frow-project .fl-rate { grid-column: 2; justify-self: center; }
  .frow-project .fl-size { grid-column: 2; justify-self: end; }
  .frow-project .fl-date { display: none; }
  .frow-project .fl-menu {
    grid-area: 1 / 3 / 3 / 4; justify-self: end; align-self: center;
    width: var(--tap); height: var(--tap);
    background: transparent; border: none; border-radius: 8px;
    color: var(--txt-2); font-size: 19px; cursor: pointer;
  }

  /* ---------- danh sách ảnh trong project → thẻ dọc ---------- */
  .flist .frow.frow-head { display: none; }
  #dList .frow:not(.frow-head) {
    min-width: 0;
    grid-template-columns: 64px minmax(0, 1fr) var(--tap);
    grid-template-rows: auto auto auto;
    gap: 3px 10px; padding: 10px 12px; min-height: 88px;
  }
  #dList .fl-check { display: none; }
  #dList .fl-thumb { grid-area: 1 / 1 / 4 / 2; width: 64px; height: 64px; border-radius: 6px; align-self: center; }
  #dList .fl-name {
    grid-area: 1 / 2 / 2 / 3;
    white-space: normal; font-size: 13.5px; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  #dList .fl-rate { grid-area: 2 / 2 / 3 / 3; }
  #dList .fl-rate .stars { gap: 5px; }
  #dList .fl-rate .star { font-size: 18px; }
  #dList .fl-cmt { grid-row: 3; grid-column: 2; justify-self: start; font-size: 11.5px; text-align: left; }
  #dList .fl-size { grid-row: 3; grid-column: 2; justify-self: end; font-size: 11.5px; }
  #dList .fl-date, #dList .fl-uploader, #dList .fl-note { display: none; }
  #dList .fl-menu {
    grid-area: 1 / 3 / 4 / 4; justify-self: end; align-self: center;
    width: var(--tap); height: var(--tap);
    background: transparent; border: none; border-radius: 8px;
    color: var(--txt-2); font-size: 19px; cursor: pointer;
  }

  /* ---------- ô ảnh của trang quản trị ---------- */
  #dGrid, #dGridF { gap: 8px; }
  /* Cỡ ô đổi được qua sheet (S/M/L) — thư mục luôn 2 cột như trang khách. */
  #dGrid { grid-template-columns: repeat(var(--dcols, 2), minmax(0, 1fr)) !important; }
  #dGridF { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .folder-menu {
    position: absolute; top: 8px; right: 8px; z-index: 4;
    width: 32px; height: 32px; border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, .35); background: rgba(0, 0, 0, .45);
    backdrop-filter: blur(4px); color: #fff; font-size: 17px; line-height: 1;
    display: grid; place-items: center; cursor: pointer; padding: 0;
  }
  /* Nút ⋯ của ô ảnh: nằm ngay trong hàng sao đánh giá (.tile-rate-row), không đặt tuyệt đối
     trên ảnh nữa để khỏi đè lên nhãn version "v2, v3..." (.ver-tag) ở góc trên-phải. Từ khi
     `.tile-marks` (sao+thẻ màu) tự xuống dòng nhường chỗ (xem .tile-rate-row phía trên) thì nút
     này luôn có nguyên 1 dòng riêng, không còn phải nhường chỗ nữa — giữ cỡ 24px dễ chạm như bản
     gốc, `margin-left:auto` để đẩy sát mép phải trên dòng riêng đó (`justify-content:space-between`
     của hàng cha không tự làm được việc này khi dòng chỉ có đúng 1 phần tử). */
  .tile-menu {
    width: 24px; height: 24px; border-radius: 6px; flex: none; margin-left: auto;
    border: 1px solid var(--line); background: var(--bg-3); color: var(--txt-2);
    font-size: 14px; line-height: 1;
    display: grid; place-items: center; cursor: pointer; padding: 0;
  }
  /* Mobile chọn trực tiếp: ô tích luôn hiện ở góc trái của cả ảnh và thư mục,
     không cần bật một chế độ Chọn trung gian. */
  #dGrid .tile .checkbox, #dGridF .tile .checkbox {
    opacity: 1; pointer-events: auto;
    width: 32px; height: 32px; border-radius: 8px; top: 8px; left: 8px; right: auto; font-size: 15px;
  }
  body.sel-mode .tile-menu { display: none; }

  /* ---------- thanh thao tác hàng loạt của trang quản trị ---------- */
  #aSelbar {
    left: 10px; right: 10px; bottom: calc(16px + var(--safe-b));
    transform: none; flex-wrap: wrap; gap: 8px;
    padding: 10px 12px 12px; border-radius: 14px;
  }
  #aSelbar > .dim { display: none; }
  #aSelCount { flex: 1 1 100%; font-size: 13px; color: var(--txt-2); }
  #aSelDl, #aSelShare, #aSelDel {
    flex: 1 1 30%; height: var(--tap); padding: 0 8px; font-size: 13px; justify-content: center;
  }
  #aSelClear { display: none; }
  body.sel-mode .wrap { padding-bottom: 215px; }

  /* ---------- menu chuột phải → sheet dán đáy ---------- */
  .ctx-mask { position: fixed; inset: 0; z-index: 290; background: rgba(4, 5, 8, .55); animation: fadein .15s ease; }
  .ctxmenu {
    left: 10px !important; right: 10px; top: auto !important;
    bottom: calc(16px + var(--safe-b));
    width: auto; min-width: 0; max-height: 76dvh; overflow-y: auto;
    border-radius: 14px; animation: sheetup .22s var(--ease-drawer);
  }
  .ctx-item { min-height: 48px; padding: 8px 12px; border-radius: 9px; font-size: 14.5px; gap: 10px; }
  .ctx-item svg { width: 17px; height: 17px; flex: none; }
  .ctx-head { padding: 9px 12px 7px; max-width: none; }
  .ctx-ws-summary { width: calc(100% - 12px); margin: 3px 6px 8px; padding: 12px; border-radius: 10px; }
  .ctx-ws-plan { font-size: 13px; }
  .ctx-ws-storage { font-size: 12px; }
  /* Mục dạng chọn một (lọc/sắp xếp/cỡ ô): nhãn giãn hết chỗ, gợi ý phụ nằm bên phải,
     giống hệt .si-lb/.si-hint của trang khách — chỉ khác tên lớp vì dùng chung .ctx-item. */
  .ctx-item .ci-lb { flex: 1; min-width: 0; }
  .ctx-item .ci-hint { flex: none; color: var(--txt-3); font-size: 12.5px; }

  /* ---------- thông báo → sheet dán đáy ---------- */
  .notif-wrap { position: static; }
  .notif-drop {
    position: fixed; left: 0; right: 0; top: auto; bottom: 0; z-index: 260;
    width: auto; max-height: 70dvh;
    border-radius: 18px 18px 0 0; border-bottom: 0;
    animation: sheetup .24s var(--ease-drawer);
    padding-bottom: var(--safe-b); overscroll-behavior: contain; touch-action: pan-y;
  }
  .notif-item { min-height: 48px; padding: 12px 14px; }

  /* ---------- hàng đợi chuyển mã → sheet dán đáy, cùng kiểu với thông báo ---------- */
  .jobs-wrap { position: static; }
  .jobs-pop {
    position: fixed; left: 0; right: 0; top: auto; bottom: 0; z-index: 260;
    width: auto; max-height: 70dvh;
    border-radius: 18px 18px 0 0; border-bottom: 0;
    animation: sheetup .24s var(--ease-drawer);
    padding-bottom: calc(12px + var(--safe-b));
  }
  .jobs-pop-head { font-size: 13px; }
  .jobs-pop .jp-row { padding: 2px 0; }

  /* ---------- hộp thoại ---------- */
  .mask { padding: 16px; }
  .modal { width: 100%; max-height: calc(100dvh - 32px); min-height: 0; display: flex; flex-direction: column; }
  .modal .m-body { max-height: none; flex: 1; min-height: 0; }
  .modal .m-foot { flex: none; }
  .modal .m-foot .btn { flex: 1; justify-content: center; }
  .modal.account-settings-modal .m-body { height: auto; max-height: none; }
  .account-settings-shell { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
  .account-settings-nav {
    flex-direction: row; gap: 6px; padding: 9px 10px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--line-soft); scrollbar-width: none;
  }
  .account-settings-nav::-webkit-scrollbar { display: none; }
  .account-settings-nav button { justify-content: center; min-width: max-content; min-height: 38px; padding: 8px 11px; }
  .account-settings-content { padding: 14px; }
  .account-panel-head { margin-bottom: 13px; }
  .account-profile-card { grid-template-columns: 56px minmax(0, 1fr); gap: 12px; }
  #acctDlgAvatar { width: 56px; height: 56px; }
  .account-profile-card #acctAvatarBtn { grid-column: 1 / -1; width: 100%; justify-content: center; }
  .account-name-row { align-items: stretch; }
  .account-name-row .btn { justify-content: center; }
  .account-plan-card { align-items: flex-start; }
  .account-security-card .btn { width: 100%; justify-self: stretch; justify-content: center; }
  .modal.share-modal .m-body { padding: 0; max-height: none; }
  .share-scope { margin: 14px; }
  .share-section { padding: 0 14px 14px; }
  .share-section + .share-section { padding-top: 14px; }
  .share-section-head { display: grid; gap: 2px; }
  .share-section-head > span { text-align: left; }
  .share-field-grid { grid-template-columns: 1fr; }
  .share-option { min-height: 64px; }
  .share-option input[type="checkbox"] { width: 22px; height: 22px; }
  .workspace-members-dialog #wsMembers .tbl td,
  .workspace-members-dialog #wsMembers .tbl td:first-child,
  .workspace-members-dialog #wsMembers .tbl td:nth-child(2),
  .workspace-members-dialog #wsMembers .tbl td:last-child {
    width: 100%; text-align: left;
  }
  .workspace-members-dialog #wsMembers .tbl td:nth-child(2) { padding-top: 7px; }
  .pending-invite-actions { justify-content: flex-start; }
  /* Project Settings: ảnh bìa thành phần tóm tắt trên cùng, card cài đặt xếp dọc. */
  .modal.project-settings-modal .m-body { max-height: none; }
  .psettings { grid-template-columns: 1fr; min-height: 0; }
  .ps-cover-panel {
    display: grid; grid-template-columns: 100px minmax(0, 1fr); align-items: start;
    gap: 7px 13px; padding: 14px; border-right: 0; border-bottom: 1px solid var(--line-soft);
  }
  .ps-panel-label { grid-column: 1 / -1; margin-bottom: 2px; }
  .ps-cover { grid-column: 1; grid-row: 2 / span 3; width: 100px; }
  .ps-cover-hint { grid-column: 2; margin: 0; text-align: left; }
  .ps-cover-change { grid-column: 2; margin-top: 0; }
  .ps-cover-picker, .ps-project-origin { grid-column: 1 / -1; }
  .ps-project-origin { margin-top: 7px; padding-top: 12px; }
  .ps-fields { gap: 10px; padding: 14px; }
  .ps-card { padding: 13px; }
  .ps-form-grid { grid-template-columns: 1fr; }
  .ps-toggle-card { padding: 0; }
  .ps-switch-row { min-height: 66px; }
  .ps-member-form { grid-template-columns: minmax(0, 1fr) auto; }
  .ps-member-form #psMemberEmail { grid-column: 1 / -1; }
  .ps-member-form #psMemberRole { min-width: 0; }
  /* ---------- phản hồi & link chia sẻ ---------- */
  #tabFeedback .toolbar { gap: 8px; }
  .feedback-sort { width: 100%; margin-left: 0; }
  .feedback-sort span { flex: 1; }
  .feedback-sort .input { width: min(190px, 58%); height: var(--tap); }
  .feedback-list { gap: 10px; padding-top: 10px; }
  .feedback-card { grid-template-columns: 76px minmax(0, 1fr); gap: 10px; padding: 10px; border-radius: 12px; }
  .fb-media { width: 76px; aspect-ratio: 1; }
  .fb-card-head { display: grid; gap: 8px; padding-bottom: 9px; }
  .fb-summary { margin-left: 0; justify-content: flex-start; }
  .fb-chip:first-child { display: none; }
  .fb-comment { padding: 9px; }
  .fb-comment .avatar { width: 22px; height: 22px; }
  .fb-comment .when { display: none; }
  .fb-open-hint { display: none; }

  #tabFeedback .toolbar .btn { flex: 1; height: var(--tap); justify-content: center; font-size: 13px; }

  /* Bảng link chia sẻ có 7 cột — trên điện thoại đổ mỗi hàng thành một thẻ.
     Làm bằng CSS nên loadShares() trong admin.js không phải sửa gì. */
  table.tbl, table.tbl tbody, table.tbl tr, table.tbl td { display: block; width: 100%; }
  table.tbl tr {
    background: var(--bg-1); border: 1px solid var(--line-soft);
    border-radius: 12px; padding: 13px; margin-bottom: 12px;
  }
  table.tbl td { border: none; padding: 3px 0; }

  /* Riêng liên kết chia sẻ: bỏ chiều rộng bảng desktop và trình bày mỗi ô theo cặp
     nhãn–giá trị. Người dùng đọc được toàn bộ thông tin mà không phải trượt ngang. */
  #tabLinks { overflow: visible; padding-bottom: 0; }
}

/* ============================================================
   VẼ TOÀN KHUNG
   Đặt cuối file có chủ đích: chế độ này phải thắng mọi quy tắc lightbox ở trên,
   kể cả trong khối điện thoại (cùng độ ưu tiên thì luật sau thắng).
   ============================================================ */

/* Khung nhận xét, thanh trên/dưới và dải ảnh nhỏ nhường chỗ để ảnh giãn hết màn hình */
.lb.draw-mode .lb-head,
.lb.draw-mode .lb-acts,
.lb.draw-mode .filmstrip,
.lb.draw-mode .panel,
.lb.draw-mode .zoombar,
.lb.draw-mode .qwrap,
.lb.draw-mode .vscrub { display: none !important; }
/* Ẩn thanh trên và dải ảnh bằng display:none nghĩa là chúng rời khỏi lưới, .lb-body
   tụt lên hàng 1. Hàng 1 vốn là "auto" mà .lb-body chỉ chứa con định vị tuyệt đối nên
   nó co về 0 — khung ảnh biến mất. Rút lưới còn đúng một hàng 1fr để .lb-body chiếm hết. */
.lb.draw-mode.open {
  grid-template-rows: minmax(0, 1fr);
  padding-bottom: 0;
}
.lb.draw-mode .lb-body, .lb.draw-mode .lb-body.with-panel { grid-template-columns: minmax(0, 1fr); }

/* Lớp phủ trong suốt: chỉ hai thanh công cụ nhận chạm, giữa khung để trống cho nét vẽ */
.drawmode {
  position: fixed; inset: 0; z-index: 120; pointer-events: none;
  display: flex; flex-direction: column; justify-content: space-between;
}
.dm-bar {
  pointer-events: auto; display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: linear-gradient(rgba(8, 9, 12, .82), rgba(8, 9, 12, 0));
}
.dm-top { padding-top: calc(10px + var(--safe-t)); }
.dm-tools {
  justify-content: center;
  padding: 14px calc(14px + var(--safe-r)) calc(14px + var(--safe-b)) calc(14px + var(--safe-l));
  background: linear-gradient(rgba(8, 9, 12, 0), rgba(8, 9, 12, .82));
}
.dm-n { font-size: 12.5px; color: var(--txt-2); }
.dm-tools .dtools { display: flex; align-items: center; gap: 10px; }

/* ---------- so sánh phiên bản side-by-side (window.createCompareView trong thread.js) ----------
   2 khung độc lập cạnh nhau, mỗi bên tự chọn version riêng, có thể "khoá" (link) để zoom/kéo
   đồng thời cả 2 bên; bấm vào bên nào thì bên đó "focus" (viền tím dưới header), panel nhận
   xét bên dưới lọc đúng theo bên đang focus. Kiểu Frame.io — xem yêu cầu gốc trong hội thoại. */
/* Chừa đúng var(--header-h) phía trên (topbar app) thay vì inset:0 phủ hết màn hình — mở
   compare xong vẫn thấy topbar (logo/tên workspace/tài khoản) như bình thường, không bị che. */
.cmp-overlay {
  position: fixed; top: var(--header-h); right: 0; bottom: 0; left: 0; z-index: 200; background: #08090c;
  display: none;
}
.cmp-overlay.open { display: grid; grid-template-rows: minmax(0, 1fr); }
/* Mở compare THẲNG từ lưới ảnh (không qua trình xem đơn, xem openCompare() trong admin.js)
   thì .topbar chính là thanh đang hiện phía trên khung so sánh — nhưng .topbar tự tạo
   stacking context riêng (z-index 60, xem khối .topbar phía trên), nên popup con của nó
   (#notifDrop, menu đổi workspace...) dù z-index cao cỡ nào cũng chỉ so được với nhau TRONG
   NỘI BỘ topbar, ra ngoài vẫn thua .cmp-overlay (200) — bị compare đè lên, mở ra coi như vô
   hình. Nâng hẳn .topbar lên đây, KHÔNG áp dụng khi mở compare từ trong trình xem đơn (JS chỉ
   gắn class .cmp-only khi .alb/.lb chưa mở) vì lúc đó .topbar phải nằm dưới .alb (100) như
   bình thường — nâng vô điều kiện sẽ khiến .topbar đè lên .lb-head, ra 2 thanh trên chồng nhau. */
body.cmp-only .topbar { z-index: 210; }
/* .cmp-body: cột ảnh/video bên trái + panel nhận xét cố định bên phải (340px, như
   .lb-body.with-panel ở trình xem đơn) trên desktop — cả ảnh lẫn video đều dùng chung 1 layout
   này. Điện thoại đổi lại thành 1 cột, nhận xét tụt xuống dưới cùng bề rộng (media query cuối
   file, cùng ngưỡng 640px với .lb-body). .cmp-head giờ nằm TRONG .cmp-main (không phải hàng
   riêng phủ hết bề ngang overlay) — để nó chỉ trải đúng bề rộng cột ảnh/video, không tràn qua
   đè lên panel nhận xét bên phải (panel có tab Comments/Fields riêng cùng hàng, xem .cmp-cmts). */
.cmp-body { display: grid; grid-template-columns: minmax(0, 1fr) 340px; min-height: 0; }
.cmp-main { display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; min-height: 0; min-width: 0; }
/* min-width:0 + overflow:hidden: .cmp-head là 1 hàng trong lưới nội bộ của .cmp-main (chỉ khai
   grid-template-rows, không khai cột) nên mặc định nó nhận min-width:auto = bề rộng tối thiểu
   theo NỘI DUNG (2 tên file + các nút/pill cố định không co giãn). Cửa sổ hẹp lại làm bề rộng
   cột thật (do .cmp-body chia) nhỏ hơn mức tối thiểu đó — nếu không ép min-width:0 + cắt overflow
   thì .cmp-head (và theo đó .cmp-main) tự phình rộng hơn cột được cấp, tràn đè lên panel nhận xét
   .cmp-cmts bên cạnh (dù .cmp-side-name đã có ellipsis, ellipsis chỉ có tác dụng SAU khi container
   đã co đúng bề rộng, không tự ép container co được). */
.cmp-head { display: flex; align-items: stretch; position: relative; min-width: 0; overflow: hidden; border-bottom: 1px solid var(--line-soft); background: var(--bg-1); }
.cmp-side-head {
  flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px; cursor: pointer;
}
/* Lấn thêm 10px về phía nút ✕ kế bên (đúng bằng margin của .cmp-side-close) — để chữ+pill ở
   giữa canh đúng tâm phần khung ảnh của nó, không lệch theo hướng nút ✕. Bù lại bằng padding
   cùng phía nên chữ+pill không bị xê dịch theo margin âm này. */
.cmp-side-head[data-side="a"] { margin-left: -10px; padding-left: 24px; }
.cmp-side-head[data-side="b"] { margin-right: -10px; padding-right: 24px; }
/* Vạch highlight khi 1 bên đang focus — 1 phần tử THẬT duy nhất (.cmp-focus-bar, không phải
   ::after CSS đoán trước số px cố định) được paintFocusBar() trong thread.js đo TOẠ ĐỘ THẬT
   của nút ✕ + tâm .cmp-tools rồi set left/width trực tiếp mỗi khi đổi focus/đổi số nút hiện
   trong .cmp-tools (ảnh so kiểu trượt hiện thêm 2 nút, video thì ẩn bớt) — nhờ vậy luôn khớp
   chính xác dù .cmp-tools rộng hay hẹp, không còn hụt/lố như ước lượng cố định trước đây. */
.cmp-focus-bar { position: absolute; bottom: -1px; height: 2px; background: var(--accent); pointer-events: none; transition: left .15s, width .15s; }
.cmp-side-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13.5px; color: var(--txt);
}
.cmp-side-verbtn {
  flex: none; display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 8px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 6px;
  color: var(--txt-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .cmp-side-verbtn:hover { color: var(--txt); } }
/* .cmp-tools: bọc chung link + 2 nút chọn kiểu, để cả 3 chắc chắn cùng cỡ/cùng hàng — trước đây
   mỗi nút tự set kích thước riêng (link có thêm <span> lồng bên trong) nên bị lệch hàng nhau. */
.cmp-tools { flex: none; display: flex; align-items: center; gap: 6px; }
.cmp-tool-btn {
  flex: none; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 6px; background: var(--bg-3); color: var(--txt-3); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .cmp-tool-btn:hover:not(.on) { color: var(--txt); } }
.cmp-tool-btn.on { background: var(--accent); color: #fff; }
/* Kiểu trượt bắt buộc luôn khoá link (2 ảnh phải khớp tuyệt đối mới so được) — setMode()
   thêm class .locked lúc đó, nút link tạm thời không bấm tắt được. */
.cmp-link-btn.locked { cursor: default; }
.cmp-side-close { flex: none; margin: 8px 10px; align-self: center; }
/* Chặn bôi chọn khi kéo (pan) từ khung này sang khung kia — WebKit (Safari/app macOS) chỉ hiểu -webkit-user-select,
   thiếu thì cả 2 ảnh bị phủ màu chọn (giống .stage của trình xem đơn). */
.cmp-stage { position: relative; min-height: 0; background: #000; user-select: none; -webkit-user-select: none; }
.cmp-stage-side { position: absolute; inset: 0; display: flex; }
/* .cmp-pane-wrap: 1 bên so sánh = ảnh/video (.cmp-pane, bị setSide() xoá/dựng lại mỗi khi đổi
   version) CHỒNG với lớp vẽ (.cmp-draw, canvas riêng, sống lâu hơn .cmp-pane để giữ nguyên nét
   đang xem lại qua các lần đổi version) — cả 2 đều inset:0 bên trong wrap này. */
.cmp-pane-wrap { flex: 1 1 0; min-width: 0; position: relative; }
.cmp-pane-wrap + .cmp-pane-wrap { border-left: 1px solid var(--line-soft); }
.cmp-pane { position: absolute; inset: 0; overflow: hidden; cursor: grab; }
.cmp-pane:active { cursor: grabbing; }
/* Canvas do draw.js tự đặt left/top/width/height khớp đúng khung ảnh/video (xem syncGeometry()
   trong draw.js) — transform zoom/kéo được applyXf() áp giống hệt .cmp-media để luôn khớp. */
.cmp-draw { position: absolute; pointer-events: none; z-index: 1; transform-origin: center; }
/* width/height:auto + object-fit:contain khai báo tường minh — giống hệt .stage video ở trình
   xem đơn (đã chạy đúng từ trước). Thiếu 2 dòng này thì <video> (khác <img>) có thể không tự
   co theo kích thước thật trong ngữ cảnh position:absolute, co về 0 hoặc cỡ mặc định của trình
   duyệt (300×150) nên nhìn như trống trơn dù vẫn phát/tua bình thường ở dưới. */
.cmp-media {
  position: absolute; top: 50%; left: 50%; max-width: 100%; max-height: 100%;
  width: auto; height: auto; object-fit: contain;
  transform-origin: center; user-select: none; -webkit-user-select: none; -webkit-user-drag: none; pointer-events: none;
}
/* Kiểu trượt/wipe: TÁI DÙNG thẳng 2 khung .cmp-pane-wrap đang hiển thị ở kiểu cạnh nhau (ảnh lẫn
   video đều so được, không cần bản sao <img> riêng như trước — xem wireSlider() trong thread.js).
   .slider-on chồng khít 2 khung lên nhau (thay vì cạnh nhau), khung A nằm trên + bị clip-path cắt
   còn đúng % bên trái theo tay cầm kéo (JS tính trong paintSlider()), khung B nằm dưới hiện trọn
   — lộ A bên trái, B bên phải, khớp đúng thứ tự header trái=A/phải=B. Vùng bị clip-path cắt của A
   không nhận sự kiện chuột nữa nên .cmp-slider-ui (lớp trong suốt phủ khắp, chỉ để bắt thao tác
   kéo/bấm tay cầm) mới cần đặt TRÊN CÙNG — không thì kéo ở vùng đã lộ B sẽ lọt xuống pane B thay
   vì được lớp này bắt trước để pan chung cả 2 bên. */
.cmp-stage-side.slider-on .cmp-pane-wrap { position: absolute; inset: 0; border-left: none; }
.cmp-stage-side.slider-on .cmp-pane-wrap[data-side="b"] { z-index: 0; }
.cmp-stage-side.slider-on .cmp-pane-wrap[data-side="a"] { z-index: 1; }
.cmp-slider-ui { position: absolute; inset: 0; overflow: hidden; touch-action: none; cursor: grab; z-index: 2; }
.cmp-slider-ui:active { cursor: grabbing; }
.cmp-slider-handle {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 28px; margin-left: -14px;
  cursor: ew-resize; z-index: 2;
}
.cmp-slider-handle::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; margin-left: -.5px;
  background: rgba(255, 255, 255, .8);
}
/* Tay cầm chỉ là 1 viên nang trắng nhỏ ở giữa đường chia — tinh giản, không vòng tròn/mũi tên
   như trước (đã to và rối mắt hơn cần thiết). */
.cmp-slider-handle::after {
  content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 6px; height: 36px; border-radius: 6px; background: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
}
.cmp-zoombar {
  display: flex; align-items: center; justify-content: center; gap: 6px; padding: 7px;
  border-top: 1px solid var(--line-soft); background: var(--bg-1);
}
.cmp-zoombar button {
  width: 28px; height: 28px; border-radius: 7px; border: none; background: var(--bg-3);
  color: var(--txt-2); cursor: pointer; display: flex; align-items: center; justify-content: center;
}
@media (hover: hover) and (pointer: fine) { .cmp-zoombar button:hover { color: var(--txt); } }
.cmp-zoompct { min-width: 44px; text-align: center; font-size: 12.5px; color: var(--txt-2); cursor: pointer; }
/* .cmp-scrub dùng chung class .vscrub với thanh tua ở trình xem đơn để thừa hưởng style (track,
   nút play/mute...) — nhưng .vscrub có sẵn rule "grid-column:1; grid-row:2" ép theo lưới của
   .lb-body (2 hàng) hoàn toàn khác lưới 4 hàng của .cmp-main, nếu không ghi đè thì .cmp-scrub bị
   nhảy vào đúng ô hàng 2 (chỗ của .cmp-stage!), đẩy khung ảnh/video co về 0 — vỡ hẳn khung xem. */
.cmp-scrub { position: static; grid-column: auto; grid-row: auto; border-top: 1px solid var(--line-soft); }
.cmp-cmts { display: flex; flex-direction: column; min-height: 0; border-left: 1px solid var(--line-soft); background: var(--bg-1); }
/* Tối thiểu 50px khớp .cmp-head (do nút ✕ .cmp-side-close cao nhất trong hàng đó quyết định)
   nhưng cho tự cao thêm (min-height, không phải height cố định) — chữ "Nhận xét" giờ to/đậm
   bằng trình xem đơn (.panel .p-head: font-weight 600, kế thừa cỡ chữ gốc 14px của body),
   còn tên bản/tệp bên dưới chỉ là phụ nên nhỏ + mờ hơn — cần thêm chỗ cho 2 dòng, không ép
   co lại 1 dòng như trước nữa. */
.cmp-cmts-head {
  flex: none; min-height: 50px; box-sizing: border-box; display: flex; flex-direction: column;
  justify-content: center; gap: 3px; padding: 10px 14px; font-size: 14px; line-height: 1.3;
  color: var(--txt); border-bottom: 1px solid var(--line-soft);
}
/* Tên file có thể là 1 chuỗi dài không khoảng trắng (ID Pinterest, hash...) — không có
   overflow-wrap thì trình duyệt không tìm được chỗ ngắt dòng, chuỗi tràn ngang ra khỏi cột
   340px cố định của .cmp-cmts, đẩy vỡ layout panel nhận xét bên phải. */
.cmp-cmts-head, .cmp-cmts-sub { overflow-wrap: anywhere; }
.cmp-cmts-head b { font-weight: 600; }
.cmp-cmts-head .cmp-cmts-sub { color: var(--txt-2); font-size: 12.5px; font-weight: 400; }
.cmp-cmts-list { flex: 1 1 auto; overflow-y: auto; padding: 4px 14px; }
/* Ô soạn dùng CHUNG một bộ style với trình xem đơn: khung so sánh cũng gắn class
   .comment-composer (+ .admin-composer/.share-composer) nên chỉ cần thêm selector này vào
   quy tắc .panel .comment-composer ở trên là ra đúng bố cục hai hàng — ô nhập ở trên,
   thanh công cụ + cụm gửi chung 1 hàng lưới (xem .compose-actions) ở dưới. Ở đây chỉ còn phần
   riêng của khung so sánh: không co lại và có đường kẻ ngăn với danh sách nhận xét. */
.cmp-cmts-compose { flex: none; border-top: 1px solid var(--line-soft); }
/* .cmp-nocmts: tắt hẳn cột panel — .cmp-body chỉ còn 1 cột full-width cho khung ảnh/video. Bật
   qua nút "Nhận xét" sẵn có ở .lb-head (xem toggleCmts() trả về từ createCompareView trong
   thread.js + wiring ở admin.js/share.js), không có nút riêng trong khung so sánh nữa. */
.cmp-overlay.cmp-nocmts .cmp-body { grid-template-columns: minmax(0, 1fr); }
.cmp-overlay.cmp-nocmts .cmp-cmts { display: none; }
@media (max-width: 640px) {
  .cmp-side-name { display: none; }
  .cmp-body { grid-template-columns: minmax(0, 1fr); }
  .cmp-cmts { border-left: none; border-top: 1px solid var(--line-soft); max-height: 30vh; }
}

/* ---------- nút Theo dõi trên trang khách (chỉ hiện với link Live Capture, xem share.js) ----------
   xanh nhấp nháy = đang nhận đẩy tức thì; vàng = đang hỏi theo nhịp (proxy chặn kết nối dài);
   xám = mất kết nối. Chỉ đặt trong .lb-head (khung xem toàn màn hình, xem share.html) — nút chỉ
   có ý nghĩa khi khách đang xem 1 ảnh, không lặp ở topbar lưới ảnh. */
.live-dot {
  width: 9px; height: 9px; border-radius: 3px; flex: none;
  background: var(--txt-3); margin-right: 4px; display: inline-block;
}
.live-dot[data-mode="sse"] { background: #35c07a; animation: live-pulse 1.8s ease-in-out infinite; }
.live-dot[data-mode="poll"] { background: #d9a441; }
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .live-dot[data-mode="sse"] { animation: none; }
}
.live-follow-btn[aria-pressed="false"] { opacity: .6; }

/* ---------- tab "Live Capture" bên admin (renderLive() trong admin.js) ----------
   .card dùng cho thẻ DỰ ÁN có thể bấm (padding chỉ nằm ở .card .meta, không phải .card),
   dùng lại cho khối tĩnh sẽ ra chữ sát viền + con trỏ bấm/nhấc lên vô nghĩa — nên tách riêng
   class này, có padding + không bắt sự kiện bấm. */
.lc-card {
  background: var(--bg-1); border: 1px solid var(--line-soft);
  border-radius: 12px; padding: 16px;
}
/* Bố cục mới (danh sách Session, thẻ Live nổi bật, số liệu) nằm ở khối Nocturne cuối file */


/* ---------- Trang khách, điện thoại: thanh dưới gọn một hàng icon (2026-09-25) ----------
   Trước đây thanh dưới nhét cả chữ "Đang theo dõi" lẫn "Chưa có bình luận" + mũi tên cạnh hàng
   sao giãn hết chỗ → tràn, các phần đè lên nhau. Làm lại theo kiểu Capture One Live: một hàng
   icon căn giữa — theo dõi (icon + chấm trạng thái) · thẻ màu · 5 sao · bình luận (chỉ số).
   Chỉ áp dụng #lb (trang khách); trình xem của studio (#alb) giữ nguyên. */
@media (max-width: 640px) {
  #lb .lb-acts { justify-content: center; gap: 14px; padding-left: 12px; padding-right: 12px; }
  #lb .lb-acts .live-follow-dot { order: 0; }
  #lb .lb-acts .live-follow-btn { order: 0; }
  #lb .lb-acts #lbColorTag { order: 1; }
  #lb .lb-acts #lbStars { order: 2; flex: none; }
  #lb .lb-acts .compose-trigger { order: 3; }

  /* Theo dõi: chỉ icon mắt, chấm trạng thái đè nhỏ ở góc trên phải thay vì đứng riêng. */
  #lb .lb-acts .live-follow-btn {
    position: relative; width: 40px; min-width: 40px; height: 40px; padding: 0;
    justify-content: center; background: transparent; border: 0; box-shadow: none;
  }
  #lb .lb-acts .live-follow-btn svg { width: 22px; height: 22px; color: var(--txt-2); }
  #lb .lb-acts .live-follow-label { display: none; }
  #lb .lb-acts .live-follow-dot {
    position: relative; width: 8px; height: 8px; margin: 0 -18px 0 0;
    align-self: flex-start; margin-top: 10px; z-index: 1; pointer-events: none;
  }

  #lb .lb-acts .stars { gap: 6px; }
  #lb .lb-acts .stars .star { font-size: 22px; padding: 4px 1px; }

  /* Bình luận: icon + con số (data-n do share.js đặt), không chữ, không mũi tên. */
  #lb .lb-acts .compose-trigger { flex: none; width: auto; padding: 0 6px; gap: 5px; }
  #lb .lb-acts .compose-trigger .cmt-chevron { display: none; }
  #lb .lb-acts .compose-trigger .cmt-count { font-size: 0; }
  #lb .lb-acts .compose-trigger .cmt-count::after {
    content: attr(data-n); font-size: 14px; font-weight: 600; color: var(--txt-2);
  }
  #lb .lb-acts .compose-trigger .cmt-count[data-n="0"]::after { content: ""; }
  #lb .lb-acts .compose-trigger .panel-ic { width: 22px; height: 22px; }
}
/* Máy hẹp (iPhone SE 320px): cùng hàng icon nhưng khít hơn để không tràn mép. */
@media (max-width: 360px) {
  #lb .lb-acts { gap: 8px; padding-left: 8px; padding-right: 8px; }
  #lb .lb-acts .stars { gap: 3px; }
  #lb .lb-acts .stars .star { font-size: 20px; }
}
/* Điện thoại (khách lẫn admin): bỏ hẳn dải ảnh nhỏ (yêu cầu 2026-09-25, mở rộng sang admin
   2026-09-28) — chuyển ảnh bằng vuốt, giống Capture One Live. Ẩn luôn nút bật/tắt dải ảnh
   trên thanh đầu để khỏi còn nút vô tác dụng. */
@media (max-width: 640px) {
  #lb .filmstrip, #lb.strip-on .filmstrip,
  #alb .filmstrip, #alb.strip-on .filmstrip { display: none !important; }
}

/* ==========================================================================
   Nocturne — giao diện mới (thiết kế "Slate Frame Admin", Claude Design, 2026-09-25)
   Lớp này đè lên toàn bộ phần trên: đổi token màu/chữ, đổi kiểu nút/ô nhập/thẻ/popover,
   thêm thanh bên trái cho trang quản trị trên desktop (≥1024px) và trang Live Capture.
   Áp dụng chung cho admin.html và share.html (trang khách + trang Live /live/:token).
   ========================================================================== */
:root {
  --bg: #161826;          /* nền chính */
  --bg-1: #1c1e2b;        /* bề mặt nổi: thẻ, ô nhập, popover */
  --bg-2: #232532;        /* bề mặt đặc: ô ảnh, avatar */
  --bg-3: #2a2c3b;
  --side: #131521;        /* thanh bên */
  --line: rgba(233, 233, 237, .18);
  --line-soft: rgba(233, 233, 237, .09);
  --hover: rgba(233, 233, 237, .06);
  --txt: #e9e9ed;
  --txt-1: #e9e9ed;
  --txt-2: #a9abb9;
  --txt-3: #858899;
  --accent: #9184d9;
  --accent-hi: #a79be6;
  --ink: #d2cefd;         /* chữ trên nền nhấn / link */
  --tint: rgba(145, 132, 217, .14);
  --on-accent: #161826;
  --ok: #7fcfa0;
  --warn: #e6c35c;
  --danger: #e8959a;
  --shadow: 0 0 0 1px #3f424d, 0 16px 40px rgba(0, 0, 0, .6);
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
html, body { font-family: var(--font); font-size: 14px; }
::-webkit-scrollbar-thumb { background: #33364a; border-color: var(--bg); }
a.link, .link { color: var(--ink); }
.muted { color: var(--txt-2); }
.dim { color: var(--txt-3); }

/* ---------- chữ thương hiệu ---------- */
.wordmark { font-family: var(--font); font-weight: 600; font-size: 16px; letter-spacing: -.02em; }
.wordmark .w-frame { color: var(--ink); }

/* ---------- nút: viền mảnh, nút chính là viền tím + chữ tím nhạt ---------- */
.btn {
  height: 36px; padding: 0 14px; gap: 6px;
  background: transparent; border: 1px solid var(--line); border-radius: 8px;
  font-size: 13.5px; color: var(--txt);
  transition: background-color .12s ease, border-color .12s ease, color .12s ease, opacity .12s ease, transform .16s var(--ease-out);
  touch-action: manipulation;
}
@media (hover: hover) and (pointer: fine) { .btn:hover { background: var(--hover); } }
/* Nhấn là co nhẹ — giao diện "nghe thấy" cú bấm ngay lúc ngón tay chạm, không đợi nhả ra */
.btn:active { transform: scale(.97); background: rgba(233, 233, 237, .1); }
.btn:disabled:active { transform: none; }
.btn, .sheet-item { -webkit-tap-highlight-color: transparent; }
.btn.primary { background: transparent; border-color: var(--accent); color: var(--ink); font-weight: 500; }
@media (hover: hover) and (pointer: fine) { .btn.primary:hover { background: var(--tint); } }
.btn.primary:active { background: rgba(145, 132, 217, .22); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--txt-2); }
@media (hover: hover) and (pointer: fine) { .btn.ghost:hover { background: var(--hover); color: var(--txt); } }
.btn.danger { border-color: var(--danger); color: var(--danger); background: transparent; }
@media (hover: hover) and (pointer: fine) { .btn.danger:hover { background: rgba(232, 149, 154, .1); } }
.btn.sm { height: 32px; font-size: 13px; }
/* Nút gửi nhận xét: vuông, icon giữa — luật .btn.sm ở trên không được đè lề/kích thước của nó */
.comment-composer .btn.compose-send, .btn.compose-send { width: 34px; height: 32px; padding: 0; display: grid; place-items: center; }
.btn.icon { width: 36px; padding: 0; justify-content: center; }
.btn.sm.icon { width: 32px; }

/* ---------- ô nhập ---------- */
.input, textarea.input, select.input {
  height: 36px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px;
  font-size: 13.5px; color: var(--txt); caret-color: var(--accent);
}
@media (hover: hover) and (pointer: fine) { .input:hover { border-color: rgba(233, 233, 237, .3); } }
.input:focus { border-color: var(--accent); }
.input::placeholder { color: var(--txt-3); }
label.field > span { color: var(--txt-2); font-size: 12.5px; }

/* ---------- chip / nhãn ---------- */
.chip { height: 22px; padding: 0 8px; border-radius: 6px; background: var(--hover); color: var(--txt-2); font-size: 12.5px; }
.chip.acc { background: var(--tint); color: var(--ink); }
.chip.warn { background: rgba(230, 195, 92, .12); color: var(--warn); }

/* ---------- thanh trên ---------- */
.topbar { height: 56px; padding: 0 24px; gap: 12px; border-bottom: 1px solid var(--line-soft); }
.topbar::before { background: rgba(22, 24, 38, .9); }
.crumb { font-size: 13.5px; color: var(--txt-2); }
.crumb b { color: var(--txt); font-weight: 400; }
.crumb .cr-root { display: none; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .crumb .cr-root:hover { color: var(--txt); } }
.crumb .sep { color: var(--txt-3); }
.notif-badge { background: var(--accent); color: var(--on-accent); font-weight: 600; }

/* ---------- khung trang ---------- */
.page-head { gap: 12px; margin-bottom: 20px; }
.page-head h1 { font-size: 26px; line-height: 1.2; font-weight: 500; letter-spacing: -.015em; }
.page-head #pjCount, .page-head #trCount { font-size: 14px; color: var(--txt-3); }
.fbar { gap: 10px; margin: 0 0 20px; }
.toolbar { border-bottom: 0; padding: 0; margin: 16px 0; }

/* ---------- tab: gạch chân, không nền ---------- */
.tabs { gap: 24px; border-bottom: 1px solid var(--line-soft); }
.tab {
  display: inline-flex; align-items: center; gap: 6px; height: 40px; padding: 0;
  border-radius: 0; border-bottom: 2px solid transparent; margin-bottom: -1px;
  font-size: 14px; color: var(--txt-2); background: none;
}
@media (hover: hover) and (pointer: fine) { .tab:hover { color: var(--txt); } }
.tab.on { background: none; color: var(--txt); border-bottom-color: var(--accent); }
.tab .dim { min-width: 0; height: auto; padding: 0; margin: 0; background: none; color: var(--txt-3); font-size: 12.5px; }
#viewProject .pj-hero > .tabs { margin: 18px 0 16px !important; }

/* ---------- thẻ dự án ---------- */
.cards { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 16px; }
.card { background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: 12px; }
@media (hover: hover) and (pointer: fine) { .card:hover { transform: none; border-color: var(--line); } }
.card .thumb { background-color: var(--bg-2); }
.card .meta { padding: 12px 14px 14px; }
.card .meta h3 { font-size: 15px; font-weight: 500; line-height: 1.3; margin-bottom: 6px;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.card .meta .sub { font-size: 12.5px; color: var(--txt-2); }
.project-card-stats { gap: 4px 14px; }
.project-stat, .project-stat-link, .project-stat-comment {
  min-height: 0; padding: 0; border: 0; background: none; border-radius: 0;
  font-size: 12.5px; color: var(--txt-2); gap: 5px;
}
.project-stat svg { width: 13px; height: 13px; }
.project-stat b, .project-stat-link b { color: var(--txt-2); font-weight: 400; }
.project-stat-comment, .project-stat-comment b { color: var(--ink); font-weight: 400; }
.project-created { display: block; font-size: 12px; color: var(--txt-3); margin-top: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.project-created time, .project-created span { color: var(--txt-3); }
.shared-title { font-size: 16px; font-weight: 500; color: var(--txt); letter-spacing: 0; text-transform: none; }
.viewtoggle { padding: 3px; gap: 0; border: 1px solid var(--line-soft); border-radius: 8px; }
.vt-btn { width: 30px; height: 28px; border-radius: 6px; color: var(--txt-2); }
.vt-btn.on { background: var(--bg-2); color: var(--txt); }
/* Trang Dự án: nút lưới/danh sách to ngang ô tìm kiếm + ô sắp xếp bên trái (icon 17px như .btn.icon) */

/* ---------- danh sách dạng hàng ---------- */
.flist { border-color: var(--line-soft); border-radius: 12px; }
.frow { border-bottom-color: var(--line-soft); }
.frow-head { color: var(--txt-3); font-size: 12.5px; background: none; }

/* ---------- ô tệp ---------- */
.tile { background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: 10px; }
@media (hover: hover) and (pointer: fine) { .tile:hover { border-color: var(--line); } }
.tile .ph { background: var(--bg-2); }
.tile .cap { border-top: 0; padding: 9px 11px 2px; font-size: 13px; color: var(--txt); }
.tile .cap .nm { font-weight: 500; }
.tile.picked .ph::after { background: rgba(145, 132, 217, .22); box-shadow: inset 0 0 0 2px var(--accent); }
.stars .star { color: rgba(233, 233, 237, .36); }
.stars .star.on { color: var(--txt); }
.sec-head { font-size: 13.5px; font-weight: 500; color: var(--txt-2); margin: 4px 0 10px; }
.crumbs { font-size: 13.5px; margin-bottom: 16px; }
.crumbs .cr.cur { color: var(--txt); }

/* ---------- trống / kéo thả ---------- */
.empty {
  margin-top: 20px; padding: 48px 24px; border: 1px dashed var(--line); border-radius: 12px;
  color: var(--txt-2);
}
.dropzone { border-color: var(--line); border-radius: 12px; color: var(--txt-2); padding: 56px 24px; }
/* Ô thư mục rỗng dùng lớp .ph.empty (admin/share/live.js) — trùng tên với khung "trống" .empty ngay
   trên nên bị thêm margin/padding/viền đứt, ô cao hơn và lệch hàng tên so với thư mục có ảnh
   (lỗi thật, 2026-09-28). Trả về đúng khung .ph như ô thường. */
.tile.folder .ph.empty { margin: 0; padding: 0; border: 0; border-radius: 0; text-align: initial; }

/* ---------- popover, menu, hộp thoại ---------- */
.ctxmenu, .notif-drop, .jobs-pop, .appearance-pop {
  background: var(--bg-1); border: 0; border-radius: 12px; box-shadow: var(--shadow);
}
.ctxmenu { padding: 6px; }
.ctx-item { padding: 0 10px; min-height: 34px; border-radius: 6px; font-size: 13px; }
@media (hover: hover) and (pointer: fine) { .ctx-item:hover { background: var(--hover); } }
.ctx-item.danger { color: var(--danger); }
@media (hover: hover) and (pointer: fine) { .ctx-item.danger:hover { background: rgba(232, 149, 154, .1); } }
.ctx-head { color: var(--txt-3); }
.ctx-sep { background: var(--line-soft); }
.notif-head { border-bottom: 0; font-size: 14px; font-weight: 500; }
.notif-head .link { color: var(--ink); font-size: 12.5px; }
.notif-filters { border-bottom: 1px solid var(--line-soft); padding: 0 10px 8px; }
.appearance-seg { background: var(--bg-2); }
.appearance-select { background: var(--bg-2); }
.mask { background: rgba(10, 11, 18, .6); }
.modal { background: var(--bg-1); border: 0; border-radius: 14px; box-shadow: var(--shadow); }
.modal h2 { font-size: 20px; font-weight: 500; padding: 20px 20px 6px; border-bottom: 0; }
.modal .m-body { padding: 12px 20px 16px; }
.modal .m-foot { padding: 4px 20px 20px; border-top: 0; gap: 8px; }
.gate-box { background: var(--bg-1); border: 0; box-shadow: var(--shadow); border-radius: 14px; }
.gate-box h1 { font-weight: 500; }
.selbar {
  background: var(--bg-1); border: 0; box-shadow: var(--shadow); border-radius: 12px;
  padding: 8px 8px 8px 16px; gap: 8px;
}
.selbar { white-space: nowrap; }
.selbar > span:first-child { font-weight: 500; margin-right: 8px; }
.toast { background: #262836; border: 0; box-shadow: 0 0 0 1px #3f424d, 0 12px 30px rgba(0, 0, 0, .5); font-size: 13.5px; }
.warnbox { background: var(--tint); border: 0; color: var(--txt); border-radius: 10px; }
.warnbox b { color: var(--ink); font-weight: 500; }
.ws-avatar { background: #423a6a; color: #e7e5fe; font-weight: 600; }

/* ---------- trình xem ---------- */
.lb { background: #10111b; }
.lb-head { background: #10111b; border-bottom-color: var(--line-soft); }
.panel { background: var(--bg); border-left-color: var(--line-soft); }
.panel .p-head, .panel .p-foot { border-color: var(--line-soft); }

/* ---------- thanh bên (chỉ desktop ≥1024px) ---------- */
.sf-side { display: none; }
/* App macOS Slate Frame (class sf-desktop-app do app gắn vào <html>): trang quản trị cuộn trong .sf-main
   thay vì cả trang — để hiệu ứng nảy GỐC của macOS chỉ áp cho vùng nội dung, thanh bên đứng yên (nảy
   của cả trang kéo theo cả thanh bên position:fixed). Mọi JS đọc/đặt vị trí cuộn đi qua
   window.sfScroller()/sfScrollY()/sfScrollTo() trong thread.js. Trình duyệt thường không bị ảnh hưởng. */
html.sf-desktop-app:has(.sf-main), html.sf-desktop-app:has(.sf-main) body { height: 100%; overflow: hidden; }
html.sf-desktop-app .sf-main {
  height: 100vh; overflow-x: hidden; overflow-y: auto;
  overscroll-behavior-y: auto;   /* nảy gốc của macOS chỉ ở đây */
}
/* macOS chỉ nảy khung cuộn khi nó THẬT SỰ cuộn được — trang ngắn (vài dự án, thư mục ít tệp) thì không
   nảy. Nên màn đang hiện luôn cao ít nhất = khung nhìn − các thanh phía trên nó (--sf-chrome-h, admin.js
   đo bằng ResizeObserver) + 2px → luôn cuộn được 2px: đủ để khi nghỉ, trang đứng cách MỖI mép 1px
   (xem sfRestOffEdges trong admin.js). Mắt không thấy vì 1px đó rơi vào phần lề trống. */
html.sf-desktop-app .sf-main > .wrap[id^="view"] { min-height: calc(100vh - var(--sf-chrome-h, 56px) + 2px); }
/* Các khung cuộn con trong app cuộn tới cuối thì dừng, không kéo theo vùng chính / không nảy riêng */
html.sf-desktop-app .sf-side, html.sf-desktop-app .sf-main * { overscroll-behavior: none; }
.sf-ink { color: var(--ink); }
@media (min-width: 1024px) {
  .sf-side {
    position: fixed; left: 0; top: 0; bottom: 0; z-index: 70; width: 236px;
    display: flex; flex-direction: column; gap: 18px; padding: 14px 12px;
    background: var(--side); border-right: 1px solid var(--line-soft); overflow: auto;
  }
  .sf-main { margin-left: 236px; min-width: 0; }
  /* Thanh trên: logo, tên workspace, avatar đã chuyển sang thanh bên */
  .sf-main .topbar .brand, .sf-main #btnAccount, .sf-main .crumb .cr-ws { display: none; }
  .sf-main .crumb .cr-root { display: inline; }
  .sf-main .crumb .cr-root + .sep { margin: 0 8px; }
  .sf-main .wrap { max-width: none; padding: 28px 32px 96px; }
  .sf-main #warnBar, .sf-main #planBar { padding: 16px 32px 0; }
  #btnBack, #btnTrashBack, #btnLiveBack { display: none; }
  .selbar { left: calc(50% + 118px); }
  .toast { left: calc(50% + 118px); }
}
.sf-side button { font: inherit; color: inherit; cursor: pointer; text-align: left; }
.sf-brand {
  display: flex; align-items: center; gap: 10px; padding: 4px 6px; border: 0; background: transparent;
  font-size: 16px !important; font-weight: 600 !important; letter-spacing: -.02em; color: var(--txt) !important;
}
.sf-ws {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; gap: 2px 10px; align-items: center;
  padding: 8px; border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg-1);
}
@media (hover: hover) and (pointer: fine) { .sf-ws:hover { border-color: var(--line); } }
.sf-ws-av {
  grid-row: span 2; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 8px;
  background: #2b2741; color: var(--ink); font-size: 12px; font-weight: 600;
}
.sf-ws-name { font-size: 13.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-ws .sf-caret { grid-row: span 2; }
.sf-ws-sub { grid-column: 2; font-size: 12px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-caret { color: var(--txt-3); flex: none; }
.sf-nav { display: flex; flex-direction: column; gap: 2px; }
.sf-nav button {
  height: 34px; padding: 0 10px; display: flex; align-items: center; gap: 10px;
  border: 0; border-radius: 8px; background: transparent; color: var(--txt-2) !important; font-size: 13.5px;
}
@media (hover: hover) and (pointer: fine) { .sf-nav button:hover { background: var(--hover); color: var(--txt) !important; } }
.sf-nav button.on { background: var(--tint); color: var(--txt) !important; }
.sf-nav button[hidden] { display: none; }
.sf-nav-lb { flex: 1; }
.sf-count { font-size: 12px; color: var(--txt-3); }
.sf-recent { display: flex; flex-direction: column; gap: 2px; }
.sf-label { padding: 0 10px 4px; font-size: 12px; color: var(--txt-3); }
.sf-recent-item {
  width: 100%; height: 32px; padding: 0 10px; display: flex; align-items: center; gap: 10px; min-width: 0;
  border: 0; border-radius: 8px; background: transparent; color: var(--txt-2) !important; font-size: 13px;
}
.sf-recent-item:hover, .sf-recent-item.on { background: var(--hover); color: var(--txt) !important; }
.sf-dot { flex: none; width: 8px; height: 8px; border-radius: 2px; }
/* Ảnh bìa thu nhỏ của dự án trong "Mở gần đây" (thay cho chấm màu cũ) */
.sf-recent-item { height: 36px; }
.sf-recent-thumb {
  flex: none; width: 24px; height: 24px; border-radius: 6px; background: var(--bg-3) center / cover no-repeat;
  box-shadow: inset 0 0 0 1px var(--line-soft); display: grid; place-items: center; color: var(--txt-3);
}
.sf-recent-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-foot { margin-top: auto; }
/* Nhóm Được chia sẻ + Live Capture ở đáy thanh bên, ngay trên ô tài khoản */
.sf-nav-more { margin-top: auto; padding-top: 8px; border-top: 1px solid var(--line-soft); }
.sf-nav-more + .sf-foot { margin-top: 8px; }
.sf-acct {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 6px;
  border: 0; border-radius: 8px; background: transparent;
}
@media (hover: hover) and (pointer: fine) { .sf-acct:hover { background: var(--hover); } }
.sf-acct-av { width: 30px; height: 30px; font-size: 11.5px; }
.sf-acct-av img { width: 30px; height: 30px; }
.sf-acct-txt { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; flex: 1; }
.sf-acct-name { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-acct-role { font-size: 12px; color: var(--txt-3); }

/* ---------- Live Capture ---------- */
.lc-page-head { align-items: flex-end; }
.lc-page-title { display: flex; flex-direction: column; gap: 4px; }
.lc-page-title .muted { font-size: 14px; max-width: 60ch; }
/* Danh sách phẳng: mỗi link Live một hàng — ảnh bìa · tên dự án + số ảnh/hạn · thao tác */
.lc-list { border: 1px solid var(--line-soft); border-radius: 12px; background: var(--bg-1); overflow: hidden; }
.lc-thumb {
  flex: none; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 8px; cursor: pointer;
  background: var(--bg-2) center/cover no-repeat; display: grid; place-items: center; color: var(--txt-3);
}
.lc-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lc-name {
  padding: 0; border: 0; background: transparent; font: inherit; font-size: 14.5px; cursor: pointer; text-align: left;
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--txt);
}
.lc-name b { font-weight: 500; }
@media (hover: hover) and (pointer: fine) { .lc-name:hover b { color: var(--ink); } }
.lc-meta { font-size: 12.5px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.lc-warn { color: var(--warn); }
.lc-copy { display: inline-flex; align-items: center; gap: 6px; }
.lc-copy.done { color: var(--ok); }
.lc-icon-btn {
  flex: none; width: 32px; height: 32px; display: grid; place-items: center; border: 0; border-radius: 7px;
  background: transparent; color: var(--txt-2); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .lc-icon-btn:hover { background: var(--hover); color: var(--txt); } }
@media (hover: hover) and (pointer: fine) { .lc-icon-btn.lc-stop:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); } }
/* Kho SlateLive (2026-10-13, phương án A2): mỗi Session một khối — dòng đầu ảnh bìa · tên + máy ·
   hạn + Gia hạn · ⋯; các link trong khối lõm thẳng mép tên, chia cột icon · tên · số ảnh · nút chữ
   (cùng độ rộng --lc-wbtn) · mở · dừng. Link dừng vẫn giữ ô trống để mọi cột thẳng hàng. */
.lc-ses { --lc-wbtn: 124px; padding: 12px 14px; }
.lc-ses + .lc-ses { border-top: 1px solid var(--line-soft); }
/* Hạn chung · đồng hồ (cùng cột nút mở của link) · ⋯ (cùng cột nút dừng) */
.lc-ses-h { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto 32px 32px; column-gap: 10px; align-items: center; padding-right: 6px; }
.lc-exp { font-size: 12.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lc-ses-h .lc-thumb { width: 40px; height: 40px; }
.lc-dim { color: var(--txt-3); }
.lc-links { margin: 10px 0 0 52px; border-radius: 9px; background: var(--bg-2); }
.lc-link { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto var(--lc-wbtn) 32px 32px; column-gap: 10px;
  align-items: center; min-height: 42px; padding: 0 6px 0 12px; font-size: 13px; }
.lc-link + .lc-link { border-top: 1px solid var(--line-soft); }
.lc-link-ic { display: inline-flex; color: var(--txt-3); }
.lc-link-name { min-width: 0; padding: 0; border: 0; background: none; color: var(--txt); font: inherit; text-align: left;
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (hover: hover) and (pointer: fine) { .lc-link-name:hover { color: var(--ink); } }
.lc-num { font-size: 12.5px; color: var(--txt-3); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.lc-wbtn { width: var(--lc-wbtn); justify-content: center; display: inline-flex; align-items: center; gap: 6px; }
.lc-link.stopped > :not(.lc-wbtn), .lc-link.expired > :not(.lc-wbtn) { opacity: .55; }
.lc-trash-note { margin: 2px 0 8px; font-size: 12.5px; color: var(--txt-3); }
/* Hàng Thùng rác dùng đúng cột phải của khối link: Khôi phục thẳng cột "Sao chép link", xoá hẳn thẳng cột ✕ */
.lc-trash-row { --lc-wbtn: 124px; display: grid; grid-template-columns: 40px minmax(0, 1fr) var(--lc-wbtn) 32px 32px;
  column-gap: 10px; align-items: center; padding: 10px 20px 10px 14px; }
.lc-trash-row + .lc-trash-row { border-top: 1px solid var(--line-soft); }
.lc-trash-row .lc-thumb { width: 40px; height: 40px; }
.lc-thumb-off { display: grid; place-items: center; opacity: .45; }
.lc-trash-row .lc-main b { font-weight: 500; }
.lc-opt { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; margin-bottom: 8px; border: 1px solid var(--line-soft);
  border-radius: 9px; cursor: pointer; }
.lc-opt:has(input:checked) { border-color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); }
.lc-opt input[type=radio] { margin-top: 3px; accent-color: var(--ink); }
.lc-opt > span { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.lc-opt b { font-weight: 500; }
.lc-opt .input { width: 100%; }
.lc-note { display: flex; gap: 8px; align-items: flex-start; margin: 4px 0 0; padding: 9px 10px; border-radius: 8px;
  background: var(--bg-2); font-size: 12.5px; color: var(--txt-2); }
.lc-note svg { flex: none; margin-top: 2px; }
.lc-stopped { margin-top: 18px; }
.lc-stopped > summary {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 10px; cursor: pointer; list-style: none;
  font-size: 13px; color: var(--txt-2);
}
.lc-stopped > summary::-webkit-details-marker { display: none; }
.lc-stopped > summary::before { content: '›'; display: inline-block; transition: transform .15s; }
.lc-stopped[open] > summary::before { transform: rotate(90deg); }
.lc-stopped > summary span { color: var(--txt-3); font-variant-numeric: tabular-nums; }
@media (hover: hover) and (pointer: fine) { .lc-stopped > summary:hover { color: var(--txt); } }
.lc-empty {
  padding: 40px 32px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  border: 1px dashed var(--line); border-radius: 12px; max-width: 640px; color: var(--ink);
}
.lc-empty h2 { margin: 0; font-size: 18px; font-weight: 500; color: var(--txt); }
.lc-empty p { margin: 0; color: var(--txt-2); }
/* Bánh răng đầu trang → hộp thoại "Cài đặt link Live" */
.lc-head-set { width: 36px; height: 36px; }
.lc-set-row { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--txt-2); }
.lc-set-row .input { width: 72px; height: 34px; }
/* Chưa có dự án Live nào: trang giới thiệu app */
.lc-intro { max-width: 560px; margin: 24px 0; display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
/* Ô vuông bo góc chứa biểu tượng khung ngắm — giống ô biểu tượng trong app Mac */
.lc-tile {
  --tile-bg: var(--bg-2);
  flex: none; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 11px;
  background: var(--tile-bg); color: var(--txt);
}
.lc-intro-icon { width: 64px; height: 64px; border-radius: 16px; }
.lc-mark.idle { opacity: .55; }
.lc-mark-dot { fill: #ff453a; stroke: var(--tile-bg, var(--bg-1)); stroke-width: 1.8; paint-order: stroke; }
.lc-intro h2 { margin: 4px 0 0; font-size: 22px; font-weight: 500; color: var(--txt); }
.lc-intro > p { margin: 0; color: var(--txt-2); font-size: 14px; line-height: 1.6; }
.lc-steps { margin: 8px 0; padding: 0; list-style: none; counter-reset: lcstep; display: flex; flex-direction: column; gap: 14px; }
.lc-steps li { counter-increment: lcstep; position: relative; padding-left: 40px; display: flex; flex-direction: column; gap: 2px; }
.lc-steps li::before {
  content: counter(lcstep); position: absolute; left: 0; top: -1px; width: 26px; height: 26px; border-radius: 6px;
  display: grid; place-items: center; border: 1px solid var(--line); color: var(--txt-2); font-size: 12.5px;
}
.lc-steps b { font-weight: 500; font-size: 14px; color: var(--txt); }
.lc-steps span { font-size: 13px; color: var(--txt-3); }
.lc-intro-cta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 6px; }
.lc-intro-cta .btn { display: inline-flex; align-items: center; gap: 8px; }
.lc-intro-cta .dim { font-size: 12.5px; }
@media (max-width: 640px) {
  /* Điện thoại: hạn xuống dòng dưới tên; link còn 1 cột tên + 3 ô icon (nút chữ thành icon) */
  .lc-ses { --lc-wbtn: 32px; padding: 12px; }
  .lc-ses-h { grid-template-columns: 40px minmax(0, 1fr) 32px 32px; column-gap: 4px; padding-right: 4px; }
  .lc-ses-h .lc-exp { grid-column: 2; grid-row: 2; margin-top: 2px; font-size: 12px; }
  .lc-ses-h > .lc-thumb { grid-row: 1 / 3; }
  .lc-ses-h > .lc-renew-btn, .lc-ses-h > [data-lc-more], .lc-ses-h > span { grid-row: 1 / 3; }
  .lc-links { margin-left: 0; }
  .lc-link { grid-template-columns: 16px minmax(0, 1fr) auto 32px 32px 32px; column-gap: 4px; padding: 0 4px 0 10px; }
  .lc-link .lc-copy { width: 32px; padding: 0; border: 0; background: transparent; }
  .lc-link .lc-copy span { display: none; }
  .lc-link .lc-wbtn:not(.lc-copy) { grid-column: 4 / -1; width: auto; }
  .lc-link .lc-wbtn:not(.lc-copy) ~ span { display: none; }
  .lc-trash-row { --lc-wbtn: 0px; grid-template-columns: 40px minmax(0, 1fr) 0 32px 32px; padding: 10px 16px 10px 12px; }
  .lc-trash-row .lc-meta { white-space: normal; }
}
@media (max-width: 640px) {
  /* Điện thoại giữ dạng segmented control cho tab dự án (đủ chỗ bấm), chỉ đổi màu theo Nocturne */
  #viewProject .pj-hero > .tabs {
    margin: 0 0 14px !important; gap: 2px; padding: 3px;
    border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg-1);
  }
  #viewProject .pj-hero > .tabs .tab { height: 34px; padding: 0 10px; margin: 0; border-bottom: 0; border-radius: 8px; }
  #viewProject .pj-hero > .tabs .tab.on { background: var(--bg-2); }
  .topbar { padding: 0 14px; }
}
@media (min-width: 1024px) {
  /* Trang khách / Live: cùng lề nội dung với trang quản trị */
  .wrap { padding-left: 32px; padding-right: 32px; }
}

/* ---------- Nocturne, đợt 2: bám sát thiết kế hơn ---------- */
/* Tiến độ chuyển mã: pill có chữ (desktop) */
.jobs-label { display: none; }
.sel-all-d { display: none; }
.tile-cmt { display: none; }

/* Nhận xét trong trình xem: thẻ phẳng, không bong bóng */
.cmt { padding: 12px; margin-bottom: 2px; border-radius: 8px; }
.cmt .who { margin-bottom: 4px; }
.cmt .body { background: none; padding: 0; border-radius: 0; font-size: 13.5px; line-height: 1.5; }
.cmt.showing, .cmt.flash { background: var(--hover); }
.cmt.showing .body { background: none; }
.cmt.internal .body, .cmt.has-draw .body { border-left: 0; }
.cmt .avatar, .avatar { width: 28px; height: 28px; background: #423a6a; color: #e7e5fe; font-weight: 600; }
.cmt-author b { font-weight: 500; font-size: 13px; }
.cmt .when { font-size: 12px; }
.viewer-panel-tabs { display: flex; gap: 4px; padding: 0; background: none; border-radius: 0; }
.viewer-panel-tabs button { height: 30px; padding: 0 12px; border-radius: 6px; font-size: 13px; color: var(--txt-2); }
.viewer-panel-tabs button.on { background: var(--bg-2); box-shadow: none; }
.asset-info-panel { background: var(--bg); }

/* Thông báo: tab dạng pill (width 380px chỉ áp cho dropdown máy tính — bỏ quên
   @media nên trước đây đè luôn cả width:auto của sheet dán đáy trên điện thoại,
   khiến sheet không giãn hết 2 cạnh màn hình trên máy có bề ngang > 380px) */
@media (min-width: 721px) {
  .notif-drop { width: 380px; }
}
.notif-filters { gap: 4px; border-bottom: 1px solid var(--line-soft); }
.notif-filters button { height: 28px; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: var(--txt-2); font-size: 12.5px; }
.notif-filters button.on { background: var(--bg-2); color: var(--txt); }
.notif-item { border-bottom: 1px solid var(--line-soft); }

/* Trạng thái chưa có dự án (thiết kế: hình minh hoạ + 3 bước) */
#pjEmpty.pj-onboard {
  margin-top: 24px; padding: 48px 40px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 48px; align-items: center; text-align: left; color: var(--txt);
  border: 1px dashed var(--line); border-radius: 16px;
  background: radial-gradient(600px 300px at 20% 0%, var(--tint), transparent 70%);
}
#pjEmpty.pj-onboard[hidden] { display: none; }
.pjo-art { position: relative; aspect-ratio: 3 / 2; max-width: 360px; width: 100%; justify-self: center; }
.pjo-art i { position: absolute; aspect-ratio: 16/10; border-radius: 10px; box-shadow: 0 0 0 1px var(--line); }
.pjo-a { left: 8%; top: 18%; width: 62%; transform: rotate(-7deg);
  background: repeating-linear-gradient(135deg, oklch(0.27 0.045 210) 0 12px, oklch(0.24 0.045 210) 12px 24px); }
.pjo-b { right: 6%; top: 6%; width: 58%; transform: rotate(6deg);
  background: repeating-linear-gradient(135deg, oklch(0.27 0.045 25) 0 12px, oklch(0.24 0.045 25) 12px 24px); }
.pjo-art .pjo-c { left: 18%; top: 34%; width: 66%; display: grid; place-items: center;
  background: repeating-linear-gradient(135deg, oklch(0.29 0.06 280) 0 12px, oklch(0.25 0.06 280) 12px 24px);
  box-shadow: 0 0 0 1px var(--accent), 0 18px 40px rgba(0, 0, 0, .45); }
.pjo-c span { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 8px; background: rgba(16, 17, 27, .75); color: #d2cefd; }
.pjo-tc { position: absolute; left: 62%; top: 72%; padding: 4px 9px; border-radius: 6px; background: var(--accent);
  color: var(--on-accent); font-size: 12px; font-weight: 500; white-space: nowrap; box-shadow: 0 8px 20px rgba(0, 0, 0, .35); }
.pjo-copy { display: flex; flex-direction: column; gap: 14px; max-width: 46ch; }
.pjo-copy h2 { margin: 0; font-size: 24px; line-height: 1.25; font-weight: 500; letter-spacing: -.01em; }
.pjo-copy p { margin: 0; color: var(--txt-2); }
.pjo-copy ol { margin: 4px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
.pjo-copy li { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 10px; align-items: baseline; }
.pjo-copy li span { width: 24px; height: 24px; display: grid; place-items: center; border-radius: 6px;
  background: var(--tint); color: var(--ink); font-size: 12px; font-weight: 600; }
.pjo-cta { margin-top: 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.pjo-cta .btn { height: 40px; padding: 0 16px; font-size: 14px; }
.pjo-cta .dim { font-size: 13px; }
@media (max-width: 760px) {
  #pjEmpty.pj-onboard { grid-template-columns: 1fr; padding: 28px 20px; gap: 20px; }
  .pjo-art { max-width: 300px; }
}

/* Thùng rác: danh sách hàng như thiết kế thay cho lưới thẻ */
#trCards { display: flex; flex-direction: column; gap: 0; border: 1px solid var(--line-soft); border-radius: 12px; overflow: hidden; }
#trCards:empty { display: none; }
#trCards .card.trash {
  display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; align-items: center; gap: 14px;
  padding: 12px 14px; border: 0; border-bottom: 1px solid var(--line-soft); border-radius: 0; background: none;
}
#trCards .card.trash:last-child { border-bottom: 0; }
#trCards .card.trash .thumb { width: 64px; height: 40px; aspect-ratio: auto; border-radius: 6px; font-size: 0; background-size: cover; }
#trCards .card.trash .meta { padding: 0; min-width: 0; }
#trCards .card.trash .meta h3 { margin: 0 0 2px; font-size: 14px; font-weight: 500; }
#trCards .card.trash .meta .sub { font-size: 12.5px; color: var(--txt-3); }
#trCards .card.trash .sub .chip { display: inline; height: auto; padding: 0; background: none; color: var(--txt-3); font-size: 12.5px; }
#trCards .card-actions { padding: 0; }
#trCards .card-actions .btn { flex: none; }
#trCards .card.trash .sub > span + span::before { content: '·'; margin-right: 6px; color: var(--txt-3); }
/* Điện thoại: 3 cột (ảnh | tên | 2 nút) ép tên + thông tin thành cột hẹp, xuống dòng từng chữ
   (người dùng báo 2026-09-29) → ảnh + tên hàng trên, 2 nút chia đôi bề ngang ở hàng dưới. */
@media (max-width: 640px) {
  #trCards .card.trash { grid-template-columns: 56px minmax(0, 1fr); gap: 12px; padding: 14px; }
  #trCards .card.trash .thumb { width: 56px; height: 42px; }
  #trCards .card.trash .meta h3 { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #trCards .card-actions { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  #trCards .card-actions .btn { width: 100%; }
}
#viewTrash > p.dim { color: var(--txt-2) !important; max-width: 70ch; margin: -8px 0 20px !important; }

/* Liên kết đã mở: một danh sách có viền, mỗi dòng một link */
.shared-links { gap: 0; border: 1px solid var(--line-soft); border-radius: 12px; overflow: hidden; }
.shared-links > * { border: 0; border-bottom: 1px solid var(--line-soft); border-radius: 0; background: none; padding: 12px 14px; }
.shared-links > :last-child { border-bottom: 0; }
.shared-section + .shared-section { margin-top: 32px; }

@media (min-width: 1024px) {
  /* Thanh trên: pill tiến độ */
  #btnJobs {
    width: auto; height: 30px; padding: 0 10px; gap: 8px; border-radius: 6px; border: 0;
    background: var(--tint); color: var(--ink); font-size: 12.5px;
  }
  #btnJobs .jobs-spin { width: 13px; height: 13px; border-width: 1.5px; border-color: rgba(210, 206, 253, .3); border-top-color: var(--ink); }
  .jobs-label { display: inline; }

  /* Danh sách dự án: ô tìm + 2 select hiện thẳng như thiết kế, bỏ 3 nút icon */
  #btnPjSearch, #btnDSearch { display: none !important; }
  #pjSearchWrap, #dSearchWrap {
    max-height: none; opacity: 1; margin: 0; overflow: visible; position: relative;
    flex: 1 1 240px; max-width: 340px;
  }
  #pjSearchWrap, #dSearchWrap { order: 0; }
  #dSearchWrap { flex-basis: 220px; max-width: 320px; }
  #btnPjFilter { order: 1; }
  #btnPjSort { order: 2; }
  #viewProjects .fbar > .spacer { order: 3; flex: 1; }
  #pjAppearance { order: 4; margin-left: 0; }
  #pjSearchWrap .input, #dSearchWrap .input {
    height: 36px; font-size: 13.5px; max-width: none; padding-left: 32px;
    background: var(--bg-1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23858899' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/svg%3E") no-repeat 10px 50% / 15px;
  }
  .fbar { margin-top: 20px; }
  #viewProjects .fbar { margin: 20px 0; }

  /* Tệp trong dự án: breadcrumb thư mục nằm cùng hàng với thanh công cụ */
  #tabPhotos { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 8px; align-content: start; }
  #tabPhotos > * { grid-column: 1 / -1; }
  #tabPhotos > .crumbs { grid-column: 1; grid-row: 1; margin: 0; align-self: center; white-space: nowrap; }
  #tabPhotos > .fbar { grid-column: 2; grid-row: 1; margin: 0 0 4px; }
  .crumbs .cr { color: var(--txt-2); }
  .crumbs .sep { color: var(--txt-3); }
  #btnDFilter { background: var(--bg-1); }

  /* Tiêu đề nhóm "Thư mục"/"Tệp": chữ nhỏ mờ, bỏ nút thu gọn */
  .sec-head { margin: 24px 0 10px; }
  .sec-head .caret { display: none; }


  /* Ô tệp trên màn hình rộng: giữ ĐÚNG bố cục như trang khách — ô tích góc TRÁI, nhãn phiên bản
     (v2, v3...) góc PHẢI. Bản trước đảo ngược 2 vị trí này (ô tích phải/nhãn trái) — lúc sửa cách
     hiện (chỉ hiện khi rê chuột, xong lần trước) quên sửa luôn vị trí, người dùng chụp ảnh báo
     tiếp 2026-09-27. Cách HIỆN vẫn kế thừa từ .tile .checkbox/.tile.picked .checkbox ở trên (chỉ
     hiện khi rê chuột vào hoặc đã chọn), chỉ riêng CSS này chỉnh style/kích thước cho màn rộng. */
  #dGrid .tile .checkbox { left: 8px !important; right: auto; top: 8px; border-color: rgba(233, 233, 237, .7); background: rgba(16, 17, 27, .45); color: transparent; }
  #dGrid .tile.picked .checkbox { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  #dGrid .tile .ver-tag { left: auto; right: 8px; top: 8px; padding: 1px 7px; border-radius: 5px; font-size: 12px; font-weight: 500; background: rgba(16, 17, 27, .85); color: #d2cefd; backdrop-filter: none; }
  #dGrid .tile .vdur { right: 8px; bottom: 8px; padding: 1px 7px; background: rgba(16, 17, 27, .85); color: var(--txt); font: 12px var(--font); font-variant-numeric: tabular-nums; }
  #dGrid .tile .ph .badges { display: none; }
  /* Trang khách: cùng lý do với #dGrid ở trên — màn rộng đã có .tile-cmt trong .tile-rate-row
     (cùng hàng sao/thẻ màu, căn phải, chung CSS .tile-cmt với admin nên luôn cùng cỡ), khỏi cần
     huy hiệu đè lên ảnh nữa (2026-09-27, người dùng yêu cầu 2 trang giống nhau). */
  #grid .tile .ph .badges { display: none; }
  #dGrid .tile .cap { padding: 9px 11px 0; }
  #dGrid .tile .cap .meta.dim { display: none; }
  #dGrid .tile .by { display: none; }
  /* Trang khách (#grid) dùng CÙNG lề với trang quản trị: trước đây chỉ có đệm trái 7px, phải 0 →
     số nhận xét dính sát mép phải, còn sao có đệm dưới 6px nên lệch lên so với số nhận xét
     (người dùng báo 2026-09-29) */
  #dGrid .tile .tile-rate-row,
  #grid .tile .tile-rate-row { padding: 2px 11px 10px 11px; gap: 8px; flex-wrap: nowrap; }
  /* trang khách còn dòng ngày giờ (.by) ngay dưới — không cần đệm dưới */
  #grid .tile .tile-rate-row { padding-bottom: 2px; }
  /* ô hẹp (nhiều cột): sao tự cắt trong phần của mình, không tràn đè lên số nhận xét */
  #grid .tile .tile-marks { overflow: hidden; }
  #dGrid .tile .stars.tile-stars,
  #grid .tile .stars.tile-stars { padding: 0; }
  #dGrid .tile .stars.tile-stars .star { font-size: 12px; }
  /* Chỉ hiện khi CÓ bình luận (.on, gán trong admin.js/share.js khi comments>0) — `.tile-cmt`
     base (không media query, phía trên) đã `display:none` mặc định; 0 bình luận thì giữ nguyên
     ẩn, đỡ rợp mắt cả lưới toàn icon xám không có nghĩa gì (2026-09-27, người dùng yêu cầu). */
  .tile-cmt.on { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; font-size: 12px; color: var(--ink); flex: none; }

  /* Đầu trang dự án */
  #btnInvite { width: 30px; height: 30px; border: 1px dashed var(--line); border-radius: 6px; color: var(--txt-2); }
  @media (hover: hover) and (pointer: fine) { #btnInvite:hover { color: var(--txt); background: transparent; } }
  #dCount { height: 22px; }

  /* Thanh chọn nhiều */
  .sel-hint { display: none; }
  .sel-all-d { display: inline-flex; color: var(--ink) !important; }
  @media (hover: hover) and (pointer: fine) { .sel-all-d:hover { background: var(--tint) !important; } }
}

/* Trình xem (desktop): thứ tự nút như thiết kế — sao · ‹ n/N › · chia sẻ · tải xuống · Nhận xét N */
.lb-crumb .cr-root { text-transform: none; letter-spacing: 0; font-size: 13.5px; color: var(--txt-3); }
.lb-crumb .cr-file { font-weight: 500; }
.ver-pill { height: 28px; padding: 0 10px; background: transparent; border-color: var(--line); border-radius: 8px; font-weight: 400; font-size: 12.5px; color: var(--txt); }
@media (hover: hover) and (pointer: fine) { .ver-pill:hover { background: var(--hover); } }
.lb-nav { height: auto; background: none; border: 0; padding: 0; gap: 2px; }
.lb-nav .nav-btn { width: 32px; height: 32px; border-radius: 8px; font-size: 17px; color: var(--txt-2); }
@media (hover: hover) and (pointer: fine) { .lb-nav .nav-btn:hover { background: var(--hover); } }
.lb-nav .nav-idx { min-width: 44px; text-align: center; font: 12.5px var(--font); font-variant-numeric: tabular-nums; color: var(--txt-3); }
@media (min-width: 1024px) {
  .lb-head { gap: 12px; padding: 0 14px; }
  #alb .lb-head > .lb-acts { display: contents; }
  #albStars { order: 1; } #albColorTag { order: 2; } #alb .lb-head > .lb-nav { order: 3; margin: 0 6px; }
  #albShare { order: 5; } #albDl { order: 6; } #albPanel { order: 7; }
  #albShare, #albDl { width: 34px; height: 34px; padding: 0; justify-content: center; }
  #albShare span, #albDl span { display: none; }
  .lb-acts .panel-toggle, #albPanel, #lbPanel { width: auto; height: 34px; padding: 0 12px; gap: 6px; color: var(--txt-2); }
  .lb-acts .panel-toggle .panel-label, .lb-acts .panel-toggle .cmt-count { display: inline; }
  .lb-acts .panel-toggle .cmt-count { color: inherit; background: none; padding: 0; min-width: 0; font-size: 0; }
  .lb-acts .panel-toggle .cmt-count::after { content: attr(data-n); font-size: 13px; }
  .lb-acts .panel-toggle[aria-pressed="true"] { border-color: var(--accent); color: var(--ink); }
  #albClose { color: var(--txt-2); }
}

/* ==========================================================================
   Nocturne — chế độ Sáng (nút Tối/Sáng trong menu tài khoản, lưu localStorage sf_theme).
   Trình xem tệp luôn giữ nền tối như thiết kế (data-sf="dark" trên khung xem).
   ========================================================================== */
html[data-theme="light"] {
  color-scheme: light;
  --bg: #ffffff; --side: #f8f9fa; --bg-1: #ffffff; --bg-2: #f1f3f4; --bg-3: #e8eaed;
  --line: rgba(32, 33, 36, .16); --line-soft: rgba(32, 33, 36, .08); --hover: rgba(32, 33, 36, .06);
  --txt: #202124; --txt-1: #202124; --txt-2: #3c4043; --txt-3: #5f6368;
  --accent: #5546b8; --accent-hi: #43379b; --ink: #43379b; --tint: rgba(85, 70, 184, .12); --on-accent: #ffffff;
  --ok: #137333; --warn: #a35200; --danger: #c5221f;
  --shadow: 0 0 0 1px rgba(32, 33, 36, .12), 0 16px 40px rgba(32, 33, 36, .16);
}
html[data-theme="light"] .tile.folder .ph:not(.empty)::before { background: #dadce0; box-shadow: 0 -14px 0 -7px #e8eaed; }
html[data-theme="light"] .tile.folder .ph.stack-1::before { box-shadow: none; }
html[data-theme="light"] .tile.folder .ph:not(.empty) .mosaic { box-shadow: 0 2px 8px rgba(28, 29, 41, .18); }
html[data-theme="light"] .topbar::before { background: rgba(255, 255, 255, .9); }
html[data-theme="light"] .toast { background: var(--bg-1); color: var(--txt); border-color: var(--line); }
html[data-theme="light"] .mask { background: rgba(28, 29, 41, .35); }
html[data-theme="light"] .input { background-color: #fff; border-color: rgba(32, 33, 36, .45); }
html[data-theme="light"] .input:focus { border-color: var(--accent); }
html[data-theme="light"] .ws-avatar, html[data-theme="light"] .avatar { background: #423a6a; color: #e7e5fe; }
/* Khung xem tệp (admin #alb, khách #lb) và mọi thứ bên trong: giữ bảng màu tối */
html[data-theme="light"] .lb {
  color-scheme: dark; color: #e9e9ed;
  --bg: #161826; --bg-1: #1c1e2b; --bg-2: #232532; --bg-3: #2a2c3b;
  --line: rgba(233, 233, 237, .18); --line-soft: rgba(233, 233, 237, .09); --hover: rgba(233, 233, 237, .06);
  --txt: #e9e9ed; --txt-1: #e9e9ed; --txt-2: #a9abb9; --txt-3: #858899;
  --accent: #9184d9; --accent-hi: #a79be6; --ink: #d2cefd; --tint: rgba(145, 132, 217, .14); --on-accent: #161826;
  --ok: #7fcfa0; --warn: #e6c35c; --danger: #e8959a;
  --shadow: 0 0 0 1px #3f424d, 0 16px 40px rgba(0, 0, 0, .6);
}
html[data-theme="light"] .lb .input { background: var(--bg-1); }
/* Sao chưa chấm: ở giao diện Sáng vẽ viền sao (nền sáng làm sao mờ gần như biến mất).
   --star-empty đổi theo nền: tối trên nền sáng, sáng trên khung xem tối. */
html[data-theme="light"] { --star-empty: rgba(28, 29, 41, .42); }
/* Ô chữ viết tắt workspace: nền tím đậm cố định ở giao diện Tối, sang Sáng thì chữ --ink (tím đậm) chìm hẳn vào nền */
html[data-theme="light"] .sf-ws-av { background: var(--tint); }
html[data-theme="light"] .lb { --star-empty: rgba(233, 233, 237, .45); }
html[data-theme="light"] .stars .star:not(.on) { color: transparent; -webkit-text-stroke: 1.3px var(--star-empty); }
/* Sao nhỏ ở lưới/danh sách: viền mảnh và nhạt hơn để không nặng mắt */
html[data-theme="light"] .tile .stars .star:not(.on),
html[data-theme="light"] .fl-rate .star:not(.on) { -webkit-text-stroke: .9px rgba(28, 29, 41, .28); }
/* Nút chọn Tối/Sáng trong menu tài khoản */
.ctx-theme { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 3px; margin: 6px 4px; border: 1px solid var(--line-soft); border-radius: 8px; }
.ctx-theme button {
  height: 28px; padding: 0 4px; display: flex; align-items: center; justify-content: center; gap: 4px; white-space: nowrap;
  border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--txt-2); font: inherit; font-size: 12.5px; cursor: pointer;
}
.ctx-theme button.on { background: var(--bg-2); border-color: var(--line); color: var(--txt); }

/* Tab "Chia sẻ" trong dự án: danh sách hàng (thiết kế Nocturne) */
.sl-list { margin-top: 20px; border: 1px solid var(--line-soft); border-radius: 12px; overflow: hidden; }
.sl-row {
  padding: 14px 16px; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 20px; align-items: center;
  border-bottom: 1px solid var(--line-soft);
}
.sl-row:last-child { border-bottom: 0; }
.sl-row.off .sl-name { color: var(--txt-2); }
.sl-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.sl-name { font-weight: 500; overflow-wrap: anywhere; }
.sl-scope { font-size: 12.5px; color: var(--txt-3); overflow-wrap: anywhere; }
.sl-scope a { color: var(--txt-2); }
@media (hover: hover) and (pointer: fine) { .sl-scope a:hover { color: var(--ink); } }
.sl-flags { display: flex; flex-wrap: wrap; gap: 6px; }
.sl-flags span {
  height: 22px; padding: 0 8px; display: inline-flex; align-items: center; border-radius: 6px;
  background: var(--hover); font-size: 12px; color: var(--txt-2); white-space: nowrap;
}
.sl-side { display: flex; align-items: center; gap: 8px; }
.sl-views { font-size: 12.5px; color: var(--txt-3); white-space: nowrap; margin-right: 4px; }
.btn.danger-text { color: var(--danger); }
@media (hover: hover) and (pointer: fine) { .btn.danger-text:hover { background: rgba(232, 149, 154, .1); color: var(--danger); } }
@media (max-width: 760px) {
  .sl-row { grid-template-columns: minmax(0, 1fr); }
  .sl-side { flex-wrap: wrap; }
}

/* Trang quản trị: bỏ logo app ở thanh trên trên mọi cỡ màn hình — desktop đã có ở thanh bên,
   điện thoại/tablet chỉ giữ ô workspace. Về trang chủ bằng nút "‹ Tất cả dự án" của từng màn. */
.sf-main .topbar .brand { display: none; }
@media (max-width: 1023px) {
  .lc-page-head { flex-direction: column; align-items: flex-start; gap: 10px; }
  .lc-page-head > .spacer { display: none; }
  #btnLiveBack { margin-left: -8px; }
  .lc-page-title > h1, .lc-page-title > .muted { order: 0; flex: none; }
}

/* Logo workspace */
.sf-ws-av { overflow: hidden; }
.sf-ws-av img, .ws-logo-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.crumb .cr-ws { gap: 8px; }
.crumb .cr-ws-badge {
  width: 24px; height: 24px; flex: none; display: grid; place-items: center; overflow: hidden;
  border-radius: 6px; background: #2b2741; color: #d2cefd; font-size: 10px; font-weight: 600; letter-spacing: 0;
}
.crumb .cr-ws-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ws-logo-row { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.ws-logo-preview {
  width: 56px; height: 56px; flex: none; display: grid; place-items: center; overflow: hidden;
  border-radius: 12px; background: #2b2741; color: #d2cefd; font-size: 18px; font-weight: 600;
}
.ws-logo-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ws-logo-copy strong { font-size: 13.5px; font-weight: 500; }
.ws-logo-copy small { font-size: 12px; color: var(--txt-3); }
.ws-logo-acts { display: flex; gap: 8px; margin-top: 8px; }
.ws-logo-acts[hidden] { display: none; }

/* Ô thư mục: dùng lại kiểu ô có ảnh thu nhỏ như trước Nocturne (người dùng yêu cầu 2026-09-26) —
   khối "hàng gọn 56px" đã gỡ. */
/* Thẻ dự án ở danh sách: chỉ hiện số tệp + dung lượng, bỏ số liên kết và số nhận xét */
.project-card-stats .project-stat-link, .project-card-stats .project-stat-comment { display: none; }

/* Ô chọn (select): mũi tên riêng cách mép phải 12px thay cho mũi tên mặc định sát viền */
select.input {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 34px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23858899' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 14px;
}

/* Dãy avatar thành viên (đầu trang Dự án + đầu trang 1 dự án) và nút mời tròn viền gạch */
.av-stack-btn {
  display: inline-flex; align-items: center; flex: none; padding: 0 0 0 4px; border: 0; background: transparent; cursor: pointer;
}
.av-stack-btn[hidden] { display: none; }
.av-stack-btn .av {
  position: relative; width: 26px; height: 26px; margin-left: -4px; flex: none; display: grid; place-items: center;
  overflow: hidden; border-radius: 6px; box-shadow: 0 0 0 2px var(--bg);
  font-size: 10.5px; font-weight: 600; background: #423a6a; color: #e7e5fe;
}
.av-stack-btn .av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.av-stack-btn .av-more { background: var(--bg-3); color: var(--txt-2); z-index: 0; }
@media (hover: hover) and (pointer: fine) { .av-stack-btn:hover .av { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px var(--line); } }
#btnInvite, #btnWorkspaceMembers {
  width: 30px; height: 30px; padding: 0; border: 1px dashed var(--line); border-radius: 6px;
  background: transparent; color: var(--txt-2);
}
@media (hover: hover) and (pointer: fine) { #btnInvite:hover, #btnWorkspaceMembers:hover { color: var(--txt); border-color: var(--txt-3); background: transparent; } }
#btnInvite svg, #btnWorkspaceMembers svg { width: 15px; height: 15px; }
@media (max-width: 640px) {
  .page-head #btnInvite, #viewProjects .page-head #btnWorkspaceMembers { width: 36px; height: 36px; }
  /* nút Chia sẻ (chỉ icon trên điện thoại) cùng cỡ với nút mời bên cạnh — trước đây 44px (--tap) to hơn hẳn nút 36px */
  .page-head #btnShare { width: 36px; height: 36px; }
  .page-head #pjAvatars { order: 1; margin-left: auto; }
  #viewProjects .page-head #wsAvatars { order: 2; margin-left: auto; }
  .page-head #pjAvatars:not([hidden]) + #btnInvite,
  #viewProjects .page-head #wsAvatars:not([hidden]) + #btnWorkspaceMembers { margin-left: 4px; }
}

/* Mục Lưu trữ: dòng giải thích dưới tiêu đề */
.pj-archive-hint { margin: -8px 0 16px; max-width: 70ch; color: var(--txt-2); font-size: 13.5px; }
.pj-archive-hint[hidden] { display: none; }
/* Nút "Theo dõi" (link Live) cùng chiều cao/kiểu với các nút tìm/lọc/sắp xếp cạnh nó */
#btnLiveFollowGrid { height: 36px; padding: 0 12px; font-size: 13.5px; }
@media (max-width: 640px) {
  #btnLiveFollowGrid { height: var(--tap); background: var(--bg-1); border-color: var(--line-soft); color: var(--txt-2); }
}

/* ---------- Khung xem trang khách/Live (máy tính + tablet): thanh trên gọn lại ----------
   Trái: ✕ + tên tệp (được ưu tiên chỗ). Phải: sao · thẻ màu · ‹ n/N › · Theo dõi (icon + chấm
   trạng thái) · dải ảnh · Tải xuống (icon) · Nhận xét N. Điện thoại giữ thanh dưới riêng ở trên. */
@media (min-width: 641px) {
  #lb .lb-head { gap: 8px; }
  #lb .lb-head > .lb-acts { display: contents; }
  #lb #lbStars { order: 1; }
  #lb #lbColorTag { order: 2; margin-right: 6px; }
  #lb .lb-head > .lb-nav { order: 3; margin-right: 6px; }
  #lb .live-follow-btn { order: 4; }
  #lb .live-follow-dot { order: 5; }
  #lb #lbDl { order: 7; }
  #lb #lbPanel { order: 8; }
  /* Các nút icon cùng một cỡ vuông 34px */
  #lb .live-follow-btn, #lb #lbDl {
    position: relative; width: 34px; min-width: 34px; height: 34px; padding: 0; justify-content: center;
  }
  #lb .live-follow-label, #lb #lbDl span { display: none; }
  #lb .live-follow-btn[aria-pressed="true"] { border-color: var(--accent); color: var(--ink); }
  #lb .live-follow-btn[aria-pressed="false"] { opacity: 1; color: var(--txt-3); border-style: dashed; }
  /* Chấm trạng thái kết nối đè nhỏ ở góc trên-phải nút Theo dõi */
  #lb .live-follow-dot {
    width: 8px; height: 8px; margin: 0 0 0 -14px; align-self: flex-start; margin-top: 12px;
    z-index: 1; pointer-events: none; box-shadow: 0 0 0 2px #10111b;
  }
  #lb #lbPanel { height: 34px; }
}
/* Tablet: bớt chữ để tên tệp còn chỗ */
@media (min-width: 641px) and (max-width: 1100px) {
  #lb .lb-crumb .cr-root, #lb .lb-crumb .cr-sep { display: none; }
  #lb #lbPanel .panel-label { display: none; }
  #lb .lb-head > .lb-nav .nav-idx { min-width: 36px; }
}
@media (min-width: 641px) and (max-width: 1023px) {
  /* Nhận xét: icon + con số (data-n do share.js đặt) */
  #lb #lbPanel { width: auto; padding: 0 10px; gap: 6px; }
  #lb #lbPanel .panel-ic { display: block; }
  #lb #lbPanel .cmt-count { display: inline; font-size: 0; background: none; padding: 0; min-width: 0; color: inherit; }
  #lb #lbPanel .cmt-count::after { content: attr(data-n); font-size: 13px; }
}

/* Nút ẩn/hiện dải ảnh thu nhỏ nằm cạnh cụm zoom (góc dưới trái khung xem) thay vì thanh trên */
.zoombar .zb-sep { width: 1px; height: 16px; margin: 0 4px; background: var(--line); flex: none; }
.zoombar .filmstrip-trigger {
  width: 26px; height: 26px; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: var(--txt-2); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .zoombar .filmstrip-trigger:hover { background: var(--bg-3); color: var(--txt); } }
.zoombar .filmstrip-trigger.on { color: var(--ink); }
.zoombar .filmstrip-trigger svg { width: 16px; height: 16px; }

/* Cụm chuyển tệp: bỏ 2 nút ‹ › cho gọn, chỉ còn số thứ tự "n / N" — chuyển tệp bằng phím ← →,
   dải ảnh thu nhỏ hoặc vuốt (điện thoại). Nút vẫn nằm trong DOM vì JS/phím tắt dùng chung. */
.lb-nav { height: auto; gap: 0; padding: 0; border: 0; background: none; }
.lb-nav .nav-btn { display: none; }
.lb-nav .nav-idx { min-width: 0; padding: 0 6px; font-size: 12.5px; color: var(--txt-3); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Trang Live / khách — học theo Capture One Live (2026-09-26)
   ========================================================================== */
/* Nút tròn chuyển tệp nổi ở mép ảnh (thay ‹ › trên thanh trên). Điện thoại chuyển bằng vuốt. */
.edge-nav {
  position: absolute; top: 50%; z-index: 4; width: 36px; height: 36px; margin-top: -18px; padding: 0;
  display: grid; place-items: center; border: 0; border-radius: 6px; cursor: pointer;
  background: rgba(16, 17, 27, .55); color: #e9e9ed; opacity: .75; transition: opacity .15s, background .15s;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.edge-nav:hover { opacity: 1; background: rgba(16, 17, 27, .8); }
.edge-nav.prev { left: 12px; }
.edge-nav.next { right: 12px; }
.edge-nav[hidden] { display: none; }
.lb.chrome-off .edge-nav, .lb.draw-mode .edge-nav { opacity: 0; pointer-events: none; }
@media (max-width: 640px) { .edge-nav { display: none; } }




/* Bảng "Tất cả bình luận" (mở từ lưới) */
.allc {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 150; width: min(380px, 100vw);
  display: flex; flex-direction: column; background: var(--bg-1); border-left: 1px solid var(--line-soft);
  box-shadow: var(--shadow); animation: allcIn .2s var(--ease-out);
}
.allc[hidden] { display: none; }
@keyframes allcIn { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.allc-head { flex: none; height: 56px; padding: 0 8px 0 16px; display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--line-soft); }
.allc-head b { font-weight: 500; font-size: 15px; }
.allc-head .dim { font-size: 13px; }
.allc-head .btn { margin-left: auto; }
.allc-body { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 0 24px; }
.allc-empty { padding: 48px 28px; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; color: var(--txt-2); font-size: 13.5px; }
.allc-empty p { margin: 0; }
.allc-group { padding: 6px 0 10px; border-bottom: 1px solid var(--line-soft); }
.allc-file {
  width: 100%; padding: 6px 16px; display: flex; align-items: center; gap: 10px; border: 0; background: transparent;
  color: var(--txt); font: inherit; text-align: left; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .allc-file:hover { background: var(--hover); } }
.allc-file img { width: 40px; height: 40px; flex: none; border-radius: 6px; object-fit: cover; background: var(--bg-2); }
.allc-name { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.allc-n { flex: none; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 6px; background: var(--tint); color: var(--ink); font-size: 11.5px; display: grid; place-items: center; }
.allc-filter { flex: none; padding: 10px 16px; border-bottom: 1px solid var(--line-soft); }
.allc-filter[hidden] { display: none; }
.allc-filter .fbx-seg { display: flex; }
.allc-filter .fbx-seg button { flex: 1; justify-content: center; }
.allc-resolve {
  margin-left: auto; align-self: center; width: 24px; height: 24px; flex: none; display: grid; place-items: center;
  border: 0; border-radius: 6px; background: transparent; color: var(--txt-3); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .allc-resolve:hover { background: var(--hover); color: var(--txt); } }
.allc-resolve.on { color: var(--ok); }
.allc-cmt.resolved p { color: var(--txt-3); }
.allc-cmt.resolved .allc-who b { color: var(--txt-2); }
.allc-cmt { padding: 6px 16px 6px 66px; }
.allc-cmt.reply { padding-left: 82px; }
.allc-cmt[data-cid] { cursor: pointer; transition: background .12s; }
@media (hover: hover) and (pointer: fine) { .allc-cmt[data-cid]:hover { background: var(--hover); } }
.allc-who { display: flex; align-items: center; gap: 8px; font-size: 12.5px; min-height: 24px; }
.allc-who b { font-weight: 500; color: var(--txt); }
.allc-who span { color: var(--txt-3); font-size: 12px; }
.allc-tc { display: inline-block; margin-top: 2px; padding: 0 5px; border-radius: 4px; background: var(--bg-2); color: var(--ink); font: 11.5px ui-monospace, Menlo, monospace; }
.allc-cmt p { margin: 3px 0 0; font-size: 13.5px; line-height: 1.45; color: var(--txt-2); white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 640px) {
  #btnAllComments { position: relative; width: var(--tap); height: var(--tap); padding: 0; justify-content: center; flex: none; background: var(--bg-1); border-color: var(--line-soft); color: var(--txt-2); }
  .allc-cmt { padding-left: 16px; }
  .allc-cmt.reply { padding-left: 32px; }
}

/* ---------- Điện thoại: thanh dưới khung xem không nền (2026-09-26) ----------
   Bỏ nền/viền của .lb-acts để hàng icon nằm thẳng trên nền khung xem. Ảnh vẫn dừng phía trên
   hàng icon (giữ nguyên phần chừa 56px đáy của .lb.open). Áp cho cả admin (#alb) lẫn khách (#lb). */
@media (max-width: 640px) {
  .lb .lb-acts {
    background: transparent !important; border-top: 0 !important; box-shadow: none !important;
    -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
  }
  /* Sheet bình luận đóng vẫn nằm ngay dưới mép màn hình — bóng đổ lên của nó tạo thành dải
     tối như gradient sau hàng icon. Chỉ đổ bóng khi sheet đang mở. */
  .lb:not(.panel-on) .panel { box-shadow: none !important; }
}

/* ---------- Thẻ màu: ô vuông bo góc, đứng TRƯỚC hàng sao (trang khách; trang Live có live.css) ---------- */
.ctag-dot { border-radius: 4px; }
/* Lưới: thẻ màu + sao căn trái, mép ô thẻ màu thẳng hàng với chữ tên tệp (đệm .cap 11px − đệm nút 4px),
   ô thẻ màu cao bằng ngôi sao, sát nhau như trang Live */
#grid .tile .tile-rate-row { justify-content: flex-start; gap: 3px; padding-left: 7px; }
#grid .tile .tile-rate-row .ctag-btn.tile-ctag { order: -1; padding: 4px; margin-left: 0; }
#grid .tile .tile-rate-row .stars.tile-stars { flex: none; padding: 0; }
#grid .tile .stars.tile-stars .star { font-size: 16px; }
#grid .tile .tile-rate-row .ctag-dot { width: 15px; height: 15px; }
#grid .tile .by { padding-left: 11px; padding-right: 11px; }
.frow-guest .fl-rate .ctag-btn { order: -1; margin-right: 6px; }
@media (min-width: 641px) {
  /* order 0: vẫn sau .spacer (đứng trước trong DOM) nhưng trước sao (order 1) */
  #lb #lbColorTag { order: 0; margin-right: 0; }
  #lb #lbStars { order: 1; margin-right: 6px; }
}
/* Hàng đường dẫn trang khách/Live ẩn ở thư mục gốc (tên dự án đã có trên thanh trên) */
#pathCrumbs[hidden] { display: none; }
/* Tải tất cả (trang khách): mọi cỡ màn hình đều sát mép phải, ngay trước nút Hiển thị */
.fbar #btnDlAll { margin-left: auto; }
#btnDlAll + #gAppearance { margin-left: 0; }

/* Điện thoại, trang khách/Live: nút thanh lọc gọn lại 38px (44px trông quá to so với nội dung) */
@media (max-width: 640px) {
  .fbar #btnSearch, .fbar #btnFilterSheet, .fbar #btnSortSheet, .fbar #btnAllComments, .fbar #btnDlAll, .fbar #btnGView {
    width: 38px; height: 38px; min-width: 38px; border-radius: 9px;
  }
  .fbar #btnLiveFollowGrid { height: 38px; }
  .fbar #btnSearch svg, .fbar #btnFilterSheet svg, .fbar #btnSortSheet svg, .fbar #btnAllComments svg, .fbar #btnDlAll svg { width: 16px; height: 16px; }
}

/* ---------- Trang quản trị: đồng bộ với trang khách/Live (2026-09-26) ----------
   Thẻ màu vuông đứng TRƯỚC hàng sao, sát nhau, cao bằng ngôi sao; mép ô thẻ màu thẳng với chữ tên
   tệp (đệm .cap 11px − đệm nút 3px). Khung xem (#alb): thẻ màu cũng đứng trước sao. */
#dGrid .tile .tile-rate-row { padding-left: 8px; }
#dGrid .tile .tile-marks { gap: 3px; }
#dGrid .tile .tile-marks .ctag-btn.tile-ctag { order: -1; padding: 3px; margin: 0; }
#dGrid .tile .tile-marks .stars.tile-stars { flex: none; padding: 0; }
#dGrid .tile .stars.tile-stars .star { font-size: 15px; }
#dGrid .tile .tile-marks .ctag-dot { width: 14px; height: 14px; }
@media (max-width: 1023px) { #alb .lb-acts #albColorTag { order: -1; } }
#albColorTagTop { order: -1; }
@media (min-width: 1024px) {
  /* Thẻ màu order 1, sao đẩy lên order 2 (vẫn trước ‹ n/N › order 3) */
  #albColorTag { order: 1; }
  #albStars { order: 2; margin-right: 6px; }
}
@media (max-width: 640px) {
  #albColorTagTop .ctag-dot { width: 19px; height: 19px; border-radius: 5px; }
  /* Nút thanh lọc/đầu trang dự án gọn lại 38px như trang khách */
  .fbar #btnDSearch, .fbar #btnDFilter, .fbar #btnDSort, .fbar #btnDView,
  .fbar #btnPjSearch, .fbar #btnPjSort, .fbar #btnPjFilter, .fbar #btnPjView, .fbar #btnPjNew {
    width: 38px; height: 38px; min-width: 38px; border-radius: 9px;
  }
}

/* ---------- Đường dẫn thư mục chỉ còn MỘT chỗ (2026-09-26) ----------
   Máy tính: thanh trên "Dự án / Tên dự án / thư mục / …" (renderTopCrumb) — bấm tên dự án hay
   thư mục để lùi về; hàng "Tất cả tệp / …" trong trang dự án ẩn đi. Điện thoại/tablet: thanh trên
   không đủ chỗ nên .cr-path ẩn, vẫn dùng hàng trong trang — nhưng ở gốc dự án (chỉ có "Tất cả tệp")
   thì ẩn luôn vì thừa. */
.crumb .cr-path { display: none; }
.crumb .cr-proj { cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .crumb .cr-proj:hover { color: var(--txt); } }
#pathCrumbs.at-root { display: none; }
@media (min-width: 1024px) {
  .sf-main .crumb .cr-path { display: inline; }
  #tabPhotos > #pathCrumbs { display: none; }
  #tabPhotos > .fbar { grid-column: 1 / -1; }
}
/* Dấu × bên phải mỗi mục "Mở gần đây" — chỉ hiện khi rê chuột/đang focus vào mục đó */
.sf-recent-x {
  flex: none; margin-left: auto; width: 22px; height: 22px; border-radius: 6px; display: grid; place-items: center;
  color: var(--txt-3); opacity: 0; transition: opacity .12s;
}
.sf-recent-item:hover .sf-recent-x, .sf-recent-item:focus-visible .sf-recent-x { opacity: 1; }
@media (hover: hover) and (pointer: fine) { .sf-recent-x:hover { background: var(--hover); color: var(--txt); } }
/* Điện thoại/tablet: trong dự án thanh trên VẪN là ô workspace + tên workspace — tên dự án đã có to
   ở tiêu đề trang (ảnh bìa + tên, .pj-hero-row) nên không lặp lại ở đây (đổi 2026-09-28, trước đó
   tên dự án thay tên workspace). Bấm ô workspace vẫn mở menu đổi workspace như cũ. */
@media (max-width: 1023px) {
  #crumb.in-proj > .sep, #crumb.in-proj > b, #crumb.in-proj > .cr-proj, #crumb.in-proj > .cr-path { display: none; }
}

/* ---------- Thanh công cụ lưới tệp trên máy tính (2026-09-27) ----------
   Thứ tự theo luồng dùng: Tìm → Lọc → Sắp xếp, nút Hiển thị bám mép phải. Mỗi nút có icon rõ
   nghĩa + chữ; Lọc hiện số điều kiện đang bật, Sắp xếp hiện luôn kiểu đang dùng. */
@media (min-width: 1024px) {
  #dSearchWrap { order: 0; }
  #btnDFilter { order: 1; }
  #btnDSort { order: 2; }
  #dAppearance { order: 3; margin-left: auto; }
  /* Trang khách + Live: cùng bố cục — ô tìm hiện thẳng (bỏ nút kính lúp), rồi Lọc → Sắp xếp →
     (Theo dõi) → Bình luận, Hiển thị bám phải */
  .fbar #btnSearch { display: none; }
  #searchWrap {
    order: 0; max-height: none; opacity: 1; margin: 0; overflow: visible; position: relative;
    flex: 1 1 220px; max-width: 320px;
  }
  #searchWrap .input {
    height: 36px; font-size: 13.5px; max-width: none; padding-left: 32px;
    background: var(--bg-1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23858899' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/svg%3E") no-repeat 10px 50% / 15px;
  }
  #btnFilterSheet { order: 1; }
  #btnSortSheet { order: 2; }
  .fbar #btnLiveFollowGrid { order: 3; }
  .fbar #btnAllComments { order: 4; }
  /* Tải tất cả: sát mép phải, ngay trước nút Hiển thị */
  .fbar #btnDlAll { order: 5; }
  .fbar > .spacer { order: 5; }
  #gAppearance { order: 6; margin-left: auto; }
  .fbar .fb-btn {
    width: auto; padding: 0 12px; gap: 7px; flex: none;
    background: var(--bg-1); border-color: var(--line-soft); color: var(--txt-2);
  }
  @media (hover: hover) and (pointer: fine) { .fbar .fb-btn:hover { color: var(--txt); border-color: var(--line); } }
  .fbar .fb-btn > svg { flex: none; }
  .fb-label { display: inline; color: var(--txt); white-space: nowrap; }
  .fb-dim { color: var(--txt-3); }
  .fb-caret { display: block; color: var(--txt-3); margin-right: -3px; }
  .fb-count {
    display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px; background: var(--accent); color: var(--on-accent, #161826); font-size: 11.5px; font-weight: 600;
  }
  .fb-count[hidden], #dFilterDot, #filterDot, #pjFilterDot { display: none; }
  .fbar #btnDFilter.active, .fbar #btnFilterSheet.active, .fbar #btnPjFilter.active { background: var(--tint); border-color: rgba(145, 132, 217, .45); color: var(--ink); }
  .fbar #btnDFilter.active .fb-label, .fbar #btnFilterSheet.active .fb-label, .fbar #btnPjFilter.active .fb-label { color: var(--ink); }
  #btnDView[aria-expanded="true"], #btnGView[aria-expanded="true"] { background: var(--bg-3); color: var(--txt); }
}

/* ---------- Nút gửi nhận xét: chữ "Gửi" + icon, nền tím nhạt (2026-09-27) ----------
   Áp cho mọi ô soạn: trang dự án (#aCmtSend), khách/Live (#cmtSend), khung so sánh (.cmp-cmt-send).
   Đặt cuối file + kèm id để thắng các luật cũ 34×32 / 36×34 (điện thoại) phía trên. */
.btn.compose-send, .comment-composer .btn.compose-send, #cmtSend.compose-send, #aCmtSend.compose-send {
  width: auto; height: 32px; padding: 0 12px; display: inline-flex; align-items: center; gap: 6px;
  border: 0; border-radius: 8px; background: var(--tint); color: var(--ink);
  font-size: 13px; font-weight: 500; white-space: nowrap;
}
.btn.compose-send svg { width: 15px; height: 15px; flex: none; }
@media (hover: hover) and (pointer: fine) { .btn.compose-send:hover { background: rgba(145, 132, 217, .26); color: var(--ink); } }
.btn.compose-send:disabled { opacity: .5; cursor: default; }
@media (max-width: 640px) {
  #cmtSend.compose-send, #aCmtSend.compose-send, .btn.compose-send { height: 36px; padding: 0 14px; font-size: 14px; }
}

/* Nút "Công khai/Nội bộ" trong ô soạn: chỉ còn icon (quả địa cầu / nhóm người, JS tự đổi) để
   hàng công cụ không phải xuống 2 dòng; Nội bộ thì tô vàng cho khỏi gửi nhầm. */
.comment-composer .vis-pick > .btn { width: 32px; padding: 0; justify-content: center; }
.comment-composer .vis-pick > .btn svg:first-child { margin-right: 0 !important; }
.comment-composer .vis-pick > .btn > span { display: none; }
.comment-composer .vis-pick > .btn.is-internal { background: rgba(255, 212, 138, .14); color: var(--warn); }
@media (max-width: 640px) {
  .comment-composer .vis-pick > .btn { width: 36px; height: 36px; max-width: none; padding: 0; }
}

/* Icon đầu nút "Sắp xếp" (A/Z theo chiều, xem window.paintSortIcon trong thread.js) */
.sort-ic { display: inline-flex; flex: none; }
.sort-ic svg { display: block; }
/* Đường kẻ trong menu/sheet trang khách (tách tiêu chí với chiều sắp xếp) — giống .ctx-sep */
.sheet-sep { height: 1px; margin: 5px 8px; background: var(--line-soft); }
/* Icon trên 3 tab của dự án (Tệp / Chia sẻ / Phản hồi) — tab đang mở tô màu nhấn */
.tab .tab-ic { flex: none; opacity: .85; }
.tab.on .tab-ic { color: var(--ink); opacity: 1; }

/* ---------- Tab Phản hồi (làm lại 2026-09-27) ----------
   Hàng đầu: lọc trạng thái (Tất cả / Chưa xử lý / Đã xử lý) · sắp xếp · tải CSV / tệp đã duyệt.
   Thẻ tệp: tiêu đề + "N nhận xét · mới nhất …", trạng thái, tối đa 3 nhận xét rồi "Xem thêm". */
.fbx-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.fbx-seg { display: inline-flex; padding: 3px; gap: 2px; border: 1px solid var(--line-soft); border-radius: 9px; background: var(--bg-1); }
.fbx-seg button {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
  border: 0; border-radius: 6px; background: transparent; color: var(--txt-2);
  font: inherit; font-size: 13px; cursor: pointer; white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) { .fbx-seg button:hover { color: var(--txt); } }
.fbx-seg button.on { background: var(--bg-3); color: var(--txt); }
.fbx-seg button span { color: var(--txt-3); font-size: 12px; }
.fbx-seg button span:empty { display: none; }
.fbx-dot { display: inline-block; width: 7px; height: 7px; border-radius: 2px; flex: none; } /* hạt vuông bo góc (2026-10-11) — cùng đợt: chấm chưa đọc thông báo, chấm lọc, live-dot, chấm thẻ màu Drive */
.fbx-dot.pending { background: var(--warn); }
.fbx-dot.done { background: var(--ok); }
#tabFeedback .feedback-sort { margin-left: 0; }
#tabFeedback .feedback-sort .input { width: 160px; height: 36px; }
.fbx-dl { gap: 6px; height: 36px; padding: 0 11px; background: var(--bg-1); border-color: var(--line-soft); color: var(--txt-2); }
@media (hover: hover) and (pointer: fine) { .fbx-dl:hover { color: var(--txt); border-color: var(--line); } }
.fbx-dl svg { flex: none; }

.feedback-list { gap: 10px; padding-top: 0; }
.feedback-card { grid-template-columns: 88px minmax(0, 1fr); gap: 14px; padding: 12px; transition: border-color .15s; }
@media (hover: hover) and (pointer: fine) { .feedback-card:hover { border-color: var(--line); } }
.feedback-card .fb-media { width: 88px; align-self: start; }
.feedback-card.all-done .fb-media { opacity: .8; }
.fb-card-head { align-items: flex-start; padding: 0 0 4px; }
.fb-open { font-weight: 500; font-size: 14px; }
.fb-sub { color: var(--txt-3); font-size: 12px; }
.fb-summary { align-items: center; }
.fb-chip { gap: 6px; min-height: 22px; padding: 1px 8px; font-size: 11.5px; }
.fb-chip.pending { background: rgba(255, 176, 72, .1); }
.fb-chip.done { background: rgba(47, 191, 113, .1); }
/* trạng thái thẻ phản hồi: chữ trơn + chấm nhỏ, không khung/nền (khung viên thuốc trông "AI" quá) */
.fb-state { flex: none; display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--txt-2); white-space: nowrap; line-height: 20px; }
.fb-state .fbx-dot { width: 6px; height: 6px; }
.fb-state.done { color: var(--txt-3); }
.fb-state.done svg { width: 13px; height: 13px; color: var(--ok); }
.fb-comment { padding: 6px 8px; margin: 0 -8px; border-top: 0; border-radius: 8px; cursor: pointer; transition: background .12s; }
.fb-comment + .fb-comment { box-shadow: 0 -1px 0 var(--line-soft); }
@media (hover: hover) and (pointer: fine) { .fb-comment:hover { background: var(--bg-2); box-shadow: none; } }
@media (hover: hover) and (pointer: fine) { .fb-comment:hover + .fb-comment { box-shadow: none; } }
.fb-comment.resolved { opacity: 1; }
.fb-comment.resolved .body { color: var(--txt-2); }
.fb-comment .who { display: flex; align-items: center; gap: 6px; margin-bottom: 1px; }
.fb-comment .avatar { width: 20px; height: 20px; font-size: 10px; }
.fb-comment .fb-who b { font-weight: 500; font-size: 13px; }
.fb-comment .who > * { grid-column: auto; grid-row: auto; }
.fb-comment .who .spacer { flex: 1; }
.fb-comment .who > .resolved-tag { width: 18px; height: 18px; font-size: 10px; }
.fb-on { flex: none; color: var(--txt-3); font-size: 12px; white-space: nowrap; }
/* thẻ "V1" = nhận xét nằm trên phiên bản nào (admin tab Phản hồi + bảng Tất cả nhận xét trang khách) */
.fb-vtag {
  flex: none; align-self: center; padding: 0 6px; border-radius: 5px; border: 1px solid var(--line);
  background: var(--bg-2); color: var(--txt-2); font-size: 11px; font-weight: 500; font-style: normal; line-height: 16px;
}
.fb-on::before { content: '· '; }
.fb-resolve {
  width: 24px; height: 24px; flex: none; display: grid; place-items: center; border: 0; border-radius: 7px;
  background: transparent; color: var(--txt-3); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .fb-resolve:hover { background: var(--hover); color: var(--txt); } }
.fb-resolve.on { color: var(--ok); }
.fb-draw { flex: none; display: inline-grid; place-items: center; color: var(--txt-3); }
.fb-draw svg { width: 16px; height: 16px; }
/* Khung gợi ý cho nút ✓ (tab Phản hồi admin + bảng Tất cả nhận xét trang khách): "Đã xử lý bởi…"
   chỉ hiện khi trỏ vào nút — mặc định ẩn cho gọn. Hiện ngay, không chờ như title của trình duyệt. */
.fb-resolve, .allc-resolve { position: relative; }
.sf-tip {
  position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 5; width: max-content; max-width: min(340px, 80vw);
  padding: 6px 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--bg-3); box-shadow: var(--shadow);
  color: var(--txt); font-size: 12px; font-weight: 400; line-height: 1.4; text-align: left; white-space: normal;
  opacity: 0; transform: translateY(2px); pointer-events: none; transition: opacity .12s, transform .12s;
}
.sf-tip small { display: block; margin-top: 1px; color: var(--txt-3); font-size: 11px; }
.fb-resolve:hover .sf-tip, .fb-resolve:focus-visible .sf-tip,
.allc-resolve:hover .sf-tip, .allc-resolve:focus-visible .sf-tip { opacity: 1; transform: none; }
@media (hover: none) { .sf-tip { display: none; } }
.fb-comment .body { padding-left: 26px; font-size: 13.5px; line-height: 1.45; }
.fb-comment.resolved .body { padding-left: 26px; color: var(--txt-3); }
.fb-comment.resolved .body::before { display: none; }
.fb-comment .when { color: var(--txt-3); font-size: 12px; white-space: nowrap; }
.fb-tag { display: inline-flex; align-items: center; gap: 3px; padding: 1px 7px; border-radius: 6px; font-size: 10.5px; line-height: 16px; white-space: nowrap; }
.fb-tag.internal { background: rgba(255, 212, 138, .14); color: var(--warn); }
.fb-tag.draw { padding: 0; background: none; color: var(--ink); }
.fb-tag.draw svg { width: 11px; height: 11px; }
.fb-more {
  margin-top: 6px; padding: 5px 0; border: 0; background: none; color: var(--ink);
  font: inherit; font-size: 12.5px; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .fb-more:hover { text-decoration: underline; text-underline-offset: 3px; } }

@media (max-width: 640px) {
  .fbx-head { gap: 8px; }
  .fbx-seg { width: 100%; }
  .fbx-seg button { flex: 1; justify-content: center; padding: 0 6px; height: 34px; font-size: 12.5px; }
  #tabFeedback .fbx-head > .spacer { display: none; }
  #tabFeedback .feedback-sort { width: 100%; flex: 1 1 100%; }
  #tabFeedback .feedback-sort .input { width: 100%; height: 38px; }
  .fbx-dl { flex: 1; justify-content: center; height: 38px; padding: 0 10px; }
  /* ảnh nhỏ cạnh tiêu đề, danh sách nhận xét trải hết bề ngang bên dưới */
  .feedback-card { grid-template-columns: 60px minmax(0, 1fr); column-gap: 12px; row-gap: 0; padding: 12px; }
  .feedback-card .fb-media { width: 60px; aspect-ratio: 1; }
  .feedback-card .fb-main { display: contents; }
  .feedback-card .fb-card-head { grid-column: 2; display: grid; gap: 6px; padding-bottom: 0; }
  .feedback-card .fb-comments, .feedback-card .fb-more { grid-column: 1 / -1; }
  .feedback-card .fb-comments { margin-top: 10px; }
  .fb-comment .when { display: inline; }
  .fb-chip:first-child { display: inline-flex; }
}

/* ---------- Hiển thị danh sách dự án (2026-09-27) ----------
   #cards nhận: --pcard-min (cỡ thẻ S/M/L), data-aspect (ảnh bìa), .pj-gallery (Thư viện), .pj-noinfo. */
@media (min-width: 641px) {
  #cards { grid-template-columns: repeat(auto-fill, minmax(var(--pcard-min, 250px), 1fr)); }
}
#cards[data-aspect="square"] .card .thumb { aspect-ratio: 1; }
#cards[data-aspect="portrait"] .card .thumb { aspect-ratio: 4 / 5; }
#cards.pj-noinfo .project-card-stats, #cards.pj-noinfo .project-created { display: none; }
#cards.pj-noinfo .card .meta h3 { margin-bottom: 0; }
#pjViewPop.list-mode .pj-grid-setting, #pjViewPop.list-mode .pj-info-setting { opacity: .4; pointer-events: none; }
/* Thư viện — phương án A "Tấm phim" (2026-10-13, tools/mockup-gallery-mode.html): ảnh bo 8px không khung,
   tên + dòng phụ "ngày tạo · tệp · dung lượng" nằm DƯỚI ảnh (ảnh không bị đè gì),
   rê chuột hiện số tệp/dung lượng/nhận xét/link đè đáy ảnh. Phần tử .pj-* chỉ hiện trong .pj-gallery. */
.pj-gal-hov, .pj-gal-sub { display: none; }
#cards.pj-gallery { gap: 22px 16px; }
#cards.pj-gallery .card { background: none; border: 0; border-radius: 0; overflow: visible; }
@media (hover: hover) and (pointer: fine) { #cards.pj-gallery .card:hover { transform: none; } }
#cards.pj-gallery .card .thumb { position: relative; border-radius: 8px; overflow: hidden; transition: filter .2s; }
#cards.pj-gallery[data-aspect="landscape"] .card .thumb { aspect-ratio: 3 / 2; }
@media (hover: hover) and (pointer: fine) { #cards.pj-gallery .card:hover .thumb { filter: brightness(1.07); } }
#cards.pj-gallery .pj-gal-hov {
  position: absolute; left: 0; right: 0; bottom: 0; display: flex; gap: 12px; padding: 24px 10px 8px;
  font-size: 12px; color: #fff; background: linear-gradient(to top, rgba(10, 11, 18, .78), transparent);
  opacity: 0; transition: opacity .2s; pointer-events: none;
}
#cards.pj-gallery .pj-gal-hov span { display: inline-flex; align-items: center; gap: 4px; }
#cards.pj-gallery .pj-gal-hov svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
#cards.pj-gallery .card:hover .pj-gal-hov { opacity: 1; }
#cards.pj-gallery .card .meta { padding: 9px 2px 0; }
#cards.pj-gallery .card .meta h3 { display: block; margin: 0; font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cards.pj-gallery .project-card-stats, #cards.pj-gallery .project-created { display: none; }
#cards.pj-gallery .pj-gal-sub { display: block; margin-top: 1px; font-size: 12px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cards.pj-gallery .pj-gal-sub time { color: var(--txt-2); }
#cards.pj-gallery.pj-noinfo .pj-gal-sub, #cards.pj-gallery.pj-noinfo .pj-gal-hov { display: none; }
@media (hover: none) { #cards.pj-gallery .pj-gal-hov { display: none; } }
@media (max-width: 640px) {
  #cards.pj-gallery { gap: 16px 10px; }
  #cards.pj-gallery .card .meta h3 { font-size: 13.5px; }
}


/* ---------- Phân biệt "đang ở trong dự án" với danh sách dự án (2026-09-27) ----------
   1) Thanh bên: dòng dự án đang mở thụt vào dưới "Dự án" (#sfNavCur, vạch tím trái).
   2) Nút "‹ Tất cả dự án" hiện cả trên máy tính (trước chỉ điện thoại).
   3) Bìa dự án (.pj-hero): nền mờ lấy từ ảnh bìa + ảnh bìa nhỏ + nhãn "DỰ ÁN" + 3 tab. */
.ph-break, .pj-hero-cover { display: none; }
.sf-nav button.sf-nav-sub {
  height: 34px; margin-left: 14px; padding-left: 10px; gap: 9px;
  border-left: 2px solid var(--accent); border-radius: 0 8px 8px 0;
}
.sf-nav button.sf-nav-sub .sf-recent-thumb { width: 20px; height: 20px; border-radius: 5px; }
.sf-nav button.sf-nav-sub .sf-nav-lb { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 1024px) {
  #viewProject .pj-hero {
    position: relative; isolation: isolate; overflow: hidden;
    margin: -28px -32px 16px; padding: 16px 32px 0;
  }
  #viewProject .page-head { margin-bottom: 0; row-gap: 12px; }
  /* .pj-hero-row bọc ảnh bìa + tiêu đề (thêm 2026-09-28 để sửa lỗi tablet) — quên khai báo
     display:flex ở đây nên máy tính rơi về display:block mặc định, xếp DỌC thay vì NGANG (ảnh bìa
     nhảy lên trên tiêu đề) và các nút bên cạnh (avatar, Chia sẻ) bị canh giữa theo chiều cao khối
     dọc đó thay vì theo đúng 1 hàng với tiêu đề (lỗi thật, 2026-09-28). */
  /* flex-basis 0 (không phải auto): flex-wrap quyết định xuống dòng theo kích thước GỐC trước khi co,
     nên basis auto = cả chiều dài tên → nút "Chia sẻ" vẫn rớt dòng ở 1024px dù tên co được. Basis 0
     + grow 1 thay luôn vai trò .spacer (ẩn bên dưới) đẩy avatar/nút sang phải. */
  #viewProject .pj-hero-row { display: flex; align-items: center; gap: 10px; flex: 1 1 0; min-width: 0; }
  #viewProject .page-head > .spacer { display: none; }
  /* Tên dự án dài/màn 1024px (thanh bên đã chiếm 236px): cho tên co lại + "…" thay vì đẩy nút
     "Chia sẻ" rớt xuống 1 hàng riêng bên dưới (lỗi thật, 2026-09-28). Rê chuột xem tên đầy đủ:
     paintProjectHero() gắn title cho #dName. */
  #viewProject .ph-title h1 { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #viewProject .pj-hero-cover {
    display: block; flex: none; width: 52px; height: 52px; border-radius: 8px;
    background: var(--bg-2) center / cover no-repeat; box-shadow: 0 0 0 1px var(--line-soft);
  }
  #viewProject .pj-hero-cover.no-img {
    background: rgba(145, 132, 217, .2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d2cefd' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7.5V18a1.5 1.5 0 0 0 1.5 1.5h15A1.5 1.5 0 0 0 21 18V9.5A1.5 1.5 0 0 0 19.5 8H12l-2.2-2.6a1.5 1.5 0 0 0-1.15-.4H4.5A1.5 1.5 0 0 0 3 6.5z'/%3E%3C/svg%3E") center / 24px no-repeat;
  }
  #viewProject .pj-hero-row { gap: 14px; }
  #viewProject .ph-title { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  #viewProject .pj-hero > .tabs { margin: 14px 0 0 !important; }
}

/* ---------- Bìa dự án cũng hiện trên điện thoại/tablet (2026-09-28) ----------
   Trước đây .pj-hero (nền mờ + ảnh bìa nhỏ + nhãn "DỰ ÁN") chỉ có ở máy tính — điện thoại/tablet
   chỉ thấy chữ trơn. Dùng lại đúng cấu trúc đó, chỉ đổi số đo (lề âm phải khớp padding của .wrap
   ở từng cỡ màn hình để ảnh nền tràn đúng ra sát mép, xem .wrap trong khối @media tương ứng) và cho
   .ph-title chia sẻ hàng với ảnh bìa nhỏ thay vì chiếm trọn 100% bề ngang như bản chữ trơn cũ. */
@media (max-width: 1023px) {
  #viewProject .pj-hero { position: relative; isolation: isolate; overflow: hidden; }
  #viewProject .ph-break { display: none; } /* chỉ dùng ở máy tính — điện thoại/tablet ngắt dòng bằng .pj-hero-row bên dưới */
  /* .pj-hero-row (ảnh bìa + tiêu đề) LUÔN chiếm trọn 1 hàng riêng, bất kể còn thừa chỗ hay không —
     dùng flex-basis:100% ngay trên chính khối này (không phải suy đoán qua "tràn thì tự xuống dòng"
     như bản cũ, vốn chỉ tình cờ đúng ở màn điện thoại hẹp mà SAI ở tablet dọc vì mọi thứ vẫn đủ chỗ
     nằm chung 1 hàng — lỗi thật, 2026-09-28). */
  #viewProject .pj-hero-row {
    display: flex; align-items: center; gap: 10px; flex-basis: 100%; order: 2; margin-top: 4px;
    min-width: 0; /* thiếu dòng này thì tên dài làm hàng phình ra ngoài màn hình, "…" không bao giờ hiện */
  }
  #viewProject .pj-hero-cover {
    display: block; flex: none; border-radius: 8px;
    background: var(--bg-2) center / cover no-repeat; box-shadow: 0 0 0 1px var(--line-soft);
  }
  #viewProject .pj-hero-cover.no-img {
    background: rgba(145, 132, 217, .2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d2cefd' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7.5V18a1.5 1.5 0 0 0 1.5 1.5h15A1.5 1.5 0 0 0 21 18V9.5A1.5 1.5 0 0 0 19.5 8H12l-2.2-2.6a1.5 1.5 0 0 0-1.15-.4H4.5A1.5 1.5 0 0 0 3 6.5z'/%3E%3C/svg%3E") center / 20px no-repeat;
  }
  /* Tự định nghĩa đầy đủ .ph-title ở đây (không dựa vào bản ≤640px của khối "tiêu đề trang" phía
     trên) — .wrap gốc chỉ đổi cách trình bày ở 2 mốc 640/1024px nên khoảng 641–1023px (tablet dọc)
     nếu không tự lo sẽ rơi về display:contents của bản desktop, làm ảnh bìa lạc chỗ. #viewProject
     (id) nên luôn thắng .ph-title (class) dù rule nào định nghĩa sau. */
  #viewProject .ph-title {
    display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0;
  }
  #viewProject .ph-title h1 { flex: none; font-size: 21px; }
  /* Nhóm nút ở hàng "‹ Tất cả dự án" vốn chỉ ép order:1 ở ≤640px (khối "tiêu đề trang") — khoảng
     641–1023px (tablet dọc) không có mốc này nên trước đây rơi về order mặc định 0. Ép lại ở đây
     cho cả dải ≤1023px (order:2 cũng được, chỉ cần NHỎ HƠN .pj-hero-row để đứng trước nó). */
  #viewProject #btnBack, #viewProject #pjAvatars, #viewProject #btnInvite,
  #viewProject #btnMore, #viewProject #btnUpload, #viewProject #btnShare { order: 1; }
  /* Chỉ cụm avatar được đẩy sang phải (margin-left:auto); nút Mời bám sát ngay sau nó — để cả 2
     cùng auto thì khoảng trống bị chia đôi, avatar lơ lửng giữa hàng (lỗi thật, 2026-09-28). Không
     có avatar (dự án chưa mời ai) thì nút Mời tự nhận việc đẩy sang phải. Giống bản ≤640px. */
  #viewProject #pjAvatars { margin-left: auto; }
  #viewProject #pjAvatars:not([hidden]) + #btnInvite { margin-left: 4px; }
  #viewProject #pjAvatars[hidden] + #btnInvite { margin-left: auto; }
  /* .spacer (flex:1, order mặc định 0) vốn chỉ bị ẩn ở ≤640px (".page-head .spacer") — thiếu ở
     641–1023px thì nó nhảy lên ĐẦU hàng (order 0 < order 1 vừa gán) và nuốt hết chỗ trống, đẩy cả
     cụm nút (kể cả "‹ Tất cả dự án") dạt hẳn sang phải (lỗi thật, 2026-09-28). */
  #viewProject .page-head > .spacer { display: none; }
}
@media (min-width: 721px) and (max-width: 1023px) {
  /* Lề âm khớp padding của .wrap ở cỡ tablet (22px/18px, xem .wrap không kèm media) để ảnh nền
     tràn sát mép màn hình thay vì chừa viền trắng quanh khối .pj-hero. */
  #viewProject .pj-hero { margin: -22px -18px 14px; padding: 14px 18px 0; }
  #viewProject .pj-hero-cover { width: 48px; height: 48px; }
}
@media (max-width: 720px) {
  /* Lề âm khớp padding của .wrap ở cỡ điện thoại (16px/12px, xem khối "max-width: 720px" đầu file). */
  #viewProject .pj-hero { margin: -16px -12px 14px; padding: 10px 12px 0; }
  #viewProject .pj-hero-cover { width: 40px; height: 40px; }
}

/* ---------- Đường dẫn thư mục chuyển sang thanh bên (2026-09-27) ----------
   Máy tính: thanh trên không còn đường dẫn; thanh bên hiện cây "dự án › thư mục cha › thư mục đang mở"
   + thư mục con (#sfPath). Điện thoại/tablet: hàng đường dẫn trong trang có nút ‹ lên cấp trên,
   dấu ›, cuộn ngang (không xuống dòng). */
.sf-path { display: flex; flex-direction: column; gap: 1px; }
.sf-path[hidden] { display: none; }
.sf-nav .sf-path-item {
  height: 30px; margin-left: calc(14px + var(--lvl, 1) * 12px); padding: 0 8px; gap: 8px;
  border-radius: 7px; font-size: 13px;
}
.sf-nav .sf-path-item svg { flex: none; opacity: .8; }
.sf-nav .sf-path-item .sf-nav-lb { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-nav .sf-path-item.on { background: var(--tint); color: var(--txt) !important; }
.sf-nav .sf-path-item.on svg { color: var(--ink); opacity: 1; }
.sf-nav .sf-path-item.child { color: var(--txt-3) !important; }
@media (hover: hover) and (pointer: fine) { .sf-nav .sf-path-item.child:hover { color: var(--txt) !important; } }
.sf-path-more { margin-left: calc(22px + var(--lvl, 1) * 12px); padding: 4px 8px; font-size: 12px; color: var(--txt-3); }
/* "Xem thêm N thư mục" / "Thu gọn" — bấm được (2026-09-30) */
button.sf-path-more { align-self: flex-start; border: 0; background: none; font: inherit; font-size: 12px; border-radius: 6px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { button.sf-path-more:hover { color: var(--ink); background: var(--hover); } }
@media (min-width: 1024px) {
  .sf-main .topbar .crumb { visibility: hidden; }
}
@media (max-width: 1023px) {
  #pathCrumbs { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 14px; }
  #pathCrumbs.at-root { display: none; }
  #pathCrumbs .cr-up {
    flex: none; width: 34px; height: 34px; display: grid; place-items: center; padding: 0;
    border: 1px solid var(--line-soft); border-radius: 9px; background: var(--bg-1); color: var(--txt-2); cursor: pointer;
  }
  #pathCrumbs .cr-up:active { background: var(--bg-2); }
  #pathCrumbs .cr-trail {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px;
    overflow-x: auto; white-space: nowrap; scrollbar-width: none;
    padding-left: 2px;
  }
  #pathCrumbs .cr-trail::-webkit-scrollbar { display: none; }
  #pathCrumbs .cr { flex: none; padding: 6px 2px; color: var(--txt-2); }
  #pathCrumbs .cr.cur { color: var(--txt); font-weight: 500; }
  #pathCrumbs .sep { flex: none; color: var(--txt-3); font-size: 16px; line-height: 1; }
}
/* Đường dẫn thư mục dài (mọi khổ màn hình, kể cả iPad ngang): mờ mép nào còn phần bị che.
   JS gắn .is-scrolled (che bên trái) / .has-more (che bên phải). */
#pathCrumbs .cr-trail.is-scrolled {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 14px); mask-image: linear-gradient(to right, transparent, #000 14px);
}
#pathCrumbs .cr-trail.has-more {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 24px); mask-image: linear-gradient(to left, transparent, #000 24px);
}
#pathCrumbs .cr-trail.is-scrolled.has-more {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 24px), transparent);
}

/* ---------- Máy tính: bỏ thanh trên, chuông thông báo sang thanh bên (2026-09-28) ----------
   JS placeTopbarItems() chuyển #jobsWrap + .notif-wrap vào #sfTopSlot (góc phải hàng logo) và
   Popover thông báo/tiến độ mở sang PHẢI thanh bên. "+ Dự án mới" nằm ở hàng tiêu đề trang dự án. */
.sf-top { display: flex; align-items: center; gap: 4px; }
.sf-top .sf-brand { flex: 1; min-width: 0; }
.sf-top-slot { display: flex; align-items: center; gap: 2px; flex: none; }
.sf-top-slot:empty { display: none; }
@media (min-width: 1024px) {
  .sf-main > .topbar:not(.tb-sel) { display: none; }
  .cmp-overlay { top: 0; }
  .sf-top-slot .notif-wrap { position: static; }
  .sf-top-slot #btnNotif, .sf-top-slot #btnJobs { width: 32px; height: 32px; color: var(--txt-2); }
  @media (hover: hover) and (pointer: fine) { .sf-top-slot #btnNotif:hover, .sf-top-slot #btnJobs:hover { background: var(--hover); color: var(--txt); } }
  .sf-top-slot #btnJobs { width: auto; padding: 0 8px; }
  .sf-top-slot .jobs-label { display: none; }
  .sf-top-slot .notif-drop, .sf-top-slot .jobs-pop {
    position: fixed; top: 12px; left: 244px; right: auto; max-height: calc(100vh - 24px);
  }
  .sf-top-slot .notif-drop { width: 360px; max-height: min(560px, calc(100vh - 24px)); }
}

/* "+ Dự án mới" ở hàng tiêu đề trang chủ dự án — mọi cỡ màn hình (2026-09-28); nút "+" cũ trên
   hàng công cụ điện thoại (#btnPjNew) bỏ đi cho khỏi trùng */
#viewProjects .page-head > .spacer { flex: 1; }
.pj-head-new { gap: 6px; height: 34px; padding: 0 13px; }
.pj-head-new svg { flex: none; }
.pj-head-new.pj-hide { display: none; }
#btnPjNew { display: none !important; }
@media (max-width: 640px) {
  /* cùng hàng với tiêu đề "Dự án" + avatar + nút mời, đứng cuối bên phải */
  /* điện thoại hẹp: chỉ icon "+" 38px để nằm vừa cùng hàng (chữ "Dự án mới" vẫn có trong aria-label) */
  #viewProjects .page-head #btnNew.pj-head-new { order: 2; width: 38px; height: 38px; padding: 0; justify-content: center; border-radius: 9px; }
  #viewProjects .page-head #btnNew.pj-head-new span { display: none; }
  #viewProjects .page-head #btnNew.pj-head-new svg { width: 18px; height: 18px; }
}



/* ---------- Tiêu đề dự án co lại khi cuộn (điện thoại/tablet, 2026-09-28) ----------
   Điều khiển bởi setupPjCollapse() trong admin.js: .pj-on bật chế độ, .pj-mini khi tên chạm thanh trên,
   --pj-stick = top âm để chỉ chừa dải tên + tab dưới thanh trên, --pj-dx/--pj-dy/--pj-s = đường đi
   của tên dự án tới chỗ nằm ngay trên hàng tab. Chỉ transform/opacity → không đổi bố cục. */
@media (max-width: 1023px) {
  #viewProject .pj-hero { background-color: var(--head-band); border-bottom: 1px solid var(--line); } /* nền đặc để nội dung cuộn không lộ qua */
  #viewProject .pj-hero.pj-on {
    position: sticky; top: var(--pj-stick, 0px); z-index: 40;
    transition: transform .24s ease, opacity .24s ease;
  }
  #viewProject .pj-hero.pj-measure { position: relative; top: auto; }
  #viewProject .pj-hero.pj-measure * { transform: none !important; }
  #viewProject .pj-hero.pj-notr * { transition: none !important; }
  /* Tên dự án 1 dòng (thu nhỏ vẫn gọn, dài thì "…" — rê/nhấn giữ xem tên đủ qua title) */
  #viewProject .pj-hero.pj-on .ph-title h1 {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
    transform-origin: 0 50%; will-change: transform;
    transition: transform .24s var(--ease-out);
  }
  #viewProject .pj-hero.pj-on .page-head > :not(.pj-hero-row),
  #viewProject .pj-hero.pj-on .ph-title > .pj-meta { transition: opacity .2s ease; }
  #viewProject .pj-hero.pj-on .pj-hero-cover {
    transform-origin: 0 50%; transition: opacity .2s ease, transform .24s var(--ease-out);
  }
  /* .pj-mini: tên lớn đã chạm mép thanh trên → thu gọn (transition ở trên lo phần chuyển động) */
  #viewProject .pj-hero.pj-mini .ph-title h1 {
    transform: translate(var(--pj-dx, 0px), var(--pj-dy, 0px)) scale(var(--pj-s, 1));
  }
  #viewProject .pj-hero.pj-mini .page-head > :not(.pj-hero-row),
  #viewProject .pj-hero.pj-mini .ph-title > .pj-meta { opacity: 0; }
  #viewProject .pj-hero.pj-mini .pj-hero-cover { opacity: 0; transform: scale(.65); }
  /* Đã dính: phần trên (khuất sau thanh trên) không nhận chạm; tên dự án bấm được để lên đầu trang */
  #viewProject .pj-hero.pj-stuck .page-head > :not(.pj-hero-row) { visibility: hidden; }
  #viewProject .pj-hero.pj-stuck .ph-title h1 { cursor: pointer; }
  #viewProject .pj-hero.pj-stuck { box-shadow: 0 1px 0 var(--line-soft); }
  /* Cách 3: cuộn xuống ẩn luôn dải tên + tab (trượt lên sau thanh trên), vuốt ngược lên hiện lại */
  #viewProject .pj-hero.pj-tuck { transform: translateY(calc(-1 * var(--pj-band, 0px))); opacity: 0; pointer-events: none; }
}
/* Máy tính (≥1024px, không có thanh trên): đủ chỗ nên GIỮ NGUYÊN cả khối bìa dự án (nút quay lại,
   ảnh bìa, tên, nút Chia sẻ, 3 tab) dính ở mép trên khi cuộn — không thu gọn như điện thoại.
   Nền đặc bên dưới lớp mờ để lưới ảnh cuộn phía sau không lộ qua (2026-09-28). */
@media (min-width: 1024px) {
  #viewProject .pj-hero { position: sticky; top: 0; z-index: 40; background-color: var(--bg); }
}

/* ---------- Trang khách: tên dự án/tệp/thư mục được chia sẻ là tiêu đề riêng (2026-09-28) ----------
   Trước đây nằm chen trong thanh trên cạnh logo (.crumb) — nay tách xuống đầu .wrap, thanh trên chỉ
   còn logo + thông báo + tài khoản. */
.sh-head { display: flex; flex-direction: column; gap: 4px; margin: 4px 0 18px; min-width: 0; }
.sh-head h1 {
  margin: 0; font-size: 26px; font-weight: 500; line-height: 1.25; letter-spacing: -.01em; color: var(--txt);
  overflow-wrap: anywhere;
}
.sh-head #pCount { font-size: 13.5px; color: var(--txt-3); font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .sh-head { margin: 2px 0 14px; }
  .sh-head h1 { font-size: 22px; }
}
/* Thanh trên không còn .crumb (vốn flex:1 đẩy chuông + avatar sang phải; điện thoại lại ẩn .spacer)
   → để logo tự đẩy phần còn lại sang mép phải */
.topbar:not(:has(.crumb)) > .brand { margin-right: auto; }

/* ==========================================================================
   My Drive (2026-09-29) — kho file riêng của tài khoản, giao diện Nocturne.
   DOM dựng bởi public/js/drive.js trong #viewDrive; chỉ dùng token màu (--bg-1…3, --txt-1…3,
   --accent/--ink/--tint/--danger) để chế độ Sáng tự đúng.
   ========================================================================== */
.drv-view { position: relative; min-height: 60vh; }
.drv-head .btn svg { flex: none; }
.drv-view .btn.ghost.danger { border-color: transparent; color: var(--danger); }
@media (hover: hover) and (pointer: fine) { .drv-view .btn.ghost.danger:hover { background: rgba(232, 149, 154, .1); } }

/* dung lượng */
.drv-quota { margin: -6px 0 18px; max-width: 520px; }
.drv-quota-txt { display: flex; align-items: center; gap: 12px; font-size: 12.5px; color: var(--txt-2); margin-bottom: 6px; }
.drv-quota-bar { height: 4px; border-radius: 4px; background: var(--bg-2); overflow: hidden; }
.drv-quota-bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width .3s; }
.drv-quota.warn .drv-quota-bar i { background: var(--warn); }
.drv-quota.in-modal { margin: 0 0 14px; max-width: none; }
.drv-link { background: none; border: 0; padding: 0; color: var(--ink); font: inherit; font-size: 12.5px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .drv-link:hover { text-decoration: underline; } }

/* thanh đường dẫn + công cụ */
.drv-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 16px; min-height: 36px; flex-wrap: wrap; }
.drv-bar > .spacer { flex: 1; }
.drv-crumbs { display: flex; align-items: center; gap: 2px; min-width: 0; font-size: 14px; flex-wrap: wrap; }
.drv-crumb { background: none; border: 0; padding: 4px 6px; border-radius: 6px; color: var(--txt-2); font: inherit; cursor: pointer;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) and (pointer: fine) { button.drv-crumb:hover { background: var(--hover); color: var(--txt); } }
b.drv-crumb { color: var(--txt); font-weight: 500; cursor: default; }
.drv-crumb-sep { display: inline-flex; color: var(--txt-3); }
.drv-seg { display: inline-flex; padding: 3px; gap: 2px; border: 1px solid var(--line-soft); border-radius: 8px; }
.drv-seg button { height: 28px; min-width: 30px; padding: 0 10px; border: 0; border-radius: 6px; background: none; color: var(--txt-2);
  font: inherit; font-size: 13px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .drv-seg button:hover { color: var(--txt); } }
.drv-seg button.on { background: var(--bg-2); color: var(--txt); }
.drv-viewseg button { padding: 0 7px; }
.drv-sortbtn { color: var(--txt-2); }
/* nút sắp xếp trang khách: icon to hơn, luôn hiện tên cách sắp xếp (cả điện thoại) */
#dshSort { gap: 7px; }
#dshSort svg { width: 18px; height: 18px; flex: none; }
#dshSort span { white-space: nowrap; }

/* thanh chọn nhiều */
.drv-selbar { position: sticky; top: 8px; z-index: 6; display: flex; align-items: center; gap: 6px; margin: 0 0 16px;
  padding: 6px 8px; border-radius: 10px; background: var(--bg-1); box-shadow: var(--shadow); font-size: 13.5px; }
.drv-selbar[hidden] { display: none; }
.drv-selbar > .spacer { flex: 1; }
.drv-selbar #drvSelN { color: var(--txt); font-weight: 500; }

/* khu nội dung */
.drv-sec + .drv-sec { margin-top: 26px; }
.drv-sec[hidden] { display: none; }
.drv-sec-title { font-size: 13.5px; font-weight: 500; color: var(--txt-2); margin: 0 0 10px; }
.drv-it { position: relative; cursor: pointer; user-select: none; -webkit-user-select: none; outline: none; }
.drv-it:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.drv-check { position: absolute; z-index: 2; width: 20px; height: 20px; border-radius: 6px; display: grid; place-items: center;
  border: 1.5px solid var(--line); background: var(--bg-1); color: transparent; opacity: 0; transition: opacity .12s; }
.drv-it:hover .drv-check, .drv-selecting .drv-check, .drv-it.picked .drv-check { opacity: 1; }
.drv-it.picked .drv-check { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.drv-badge { display: inline-flex; color: var(--txt-3); flex: none; }

/* ô thư mục: hàng 56px như lưới thư mục trong dự án */
.drv-folders { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.drv-folder { display: flex; align-items: center; gap: 10px; height: 56px; padding: 0 14px 0 12px; border-radius: 10px;
  background: var(--bg-1); border: 1px solid var(--line-soft); }
@media (hover: hover) and (pointer: fine) { .drv-folder:hover { border-color: var(--line); } }
/* Sáng: --bg-1 trùng nền trang (trắng) nên ô thư mục lẫn vào nền — nền xám rất nhạt (2026-10-11) */
html[data-theme="light"] .drv-folder:not(.picked) { background: #f6f7f9; }
@media (hover: hover) and (pointer: fine) { html[data-theme="light"] .drv-folder:not(.picked):hover { background: #f1f3f5; } }
.drv-folder .drv-check { left: -7px; top: -7px; }
.drv-folder-ic { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 8px; background: var(--tint); color: var(--ink); flex: none; }
.drv-folder .drv-name { flex: 1; }
.drv-folder.picked { border-color: var(--accent); background: var(--tint); }
.drv-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; color: var(--txt); font-weight: 500; }

/* ô tệp dạng lưới */
.drv-files.is-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 14px; }
.drv-tile { border-radius: 10px; background: var(--bg-1); border: 1px solid var(--line-soft); overflow: hidden; display: flex; flex-direction: column; }
@media (hover: hover) and (pointer: fine) { .drv-tile:hover { border-color: var(--line); } }
.drv-tile .drv-check { left: 8px; top: 8px; }
.drv-tile.picked { border-color: var(--accent); }
.drv-tile.picked .drv-thumb::after { content: ''; position: absolute; inset: 0; background: rgba(145, 132, 217, .18); }
.drv-thumb { position: relative; aspect-ratio: 16 / 10; background: var(--bg-2); display: grid; place-items: center; overflow: hidden; }
.drv-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.drv-kind { display: grid; justify-items: center; gap: 6px; color: var(--txt-3); }
.drv-kind em { font-style: normal; font-size: 11px; font-weight: 600; letter-spacing: .04em; color: var(--txt-2);
  padding: 2px 6px; border-radius: 4px; background: var(--hover); }
.drv-tile.k-pdf .drv-kind, .drv-row.k-pdf .drv-row-ic { color: #e8959a; }
.drv-tile.k-video .drv-kind, .drv-row.k-video .drv-row-ic { color: #a79be6; }
.drv-tile.k-audio .drv-kind, .drv-row.k-audio .drv-row-ic { color: #7fcfa0; }
.drv-tile.k-zip .drv-kind, .drv-row.k-zip .drv-row-ic { color: #e6c35c; }
.drv-tile.k-sheet .drv-kind, .drv-row.k-sheet .drv-row-ic { color: #7fcfa0; }
.drv-tile.k-design .drv-kind, .drv-row.k-design .drv-row-ic { color: #8fb8e8; }
.drv-meta { display: grid; gap: 2px; padding: 9px 11px 10px; min-width: 0; }
.drv-sub { font-size: 12px; color: var(--txt-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-tile > .drv-badge { position: absolute; right: 8px; top: 8px; padding: 4px; border-radius: 6px; background: rgba(16, 17, 27, .7); color: #e9e9ed; }

/* ô tệp dạng danh sách */
.drv-list-head, .drv-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) minmax(0, 160px) 110px 90px 28px; align-items: center; gap: 12px; }
.drv-list-head { padding: 0 12px 8px; font-size: 12.5px; color: var(--txt-3); border-bottom: 1px solid var(--line-soft); }
.drv-list-head[hidden] { display: none; }
.drv-files.is-list { display: flex; flex-direction: column; }
.drv-row { min-height: 48px; padding: 6px 12px; border-bottom: 1px solid var(--line-soft); border-radius: 8px; }
@media (hover: hover) and (pointer: fine) { .drv-row:hover { background: var(--hover); } }
.drv-row.picked { background: var(--tint); }
.drv-row .drv-check { position: static; opacity: 1; background: none; }
.drv-row:not(.picked) .drv-check { opacity: .0; }
.drv-row:hover .drv-check, .drv-selecting .drv-row .drv-check { opacity: 1; }
.drv-row-name { display: flex; align-items: center; gap: 10px; min-width: 0; }
.drv-row-ic { position: relative; width: 32px; height: 32px; flex: none; border-radius: 6px; background: var(--bg-2);
  display: grid; place-items: center; color: var(--txt-3); overflow: hidden; }
.drv-row-ic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.drv-cell { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Ảnh nền trong suốt (JS sfThumbLoad gắn .is-alpha): nền ô cờ như Figma, thu vừa khung chừa lề thay vì cắt;
   ảnh đã tải xong thì ẩn icon loại tệp nằm dưới (trước đây lộ qua phần trong suốt). */
.drv-thumb.has-img > .drv-kind, .drv-row-ic.has-img > svg { visibility: hidden; }
.drv-thumb.is-alpha, .drv-row-ic.is-alpha, .drv-lb-stage > img.is-alpha {
  --chk: color-mix(in srgb, var(--txt) 9%, var(--bg-2));
  background-color: var(--bg-2);
  background-image: conic-gradient(var(--chk) 25%, transparent 0 50%, var(--chk) 0 75%, transparent 0);
  background-size: 14px 14px;
}
.drv-thumb.is-alpha img { object-fit: contain; padding: 9% 11%; box-sizing: border-box; }
.drv-row-ic.is-alpha { background-size: 8px 8px; }
.drv-row-ic.is-alpha img { object-fit: contain; padding: 3px; box-sizing: border-box; }
.drv-lb-stage > img.is-alpha { background-size: 16px 16px; }

/* trống */
.drv-empty { margin-top: 20px; padding: 56px 24px; border: 1px dashed var(--line); border-radius: 16px; text-align: center;
  background: radial-gradient(520px 240px at 50% 0%, var(--tint), transparent 70%); }
.drv-empty[hidden] { display: none; }
.drv-empty-art { display: inline-grid; place-items: center; width: 72px; height: 72px; border-radius: 20px; background: var(--tint); color: var(--ink); margin-bottom: 14px; }
.drv-empty h3 { margin: 0 0 6px; font-size: 18px; font-weight: 500; color: var(--txt); }
.drv-empty p { margin: 0 auto; max-width: 52ch; }
.drv-empty-cta { display: flex; justify-content: center; gap: 10px; margin-top: 18px; flex-wrap: wrap; }

/* kéo thả từ máy */
.drv-drop-hint { position: fixed; inset: 0; z-index: 40; display: none; place-items: center; align-content: center; gap: 10px;
  color: var(--ink); font-size: 15px; font-weight: 500; pointer-events: none;
  background: rgba(22, 24, 38, .55); box-shadow: inset 0 0 0 3px var(--accent); }
.drv-dragging .drv-drop-hint { display: grid; }

/* thùng rác */
.drv-trash[hidden] { display: none; }
.drv-trash-head { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
.drv-trash-head p { margin: 0; flex: 1; }
.drv-trash-list { border: 1px solid var(--line-soft); border-radius: 12px; overflow: hidden; }
.drv-trash-row { display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft); cursor: default; }
.drv-trash-row:last-child { border-bottom: 0; }
.drv-trash-main { display: grid; gap: 2px; min-width: 0; font-size: 12.5px; }
.drv-trash-acts { display: flex; gap: 6px; }

/* hộp thoại */
.modal.drv-modal { width: min(560px, calc(100vw - 32px)); }
.drv-field { display: grid; gap: 6px; font-size: 12.5px; color: var(--txt-2); }
.drv-field .input { width: 100%; }
.drv-hint { font-size: 12.5px; margin: 8px 0 0; line-height: 1.5; }
.drv-h3 { font-size: 13.5px; font-weight: 500; color: var(--txt); margin: 20px 0 10px; }
.drv-h3 .dim { font-weight: 400; font-size: 12.5px; }
.drv-invite { display: grid; grid-template-columns: minmax(0, 1fr) 120px auto; gap: 8px; }
.drv-people { display: grid; gap: 2px; }
.drv-person { display: grid; grid-template-columns: 32px minmax(0, 1fr) 120px 32px; align-items: center; gap: 10px; padding: 6px 0; }
.drv-person .drv-person-role { grid-column: 3 / 5; text-align: right; font-size: 12.5px; }
.drv-person-main { display: grid; min-width: 0; font-size: 13px; }
.drv-person-main b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-person-main .dim { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-person select.input { height: 32px; font-size: 12.5px; padding: 0 8px; }
.drv-av { width: 32px; height: 32px; border-radius: 6px; display: grid; place-items: center; overflow: hidden; font-size: 12px; font-weight: 600;
  background: var(--bg-2); color: var(--txt-2); }
.drv-av img { width: 100%; height: 100%; object-fit: cover; }
.drv-links { display: grid; gap: 8px; }
.drv-linkrow { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto 32px; align-items: center; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--line-soft); border-radius: 10px; }
.drv-link-ic { color: var(--ink); display: grid; place-items: center; }
.drv-link-main { display: grid; gap: 4px; min-width: 0; }
.drv-link-url { font-size: 12.5px; color: var(--txt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-link-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 12px; }
.drv-link-tags .chip { height: 20px; font-size: 11.5px; gap: 4px; display: inline-flex; align-items: center; }
.drv-newlink { margin-top: 12px; border: 1px dashed var(--line); border-radius: 10px; padding: 10px 12px; }
.drv-newlink summary { cursor: pointer; font-size: 13px; color: var(--ink); }
.drv-newlink-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 12px 0; }
.drv-check-row { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--txt); }
.drv-move-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 13px; margin-bottom: 10px; color: var(--txt-3); }
.drv-move-crumbs button { background: none; border: 0; padding: 2px 4px; color: var(--txt-2); font: inherit; cursor: pointer; border-radius: 4px; }
@media (hover: hover) and (pointer: fine) { .drv-move-crumbs button:hover { background: var(--hover); color: var(--txt); } }
.drv-move-crumbs b { color: var(--txt); font-weight: 500; }
.drv-move-list { display: grid; max-height: 320px; overflow: auto; border: 1px solid var(--line-soft); border-radius: 10px; }
.drv-move-row { display: grid; grid-template-columns: 20px minmax(0, 1fr) 16px; align-items: center; gap: 10px; padding: 10px 12px;
  background: none; border: 0; border-bottom: 1px solid var(--line-soft); color: var(--txt); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer; }
.drv-move-row:last-child { border-bottom: 0; }
@media (hover: hover) and (pointer: fine) { .drv-move-row:hover { background: var(--hover); } }
.drv-move-row:disabled { opacity: .4; cursor: not-allowed; }
.drv-move-row svg:first-child { color: var(--ink); }
.drv-move-empty { padding: 18px; margin: 0; text-align: center; }
.drv-bill-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; margin: 12px 0 0; border-radius: 10px; background: var(--bg-2); font-size: 13px; }
.drv-cycle { margin: 16px 0 12px; }
.drv-plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.drv-plan { display: grid; gap: 4px; justify-items: start; padding: 14px; border-radius: 12px; border: 1px solid var(--line-soft);
  background: var(--bg-1); color: var(--txt); font: inherit; text-align: left; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .drv-plan:hover { border-color: var(--line); } }
.drv-plan.on { border-color: var(--accent); background: var(--tint); }
.drv-plan:disabled { opacity: .45; cursor: not-allowed; }
.drv-plan-gb { font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
.drv-plan-price { font-size: 13.5px; color: var(--ink); }
.drv-plan .dim { font-size: 12px; }

/* xem nhanh — luôn nền tối như khung xem tệp của dự án */
.drv-lb { position: fixed; inset: 0; z-index: 120; display: grid; grid-template-rows: auto minmax(0, 1fr);
  background: #0e0f18; color: #e9e9ed; color-scheme: dark;
  --bg-1: #1c1e2b; --bg-2: #232532; --line: rgba(233, 233, 237, .18); --line-soft: rgba(233, 233, 237, .09);
  --hover: rgba(233, 233, 237, .08); --txt: #e9e9ed; --txt-2: #a9abb9; --txt-3: #858899; --ink: #d2cefd; --accent: #9184d9; }
body.drv-lb-open { overflow: hidden; }
.drv-lb-top { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--line-soft); }
.drv-lb-top .spacer { flex: 1; }
.drv-lb-ic { color: var(--txt-2); display: grid; }
.drv-lb-title { display: grid; min-width: 0; }
.drv-lb-title b { font-weight: 500; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-lb-title .dim { font-size: 12px; }
.drv-lb-stage { position: relative; display: grid; place-items: center; padding: 20px 64px; min-height: 0; overflow: auto; }
.drv-lb-stage > img, .drv-lb-stage > video { max-width: 100%; max-height: calc(100vh - 110px); object-fit: contain; border-radius: 4px; }
.drv-lb-stage > iframe { width: 100%; height: 100%; border: 0; background: #fff; }
/* ảnh: zoom/kéo bằng zoom.js (createLbZoom) — ảnh đặt tuyệt đối giữa khung như .stage img của khung xem dự án,
   zoom.js đổi cỡ thật của thẻ ảnh (không scale) nên ảnh gốc vẫn nét; touch-action:none để chụm 2 ngón không phóng cả trang */
.drv-lb-stage.is-zoomable { overflow: hidden; touch-action: none; }
.drv-lb-stage.is-zoomable > img { position: absolute; inset: 20px 64px; margin: auto; max-width: calc(100% - 128px); max-height: calc(100% - 40px);
  width: auto; height: auto; user-select: none; -webkit-user-drag: none; }
.drv-lb-stage:has(> iframe) { padding: 0; place-items: stretch; }
.drv-lb-note { position: absolute; bottom: 10px; left: 0; right: 0; text-align: center; font-size: 12px; margin: 0; }
.drv-lb-audio, .drv-lb-none { display: grid; justify-items: center; gap: 12px; text-align: center; color: var(--txt-2); max-width: 420px; }
.drv-lb-audio b, .drv-lb-none b { color: var(--txt); font-weight: 500; font-size: 15px; word-break: break-word; }
.drv-lb-audio audio { width: min(420px, 80vw); }
.drv-lb-text { width: min(900px, 100%); max-height: calc(100vh - 130px); overflow: auto; margin: 0; padding: 16px 18px; border-radius: 10px;
  background: var(--bg-1); color: var(--txt); font: 12.5px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; word-break: break-word; }
.drv-lb-nav { position: absolute; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; border-radius: 8px; border: 0;
  background: rgba(233, 233, 237, .08); color: #e9e9ed; display: grid; place-items: center; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .drv-lb-nav:hover { background: rgba(233, 233, 237, .16); } }
.drv-lb-nav.prev { left: 12px; }
.drv-lb-nav.next { right: 12px; }
.drv-lb-nav[hidden] { display: none; }

/* Word / Excel xem ngay trên trình duyệt — public/js/office-view.js */
.drv-lb-stage:has(> .ofv) { padding: 0; place-items: stretch; overflow: hidden; }
.ofv { display: grid; min-height: 0; height: 100%; }
.ofv-load { place-self: center; display: flex; align-items: center; gap: 10px; color: var(--txt-2); font-size: 13px; }
.ofv-spin { width: 16px; height: 16px; border-radius: 5px; --tr-fg: var(--accent); --tr-bg: var(--line); } /* kiểu khung viền chạy, xem khối "Biểu tượng đang tải" */
@keyframes ofvSpin { to { transform: rotate(360deg); } }
.ofv-doc-body { overflow: auto; min-height: 0; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.ofv .docx-wrapper { background: transparent !important; padding: 24px 16px 40px !important; }
.ofv .docx-wrapper > section.docx { box-shadow: 0 4px 24px rgba(0, 0, 0, .45) !important; margin-bottom: 24px !important; color: #000; }
.ofv-sheet { grid-template-rows: minmax(0, 1fr) auto; }
.ofv-grid-wrap { overflow: auto; min-height: 0; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.ofv-grid { border-collapse: separate; border-spacing: 0; font-size: 12.5px; color: var(--txt); table-layout: auto; }
.ofv-grid th, .ofv-grid td { border-right: 1px solid var(--line-soft); border-bottom: 1px solid var(--line-soft); padding: 4px 8px;
  white-space: pre; max-width: 420px; overflow: hidden; text-overflow: ellipsis; vertical-align: top; text-align: left; }
.ofv-grid td { min-width: 56px; }
.ofv-grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
.ofv-grid td.err { color: #ff8a8a; }
.ofv-grid thead th { position: sticky; top: 0; z-index: 2; background: var(--bg-2); color: var(--txt-2); font-weight: 500; text-align: center; font-size: 11.5px; }
.ofv-grid tbody th { position: sticky; left: 0; z-index: 1; background: var(--bg-1); color: var(--txt-3); font-weight: 400; text-align: right; font-size: 11.5px; min-width: 40px; }
.ofv-grid thead th.ofv-corner { left: 0; z-index: 3; }
.ofv-grid .ofv-empty { color: var(--txt-3); padding: 24px; }
.ofv-foot { display: flex; align-items: center; gap: 12px; border-top: 1px solid var(--line-soft); min-width: 0; }
.ofv-tabs { display: flex; overflow-x: auto; min-width: 0; scrollbar-width: none; }
.ofv-tabs[hidden] { display: none; }
.ofv-tabs button { flex: none; border: 0; background: none; color: var(--txt-2); font: inherit; font-size: 12.5px; padding: 9px 14px; cursor: pointer;
  border-top: 2px solid transparent; white-space: nowrap; }
@media (hover: hover) and (pointer: fine) { .ofv-tabs button:hover { color: var(--txt); background: var(--hover); } }
.ofv-tabs button[aria-selected="true"] { color: var(--txt); border-top-color: var(--accent); background: var(--bg-1); }
.ofv-note { margin-left: auto; padding: 0 14px; font-size: 12px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ofv-note:empty { display: none; }

/* thanh bên + tab con Được chia sẻ */
.sh-tabs { margin: 0 0 18px; }
.drv-shared-ic { display: grid; place-items: center; color: var(--ink); background: var(--tint); }

/* chế độ Sáng: lớp phủ kéo thả + badge trên ảnh */
html[data-theme="light"] .drv-drop-hint { background: rgba(255, 255, 255, .7); }

/* điện thoại / tablet */
@media (max-width: 1023px) {
  .drv-bar { gap: 8px; }
  .drv-sortbtn span { display: none; }
  .drv-sortbtn { width: 32px; padding: 0; justify-content: center; }
  #dshSort span { display: inline; }
  #dshSort { width: auto; padding: 0 10px; justify-content: flex-start; }
}
@media (max-width: 640px) {
  .drv-head h1 { font-size: 22px; }
  .drv-head .btn span { display: none; }
  .drv-head .btn { width: 36px; padding: 0; justify-content: center; }
  .drv-quota { margin-top: -10px; }
  .drv-crumbs { order: -1; flex-basis: 100%; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
  .drv-crumbs::-webkit-scrollbar { display: none; }
  .drv-folders { grid-template-columns: 1fr 1fr; gap: 8px; }
  .drv-folder { height: 52px; padding: 0 10px; gap: 8px; }
  .drv-folder-ic { width: 28px; height: 28px; }
  .drv-files.is-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .drv-check { opacity: 0; }
  .drv-selecting .drv-check, .drv-it.picked .drv-check { opacity: 1; }
  .drv-list-head { display: none !important; }
  .drv-row { grid-template-columns: minmax(0, 1fr) auto; }
  .drv-row .drv-check, .drv-row .drv-cell:nth-of-type(2), .drv-row .drv-cell:nth-of-type(3) { display: none; }
  .drv-selecting .drv-row { grid-template-columns: 22px minmax(0, 1fr) auto; }
  .drv-selecting .drv-row .drv-check { display: grid; }
  .drv-selbar { position: fixed; left: 12px; right: 12px; top: auto; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); margin: 0; }
  .drv-selbar .btn span { display: none; }
  .drv-selbar .btn { width: 36px; padding: 0; justify-content: center; }
  .drv-trash-head { flex-direction: column; align-items: stretch; }
  .drv-trash-row { grid-template-columns: 28px minmax(0, 1fr); }
  .drv-trash-acts { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1fr; }
  .drv-invite { grid-template-columns: 1fr 1fr; }
  .drv-invite .input:first-child { grid-column: 1 / -1; }
  .drv-person { grid-template-columns: 32px minmax(0, 1fr) 100px 32px; }
  .drv-newlink-grid { grid-template-columns: 1fr; }
  .drv-plans { grid-template-columns: 1fr; }
  .drv-lb-stage { padding: 12px; }
  .drv-lb-stage.is-zoomable > img { inset: 12px; max-width: calc(100% - 24px); max-height: calc(100% - 24px); }
  .drv-lb-nav { display: none; }
  .drv-lb-top .btn.sm span { display: none; }
}

/* Trang khách link công khai My Drive (/d/:token — public/drive-share.html) */
.dsh-page { background: var(--bg); }
.dsh-top { position: sticky; top: 0; z-index: 20; }
.dsh-top .brand { text-decoration: none; color: inherit; display: flex; align-items: center; gap: 8px; }
.dsh-wrap { max-width: 1240px; margin: 0 auto; padding-top: 28px; }
.dsh-title { display: grid; gap: 4px; min-width: 0; }
.dsh-title h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dsh-kicker { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink); }
.dsh-upnote { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; margin: 0 0 18px; padding: 12px 14px;
  border-radius: 12px; background: var(--tint); color: var(--txt); font-size: 13px; }
.dsh-upnote[hidden] { display: none; }
.dsh-upnote > svg { color: var(--ink); flex: none; }
.dsh-upnote > span { flex: 1; min-width: 220px; }
.dsh-upnote label { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.dsh-upnote .input { height: 32px; width: 220px; }
.dsh-dl { position: absolute; right: 8px; bottom: 8px; width: 30px; height: 30px; border-radius: 8px; border: 0;
  display: grid; place-items: center; background: var(--bg-2); color: var(--txt-2); cursor: pointer; opacity: 0; transition: opacity .12s; }
.drv-tile .dsh-dl { top: 8px; bottom: auto; background: rgba(16, 17, 27, .7); color: #e9e9ed; }
.drv-it:hover .dsh-dl, .dsh-dl:focus-visible { opacity: 1; }
@media (hover: hover) and (pointer: fine) { .dsh-dl:hover { color: var(--txt); } }
.drv-row .dsh-size { position: relative; padding-right: 36px; overflow: visible; }
.drv-row .dsh-dl { right: 0; top: 50%; bottom: auto; transform: translateY(-50%); }
.dsh-foot { text-align: center; font-size: 12px; margin: 40px 0 28px; }
.dsh-fail { text-align: center; }
.dsh-fail h1 { font-size: 20px; font-weight: 500; margin: 0 0 8px; }
.dsh-dock { position: fixed; right: 16px; bottom: 16px; z-index: 130; }
.dsh-dock[hidden] { display: none; }
@media (hover: none) { .dsh-dl { opacity: 1; } }
@media (max-width: 640px) {
  .dsh-wrap { padding-top: 18px; }
  .dsh-upnote .input { width: 100%; }
  .dsh-upnote label { flex-basis: 100%; }
  .dsh-dock { left: 12px; right: 12px; }
}
.dsh-wrap .page-head { align-items: flex-end; }
/* Máy tính có thanh bên (Dự án / Được chia sẻ là 2 mục riêng) → bỏ hàng tab "Dự án của tôi / Được
   chia sẻ" cho khỏi trùng với tab con Dự án / Thư mục Drive. Điện thoại/tablet vẫn dùng hàng tab này. */
@media (min-width: 1024px) { #pjTabs { display: none !important; } }
.drv-back { display: none; }
.drv-view .drv-head .drv-back[hidden] { display: none; }
/* Tiêu đề "My Drive" có icon ổ đĩa phía trước — cùng hình với mục My Drive ở thanh bên */
.drv-title { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.drv-title-ic { display: inline-flex; flex: none; color: var(--txt-2); }
.drv-title-ic svg { display: block; }
#drvTitle { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-crumbs[hidden] { display: none; }
@media (max-width: 1023px) {
  .drv-view .drv-head .drv-back { display: inline-flex; flex: 0 0 100%; justify-content: flex-start; padding-left: 0; background: none; width: auto; }
  @media (hover: hover) and (pointer: fine) { .drv-back:hover { color: var(--txt); } }
}
@media (max-width: 640px) {
  .drv-head .drv-back { order: 0; }
  .drv-head h1 { order: 1; flex: 1 1 auto; }
  .drv-head > .btn:not(.drv-back) { order: 2; }
  .drv-head #drvCount { order: 3; flex-basis: 100%; margin-top: -6px; }
}

/* ---------- My Drive — tinh chỉnh đợt 2 (2026-09-30) ---------- */
/* Hàng công cụ: thanh chọn nhiều thế chỗ đúng hàng này (không đẩy nội dung xuống); máy tính: dính đầu trang */
.drv-toolrow { position: relative; margin: 0 0 16px; }
.drv-toolrow .drv-bar { margin: 0; }
.drv-toolrow .drv-selbar { position: absolute; inset: 0; margin: 0; }
.drv-selecting .drv-toolrow .drv-bar { visibility: hidden; }
@media (min-width: 1024px) {
  .drv-toolrow { position: sticky; top: 0; z-index: 6; padding-block: 8px; margin: -8px 0 8px; background: var(--bg); }
  .drv-toolrow .drv-selbar { inset: 8px 0; }
}
.drv-search { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; width: 220px; max-width: 100%;
  border: 1px solid var(--line-soft); border-radius: 8px; color: var(--txt-3); background: var(--bg-1); }
.drv-search:focus-within { border-color: var(--accent); color: var(--txt-2); }
.drv-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--txt); font: inherit; font-size: 13px; }
.drv-search input::-webkit-search-cancel-button { filter: grayscale(1); opacity: .6; }
.drv-search[hidden] { display: none; }
/* nút ⋯ trên từng mục — hiện khi rê chuột; điện thoại luôn hiện */
.drv-more { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 7px; border: 0; background: none;
  color: var(--txt-2); cursor: pointer; opacity: 0; transition: opacity .12s, background .12s; flex: none; }
@media (hover: hover) and (pointer: fine) { .drv-more:hover { background: var(--hover); color: var(--txt); } }
.drv-it:hover .drv-more, .drv-it:focus-within .drv-more, .drv-it.ctx-on .drv-more { opacity: 1; }
@media (hover: none) { .drv-more { opacity: 1; } }
.drv-tile > .drv-more { position: absolute; right: 6px; bottom: 8px; }
.drv-tile .drv-meta { padding-right: 36px; }
.drv-tile > .drv-badge { right: 8px; }
.drv-folder { padding-right: 6px; }
.drv-folder-main { display: grid; min-width: 0; flex: 1; gap: 1px; }
.drv-folder .drv-sub { font-size: 11.5px; }
.drv-folder .drv-more { margin-left: 2px; }
.drv-row-ic.is-folder { background: var(--tint); color: var(--ink); }
/* tệp không phải ảnh: nền nhạt theo màu loại tệp thay cho ô xám trống */
.drv-tile.k-pdf .drv-thumb { background: color-mix(in srgb, #e8959a 12%, var(--bg-2)); }
.drv-tile.k-video .drv-thumb { background: color-mix(in srgb, #a79be6 14%, var(--bg-2)); }
.drv-tile.k-audio .drv-thumb, .drv-tile.k-sheet .drv-thumb { background: color-mix(in srgb, #7fcfa0 12%, var(--bg-2)); }
.drv-tile.k-zip .drv-thumb { background: color-mix(in srgb, #e6c35c 12%, var(--bg-2)); }
.drv-tile.k-design .drv-thumb { background: color-mix(in srgb, #8fb8e8 13%, var(--bg-2)); }
@media (max-width: 1023px) {
  .drv-search { width: 100%; order: 5; flex-basis: 100%; }
}
@media (max-width: 640px) {
  .drv-toolrow .drv-selbar { position: fixed; inset: auto 12px calc(12px + env(safe-area-inset-bottom, 0px)) 12px; }
  .drv-selecting .drv-toolrow .drv-bar { visibility: visible; }
  /* con của .drv-row: check, tên, người tải (span 3), ngày (span 4), dung lượng, ⋯ — điện thoại chỉ giữ tên | dung lượng | ⋯ */
  .drv-row { grid-template-columns: minmax(0, 1fr) auto 28px; }
  .drv-row .drv-cell:nth-of-type(4) { display: none; }
  .drv-selecting .drv-row { grid-template-columns: 22px minmax(0, 1fr) auto 28px; }
  /* trang khách (/d/:token): dòng không có ô chọn/⋯ mà có <span> trống đầu dòng — bỏ đi, chỉ còn tên | dung lượng+nút tải */
  .dsh-page .drv-row { grid-template-columns: minmax(0, 1fr) auto; }
  .dsh-page .drv-row > span:first-child { display: none; }
}
/* My Drive — dung lượng dạng viên nhỏ cạnh số mục (2026-09-30), thay cho thanh dài dưới tiêu đề */
/* Phương án B "Pin chia vạch" (2026-10-11): 10 vạch như mức pin + "đã dùng / tổng" */
.drv-qpill { align-self: center; display: inline-flex; align-items: center; gap: 9px; height: 28px; padding: 0 10px;
  border: 1px solid var(--line-soft); border-radius: 8px; background: none; color: var(--txt-2);
  font: inherit; font-size: 12px; font-variant-numeric: tabular-nums; cursor: pointer; transition: border-color .15s, background .15s; }
@media (hover: hover) and (pointer: fine) { .drv-qpill:hover { border-color: var(--line); background: var(--hover, rgba(255, 255, 255, .03)); } }
.drv-qseg { display: inline-grid; grid-template-columns: repeat(10, 4px); gap: 2px; flex: none; }
.drv-qseg i { height: 11px; border-radius: 1.5px; background: color-mix(in srgb, var(--txt-3) 28%, transparent); transition: background .2s ease; }
.drv-qseg i.on { background: var(--accent); }
.drv-qtxt b { color: var(--txt); font-weight: 600; }
.drv-qpill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.drv-qbuy { color: var(--ink); font-weight: 600; padding-left: 9px; border-left: 1px solid var(--line-soft); }
.drv-qbuy[hidden] { display: none; }
.drv-qpill.warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); color: var(--txt-2); }
.drv-qpill.warn .drv-qseg i.on { background: var(--warn); }
@media (prefers-reduced-motion: reduce) { .drv-qseg i { transition: none; } }
@media (max-width: 640px) {
  /* hàng 1: tiêu đề + nút; hàng 2: số mục (trái) + dung lượng (phải) */
  .drv-head h1 { flex: 1 1 calc(100% - 130px); min-width: 0; }
  .drv-head #drvCount { flex: 0 1 auto; margin-top: 0; }
  .drv-head .drv-qpill { order: 3; margin-left: auto; }
  /* thư mục: 1 cột như danh sách để tên không bị cắt còn vài chữ */
  .drv-folders { grid-template-columns: 1fr; gap: 6px; }
}
/* My Drive — kéo thả vào thư mục (tải tệp từ máy vào, hoặc chuyển mục đang có) */
.drv-it.drop-over, .drv-crumb.drop-over { border-color: var(--accent) !important; background: var(--tint) !important;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.drv-crumb.drop-over { color: var(--ink); }
.drv-it.dragging { opacity: .45; }
/* đang ở trên 1 thư mục: bỏ lớp phủ "thả để tải lên" toàn trang, chỉ tô sáng thư mục đích */
.drv-drop-folder .drv-drop-hint { display: none !important; }
.drv-it[draggable="true"] { -webkit-user-drag: element; }
.drv-drag-ghost { position: fixed; top: -100px; left: -100px; padding: 6px 12px; border-radius: 8px;
  background: var(--accent); color: var(--on-accent); font: 500 13px var(--font); }
/* Thanh bên kiểu A (2026-09-30): đường kẻ mảnh tách nhóm dự án với nhóm My Drive / Được chia sẻ */
.sf-nav-sep { display: block; height: 1px; margin: 8px 10px; background: var(--line-soft); }
/* My Drive — thẻ màu kiểu Finder (2026-09-30): thư mục đổi màu theo thẻ, tệp có chấm màu, lọc theo thẻ */
.drv-folder.tagged .drv-folder-ic, .drv-row.tagged .drv-row-ic.is-folder {
  background: color-mix(in srgb, var(--tag) 20%, transparent); color: var(--tag); }
.drv-folder.tagged { border-color: color-mix(in srgb, var(--tag) 28%, var(--line-soft)); }
@media (hover: hover) and (pointer: fine) { .drv-folder.tagged:hover { border-color: color-mix(in srgb, var(--tag) 55%, var(--line-soft)); } }
.drv-tagdot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 2px; background: var(--tag);
  margin-right: 6px; vertical-align: 1px; }
.sf-nav .sf-path-item.tagged svg { color: var(--tag); opacity: 1; }
/* hàng chọn màu trong menu chuột phải */
.ctx-tags { display: flex; align-items: center; gap: 8px; padding: 10px 10px 8px; margin-top: 4px; border-top: 1px solid var(--line-soft); }
.ctx-tag { width: 18px; height: 18px; padding: 0; border-radius: 6px; border: 0; background: var(--tag); cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18); transition: transform .12s; }
@media (hover: hover) and (pointer: fine) { .ctx-tag:hover { transform: scale(1.18); } }
.ctx-tag.on { box-shadow: 0 0 0 2px var(--bg-1), 0 0 0 3.5px var(--tag); }
.ctx-tag:focus-visible, .ctx-tag-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctx-tag-clear { width: 20px; height: 20px; margin-left: 2px; padding: 0; display: grid; place-items: center; border-radius: 6px;
  border: 1px solid var(--line); background: none; color: var(--txt-3); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .ctx-tag-clear:hover { color: var(--txt); border-color: var(--txt-3); } }
.ctx-tag-clear svg { width: 12px; height: 12px; }
@media (prefers-reduced-motion: reduce) { .ctx-tag { transition: none; } }
/* nút lọc theo thẻ trên thanh công cụ */
.drv-tagbtn { color: var(--txt-2); gap: 7px; }
.drv-tagbtn.on { color: var(--txt); background: var(--hover); }
.drv-tagdots { display: inline-flex; }
.drv-tagdots i { width: 9px; height: 9px; border-radius: 3px; background: var(--tag); box-shadow: 0 0 0 1.5px var(--bg); }
.drv-tagdots i + i { margin-left: -3px; }
.drv-tagbtn .drv-tagdot { margin-right: 0; }
@media (max-width: 1023px) { .drv-tagbtn span:not(.drv-tagdots) { display: none; } }
/* thư mục có thẻ: tô cả thân biểu tượng như Finder macOS, không chỉ viền */
.drv-folder.tagged .drv-folder-ic svg, .drv-row.tagged .drv-row-ic.is-folder svg, .sf-nav .sf-path-item.tagged svg {
  fill: color-mix(in srgb, var(--tag) 55%, transparent); }
.drv-folder.tagged .drv-folder-ic { background: color-mix(in srgb, var(--tag) 14%, transparent); }
/* vùng Drive phủ kín màn hình để chuột phải được ở mọi chỗ trống */
.drv-view { min-height: calc(100vh - 120px); }
/* ô thư mục My Drive to hơn một chút (2026-09-30) */
.drv-folders { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.drv-folder { height: 66px; padding: 0 10px 0 13px; gap: 12px; border-radius: 12px; }
.drv-folder-ic { width: 40px; height: 40px; border-radius: 10px; }
.drv-folder .drv-name { font-size: 14.5px; }
.drv-folder .drv-sub { font-size: 12px; }
@media (max-width: 640px) {
  .drv-folder { height: 60px; }
  .drv-folder-ic { width: 36px; height: 36px; }
}
/* Thẻ màu: CHỈ tô biểu tượng thư mục — viền ô và ô vuông bo quanh biểu tượng giữ màu mặc định (2026-09-30) */
.drv-folder.tagged, .drv-folder.tagged:hover { border-color: var(--line-soft); }
@media (hover: hover) and (pointer: fine) { .drv-folder.tagged:hover { border-color: var(--line); } }
.drv-folder.tagged .drv-folder-ic { background: var(--tint); }
.drv-row.tagged .drv-row-ic.is-folder { background: var(--tint); }
.drv-folder.tagged .drv-folder-ic svg, .drv-row.tagged .drv-row-ic.is-folder svg { color: var(--tag); }
/* ==========================================================================
   My Drive — rà lại giao diện điện thoại (2026-09-30)
   ========================================================================== */
.drv-head-break { display: none; }
.drv-row-main { display: grid; min-width: 0; flex: 1; }
.drv-row-sub { display: none; font-size: 11.5px; color: var(--txt-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsh-actions { display: flex; gap: 8px; }
@media (max-width: 640px) {
  /* đầu trang: hàng 1 tiêu đề + nút (có hay không có nút "Mới" cũng vậy), hàng 2 số mục + dung lượng */
  .drv-head h1 { flex: 1 1 auto; }
  .drv-head .drv-head-break { display: block; order: 2; flex-basis: 100%; height: 0; }
  /* hàng công cụ: ô tìm lên trên cùng, rồi Tệp/Thùng rác bên trái — thẻ · sắp xếp · kiểu xem bên phải */
  .drv-bar .drv-search { order: -1; }
  .drv-bar #drvTabs { order: 0; }
  .drv-bar > .spacer { display: block; order: 1; flex: 1; }
  .drv-bar .drv-tagbtn, .drv-bar .drv-sortbtn, .drv-bar .drv-viewseg { order: 2; }
  /* ô tích của thư mục: khi đang chọn thì thế chỗ nút ⋯ bên phải (tròn kiểu iOS) — trước đây lệch
     ra ngoài mép màn hình, rồi chồng lên góc biểu tượng thư mục */
  .drv-folder .drv-check { left: auto; right: 14px; top: 50%; transform: translateY(-50%); width: 24px; height: 24px; border-radius: 6px; }
  .drv-selecting .drv-folder .drv-more { visibility: hidden; }
  /* thanh "Đã chọn" dán đáy không che hàng cuối */
  .drv-selecting .drv-body { padding-bottom: 88px; }
  /* chấm màu trong menu đủ to để chạm */
  .ctx-tags { gap: 14px; padding: 14px 12px 10px; }
  .ctx-tag { width: 28px; height: 28px; }
  .ctx-tag-clear { width: 28px; height: 28px; }
  /* danh sách: dưới tên ghi vị trí (khi tìm) hoặc ngày sửa */
  .drv-row { min-height: 56px; }
  .drv-row-sub { display: block; }
  /* link công khai trong hộp chia sẻ: địa chỉ + nhãn chiếm cả hàng, nút Sao chép xuống dưới */
  .drv-linkrow { grid-template-columns: 24px minmax(0, 1fr) 32px; row-gap: 8px; align-items: start; }
  .drv-linkrow .drv-link-ic { grid-row: 1 / 3; padding-top: 2px; }
  .drv-linkrow .drv-link-main { grid-column: 2; grid-row: 1; }
  .drv-linkrow [data-copy] { grid-column: 2; grid-row: 2; justify-self: start; border-color: var(--line); color: var(--txt); }
  .drv-linkrow [data-revoke] { grid-column: 3; grid-row: 1; }
  .drv-link-url { white-space: normal; word-break: break-all; }
  /* trang khách: 2 nút hành động thành 1 hàng riêng dưới tiêu đề, có chữ */
  .dsh-wrap .page-head { align-items: flex-start; }
  .dsh-wrap .page-head .dsh-title { flex: 1 1 100%; }
  .dsh-wrap .page-head #dCount { order: 1; }
  .dsh-actions { order: 2; flex: 1 1 100%; }
  .dsh-actions .btn { flex: 1; justify-content: center; width: auto !important; padding: 0 12px !important; }
  .dsh-actions .btn span { display: inline !important; }
  .dsh-actions .btn.ghost { border-color: var(--line); color: var(--txt); }
  .dsh-upnote label { flex-direction: column; align-items: stretch; gap: 6px; }
  /* thùng rác: nút có viền cho rõ là nút; đường dẫn trùng với tiêu đề + tab nên bỏ */
  .drv-trash-acts .btn { border-color: var(--line); }
  .drv-trash-acts .btn.danger { border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
  #viewDrive:has(.drv-trash:not([hidden])) .drv-crumbs { display: none; }
}
/* Đường dẫn thư mục trong dự án hiện cả trên MÁY TÍNH (2026-09-30) — cùng kiểu với điện thoại/iPad:
   nút ‹ lên cấp cha + "Tất cả tệp › … › thư mục đang mở", nằm hàng riêng trên thanh công cụ.
   Ở gốc dự án (chỉ có "Tất cả tệp") vẫn ẩn vì thừa. Thanh bên vẫn giữ cây thư mục như cũ. */
@media (min-width: 1024px) {
  /* đường dẫn ở hàng 1, thanh công cụ xuống hàng 2 (giống iPad). KHÔNG ghim cứng grid-row: 2 —
     ở gốc dự án đường dẫn ẩn, hàng 1 trống thì lưới tệp tự xếp lên đó và thanh công cụ rớt xuống dưới.
     Để auto: đường dẫn hiện → thanh công cụ tự sang hàng 2; ẩn → thanh công cụ ở hàng 1. */
  #tabPhotos > .fbar { grid-row: auto; }
  #tabPhotos > #pathCrumbs { display: flex; grid-column: 1 / -1; grid-row: 1; align-items: center; gap: 8px;
    margin: 0 0 14px; font-size: 14px; white-space: nowrap; }
  #tabPhotos > #pathCrumbs.at-root, #tabPhotos > #pathCrumbs[hidden] { display: none; }
  #pathCrumbs .cr-up { flex: none; width: 34px; height: 34px; display: grid; place-items: center; padding: 0;
    border: 1px solid var(--line-soft); border-radius: 9px; background: var(--bg-1); color: var(--txt-2); cursor: pointer; }
  @media (hover: hover) and (pointer: fine) { #pathCrumbs .cr-up:hover { background: var(--hover); color: var(--txt); } }
  #pathCrumbs .cr-trail { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; overflow-x: auto; scrollbar-width: none; }
  #pathCrumbs .cr-trail::-webkit-scrollbar { display: none; }
  #pathCrumbs .cr { flex: none; padding: 6px 2px; color: var(--txt-2); border-radius: 5px; }
  @media (hover: hover) and (pointer: fine) { #pathCrumbs .cr:not(.cur):hover { color: var(--txt); } }
  #pathCrumbs .cr.cur { color: var(--txt); font-weight: 500; }
  #pathCrumbs .sep { flex: none; color: var(--txt-3); font-size: 16px; line-height: 1; }
}


/* ---------- Ô soạn nhận xét kiểu Frame.io (2026-10-01) ----------
   Đo trực tiếp từ Frame.io: dòng 1 = chip mốc thời gian vàng + ô nhập; dòng 2 = 4 icon 24px cách
   nhau 12px (đồng hồ bật/tắt mốc → đính kèm → emoji → vẽ, thêm ghim vị trí), bên phải là nút
   "Công khai ▾" + nút gửi vuông 32px (mờ khi chưa gõ gì). Chỉ áp cho ô soạn trình xem đơn
   (#cmtFoot khách, #aCmtFoot studio); đặt cuối file để thắng các luật cũ phía trên. */
#cmtFoot.comment-composer, #aCmtFoot.comment-composer { padding: 11px 12px 12px; border-top: 1px solid var(--line-soft); }
/* Chip mốc nằm CHUNG dòng với chữ như Frame.io: chip đặt tuyệt đối ở góc trên-trái ô nhập, dòng
   đầu của textarea thụt vào đúng bề rộng chip (text-indent do JS đo, xem syncTcIndent), các dòng
   sau chạy tràn hết bề ngang bên dưới chip — không bị ép thành cột hẹp cạnh chip. */
#cmtFoot .compose-input, #aCmtFoot .compose-input { display: block; position: relative; }
#cmtFoot textarea.input, #aCmtFoot textarea.input {
  min-height: 24px; max-height: 220px; padding: 2px 0; font-size: 13.5px; line-height: 20px;
}
/* chip mốc: vàng nhạt, không icon đồng hồ (đã có nút đồng hồ ở hàng dưới); tắt mốc thì ẩn */
#cmtFoot .tcbtn, #aCmtFoot .tcbtn {
  position: absolute; z-index: 1; left: 0; top: 2px;
  height: 20px; margin: 0; padding: 0 6px; gap: 4px; border-radius: 6px;
  background: rgba(255, 197, 0, .15); color: rgba(255, 197, 0, .85);
  font-family: inherit; font-size: 12.5px; font-weight: 400; line-height: 20px; font-variant-numeric: tabular-nums;
}
#cmtFoot .tcbtn.on, #aCmtFoot .tcbtn.on { background: rgba(255, 197, 0, .15); color: rgba(255, 197, 0, .85); }
#cmtFoot .tcbtn > svg, #aCmtFoot .tcbtn > svg { display: none; }
#cmtFoot .tcbtn > svg.tc-caret, #aCmtFoot .tcbtn > svg.tc-caret { display: inline-block; vertical-align: 1px; }
#cmtFoot .tcbtn.off, #aCmtFoot .tcbtn.off { display: none; }
#cmtFoot .tcbtn .tc-x, #aCmtFoot .tcbtn .tc-x { margin-left: 2px; }
/* hàng công cụ: icon 24px trơn, cách 12px, thứ tự như Frame.io */
#drawBar, #aDrawBar { gap: 8px; margin-top: 10px; align-items: center; align-self: center; }
#drawBar > .pen, #drawBar > .btn, #aDrawBar > .pen, #aDrawBar > .btn {
  width: 24px; height: 24px; min-width: 24px; padding: 0; border-radius: 6px;
  background: transparent; color: rgba(245, 245, 245, .9);
}
#drawBar > .pen svg, #drawBar > .btn svg, #aDrawBar > .pen svg, #aDrawBar > .btn svg { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) { #drawBar > .pen:hover, #drawBar > .btn:hover, #aDrawBar > .pen:hover, #aDrawBar > .btn:hover { background: var(--bg-3); color: #fff; } }
#tcToggle, #aTcToggle { order: -2; color: var(--txt-3) !important; }
/* Vẽ là công cụ ưu tiên: đứng ĐẦU hàng, kèm chữ "Vẽ", chữ sáng hơn các icon khác — nhưng KHÔNG
   nền/viền nổi bật khi chưa bấm (chỉ tô tím lúc đang vẽ, xem .pen.on). */
#penBtn, #aPenBtn {
  order: -3; width: auto !important; padding: 0 8px 0 5px !important; gap: 5px;
  display: inline-flex !important; align-items: center; color: #fff !important; font-size: 13px; font-weight: 600;
}
#penBtn .pen-label, #aPenBtn .pen-label { display: inline; }
#tcToggle.on, #aTcToggle.on { color: #5b53ff !important; }
#attachBtn, #aAttachBtn { order: 1; }
#emojiBtn, #aEmojiBtn { order: 2; }
#drawBar > .pen.on, #aDrawBar > .pen.on { background: var(--accent); color: #fff; }
/* Đang vẽ: hàng này nhường chỗ cho bộ công cụ vẽ — ẩn nút đồng hồ, khoảng cách hẹp lại */
.comment-composer .drawbar.drawing > .tc-toggle { display: none; }
#drawBar.drawing, #aDrawBar.drawing { gap: 4px; }
/* Đang trả lời: không gắn mốc thời gian (như Frame.io) → ẩn chip mốc + nút đồng hồ */
.comment-composer.is-reply .tcbtn, .comment-composer.is-reply .tc-toggle { display: none !important; }
/* không phải video/nhạc (chip mốc ẩn) thì ẩn luôn nút đồng hồ */
.comment-composer:has(.tcbtn[hidden]) .tc-toggle { display: none; }
/* cụm phải: "Công khai ▾" có chữ + nút gửi vuông */
#cmtFoot .compose-actions, #aCmtFoot .compose-actions { margin-top: 10px; gap: 8px; align-self: center; }
#cmtFoot .compose-actions > .spacer, #aCmtFoot .compose-actions > .spacer { display: none; }
#cmtFoot .vis-pick > .btn, #aCmtFoot .vis-pick > .btn {
  width: auto; height: 32px; padding: 4px 8px; gap: 5px; border-radius: 6px;
  background: rgba(85, 88, 110, .4); color: #fff; font-size: 13px; font-weight: 500;
}
#cmtFoot .vis-pick > .btn > span, #aCmtFoot .vis-pick > .btn > span { display: inline; }
#cmtFoot .vis-pick > .btn::after, #aCmtFoot .vis-pick > .btn::after {
  content: ''; width: 5px; height: 5px; margin: -3px 1px 0 1px; border: solid currentColor;
  border-width: 0 1.6px 1.6px 0; transform: rotate(45deg);
}
#cmtFoot .vis-pick > .btn.is-internal, #aCmtFoot .vis-pick > .btn.is-internal { background: rgba(255, 212, 138, .16); color: var(--warn); }
#cmtSend.compose-send, #aCmtSend.compose-send {
  width: 32px; height: 32px; padding: 0; justify-content: center; border-radius: 6px;
  background: #5b53ff; color: #fff;
}
#cmtSend.compose-send > span, #aCmtSend.compose-send > span { display: none; }
#cmtSend.compose-send svg, #aCmtSend.compose-send svg { width: 17px; height: 17px; }
/* chưa gõ gì: nút gửi mờ như Frame.io (vẫn bấm được — gửi nét vẽ/tệp không cần chữ) */
#cmtFoot:has(textarea.input:placeholder-shown) #cmtSend, #aCmtFoot:has(textarea.input:placeholder-shown) #aCmtSend {
  background: rgba(91, 83, 255, .25); color: rgba(255, 255, 255, .4);
}
/* điện thoại: giữ vùng chạm đủ lớn */
@media (max-width: 640px) {
  #drawBar > .pen, #drawBar > .btn, #aDrawBar > .pen, #aDrawBar > .btn { width: 34px; height: 34px; min-width: 34px; }
  #drawBar, #aDrawBar { gap: 4px; margin-top: 8px; }
  #cmtSend.compose-send, #aCmtSend.compose-send { width: 36px; height: 36px; padding: 0; }
  #cmtFoot .vis-pick > .btn, #aCmtFoot .vis-pick > .btn { height: 36px; }
  /* màn hẹp: chỉ còn quả địa cầu + mũi tên, giữ hàng công cụ 1 dòng */
  #cmtFoot .vis-pick > .btn > span, #aCmtFoot .vis-pick > .btn > span { display: none; }
}
html[data-theme="light"] #drawBar > .pen, html[data-theme="light"] #drawBar > .btn,
html[data-theme="light"] #aDrawBar > .pen, html[data-theme="light"] #aDrawBar > .btn { color: var(--txt-2); }
html[data-theme="light"] #cmtFoot .vis-pick > .btn, html[data-theme="light"] #aCmtFoot .vis-pick > .btn { color: var(--txt); background: var(--bg-3); }
html[data-theme="light"] #cmtFoot .tcbtn, html[data-theme="light"] #aCmtFoot .tcbtn { color: #8a6a00; background: rgba(255, 197, 0, .22); }

/* ---------- Tạo không gian làm việc (tài khoản chưa có workspace, 2026-10-01) ---------- */
body.no-ws #viewProjects > :not(#wsOnboard) { display: none !important; }
.ws-onboard { display: flex; justify-content: center; padding: 48px 16px 64px; }
.wso-card { width: 100%; max-width: 460px; }
.wso-steps { display: flex; align-items: center; gap: 8px; margin-bottom: 18px; }
.wso-steps span { width: 22px; height: 22px; border-radius: 6px; display: grid; place-items: center;
  font-size: 11px; font-weight: 600; border: 1px solid var(--line); color: var(--txt-3); }
.wso-steps span.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.wso-steps i { width: 28px; height: 1px; background: var(--line); }
.wso-title { font-size: 22px; font-weight: 600; margin: 0 0 8px; letter-spacing: -.01em; }
.wso-lead { color: var(--txt-2); font-size: 14px; line-height: 1.55; margin: 0 0 22px; }
.wso-lead b { color: var(--txt); font-weight: 600; }
.wso-preview { display: flex; align-items: center; gap: 12px; padding: 12px; margin-bottom: 16px;
  border: 1px solid var(--line-soft); border-radius: 12px; background: var(--bg-1); }
.wso-badge { width: 40px; height: 40px; flex: none; border-radius: 9px; display: grid; place-items: center;
  background: var(--tint, rgba(91, 83, 255, .15)); color: var(--ink, var(--accent)); font-weight: 700; font-size: 14px; }
.wso-pv-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wso-pv-text b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wso-pv-text b:empty::before { content: 'Tên không gian làm việc'; color: var(--txt-3); font-weight: 500; }
.wso-pv-text small { color: var(--txt-3); font-size: 12px; }
.wso-form .field { margin-bottom: 6px; }
.wso-submit { width: 100%; justify-content: center; margin-top: 10px; height: 40px; }
.wso-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.wso-note { margin: 26px 0 0; padding-top: 16px; border-top: 1px solid var(--line-soft); color: var(--txt-3); font-size: 13px; line-height: 1.5; }
.wso-note a { color: var(--ink, var(--accent)); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .wso-note a:hover { text-decoration: underline; } }
.sf-ws.is-create .sf-ws-av { background: transparent; border: 1px dashed var(--line); color: var(--txt-2); }
.sf-ws.is-create .sf-caret { display: none; }

/* Icon của nhãn thay tên workspace trên thanh trên (Được chia sẻ / My Drive / Tạo workspace) */
.crumb .cr-ws-ic { display: inline-grid; place-items: center; color: var(--ink, var(--accent)); }

/* Tiêu đề nhóm nhỏ trong menu (vd "Không gian làm việc", "Ít dùng") — xem 'sec:' trong buildCtx() */
.ctx-sec { padding: 6px 12px 4px; font-size: 11.5px; font-weight: 500; color: var(--txt-3); letter-spacing: .01em; }
.ctx-sec + .ctx-ws-summary { margin-top: 2px; }

/* Menu workspace điện thoại/iPad — phương án D (buildWsNavMenu trong admin.js) */
.ctx-area { display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px; padding: 3px; margin: 4px 4px 6px;
  border-radius: 10px; background: var(--bg-2); }
.ctx-area.two { grid-template-columns: repeat(2, 1fr); }
.ctxmenu:has(> .ctx-area) { min-width: 300px; }
.ctx-area button { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px; padding: 0 6px;
  border: 0; border-radius: 8px; background: none; color: var(--txt-2); font: inherit; font-size: 13px; cursor: pointer; white-space: nowrap; }
.ctx-area button svg { flex: none; }
@media (hover: hover) and (pointer: fine) { .ctx-area button:hover { color: var(--txt); } }
.ctx-area button.on { background: var(--bg-1); color: var(--txt); box-shadow: 0 1px 2px rgba(0, 0, 0, .25); }
.ctx-area button.on svg { color: var(--ink, var(--accent)); }
.ctx-item.ctx-wsrow { align-items: center; padding-top: 7px; padding-bottom: 7px; height: auto; }
.ctx-wsrow.on { background: var(--tint, rgba(145, 132, 217, .14)); }
.ctx-ws-av { width: 28px; height: 28px; flex: none; display: grid; place-items: center; overflow: hidden; border-radius: 7px;
  background: #2b2741; color: #d2cefd; font-size: 11px; font-weight: 600; }
.ctx-ws-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ctx-wsrow .ci-lb { display: grid; gap: 1px; min-width: 0; }
.ctx-ws-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-ws-sub { font-size: 11.5px; color: var(--txt-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-ws-bar { display: block; height: 3px; margin-top: 4px; border-radius: 6px; background: var(--bg-3, var(--line-soft)); overflow: hidden; }
.ctx-ws-bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); }
.ctx-ws-go { flex: none; display: grid; place-items: center; color: var(--txt-3); }
html[data-theme="light"] .ctx-ws-av { background: #e6e3fb; color: #4b3f9e; }
html[data-theme="light"] .ctx-area button.on { box-shadow: 0 1px 2px rgba(28, 29, 41, .12); }


/* ==========================================================================
   Tách khối đầu trang khỏi nội dung (phương án "thanh nền nổi", 2026-10-10)
   Khối đầu = nền nổi hơn trang một nấc + đường kẻ dưới. Danh sách dự án: bọc tiêu đề + thanh công cụ
   trong .head-band (tràn mép như .wrap). Trong dự án (máy tính): .pj-hero và hàng thanh công cụ
   lưới tệp cùng nền nổi. Tối: --bg-1; Sáng: --bg-2 (vì nền trang đã trắng).
   ========================================================================== */
:root { --head-band: var(--bg-1); }
html[data-theme="light"] { --head-band: var(--bg-2); }
#viewProjects .head-band {
  background: var(--head-band); border-bottom: 1px solid var(--line);
  margin: -22px -18px 18px; padding: 22px 18px 2px;
}
#viewProjects .head-band .page-head { margin-bottom: 14px; }
#viewProjects .head-band .fbar { margin: 14px 0 16px; }
#viewProjects .head-band .input { background-color: var(--bg); }
@media (max-width: 640px) {
  #viewProjects .head-band { margin: -16px -12px 14px; padding: 16px 12px 2px; }
  /* hàng ô tìm thu gọn (.search-collapse) vẫn chiếm một khe gap ~10px dưới các nút */
  #viewProjects .head-band .fbar { margin-bottom: 6px; }
}
@media (min-width: 1024px) {
  #viewProjects .head-band { margin: -28px -32px 22px; padding: 28px 32px 2px; }
  #viewProject .pj-hero { background-color: var(--head-band); border-bottom: 1px solid var(--line); }
  #viewProject .pj-hero > .tabs { border-bottom: 0; }
}

/* Số đếm cạnh nhãn tab ("Chia sẻ 3", "Phản hồi 3"…): chữ số 12.5px được căn GIỮA hộp nên baseline cao hơn nhãn 14px
   khoảng 0.9px (nhìn như lệch lên) — hạ xuống cho cùng baseline. */
.tab .dim { position: relative; top: .9px; }

/* ==========================================================================
   Khung xem của TRANG KHÁCH (#lb) và TRANG QUẢN TRỊ (#alb) theo giao diện chung Sáng/Tối (2026-10-10)
   Trước đây `html[data-theme="light"] .lb` ở trên ép mọi khung xem luôn tối. Trang Live đã tự trả lại bảng màu sáng cho #lb
   (live.css); trang khách (#lb) và trang quản trị (#alb) giờ cũng theo giao diện chung. Cùng giá trị với khối trong live.css.
   ========================================================================== */
html[data-theme="light"] #lb, html[data-theme="light"] #alb {
  color-scheme: light; color: #202124; background: #ffffff;
  --bg: #ffffff; --bg-1: #ffffff; --bg-2: #f1f3f4; --bg-3: #e8eaed;
  --line: rgba(32, 33, 36, .16); --line-soft: rgba(32, 33, 36, .08); --hover: rgba(32, 33, 36, .06);
  --txt: #202124; --txt-1: #202124; --txt-2: #3c4043; --txt-3: #5f6368;
  --accent: #5546b8; --accent-hi: #43379b; --ink: #43379b; --tint: rgba(85, 70, 184, .12); --on-accent: #ffffff;
  --ok: #137333; --warn: #a35200; --danger: #c5221f; --star-empty: rgba(32, 33, 36, .42);
  --shadow: 0 0 0 1px rgba(32, 33, 36, .12), 0 16px 40px rgba(32, 33, 36, .16);
}
html[data-theme="light"] #lb .lb-head, html[data-theme="light"] #alb .lb-head { background: #ffffff; }
html[data-theme="light"] #lb .lb-body, html[data-theme="light"] #lb .stage,
html[data-theme="light"] #alb .lb-body, html[data-theme="light"] #alb .stage { background: #ffffff; }
html[data-theme="light"] #lb .input, html[data-theme="light"] #alb .input { background: #fff; }
html[data-theme="light"] #lb .edge-nav, html[data-theme="light"] #alb .edge-nav { background: rgba(32, 33, 36, .35); color: #fff; }
/* Thanh zoom nền tối mờ + chữ lấy từ biến → chữ tối trên nền tối không đọc được; đổi sang thanh sáng. Vạch tua video/tốc độ
   vẽ bằng trắng 20% (chỉ thấy trên nền tối) → đổi sang xám tối. */
html[data-theme="light"] #lb .zoombar, html[data-theme="light"] #alb .zoombar {
  background: rgba(255, 255, 255, .94); box-shadow: 0 1px 6px rgba(32, 33, 36, .22);
}
html[data-theme="light"] #lb .vs-track, html[data-theme="light"] #lb .vsp-track,
html[data-theme="light"] #alb .vs-track, html[data-theme="light"] #alb .vsp-track { background: rgba(32, 33, 36, .2); }
@media (max-width: 640px) {
  html[data-theme="light"] #lb.panel-on .panel, html[data-theme="light"] #alb.panel-on .panel { box-shadow: 0 -8px 28px rgba(32, 33, 36, .14) !important; }
}

/* Thanh cuộn chế độ Sáng: thumb cố định #33364a (bảng màu tối) nhìn như một vệt đen đậm trên nền trắng — dùng xám nhạt hơn. */
html[data-theme="light"] ::-webkit-scrollbar-thumb { background: rgba(32, 33, 36, .28); }
@media (hover: hover) and (pointer: fine) { html[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: rgba(32, 33, 36, .42); } }

/* Nút "Vẽ" ở ô nhận xét bị ép chữ TRẮNG bằng !important (thiết kế tối) → trắng trên nền sáng thì không thấy nút trong khung xem
   Sáng (admin #aPenBtn, khách/Live #penBtn). Đang vẽ (.on, nền tím) vẫn giữ chữ trắng. */
html[data-theme="light"] #penBtn:not(.on), html[data-theme="light"] #aPenBtn:not(.on) { color: var(--txt) !important; }

/* ==========================================================================
   Đầu trang dự án — phương án A "gọn một khối" (2026-10-10)
   Bỏ nền mờ lấy từ ảnh bìa + nhãn "DỰ ÁN" + chip số tệp. Dải nền phẳng --head-band (giống danh sách
   dự án), ảnh bìa vuông bo 8px, tên + dòng phụ .pj-meta (số tệp · dung lượng · ngày tạo).
   Đường dẫn thư mục ("cách 1"): hàng #pathCrumbs ngay trên lưới tệp ở MỌI cỡ màn hình — cấp đang mở
   có icon thư mục + chữ đậm; hơn 3 cấp thì các cấp giữa gộp vào nút .cr-more "…" (renderCrumbs).
   ========================================================================== */
.pj-meta {
  display: flex; align-items: center; flex-wrap: wrap; column-gap: 8px;
  font-size: 13px; line-height: 1.4; color: var(--txt-2); font-variant-numeric: tabular-nums;
}
.pj-meta > span:empty { display: none; }
.pj-meta > span + span::before {
  content: ''; display: inline-block; width: 3px; height: 3px; margin-right: 8px; border-radius: 50%;
  background: var(--txt-3); vertical-align: middle;
}
#viewProject .pj-meta #dCount { height: auto; padding: 0; background: none; font-size: inherit; color: inherit; }
#viewProject #btnInvite { border-style: solid; border-color: var(--line); border-radius: 7px; }
#pathCrumbs .cr-more {
  flex: none; min-width: 28px; height: 26px; padding: 0 8px; border: 0; border-radius: 6px;
  background: var(--bg-3); color: var(--txt-2); font: inherit; line-height: 1; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { #pathCrumbs .cr-more:hover { color: var(--txt); } }
#pathCrumbs .cr.cur { display: inline-flex; align-items: center; gap: 7px; }
#pathCrumbs .cr.cur::before {
  content: ''; width: 17px; height: 17px; flex: none; background: var(--txt-2);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (max-width: 1023px) {
  #viewProject .pj-meta { font-size: 12.5px; }
}
@media (min-width: 1024px) {
  #viewProject #btnBack {
    display: inline-flex; height: 26px; padding: 0 8px; margin-left: -8px;
    color: var(--txt-2); font-size: 12.5px;
  }
  @media (hover: hover) and (pointer: fine) { #viewProject #btnBack:hover { color: var(--txt); } }
  #viewProject .ph-break { display: block; flex-basis: 100%; height: 0; }
  #viewProject .pj-hero-cover.no-img { background-size: 22px; }
  #tabPhotos > #pathCrumbs { font-size: 14.5px; }
  #tabPhotos > #pathCrumbs .cr.cur { font-size: 16px; font-weight: 600; }
}
/* Nút mời thành viên: chưa có ai → nút đầy đủ (icon người +); đã có thành viên → thu thành ô "+"
   cùng cỡ/kiểu với avatar, gắn liền cuối dãy avatar (2026-10-10, theo mockup phương án A). Ô "+" nằm
   LỚP DƯỚI CÙNG ở cuối bên phải (avatar cuối đè lên mép trái của nó, giống thứ tự xếp chồng của dãy
   avatar) — người dùng chọn kiểu này. Bấm cụm hay bấm "+" đều mở bảng thành viên. */
#btnInvite .inv-plus { display: none; }
#viewProject #pjAvatars:not([hidden]) + #btnInvite {
  /* -16px = bù khoảng gap 12px của .page-head + chồng 4px như giữa các avatar */
  position: relative; z-index: 0; width: 26px; height: 26px; min-width: 26px; margin-left: -16px;
  border: 0; border-radius: 6px; background: var(--bg-3); color: var(--txt-2); box-shadow: 0 0 0 2px var(--bg);
}
@media (hover: hover) and (pointer: fine) { #viewProject #pjAvatars:not([hidden]) + #btnInvite:hover { color: var(--txt); box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px var(--line); } }
#viewProject #pjAvatars:not([hidden]) + #btnInvite .inv-full { display: none; }
#viewProject #pjAvatars:not([hidden]) + #btnInvite .inv-plus { display: block; width: 14px; height: 14px; }

/* ==========================================================================
   Video đang chờ tải — phương án A "ánh quét" (2026-10-10). Ô ảnh lưới, khung xem ảnh và lúc tải
   thư mục GIỮ NGUYÊN (người dùng yêu cầu, chỉ sửa phần video).
   Video: .vs-buf = đoạn đã tải (xám nhạt dưới phần đã phát); .is-wait = đang chờ dữ liệu → đoạn đó
   ánh lên (createVideoBar trong thread.js). Chỉ CSS animation, không gọi thêm gì lên NAS.
   ========================================================================== */
@keyframes sfSheen { from { background-position: 120% 0; } to { background-position: -120% 0; } }
.vs-buf {
  /* phủ cả thanh; thread.js tô từng đoạn đã tải bằng linear-gradient màu --buf-c */
  position: absolute; left: 0; top: 0; bottom: 0; width: 100%; border-radius: 6px; pointer-events: none;
  --buf-c: rgba(255, 255, 255, .28); background: none;
}
html[data-theme="light"] #lb .vs-buf, html[data-theme="light"] #alb .vs-buf { --buf-c: rgba(32, 33, 36, .22); }
/* Ánh quét chạy suốt cả thanh (không chỉ đoạn đã tải) — tua tới giữa video chưa tải thì .vs-buf
   rỗng, vẫn phải thấy là đang chờ */
.vs-track.is-wait::after {
  content: ''; position: absolute; inset: 0; z-index: 2; border-radius: 6px; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .55) 50%, transparent 70%) 0 0 / 220% 100%;
  animation: sfSheen 1.1s linear infinite;
}
html[data-theme="light"] #lb .vs-track.is-wait::after, html[data-theme="light"] #alb .vs-track.is-wait::after {
  background-image: linear-gradient(100deg, transparent 30%, rgba(32, 33, 36, .35) 50%, transparent 70%);
}
@media (prefers-reduced-motion: reduce) {
  .vs-track.is-wait::after { animation: none; }
}


/* ==========================================================================
   Biểu tượng đang tải "khung bo góc viền chạy" (kiểu 5, 2026-10-10) — thay ô vuông bo góc XOAY (từ khi
   bỏ hình tròn trông như lỗi). Khung đứng yên, một đoạn viền chạy quanh: conic-gradient quay theo góc
   --sf-trace, mask chỉ giữ phần viền 2px. Áp cho: ô ảnh đang tải (.spin), khung xem lúc mở ảnh
   (.viewer-image-spin), "Đang tải…" khi mở dự án/thư mục/My Drive (.sf-loader-ring), đang chuyển mã
   ở thanh trên (.jobs-spin) và cạnh ô chất lượng video (.qspin). Khung % chuyển mã: .ring ở trên.
   ========================================================================== */
@property --sf-trace { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@keyframes sfTrace { to { --sf-trace: 360deg; } }
.spin::before, .sf-loader-ring, .jobs-spin, .qspin, .ofv-spin {
  --tr-fg: var(--txt-2); --tr-bg: rgba(128, 128, 140, .24);
  box-sizing: border-box; border: 0; padding: 2px;
  background: conic-gradient(from var(--sf-trace), var(--tr-fg) 0 24%, var(--tr-bg) 24% 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  animation: sfTrace 1.1s linear infinite;
}
.spin::before { border-radius: 7px; }
.sf-loader-ring { border-radius: 7px; }
.jobs-spin { --tr-fg: var(--warn); --tr-bg: rgba(245, 166, 35, .25); border-radius: 5px; }
.qspin { --tr-bg: rgba(255, 255, 255, .18); border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  .spin::before, .sf-loader-ring, .jobs-spin, .qspin, .ofv-spin { animation-duration: 3s; }
  .ring.indeterminate .rfg { animation-duration: 3s; }
}

/* Chuông thông báo — phương án A (2026-10-11): số chưa đọc là ô vuông bo 5px (thay viên tròn bo 8px),
   viền 2px cùng màu nền xung quanh để tách khỏi nét chuông; chấm "dùng thử" đổi viền sang bóng cùng
   kiểu. Thanh bên máy tính nền --side, còn lại (thanh trên điện thoại, trang khách) nền --bg. */
.notif-badge { border-radius: 5px; box-shadow: 0 0 0 2px var(--bg); }
.notif-dot { border: 0; box-shadow: 0 0 0 2px var(--bg); }
.sf-side .notif-badge, .sf-side .notif-dot { box-shadow: 0 0 0 2px var(--side, var(--bg-1)); }


/* Thanh điều khiển video ở giao diện Sáng (2026-10-11): các nút vốn tô cứng #fff/rgba(255,…) cho nền
   tối, sang khung xem nền trắng (#lb trang khách/Live, #alb quản trị) thì gần như biến mất → đổi sang
   màu chữ của bảng màu Sáng. Đầu phát (vạch nhô của .vs-fill) và nút trượt âm lượng cũng đổi cho thấy. */
html[data-theme="light"] #lb .vs-play,
html[data-theme="light"] #lb .vs-mute,
html[data-theme="light"] #lb .vs-fs,
html[data-theme="light"] #lb .vs-timebtn,
html[data-theme="light"] #lb .vs-time,
html[data-theme="light"] #alb .vs-play,
html[data-theme="light"] #alb .vs-mute,
html[data-theme="light"] #alb .vs-fs,
html[data-theme="light"] #alb .vs-timebtn,
html[data-theme="light"] #alb .vs-time { color: var(--txt); }
html[data-theme="light"] #lb .vs-loop,
html[data-theme="light"] #alb .vs-loop { color: var(--txt-3); }
html[data-theme="light"] #lb .vs-loop.on,
html[data-theme="light"] #alb .vs-loop.on { color: var(--accent); }
html[data-theme="light"] #lb .vs-time-sep,
html[data-theme="light"] #alb .vs-time-sep { color: var(--txt-3); }
html[data-theme="light"] #lb .vs-time-total,
html[data-theme="light"] #alb .vs-time-total { color: var(--txt-2); }
html[data-theme="light"] #lb .vs-row .qbar,
html[data-theme="light"] #alb .vs-row .qbar {
  color: var(--txt);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23202124' stroke-opacity='.6' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
html[data-theme="light"] #lb .vs-fill::after,
html[data-theme="light"] #alb .vs-fill::after { background: var(--txt); }
html[data-theme="light"] #lb .vsp-tick,
html[data-theme="light"] #alb .vsp-tick { background: rgba(32, 33, 36, .25); }
html[data-theme="light"] #lb .vsp-thumb,
html[data-theme="light"] #alb .vsp-thumb { background: #fff; box-shadow: 0 0 0 1px rgba(32, 33, 36, .25), 0 1px 3px rgba(32, 33, 36, .3); }


/* ==========================================================================
   Khung bình luận gọn — phương án A (2026-10-11, renderThread trong thread.js thêm class .cv).
   Avatar 22px, nội dung thẳng hàng với tên (lùi 31px); nút Trả lời / Cảm xúc / ⋯ / ✓ là icon cuối
   hàng tên, chỉ hiện khi rê chuột (✓ đã xử lý luôn hiện; màn cảm ứng hiện sẵn, mờ); không còn hàng
   nút riêng, không còn dòng "có đánh dấu"; khoảng cách giữa các góp ý nhỏ lại. Chỉ nhắm .cmt.cv nên
   tab Phản hồi (.fb-comment) và bảng Tất cả nhận xét không đổi.
   ========================================================================== */
.cmt.cv { position: relative; margin: 0 -8px 2px; padding: 7px 8px 8px 39px; border-radius: 8px; }
@media (hover: hover) and (pointer: fine) { .cmt.cv:hover { background: var(--hover); } }
.cmt.cv .who { display: flex; align-items: center; gap: 6px; min-height: 22px; margin-bottom: 1px; padding-right: 28px; }
.cmt.cv .who > .avatar {
  position: absolute; left: 8px; top: 7px; width: 22px; height: 22px; font-size: 9.5px; border-radius: 6px;
}
.cmt.cv .cmt-author { flex: 0 1 auto; min-width: 0; flex-wrap: nowrap; }
.cmt.cv .cmt-author b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; overflow-wrap: normal; }
.cmt.cv .who > .when { flex: none; font-size: 11.5px; }
.cmt.cv .body { font-size: 13px; line-height: 1.45; }
.cmt.cv .tc { margin-right: 6px; }
/* Góp ý có vẽ trên ảnh: dòng nhỏ dưới nội dung "〰 Có đánh dấu trên hình" (icon nét xoắn giống tab Phản hồi) */
.cmt.cv .draw-note { display: flex; align-items: center; gap: 5px; margin-top: 3px; font-size: 11.5px; color: var(--txt-3); }
.cmt.cv .draw-note svg { width: 14px; height: 14px; flex: none; }
@media (hover: hover) and (pointer: fine) { .cmt.cv:hover .draw-note { color: var(--txt-2); } }
.cmt.cv.reply { margin-left: 23px; padding-left: 39px; border-left: 2px solid var(--line-soft); border-radius: 0 8px 8px 0; }
.cmt.cv.reply .who > .avatar { left: 8px; }
/* Nhóm nút: THANH NỔI ở góc phải hàng tên (kết hợp phương án B) — position:absolute nên hiện/ẩn khi rê
   chuột không làm xô lệch bố cục; ✓ của góp ý đã xử lý là nút cuối nên luôn nằm đúng góc đó (hàng tên
   chừa sẵn 28px bên phải cho nó). */
.cmt-tools {
  position: absolute; top: 4px; right: 6px; z-index: 5; display: flex; align-items: center; gap: 1px;
  padding: 1px; border: 1px solid transparent; border-radius: 8px;
}
.cmt.cv:hover .cmt-tools, .cmt.cv:focus-within .cmt-tools {
  background: var(--bg-1); border-color: var(--line); box-shadow: 0 4px 14px rgba(0, 0, 0, .22);
}
.cmt.cv .cmt-tool {
  width: 24px; height: 24px; padding: 0; border: 0; border-radius: 6px; background: none; cursor: pointer;
  display: none; place-items: center; color: var(--txt-3); transition: background-color .12s;
}
.cmt.cv .cmt-tool svg { width: 15px; height: 15px; }
/* ẩn hẳn (không chiếm chỗ) để tên dài không bị cắt khi không rê chuột */
.cmt.cv:hover .cmt-tool, .cmt.cv:focus-within .cmt-tool { display: grid; }
@media (hover: hover) and (pointer: fine) { .cmt.cv .cmt-tool:hover { background: var(--bg-3); color: var(--txt); } }
.cmt.cv .cmt-resolve-btn.on { display: grid; color: var(--ok); }
@media (hover: hover) and (pointer: fine) { .cmt.cv .cmt-resolve-btn.on:hover { background: rgba(47, 191, 113, .14); color: var(--ok); } }
@media (hover: none) {
  .cmt.cv .who { padding-right: 112px; }
  .cmt.cv .cmt-tool { display: grid; opacity: .55; }
  .cmt.cv .cmt-resolve-btn.on { opacity: 1; }
  @media (hover: hover) and (pointer: fine) { .cmt.cv:hover .cmt-tools { background: none; border-color: transparent; box-shadow: none; } }
}
.cmt-more-wrap { position: relative; display: inline-flex; }
.cmt-more-pop {
  position: absolute; top: 26px; right: 0; z-index: 30; min-width: 110px; padding: 4px;
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  display: flex; flex-direction: column;
}
.cmt-more-pop[hidden] { display: none; }
.cmt-more-pop button {
  border: 0; background: none; color: var(--txt); font: inherit; font-size: 13px; text-align: left;
  padding: 6px 10px; border-radius: 6px; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .cmt-more-pop button:hover { background: var(--hover); } }
.cmt-more-pop button.del { color: var(--danger); }
/* Cảm xúc: chip nhỏ + nút ☺ thêm nhanh ở cuối */
.cmt.cv .cmt-reactions { gap: 4px; margin-top: 5px; }
.cmt.cv .react-chip { height: 22px; }
.cmt.cv .cmt-react-add { width: 26px; padding: 0; display: inline-grid; place-items: center; color: var(--txt-3); }
.cmt.cv .cmt-react-add svg { width: 13px; height: 13px; }

/* Ô trả lời ngay dưới góp ý — kiểu B (openInlineReply trong thread.js, 2026-10-11): 1 khung duy nhất,
   ô nhập tự giãn ở trên, hàng công cụ mảnh ở dưới (📎 ☺ · Huỷ · Gửi). Viền tím khi đang gõ. */
.cmt-inline-reply {
  margin: 2px 0 10px 31px; border: 1px solid var(--line); border-radius: 9px; background: var(--bg-1);
  transition: border-color .12s;
}
.cmt-inline-reply:focus-within { border-color: var(--accent); }
.cmt-inline-reply textarea {
  display: block; width: 100%; min-height: 34px; max-height: 168px; resize: none; overflow-y: auto;
  padding: 8px 10px 4px; border: 0; outline: 0; background: transparent; color: var(--txt);
  font: inherit; font-size: 13px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere;
}
.cmt-inline-reply textarea::placeholder { color: var(--txt-3); }
.ir-files { display: flex; flex-wrap: wrap; gap: 4px; padding: 2px 8px 0; }
.ir-files[hidden] { display: none; }
.ir-file {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 24px; padding: 0 4px 0 8px;
  border-radius: 6px; background: var(--bg-2); border: 1px solid var(--line-soft); font-size: 11.5px; color: var(--txt-2);
}
.ir-file .nm { color: var(--txt); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; }
.ir-file.up { opacity: .7; }
.ir-file button { border: 0; background: none; color: var(--txt-3); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 3px; }
@media (hover: hover) and (pointer: fine) { .ir-file button:hover { color: var(--txt); } }
.ir-tools { display: flex; align-items: center; gap: 1px; padding: 3px 4px 4px 5px; }
.ir-tool {
  width: 26px; height: 26px; padding: 0; border: 0; border-radius: 6px; background: none; color: var(--txt-3);
  display: grid; place-items: center; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .ir-tool:hover { background: var(--bg-3); color: var(--txt); } }
.ir-emoji-wrap { position: relative; display: inline-flex; }
.ir-emoji-pop { top: auto; bottom: 30px; left: 0; right: auto; }
.ir-sp { flex: 1; }
.ir-cancel { border: 0; background: none; color: var(--txt-3); font: inherit; font-size: 12px; padding: 4px 8px; border-radius: 6px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .ir-cancel:hover { color: var(--txt); background: var(--hover); } }
.ir-send {
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 7px; background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center; cursor: pointer;
}
.ir-send:disabled { background: var(--bg-3); color: var(--txt-3); cursor: default; }
@media (hover: none) { .cmt-inline-reply textarea { font-size: 16px; } }

/* Đang kéo sắp xếp: không bôi chọn văn bản (khối màu nhấn khi rê chuột) */
html.sf-reordering, html.sf-reordering * { user-select: none !important; -webkit-user-select: none !important; }

/* ---------- Gom dự án theo tháng (2026-10-12) ---------- */
#cards.pj-months { display: block; }
.pj-mgroup { border: 1px solid var(--line-soft); border-radius: 12px; margin-bottom: 10px; background: var(--bg-1); overflow: hidden; }
.pj-mhead { display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px 14px; border: 0; background: transparent; color: var(--text); font: inherit; cursor: pointer; text-align: left; }
@media (hover: hover) and (pointer: fine) { .pj-mhead:hover { background: var(--bg-2); } }
.pj-mhead b { font-weight: 600; font-size: 14px; }
.pj-mcount { font-size: 12px; color: var(--muted, #8b90a0); }
.pj-mchev { flex: none; transition: transform .15s; color: var(--muted, #8b90a0); }
.pj-mgroup.open .pj-mchev { transform: rotate(90deg); }
.pj-mthumbs { margin-left: auto; display: flex; padding-left: 10px; }
.pj-mthumbs i { width: 34px; height: 34px; border-radius: 7px; margin-left: -10px; border: 2px solid var(--bg-1); background: var(--bg-3, #3a3f50) center / cover; }
@media (hover: hover) and (pointer: fine) { .pj-mhead:hover .pj-mthumbs i { border-color: var(--bg-2); } }
.pj-mgroup.open .pj-mthumbs { display: none; }
.pj-mgrid { display: none; padding: 4px 14px 14px; grid-template-columns: repeat(auto-fill, minmax(var(--pcard-min, 250px), 1fr)); gap: 16px; }
.pj-mgroup.open .pj-mgrid { display: grid; }
@media (max-width: 640px) {
  .pj-mgrid { grid-template-columns: repeat(var(--pcols, 1), minmax(0, 1fr)); gap: 12px; padding: 4px 10px 12px; }
  .pj-mthumbs i:nth-child(n+4) { display: none; }
}

/* ---------- Trang Lưu trữ: dòng thời gian theo năm (2026-10-13) ---------- */
#cards.pj-archive { display: block; }
.pj-archive-hint { display: flex; align-items: center; gap: 10px; max-width: none; padding: 9px 12px; border: 1px dashed var(--line); border-radius: 8px; background: color-mix(in srgb, var(--warn) 6%, transparent); }
.mf-year { padding: 0 9px; }   /* ô chọn năm trong bảng Lọc (trang Lưu trữ) — cùng kiểu ô sao .mf-star */
.pj-ayear { display: flex; align-items: center; gap: 10px; margin: 18px 0 4px; font-size: 12px; letter-spacing: .06em; color: var(--txt-3); }
.pj-ayear i { flex: 1; height: 1px; background: var(--line); }
.pj-ayear em { font-style: normal; letter-spacing: 0; }
.pj-arow { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto auto; gap: 14px; align-items: center; padding: 8px 6px; border-bottom: 1px solid var(--line-soft); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .pj-arow:hover { background: var(--bg-1); } }
.pj-athumb { width: 56px; aspect-ratio: 16 / 9; border-radius: 5px; background: var(--bg-3); overflow: hidden; }
.pj-athumb img { width: 100%; height: 100%; object-fit: cover; display: block; filter: grayscale(.85); opacity: .75; }
.pj-arow:hover .pj-athumb img { filter: none; opacity: 1; }
.pj-aname { display: flex; flex-direction: column; min-width: 0; }
.pj-aname b { font-weight: 500; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pj-aname small { font-size: 12px; color: var(--txt-3); }
.pj-adate { font-size: 12px; white-space: nowrap; }
@media (max-width: 640px) {
  .pj-arow { grid-template-columns: 56px minmax(0, 1fr) auto; gap: 10px; }
  .pj-adate { display: none; }
  .pj-arestore { display: none; }
}
.pj-amenu { display: none; width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 8px; background: transparent; color: var(--txt-2); font-size: 16px; line-height: 1; cursor: pointer; }
@media (max-width: 640px) { .pj-amenu { display: block; } }
/* Gom theo tháng ở chế độ danh sách: hàng nằm gọn trong khung tháng */
.pj-mlist { display: none; padding: 0 6px 6px; }
.pj-mgroup.open .pj-mlist { display: block; }
.pj-mlist .frow:last-child { border-bottom: 0; }

/* Riêng / Chung / Thùng rác của SlateDrive: máy tính chọn ở thanh bên (kiểu Google Drive, 2026-10-21),
   điện thoại/tablet không có thanh bên nên giữ 3 tab trên thanh công cụ. */
@media (min-width: 1024px) { #drvTabs { display: none !important; } }
