/* Slate Frame — giao diện tối lấy cảm hứng từ Frame.io */
:root {
  --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: #333846; 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;
}
.btn:hover { background: #2d3140; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-hi); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--txt-2); }
.btn.ghost:hover { background: var(--bg-2); color: var(--txt); }
.btn.danger { border-color: #55232a; color: #ff8b96; background: transparent; }
.btn.danger:hover { background: #2a1518; }
.btn.sm { height: 28px; padding: 0 10px; font-size: 13px; }
.btn.icon { width: 34px; padding: 0; justify-content: center; }

.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: 999px;
  background: var(--bg-3); font-size: 11.5px; color: var(--txt-2);
}
.chip.ok { background: rgba(47, 191, 113, .15); color: #6fe0a4; }
.chip.warn { background: rgba(245, 166, 35, .15); color: #ffc766; }
.chip.acc { background: rgba(91, 83, 255, .18); color: #b0abff; }

/* ---------- topbar ---------- */
.topbar {
  /* z-index ở đây phải LỚN HƠN z-index của #btnUpload/#btnShare (50, xem @media mobile):
     .topbar tự tạo stacking context riêng (position:sticky + z-index), nên các con bên
     trong nó như #notifDrop/.jobs-pop dù z-index cao (250/260) cũng chỉ so được với nhau
     TRONG NỘI BỘ topbar — ra ngoài, cả khối topbar bị so bằng đúng z-index này. Để 40 thì
     hai nút nổi (z-index 50) đè lên trên toàn bộ topbar, kể cả bảng thông báo. */
  position: sticky; top: 0; z-index: 60;
  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: -1; pointer-events: none;
  background: rgba(20, 22, 28, .92); backdrop-filter: blur(12px);
}
.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 { cursor: pointer; }
.crumb .cr-ws:hover { color: var(--txt); }

/* ---------- 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; }

.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;
}
.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: 8px; flex-wrap: wrap; }

/* ---------- thùng rác ---------- */
.card.trash { cursor: default; }
.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: 50%; display: block;
  border: 2px solid rgba(245, 166, 35, .25); border-top-color: #ffc766;
  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: slideup .15s ease;
}
.jobs-pop-head { font-size: 12.5px; color: #ffc766; 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: 999px; 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 { 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;
}
.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;
}
.notif-head {
  display: flex; align-items: center; justify-content: space-between;
  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-list { overflow-y: auto; }
.notif-item {
  display: block; width: 100%; text-align: left; padding: 10px 14px; border: none; background: none;
  cursor: pointer; border-bottom: 1px solid var(--line-soft); color: inherit; font: inherit;
}
.notif-item:hover { background: var(--bg-3); }
.notif-item.unread { background: rgba(91, 83, 255, .07); }
.notif-item .ntitle { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.notif-item .ntitle .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.notif-item .nbody { font-size: 12.5px; color: var(--txt-2); margin-top: 3px; }
.notif-item .ntime { font-size: 11px; color: var(--txt-3); margin-top: 4px; }
.notif-empty { padding: 24px 14px; text-align: center; color: var(--txt-3); font-size: 13px; }
.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;
}
.notif-push:hover { background: var(--bg-3); color: var(--txt); }
.notif-push.on { color: var(--accent-hi); }
.notif-push svg { flex: none; }
.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 — #pjFilter/#pjSort/#dFilter/#dSort vẫn là nguồn sự thật,
   luôn ẩn, thay bằng #btnPjFilter/#btnPjSort/#btnDFilter/#btnDSort mở sheet/dropdown. */
#pjFilter, #pjSort, #dFilter, #dSort { display: none; }
.viewtoggle { display: flex; border: 1px solid var(--line-soft); border-radius: 8px; overflow: hidden; flex: 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); }
.vt-btn:hover { color: var(--txt); }

/* ---------- chế độ xem danh sách ---------- */
/* cột cố định theo thứ tự: chọn · ảnh · Tên · Trạng thái · 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 110px 150px 140px 90px 110px 90px minmax(220px, 1fr);
  min-width: 1350px;
  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; }
.frow:hover { background: var(--bg-2); }
.frow.picked { background: rgba(91, 83, 255, .08); }
.frow-head {
  cursor: default; font-size: 11px; color: var(--txt-3); text-transform: uppercase;
  letter-spacing: .02em; background: var(--bg-2);
}
.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;
}
.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 110px 150px 90px 110px 90px; min-width: 980px; }

/* 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 120px 110px 90px 90px 90px; min-width: 760px; }

/* ---------- 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)); }
.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;
}
.tile:hover { border-color: #3a4152; }
.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; }
/* 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(91, 83, 255, .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ề icon, hiển thị thu nhỏ ở giữa cho gọn */
.tile .ph.isfile { display: grid; place-items: center; }
.tile .ph.isfile img { width: 72%; height: 72%; 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; }
/* 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; }
.stars .star:hover { transform: scale(1.15); }
.stars .star.on { color: var(--txt); }
.tile .stars.tile-stars { padding: 3px 9px 6px; }
.tile .stars.tile-stars .star { font-size: 14px; }
#albStars.lb-stars, .lb-stars { display: flex; gap: 2px; }
.lb-stars .star { font-size: 16px; }

/* 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;
}
.tile .badges { position: absolute; top: 8px; left: 8px; 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, .55); color: #fff; backdrop-filter: blur(4px);
}
/* 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(91, 83, 255, .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; }

/* Ô 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, .45); backdrop-filter: blur(4px);
  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.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; }

/* 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: 50%;
  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); } }
.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; transform: rotate(-90deg); grid-area: 1/1; }
.ring circle { 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) thì quay tròn nguyên vòng thay vì đứng im ở 0% —
   quay ở div ngoài để không đụng transform rotate(-90deg) cố định trên svg bên trong. */
.ring.indeterminate { animation: wahspin 1s linear infinite; }
/* đ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: 50%; pointer-events: none;
  background: rgba(0, 0, 0, .5); backdrop-filter: blur(3px);
  display: grid; place-items: center; color: #fff; z-index: 2;
}
.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: 50%; display: grid; place-items: center;
  font-size: 10px; font-weight: 700; background: rgba(0, 0, 0, .55); backdrop-filter: blur(4px);
}

/* Huy hiệu góp ý: icon kèm luôn số lượng nên phải nới ra thành viên thuốc */
.badge-cmt {
  width: auto; min-width: 20px; padding: 0 6px; border-radius: 10px;
  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; transition: grid-template-columns .18s;
}
.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;
}
.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;
}
/* 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 vào để phát/tạm dừng — xem createWaveform() trong waveform.js */
#lbWave, #albWave {
  inset: 20px; width: calc(100% - 40px); height: calc(100% - 40px);
  background: rgba(0, 0, 0, .35); cursor: pointer; pointer-events: auto;
}
.lb.audio-mode .zoombar { display: none; }

/* 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: 50%;
  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(20, 22, 28, .88); border: 1px solid var(--line);
  border-radius: 9px; color: var(--txt-2); font-size: 12.5px;
  backdrop-filter: blur(8px);
}
.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(20, 22, 28, .9); border: 1px solid var(--line); color: var(--txt-2);
}
.prepping .prep-bar {
  height: 5px; margin: 12px 0 7px; border-radius: 999px;
  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(91, 83, 255, .2); color: #b0abff;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px;
}
.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; }

/* Đườ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;
}

/* Đ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: 2px; flex: none;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; padding: 0 2px;
}
.lb-nav .nav-btn {
  width: 26px; height: 26px; border-radius: 6px; border: none; background: transparent;
  color: var(--txt-2); cursor: pointer; display: grid; place-items: center; font-size: 16px;
  line-height: 1; transition: background .12s, color .12s;
}
.lb-nav .nav-btn:hover { background: var(--bg-3); color: var(--txt); }
.lb-nav .nav-idx {
  font-size: 12px; color: var(--txt-2); padding: 0 7px; 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; }

/* ---------- video: nút phát giữa khung + thanh chạy dưới khung ----------
   Thay hẳn cho control mặc định của trình duyệt (đã bỏ thuộc tính controls trên <video>). */
.vcenter-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 4;
  width: 60px; height: 60px; border-radius: 50%; border: none; cursor: pointer;
  display: grid; place-items: center; color: #fff; padding: 0;
  background: rgba(20, 22, 28, .55); backdrop-filter: blur(4px);
  transition: background .12s, transform .12s;
}
.vcenter-play:hover { background: rgba(20, 22, 28, .75); transform: translate(-50%, -50%) scale(1.06); }
.vcenter-play svg { margin-left: 3px; }   /* tam giác play lệch tâm quang học, dịch sang phải chút */

/* Dải riêng dưới khung hình — 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: 999px; 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 { display: block; height: 100%; width: 0; border-radius: 999px; background: var(--accent); pointer-events: none; }
.vs-marks { position: absolute; inset: 0; }
.vs-mark {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  padding: 0; border: 0; background: none; cursor: pointer; line-height: 0;
}
.vs-mark .avatar { width: 20px; height: 20px; font-size: 9px; box-shadow: 0 0 0 2px var(--bg-1); }
.vs-mark:hover .avatar { box-shadow: 0 0 0 2px var(--bg-1), 0 0 0 3px var(--accent-hi); }
.vs-row { display: flex; align-items: center; gap: 8px; }
.vs-play, .vs-mute {
  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 { width: 22px; height: 22px; }
.vs-play:hover, .vs-mute:hover { background: var(--bg-3); }
.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;
}
/* 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; }

.cmt { margin-bottom: 14px; border-radius: 8px; transition: background-color .3s; }
.cmt.flash { background-color: rgba(91, 83, 255, .18); }
.cmt .who { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.avatar {
  width: 24px; height: 24px; border-radius: 50%; 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: #b0abff; text-decoration: underline; text-underline-offset: 2px; }
.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 #ffc766; }

.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; }

/* ---------- thanh zoom ---------- */
.zoombar {
  position: absolute; left: 16px; bottom: 16px; z-index: 3;
  display: flex; align-items: center; gap: 2px; padding: 4px;
  background: rgba(20, 22, 28, .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;
}
.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;
}
.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: 50%; 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;
}
.tool-pop button:hover { background: var(--bg-3); }
.tool-pop button.on { background: var(--accent); color: #fff; }

/* 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; }

/* 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: #b0abff; }
.pen.has-draw::after {
  content: attr(data-n); margin-left: 2px; min-width: 15px; height: 15px; padding: 0 4px;
  border-radius: 999px; 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;
}
.emoji-pop span:hover { background: var(--bg-3); }

/* Chọn Công khai/Nội bộ khi gửi nhận xét (chỉ có ở trang admin) — bảng rớt xuống
   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;
}
.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; }
.file-chip .rm:hover { color: #ff8b96; }
.file-chip.up { opacity: .55; }
a.file-chip:hover { border-color: var(--line); background: var(--bg-3); }

.cmt.has-draw { 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)); }
.cmt-acts { display: flex; gap: 12px; margin-top: 4px; opacity: 0; transition: opacity .12s; }
.cmt:hover .cmt-acts { opacity: 1; }
.cmt-acts .act { font-size: 11.5px; color: var(--txt-3); cursor: pointer; }
.cmt-acts .act:hover { color: var(--txt); }
.cmt-acts .act.del:hover { color: #ff8b96; }

.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); }
.reply-to .x:hover { color: var(--txt); }

/* ---------- modal ---------- */
.mask { position: fixed; inset: 0; background: rgba(4, 5, 8, .72); display: none; place-items: center; z-index: 200; 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 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; }

/* ---------- gate (màn hình nhập mật khẩu) ---------- */
.gate { min-height: 100dvh; display: grid; place-items: center; padding: 24px; }
.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; }
.gate-box .link:hover { text-decoration: underline; }
.err { color: #ff8b96; 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: 50%; 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; }
.crumbs .cr:hover { color: var(--txt); }
.crumbs .cr.cur { color: var(--txt); cursor: default; }
.crumbs .sep { color: var(--txt-3); }

/* Ô 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 */
.mcell-folder {
  display: grid; place-items: center;
  background: var(--bg-3); color: var(--txt-2);
}
.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; }
.tile.folder .ph.empty .fic { position: static; color: var(--txt-3); filter: none; }
.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;
}
.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(91, 83, 255, .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;
}
.ctx-item:hover { background: var(--bg-3); }
.ctx-item.danger { color: #ff8b96; }
.ctx-item.danger:hover { background: #2a1518; }
.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;
}

/* ---------- 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;
}
.cover-pick-item:hover { border-color: var(--accent); }

/* ---------- Project Settings ---------- */
.psettings { display: grid; grid-template-columns: 160px 1fr; gap: 22px; }
.ps-cover {
  aspect-ratio: 1; border-radius: 10px; 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;
}
.ps-cover.has-cover { cursor: grab; }
.ps-cover.has-cover.dragging { cursor: grabbing; }
.ps-fields { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.ps-sec { padding-top: 12px; border-top: 1px solid var(--line-soft); }
.ps-sec-head { font-size: 11.5px; color: var(--txt-3); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 8px; }
.ps-row {
  display: flex; align-items: flex-start; gap: 10px; font-size: 13px; cursor: default;
}
.ps-row input[type="checkbox"] { margin-top: 3px; }
.ps-row.disabled { opacity: .55; }
.ps-row .dim { font-size: 12px; }
.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-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none; object-fit: cover;
  background: var(--bg-3); display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--txt-2);
}

/* ---------- 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: #ffc766;
}
.warnbox b { color: #ffd899; }
.warnbox.danger {
  background: rgba(255, 90, 90, .12); border-color: rgba(255, 90, 90, .35); color: #ff8b96;
}
.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); }
.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); }

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; }

/* ============================================================
   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,
   giữ nguyên thứ tự cũ (các nút rồi mới tới chip phần trăm zoom). */
.lb-acts { display: flex; align-items: center; gap: 12px; }
.lb-head > .lb-acts { order: 1; }
.lb-head > #lbZoom { order: 2; }

/* 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: 240px; max-height: 70vh; overflow-y: auto;
  padding: 6px; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow);
  animation: slideup .15s ease;
}
@keyframes slideup { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.sheet-title {
  padding: 9px 12px 7px; 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; min-height: 48px;
  padding: 8px 12px; border-radius: 9px; cursor: pointer; font-size: 14.5px;
}
.sheet-item:active { background: var(--bg-3); }
.sheet-item .si-ic { width: 20px; 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); }

/* Thiết bị cảm ứng: những nút vốn chỉ hiện khi rê chuột phải hiện thường trực */
@media (hover: none) {
  .cmt-acts { opacity: 1; }
}

@media (max-width: 720px) {
  .wrap { padding: 16px 12px 120px; }
}

@media (max-width: 640px) {

  /* ---------- thanh trên: 2 tầng ---------- */
  .topbar {
    height: auto; min-height: 50px; padding: 0 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;
  }
  /* tabs lọc xuống tầng 2, cuộn ngang có chủ đích */
  .topbar > .tabs {
    order: 2; flex: 1 1 100%;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .topbar > .tabs::-webkit-scrollbar { width: 0; height: 0; }
  .tab { flex: none; padding: 8px 13px; font-size: 13.5px; white-space: nowrap; }
  #btnSelMode { height: var(--tap); padding: 0 13px; font-size: 13.5px; }
  #btnMoreGrid, #lbMore, #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;
    animation: sheetup .2s cubic-bezier(.22, .8, .2, 1);
  }

  /* 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: #b0abff; }

  /* ---------- thanh lọc ---------- */
  .fbar { flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
  .fbar .spacer { display: none; }
  #btnFilterSheet, #btnSortSheet {
    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);
  }
  /* 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 { background: var(--bg-3); color: #b0abff; }
  .filter-dot { position: absolute; top: 6px; right: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
  #viewToggle { flex: none; margin-left: auto; }
  .fbar .viewtoggle .vt-btn { width: var(--tap); height: var(--tap); justify-content: center; }

  /* ---------- 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; }
  .tile .stars.tile-stars { padding: 0 9px 9px; gap: 6px; }
  .tile .stars.tile-stars .star { font-size: 20px; padding: 2px 0; }

  /* ô tích chỉ xuất hiện khi đã vào chế độ chọn, để không lẫn với các dấu hiệu khác trên ô ảnh */
  #grid .tile .checkbox { opacity: 0; pointer-events: none; }
  body.sel-mode #grid .tile .checkbox {
    opacity: 1; pointer-events: auto;
    width: 32px; height: 32px; border-radius: 8px; top: 8px; left: 8px; right: auto; font-size: 15px;
  }

  /* ---------- 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 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 / 6; 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 / 6; grid-row: 2; }
  .frow-guest .fl-rate .stars { gap: 5px; }
  .frow-guest .fl-rate .star { font-size: 18px; }
  /* dòng phụ: trạng thái · dung lượng · góp ý · ngày */
  .frow-guest .fl-status { grid-column: 2; grid-row: 3; }
  .frow-guest .fl-size   { grid-column: 3; grid-row: 3; }
  .frow-guest .fl-cmt    { grid-column: 4; grid-row: 3; text-align: left; }
  .frow-guest .fl-date   { grid-column: 5; grid-row: 3; }
  .frow-guest .fl-status, .frow-guest .fl-size,
  .frow-guest .fl-cmt, .frow-guest .fl-date { font-size: 11.5px; }
  .frow-guest .fl-status .chip { height: 18px; padding: 0 6px; font-size: 11px; }
  .frow-guest .fl-check { grid-column: 6; 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); }
  .selbar [data-bulk] { flex: 1 1 30%; height: var(--tap); padding: 0 8px; font-size: 13px; justify-content: center; }
  #selDl { flex: 1 1 100%; height: var(--tap); justify-content: center; }
  /* đã có nút Huỷ ở thanh trên của chế độ chọn */
  #selClear { display: none; }
  /* 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(60px + var(--safe-b));
    transition: padding-bottom .22s;
  }
  .lb.open.chrome-off { padding-bottom: 0; }
  /* 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. */
  .lb.open.panel-on { padding-bottom: var(--sheet-h, 60px); }

  .lb-head {
    height: 52px; padding: 0 8px; gap: 8px;
    transition: height .22s, opacity .18s;
  }
  /* 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: height .22s, opacity .18s, visibility 0s .18s;
  }
  .lb-head { flex-wrap: wrap; }
  /* Thanh trên có flex-wrap (để #albMeta xuống dòng 2). Ô 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) { 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: var(--tap); height: var(--tap); font-size: 21px; }
  /* Trình xem của studio (khác trang khách): albMeta (kích thước · dung lượng · người tải)
     hiện thành dòng thứ 2 của thanh trên — #albMore đứng lại dòng 1 nhờ order thấp hơn. */
  #albMore { order: 1; }
  #albMeta {
    display: block; order: 5; flex: 1 1 100%;
    font-size: 11.5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  #alb .lb-head { height: auto; min-height: 52px; padding: 6px 8px; }
  #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(60px + var(--safe-b)); padding: 0 18px var(--safe-b);
    gap: 6px; background: var(--bg-1); border-top: 1px solid var(--line-soft);
    overflow: hidden; transition: height .22s, opacity .18s;
  }
  /* .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; }
  .lb-acts #lbStars { flex: none; }
  .lb-acts .stars { gap: 6px; }
  .lb-acts .stars .star { font-size: 22px; padding: 4px 1px; }
  .lb-acts .btn { height: var(--tap); padding: 0 10px; font-size: 13px; flex: none; }
  /* nút đầu tiên sau cụm sao bị đẩy sang phải, sao ở lại bên trái */
  #lbChanges, #albPanel { margin-left: auto; }
  /* Tải về và Chia sẻ đã chuyển vào menu ⋯ */
  .lb-acts #lbDl, .lb-acts #albDl, .lb-acts #albZoom, .lb-acts #albShare { display: none !important; }

  /* 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); }
  .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 {
    /* Vẫn dính chặt đáy màn hình (KHÔNG trồi theo --kb-inset ở chính .panel) — dời cả
       khung lên thì hở ra khoảng trống bên dưới, lộ nội dung tĩnh phía sau (ảnh/dải phim)
       vì chúng không đổi theo bàn phím. Panel cứ trải nền/bóng đổ tới tận đáy thật của
       màn hình như cũ (khuất sau bàn phím thì thôi, không sao) — chỉ đẩy phần NỘI DUNG
       (khung soạn ở .p-foot bên dưới) trồi lên trên bàn phím bằng padding, nền che kín. */
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
    /* 62dvh chứ không 74dvh như trước: giờ ảnh bị đẩy lên trên sheet chứ không nằm
       khuất sau nó nữa, sheet cao quá thì phần ảnh còn lại chẳng xem được gì */
    max-height: 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 cubic-bezier(.22, .8, .2, 1);
  }
  .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: 999px; background: #3a3f4d;
  }
  .panel .p-foot { padding: 10px 12px calc(12px + var(--safe-b) + var(--kb-inset, 0px)); }

  /* ---------- ô 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; }
  .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; }
  #cmtSend { height: var(--tap); padding: 0 20px; }

  /* ---------- 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 · ⋯
     Mọi nút khác dồn vào menu ⋯ hoặc xuống dải hành động ngay dưới.
     ============================================================ */

  /* 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; }
  /* ⋯ ở góc: cỡ chữ .btn mặc định vẽ ba chấm quá mảnh so với ô chạm 44px */
  #btnMore { font-size: 21px; }

  /* dải hành động tầng 2 — chỉ ở trang danh sách project */
  .tb-row2 {
    order: 2; flex: 1 1 100%;
    display: flex; align-items: center; justify-content: flex-end; gap: 8px;
    padding: 0 0 2px; overflow-x: auto; scrollbar-width: none;
  }
  .tb-row2::-webkit-scrollbar { width: 0; height: 0; }
  /* 34px thay vì --tap (44px): đây là hàng riêng chỉ có một nút, đủ chỗ để nới tay chạm
     bằng cỡ thật (không cần ép cao bằng nút trong thanh chính vốn chật chỗ) */
  .tb-row2 .btn { height: 34px; padding: 0 14px; font-size: 13.5px; white-space: nowrap; flex: none; }
  /* vào trong project thì tabs thay chỗ dải này */
  body.in-project .tb-row2, body.in-trash .tb-row2 { display: none; }

  /* tabs của project nằm ở tầng 2 của thanh trên */
  #viewProject > .tabs {
    margin: 0 0 14px; gap: 4px;
    overflow-x: auto; scrollbar-width: none;
  }
  #viewProject > .tabs::-webkit-scrollbar { width: 0; height: 0; }

  /* ---------- tiêu đề trang ---------- */
  .page-head { gap: 8px 10px; margin-bottom: 14px; }
  .page-head h1 { font-size: 21px; flex: 1 1 100%; order: 2; }
  .page-head #btnBack, .page-head #btnTrashBack {
    order: 1; height: var(--tap); padding: 0 10px; margin-left: -10px; font-size: 13.5px;
  }
  .page-head .chip, .page-head .dim { order: 3; }
  .page-head .spacer { display: none; }
  /* Tải ảnh lên / Tạo link chia sẻ rời khỏi tiêu đề, xuống thanh nổi ở đáy */
  #btnUpload, #btnShare {
    position: fixed; bottom: calc(16px + var(--safe-b)); z-index: 50;
    height: 48px; width: calc(50% - 14px);
    justify-content: center; border-radius: 10px; box-shadow: var(--shadow);
  }
  #btnUpload { left: 10px; }
  #btnShare { right: 10px; }
  /* đang chọn nhiều ảnh thì thanh thao tác chiếm chỗ đó */
  body.sel-mode #btnUpload, body.sel-mode #btnShare { display: none; }
  /* chỉ trang project mới có hai nút này */
  body:not(.in-project) #btnUpload, body:not(.in-project) #btnShare { display: none; }

  /* ---------- tìm/lọc/sắp xếp: nút mở sheet ---------- */
  #btnPjSearch, #btnPjFilter, #btnPjSort, #btnDSearch, #btnDFilter, #btnDSort {
    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);
  }
  /* chỉ nút lọc mới có trạng thái bật/tắt — nút tìm/sắp xếp không đổi màu */
  #btnPjFilter.active, #btnDFilter.active { background: var(--bg-3); color: #b0abff; }
  #btnPjSearch.active, #btnDSearch.active { background: var(--bg-3); color: var(--txt); }
  /* ô 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; }
  #btnSelMode { height: var(--tap); padding: 0 13px; font-size: 13.5px; margin-left: auto; }

  /* ---------- 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, .45); 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 auto;
    gap: 3px 10px; padding: 10px 12px; min-height: 88px;
  }
  .frow-project .fl-thumb { grid-area: 1 / 1 / 4 / 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;
  }
  .frow-project .fl-status { grid-area: 2 / 2 / 3 / 3; }
  .frow-project .fl-status .chip { height: 18px; padding: 0 6px; font-size: 11px; }
  /* 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: 3; 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 / 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;
  }

  /* ---------- 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-status { grid-row: 3; grid-column: 2; justify-self: start; font-size: 11.5px; }
  #dList .fl-cmt { grid-row: 3; grid-column: 2; justify-self: center; 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-status .chip { height: 18px; padding: 0 6px; font-size: 11px; }
  #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; }
  /* huy hiệu trạng thái ở góc trái, nút ⋯ ở góc phải — không giẫm chân nhau */
  .tile .badges { top: 8px; left: 8px; gap: 5px; }
  .tile-menu, .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;
  }
  /* chế độ chọn: ô tích thay chỗ nút ⋯ */
  #dGrid .tile .checkbox { opacity: 0; pointer-events: none; }
  body.sel-mode #dGrid .tile .checkbox {
    opacity: 1; pointer-events: auto;
    width: 32px; height: 32px; border-radius: 8px; top: 8px; right: 8px; left: 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 .2s cubic-bezier(.22, .8, .2, 1);
  }
  .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; }
  /* 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 cubic-bezier(.22, .8, .2, 1);
    padding-bottom: var(--safe-b);
  }
  .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 cubic-bezier(.22, .8, .2, 1);
    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: 100%; 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; }
  /* Project Settings: ảnh bìa và các ô nhập xếp dọc thay vì hai cột */
  .psettings { grid-template-columns: 1fr; gap: 16px; }
  .ps-cover { width: 96px; aspect-ratio: 1; }
  .ps-row { min-height: 48px; align-items: center; }
  .ps-row input[type="checkbox"] { width: 22px; height: 22px; margin-top: 0; }
  /* Modal Tạo link chia sẻ: checkbox hệ điều hành 13px → 24px, mỗi hàng cao 48px */
  #mBody label.row { min-height: 48px; }
  #mBody label.row input[type="checkbox"] { width: 24px; height: 24px; flex: none; }

  /* ---------- phản hồi & link chia sẻ ---------- */
  #tabFeedback .toolbar { gap: 8px; }
  /* ảnh trong danh sách phản hồi: 96px → 76px cho vừa 390 */
  .fb-thumb { width: 76px !important; height: 76px !important; }

  #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 thead { display: none; }
  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; }
  table.tbl td .row { gap: 8px; margin-top: 8px; }
  table.tbl td .row .btn { flex: 1; height: var(--tap); justify-content: center; }
}

/* ============================================================
   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,
.lb.draw-mode .vcenter-play { 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 (window.createCompareView trong thread.js) ---------- */
.cmp-overlay {
  position: fixed; inset: 0; z-index: 200; background: #08090c;
  display: none; grid-template-rows: var(--header-h) minmax(0, 1fr) auto;
}
.cmp-overlay.open { display: grid; }
.cmp-head {
  display: flex; align-items: center; gap: 12px; padding: 0 14px;
  border-bottom: 1px solid var(--line-soft); background: var(--bg-1);
}
.cmp-labels { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--txt-2); overflow: hidden; }
.cmp-labels .cmp-a, .cmp-labels .cmp-b { color: var(--txt); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-stage { position: relative; min-height: 0; overflow: hidden; background: #000; }
.cmp-img-slider { position: absolute; inset: 0; overflow: hidden; touch-action: none; cursor: ew-resize; }
.cmp-img-a, .cmp-img-b { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; user-select: none; pointer-events: none; }
/* KHÔNG đặt position:absolute cho .cmp-img-b-clip — để .cmp-img-b (position:absolute; inset:0)
   lấy .cmp-img-slider (khung ngoài) làm mốc toạ độ thay vì lấy đúng khung clip 50% này, nếu
   không ảnh B sẽ bị co lại theo đúng bề rộng đang bị cắt thay vì lộ dần đúng vị trí thật. */
.cmp-img-b-clip { width: 50%; height: 100%; overflow: hidden; }
.cmp-handle {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 3px; margin-left: -1.5px;
  background: #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .4); pointer-events: none;
}
.cmp-handle::after {
  content: '⟷'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 30px; height: 30px; border-radius: 50%; background: #fff; color: #111;
  display: grid; place-items: center; font-size: 14px; box-shadow: 0 2px 8px rgba(0, 0, 0, .4);
}
.cmp-vid-row { position: absolute; inset: 0; display: flex; gap: 2px; background: #000; }
.cmp-vid-row video { flex: 1; min-width: 0; width: 100%; height: 100%; object-fit: contain; background: #000; }
.cmp-scrub { position: static; }
