/* ===========================================================================
   DESIGN SYSTEM — nguồn sự thật duy nhất cho tokens (màu/spacing/radius/
   shadow/typography) và các class UI dùng chung (button, card, badge, form
   control, table, focus state). KHÔNG chứa CSS đặc thù 1 màn hình cụ thể —
   phần đó thuộc về style.css (app-shell, sidebar, gantt calendar...).

   File này phải được include TRƯỚC style.css trong base.html, vì style.css
   (và mọi template) dựa vào các biến định nghĩa ở đây.

   Hỗ trợ Light/Dark mode qua [data-theme] trên <html>, mặc định theo
   prefers-color-scheme nếu người dùng chưa từng bấm nút chuyển theme.
   =========================================================================== */

/* ===================== 1. TOKENS ===================== */
:root {
    /* ---- Brand: xanh dương tươi làm màu chủ đạo — DARK MODE LÀ MẶC ĐỊNH ----
       Khác hẳn thế hệ pastel trước: *-500 giờ ĐỦ ĐẬM để tự làm nền + chữ
       trắng lên trên (không còn kiểu "nền nhạt + chữ đậm cùng tông"). Vẫn
       giữ *-600/700 làm biến thể đậm hơn cho hover/text phụ khi cần. */
    --brand-50:  #eaf1ff;
    --brand-100: #d3e2ff;
    --brand-400: #7ba3f2;
    --brand-500: #5B8DEF;
    /* Bản đậm hơn ~20% so với brand-500 gốc — dùng làm NỀN khi cần chữ trắng
       đạt AA-normal 4.5:1 đầy đủ (nút bấm, text quan trọng) thay vì brand-500
       nguyên bản chỉ đạt 3.23:1. brand-500 nguyên bản vẫn dùng được cho badge
       nhỏ/đậm (chỉ cần đạt AA-Large 3:1). */
    --brand-600: #4870bf;
    --brand-700: #35578f;

    /* ---- Accent (CTA tích cực / nút "+") — xanh lá tươi ----
       accent-500 giữ nguyên độ tươi cho badge/icon nhỏ (đậm, đạt AA-Large).
       accent-600 (darken 35%) dùng cho nút bấm/text cần AA-normal đầy đủ
       (4.93:1 với chữ trắng — 30% như các *-600 khác chỉ đạt 4.34:1, fail). */
    --accent-500: #34C759;
    /* accent-600 darken 35% (không phải 30% như các *-600 khác) — 30% chỉ đạt
       4.34:1 với chữ trắng (fail AA-normal 4.5), 35% đạt 4.93:1. */
    --accent-600: #218139;

    /* ---- Semantic: success / warning / danger / info -----------------
       *-500 = màu tươi nguyên bản (đúng tinh thần ảnh mẫu) — CHỈ dùng cho
       badge nhỏ/chữ đậm (đạt AA-Large 3:1), KHÔNG dùng làm nền cho khối chữ
       thường lớn. *-600 = bản đậm hơn, đạt AA-normal 4.5:1 với chữ trắng,
       dùng cho nút bấm và mọi chỗ cần contrast chắc chắn. */
    --success-500: #34C759;
    --success-600: #248b3e;
    --warning-500: #F5B940;
    --warning-600: #ab812c;
    --danger-500:  #FF5C5C;
    --danger-600:  #cc4949;
    --info-500:    #5B8DEF;
    --info-600:    #4870bf;

    /* success/warning tươi quá sáng: chữ TRẮNG trên các nền này (kể cả *-600)
       không đạt nổi AA-Large (2.22:1 / 1.77:1 đo thực tế) — PHẢI dùng chữ
       TỐI (đạt 7.6:1 / 9.55:1) cho mọi text/badge/nút nền success|warning.
       danger/info/brand vẫn dùng --text-on-brand (trắng) như bình thường. */
    --text-on-warm: #1a1d24;

    /* ---- Border-radius: card lớn theo tinh thần ảnh mẫu ---- */
    --radius-sm: 10px;
    --radius-md: 16px;
    --radius-lg: 20px;
    --radius-full: 999px;

    /* ---- Spacing scale 4px ---- */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-6: 24px;
    --space-8: 32px;
    --space-12: 48px;
    /* alias giữ tương thích các nơi đã dùng --space-5 (20px, nửa bước giữa 16/24) */
    --space-5: 20px;

    /* ---- Typography: 1 font, scale 11/12/14/16/18/20/24/32, line-height 1.5
       cho body. Đợt 3 design audit (#6) — bổ sung --text-2xs (11px) và
       --text-xl-plus (20px) để quy hết 18 giá trị font-size hardcode lẻ
       trong style.css về đúng 1 trong 8 bước này (không còn số tự do nào).
       --text-xl-plus KHÔNG dùng tên "--text-lg2"/đổi nghĩa "--text-xl" hiện
       có (24px, đang dùng cho h2 toàn app) để tránh vô tình thu nhỏ mọi
       heading h2 — đặt tên mới riêng cho bước trung gian 20px. ---- */
    --font-sans: 'Be Vietnam Pro', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --text-2xs: 11px;
    --text-xs: 12px;
    --text-sm: 14px;
    --text-base: 16px;
    --text-lg: 18px;
    --text-xl-plus: 20px;
    --text-xl: 24px;
    --text-2xl: 32px;
    --line-height-body: 1.5;

    /* ---- Shadow 3 cấp — đậm hơn (dark mode là mặc định, cần bóng rõ trên nền đen) ---- */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.5);
    /* Đợt 3 design audit (#10) — bóng NGANG riêng cho sidebar drawer mobile
       (trước đây hardcode "2px 0 12px rgba(0,0,0,0.2)" trong style.css,
       không qua token nào) — giữ nguyên giá trị cũ, chỉ đặt tên; không theo
       theme (giống hành vi cũ, không có bản light/dark riêng). */
    --shadow-drawer: 2px 0 12px rgba(0, 0, 0, 0.2);

    /* ---- Transition: 150-200ms hover/focus, 250-300ms modal/dropdown ---- */
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --transition-fast: 0.15s var(--ease-out);
    --transition-base: 0.2s var(--ease-out);
    --transition-modal: 0.28s var(--ease-out);

    color-scheme: dark;

    /* ===== DARK THEME (MẶC ĐỊNH) — nền đen tuyền, accent tươi ===== */
    --bg-app: #0f1115;
    --bg-surface: #1c1f26;
    --bg-subtle: #252932;
    --bg-hover: #2d323c;

    --text-primary: #f5f6f8;
    --text-secondary: #9a9fa8;
    --text-tertiary: #6b7078;
    --text-on-brand: #ffffff;

    --border-color: #2d323c;
    --border-color-strong: #3a4049;
}

:root[data-theme="light"] {
    color-scheme: light;
    /* Bản sáng tương ứng — vẫn dùng accent xanh dương/xanh lá/vàng/đỏ như
       dark mode (chỉ đổi nền/chữ), giữ nhất quán thương hiệu giữa 2 theme. */
    --bg-app: #f5f6f8;
    --bg-surface: #ffffff;
    --bg-subtle: #eef0f3;
    --bg-hover: #e4e7ec;

    /* Đợt 2 design audit (#7 + #8) — --brand-600 gốc (#4870bf) đo được CHỈ
       4.47:1 khi làm CHỮ (link a:not(.btn), .btn-outline-primary) đặt trực
       tiếp trên --bg-app light (#f5f6f8, không phải trắng tuyệt đối) — dưới
       ngưỡng AA 4.5:1, xác nhận bằng design_audit/check_all_contrast.py.
       Darken thêm 4% (#4870bf -> #456bb7) giải quyết CẢ HAI cùng lúc (link +
       outline button dùng chung 1 biến) vì đây là override CHỈ áp dụng ở
       light theme — nền nút .btn-primary/.btn-success dùng brand-600 làm
       BACKGROUND (không phải chữ) vẫn an toàn tuyệt đối vì đậm hơn chỉ giúp
       contrast với chữ trắng tốt hơn, không bao giờ làm giảm. Dark theme
       KHÔNG đổi (--brand-600 gốc trong :root vẫn giữ nguyên #4870bf, biến
       này không theme-scoped ở đó). */
    --brand-600: #456bb7;

    /* Fail riêng phát hiện thêm khi verify lại — CÙNG họ bug với brand-600
       ở trên (màu *-600 đủ đậm trên NỀN TRẮNG tuyệt đối nhưng KHÔNG đủ trên
       --bg-app light #f5f6f8 off-white): .invalid-feedback dùng danger-600
       làm chữ, chỉ đạt 4.21:1 trên bg-app (đo được qua check_all_contrast.py
       trước khi sửa). Darken 5% (không phải 4% như brand — xuất phát điểm
       gần ngưỡng hơn) để đạt 4.62:1. Nền .btn-danger/.btn-outline-danger:hover
       dùng danger-600 làm BACKGROUND (không phải chữ) vẫn an toàn tuyệt đối
       như brand-600 ở trên. */
    --danger-600: #c14545;

    --text-primary: #1a1d24;
    --text-secondary: #565c66;
    --text-tertiary: #868c96;

    --border-color: #e4e7ec;
    --border-color-strong: #d3d8e0;

    --shadow-sm: 0 1px 2px rgba(24, 25, 45, 0.06);
    --shadow-md: 0 4px 14px rgba(24, 25, 45, 0.08);
    --shadow-lg: 0 12px 32px rgba(24, 25, 45, 0.12);
}

/* Nếu người dùng chưa từng bấm toggle (không có data-theme lưu sẵn), tôn
   trọng theme hệ điều hành CHỈ KHI hệ điều hành là light — vì :root mặc định
   (không có selector) đã LÀ dark theme rồi, nhánh này chỉ cần override sang
   light khi OS đang ở light mode. base.html luôn set data-theme trước khi
   render nên nhánh này chỉ là lưới an toàn (progressive enhancement). */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="light"]):not([data-theme="dark"]) {
        color-scheme: light;
        --bg-app: #f5f6f8;
        --bg-surface: #ffffff;
        --bg-subtle: #eef0f3;
        --bg-hover: #e4e7ec;
        --text-primary: #1a1d24;
        --text-secondary: #565c66;
        --text-tertiary: #868c96;
        --border-color: #e4e7ec;
        --border-color-strong: #d3d8e0;
        --shadow-sm: 0 1px 2px rgba(24, 25, 45, 0.06);
        --shadow-md: 0 4px 14px rgba(24, 25, 45, 0.08);
        --shadow-lg: 0 12px 32px rgba(24, 25, 45, 0.12);
    }
}

/* ===================== 2. BASE / TYPOGRAPHY ===================== */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    background-color: var(--bg-app);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: var(--line-height-body);
    margin: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--transition-base), color var(--transition-base);
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-sans);
    color: var(--text-primary);
    letter-spacing: -0.01em;
}
h1, .h1 { font-size: var(--text-2xl); }
h2, .h2 { font-size: var(--text-xl); }
h3, .h3 { font-size: var(--text-lg); }
h4, .h4, h5, .h5 { font-size: var(--text-base); }
h6, .h6 { font-size: var(--text-sm); }

/* Dark là mặc định: link cần bản SÁNG (brand-400) để đọc được trên nền đen.
   Light mode override dùng bản ĐẬM (brand-600) để đọc được trên nền trắng.

   QUAN TRỌNG — loại TRỪ .btn (":not(.btn)"): bug thật đã tìm (ảnh hưởng
   MỌI nút "<a class="btn ...">" toàn app, không riêng 1 nút) — trước đây
   "a { color }" áp dụng cho MỌI thẻ <a>, kể cả .btn-primary/.btn-success/
   .btn-danger/.btn-info (nút CTA "+ Đặt phòng mới", "Tin nhắn xác nhận"...).
   Selector "a" (0,0,1) có vẻ yếu hơn ".btn-success" (0,1,0), nhưng
   ":root[data-theme="light"] a" có specificity (0,2,1) — CAO HƠN
   ".btn-success" — nên ở light theme, MÀU CHỮ LINK (--brand-600, xanh
   dương) đè mất color: var(--text-on-brand) (trắng) của nút, khiến chữ
   xanh dương hiện trên nền xanh lá/đỏ/vàng của nút — gần như không đọc
   được (contrast đo được chỉ ~1:1 cho .btn-success). Thêm ":not(.btn)" để
   rule màu link không bao giờ áp dụng lên nút — nút luôn tự quyết định màu
   chữ qua .btn-*, không phụ thuộc thứ tự nguồn/specificity may rủi. */
a:not(.btn) { color: var(--brand-400); }
a:not(.btn):hover { color: var(--brand-100); }
:root[data-theme="light"] a:not(.btn) { color: var(--brand-600); }
:root[data-theme="light"] a:not(.btn):hover { color: var(--brand-700); }

small, .text-muted {
    color: var(--text-secondary) !important;
}

/* <fieldset>/<legend> dùng để nhóm trường form theo semantic HTML5 — reset
   viền/padding mặc định của trình duyệt để trông giống nhóm <div> thường. */
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
legend { border: 0; float: none; }

/* ===================== 3. FOCUS STATE (accessibility) ===================== */
/* Không bao giờ outline:none trần — mọi phần tử focus qua bàn phím đều phải
   có viền rõ ràng. */
a:focus-visible, button:focus-visible, .btn:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible {
    /* --brand-500 là màu tươi nguyên bản, đủ tương phản trên cả nền đen
       (dark mặc định) lẫn nền trắng (light override) để focus ring luôn rõ. */
    outline: 2px solid var(--brand-500);
    outline-offset: 2px;
}

/* ===================== 4. BUTTON ===================== */
.btn {
    border-radius: var(--radius-sm);
    font-weight: 600;
    font-size: var(--text-sm);
    letter-spacing: 0.01em;
    border-width: 1.5px;
    min-height: 40px;
    padding-left: var(--space-4);
    padding-right: var(--space-4);
    transition: transform var(--transition-fast), box-shadow var(--transition-fast),
                background-color var(--transition-fast), border-color var(--transition-fast),
                filter var(--transition-fast);
}
.btn:active { transform: scale(0.97); }
.btn:disabled, .btn.disabled { transform: none; cursor: not-allowed; }

/* Nút màu tươi: nền ĐẬM (*-600, hoặc *-500 với brand/danger/info đã đủ đậm)
   + chữ TRẮNG luôn — đúng tinh thần dark-mode-first. Hover đậm thêm bằng
   filter brightness, KHÔNG đổi màu chói. Text-shadow tối rất nhẹ giúp chữ
   trắng nét viền hơn trên các nền màu bão hòa thấp (đặc biệt accent-600 xanh
   lá) — không đủ đậm để coi là "đổ bóng" thị giác, chỉ tăng độ sắc nét. */
.btn-primary {
    background: var(--brand-600);
    border-color: var(--brand-600);
    color: var(--text-on-brand);
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}
.btn-primary:hover, .btn-primary:focus {
    filter: brightness(1.12);
    box-shadow: var(--shadow-md);
    color: var(--text-on-brand);
}
.btn-success {
    background: var(--accent-600);
    border-color: var(--accent-600);
    color: var(--text-on-brand);
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}
.btn-success:hover, .btn-success:focus {
    filter: brightness(1.12);
    box-shadow: var(--shadow-md);
    color: var(--text-on-brand);
}
.btn-danger {
    background: var(--danger-600);
    border-color: var(--danger-600);
    color: var(--text-on-brand);
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}
.btn-danger:hover, .btn-danger:focus {
    filter: brightness(1.12);
    box-shadow: var(--shadow-md);
    color: var(--text-on-brand);
}
.btn-warning {
    background: var(--warning-600);
    border-color: var(--warning-600);
    /* warning-600 + chữ trắng chỉ đạt 3.55:1 (fail AA-normal 4.5) — chữ tối
       đạt AA-normal chắc chắn (xem --text-on-warm ở TOKENS). Chữ tối không
       cần text-shadow (đã sắc nét sẵn trên nền sáng). */
    color: var(--text-on-warm);
}
.btn-warning:hover, .btn-warning:focus {
    filter: brightness(1.12);
    box-shadow: var(--shadow-md);
    color: var(--text-on-warm);
}
.btn-info {
    background: var(--info-600);
    border-color: var(--info-600);
    color: var(--text-on-brand);
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}
.btn-info:hover, .btn-info:focus {
    filter: brightness(1.12);
    box-shadow: var(--shadow-md);
    color: var(--text-on-brand);
}
.btn-secondary {
    background: var(--bg-subtle);
    border-color: var(--border-color-strong);
    color: var(--text-primary);
}
.btn-secondary:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.btn-outline-primary { color: var(--brand-400); border-color: var(--brand-500); }
.btn-outline-primary:hover { background: var(--brand-600); border-color: var(--brand-600); color: var(--text-on-brand); }
/* Đợt 2 design audit (#7) — .btn-outline-primary dùng --brand-400 (KHÔNG
   phải --brand-600), biến này KHÔNG được darken theo theme ở trên (chỉ
   brand-600 mới có override light) — nên fix #7+#8 (darken brand-600) không
   tự động sửa nút này. Đo trực tiếp: brand-400 trên bg-app light chỉ 2.32:1
   (fail rất xa AA). Thêm override riêng dùng brand-600 (đã darken) cho light
   theme — cùng cách "a:not(.btn)" đã làm trước đó, KHÔNG đổi brand-400 dùng
   ở dark theme (đã đạt 7.53:1, không cần sửa). */
:root[data-theme="light"] .btn-outline-primary { color: var(--brand-600); }

/* Đợt 1 design audit — toggle "Qua đêm/Theo giờ" (booking_form.html) dùng
   pattern Bootstrap ".btn-check" + ".btn-outline-primary" cho hiệu ứng radio-
   as-button, nhưng KHÔNG có CSS riêng nào ở đây trước đó — trạng thái
   ":checked" tự rơi về "--bs-primary" mặc định của Bootstrap (#0d6efd, xanh
   dương KHÁC hẳn --brand-600 #4870bf của app), khiến 1 chi tiết nhỏ trên
   form lệch hẳn tông màu thương hiệu so với mọi nút primary khác. Style
   tường minh theo đúng token app, không phụ thuộc biến Bootstrap. */
.btn-check:checked + .btn-outline-primary,
.btn-check:active + .btn-outline-primary {
    background-color: var(--brand-600);
    border-color: var(--brand-600);
    color: var(--text-on-brand);
}
.btn-outline-secondary { color: var(--text-secondary); border-color: var(--border-color-strong); }
.btn-outline-secondary:hover { background: var(--bg-subtle); color: var(--text-primary); border-color: var(--border-color-strong); }
.btn-outline-danger { color: var(--danger-500); border-color: var(--danger-500); }
.btn-outline-danger:hover { background: var(--danger-600); border-color: var(--danger-600); color: var(--text-on-brand); }
.btn-outline-warning { color: var(--warning-500); border-color: var(--warning-500); }
.btn-outline-warning:hover { background: var(--warning-600); border-color: var(--warning-600); color: var(--text-on-warm); }
.btn-outline-dark { color: var(--text-primary); border-color: var(--border-color-strong); }
.btn-outline-dark:hover { background: var(--text-primary); border-color: var(--text-primary); color: var(--bg-surface); }

.btn-sm { min-height: 32px; padding: 6px 12px; font-size: var(--text-xs); }

/* Vùng chạm tối thiểu 44x44px cho icon-button trên mobile */
@media (max-width: 767.98px) {
    .btn:not(.btn-sm) { min-height: 44px; }
}

/* ===================== 5. CARD ===================== */
.card {
    background: var(--bg-surface);
    color: var(--text-primary);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    transition: background-color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-fast);
}
.card:hover { box-shadow: var(--shadow-md); }
.card-body { padding: var(--space-4); }

/* ===================== 6. BADGE ===================== */
.badge {
    border-radius: var(--radius-full);
    font-weight: 600;
    font-size: var(--text-xs);
    padding: 5px 10px;
    letter-spacing: 0.01em;
}

/* Màu trạng thái booking — nguồn sự thật DUY NHẤT, dùng chung giữa
   booking_list.html, booking_detail.html, lịch Gantt (calendar) và legend.
   Trạng thái nào map màu nào phải sửa Ở ĐÂY, không lặp lại dict màu trong
   template.

   Cùng cấu trúc theme với TOKENS phía trên (color-scheme: dark ở :root mặc
   định, [data-theme="light"] override sang sáng): giá trị --status-*-bg/-fg
   khai báo ở :root DƯỚI ĐÂY LÀ BẢN DARK (nền TRẦM lightness ~26-27%, giữ tỉ
   lệ saturation gốc của light để các trạng thái vẫn phân biệt được nhau,
   chữ SÁNG cùng tông lightness ~87%) — đây là bug cần sửa: trước đây badge/
   Gantt/legend dùng chung 1 bộ pastel sáng của light mode cho MỌI theme.
   [data-theme="light"] override lại đúng bản PASTEL NHẠT + chữ đậm cùng
   tông (nền là mã hex cụ thể user cung cấp, chữ darken 60% để đạt AA-normal
   4.5:1) — không đổi so với thiết kế light mode đã chốt trước đó.
   Tất cả 6 cặp ở CẢ HAI theme verify contrast ≥4.5:1 bằng script luminance
   chuẩn W3C (xem tools/check_status_contrast.py). */
:root {
    --status-pending-bg: #725518;       --status-pending-fg: #ebe2d1;
    --status-confirmed-bg: #183872;     --status-confirmed-fg: #d1daeb;
    --status-checkin_today-bg: #256559; --status-checkin_today-fg: #d4e7e4;
    --status-checked_in-bg: #6d481d;    --status-checked_in-fg: #eadfd2;
    --status-checked_out-bg: #50483a;   --status-checked_out-fg: #e1dfdb;
    --status-cancelled-bg: #722118;     --status-cancelled-fg: #ebd3d1;
}
:root[data-theme="light"] {
    --status-pending-bg: #fdf0d5;       --status-pending-fg: #7c6217;
    --status-confirmed-bg: #B7CDF5;     --status-confirmed-fg: #495262;
    --status-checkin_today-bg: #89D9CA; --status-checkin_today-fg: #365650;
    --status-checked_in-bg: #F2DCC2;    --status-checked_in-fg: #60584d;
    --status-checked_out-bg: #ece9e4;   --status-checked_out-fg: #6b6559;
    --status-cancelled-bg: #fbe0dd;     --status-cancelled-fg: #b03a30;
}
/* Chưa từng bấm toggle (không có data-theme lưu sẵn) + OS đang light —
   cùng lưới an toàn progressive-enhancement như TOKENS phía trên. */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="light"]):not([data-theme="dark"]) {
        --status-pending-bg: #fdf0d5;       --status-pending-fg: #7c6217;
        --status-confirmed-bg: #B7CDF5;     --status-confirmed-fg: #495262;
        --status-checkin_today-bg: #89D9CA; --status-checkin_today-fg: #365650;
        --status-checked_in-bg: #F2DCC2;    --status-checked_in-fg: #60584d;
        --status-checked_out-bg: #ece9e4;   --status-checked_out-fg: #6b6559;
        --status-cancelled-bg: #fbe0dd;     --status-cancelled-fg: #b03a30;
    }
}

.badge-status-pending       { background: var(--status-pending-bg);       color: var(--status-pending-fg); }
.badge-status-confirmed     { background: var(--status-confirmed-bg);     color: var(--status-confirmed-fg); }
.badge-status-checkin_today { background: var(--status-checkin_today-bg); color: var(--status-checkin_today-fg); }
.badge-status-checked_in    { background: var(--status-checked_in-bg);    color: var(--status-checked_in-fg); }
.badge-status-checked_out   { background: var(--status-checked_out-bg);   color: var(--status-checked_out-fg); }
.badge-status-cancelled     { background: var(--status-cancelled-bg);     color: var(--status-cancelled-fg); }

/* ===================== 7. FORM CONTROL ===================== */
.form-control, .form-select,
.form-control-sm, .form-select-sm {
    background-color: var(--bg-surface);
    border: 1.5px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: var(--text-sm);
    min-height: 40px;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-base);
}
/* Đợt 2 design audit (#4) — TRƯỚC ĐÂY ".form-control-sm"/".form-select-sm"
   KHÔNG nằm trong rule chọn phần tử ở trên (chỉ có ".form-control, .form-
   select" — không khớp class "-sm" vì CSS không tự suy ra quan hệ tên class)
   nên rơi thẳng về mặc định LIGHT-MODE của Bootstrap (nền trắng, chữ đen,
   viền xám nhạt) — ở dark theme, bộ lọc đơn đặt phòng (dùng "-sm" cho gọn)
   hiện mờ nhạt như bị disable. min-height 40px của bản thường hơi cao cho
   "-sm" nên override nhỏ hơn ngay dưới đây. */
.form-control-sm, .form-select-sm {
    min-height: 32px;
    font-size: var(--text-xs);
    padding: 6px 10px;
}
.form-control:focus, .form-select:focus,
.form-control-sm:focus, .form-select-sm:focus {
    background-color: var(--bg-surface);
    color: var(--text-primary);
    border-color: var(--brand-600);
    box-shadow: 0 0 0 3px rgba(72, 112, 191, 0.28);
}
.form-control::placeholder { color: var(--text-tertiary); }

/* Đợt 2 design audit (#3) — input[type=file] có phần "Choose Files"/"No file
   chosen" là 1 pseudo-element RIÊNG (::file-selector-button), KHÔNG được
   .form-control ở trên phủ tới (chỉ đổi được nền/viền của phần input bao
   ngoài) — trước đây phần nút bấm này hiện nguyên bản trắng chói mặc định
   trình duyệt, vỡ hoàn toàn giữa nền tối. Style nút theo đúng token
   .btn-secondary (nền bg-subtle, chữ primary) để đồng bộ với các nút phụ
   khác trong app, phần text "No file chosen" thừa kế .form-control có sẵn. */
.form-control[type="file"]::file-selector-button {
    background-color: var(--bg-subtle);
    color: var(--text-primary);
    border: 1.5px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    padding: 6px 12px;
    margin-right: var(--space-3);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.form-control[type="file"]::file-selector-button:hover {
    background-color: var(--bg-hover);
}
/* Bootstrap mặc định tô nền input disabled màu xám sáng kiểu light-mode
   (#e9ecef) — trên nền tối/card của app, chữ mờ gần như không đọc được.
   Override rõ ràng để vẫn đạt contrast tối thiểu dù đã disable. */
.form-control:disabled, .form-select:disabled,
.form-control[readonly] {
    background-color: var(--bg-subtle);
    color: var(--text-secondary);
    opacity: 1;
}
.form-label {
    color: var(--text-primary);
    font-weight: 600;
    font-size: var(--text-sm);
    margin-bottom: 6px;
}
.form-text, .form-check-label { color: var(--text-secondary); font-size: var(--text-xs); }

/* Trạng thái lỗi validate inline: field đỏ + message đỏ ngay dưới field */
.form-control.is-invalid, .form-select.is-invalid {
    border-color: var(--danger-500);
}
.form-control.is-invalid:focus, .form-select.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(255, 92, 92, 0.28);
}
.invalid-feedback {
    display: none;
    /* danger-600 (đậm) chỉ đạt AA trên nền trắng — trên nền đen mặc định
       phải dùng danger-500 (tươi, sáng hơn) mới đủ 4.5:1. */
    color: var(--danger-500);
    font-size: var(--text-xs);
    margin-top: 4px;
}
:root[data-theme="light"] .invalid-feedback {
    color: var(--danger-600);
}
.form-control.is-invalid ~ .invalid-feedback,
.form-select.is-invalid ~ .invalid-feedback {
    display: block;
}
.form-control.is-valid, .form-select.is-valid {
    border-color: var(--success-500);
}

@media (max-width: 575.98px) {
    /* Input/select tối thiểu 16px để Safari iOS không tự zoom khi bấm vào ô nhập */
    .form-control, .form-select, .form-select-sm, .form-control-sm,
    input, select, textarea {
        font-size: 16px !important;
    }
}

.badge-brand { background: var(--brand-500); color: var(--text-on-brand); }
/* Đợt 3 design audit (#9) — badge trạng thái TRUNG TÍNH (thông tin, không
   phải cảnh báo/lỗi) — dùng cho "X/N đã khai báo" khi chưa đủ NHƯNG chưa
   tới lúc cần chú ý gấp (booking còn xa ngày check-in). Trước đây không có
   class nào cho trường hợp này, mọi badge "chưa xong" đều mượn màu warning. */
.badge-neutral { background: var(--bg-subtle); color: var(--text-secondary); }

/* ===================== 7b. PROGRESS BAR ===================== */
.progress {
    background-color: var(--bg-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.progress-bar {
    background-color: var(--brand-500);
    color: var(--text-on-brand);
    font-size: var(--text-xs);
    font-weight: 600;
    transition: width var(--transition-modal);
}

/* ===================== 8. TABLE ===================== */
.table {
    color: var(--text-primary);
    font-size: var(--text-sm);
}
.table thead {
    background-color: var(--bg-subtle);
}
.table thead th {
    color: var(--text-secondary);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom-width: 1px;
}
.table > :not(caption) > * > * {
    border-bottom-color: var(--border-color);
    background-color: transparent;
    color: var(--text-primary);
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
    background-color: var(--bg-subtle);
    color: var(--text-primary);
}
.table-hover > tbody > tr:hover > * {
    background-color: var(--bg-hover);
}

/* ===================== 9. MODAL ===================== */
.modal-content {
    background: var(--bg-surface);
    color: var(--text-primary);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-lg);
}
.modal-header, .modal-footer { border-color: var(--border-color); }

/* Modal: fade + slide-up nhẹ (translateY 8px), 250-300ms */
.modal.fade .modal-dialog {
    transform: translateY(8px);
    transition: transform var(--transition-modal), opacity var(--transition-modal);
    opacity: 0;
}
.modal.show .modal-dialog {
    transform: translateY(0);
    opacity: 1;
}

/* ===================== 10. ANIMATION / MOTION ===================== */
@keyframes fadeSlideUp {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes toastSlideIn {
    from { opacity: 0; transform: translateX(16px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes skeletonPulse {
    0%, 100% { opacity: 0.55; }
    50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
