/* =============================================================================
 * bulbal-chat-extras.css — Phase 04 (đợt 3): khung chat phụ + lưới an toàn ẩn
 * giao diện gọi thoại/video. Nạp SAU css/base.css + bulbal-tokens.css + bulbal-
 * messages.css (thứ tự nạp do phase 06 quyết định khi wire index.html/-dev.html).
 *
 * Sở hữu độc quyền:
 *   1) Tin ghim: #pinned-wrapper, .pinned, .pinned-scroll (+ .dot/.adot),
 *      .pinned-menu (+ .menuTrigger.upper/.lower bên trong), .cancel
 *      (widgets/pinned-messages.jsx).
 *   2) Sửa tại chỗ: span.in-place-edit/div.in-place-edit (+ modifier .short/
 *      .disabled/.placeholder), input.in-place-edit, i.material-icons.light-gray
 *      KHÔNG có .clickable (widgets/in-place-edit.jsx).
 *   3) Ô mật khẩu hiện/ẩn: .group-focus, input.with-icon-right
 *      (widgets/visible-password.jsx).
 *   4) BỔ SUNG ô tích: .panel-form-row > i.material-icons.clickable — CHỈ vùng
 *      chạm + :focus-visible (widgets/checkbox.jsx, xem cảnh báo §4).
 *   5) side-navbar.jsx — KHÔNG viết gì, xem lý do ở cuối file.
 *   6) Lưới an toàn ẨN giao diện gọi (display:none), xem cảnh báo §6.
 *
 * CHỈ dùng var(--bb-*) khai báo ở bulbal-tokens.css — KHÔNG hardcode hex/rgba.
 * KHÔNG !important (không có thuộc tính nào trong file này trùng đúng thuộc
 * tính mà base.css đã ép !important ở các selector bên dưới, xem báo cáo kèm
 * phase — do đó không viện dẫn được ngoại lệ, cả file không dùng !important).
 *
 * Số đo tương phản (WCAG, relative luminance chuẩn, script scratch/scripts/
 * wcag-contrast.mjs) ghi đầy đủ trong report:
 * plans/20260729-1740-bulbal-chat-ui-dot3/reports/phase-04-chat-extras.md
 * ============================================================================= */

/* ═══════════════════════════════════════════════════════════════════════════
 * 1. TIN GHIM (pinned-messages.jsx) — trọng tâm phase
 *
 * DOM thật (đọc từ widgets/pinned-messages.jsx):
 *   #pinned-wrapper
 *     ├─ .cancel > a > i.material-icons          (isAdmin=true)
 *     │  | <div> > i.material-icons (không class riêng, isAdmin=false — BỎ, xem dưới)
 *     ├─ .pinned-scroll > div.dot|div.adot
 *     ├─ .pinned > p                              (nội dung tin ghim, click để nhảy tới)
 *     └─ .pinned-menu > span.menuTrigger.upper|.lower > a > i.material-icons
 *
 * LỆCH BẢNG KIẾN TRÚC CỦA PHASE (ghi rõ trong report):
 *   - Bảng gốc ghi ".pinned .menuTrigger.upper/.lower" và ".pinned .cancel" như
 *     thể là con của .pinned — thực tế cả 3 (.cancel/.pinned/.pinned-menu) là
 *     3 ANH EM cùng cấp trong #pinned-wrapper, không lồng nhau. Viết đúng theo
 *     DOM thật (câu 5 trong Requirements bắt buộc bám class thật).
 *   - ".pinned .timestamp": KHÔNG tồn tại. Đã đọc pinned-messages.jsx +
 *     lib/formatters.js (previewFormatter) — không nơi nào render span.timestamp
 *     bên trong .pinned. KHÔNG viết rule chết cho selector không có trong DOM.
 *
 * QUYẾT ĐỊNH THIẾT KẾ (khác với ý đồ "thanh ngang DƯỚI header" ghi trong phase
 * file) — GHI RÕ LỆCH MOCKUP: #pinned-wrapper vốn là 1 flex-item NẰM TRONG
 * #topic-caption-panel (header), không phải phần tử độc lập bên dưới. Kéo nó
 * ra khỏi header bằng position:absolute là khả thi (header có position:relative
 * từ bulbal-shell.css) nhưng phase này BỊ CẤM mở trình duyệt để tự kiểm layout
 * sau khi đổi position — rủi ro vỡ chồng lớp (z-index header=4, li.meta=3,
 * overlap vùng tin nhắn) không thể tự xác minh. Chọn phương án AN TOÀN HƠN:
 * giữ nguyên vị trí trong luồng flex của header (đúng như base.css đã dựng,
 * ĐÃ CHẠY ổn định), chỉ đổi hình dạng thành 1 "viên thuốc" bo góc có vạch màu
 * thương hiệu bên trái — vẫn đúng tinh thần mockup (điểm nhấn rõ ràng, ellipsis,
 * menu mờ hiện khi hover) mà không đổi cơ chế định vị. Phase 06 verify bằng ảnh
 * thật; nếu muốn kéo xuống dưới header thật sự, cần thêm 1 vòng test browser.
 * ============================================================================= */
#pinned-wrapper {
  height: auto;
  min-height: 40px;
  margin: 0 8px 0 0;
  padding: 0;
  gap: 8px;
}

/* Viên thuốc chứa nội dung tin ghim — vạch trái --bb-brand thay cho khung đồng
 * màu cũ (--clr-background-off-white, gần trắng, mờ nhạt trên nền header xanh). */
.pinned {
  width: auto;
  flex: 1 1 220px;
  min-width: 0;
  max-width: 320px;
  height: auto;
  padding: 6px 10px 6px 12px;
  background: var(--bb-bg-side);
  border-left: 3px solid var(--bb-brand);
  border-radius: 10px;
  color: var(--bb-txt-1);
  transition: background-color var(--bb-dur) var(--bb-ease);
}

.pinned > p {
  margin: 0;
  font-size: var(--bb-fs-preview);
  color: var(--bb-txt-1);
  overflow-x: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pinned:hover {
  background: var(--bb-hover);
}

.pinned:active {
  background: var(--bb-sel);
  transition: background-color 0s;
}

/* Cột chấm điều hướng (nhiều tin ghim) — bỏ khối nền xám rời rạc cũ, để chấm
 * nổi trực tiếp trên header (màu dot/adot đã có sẵn qua cầu nối --clr-text-
 * tertiary/--clr-light-blue-accent ở bulbal-tokens.css, không đổi ở đây). */
.pinned-scroll {
  background: transparent;
  border-radius: 0;
  padding: 0 6px 0 0;
  margin-left: 0;
  height: auto;
  gap: 3px;
}

.pinned-scroll .dot,
.pinned-scroll .adot {
  transition: background-color var(--bb-dur) var(--bb-ease);
}

/* Nút hủy ghim (isAdmin=true) — vùng chạm chuẩn 44px + focus-visible bàn phím.
 * Nhánh isAdmin=false (div không class, chỉ icon push_pin tĩnh) CỐ Ý KHÔNG
 * style — không có hook selector an toàn để tách riêng khỏi các div khác
 * trong #pinned-wrapper mà không đoán mò cấu trúc, xem report mục "Bỏ qua". */
.cancel a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--bb-touch);
  height: var(--bb-touch);
  border-radius: 50%;
  color: var(--bb-txt-3);
  transition: background-color var(--bb-dur) var(--bb-ease), color var(--bb-dur) var(--bb-ease);
}

.cancel a:hover {
  background: var(--bb-hover);
  color: var(--bb-txt-1);
}

.cancel a:focus-visible {
  outline: 2px solid var(--bb-brand);
  outline-offset: -2px;
  border-radius: 50%;
}

/* Menu mờ (mũi tên lên/xuống chuyển tin ghim) — base.css đã có cơ chế mờ/hiện
 * khi hover cả cụm (#pinned-wrapper:hover .menuTrigger{opacity:.9}, dùng ID nên
 * thắng cascade bất kể thứ tự nạp file — CHẤP NHẬN, chỉ lệch 0.9 vs 1 lúc hover
 * trực tiếp, không đáng kể). Ở đây chỉ định lại kích thước/nền/viền-focus. */
.pinned-menu {
  background: transparent;
  border-radius: 0;
  gap: 2px;
  padding: 0 2px;
}

.pinned-menu .menuTrigger {
  width: 26px;
  height: 26px;
  line-height: 26px;
  opacity: .55;
  transition: opacity var(--bb-dur) var(--bb-ease), background-color var(--bb-dur) var(--bb-ease);
}

.pinned-menu .menuTrigger:hover {
  background: var(--bb-hover);
}

.pinned-menu .menuTrigger a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--bb-txt-2);
}

.pinned-menu .menuTrigger a:focus-visible {
  outline: 2px solid var(--bb-brand);
  outline-offset: -2px;
  border-radius: 6px;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * 2. SỬA TẠI CHỖ (in-place-edit.jsx)
 *
 * DOM thật: chế độ đọc = <span class="in-place-edit[.short][.disabled]
 * [.placeholder]"> (+ <i class="material-icons light-gray"> nếu có iconLeft/
 * iconRight — chỉ iconLeft thực sự được dùng, tại topic-desc-edit.jsx:363 cho
 * ô ID nhóm). Chế độ sửa = <input>/<textarea class="in-place-edit ...">.
 * base.css vẽ gạch chân đứt nét kiểu Material cũ — bỏ, thay affordance "bấm để
 * sửa" hiện đại: không viền tĩnh, nền mờ khi hover. CHỈ áp cho span/div (chế độ
 * đọc) — giữ nguyên input/textarea thật (bulbal-forms.css đợt 2 đã lo khung
 * viền/bo góc/focus cho input[type=text/password] nói chung, tránh chồng 2
 * nguồn margin khác nhau lên input thật).
 * ============================================================================= */
span.in-place-edit,
div.in-place-edit {
  border-bottom: none;
  border-radius: 8px;
  padding: 2px 6px;
  margin: 2px 0 0 -6px;
  transition: background-color var(--bb-dur) var(--bb-ease);
}

span.in-place-edit:hover,
div.in-place-edit:hover {
  background-color: var(--bb-hover);
}

/* .disabled (readOnly): base đã set cursor:default + border-bottom:none + màu
 * mờ riêng — không đổi màu ở đây (không phải cặp nền/chữ mới), chỉ tắt affordance
 * hover kế thừa từ rule chung ở trên (readOnly không nên gợi ý "bấm được"). */
span.in-place-edit.disabled:hover,
div.in-place-edit.disabled:hover {
  background-color: transparent;
}

/* Icon cạnh text (chỉ nhánh KHÔNG có .clickable — loại trừ icon con mắt của
 * visible-password.jsx cũng dùng chung .light-gray, xem báo cáo mục "Ranh giới
 * .light-gray"). Không đổi color (base.css:764 .light-gray{color:...!important}
 * đã bridge đúng qua --bb-txt-3 ở bulbal-forms.css, không cần viện dẫn ngoại lệ
 * !important vì không đụng thuộc tính color). */
i.material-icons.light-gray:not(.clickable) {
  font-size: 18px;
  vertical-align: -3px;
  margin: 0 4px;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * 3. Ô MẬT KHẨU HIỆN/ẨN (visible-password.jsx)
 *
 * DOM thật: <div class="group-focus"><input class="with-icon-right" ...>
 * <span onClick><i class="material-icons clickable light-gray">...</i></span>
 * </div>. base.css chỉ tắt outline trên .group-focus; icon "đè" lên input bằng
 * mẹo margin-right âm kiểu Material cũ (không khung) — bulbal-forms.css (đợt 2)
 * đã đổi input[type=password] sang khung bo góc/viền/focus-ring đầy đủ, mẹo
 * margin âm cũ sẽ đẩy icon nằm KHUẤT dưới viền phải khung mới ⇒ phải trung hoà
 * lại đúng 2 selector mình sở hữu (.with-icon-right, .group-focus), không đụng
 * thuộc tính border/radius/background của input (đã do bulbal-forms.css lo).
 * ============================================================================= */
.group-focus {
  position: relative;
  display: flex;
  align-items: center;
}

input.with-icon-right {
  margin-right: 0;
  padding-right: 42px;
  width: 100%;
}

.group-focus > span {
  position: absolute;
  right: 3px;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--bb-touch);
  cursor: pointer;
}

.group-focus > span:hover {
  background-color: var(--bb-hover);
  border-radius: 50%;
}

/* :focus-visible trên <span>: JSX hiện KHÔNG gắn tabIndex/role cho span này
 * (đọc widgets/visible-password.jsx — chỉ có onClick, không bàn phím tới được)
 * ⇒ rule này "ngủ" hôm nay, giữ sẵn phòng khi JSX bổ sung tabIndex (ngoài phạm
 * vi CSS, ghi vào report như giới hạn đã biết, không tự sửa JSX). */
.group-focus > span:focus-visible {
  outline: 2px solid var(--bb-brand);
  outline-offset: -2px;
  border-radius: 50%;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * 4. BỔ SUNG Ô TÍCH (checkbox.jsx) — vùng chạm + tiêu điểm bàn phím
 *
 * checkbox.jsx KHÔNG render class ".checkbox" — nó render <i class="material-
 * icons blue clickable"> (hoặc .lt-blue nếu tristate) là CON TRỰC TIẾP của
 * .panel-form-row (vd acc-security-view.jsx:127, info-view.jsx:697/707).
 *
 * PHÁT HIỆN LỖ HỔNG CHÉO (ghi rõ theo yêu cầu "trùng phạm vi → ghi report"):
 * bulbal-panels.css §4 (dòng ~179-197) viết rằng bulbal-forms.css ĐÃ có
 * `.panel-form-row > i.material-icons.clickable{width/height:var(--bb-touch);
 * border-radius:pill;hover/active}` — nhưng đọc thật bulbal-forms.css §6 (dòng
 * ~320-340) chỉ có `.panel-form-row:has(> i.material-icons.clickable) label
 * {cursor:pointer;font-size;margin:0}` (style CHO NHÃN, không phải icon). Cả
 * 2 file (viết song song đợt 2) đều GHI CHÚ "bên kia đã lo" nhưng thực tế
 * KHÔNG BÊN NÀO viết rule sizing/touch-area cho chính icon — đúng dạng lỗi
 * ".qr-code" đã từng sập, nhưng lần này KHÔNG được 2 agent kia tự phát hiện lại
 * (chỉ .qr-code được họ đối chiếu và vá ở forms.css dòng ~430). Phase 04 đã
 * được giao đúng phần "BỔ SUNG" này trong Architecture — lấp khoảng trống ở
 * đây. KHÔNG đổi color/background tĩnh (đã có qua cầu nối --clr-primary-accent
 * ở tokens.css) — chỉ kích thước vùng chạm + viền tiêu điểm.
 * Không dùng margin âm để "giấu" phần icon phóng to (không dùng !important
 * cũng không cần) — để .panel-form-row (min-height:26px, không phải height cố
 * định, xem bulbal-panels.css:45) tự giãn theo, giống cách a.flat-button
 * (min-height:46px) đã làm ở file đó — cùng 1 kiểu ứng xử, không phát minh
 * cách mới.
 * ============================================================================= */
.panel-form-row > i.material-icons.clickable {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--bb-touch);
  height: var(--bb-touch);
  border-radius: 50%;
}

.panel-form-row > i.material-icons.clickable:hover {
  background-color: var(--bb-hover);
}

/* :focus-visible: checkbox.jsx render <i onClick> không tabIndex/role="checkbox"
 * ⇒ hôm nay không bàn phím tới được (cùng giới hạn như mục 3) — giữ sẵn rule,
 * ghi vào report như giới hạn JSX ngoài phạm vi CSS. */
.panel-form-row > i.material-icons.clickable:focus-visible {
  outline: 2px solid var(--bb-brand);
  outline-offset: 2px;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * 5. side-navbar.jsx — KHÔNG VIẾT GÌ Ở ĐÂY
 *
 * Widget chỉ render 3 id/class: #side-caption-panel (className="caption-panel"),
 * #self-avatar (.avatar-box), #sidepanel-title (.panel-title). CẢ BA đã có chủ
 * TƯỜNG MINH ở bulbal-shell.css đợt 1 (xem header file đó: "Sở hữu: ...
 * #side-caption-panel (+ #self-avatar, #sidepanel-title)...") VÀ nằm trong
 * bảng "CẤM CHẠM" của chính phase file này. Không còn phần nào trống để phase
 * 04 scope riêng — bỏ hẳn mục 5, đúng hướng dẫn "Không scope được → bỏ, ghi lý
 * do" (Key Insight #4 + Unresolved question #2 của phase file).
 * ============================================================================= */

/* ═══════════════════════════════════════════════════════════════════════════
 * 6. LƯỚI AN TOÀN — ẨN HẲN GIAO DIỆN GỌI THOẠI/VIDEO (chưa có TURN server)
 *
 * NHẮC LẠI Key Insight #1 (KHÔNG phải lần đầu ẩn call): src/bulbal-config.js
 * đã có BULBAL_UI_SCOPE.hideCallButtons=true, dùng ở src/views/tinode-web.jsx:1840
 * (`webrtc = writer && iceServers && !hideCallButtons`) — mục menu "Gọi thoại/
 * Gọi video" ĐÃ bị chặn từ tầng logic. CSS dưới đây CHỈ là lưới an toàn cho 3
 * đường vào còn sót (không đi qua cờ trên): tin gọi CŨ trong lịch sử chat, cuộc
 * gọi đến từ client khác chưa cập nhật cờ, và UI cuộc gọi đang diễn ra nếu lỡ
 * vào được bằng đường khác. Ẩn bằng CSS KHÔNG PHẢI biện pháp bảo mật (Security
 * Considerations của phase file) — chỉ lớp phủ thẩm mỹ, chặn thật đã ở tầng logic.
 *
 * CROSS-SCOPE (bắt buộc khai báo — mọi dòng dưới đây chạm root KHÔNG thuộc sở
 * hữu của phase 04, CHỈ được phép vì toàn bộ đều là display:none, đúng "Ngoại
 * lệ có kiểm soát" của phase file):
 *   - #scroller > li:has(.call-message)  → root #scroller thuộc bulbal-messages.css
 *   - .call-message                       → widgets/call-message.jsx (tin gọi trong lịch sử)
 *   - .incoming-call                      → widgets/call-incoming.jsx (cuộc gọi đến)
 *   - #video-container                    → widgets/call-panel.jsx (KHÔNG có class
 *     ".call-panel" thật nào trong DOM — bảng kiến trúc phase ghi nhầm tên lớp;
 *     root THẬT của widget là id "video-container", xem call-panel.jsx dòng 663)
 *   - .caller-card, .caller-name          → dùng chung bởi cả call-panel.jsx VÀ
 *     call-incoming.jsx — đã grep xác nhận không nơi nào khác trong src/ dùng
 *     2 class này, an toàn để ẩn (dù đã bị ẩn gián tiếp qua ẩn root cha, giữ
 *     thêm ở đây làm lưới an toàn kép — defense-in-depth, đúng ý đồ "lưới an
 *     toàn" của cả mục 6)
 *
 * BỎ KHỎI DANH SÁCH BẢNG KIẾN TRÚC (ghi lý do, không im lặng bỏ qua):
 *   - ".call-status": KHÔNG map được sang selector CSS nào. Đọc widgets/call-
 *     status.jsx: component render <><div class="composed-material">...</div>
 *     {duration}</> — KHÔNG có wrapper class riêng. Dùng ở lib/formatters.js
 *     (case 'VC') để in "trích đoạn cuộc gọi" ngay TRONG luồng preview text của
 *     Drafty (danh sách hội thoại, tin chuyển tiếp, VÀ CẢ .pinned mục 1 ở trên
 *     nếu tin ghim là 1 tin gọi) — không có hook DOM để ẩn riêng mà không đoán
 *     mò cấu trúc cha (rủi ro ẩn nhầm nội dung preview thật). Chưa xác minh được
 *     bằng ảnh (không có dữ liệu test cuộc gọi cũ) — để phase 06 xác nhận bằng
 *     mắt nếu 105 tài khoản có lịch sử gọi, ghi vào danh sách "chưa xác minh".
 * ============================================================================= */
#scroller > li:has(.call-message) {
  display: none;
}

.call-message {
  display: none;
}

.incoming-call {
  display: none;
}

#video-container {
  display: none;
}

.caller-card {
  display: none;
}

.caller-name {
  display: none;
}

/* ===== Thẻ gọi RealtimeKit (B1, brainstorm-260730-call-speed-ux) =====
   Tin mời "📞 X đã bắt đầu cuộc gọi · Bấm để tham gia" là drafty LN link →
   biến LINK thành nút khối nổi bật, neo selector theo href (không phụ thuộc DOM wrapper).
   Nền #2E6BE6 (đã kiểm AA với chữ trắng — xem gotcha #3B82F6 trượt AA). */
#scroller a[href^="https://hrm.bulbalvn.com/call/"] {
  display: block;
  margin-top: 8px;
  padding: 12px 16px;
  min-height: 44px; /* chuẩn touch mobile */
  box-sizing: border-box;
  background: #2E6BE6;
  color: #fff !important; /* đè màu link trong bong bóng gửi đi/nhận */
  border-radius: 12px;
  font-weight: 600;
  font-size: 15px;
  text-align: center;
  text-decoration: none !important;
  cursor: pointer;
}
#scroller a[href^="https://hrm.bulbalvn.com/call/"]::before {
  content: '📞 ';
}
#scroller a[href^="https://hrm.bulbalvn.com/call/"]:active {
  filter: brightness(0.9);
}
