html {
  font-size: 14px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

html {
  position: relative;
  min-height: 100%;
}

body {
  margin-bottom: 60px;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
  color: var(--bs-secondary-color);
  text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
  text-align: start;
}

/* ===== Trợ lý AI chatbot — phong cách Messenger ===== */
.chatbot-overlay { display: none; } /* Messenger không dùng lớp phủ tối */

.chatbot-panel {
  position: fixed;
  bottom: 20px;
  right: 20px;
  width: 340px;
  max-width: calc(100vw - 24px);
  height: 520px;
  max-height: calc(100vh - 90px);
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .22);
  z-index: 1080;
  overflow: hidden;
  font-size: 14px;
  /* Hiệu ứng bung ra từ góc dưới-phải kiểu Messenger */
  transform: scale(.5);
  transform-origin: bottom right;
  opacity: 0;
  visibility: hidden;
  transition: transform .18s ease, opacity .18s ease, visibility .18s ease;
}
.chatbot-panel.open { transform: scale(1); opacity: 1; visibility: visible; }
.chatbot-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: linear-gradient(90deg, #0a7cff, #0064e0);
  color: #fff;
  font-weight: 600;
  font-size: 15px;
  flex-shrink: 0;
}
.chatbot-header .chatbot-avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; flex-shrink: 0;
}
.chatbot-header .chatbot-title { display: flex; flex-direction: column; line-height: 1.15; }
.chatbot-header .chatbot-title small { font-weight: 400; font-size: 11px; opacity: .9; }
.chatbot-header .chatbot-online { color: #31d863; font-size: 8px; vertical-align: middle; }
.chatbot-header .chatbot-close { margin-left: auto; }
.chatbot-close {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.chatbot-messages {
  flex: 1;
  overflow-y: auto;
  padding: 12px 12px 6px;
  background: #fff;
}
.chatbot-msg { margin-bottom: 10px; display: flex; }
.chatbot-msg.user { justify-content: flex-end; }
.chatbot-bubble {
  max-width: 78%;
  padding: 8px 12px;
  border-radius: 18px;
  line-height: 1.4;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}
.chatbot-msg.user .chatbot-bubble {
  background: #0a7cff;
  color: #fff;
  border-radius: 18px 18px 4px 18px;
}
.chatbot-msg.bot .chatbot-bubble {
  background: #e9ebee;
  color: #050505;
  border-radius: 18px 18px 18px 4px;
}
.chatbot-bubble p { margin: 0 0 6px; }
.chatbot-bubble p:last-child { margin: 0; }
.chatbot-bubble ul, .chatbot-bubble ol { margin: 4px 0; padding-left: 20px; }
.chatbot-bubble pre {
  background: #f0f0f0;
  padding: 8px;
  border-radius: 6px;
  overflow-x: auto;
}
.chatbot-bubble code { font-size: .9em; }
.chatbot-typing { font-style: italic; color: #888; }
.chatbot-input {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 10px 12px;
  border-top: 1px solid #eef0f2;
  background: #fff;
}
.chatbot-input textarea {
  flex: 1;
  resize: none;
  border: none;
  border-radius: 20px;
  background: #f0f2f5;
  padding: 9px 14px;
  max-height: 120px;
  outline: none;
  font-size: 14px;
  line-height: 1.3;
}
.chatbot-send {
  background: none;
  color: #0a7cff;
  border: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 17px;
  flex-shrink: 0;
  transition: background .15s ease;
}
.chatbot-send:hover { background: #eaf3ff; }
.chatbot-send:disabled { opacity: .45; cursor: not-allowed; background: none; }
@media (max-width: 480px) {
  .chatbot-panel { width: 100vw; }
}

/* Footer luôn nằm đáy: cho phần nội dung giãn đầy chiều cao của .app-body (flex column).
   Giữ cả 2 selector: .app-body > .app-content là cấu trúc THẬT của layout; rule .main-content
   của theme (.app-content .content-wrapper .main-content) lo phần bên trong. */
.app-body > .app-content { flex: 1 1 auto; }
.app-body > .main-content { flex: 1 1 auto; }

/* ============================================================================
   LƯỚI AN TOÀN — sidebar phải cuộn được trên điện thoại
   ----------------------------------------------------------------------------
   Theme cố ý TẮT slimscroll trên mobile để dùng cuộn native (smartApp.js:107-125:
   `if (!mobileOperator()) {...} else { BODY.classList.add('no-slimscroll') }`), và CSS
   `body:not(.no-slimscroll) .custom-scroll { overflow: hidden }` chỉ nhả cuộn khi class
   no-slimscroll CÓ MẶT trên <body>.

   Nhưng dòng đó nằm SAU `document.querySelector('.main-content').classList.add(...)` trong
   CÙNG handler DOMContentLoaded và theme KHÔNG guard null → layout nào thiếu .main-content sẽ
   ném TypeError → no-slimscroll không bao giờ được thêm → `.custom-scroll` giữ overflow:hidden
   → trên mobile `.app-sidebar` là position:fixed/top:0/bottom:0 nên menu bị CẮT CỨNG, không
   cuộn được (đo thật 2026-07-16: nav scrollHeight 1037px trong clientHeight 601px).

   Gốc rễ đã vá bằng cách bọc .main-content trong 3 layout. Rule dưới là lưới an toàn: cưỡng
   bức cuộn native trên mobile kể cả khi JS theme lại chết vì lý do khác. KHÔNG sửa file theme
   (quy tắc dự án) — chỉ ghi đè từ site.css. */
@media only screen and (max-width: 991.98px) {
  .app-sidebar .primary-nav.custom-scroll,
  body:not(.no-slimscroll) .app-sidebar .primary-nav.custom-scroll {
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  /* Bản thân sidebar cũng cho cuộn (mobile theme đặt position:fixed; top:0; bottom:0). */
  .app-sidebar { overflow-y: auto; -webkit-overflow-scrolling: touch; }
}

/* ============================================================================
   nl-notify — popup thông báo sau submit (thay cho alert alert-success/danger/info
   render inline trong view). Xem wwwroot/Scripts/nlnotify.js + Views/Shared/_NotifyPopup.cshtml.
   Namespace riêng: .nl-notify-* — KHÔNG đụng file gốc smartadminNew.
   ============================================================================ */
.nl-notify-overlay {
  position: fixed;
  inset: 0;
  z-index: 20000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(15, 23, 42, 0.55);
  opacity: 0;
  transition: opacity .18s ease;
}
.nl-notify-overlay.nl-notify-show { opacity: 1; }

.nl-notify-box {
  width: 100%;
  max-width: 380px;
  background: #ffffff;
  color: #1f2937;
  border-radius: 14px;
  padding: 30px 28px 22px;
  text-align: center;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .25);
  transform: scale(.92) translateY(8px);
  transition: transform .18s ease;
}
.nl-notify-overlay.nl-notify-show .nl-notify-box {
  transform: scale(1) translateY(0);
}

.nl-notify-icon {
  width: 64px;
  height: 64px;
  margin: 0 auto 14px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}
.nl-notify-success .nl-notify-icon { background: #e6f7ee; color: #16a34a; }
.nl-notify-error .nl-notify-icon   { background: #fdecec; color: #dc2626; }
.nl-notify-info .nl-notify-icon    { background: #e8f1ff; color: #2563eb; }

.nl-notify-message {
  font-size: 15px;
  line-height: 1.5;
  margin-bottom: 22px;
  white-space: pre-line;
  word-break: break-word;
}

.nl-notify-close-btn {
  border: none;
  border-radius: 8px;
  padding: 8px 30px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  background: #6b7280;
  transition: background .15s ease;
}
.nl-notify-success .nl-notify-close-btn { background: #16a34a; }
.nl-notify-success .nl-notify-close-btn:hover { background: #15803d; }
.nl-notify-error .nl-notify-close-btn { background: #dc2626; }
.nl-notify-error .nl-notify-close-btn:hover { background: #b91c1c; }
.nl-notify-info .nl-notify-close-btn { background: #2563eb; }
.nl-notify-info .nl-notify-close-btn:hover { background: #1d4ed8; }

/* Dark mode: theme toggle của smartadminNew set data-bs-theme trên <html> (saveloadscript.js) */
:root[data-bs-theme="dark"] .nl-notify-overlay,
[data-theme="dark"] .nl-notify-overlay {
  background: rgba(0, 0, 0, .65);
}
:root[data-bs-theme="dark"] .nl-notify-box,
[data-theme="dark"] .nl-notify-box {
  background: #1e293b;
  color: #e5e7eb;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .5);
}
:root[data-bs-theme="dark"] .nl-notify-close-btn,
[data-theme="dark"] .nl-notify-close-btn {
  color: #fff;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-bs-theme="light"]):not([data-theme="light"]) .nl-notify-box {
    background: #1e293b;
    color: #e5e7eb;
  }
  :root:not([data-bs-theme="light"]):not([data-theme="light"]) .nl-notify-overlay {
    background: rgba(0, 0, 0, .65);
  }
}
/* ===================== Ký số (kyso) — dialog xem + chọn vị trí ký ===================== */
.kyso-modal .modal-body { display: flex; flex-direction: column; }
.kyso-viewer {
  background: #525659;
  overflow: auto;
  padding: 16px 0;
  min-height: 55vh;
  max-height: 70vh;
}
.kyso-page {
  position: relative;
  margin: 0 auto 16px auto;
  background: #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,.5);
  cursor: crosshair;
}
.kyso-page canvas { display: block; }
.kyso-sigbox {
  position: absolute;
  border: 2px dashed #0a7cff;
  background: rgba(10,124,255,.12);
  box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: #0a7cff; font-weight: 600;
  pointer-events: none;
}
.kyso-toolbar { background: #f7f8fa; }
.kyso-hint { background: #eef5ff; }
@media (prefers-color-scheme: dark) {
  :root:not([data-bs-theme="light"]):not([data-theme="light"]) .kyso-toolbar { background: #1e293b; }
  :root:not([data-bs-theme="light"]):not([data-theme="light"]) .kyso-hint { background: #17233b; }
}

/* ============================================================
   nldash — Dashboard đơn vị (plan dashboard-don-vi, P0)
   Linh kiện: Views/Shared/NlDash/_*.cshtml + Scripts/nldashboard.js
   ============================================================ */
.nldash-chart-wrap { position: relative; width: 100%; }
.nldash-chart-wrap > canvas { max-width: 100%; }
.nldash-panel .panel-content { padding: 1rem; }
.nldash-table { font-size: 13px; }
.nldash-delta { opacity: .9; }
.nldash-feed-item { padding: .45rem 0; border-bottom: 1px dashed rgba(0, 0, 0, .08); }
.nldash-feed-item:last-child { border-bottom: 0; }
.nldash-feed-ico { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border-radius: .5rem; flex: 0 0 auto; }
.nldash-picker { min-width: 260px; }
[data-bs-theme="dark"] .nldash-feed-item { border-bottom-color: rgba(255, 255, 255, .08); }
.nldash-section-title { display: flex; align-items: center; gap: .5rem; margin: 1.5rem 0 .9rem; padding-left: .6rem; border-left: 4px solid #2E74B5; font-size: 1.05rem; font-weight: 700; }
.nldash-section-title i { color: #2E74B5; }

/* =============================================================================
   Modal bcommand (#myModal) responsive + đồng bộ nút — vá 2026-07-17
   Lỗi (đo THẬT browser 390px + ảnh chụp): modal-dialog width CỨNG 800px,
   max-width:none => tràn phải 410px trên điện thoại. Footer justify-content:
   flex-end => hàng nút dồn về x≈800 (ngoài màn hình) => NÚT PHẢI (Đóng/Lưu/Xóa)
   BỊ MẤT, chỉ nút trái bấm được. (transform-25% ban đầu nghi ngờ -> ĐO LOẠI: none.)
   KHÔNG sửa file theme; chỉ thêm lưới an toàn ở site.css.
   ============================================================================= */
@media (max-width: 991.98px) {
    /* Ép modal vừa khung điện thoại: bỏ width cứng 800px + dock lệch trái 25%,
       về full-screen từ mép trái. Selector kèm `.modal` để thắng specificity của
       theme `.modal.fade .modal-dialog-start` (0,3,0) — nếu chỉ `#myModal .x` thì
       transform:none KHÔNG thắng translate(-25%) của theme (đã đo THẬT: modal lệch
       trái 97px, mép trái cắt ngoài màn). Cần cả -webkit-transform + left/right. */
    #myModal.modal .modal-dialog,
    #myModal.modal .modal-dialog-start,
    #myModal.modal .modal-dialog-end,
    #kyso-modal.modal .modal-dialog {
        width: 100% !important;
        max-width: 100vw !important;
        margin: 0 !important;
        left: 0 !important;
        right: auto !important;
        transform: none !important;
        -webkit-transform: none !important;
    }
    #myModal .modal-content,
    #kyso-modal .modal-content { max-width: 100vw; border-radius: 0; }
}

/* Đồng bộ hàng nút modal về BÊN TRÁI (chốt: modal dock-start neo trái => nút
   trái luôn trong tầm ngón cái mobile). Khảo sát 606 view có nút modal:
   91 view kiểu cũ đã để nút trong <div> căn TRÁI; 512 view mới dùng
   `.d-flex.justify-content-end` (nút PHẢI) + 6 view `.modal-footer` (mặc định
   flex-end). Kéo 2 nhóm phải về trái cho nhất quán — an toàn vì trong modal,
   `.justify-content-end` CHỈ dùng cho hàng nút (đã verify: mọi chỗ là
   `<div class="d-flex justify-content-end gap-2">` bọc nút submit/dismiss). */
#myModal .modal-footer,
#myModal .justify-content-end { justify-content: flex-start !important; }

/* ============================================================================
   LƯỚI AN TOÀN RESPONSIVE BẢNG (mobile) — 2026-07-18
   Chuẩn dự án: MỌI bảng phải bọc `<div class="table-responsive">` (theme-guide
   dòng 162-166). Bảng `.dt-basic-example` do DataTables (responsive:true) tự lo.
   Rule này là LƯỚI AN TOÀN cho bảng `.table` KHÔNG phải DataTable mà LỠ quên bọc
   .table-responsive: trên điện thoại cho cuộn ngang thay vì phá vỡ layout trang.
   - `:not(.dataTable)` bỏ qua bảng DataTables đã init (theme tự thêm class này).
   - Rule reset trả bảng ĐÃ bọc .table-responsive về display:table (div cha đã lo
     cuộn) => KHÔNG đổi hành vi 204 bảng đã bọc đúng chuẩn. KHÔNG sửa file theme.
   ============================================================================ */
@media (max-width: 991.98px) {
  .app-content table.table:not(.dataTable) {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .app-content .table-responsive > table.table:not(.dataTable) {
    display: table;
  }
}

/* ============================================================================
   HEADER + SIDEBAR CỐ ĐỊNH (fixed) khi cuộn — user yêu cầu 2026-07-19
   `<html>` 3 layout area gắn `set-header-fixed set-nav-fixed` → theme cho sidebar
   position:fixed + overflow-y:auto (đứng yên, cuộn menu riêng khi dài) + header fixed.
   Header của theme fixed đúng ở TF nhưng ở Admin/KhachSan lại ra `static` (cùng markup
   .app-header, KHÔNG file CSS nào override — nguyên nhân chưa rõ). site.css nạp CUỐI ở
   cả 3 layout nên rule dưới ép header cố định ĐỒNG NHẤT (header+sidebar cùng đứng yên,
   nội dung cuộn ở giữa = mẫu admin dashboard chuẩn). KHÔNG sửa file theme.
   Chỉ áp desktop (≥992px); mobile sidebar là off-canvas riêng, không đụng.
   ============================================================================ */
@media (min-width: 992px) {
  .set-header-fixed .app-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1035;
  }
}

/* ============================================================================
   HỘP THƯ (HopThu) — khôi phục chuỗi chiều cao khi .layout-trimmed bị LỒNG
   trong lớp bọc .main-content của layout (vá 2026-07-19).
   Layout bọc @RenderBody() trong .main-content (bắt buộc — DOM contract của
   smartApp.js, vá 2026-07-16). Nhưng HopThu.cshtml là trang DUY NHẤT dùng mẫu
   "trimmed layout" của theme: tự mang .main-content.layout-trimmed và theme
   yêu cầu nó là CON TRỰC TIẾP của .content-wrapper:
   - .app-content .content-wrapper .main-content { flex:1 1 auto } chỉ có tác
     dụng khi cha là flex — lớp bọc là block ⇒ flex vô hiệu ⇒ vùng danh sách
     thư (flex-grow-1 > position-absolute + overflow-y-auto) cao 0px, thư bị
     cắt cụt dù server render đủ.
   - .content-wrapper:has(>.layout-trimmed){padding:0} không còn khớp ⇒ viền
     trắng thừa quanh khung thư.
   2 rule dưới vá cả 2 (đo thật headless 1280×800: vùng thư 0px → ~519px).
   ============================================================================ */
.content-wrapper > .main-content:has(> .layout-trimmed) {
  display: flex;
  flex-direction: column;
}
.content-wrapper:has(.layout-trimmed) {
  padding: 0 !important;
}
