/* Shared components — buttons, chips, cards, pills, inputs, lists. */

/* Buttons */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-2); border: 1px solid var(--line-1);
  color: var(--tx-2); padding: 6px 12px;
  border-radius: var(--r-2); font-size: 13px; font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.btn:hover { background: var(--bg-3); color: var(--tx-1); border-color: var(--line-2); }
.btn:disabled { opacity: .55; cursor: default; }
.btn svg { width: 14px; height: 14px; }
.btn-primary { background: var(--ac); color: var(--on-ac); border-color: var(--ac); }
.btn-primary:hover { background: var(--ac-h); color: var(--on-ac); }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--bg-2); }
.btn-danger { background: var(--danger-dim); color: var(--danger); border-color: transparent; }
/* Nút chỉ có icon: TRÒN như Telegram (họ bo 50% cho toàn bộ nút icon — 141 phần tử).
   Cần cả width/height cố định, nếu không `border-radius:50%` trên hộp chữ nhật ra hình bầu dục. */
.btn-icon {
  padding: 0; width: 32px; height: 32px; flex: 0 0 32px;
  justify-content: center; border-radius: var(--r-tron);
}
/* Bàn phím: viền focus rõ cho control lưu lượng cao thiếu focus-visible sẵn */
.btn:focus-visible,
.filter-chip:focus-visible,
.mode-switch button:focus-visible { outline: 2px solid var(--ac); outline-offset: 2px; }

/* Input */
.input {
  background: var(--bg-2); border: 1px solid var(--line-1);
  color: var(--tx-1); padding: 6px 12px;
  border-radius: var(--r-2); font-size: 13.5px;
  transition: border-color var(--dur-1);
}
.input:focus { outline: none; border-color: var(--ac); }
.input::placeholder { color: var(--tx-4); }

/* Search input with icon */
.search { position: relative; }
.search input { padding-left: 30px; width: 260px; }
/* Không đổi width khi focus — trước đây 240->300px xô đẩy các nút bên phải topbar */
.search input:focus { width: 260px; }
.search .ic { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); color: var(--tx-4); pointer-events: none; }
.search .ic svg { width: 14px; height: 14px; }
.search kbd {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  padding: 1px 5px; border-radius: 4px; background: var(--bg-3);
  border: 1px solid var(--line-2); font-family: var(--f-mono);
  font-size: 11px; color: var(--tx-3);
}

/* Chip / Pill */
.chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 20px;
  font-size: 12px; font-weight: 600; line-height: 1.6;
  background: var(--bg-3); color: var(--tx-2);
  font-variant-numeric: tabular-nums;
}
.chip.p0 { background: var(--danger-dim); color: var(--danger); }
.chip.p1 { background: var(--orange-dim); color: var(--orange); }
.chip.p2 { background: var(--warn-dim); color: var(--warn); }
.chip.p3 { background: var(--bg-3); color: var(--tx-3); }
.chip.ok { background: var(--ok-dim); color: var(--ok); }
.chip.warn { background: var(--warn-dim); color: var(--warn); }
.chip.danger { background: var(--danger-dim); color: var(--danger); }
.chip.info { background: var(--info-dim); color: var(--info); }
.chip.vip { background: var(--vip-dim); color: var(--vip); }
.chip.dim { background: var(--bg-3); color: var(--tx-3); }

/* Card */
.card {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-4);
  padding: var(--sp-4);
}
.card.pad-lg { padding: var(--sp-5); }
.card > h3 {
  margin: 0 0 var(--sp-3);
  font-size: 13.5px; font-weight: 600;
  color: var(--tx-2); letter-spacing: .01em;
  display: flex; align-items: center; gap: 8px;
}
.card > h3 .tag { color: var(--tx-4); font-weight: 400; font-size: 12px; }

/* Panel (exception list) */
.panel {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-4);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.panel .ph {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px; border-bottom: 1px solid var(--line-1);
  font-size: 13.5px; font-weight: 600; color: var(--tx-1);
  background: var(--bg-2);
}
.panel .ph .n {
  margin-left: auto; font-size: 12px; font-variant-numeric: tabular-nums;
  background: var(--bg-3); color: var(--tx-3);
  padding: 1px 8px; border-radius: 20px;
}
.panel .pb { padding: 6px; max-height: 320px; overflow: auto; }

.item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--r-2);
  cursor: pointer;
  transition: background var(--dur-1);
}
.item:hover { background: var(--bg-2); }
.item .nm { font-weight: 500; color: var(--tx-1); font-size: 13.5px; }
.item .mt { color: var(--tx-3); font-size: 12px; margin-top: 2px; }
.item > div:first-child { flex: 1; min-width: 0; overflow: hidden; }
.item .nm.truncate { max-width: 100%; }

/* KPI card */
.kpi-grid {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin-bottom: var(--sp-5);
}
.kpi {
  background: var(--bg-1); border: 1px solid var(--line-1);
  border-radius: var(--r-4); padding: 14px 16px;
  display: flex; flex-direction: column; gap: 4px;
  position: relative; overflow: hidden;
}
.kpi .ic {
  width: 30px; height: 30px; border-radius: var(--r-2);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-3); color: var(--tx-2);
  margin-bottom: 2px;
}
.kpi .ic svg { width: 16px; height: 16px; }
.kpi .v { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.kpi .l { color: var(--tx-2); font-size: 13px; font-weight: 500; }
.kpi .sub { color: var(--tx-4); font-size: 12px; }
.kpi.alert .ic { background: var(--danger-dim); color: var(--danger); }
.kpi.warn .ic { background: var(--warn-dim); color: var(--warn); }
.kpi.ok .ic { background: var(--ok-dim); color: var(--ok); }
.kpi.info .ic { background: var(--info-dim); color: var(--info); }
.kpi.vip .ic { background: var(--vip-dim); color: var(--vip); }

/* Bar / meter */
.hbar { background: var(--bg-3); border-radius: 20px; height: 6px; overflow: hidden; position: relative; }
.hbar i { display: block; height: 100%; background: var(--ac); transition: width var(--dur-3) var(--ease); }

/* Section header */
.sh {
  font-size: 13.5px; font-weight: 600; color: var(--tx-1);
  margin: var(--sp-5) 0 var(--sp-3);
  display: flex; align-items: center; gap: 10px;
}
.sh .tag {
  color: var(--tx-4); font-weight: 400; font-size: 12px;
  padding: 1px 8px; border: 1px solid var(--line-1); border-radius: 20px;
}

/* Layouts */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); }
.grid-2-3 { display: grid; grid-template-columns: 2fr 1fr; gap: var(--sp-4); }

/* Empty state */
.empty {
  padding: var(--sp-4); text-align: center; color: var(--tx-3);
  font-size: 13px; border: 1px dashed var(--line-2); border-radius: var(--r-3);
}

/* Reply-mode popover (topbar) */
.rp-anchor { position: relative; }
.rp-popover {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 360px; background: var(--bg-1);
  border: 1px solid var(--line-2); border-radius: var(--r-4);
  box-shadow: var(--sh-3); z-index: 40;
  display: none;
}
.rp-popover.on { display: block; animation: fadein var(--dur-2) var(--ease); }
.rp-popover .rp-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px; border-bottom: 1px solid var(--line-1);
  font-size: 13.5px;
}
.rp-popover .rp-body { padding: 10px; display: flex; flex-direction: column; gap: 6px; }
.rp-popover .rp-radio {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; border: 1px solid var(--line-1);
  border-radius: var(--r-2); cursor: pointer;
  transition: border-color var(--dur-1), background var(--dur-1);
}
.rp-popover .rp-radio:hover { background: var(--bg-2); }
.rp-popover .rp-radio.on { border-color: var(--ac); background: var(--ac-dim); }
.rp-popover .rp-radio.danger.on { border-color: var(--danger); background: var(--danger-dim); }
.rp-popover .rp-radio input { margin-top: 3px; accent-color: var(--ac); }
.rp-popover .rp-radio .lbl { font-size: 13.5px; font-weight: 600; color: var(--tx-1); display: flex; align-items: center; gap: 6px; }
.rp-popover .rp-radio .lbl .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.rp-popover .rp-radio .lbl .dot.ok { background: var(--ok); }
.rp-popover .rp-radio .lbl .dot.warn { background: var(--warn); }
.rp-popover .rp-radio .lbl .dot.danger { background: var(--danger); }
.rp-popover .rp-radio .desc { color: var(--tx-3); font-size: 12px; margin-top: 3px; line-height: 1.5; }
.rp-popover .rp-foot {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 14px; border-top: 1px solid var(--line-1);
}

/* Toast — phản hồi dùng chung, kèm nút Hoàn tác.
 *
 * ĐỔI TỪ ĐÁY LÊN ĐỈNH ngày 05/08. Ở `bottom: 24px` nó nằm ĐÚNG trên ô soạn tin của màn Chat —
 * hai thứ cùng canh giữa, cùng sát đáy. Đo trên ảnh chụp production: dải "Còn 20 tin chưa dịch
 * được — bấm Dịch từng tin để thử lại" che mất một phần ô "Trả lời khách…".
 *
 * Đây là ca xấu nhất của va chạm: toast CẢNH BÁO (hiện lâu hơn toast thường) đè lên đúng thứ NV
 * cần dùng ngay sau khi đọc nó. Không ai báo lỗi vì tin vẫn gõ được — chỉ là vướng.
 *
 * Đỉnh màn hình không có gì để va: thanh trên cao 56px, panel tìm kiếm nằm bên PHẢI. */
.toast {
  position: fixed; left: 50%; top: 68px; transform: translateX(-50%) translateY(-80px);
  display: flex; align-items: center; gap: 12px;
  background: var(--bg-3); color: var(--tx-1); border: 1px solid var(--line-2);
  padding: 10px 16px; border-radius: var(--r-3); font-size: 13.5px;
  box-shadow: var(--sh-3); z-index: 200; opacity: 0;
  transition: transform var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease);
  pointer-events: none;
}
.toast.on { transform: translateX(-50%) translateY(0); opacity: 1; pointer-events: auto; }
.toast.error { border-color: var(--danger); color: var(--danger); }
.toast-undo {
  border: 0; background: var(--ac-dim); color: var(--ac-h); font-weight: 600;
  padding: 4px 10px; border-radius: var(--r-2); cursor: pointer; font-size: 13px;
}
.toast-undo:hover { background: var(--ac); color: #fff; }

/* Chips carrying an inline SVG icon (semChip) */
.chip svg { margin-right: 4px; vertical-align: -1px; }

/* Chip tác vụ CS theo nhóm ①-⑥ */
.chip.tg { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip.tg-1 { background: var(--tg-1-dim); color: var(--tg-1); }
.chip.tg-2 { background: var(--tg-2-dim); color: var(--tg-2); }
.chip.tg-3 { background: var(--tg-3-dim); color: var(--tg-3); }
.chip.tg-4 { background: var(--tg-4-dim); color: var(--tg-4); }
.chip.tg-5 { background: var(--tg-5-dim); color: var(--tg-5); }
.chip.tg-6 { background: var(--tg-6-dim); color: var(--tg-6); }
.filter-chip[class*="tg-f-"].on { outline: 1px solid var(--ac); }

/* ============ Avatar — hệ 8 màu gradient kiểu Telegram ============
   Telegram gán cố định 1 trong 8 cặp gradient cho mỗi liên hệ (--peer-avatar-*-top/bottom).
   Trong danh sách dài, màu là công cụ QUÉT MẮT: nhận ra khách quen mà không phải đọc chữ.

   MÀU ĐÃ TỐI ĐI so với bản gốc của họ, cố ý. Đo 29/07/2026: chữ trắng trên CẢ 8 cặp gradient
   gốc của Telegram đều KHÔNG đạt 4.5:1 — thấp nhất là cyan 1.45:1, cao nhất cũng chỉ 4.12:1.
   Giữ nguyên tông màu, tối đi 29–45% để chữ trắng đọc được (nay 4.52–4.58:1 ở điểm sáng nhất).
   Đây đúng ranh giới đã ghi ở docs: bố cục/bo góc học Telegram, tương phản học Facebook. */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-tron); flex: 0 0 auto;
  background: var(--bg-3); color: var(--tx-2);
  font-weight: 600;
  /* KHÔNG `overflow: hidden`: badge số tin chưa đọc (.cv-unread-n) cố ý thò ra ngoài
     avatar bằng `bottom:-2px; right:-4px` — cắt là mất luôn chấm đỏ đếm tin. */
  /* Cỡ MẶC ĐỊNH bắt buộc: `border-radius: 50%` trên hộp không vuông ra hình BẦU DỤC.
     staff.js:121 gọi `.avatar` mà không có rule cỡ nào -> méo. Chỗ nào cần cỡ khác thì
     ghi đè width/height, nhưng không bao giờ rơi vào trạng thái không-có-cỡ nữa. */
  width: 32px; height: 32px; font-size: 13px;
}
.avatar.av-1 { background: linear-gradient(#b55e43, #973a32); color: #fff; }  /* đỏ */
.avatar.av-2 { background: linear-gradient(#966e36, #914c20); color: #fff; }  /* cam */
.avatar.av-3 { background: linear-gradient(#8169b1, #4d459e); color: #fff; }  /* tím */
.avatar.av-4 { background: linear-gradient(#5e7f3d, #2b7129); color: #fff; }  /* xanh lá */
.avatar.av-5 { background: linear-gradient(#2e8276, #166f65); color: #fff; }  /* cyan */
.avatar.av-6 { background: linear-gradient(#407aaf, #2d6191); color: #fff; }  /* xanh dương */
.avatar.av-7 { background: linear-gradient(#ad5e75, #943a4f); color: #fff; }  /* hồng */
.avatar.av-8 { background: linear-gradient(#70767c, #60686e); color: #fff; }  /* xám */

/* Banner "đồng nghiệp cũng đang mở hội thoại này" — CẢNH BÁO, không phải lỗi.
   Dùng --warn chứ không --danger: đây là thông tin để hai người tự thu xếp, không phải hệ thống
   hỏng. Tô đỏ là NV học cách bỏ qua màu đỏ, rồi bỏ qua cả cảnh báo thật. */
.hien-dien {
  margin: var(--sp-2) var(--sp-4) 0;
  padding: 6px 10px;
  border-radius: var(--r-2);
  background: var(--warn-dim, var(--bg-3));
  color: var(--warn, var(--tx-2));
  font-size: 12px;
}
/* `display` của khối trên là block mặc định nên `hidden` tự ăn. Vẫn ghi rõ để lần sau ai đổi sang
   flex thì không lặp lại lỗi #mau/#soan — hidden bị display:flex đè, đã dính 2 lần. */
.hien-dien[hidden] { display: none; }

/* ── Tìm kiếm toàn văn (T4.1) ─────────────────────────────────────────────────
   Panel thả xuống dưới ô #q. `.search` phải là mốc định vị, nếu không panel bay
   về góc trên trái trang. */
.search { position: relative; }
.tim-panel {
  position: absolute; top: calc(100% + 6px); right: 0;
  width: min(560px, 92vw); max-height: min(70vh, 620px); overflow-y: auto;
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: var(--r-2);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .38);
  z-index: 60;   /* trên cockpit chat, dưới modal */
}
/* `hidden` một mình KHÔNG đủ: bất kỳ `display:` nào cũng đè nó. Đã cắn 3 lần ở repo này. */
.tim-panel[hidden], .tim-panel:not(.mo) { display: none; }
.tim-dau {
  position: sticky; top: 0; z-index: 1;
  padding: 8px var(--sp-3) 4px; background: var(--bg-2);
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--tx-4); border-bottom: 1px solid var(--line-1);
}
.tim-dong {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 8px var(--sp-3); background: none; border: 0; border-bottom: 1px solid var(--line-1);
  color: var(--tx-1); font: inherit;
}
button.tim-dong:hover, button.tim-dong:focus-visible { background: var(--bg-3); }
.tim-nhan { display: block; font-weight: 500; }
/* Đoạn trích có thể dài — cắt 2 dòng, đừng để một kết quả đẩy hết phần còn lại xuống dưới. */
.tim-phu {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin-top: 2px; color: var(--tx-3); font-size: 12px; line-height: 1.45;
}
/* Dòng không mở được (thiếu cid) — nhìn phải KHÁC dòng bấm được, đừng để NV bấm vào khoảng không. */
.tim-cam { cursor: default; opacity: .62; }
.tim-hieu { float: right; margin-left: var(--sp-2); color: var(--tx-4); font-size: 11px; }
.tim-rong { padding: var(--sp-4); color: var(--tx-3); text-align: center; }
/* Trần quét phải NÓI RA. Cắt im lặng nghĩa là NV tin "chỉ có ngần này" rồi ngừng tìm. */
.tim-tran {
  padding: 8px var(--sp-3); background: rgba(255, 176, 32, .08);
  border-top: 1px solid var(--line-2); color: var(--warn); font-size: 12px;
}

/* Xác nhận LIVE dùng chung cho BotView và công tắc Reply ở topbar.
   Mount tại body, cao hơn toast/popover để không bị cắt bởi view có overflow. */
.live-confirm-scrim {
  position: fixed; inset: 0; z-index: 260;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-4); background: rgba(5, 10, 18, .68);
  backdrop-filter: blur(2px);
}
.live-confirm-dialog {
  width: min(440px, 100%); max-height: calc(100vh - 32px); overflow-y: auto;
  padding: var(--sp-5); border: 1px solid var(--line-2); border-radius: var(--r-4);
  background: var(--bg-2); color: var(--tx-1); box-shadow: var(--sh-3);
}
.live-confirm-dialog h2 { margin: 0 0 var(--sp-2); font-size: 18px; line-height: 1.35; }
.live-confirm-description { margin: 0 0 var(--sp-3); color: var(--tx-3); font-size: 13px; line-height: 1.55; }
.live-confirm-warning {
  margin-bottom: var(--sp-4); padding: 9px 10px; border: 1px solid var(--danger);
  border-radius: var(--r-2); background: var(--danger-dim); color: var(--danger);
  font-size: 12.5px; line-height: 1.45;
}
.live-confirm-label { display: block; margin-bottom: 6px; color: var(--tx-2); font-size: 12.5px; font-weight: 600; }
.live-confirm-input { width: 100%; font-family: var(--f-mono); letter-spacing: .08em; }
.live-confirm-input[aria-invalid="true"] { border-color: var(--danger); }
.live-confirm-status { min-height: 20px; padding-top: 4px; color: var(--danger); font-size: 12px; }
.live-confirm-actions { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: var(--sp-3); }
.live-confirm-actions .btn:disabled { cursor: not-allowed; opacity: .48; }

@media (max-width: 520px) {
  .live-confirm-scrim { align-items: flex-end; padding: var(--sp-2); }
  .live-confirm-dialog { width: 100%; padding: var(--sp-4); border-radius: var(--r-4) var(--r-4) var(--r-2) var(--r-2); }
  .live-confirm-actions .btn { min-height: 42px; }
}
