/* =============================================================================
 * bulbal-dialogs.css — HỘP THOẠI & LỚP PHỦ của Bulbal Chat (nạp SAU
 * bulbal-tokens/shell/contacts/messages/composer/forms/panels — thắng cascade
 * nhờ thứ tự nạp, KHÔNG dùng !important).
 *
 * Sở hữu độc quyền: alert.jsx (.alert-container/.alert), forward-dialog.jsx
 * (.forward-dialog), invitation.jsx (.accept-invite-panel), phần "chưa ai
 * style" của context-menu.jsx (ul.menu, đã có chủ bulbal-panels.css — đợt 2),
 * vỏ ngoài permissions-editor.jsx (.permission-editor, TRỪ .contact-box*,
 * .panel-form-column, .dialog-buttons, .checkbox — các phần đó có chủ khác),
 * toàn bộ cropper.jsx (.cropper và mọi lớp con — trước đợt này 100% CSS gốc
 * Tinode, xem §6), phần "chưa ai style" của error-panel.jsx (.info-box .icon,
 * .info-box .cancel — .info-box/.info-box.error/.warning/.info ĐÃ có chủ
 * bulbal-shell.css + bulbal-panels.css, CẤM đụng), và .loader-spinner của
 * load-spinner.jsx.
 *
 * KHÔNG style ở đây (dù widget nằm trong phạm vi phase): .dialog-buttons,
 * button/button.primary/.outline/.secondary (bulbal-forms.css — đợt 2),
 * .contact-box* kể cả .small (phase 03 — cùng đợt 3), ul.menu/ul.menu>li* nền
 * -viền-hover-separator-disabled (bulbal-panels.css — đợt 2, xem §4),
 * .info-box/.info-box.error/.danger/.warning/.info (bulbal-shell.css +
 * bulbal-panels.css), .panel-form-column/.checkbox trong permission-editor.
 *
 * PHÁT HIỆN đáng chú ý khi đọc mã nguồn (ghi chi tiết trong report kèm phase):
 * 1) error-panel.jsx dòng 32-34: className thật render ra là
 *    "info-box error" / "info-box warning" / "info-box info" (KHÔNG PHẢI
 *    "info-box danger" như phỏng đoán ban đầu) — nhưng bulbal-panels.css đã
 *    phòng cả 2 tên (.info-box.error, .info-box.danger) nên vẫn khớp, không
 *    có lỗ hổng.
 * 2) cropper.jsx dòng 279 render <input className="zoomer">, còn base.css
 *    dòng 3310 chỉ có rule `.cropper .zoom` (không có "er") ⇒ DEAD SELECTOR,
 *    thanh trượt phóng to CHƯA TỪNG được style — trình duyệt vẽ range mặc
 *    định. Viết mới hoàn toàn ở §6.
 * 3) base.css dòng 3267 dùng `var(--clr-shadow-cropper-gray)` nhưng biến này
 *    KHÔNG được khai báo ở bất kỳ đâu trong file ⇒ toàn bộ khai báo
 *    `box-shadow` của `.bounding-box` vô hiệu (giá trị không hợp lệ tại thời
 *    điểm tính toán ⇒ rơi về `none`) — khung crop hiện KHÔNG có đổ bóng dù
 *    code viết như có. Vá ở §6.
 * ============================================================================= */

/* ── 1. ALERT — hộp thoại xác nhận (alert.jsx) ──────────────────────────────
 * DOM: .alert-container (lớp phủ toàn màn hình) > .alert (khung trắng/tối) >
 * .title + .content + .dialog-buttons (dialog-buttons đã có chủ forms.css).
 * base.css: div.alert-container{align-items:center;background:var(--clr-alert
 * -overlay-bg)} — màu nền lớp phủ ĐÃ light-dark() theo chế độ, giữ nguyên
 * (không hardcode lại), chỉ BỔ SUNG backdrop-filter mờ nhẹ (thuộc tính base.css
 * chưa từng khai) đúng ý đồ "lớp phủ nền mờ tối" — bọc @supports vì máy yếu/
 * điện thoại cũ của công nhân có thể không hỗ trợ (Risk R3 trong phase file). */
.alert-container {
  padding: 16px;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .alert-container {
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
  }
}

/* div.alert-container.title{color:var(--clr-primary-accent)} đã bridge đúng
 * --bb-brand/--bb-brand-600 (tokens.css dòng 154) — KHÔNG phải màu gốc lòi ra,
 * nên KHÔNG đổi màu tiêu đề. Chỉ chỉnh cỡ chữ/độ đậm theo đúng thang chữ mới
 * (--bb-fs-title/600) như "Ý đồ thiết kế" yêu cầu.
 * Selector dùng `div.alert` để TRÙNG specificity (0,1,1) với base.css
 * (div.alert{...}) — thắng nhờ nạp SAU (thứ tự nguồn), không cần !important,
 * đúng quy ước đã dùng ở bulbal-forms.css (xem comment dòng 314-316 file đó). */
div.alert {
  border-radius: var(--bb-r-row);
  box-shadow: var(--bb-sh-3);
}

/* `div.alert > .title` = (0,2,1), trùng specificity với base.css
 * `div.alert-container .title` (cũng 0,2,1) ⇒ thắng nhờ nạp sau — vẫn CHỈ nhắm
 * đúng tiêu đề của alert.jsx (con trực tiếp của .alert), KHÔNG lấn sang
 * .forward-dialog .title.with-control (con của .forward-dialog, không phải
 * .alert) dù cả 2 cùng nằm trong .alert-container. */
div.alert > .title {
  font-size: var(--bb-fs-title);
  font-weight: 600;
}

/* .content: màu chữ ĐÃ đúng --bb-txt-1 qua kế thừa toàn cục
 * (html,body{color:var(--clr-text-primary)} base.css dòng 305, bridge tokens
 * dòng 189) — không khai báo lại màu (tránh lặp vô nghĩa). Chỉ chỉnh dòng chữ
 * cho dễ đọc hơn cỡ mặc định trình duyệt. */
div.alert > .content {
  font-size: var(--bb-fs-base);
  line-height: 1.5;
}

/* ── 2. FORWARD DIALOG — chuyển tiếp tin nhắn (forward-dialog.jsx) ──────────
 * DOM: .alert-container > .forward-dialog > .title.with-control (+ nút đóng)
 * + SearchContacts + ContactList (2 widget con là phạm vi Phase 03). */
.forward-dialog {
  border-radius: var(--bb-r-row);
  box-shadow: var(--bb-sh-3);
}

/* Tiêu đề: cùng lý do với mục 1 — màu đã bridge đúng, chỉ chỉnh cỡ chữ/đậm.
 * Specificity (0,3,0) > (0,2,1) của base.css `div.alert-container .title`
 * (3 class thắng 2 class bất kể số tag) ⇒ thắng cả khi không nạp sau. */
.forward-dialog .title.with-control {
  font-size: var(--bb-fs-title);
  font-weight: 600;
}

/* Nút đóng (X) — bọc vùng chạm ≥44px (yêu cầu "nút đóng ≥44px" trong Ý đồ
 * thiết kế) quanh <a> chứa icon; icon chỉ đổi màu, không đụng .material-icons
 * kích thước gốc (kế thừa từ rule .material-icons toàn cục, base.css dòng
 * 2988). `a` là con của .title.with-control, nằm trong phạm vi được giao. */
.forward-dialog .title.with-control a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--bb-touch);
  height: var(--bb-touch);
  border-radius: 50%;
  transition: background-color var(--bb-dur) var(--bb-ease);
}

.forward-dialog .title.with-control a:hover {
  background-color: var(--bb-hover);
}

.forward-dialog .material-icons {
  color: var(--bb-txt-2);
  transition: color var(--bb-dur) var(--bb-ease);
}

.forward-dialog .title.with-control a:hover .material-icons {
  color: var(--bb-txt-1);
}

/* ── 3. LỜI MỜI TRÒ CHUYỆN MỚI (invitation.jsx) ─────────────────────────────
 * DOM: .accept-invite-panel > .title + .footer > 3 button (.primary/.secondary
 * — cả 2 đều có chủ forms.css, xem Key Insight #3 phase file). Panel này thay
 * thế SendMessage ở CÙNG VỊ TRÍ footer (messages-view.jsx dòng 1833-1836) khi
 * topic chưa xác nhận — không phải modal, không dùng .alert-container.
 *
 * PHÁT HIỆN: nền gốc base.css dùng --clr-background-blue-gray-50 (bridge
 * tokens.css → --bb-hover, #F1F5F9 sáng) gần NHƯ TRÙNG MÀU với nền khung chat
 * phía sau --bb-bg-chat (#F5F7FB sáng) — 2 màu cách nhau quá ít, panel lời mời
 * gần như "biến mất" vào nền, mất phân cấp thị giác. Đổi sang --bb-bg-side
 * (trắng/tối đậm, cùng tông thẻ nổi với .alert/.forward-dialog) + viền trên
 * mỏng để tách lớp rõ ràng — không đụng .footer (nền phụ base.css vẫn ổn, để
 * nguyên tránh lặp không cần thiết). */
.accept-invite-panel {
  background-color: var(--bb-bg-side);
  box-shadow: 0 -1px 0 var(--bb-line);
}

.accept-invite-panel > .title {
  color: var(--bb-txt-1);
  font-size: var(--bb-fs-base);
  line-height: 1.5;
}

/* ── 4. MENU NGỮ CẢNH — BỔ SUNG (context-menu.jsx) ──────────────────────────
 * Đối chiếu bulbal-panels.css (dòng 242-304, đợt 2) trước khi viết — thuộc
 * tính ĐÃ bị chiếm trên `ul.menu`: min-width, padding, border-radius,
 * background-color, border, box-shadow; trên `ul.menu > li`: padding, margin,
 * border-radius, font-size, color, transition, hover/separator/disabled/danger
 * (kể cả biến thể mobile). `position`/`z-index` KHÔNG thiếu — base.css dòng
 * 594/602 đã đặt position:absolute + z-index:4, panels.css không đụng, vẫn
 * còn hiệu lực nguyên vẹn ⇒ KHÔNG cần bổ sung 2 thuộc tính này (khác với dự
 * đoán "nếu thiếu" trong Ý đồ thiết kế — ghi rõ vào report).
 * ⇒ Phần THẬT SỰ còn trống: hoạt ảnh xuất hiện (bulbal-panels.css chưa khai
 * animation trên ul.menu) + icon trong <li> (context-menu.jsx render() dòng
 * 538-555 hiện CHƯA có <li> nào chứa <i class="material-icons"> — giống hệt
 * tình trạng "chuẩn bị sẵn, đang vô tác dụng" mà panels.css đã làm với
 * li.danger, xem comment dòng 236-241 file đó). Viết PHÒNG SẴN, comment rõ. */
ul.menu {
  animation: bb-menu-in var(--bb-dur) var(--bb-ease);
  transform-origin: top left;
}

@keyframes bb-menu-in {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* Phòng sẵn cho icon trong mục menu — HIỆN VÔ TÁC DỤNG vì context-menu.jsx
 * chưa gắn <i class="material-icons"> vào bất kỳ <li> nào (đã đọc toàn bộ
 * render(), xác nhận). Không phải bịa — chỉ chuẩn bị đúng như panels.css đã
 * làm với li.danger, để khi JSX thêm icon là có màu/khoảng cách ngay. */
ul.menu > li > i.material-icons {
  font-size: 1.15rem;
  margin-right: 8px;
  vertical-align: text-bottom;
  color: var(--bb-txt-2);
}

/* ── 5. TRÌNH SỬA QUYỀN — vỏ ngoài (permissions-editor.jsx) ─────────────────
 * DOM: .panel-form-column (có chủ) > ul.contact-box.small (phase 03) +
 * table.permission-editor > thead/tbody > tr > td (td.checkbox có chủ khác,
 * TRỪ hẳn) + .dialog-buttons (có chủ forms.css). Việc thật của mình chỉ còn
 * đúng cái bảng — base.css (dòng 1073-1091) mới có width:100% + td margin
 * (margin trên td KHÔNG có tác dụng trong table layout, dead property của
 * chính base.css) + màu td.checkbox riêng (không đụng). */
table.permission-editor {
  border-collapse: collapse;
}

table.permission-editor th {
  color: var(--bb-txt-2);
  font-size: var(--bb-fs-meta);
  font-weight: 600;
  text-align: left;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--bb-line);
}

/* :not(.checkbox) — tránh tuyệt đối đụng ô td.checkbox (loại trừ theo yêu cầu
 * phase file), chỉ tô màu chữ + đệm cho ô tên quyền (J/R/W/P/A/S/D/O). */
table.permission-editor td:not(.checkbox) {
  color: var(--bb-txt-1);
  font-size: var(--bb-fs-base);
  padding: 6px 8px 6px 0;
}

/* ── 6. CROPPER — cắt/phóng ảnh đại diện (cropper.jsx) ──────────────────────
 * TRỌNG TÂM của phase: trước đợt này 100% chưa restyle, dùng thẳng biến gốc
 * Tinode (--clr-cropper-*), 2 trong số đó là DEAD (xem phát hiện #2, #3 ở đầu
 * file). avatar-crop.jsx sau khi trừ .panel-form/.panel-form-row/.dialog-
 * buttons (có chủ) thì KHÔNG còn gì để style — đúng như Câu hỏi 2 trong phase
 * file dự đoán, xác nhận ở đây, không bịa selector cho avatar-crop.jsx. */
.cropper {
  border-radius: var(--bb-r-row);
}

/* --clr-cropper-bounding-box-border đã bridge đúng --bb-brand qua
 * --clr-primary-action (tokens.css dòng 159) — KHÔNG đổi viền. box-shadow gốc
 * là DEAD (phát hiện #3) ⇒ thêm --bb-sh-2 để khung crop thật sự có đổ bóng.
 * background-color gốc dùng --clr-text-tertiary (xám trung tính, không theo
 * token) — đổi --bb-bg-chat để đồng bộ bề mặt còn hở khi ảnh nhỏ hơn khung. */
.cropper .bounding-box {
  border-radius: var(--bb-r-row);
  background-color: var(--bb-bg-chat);
  box-shadow: var(--bb-sh-2);
}

/* Cửa sổ cắt (vòng tròn nét đứt) — viền xám trung tính gốc đổi sang màu
 * thương hiệu để nổi bật rõ vùng sẽ được cắt, đúng tinh thần "vòng quay dùng
 * --bb-brand" áp dụng chung cho các control tương tác trong dialog.
 * box-shadow mask (tạo hiệu ứng làm mờ phần NGOÀI vòng tròn) giữ NGUYÊN kỹ
 * thuật spread 150rem + độ mờ 66% của base.css, chỉ đổi nguồn màu từ hex cứng
 * light-dark(rgb(230 246 255/66%), rgb(25 10 0/66%)) sang color-mix() dựng từ
 * token bề mặt (mỗi điểm dừng light-dark() lồng ở ĐÚNG 1 giá trị màu, giống
 * kỹ thuật --bb-bub-out trong tokens.css — không bọc cả hàm box-shadow). */
.cropper .cutout {
  border-color: var(--bb-brand);
  box-shadow: 0 0 150rem 150rem light-dark(
    color-mix(in srgb, var(--bb-bg-side) 66%, transparent),
    color-mix(in srgb, var(--bb-bg-chat) 66%, transparent)
  );
}
/* .cutout.circle: kế thừa nguyên trạng 2 rule trên (mọi element .cutout.circle
 * cũng khớp selector .cutout ở trên, do khớp nhiều lớp không loại trừ nhau).
 * border-radius:50% của base.css (dòng 3292-3294) giữ nguyên, không đụng. */

/* .overlay: vùng bắt sự kiện kéo/chạm trong suốt, khớp đúng vị trí/kích thước
 * ảnh qua inline style do JS tính (cropper.jsx dòng 264-269) — CỐ Ý không thêm
 * màu/viền ở đây vì sẽ đè lên ảnh xem trước, không có gì cần theme hoá. */

/* .preview: <img> thật, đã bị .bounding-box{overflow:hidden} cắt khung —
 * không cần viền/bóng riêng (sẽ trùng với viền của .bounding-box và bị cắt
 * mất một phần, gây lệch hình). CỐ Ý không thêm rule màu. */

/* .zoom-wrapper: chỉ là khung canh giữa (base.css: height/width/margin/text-
 * align), không có bề mặt riêng cần theme hoá — không thêm rule. */

/* .zoomer — PHÁT HIỆN #2: class thật trong JSX là "zoomer", base.css chỉ có
 * `.cropper .zoom` (thiếu "er") nên KHÔNG áp dụng — kể cả nếu tên đúng thì
 * rule gốc cũng chỉ có box-shadow:none + pointer-events:none (sẽ CHẶN thao
 * tác kéo trượt!) — không dùng lại, viết mới hoàn toàn theo ngôn ngữ thiết kế
 * mới (rãnh --bb-line, núm --bb-brand-600, giống thanh trượt volume Zalo). */
.cropper .zoomer {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: var(--bb-r-pill);
  background: var(--bb-line);
  outline: none;
  cursor: pointer;
}

.cropper .zoomer::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--bb-brand-600);
  box-shadow: var(--bb-sh-1);
  cursor: pointer;
  transition: transform var(--bb-dur) var(--bb-ease), background-color var(--bb-dur) var(--bb-ease);
}

.cropper .zoomer::-webkit-slider-thumb:hover {
  background: var(--bb-brand-700);
  transform: scale(1.1);
}

.cropper .zoomer::-moz-range-track {
  height: 4px;
  border-radius: var(--bb-r-pill);
  background: var(--bb-line);
}

.cropper .zoomer::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: var(--bb-brand-600);
  box-shadow: var(--bb-sh-1);
  cursor: pointer;
  transition: transform var(--bb-dur) var(--bb-ease), background-color var(--bb-dur) var(--bb-ease);
}

.cropper .zoomer::-moz-range-thumb:hover {
  background: var(--bb-brand-700);
  transform: scale(1.1);
}

.cropper .zoomer:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bb-brand) 30%, transparent);
}

/* ── 7. DẢI THÔNG BÁO — BỔ SUNG (error-panel.jsx) ───────────────────────────
 * CẤM tuyệt đối khai báo lại nền/viền/màu chữ của .info-box/.info-box.error/
 * .warning/.info (bulbal-shell.css dòng 138-151 + bulbal-panels.css dòng
 * 313-335, đợt 2) — CHỈ 2 phần con panels/shell CHƯA đụng: .icon và .cancel.
 *
 * PHÁT HIỆN: base.css (dòng 1289-1303) tự đặt màu HEX gốc Tinode riêng cho
 * icon với specificity (0,4,0) — CAO HƠN rule panels.css `.info-box.error
 * i.material-icons` (0,3,1) nên panels.css thua, icon vẫn lòi màu gốc dù nền/
 * chữ đã đổi đúng token (đã đo, xem report). Set `currentColor` ở ĐÚNG
 * specificity base.css dùng để thắng theo thứ tự nạp — icon tự động ăn theo
 * đúng màu --bb-danger/--bb-warn/--bb-info-txt mà panels/shell đã set trên
 * .info-box.<level>, không định nghĩa lại giá trị màu ở đây. */
.info-box .icon .material-icons {
  color: currentColor;
}

.info-box.error .icon .material-icons,
.info-box.warning .icon .material-icons,
.info-box.info .icon .material-icons {
  color: currentColor;
}

/* .cancel (nút đóng X, MenuCancel widget): CHỌN màu trung tính cho mọi mức độ
 * (không ăn theo currentColor như .icon) — nút đóng không phải tín hiệu cảnh
 * báo, tô đỏ/vàng theo mức dễ gây hiểu lầm "đây cũng là báo lỗi". base.css chỉ
 * tô đỏ riêng cho .error (dòng 1286-1287), .warning/.info rơi về xám mặc định
 * — KHÔNG NHẤT QUÁN giữa 3 mức. Thống nhất trung tính cho cả 3, có hover rõ
 * ràng + vùng chạm tròn (không ép đủ 44px vì đây là banner mảnh trong luồng
 * đọc, không phải hộp thoại nổi — 28px vẫn thoải mái chạm và không phá layout
 * banner cao ~40px, xem report mục "nút đóng ≥44px"). */
.info-box .cancel .material-icons {
  color: var(--bb-txt-2);
  transition: color var(--bb-dur) var(--bb-ease);
}

.info-box.error .cancel .material-icons {
  color: var(--bb-txt-2);
}

.info-box .cancel a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  transition: background-color var(--bb-dur) var(--bb-ease);
}

.info-box .cancel:hover .material-icons {
  color: var(--bb-txt-1);
}

.info-box .cancel a:hover {
  background-color: var(--bb-hover);
}

/* ── 8. VÒNG QUAY TẢI (load-spinner.jsx) ────────────────────────────────────
 * Chỉ sở hữu .loader-spinner (vòng quay) — KHÔNG đụng .load-spinner-box*
 * (khung tròn nền trắng bọc ngoài, không nằm trong Architecture của phase,
 * với lại đã bridge sẵn qua --clr-bright → --bb-bg-side, không lòi màu gốc).
 * --clr-spinner-active đã bridge đúng --clr-primary-action → --bb-brand
 * (không hỏng), nhưng viết lại tường minh theo đúng "vòng quay dùng --bb-brand
 * trên rãnh --bb-line" cho rõ ý đồ + thay --clr-spinner-track (xám không theo
 * token) bằng --bb-line. Keyframe ĐẶT TÊN MỚI tiền tố bb- (không dùng chung
 * @keyframes spin của base.css — yêu cầu bắt buộc của phase). */
.loader-spinner {
  border-color: var(--bb-line);
  border-top-color: var(--bb-brand);
  animation: bb-spin 1.5s linear infinite;
}

@keyframes bb-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* ── 9. Mobile ≤640px — hộp thoại nổi bám đáy, bo góc trên ──────────────────
 * Áp dụng cho .alert-container (dùng chung bởi alert.jsx + forward-dialog.jsx,
 * xem Key Insight #6 phase file — call-incoming.jsx cũng dùng class này nhưng
 * bị Phase 04 ẩn display:none nên không xung đột trình bày). */
@media (max-width: 640px) {
  .alert-container {
    align-items: flex-end;
    padding: 0;
  }

  div.alert {
    width: 100%;
    max-width: 100%;
    margin: 0;
    border-radius: var(--bb-r-row) var(--bb-r-row) 0 0;
  }

  .forward-dialog {
    width: 100%;
    margin: 0;
    border-radius: var(--bb-r-row) var(--bb-r-row) 0 0;
  }
}

/* ── 10. Tôn trọng prefers-reduced-motion — chỉ trong vùng sở hữu ───────────
 * ul.menu: tắt hoạt ảnh xuất hiện MỚI THÊM ở mục 4 (không đụng transition của
 * panels.css trên li, ngoài phạm vi sở hữu). .loader-spinner: KHÔNG tắt hẳn
 * animation (vòng quay là tín hiệu trạng thái thiết yếu, dừng hẳn sẽ trông như
 * treo/lỗi) — chỉ kéo dài chu kỳ để giảm cảm giác chuyển động nhanh. */
@media (prefers-reduced-motion: reduce) {
  ul.menu {
    animation: none;
  }

  .loader-spinner {
    animation-duration: 3s;
  }
}
