/*
 * bundle.css — AUTO-GENERATED, ĐỪNG SỬA TAY FILE NÀY
 * Được tạo bởi build_assets.py từ assets/css/*.css
 * Chạy lại: python build_assets.py
 */

/* ── 00_perf.css ─────────────────────────────────────── */
/* ============================================================
   00_perf.css — Performance Optimizations
   Loaded FIRST (alphabetically before all other CSS files).

   Goals:
   1. Promote composited layers ONLY for elements that actually
      animate — avoids triggering layout/paint on the main thread.
   2. Give the browser "contain" hints so it can skip re-layout
      of unrelated parts of the page.
   3. Globally disable expensive effects for low-end machines.

   LOW-PERF MODE được áp dụng theo 3 cách:
   A) html.low-perf       → set TỰ ĐỘNG bởi perf_detect.js
      Ngưỡng v2: CPU<=4 cores, RAM<=4GB, FPS<40 (2-sample avg)
   B) html.low-perf-manual → set bởi user bấm toggle button
      (dùng khi auto detect không hoạt động đúng)
   C) @media (prefers-reduced-motion: reduce) → OS Accessibility
   ============================================================ */

/* ── 1. GPU layer hints for known animated elements ────────────
   Only promote elements that actually animate. Over-promotion
   wastes VRAM and slows old integrated GPUs.
   ─────────────────────────────────────────────────────────────── */
.loading-spinner,
.fa-spin,
#loading-overlay {
    will-change: transform;
    transform: translateZ(0);
}

._dash-loading-callback {
    will-change: opacity;
}

/* ── 2. Containment hints ─────────────────────────────────────── */
#main-content-container {
    contain: layout;
}

#tab-content-overview,
#tab-content-compare,
#tab-content-incidents,
#tab-content-maintenance,
#tab-content-spare-parts,
#tab-content-reports {
    contain: layout paint;
}

/* ── 2b. content-visibility: auto cho tab ẩn ─────────────────────
   Browser hoàn toàn bỏ qua layout + paint cho tab chưa hiển thị.
   contain-intrinsic-size giữ placeholder height để tránh scroll jump
   khi tab được reveal lần đầu.
   NOTE: chỉ apply cho tab wrapper div, KHÔNG apply cho tab đang active
   vì Dash toggle display:none/block — content-visibility hoạt động
   tốt nhất với visibility:hidden hoặc display:none.
─────────────────────────────────────────────────────────────────── */
#tab-content-compare,
#tab-content-incidents,
#tab-content-maintenance,
#tab-content-spare-parts,
#tab-content-reports {
    content-visibility: auto;
    contain-intrinsic-size: 0 800px;
}

.modal-dialog {
    contain: layout;
}

/* ── 3. Smooth scroll ─────────────────────────────────────────── */
html {
    scroll-behavior: smooth;
}

/* ── 4. Image rendering ───────────────────────────────────────── */
img {
    image-rendering: auto;
}

/* ══════════════════════════════════════════════════════════════
   PERF TOGGLE BUTTON + BADGE STYLES
   Nằm trong .main-header-icons kế bên các button online/log/bell
   ══════════════════════════════════════════════════════════════ */

/* Toggle button — idle state (normal perf) */
#perf-toggle-btn {
    background: linear-gradient(145deg, #475569 0%, #334155 100%) !important;
    border: 1px solid rgba(148, 163, 184, 0.3) !important;
    opacity: 0.7;
}
#perf-toggle-btn:hover {
    opacity: 1;
}

/* Active state khi LOW-PERF đang bật (auto hoặc manual) */
html.low-perf #perf-toggle-btn,
html.low-perf-manual #perf-toggle-btn {
    background: linear-gradient(145deg, #7c3aed 0%, #4f46e5 100%) !important;
    border: 1px solid rgba(167, 139, 250, 0.5) !important;
    opacity: 1;
}

/* Badge "LOW" bên dưới icon toggle */
#perf-mode-badge {
    position: absolute;
    bottom: -7px;
    left: 50%;
    transform: translateX(-50%);
    background: linear-gradient(135deg, #7c3aed 0%, #4f46e5 100%);
    color: white;
    font-size: 8px;
    font-weight: 800;
    padding: 1px 4px;
    border-radius: 3px;
    white-space: nowrap;
    letter-spacing: 0.05em;
    pointer-events: none;
    display: none;
    z-index: 10;
}

/* Badge chỉ hiện khi đang ở low-perf mode */
html.low-perf #perf-mode-badge,
html.low-perf-manual #perf-mode-badge {
    display: block;
}

/* Source badge: "AUTO" vs "MAN" — set via JS bằng data-source attr */
#perf-toggle-btn[data-source="manual"] #perf-mode-badge {
    background: linear-gradient(135deg, #b45309 0%, #92400e 100%);
}

/* ══════════════════════════════════════════════════════════════
   LOW-PERF MODE
   Áp dụng cho CẢ html.low-perf (auto) VÀ html.low-perf-manual
   ══════════════════════════════════════════════════════════════ */

/* ── Scroll behavior ── */
html.low-perf,
html.low-perf-manual {
    scroll-behavior: auto !important;
}

/* ── Kill tất cả animation / transition ── */
html.low-perf *,
html.low-perf *::before,
html.low-perf *::after,
html.low-perf-manual *,
html.low-perf-manual *::before,
html.low-perf-manual *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
}

/* ── Kill backdrop-filter — most expensive GPU op on weak machines ── */
html.low-perf *,
html.low-perf-manual * {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* ── Kill box-shadow — tốn GPU composite pass trên mỗi repaint ── */
html.low-perf *,
html.low-perf-manual * {
    box-shadow: none !important;
}

/* ── Kill text-shadow ── */
html.low-perf *,
html.low-perf-manual * {
    text-shadow: none !important;
}

/* ── FIX MỚI: Kill filter: brightness() / saturate() / blur() ─────
   Vấn đề: CSS cũ chỉ kill box-shadow + transition nhưng KHÔNG kill
   filter:brightness/saturate trên :hover → vẫn trigger full paint
   pass mỗi lần hover (22_report_grid, 15_admin, 23_maint, 27_spare).
   Fix: Override filter về none cho toàn bộ elements + pseudo.
─────────────────────────────────────────────────────────────────── */
html.low-perf *,
html.low-perf *::before,
html.low-perf *::after,
html.low-perf-manual *,
html.low-perf-manual *::before,
html.low-perf-manual *::after {
    filter: none !important;
}

/* ── FIX MỚI: Kill transform trên :hover ─────────────────────────
   transform: translateY(-1px) / scale(1.1) trên hover tạo
   composited layer mới → tốn VRAM + trigger repaint.
   Giữ lại translateZ(0) cho spinner (set ở section GPU hints).

   QUAN TRỌNG: Loại trừ #react-entry-point khỏi rule này.
   #react-entry-point được applyScale() set transform:scale(X)
   qua inline style để thu nhỏ toàn bộ viewport cho màn hình nhỏ
   (ví dụ laptop 15": scale ≈ 0.71). Nếu :hover override transform
   về none thì toàn bộ viewport bị phóng to tràn ra ngoài khi hover.
─────────────────────────────────────────────────────────────────── */
/* FIX (2026-08-22 <modal phình to khi hover trên màn hình nhỏ, low-perf mode>):
   Trên màn hình nhỏ (vd laptop 14"), applyScale()/applyModalStyle() (utils_js.py)
   set transform:scale(X<1) bằng INLINE STYLE trực tiếp lên .modal-dialog — vì
   modal của Dash/Bootstrap luôn được portal thẳng ra <body>, nằm NGOÀI
   #react-entry-point, nên phải tự scale riêng (không được ăn theo transform của
   #react-entry-point). Rule dưới đây trước đây chỉ loại trừ #react-entry-point
   khỏi việc kill transform lúc hover — .modal-dialog KHÔNG được loại trừ. Vì có
   !important, hễ hover chuột vào bất kỳ đâu bên trong modal (khiến .modal-dialog,
   là ancestor, bị match :hover) là scale(X) bị ép về "none" ngay lập tức → modal
   bật về đúng kích thước gốc 100%, tràn ra ngoài khung nhìn, không thao tác được.
   Trên màn hình lớn (scale=1) thì transform vốn dĩ đã là "none" nên không lộ lỗi.
   FIX: thêm .modal-dialog vào danh sách loại trừ, giống #react-entry-point. */
html.low-perf *:not(#react-entry-point):not(.modal-dialog):hover,
html.low-perf *:not(#react-entry-point):not(.modal-dialog):focus,
html.low-perf *:not(#react-entry-point):not(.modal-dialog):active,
html.low-perf-manual *:not(#react-entry-point):not(.modal-dialog):hover,
html.low-perf-manual *:not(#react-entry-point):not(.modal-dialog):focus,
html.low-perf-manual *:not(#react-entry-point):not(.modal-dialog):active {
    transform: none !important;
}

/* ── Kill will-change ──────────────────────────────────────────── */
html.low-perf *,
html.low-perf-manual * {
    will-change: auto !important;
}
/* Giữ lại cho spinner — nó thực sự đang animate */
html.low-perf .loading-spinner,
html.low-perf .fa-spin,
html.low-perf-manual .loading-spinner,
html.low-perf-manual .fa-spin {
    will-change: transform !important;
    transform: translateZ(0) !important;
}

/* ── Replace glassmorphism với solid backgrounds ── */

/* LOW-PERF: dùng CSS variable để tự động đúng theo theme */
html.low-perf .sticky-header,
html.low-perf-manual .sticky-header {
    background: var(--bg-sticky) !important;
}
html.low-perf .sub-header-wrapper .nav-tabs,
html.low-perf .sub-header-wrapper.d-flex .nav-tabs,
html.low-perf-manual .sub-header-wrapper .nav-tabs,
html.low-perf-manual .sub-header-wrapper.d-flex .nav-tabs {
    background: var(--bg-main) !important;
}
html.low-perf .sticky-metrics,
html.low-perf-manual .sticky-metrics {
    background: var(--bg-kpi-wrapper) !important;
    border: 1px solid var(--border-color) !important;
}

/* LOW-PERF DARK MODE: giữ đúng màu tối */
[data-theme="dark"] html.low-perf .sticky-metrics,
[data-theme="dark"] html.low-perf-manual .sticky-metrics {
    background: rgba(15, 23, 42, 0.95) !important;
    border: 1px solid rgba(59, 130, 246, 0.2) !important;
}

/* LOW-PERF LIGHT MODE: override sang màu sáng */
[data-theme="light"] html.low-perf .sticky-header,
[data-theme="light"] html.low-perf-manual .sticky-header {
    background: rgba(255, 255, 255, 0.97) !important;
}
[data-theme="light"] html.low-perf .sub-header-wrapper .nav-tabs,
[data-theme="light"] html.low-perf .sub-header-wrapper.d-flex .nav-tabs,
[data-theme="light"] html.low-perf-manual .sub-header-wrapper .nav-tabs,
[data-theme="light"] html.low-perf-manual .sub-header-wrapper.d-flex .nav-tabs {
    background: rgba(248, 250, 252, 0.97) !important;
}
[data-theme="light"] html.low-perf .sticky-metrics,
[data-theme="light"] html.low-perf-manual .sticky-metrics {
    background: rgba(241, 245, 249, 0.95) !important;
    border: 1px solid rgba(79, 70, 229, 0.2) !important;
}

html.low-perf .sticky-metrics::before,
html.low-perf .sticky-metrics::after,
html.low-perf-manual .sticky-metrics::before,
html.low-perf-manual .sticky-metrics::after {
    display: none !important;
}

/* ── FIX MỚI: Replace card backdrop-filter (12_cards.css) ─────── */
/* Light mode: solid white card */
html.low-perf .card,
html.low-perf-manual .card {
    background: rgba(255, 255, 255, 0.98) !important;
}
/* Dark mode: solid dark card — dùng html[data-theme] để tăng specificity */
html[data-theme="dark"].low-perf .card,
html[data-theme="dark"].low-perf-manual .card,
[data-theme="dark"] html.low-perf .card,
[data-theme="dark"] html.low-perf-manual .card {
    background: rgba(30, 41, 59, 0.98) !important;
}

/* ── Tắt decorative ::before/::after có filter ── */
html.low-perf .card::before,
html.low-perf .card::after,
html.low-perf .modal-content::before,
html.low-perf .modal-content::after,
html.low-perf-manual .card::before,
html.low-perf-manual .card::after,
html.low-perf-manual .modal-content::before,
html.low-perf-manual .modal-content::after {
    display: none !important;
}

/* ── FIX MỚI: Đơn giản hóa alert-bell-container ────────────────
   07_components.css: nhiều box-shadow layer + cubic-bezier +
   scale(1.1) hover → tạo expensive composite context.
   Đã kill box-shadow + transition + transform bởi rules trên.
   Thêm: flatten background gradient → solid color.
─────────────────────────────────────────────────────────────── */
html.low-perf .alert-bell-container,
html.low-perf-manual .alert-bell-container {
    background: #4a5568 !important;
    border: 1px solid rgba(148, 163, 184, 0.35) !important;
}
html.low-perf .alert-badge,
html.low-perf-manual .alert-badge {
    background: #ef4444 !important;
    /* animation pulse đã bị kill bởi animation-duration rule */
}

/* ── FIX MỚI: Tắt shimmer/skeleton effects ─────────────────────
   background-size animation + gradient shift → expensive paint
─────────────────────────────────────────────────────────────── */
html.low-perf [class*="shimmer"],
html.low-perf [class*="skeleton"],
html.low-perf-manual [class*="shimmer"],
html.low-perf-manual [class*="skeleton"] {
    background-image: none !important;
    background-color: rgba(148, 163, 184, 0.15) !important;
}

/* ── FIX MỚI: Flatten KPI sticky-metrics gradient ───────────────
   05_layout.css: sticky-metrics có kpiBgShift 12s + kpiPulse 4s
   + 2 shimmer ::before/::after animations chạy liên tục.
   Animation đã bị kill bởi animation-duration rule ở trên,
   nhưng background-size: 400% 400% + gradient vẫn tốn paint.
   Flatten về solid color để giảm composite cost.
─────────────────────────────────────────────────────────────── */
/* (Đã được xử lý trong block "Replace glassmorphism" ở trên với light/dark split) */

/* ── FIX MỚI: Tắt Plotly hover tooltip trong low-perf ──────────
   Mỗi mousemove qua chart Plotly tính nearest data point O(n).
   Trên máy yếu với nhiều chart sẽ block main thread.
   Dùng CSS pointer-events để bypass Plotly hover computation.
─────────────────────────────────────────────────────────────── */
html.low-perf .js-plotly-plot .nsewdrag,
html.low-perf .js-plotly-plot .drag,
html.low-perf-manual .js-plotly-plot .nsewdrag,
html.low-perf-manual .js-plotly-plot .drag {
    pointer-events: none !important;
}

/* ── 5. @media fallback (OS Accessibility / DevTools emulation) ─ */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }

    * {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        box-shadow: none !important;
        text-shadow: none !important;
        will-change: auto !important;
        filter: none !important;
    }

    /* Cùng fix modal-scale với block html.low-perf ở trên — xem comment đầy đủ
       phía trên (FIX 2026-08-22 <modal phình to khi hover trên màn hình nhỏ>). */
    *:not(#react-entry-point):not(.modal-dialog):hover,
    *:not(#react-entry-point):not(.modal-dialog):focus,
    *:not(#react-entry-point):not(.modal-dialog):active {
        filter: none !important;
        transform: none !important;
    }

    .sticky-header {
        background: var(--bg-sticky) !important;
    }
    .sub-header-wrapper .nav-tabs,
    .sub-header-wrapper.d-flex .nav-tabs {
        background: var(--bg-main) !important;
    }
    .sticky-metrics {
        background: var(--bg-kpi-wrapper) !important;
    }
    [data-theme="light"] .sticky-header {
        background: rgba(255, 255, 255, 0.97) !important;
    }
    [data-theme="light"] .sub-header-wrapper .nav-tabs,
    [data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs {
        background: rgba(248, 250, 252, 0.97) !important;
    }
    [data-theme="light"] .sticky-metrics {
        background: rgba(241, 245, 249, 0.95) !important;
    }
    .alert-bell-container {
        background: #4a5568 !important;
    }
    .alert-bell-container:hover {
        transform: none !important;
    }
}

/* ══════════════════════════════════════════════════════════════
   SERVER STATS BADGE (#server-stats-btn)
   Hiển thị FPS + CPU%/RAM% bên trái perf-toggle-btn
   ══════════════════════════════════════════════════════════════ */

#server-stats-btn {
    /* Override fixed 42x42 từ .alert-bell-container */
    width: auto !important;
    height: 42px !important;
    min-width: unset !important;
    padding: 0 8px !important;
    gap: 0px;
    cursor: default !important;
    background: linear-gradient(145deg, #1e3a5f 0%, #0f2744 100%) !important;
    border: 1px solid rgba(99, 179, 237, 0.3) !important;
    /* Flex column: 2 dòng xếp dọc */
    flex-direction: column !important;
    justify-content: center !important;
    align-items: flex-start !important;
    overflow: visible !important;
}
#server-stats-btn:hover {
    transform: none !important;
}

/* 2 dòng: line1=FPS·CPU%, line2=RAM */
.stats-badge-line {
    font-size: 9.5px;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: 0.02em;
    color: #cbd5e0;
    transition: color 0.3s;
    line-height: 1.3;
    display: block;
}

/* FPS colors */
.stats-badge-line.fps-good  { color: #68d391; }   /* xanh lá — >= 50 fps */
.stats-badge-line.fps-warn  { color: #f6e05e; }   /* vàng    — 30-49 fps */
.stats-badge-line.fps-bad   { color: #fc8181; }   /* đỏ      — < 30 fps  */

/* RAM colors */
.stats-badge-line.ram-good  { color: #90cdf4; }   /* xanh dương — < 70%  */
.stats-badge-line.ram-warn  { color: #f6ad55; }   /* cam         — 70-85% */
.stats-badge-line.ram-bad   { color: #fc8181; }   /* đỏ          — > 85%  */

/* Badge đổi viền khi RAM critical */
#server-stats-btn[data-ram="warn"] {
    border-color: rgba(246, 173, 85, 0.5) !important;
}
#server-stats-btn[data-ram="bad"] {
    border-color: rgba(252, 129, 129, 0.6) !important;
    box-shadow: 0 0 6px rgba(252, 129, 129, 0.3) !important;
}

/* Light mode */
[data-theme="light"] #server-stats-btn {
    background: linear-gradient(145deg, #dbeafe 0%, #bfdbfe 100%) !important;
    border-color: rgba(59, 130, 246, 0.4) !important;
}
[data-theme="light"] .stats-badge-line             { color: #374151; }
[data-theme="light"] .stats-badge-line.fps-good    { color: #15803d; }
[data-theme="light"] .stats-badge-line.fps-warn    { color: #b45309; }
[data-theme="light"] .stats-badge-line.fps-bad     { color: #dc2626; }
[data-theme="light"] .stats-badge-line.ram-good    { color: #1d4ed8; }
[data-theme="light"] .stats-badge-line.ram-warn    { color: #c2410c; }
[data-theme="light"] .stats-badge-line.ram-bad     { color: #dc2626; }

/* Low-perf: tắt transition để giảm tải */
html.low-perf #server-stats-btn,
html.low-perf-manual #server-stats-btn {
    transition: none !important;
}
html.low-perf .stats-badge-line,
html.low-perf-manual .stats-badge-line {
    transition: none !important;
}

/* ── 01_variables.css ────────────────────────────────── */
/* ============================================================
   01_variables.css — CSS Custom Properties - Light & Dark Themes
   Auto-refactored from custom.css
   ============================================================ */

/* === CSS Variables - Light Theme (Default) === */
:root, [data-theme="light"] {
    --navbar-height: 90px;
    --sticky-header-height: 60px;
    --sticky-metrics-height: 100px;
    --sticky-title-height: 45px;
    --primary-color: #4f46e5;
    --primary-dark: #3730a3;
    --primary-light: #818cf8;
    --secondary-color: #0ea5e9;
    --success-color: #10b981;
    --warning-color: #f59e0b;
    --danger-color: #ef4444;
    --bg-light: #f1f5f9;
    --bg-main: #f8fafc;
    --bg-card: #ffffff;
    --bg-section: #f8fafc;
    --bg-kpi-wrapper: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
    --bg-chart-wrapper: #ffffff;
    --bg-analysis: linear-gradient(135deg, #fafafa 0%, #f5f5f5 100%);
    --bg-sidebar: linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%);
    --bg-sticky: linear-gradient(180deg, #f8fafc 0%, rgba(248,250,252,0.98) 100%);
    --text-primary: #1e293b;
    --text-secondary: #475569;
    --text-muted: #64748b;
    --border-color: #e2e8f0;
    --border-section: #cbd5e1;
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
    --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    --transition-fast: 0.15s ease;
    --transition-normal: 0.3s ease;
    --border-radius: 12px;
    --table-header-bg: #4f46e5;
    --table-row-odd: #f8fafc;
    --table-row-hover: rgba(79,70,229,0.05);
    --chart-bg: #ffffff;
    --scrollbar-track: #f1f5f9;
    --scrollbar-thumb: #cbd5e1;
    --scrollbar-thumb-hover: #94a3b8;
    --modal-bg: #ffffff;
}

/* === CSS Variables - Dark Theme === */
[data-theme="dark"] {
    --primary-color: #818cf8;
    --primary-dark: #6366f1;
    --primary-light: #a5b4fc;
    --secondary-color: #38bdf8;
    --success-color: #34d399;
    --warning-color: #fbbf24;
    --danger-color: #f87171;
    --bg-light: #0f172a;
    --bg-main: #1e293b;
    --bg-card: #1e293b;
    --bg-section: #1e293b;
    --bg-kpi-wrapper: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    --bg-chart-wrapper: #1e293b;
    --bg-analysis: linear-gradient(135deg, #1e293b 0%, #162032 100%);
    --bg-sidebar: linear-gradient(180deg, #1e293b 0%, #0f172a 100%);
    --bg-sticky: linear-gradient(180deg, #1e293b 0%, rgba(30,41,59,0.98) 100%);
    --text-primary: #f1f5f9;
    --text-secondary: #e2e8f0;
    --text-muted: #cbd5e1;
    --border-color: #334155;
    --border-section: #475569;
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
    --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.3);
    --table-header-bg: #4f46e5;
    --table-row-odd: #283548;
    --table-row-hover: rgba(129,140,248,0.15);
    --chart-bg: #1e293b;
    --chart-paper-bg: #1e293b;
    --chart-grid-color: #334155;
    --chart-text-color: #e2e8f0;
    --scrollbar-track: #1e293b;
    --scrollbar-thumb: #475569;
    --scrollbar-thumb-hover: #94a3b8;
    --modal-bg: #1e293b;
}

/* ── 02_base.css ─────────────────────────────────────── */
/* ============================================================
   02_base.css — Base / Reset Styles
   Auto-refactored from custom.css
   ============================================================ */

/* === Base Styles === */
html, body {
    height: 100%;
    margin: 0;
    overflow: hidden;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background-color: var(--bg-light);
}
#react-entry-point {
    height: 100%;
    display: flex;
    flex-direction: column;
}

/* ── 03_navbar.css ───────────────────────────────────── */
/* ============================================================
   03_navbar.css — Navbar · Logo · Sync Animation · Loading Overlay
   Auto-refactored from custom.css
   ============================================================ */

/* === Enhanced Navbar === */
#main-navbar,
#main-navbar.navbar,
.navbar,
:root .navbar,
[data-theme="light"] .navbar,
[data-theme="light"] #main-navbar,
[data-theme="dark"] .navbar,
[data-theme="dark"] #main-navbar {
    flex-shrink: 0;
    background: linear-gradient(135deg, #0c4a6e 0%, #0369a1 100%) !important;
    box-shadow: var(--shadow-lg);
    border-bottom: 1px solid #0284c7;
    padding: 8px 20px 8px 15px !important;
}
/* Mobile: bỏ hoàn toàn padding trái/phải navbar */
body.is-mobile-device #main-navbar,
body.is-mobile-device #main-navbar.navbar,
body.is-mobile-device .navbar,
body.is-mobile-device :root .navbar,
body.is-mobile-device [data-theme="light"] .navbar,
body.is-mobile-device [data-theme="light"] #main-navbar,
body.is-mobile-device [data-theme="dark"] .navbar,
body.is-mobile-device [data-theme="dark"] #main-navbar {
    padding: 0 !important;
}
/* Navbar flex container - pure flexbox, no Bootstrap grid */
#navbar-flex-container {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    width: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
}
.navbar h4 {
    font-weight: 700;
    letter-spacing: -0.5px;
    text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#current-time {
    font-weight: 500;
}

/* === Logo Styling === */
#company-logo {
    background: transparent !important;
    background-color: transparent !important;
    padding: 0 !important;
    margin: 0 !important;
    border-radius: 0;
    box-shadow: none;
    transition: all 0.3s ease;
}
#company-logo:hover {
    transform: scale(1.05);
}

/* === Sync Loading Animation === */
@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}
.fa-spin-custom {
    animation: spin 1s linear infinite;
}
.sync-loading {
    animation: spin 1s linear infinite;
    color: #0ea5e9;
}

/* === Loading Overlay === */
#loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 9999;
    backdrop-filter: blur(3px);
}
#loading-overlay.active {
    display: flex;
}
#loading-overlay .loading-content {
    background: white;
    padding: 30px 50px;
    border-radius: 15px;
    text-align: center;
    box-shadow: 0 10px 40px rgba(0,0,0,0.3);
}
#loading-overlay .loading-spinner {
    font-size: 2.5rem;
    color: var(--primary-color);
    animation: spin 1s linear infinite;
    margin-bottom: 15px;
}
#loading-overlay .loading-text {
    font-size: 1.1rem;
    color: #333;
    font-weight: 500;
}

/* ── 04_sidebar.css ──────────────────────────────────── */
/* ============================================================
   04_sidebar.css — Sidebar · Accordion · Sync Button · DatePicker Fixes
   Auto-refactored from custom.css
   ============================================================ */

/* === Enhanced Sidebar === */
.sidebar {
    position: fixed;
    top: var(--navbar-height);
    left: 0;
    bottom: 0;
    width: 300px;
    padding: 1.25rem;
    background: var(--bg-sidebar);
    overflow: visible !important; /* Fix: Để tab toggle không bị cắt mất */
    border-right: none;
    box-shadow: 4px 0 15px rgba(0, 0, 0, 0.05);
    z-index: 1100;
}

/* === Sidebar Sticky & Scrollable Sections === */
.sidebar {
    display: flex;
    flex-direction: column;
    padding: 0 !important;
}
.sidebar-sticky-section {
    position: sticky;
    top: 0;
    z-index: 10;
    background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
    padding: 1.25rem 1.25rem 0.5rem 1.25rem;
    border-bottom: 1px solid rgba(0,0,0,0.05);
    box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.sidebar-scrollable-section {
    flex: 1;
    overflow-y: auto;
    overflow-x: clip; /* clip thay vì hidden — ngăn scroll ngang nhưng không tạo stacking context mới */
    padding: 0.75rem 1.25rem 1.25rem 1.25rem;
}

/* === Sync Button === */
.sidebar .btn-primary {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
    border: none;
    border-radius: 10px;
    font-weight: 600;
    padding: 12px 20px;
    box-shadow: var(--shadow-md);
    transition: all var(--transition-normal);
}
.sidebar .btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    filter: brightness(1.1);
}
.sidebar .btn-primary:active {
    transform: translateY(0);
}

/* === Accordion Styling === */
.accordion {
    border-radius: var(--border-radius) !important;
    overflow: visible !important;
    box-shadow: var(--shadow-sm);
}
.accordion-item {
    border: none !important;
    background: white;
    overflow: visible !important;
}
.accordion-collapse {
    overflow: visible !important;
    transition: height 0.35s ease, opacity 0.25s ease !important;
}
.accordion-collapse.collapsing {
    height: 0;
    overflow: hidden !important;
    transition: height 0.35s ease !important;
}
.accordion-collapse.show {
    opacity: 1;
}
.accordion-collapse:not(.show) {
    opacity: 0;
}

/* LOW-PERF: Disable sidebar accordion expand/collapse animations */
html.low-perf .accordion-collapse,
html.low-perf-manual .accordion-collapse {
    transition: none !important;
}
html.low-perf .accordion-collapse.collapsing,
html.low-perf-manual .accordion-collapse.collapsing {
    transition: none !important;
    height: 0;
}
html.low-perf .accordion-button,
html.low-perf-manual .accordion-button {
    transition: none !important;
}
.accordion-button {
    font-weight: 600;
    font-size: 1rem;
    padding: 14px 16px;
    background: white !important;
    box-shadow: none !important;
    transition: all var(--transition-fast);
    border-radius: var(--border-radius) !important;
    cursor: pointer !important;
    pointer-events: auto !important;
    position: relative;
    z-index: 1;
}
.accordion-button:not(.collapsed) {
    color: var(--primary-color);
    background: linear-gradient(135deg, rgba(79,70,229,0.05) 0%, rgba(14,165,233,0.05) 100%) !important;
    border-radius: var(--border-radius) var(--border-radius) 0 0 !important;
}
.accordion-button:hover {
    background: rgba(0,0,0,0.02) !important;
}
.accordion-body {
    padding: 16px;
    background: white;
    overflow: visible !important;
}

/* === Fix Dropdown Overflow in Sidebar === */
.sidebar .Select-menu-outer {
    position: absolute !important;
    z-index: 9999 !important;
    max-height: 240px !important;
    overflow-y: auto !important;
}
.sidebar .Select {
    position: relative;
}

/* === DatePicker z-index and overflow fix === */
.SingleDatePicker_picker,
.DateRangePicker_picker {
    z-index: 2147483647 !important; /* Max z-index */
    position: fixed !important;
    top: auto;
    left: auto;
    display: block;
}
.DayPicker,
.DayPicker_portal {
    z-index: 2147483647 !important;
}
.SingleDatePickerInput,
.DateRangePickerInput {
    position: relative;
    z-index: 10;
}
.SingleDatePicker, .DateRangePicker {
    position: relative;
    z-index: 10;
    display: block;
}
/* Only inner containers need overflow visible - NOT sidebar itself */
.sidebar .accordion,
.sidebar .accordion-item,
.sidebar .accordion-collapse,
.sidebar .accordion-body,
#custom-date-pickers,
#start-date-wrapper,
#end-date-wrapper {
    overflow: visible !important;
}
/* Wrapper positioning */
#start-date-wrapper,
#end-date-wrapper {
    position: relative;
}
/* Ensure sidebar is above main content */
.sidebar {
    z-index: 1100 !important;
}
#main-content-container {
    z-index: 1;
}

/* === Fix Accordion Stacking Context for DatePicker === */
.sidebar .accordion-item {
    position: relative;
    z-index: 1;
}
.sidebar .accordion-item:hover,
.sidebar .accordion-item:focus-within {
    z-index: 100;
}
/* Ensure active datepicker container is on top */
.sidebar .accordion-item.datepicker-active {
    z-index: 1000 !important;
}

/* === Fix: Multiselect Dropdown trong Sidebar ===
 * Áp dụng cho TẤT CẢ .Select--multi trong sidebar (system, type, category, status...)
 * React-Select v1/v2: Select-control dùng display:table → tự expand theo content
 * Fix: override toàn bộ bằng flex layout
 * ============================================================ */

/* .Select container — width cố định theo parent */
.sidebar-scrollable-section .Select {
    position: relative !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
}

/* Select-control: đổi display:table → flex
   height: auto để tự giãn khi nhiều tags, mũi tên luôn căn giữa */
.sidebar-scrollable-section .Select-control {
    display: flex !important;
    align-items: stretch !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 36px !important;
    box-sizing: border-box !important;
    overflow: visible !important;
}

/* Tags wrapper: flex-wrap để tags xuống nhiều dòng, không clip height */
.sidebar-scrollable-section .Select-multi-value-wrapper {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    flex: 1 !important;
    min-width: 0 !important;
    overflow: visible !important;
    height: auto !important;
    padding: 3px 0 !important;
}

/* Mỗi tag: inline-flex, text 1 dòng với ellipsis */
.sidebar-scrollable-section .Select-value {
    display: inline-flex !important;
    align-items: center !important;
    max-width: 100% !important;
    min-width: 0 !important;
    overflow: hidden !important;
    flex-shrink: 1 !important;
}
.sidebar-scrollable-section .Select-value-label {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    min-width: 0 !important;
}
.sidebar-scrollable-section .Select-value-icon {
    flex-shrink: 0 !important;
}

/* Input ẩn trong control — không expand width */
.sidebar-scrollable-section .Select-input {
    flex-shrink: 0 !important;
    min-width: 0 !important;
}
.sidebar-scrollable-section .Select-input > input {
    min-width: 0 !important;
    width: 5px !important;
}

/* Arrow zone: fill full height, icon căn giữa */
.sidebar-scrollable-section .Select-arrow-zone {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    align-self: stretch !important;
    flex-shrink: 0 !important;
    width: 25px !important;
    visibility: visible !important;
    opacity: 1 !important;
}
.sidebar-scrollable-section .Select-arrow {
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Menu dropdown: bám theo .Select, không expand ra ngoài
   FIX: thêm max-height + overflow-y:auto — nếu không có, menu render
   TOÀN BỘ option (không tự scroll bên trong) rồi bị sidebar cha
   (.sidebar-scrollable-section có overflow-y:auto) CẮT HÌNH phần thừa,
   khiến phần bị che khuất không thể cuộn tới bằng con lăn chuột (vì bản
   thân khung menu không có scrollbar nội bộ để nhận sự kiện wheel). */
.sidebar-scrollable-section .Select-menu-outer {
    position: absolute !important;
    top: 100% !important;
    left: 0 !important;
    right: 0 !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    max-height: 240px !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    box-sizing: border-box !important;
    z-index: 9999 !important;
}

/* Accordion body chứa dropdown — overflow visible để menu hiện đúng */
.sidebar-scrollable-section .accordion-body {
    overflow: visible !important;
}
.sidebar-scrollable-section .accordion,
.sidebar-scrollable-section .accordion-item,
.sidebar-scrollable-section .accordion-collapse {
    overflow: visible !important;
}

/* ── FIX (Yêu cầu mới — dropdown "Bộ lọc Lịch ca" đôi khi nhảy sai vị trí
   trên màn hình nhỏ, vd laptop 14") ────────────────────────────────────
   Gia cố thêm 1 lớp CSS specificity cao + !important dành RIÊNG cho
   #shift-filter-container (Team/Năm/Tháng/Tuần/Nhân viên), đề phòng
   trường hợp rule chung ".sidebar-scrollable-section .Select-menu-outer"
   ở trên bị 1 rule khác (load sau, cùng specificity) ghi đè khiến menu
   dropdown không còn bám đúng theo ".Select" cha của nó nữa. Đảm bảo mỗi
   ".Select" trong khu vực filter này luôn là 1 positioning-context độc
   lập (position:relative) và menu của nó luôn neo bằng CSS % (top:100%)
   — không lệ thuộc bất kỳ toạ độ px tính bằng JS nào — để không bị ảnh
   hưởng bởi transform:scale() của applyScale() (utils_js.py) khi
   window.outerWidth < 1920 (rất phổ biến ở màn hình 14"). */
#shift-filter-container .Select {
    position: relative !important;
}
#shift-filter-container .Select-menu-outer {
    position: absolute !important;
    top: 100% !important;
    bottom: auto !important;
    left: 0 !important;
    right: 0 !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    max-height: 240px !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    box-sizing: border-box !important;
    z-index: 9999 !important;
    transform: none !important;
}

/* ── FIX (2026-07-29): Dropdown "Chọn nhà máy" (global-location-selector) nằm
   trong .sidebar-sticky-section bị che/crop mất phần dưới khi mở menu.
   Nguyên nhân: khác với các dropdown trong .sidebar-scrollable-section và
   #shift-filter-container (đã được fix riêng .Select-menu-outer ở trên), dropdown
   này chưa có z-index/position/max-height riêng nên menu render không đúng lớp,
   bị nội dung phía dưới (khối nút Restart Server / Admin / Layout...) đè lên,
   khiến phần dưới của option bị che khuất. Áp dụng cùng pattern fix. ────────── */
.sidebar-sticky-section {
    overflow: visible !important;
}
#global-location-selector-wrapper,
#global-location-selector-wrapper .lang-dropdown-wrapper {
    overflow: visible !important;
}
#global-location-selector-wrapper .Select {
    position: relative !important;
}
#global-location-selector-wrapper .Select-menu-outer {
    position: absolute !important;
    top: 100% !important;
    bottom: auto !important;
    left: 0 !important;
    right: 0 !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    max-height: 240px !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    box-sizing: border-box !important;
    z-index: 9999 !important;
    transform: none !important;
}

/* ── 05_layout.css ───────────────────────────────────── */
/* ============================================================
   05_layout.css — Main Content · Sticky Elements · Table Header Fix
   Auto-refactored from custom.css
   ============================================================ */

/* === Main Content Area === */
/* FIX <1>: Layout 3-layer để scroll Y nằm bên trong vùng content:
   Layer 1 — #main-content-container: height = viewport - navbar, overflow:hidden
   Layer 2 — .main-content: flex column, height:100%, overflow:hidden
             → chia thành: sticky-header (flex:0) + #tab-content-wrapper (flex:1)
   Layer 3 — #tab-content-wrapper: overflow-y:auto → scroll bar nằm ở đây,
             bên trong vùng content, KHÔNG lộ ra cạnh phải viewport.
   overflow-x: clip giữ nguyên để scroll X của bảng con hoạt động đúng. */
#main-content-container {
    margin-left: 300px; /* sidebar width */
    height: calc(100vh - var(--navbar-height)); /* full height below navbar */
    box-sizing: border-box;
    overflow: hidden;   /* KHÔNG scroll ngoài */
    overflow-x: clip;
    background: var(--bg-main);
}
.main-content {
    /* padding-left 40px = toggle tab width(32px) + 8px gap → nội dung không bao giờ bị che */
    padding: 0 1.5rem 0 40px;
    background: var(--bg-main);
    height: 100%;
    box-sizing: border-box;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
/* FIX <1>: #tab-content-wrapper là scroll root thực sự.
   Nó nằm dưới .sticky-header (flex:0 shrink) nên không bị che.
   flex:1 → chiếm toàn bộ chiều cao còn lại sau sticky-header.
   overflow-y: auto → scrollbar Y nằm bên trong vùng content.
   
   KEY FIX: scrollbar chạy đúng chiều cao của wrapper.
   Để scrollbar KHÔNG bị footer che, wrapper phải có margin-bottom
   bằng đúng chiều cao footer (không dùng padding-bottom vì padding
   không ảnh hưởng đến chiều cao scrollbar track).
   --copyright-footer-height được set bởi JS (đo thực tế footer).
   Fallback 26px = padding(5+4) + font ~11px + border ~1px + buffer. */
#tab-content-wrapper {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: clip;
    padding: 0.35rem 0 8px 0;
    margin-bottom: var(--copyright-footer-height, 26px);
    box-sizing: border-box;
    /* FIX: scrollbar-gutter:stable giữ chỗ cho scrollbar track ngay cả khi
       scrollbar bị ẩn tạm thời (tab inactive / browser repaint).
       Ngăn layout shift và giúp scrollbar tái hiện sau khi tab quay lại visible.
       Fallback: browsers không hỗ trợ sẽ bỏ qua property này (safe). */
    scrollbar-gutter: stable;
}
/* FIX: Force scrollbar luôn visible (không ẩn khi nội dung vừa vặn).
   Đây là defense-in-depth: scroll_restore.js sẽ fix khi tab quay lại,
   CSS này ngăn scrollbar biến mất do content-height thay đổi nhỏ. */
#tab-content-wrapper {
    /* Đảm bảo overflow-y luôn được enforce, không bị browser reset */
    overflow-y: auto !important;
}

/* Scrollbar styling cho tab-content-wrapper — khớp style với các bảng */
#tab-content-wrapper::-webkit-scrollbar { width: 6px; }
#tab-content-wrapper::-webkit-scrollbar-track { background: var(--scrollbar-track); }
#tab-content-wrapper::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 3px; }
#tab-content-wrapper::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }

/* FIX DOUBLE SCROLL: Khi sub-tab có bảng scroll riêng đang visible,
   tắt scroll ngoài #tab-content-wrapper để tránh 2 thanh scroll chồng nhau.

   ROOT CAUSE BUG (đã fix):
   Selector cũ chỉ check display:none trên sub-content div (vd: #inc-content-details)
   nhưng KHÔNG check parent tab (#tab-content-incidents).
   Khi user chuyển sang tab Báo cáo:
     - #tab-content-incidents → display:none (set bởi Dash clientside callback)
     - #inc-content-details   → KHÔNG có inline display style
   → :has() thấy #inc-content-details không có "display: none" → MATCH sai
   → overflow-y: hidden được set trên #tab-content-wrapper
   → scroll Y biến mất trên TẤT CẢ các tab sau đó!

   FIX: Thêm điều kiện parent tab phải đang display:block.
   Dash clientside callback set: {'display': 'block'} hoặc {'display': 'none'}
   trực tiếp lên #tab-content-incidents / #tab-content-maintenance / #tab-content-spare-parts.
   Dùng [style*="display: block"] để chỉ match khi tab đang THỰC SỰ hiển thị.

   Các bảng có scroll riêng (inc-detail-table-scroll / maint-planning-table-scroll):
   - #inc-content-details         → Chi tiết Sự cố         (parent: #tab-content-incidents)
   - #maint-content-maint-details → Chi tiết Bảo trì (cũ)  (parent: #tab-content-maintenance)
   - #maint-content-planning      → Planning Bảo trì        (parent: #tab-content-maintenance)
   - #sp-content-inventory        → Tồn kho Phụ tùng        (parent: #tab-content-spare-parts)
   - #sp-content-in               → Nhập kho                (parent: #tab-content-spare-parts)
   - #sp-content-out              → Xuất kho                (parent: #tab-content-spare-parts)
   - #sp-content-jit              → JIT Active              (parent: #tab-content-spare-parts)
   - #sp-content-forecast         → Dự báo                  (parent: #tab-content-spare-parts)
   - #sp-content-alerts           → Cảnh báo                (parent: #tab-content-spare-parts)
   - #shift-subtab-content-employees → Nhân viên (Ca làm việc) (parent: #tab-content-shift)
   - #shift-subtab-content-stats     → Thống kê (Ca làm việc)  (parent: #tab-content-shift)
*/
#tab-content-wrapper:has(
    #tab-content-shift[style*="display: block"]
    #shift-subtab-content-employees[style*="display: block"]
    #shift-employees-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-shift[style*="display: block"]
    #shift-subtab-content-stats[style*="display: block"]
    #shift-stats-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-incidents[style*="display: block"]
    #inc-content-details:not([style*="display: none"])
    .inc-detail-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-maintenance[style*="display: block"]
    #maint-content-maint-details:not([style*="display: none"])
    .inc-detail-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-maintenance[style*="display: block"]
    #maint-content-planning:not([style*="display: none"])
    .maint-planning-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-inventory:not([style*="display: none"])
    .inc-detail-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-in:not([style*="display: none"])
    .inc-detail-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-out:not([style*="display: none"])
    .inc-detail-table-scroll
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-jit:not([style*="display: none"])
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-forecast:not([style*="display: none"])
),
#tab-content-wrapper:has(
    #tab-content-spare-parts[style*="display: block"]
    #sp-content-alerts:not([style*="display: none"])
) {
    overflow-y: hidden !important;
}
/* login-lock-screen: cũng là con trực tiếp của .main-content, cần flex:1 */
#login-lock-screen {
    flex: 1 1 0;
    min-height: 0;
}

/* === Overview KPI Sticky Bar ===
   Nằm NGOÀI #tab-content-wrapper (scroll container) → không bị scroll.
   flex:0 shrink:0 → chiếm đúng chiều cao nội dung, không flex-grow.
   .sticky-metrics bên trong sẽ không cần position:sticky nữa vì
   bản thân #overview-kpi-sticky đã nằm ngoài vùng scroll rồi. */
#overview-kpi-sticky {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    position: relative !important;
    top: auto !important;
}

/* === Incidents Sub-Header Sticky Bar ===
   Nằm NGOÀI #tab-content-wrapper → không bị scroll.
   Không dùng class d-flex vì Bootstrap .d-flex { display:flex !important }
   sẽ override display:none. Thay vào đó dùng display:flex trực tiếp khi visible. */
#inc-sub-header-sticky {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    /* Override position:sticky từ .sub-header-wrapper — không cần vì đã ngoài scroll */
    position: relative !important;
    top: auto !important;
    /* Giữ lại style của .sub-header-wrapper.d-flex */
    align-items: center;
    border-bottom: 1px solid rgba(99, 102, 241, 0.35) !important;
    box-shadow: 0 1px 0 rgba(99, 102, 241, 0.15);
    padding: 0 !important;
}
/* Khi visible, #inc-sub-header-sticky được callback set display:flex qua inline style */

/* === Maintenance Sub-Header Sticky Bar ===
   Nằm NGOÀI #tab-content-wrapper → không bị scroll.
   Pattern giống #inc-sub-header-sticky. */
#maint-sub-header-sticky {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    position: relative !important;
    top: auto !important;
    align-items: center;
    border-bottom: 1px solid rgba(99, 102, 241, 0.35) !important;
    box-shadow: 0 1px 0 rgba(99, 102, 241, 0.15);
    padding: 0 !important;
    /* KHÔNG dùng d-flex class vì Bootstrap !important sẽ override display:none từ inline style */
    /* display được quản lý hoàn toàn bởi inline style từ callback */
}

/* === Maintenance Checklist Filter Bar Sticky ===
   Nằm NGOÀI #tab-content-wrapper → không bị scroll.
   Chỉ visible khi sub-tab Chi tiết Checklist active. */
#maint-cl-filter-sticky {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    position: relative !important;
    top: auto !important;
}
/* Inner controls bar: padding + border */
#maint-cl-filter-sticky .maint-cl-controls-bar {
    padding: 6px 14px 6px 0;
}

/* Report Sub-Header Sticky Bar — nằm NGOÀI scroll container, không bị scroll */
#report-sub-header-sticky {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    position: relative !important;
    top: auto !important;
    border-bottom: 1px solid rgba(99, 102, 241, 0.35) !important;
    box-shadow: 0 1px 0 rgba(99, 102, 241, 0.15);
    padding: 0 !important;
}
/* Khi visible, #report-sub-header-sticky được callback set display:block qua inline style */

/* === Force sticky parents === */
#tab-content,
#tab-content > div,
.sub-header-wrapper {
    overflow: visible !important;
    position: -webkit-sticky;
    position: sticky;
    top: var(--sticky-tabs-top, 0px);
    z-index: 1007;
}

/* === Sticky Elements === */
.sticky-header {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
    background: var(--bg-sticky);
    backdrop-filter: blur(10px);
    z-index: 1010;
    /* Reduced vertical padding so 42px icons + 6px badges are not cropped */
    padding: 8px 14px 8px 0;
    border-bottom: 1px solid var(--border-color);
    overflow: visible;
    min-height: 58px;
    box-sizing: border-box;
}
/* Shimmer animation for KPI container */
@keyframes kpiShimmer {
    0% { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}
@keyframes kpiBorderGlow {
    0%, 100% { opacity: 0.5; }
    50% { opacity: 1; }
}
@keyframes kpiPulse {
    0%, 100% { box-shadow: 0 0 5px rgba(59, 130, 246, 0.3), 0 4px 15px rgba(0, 0, 0, 0.1); }
    50% { box-shadow: 0 0 20px rgba(59, 130, 246, 0.5), 0 4px 20px rgba(0, 0, 0, 0.15); }
}
@keyframes kpiBgShift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}
.sticky-metrics {
    position: -webkit-sticky;
    position: sticky;
    top: var(--sticky-header-top, 0px);
    background: linear-gradient(-45deg, 
        rgba(59, 130, 246, 0.08), 
        rgba(139, 92, 246, 0.08), 
        rgba(236, 72, 153, 0.06), 
        rgba(16, 185, 129, 0.08),
        rgba(59, 130, 246, 0.08));
    background-size: 400% 400%;
    animation: kpiBgShift 12s ease infinite, kpiPulse 4s ease-in-out infinite;
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    z-index: 1009;
    padding: 15px;
    margin-bottom: 15px;
    border-radius: 16px;
    border: 1px solid transparent;
    box-shadow: 0 0 10px rgba(59, 130, 246, 0.2), 0 4px 20px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1);
    overflow: hidden;
}
/* Gradient border effect */
.sticky-metrics::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: 16px;
    padding: 1px;
    background: linear-gradient(135deg, #3b82f6, #8b5cf6, #ec4899, #f59e0b, #10b981, #3b82f6);
    background-size: 300% 300%;
    animation: kpiShimmer 8s linear infinite;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
    opacity: 0.7;
}
/* Shimmer overlay effect */
.sticky-metrics::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 50%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
    animation: kpiShimmer 6s ease-in-out infinite;
    pointer-events: none;
}
.sub-header-wrapper > h5 {
    position: -webkit-sticky;
    position: sticky;
    top: var(--sticky-title-top, 0px);
    background: var(--bg-sticky);
    backdrop-filter: blur(10px);
    z-index: 1008;
    padding: 12px 0 8px 0;
    margin: 0;
    font-weight: 700;
    color: var(--text-primary);
}
.sub-header-wrapper .nav-tabs {
    position: -webkit-sticky;
    position: sticky;
    top: var(--sticky-tabs-top, 45px);
    background: transparent;
    backdrop-filter: none;
    z-index: 1007;
}
/* Ensure tables stay below sticky elements */
.dash-table-container {
    position: relative;
    z-index: 1;
}

/* === Fix: Sticky Table Header + Filter Row ===
   Cấu trúc Dash: 2 table riêng trong .dash-spreadsheet-inner
     Table 0: header row (frozen) - không scroll
     Table 1: filter row (tr:first-child) + data rows - scroll
   Scroll container: .dash-spreadsheet-inner (overflow-y:auto)

   CSS dùng !important để thắng column_resize.js (set position:relative lên th).
   JS tính top của filter row = offsetHeight của table 0. */

/* Filter row th - sticky, top được JS set bằng BCR height của header row */
.dash-spreadsheet-inner table tr:nth-child(2) th {
    position: sticky !important;
    z-index: 99 !important;
}
.dash-spreadsheet-inner table:last-child tr:first-child th {
    position: sticky !important;
    z-index: 99 !important;
}
.sub-header-wrapper .tab-content {
    margin-top: 15px;
}
.sub-header-wrapper .tab-pane {
    padding-top: 10px;
}
/* Hide empty tab-content when dbc.Tabs has no children content (e.g. Report tab nav-only) */
.sub-header-wrapper .tab-content > .tab-pane:empty {
    display: none !important;
}
.sub-header-wrapper .tab-content:has(> .tab-pane:empty) {
    display: none !important;
    margin-top: 0 !important;
}
/* nav-only tabs: completely hide the tab-content wrapper (no content tabs like Report) */
.sub-tabs-nav-only ~ .tab-content,
.sub-tabs-nav-only + .tab-content,
.sub-tabs-nav-only .tab-content {
    display: none !important;
    margin: 0 !important;
    padding: 0 !important;
    height: 0 !important;
    overflow: hidden !important;
}
.sticky-metrics + div,
.sticky-metrics ~ .row {
    margin-top: 15px;
}

/* ============================================================
   PERF FIX: Reduce heavy animations on low-end machines.
   @media (prefers-reduced-motion) is respected by the OS
   when the user enables "Reduce motion" in accessibility
   settings. We also use it as a general CPU-saver for weak
   hardware since Chrome/Edge honour it on slow devices.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    /* Stop all infinite KPI animations — these run 24/7 */
    .sticky-metrics,
    .sticky-metrics::before,
    .sticky-metrics::after {
        animation: none !important;
        background-size: 100% 100% !important;
    }
    /* Disable backdrop-filter on KPI bar (very GPU-heavy) */
    .sticky-metrics {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(15, 23, 42, 0.92) !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf .sticky-metrics,
html.low-perf .sticky-metrics::before,
html.low-perf .sticky-metrics::after {
    animation: none !important;
    background-size: 100% 100% !important;
}
html.low-perf .sticky-metrics {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(15, 23, 42, 0.95) !important;
}

/* === FIX <1>: Sticky elements bên trong #tab-content-wrapper ===
   Scroll root mới là #tab-content-wrapper (thay vì .main-content hay body).
   Sticky elements bên trong nó dính vào top của #tab-content-wrapper.
   .sticky-header (#main-tabs-container) là flex:0 của .main-content,
   KHÔNG nằm bên trong #tab-content-wrapper → giữ nguyên position:sticky top:0.
   
   .sticky-metrics và .sub-header-wrapper nằm BÊN TRONG #tab-content-wrapper
   → sticky hoạt động đúng với top = 0 (tính từ đầu scroll viewport của wrapper). */
/* #overview-kpi-sticky đã nằm ngoài #tab-content-wrapper nên
   .sticky-metrics không cần sticky nữa, chỉ giữ z-index */
#overview-kpi-sticky .sticky-metrics {
    position: relative;
    z-index: 1009;
}
#tab-content-wrapper .sub-header-wrapper {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
    z-index: 1007;
}
#tab-content-wrapper .sub-header-wrapper > h5 {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
}
#tab-content-wrapper .sub-header-wrapper .nav-tabs {
    position: -webkit-sticky;
    position: sticky;
}

/* ── 06_tabs.css ─────────────────────────────────────── */
/* ============================================================
   06_tabs.css — Tab Navigation
   Auto-refactored from custom.css
   ============================================================ */

/* === Enhanced Tabs === */
.nav-tabs {
    border-bottom: none;
    gap: 4px;
}

/* Sticky header: never wrap — arrows handle overflow */
.sticky-header {
    flex-wrap: nowrap !important;
    overflow: visible !important;   /* badges must escape top/bottom */
}

/* Tab wrapper div (flex:1): never shrink below 0, let arrows handle it */
.sticky-header > div:first-child {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    overflow: hidden !important;    /* tabs clip inside this wrapper */
}

/* Main tabs UL: never wrap */
#main-tabs.nav {
    flex-wrap: nowrap !important;
}

/* ══════════════════════════════════════════════════════
   MAIN STICKY HEADER — glass bar with subtle glow
══════════════════════════════════════════════════════ */
.sticky-header {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
    z-index: 1010;
    padding: 8px 14px 8px 0;  /* balanced top/bottom so icons are vertically centred */
    background: var(--bg-sticky) !important;
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    border-bottom: 1px solid rgba(99, 102, 241, 0.25);
    box-shadow:
        0 1px 0 rgba(255,255,255,0.05),
        0 4px 24px rgba(0,0,0,0.35),
        0 0 0 1px rgba(99,102,241,0.08);
}
/* Light mode override — box-shadow nhẹ hơn */
[data-theme="light"] .sticky-header {
    border-bottom: 1px solid rgba(79, 70, 229, 0.15) !important;
    box-shadow: 0 2px 20px rgba(79,70,229,0.08), 0 1px 0 rgba(79,70,229,0.1) !important;
}

/* Main tab nav-link — pill style (dark mode default) */
#main-tabs .nav-link {
    border: none !important;
    border-radius: 8px !important;
    padding: 8px 16px !important;
    font-size: 18px !important;
    font-weight: 500 !important;
    color: rgba(203, 213, 225, 0.75) !important;
    background: transparent !important;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
    position: relative !important;
    letter-spacing: 0.01em !important;
    white-space: nowrap !important;
}
#main-tabs .nav-link:hover {
    color: #e2e8f0 !important;
    background: rgba(99, 102, 241, 0.12) !important;
}
#main-tabs .nav-link.active {
    color: #ffffff !important;
    background: linear-gradient(135deg, rgba(99,102,241,0.35) 0%, rgba(139,92,246,0.25) 100%) !important;
    box-shadow:
        0 0 0 1px rgba(129,140,248,0.4),
        0 4px 16px rgba(99,102,241,0.3),
        inset 0 1px 0 rgba(255,255,255,0.15) !important;
    font-weight: 700 !important;
    border-bottom: none !important;
    text-shadow: 0 0 20px rgba(165,180,252,0.5);
}
#main-tabs .nav-link.active::after {
    content: '';
    position: absolute;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%);
    width: 40%;
    height: 2px;
    background: linear-gradient(90deg, transparent, #818cf8, transparent);
    border-radius: 2px;
}
/* Light mode override */
[data-theme="light"] #main-tabs .nav-link {
    color: #64748b !important;
}
[data-theme="light"] #main-tabs .nav-link:hover {
    color: #4f46e5 !important;
    background: rgba(79,70,229,0.06) !important;
}
[data-theme="light"] #main-tabs .nav-link.active {
    color: #4f46e5 !important;
    background: linear-gradient(135deg, rgba(79,70,229,0.12) 0%, rgba(139,92,246,0.08) 100%) !important;
    box-shadow: 0 0 0 1px rgba(79,70,229,0.25), 0 4px 12px rgba(79,70,229,0.15), inset 0 1px 0 rgba(255,255,255,0.8) !important;
    text-shadow: none;
}

/* ══════════════════════════════════════════════════════
   SUB HEADER BAR — unified tabs + KPI seamless
══════════════════════════════════════════════════════ */
.sub-header-wrapper,
.sub-header-wrapper.d-flex {
    background: transparent !important;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    padding: 0 !important;
    border-bottom: none !important;
    /* Fix: extend right edge to align with main navbar buttons.
       main-content has padding-right: 1.5rem (24px).
       sticky-header has padding-right: 14px.
       Difference = 10px → pull sub-header right by 10px. */
    margin-right: -10px;
    padding-right: 10px !important;
}

/* Only the nav-tabs row gets the frosted background — dùng CSS variable */
.sub-header-wrapper .nav-tabs,
.sub-header-wrapper.d-flex .nav-tabs {
    background: var(--bg-main) !important;
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    box-shadow: 0 2px 16px rgba(0,0,0,0.15);
}
/* Light mode: nền sáng + shadow nhẹ */
[data-theme="light"] .sub-header-wrapper .nav-tabs,
[data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs {
    background: rgba(248, 250, 252, 0.95) !important;
    box-shadow: 0 1px 0 rgba(79,70,229,0.1) !important;
}

/* Ensure tab-content (table area) is fully transparent — no inherited bg */
.sub-header-wrapper .tab-content,
.sub-header-wrapper .tab-pane,
.sub-header-wrapper .tab-pane > div {
    background: transparent !important;
    background-color: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
}

/* Border line sits on .nav-tabs bottom edge — always visible regardless of tab-content inside wrapper */
.sub-header-wrapper .nav-tabs,
.sub-header-wrapper.d-flex .nav-tabs {
    border-bottom: 1px solid rgba(99, 102, 241, 0.35) !important;
    box-shadow: 0 1px 0 rgba(99, 102, 241, 0.15);
}

/* Tab content inside sub-header-wrapper: transparent bg so wrapper background
   doesn't bleed into the table/chart area below the nav strip */
.sub-header-wrapper > .tab-content,
.sub-header-wrapper > div > .tab-content,
.sub-header-wrapper .tab-content {
    margin-top: 0 !important;
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
    border: none !important;
}

/* Sub-tab nav-links — dark mode default */
.sub-header-wrapper .nav-tabs .nav-link,
.sub-header-wrapper.d-flex .nav-tabs .nav-link {
    border: none !important;
    border-radius: 6px 6px 0 0 !important;
    padding: 9px 13px !important;
    font-size: 15px !important;
    font-weight: 500 !important;
    color: rgba(203, 213, 225, 0.65) !important;
    background: transparent !important;
    transition: all 0.2s ease !important;
    position: relative !important;
}
.sub-header-wrapper .nav-tabs .nav-link:hover,
.sub-header-wrapper.d-flex .nav-tabs .nav-link:hover {
    color: #e2e8f0 !important;
    background: rgba(99,102,241,0.1) !important;
}
.sub-header-wrapper .nav-tabs .nav-link.active,
.sub-header-wrapper.d-flex .nav-tabs .nav-link.active {
    color: #ffffff !important;
    font-weight: 700 !important;
    background: rgba(99,102,241,0.18) !important;
    border-bottom: none !important;
}
/* Light mode override */
[data-theme="light"] .sub-header-wrapper .nav-tabs .nav-link,
[data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs .nav-link {
    color: #64748b !important;
}
[data-theme="light"] .sub-header-wrapper .nav-tabs .nav-link:hover,
[data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs .nav-link:hover {
    color: #4f46e5 !important;
    background: rgba(79,70,229,0.06) !important;
}
[data-theme="light"] .sub-header-wrapper .nav-tabs .nav-link.active,
[data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs .nav-link.active {
    color: #4f46e5 !important;
    background: rgba(79,70,229,0.08) !important;
}
.sub-header-wrapper .nav-tabs .nav-link.active::after,
.sub-header-wrapper.d-flex .nav-tabs .nav-link.active::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 16px;
    right: 16px;
    height: 2px;
    background: linear-gradient(90deg, #6366f1, #a78bfa);
    border-radius: 2px 2px 0 0;
}

/* Light theme: KPI badges side matches nav-tabs background */
[data-theme="light"] .sub-header-wrapper.d-flex > div:last-child {
    background: rgba(248, 250, 252, 0.95);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
}
[data-theme="light"] .sub-header-wrapper .nav-tabs .nav-link.active::after,
[data-theme="light"] .sub-header-wrapper.d-flex .nav-tabs .nav-link.active::after {
    background: linear-gradient(90deg, #4f46e5, #7c3aed);
}

/* ============================================================
   PERF FIX: On low-end machines / reduced-motion preference,
   replace GPU-heavy backdrop-filter blur with solid backgrounds.
   backdrop-filter: blur() forces the browser to composite a
   separate layer for every element that uses it — very costly
   on integrated/old GPUs.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .sticky-header {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(10, 15, 30, 0.97) !important;
    }
    .sub-header-wrapper .nav-tabs,
    .sub-header-wrapper.d-flex .nav-tabs {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(25, 35, 55, 0.97) !important;
    }
    /* Disable tab hover/active transitions */
    #main-tabs .nav-link {
        transition: none !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf .sticky-header {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(10, 15, 30, 0.97) !important;
}
html.low-perf .sub-header-wrapper .nav-tabs,
html.low-perf .sub-header-wrapper.d-flex .nav-tabs {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(25, 35, 55, 0.97) !important;
}
html.low-perf #main-tabs .nav-link {
    transition: none !important;
}

/* ══════════════════════════════════════════════════════
   HEADER ICONS TOGGLE BUTTON — expand/collapse icon group
══════════════════════════════════════════════════════ */
.header-icons-toggle-btn {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid rgba(99, 102, 241, 0.4);
    background: rgba(99, 102, 241, 0.12);
    color: rgba(203, 213, 225, 0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 0.68rem;
    transition: background 0.18s, transform 0.25s;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    margin-left: 6px;
    align-self: center;
}
.header-icons-toggle-btn:hover {
    background: rgba(99, 102, 241, 0.28);
    color: #fff;
}
.header-icons-toggle-btn:active { transform: scale(0.9); }
/* Rotated state when expanded */
.header-icons-toggle-btn.expanded #header-icons-toggle-icon,
.header-icons-toggle-btn.expanded i {
    transform: rotate(180deg);
    transition: transform 0.25s;
}
.header-icons-toggle-btn i {
    transition: transform 0.25s;
}

/* Light mode */
[data-theme="light"] .header-icons-toggle-btn {
    border-color: rgba(79, 70, 229, 0.3);
    background: rgba(79, 70, 229, 0.07);
    color: #4f46e5;
}
[data-theme="light"] .header-icons-toggle-btn:hover {
    background: rgba(79, 70, 229, 0.18);
}

/* Main header icons: animate open/close */
#main-header-icons {
    overflow: visible;          /* allow badges to poke out top/bottom */
    transition: max-width 0.3s cubic-bezier(0.4,0,0.2,1), opacity 0.25s;
    max-width: 0;
    opacity: 0;
    align-items: center !important;
    gap: 8px !important;
    /* No separate background — shares sticky-header bg */
    background: transparent !important;
    box-shadow: none !important;
    border: none !important;
    padding: 0 !important;
    align-self: center;
}
#main-header-icons.expanded {
    max-width: 600px;
    opacity: 1;
}

/* sticky-header: min-height set in 05_layout.css */

/* All icon wrappers inside the group: vertically centered */
#main-header-icons > div,
#main-header-icons .alert-bell-container,
#main-header-icons .perf-toggle-wrapper,
#main-header-icons .ai-setting-wrapper,
#main-header-icons .about-wrapper,
#main-header-icons .alert-bell-wrapper {
    align-self: center !important;
}

/* Mobile: hide toggle btn (mobile has its own ⋮ menu) */
body.is-mobile-device .header-icons-toggle-btn {
    display: none !important;
}
body.is-mobile-device #main-header-icons {
    display: none !important;
}

/* ── 07_components.css ───────────────────────────────── */
/* ============================================================
   07_components.css — Alert Bell · Metric Cards · Sidebar Controls · Login Screen
   Auto-refactored from custom.css
   ============================================================ */

/* === Alert Bell Notification === */
#main-tabs-container {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: space-between !important;
}
#main-tabs-container > div:first-child {
    flex: 1 !important;
}
.alert-bell-wrapper {
    order: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    flex-shrink: 0 !important;
    display: flex !important;
    align-items: center !important;
    align-self: center !important;
    padding-bottom: 0 !important;
}
/* Fix 11: Sync Logs Button Alignment */
#sync-logs-wrapper {
    height: 42px !important;
    align-items: center !important;
    padding-bottom: 0 !important;
}
#user-logs-wrapper {
    height: 42px !important;
    align-items: center !important;
    padding-bottom: 0 !important;
}
.alert-bell-container {
    position: relative;
    cursor: pointer;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: linear-gradient(145deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4), 
                0 2px 4px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border: 1px solid rgba(255, 255, 255, 0.2);
}
.alert-bell-container:hover {
    transform: scale(1.1) translateY(-2px);
    box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5),
                0 4px 8px rgba(0, 0, 0, 0.15),
                inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.alert-bell-container:active {
    transform: scale(0.95);
}
.alert-bell-container i {
    color: white !important;
    font-size: 1.2rem !important;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    line-height: 1 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
.alert-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 10px;
    background: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);
    color: white;
    font-size: 11px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 3px 10px rgba(255, 65, 108, 0.5),
                0 0 0 2px rgba(255, 255, 255, 0.9);
    animation: pulse-badge 2s infinite;
}
@keyframes pulse-badge {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.1); }
}
/* Dark mode adjustments */
[data-theme="dark"] .alert-bell-container {
    background: linear-gradient(145deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%);
    box-shadow: 0 4px 20px rgba(99, 102, 241, 0.5),
                0 2px 4px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.15);
}
[data-theme="dark"] .alert-bell-container:hover {
    box-shadow: 0 8px 30px rgba(99, 102, 241, 0.6),
                0 4px 8px rgba(0, 0, 0, 0.4),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.alert-popup {
    position: absolute;
    top: 100%;
    right: 0;
    width: 400px;
    max-height: 500px;
    margin-top: 10px;
    z-index: 9999;
    border-radius: 12px;
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    box-shadow: 0 15px 50px rgba(0,0,0,0.5), 0 0 30px rgba(79, 70, 229, 0.4);
    border: 2px solid rgba(99, 102, 241, 0.5);
    overflow: hidden;
}
.alert-popup-inner {
    padding: 0;
}
.alert-popup-header {
    display: flex;
    align-items: center;
    padding: 15px 20px;
    background: linear-gradient(135deg, rgba(79,70,229,0.3) 0%, rgba(14,165,233,0.2) 100%);
    border-bottom: 1px solid rgba(255,255,255,0.1);
    color: white;
}
.alert-popup-close {
    margin-left: auto;
    background: none;
    border: none;
    color: white;
    font-size: 1.5rem;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.2s;
}
.alert-popup-close:hover {
    opacity: 1;
}
.alert-popup-content {
    padding: 15px;
    max-height: 350px;
    overflow-y: auto;
    color: white;
}
.no-alerts-msg {
    text-align: center;
    padding: 20px;
    color: rgba(255,255,255,0.7);
}

.nav-tabs .nav-link {
    border: none;
    border-radius: 8px 8px 0 0;
    padding: 9px 16px;
    font-size: 14px;
    font-weight: 500;
    color: #64748b;
    transition: all 0.2s ease;
    position: relative;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
/* Override for admin modal tabs */
#admin-modal .nav-tabs .nav-link {
    font-size: 14px !important;
    padding: 10px 16px !important;
}
.nav-tabs .nav-link:hover {
    color: var(--primary-color);
    background: rgba(79,70,229,0.05);
}
.nav-tabs .nav-link.active {
    font-weight: 700;
    color: var(--primary-color) !important;
    background: linear-gradient(180deg, rgba(79,70,229,0.1) 0%, transparent 100%);
    border-bottom: 2px solid var(--primary-color);
}

/* === Enhanced Metric Cards === */
.metric-card {
    border-radius: var(--border-radius);
    padding: 24px;
    text-align: center;
    box-shadow: var(--shadow-lg);
    transition: all var(--transition-normal);
    position: relative;
    overflow: hidden;
}
.metric-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(135deg, rgba(255,255,255,0.2) 0%, transparent 50%);
    pointer-events: none;
}
.metric-card:hover {
    transform: translateY(-5px);
    box-shadow: var(--shadow-xl);
}
.metric-card.blue { 
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
}
.metric-card.green { 
    background: linear-gradient(135deg, #10b981 0%, #059669 100%); 
}
.metric-card.orange { 
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); 
}
.metric-value { 
    font-size: 2.5rem; 
    font-weight: 800; 
    text-shadow: 0 2px 4px rgba(0,0,0,0.1);
    letter-spacing: -1px;
}
.metric-label { 
    font-size: 0.95rem; 
    opacity: 0.95;
    font-weight: 500;
    margin-top: 5px;
}

/* === Sidebar Controls Wrapper (disabled when not logged in) === */
.sidebar-controls-wrapper {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    transition: opacity 0.3s ease;
}
.sidebar-controls-wrapper.disabled {
    opacity: 0.4;
    pointer-events: none;
}
.sidebar-controls-sticky {
    padding: 0.75rem 1.25rem;
    background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
    /* FIX (2026-07-29): .sidebar-controls-sticky và .sidebar-sticky-section (chứa
       dropdown "Chọn nhà máy") đều có z-index:10 và đều position:sticky — 2 khối
       SIBLING cùng z-index thì khối nào đứng SAU trong DOM sẽ đè lên khối đứng
       trước (bất kể z-index cao thế nào bên trong khối trước). Vì khối controls
       (Restart/Admin/Batch Export) nằm sau .sidebar-sticky-section (chứa dropdown)
       trong DOM, nó đang đè lên phần dưới của menu dropdown khi mở ra. Hạ z-index
       xuống dưới 10 để đảm bảo dropdown luôn nổi lên trên. */
    z-index: 5 !important;
}
[data-theme="dark"] .sidebar-controls-sticky {
    background: linear-gradient(180deg, #1e293b 0%, #0f172a 100%);
}

/* === Login Required Container === */
.login-required-container {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: calc(100vh - var(--navbar-height) - 100px);
    padding: 40px;
}
.login-required-content {
    text-align: center;
    padding: 60px 40px;
    background: linear-gradient(135deg, rgba(79,70,229,0.05) 0%, rgba(14,165,233,0.05) 100%);
    border-radius: 20px;
    border: 2px dashed #cbd5e1;
    max-width: 500px;
    color: #475569;
}
.login-required-content h3 {
    color: #1e293b;
    font-weight: 700;
}
.login-required-content .fa-lock {
    color: #6366f1;
}
/* Dark mode login required */
[data-theme="dark"] .login-required-content {
    background: linear-gradient(135deg, rgba(129,140,248,0.1) 0%, rgba(56,189,248,0.1) 100%);
    border-color: #475569;
    color: #cbd5e1;
}
[data-theme="dark"] .login-required-content h3 {
    color: #f1f5f9;
}
[data-theme="dark"] .login-required-content .fa-lock {
    color: #818cf8;
}
[data-theme="dark"] .login-required-content .text-muted {
    color: #94a3b8 !important;
}

/* === Hide Maintenance & Spare Parts Tabs for viewer/export === */
/* Admin and Tech can see all tabs, viewer/export cannot see Maintenance and Spare Parts */
/* Note: Callback handles tab visibility dynamically, CSS is backup */
html[data-user-role="viewer"] #main-tabs .nav-item:has(.nav-link[data-rr-ui-event-key="tab-maintenance"]),
html[data-user-role="viewer"] #main-tabs .nav-item:has(.nav-link[data-rr-ui-event-key="tab-spare-parts"]),
html[data-user-role="export"] #main-tabs .nav-item:has(.nav-link[data-rr-ui-event-key="tab-maintenance"]),
html[data-user-role="export"] #main-tabs .nav-item:has(.nav-link[data-rr-ui-event-key="tab-spare-parts"]),
html[data-user-role="viewer"] #tab-spare-parts-item,
html[data-user-role="export"] #tab-spare-parts-item {
    display: none !important;
}

/* === Filter Labels === */
.filter-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: #475569;
    margin-top: 0.75rem;
    margin-bottom: 0.35rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* (FIX 2026-08 <chống spam click — Auto PM Settings>) Trạng thái khoá tạm
   thời trong lúc chờ server xử lý — dùng class thay vì thuộc tính
   "disabled" thật để không xung đột với reconciliation của React/Dash.
   Xem assets/maint_settings_btn_lock.js. */
.asm-btn-locked {
    pointer-events: none !important;
    opacity: 0.65 !important;
    cursor: not-allowed !important;
}

/* ── 08_filters.css ──────────────────────────────────── */
/* ============================================================
   08_filters.css — Filter Labels · Comparison DatePicker · Dark Theme Text
   Auto-refactored from custom.css
   ============================================================ */

/* === Comparison DatePicker Styling === */
.compare-datepicker .SingleDatePickerInput {
    border-radius: 6px !important;
}
.compare-datepicker .DateInput {
    width: 100% !important;
}
.compare-datepicker .DateInput_input {
    font-size: 16px !important;
    padding: 4px 2px !important;
    text-align: center;
    font-weight: 500;
}
.compare-datepicker .SingleDatePicker,
.compare-datepicker .SingleDatePickerInput {
    width: 100%;
}
.compare-datepicker .DateInput {
    width: 100%;
}
/* Compare chart dropdowns - dark mode fix */
#compare-chart-left, #compare-chart-right {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
    border: 1px solid var(--border-color) !important;
}
/* Compare chart containers - smooth transitions */
#compare-chart-left-container, #compare-chart-right-container {
    transition: opacity 0.15s ease-in-out;
    position: relative;
}
/* Loading overlay for compare charts - keep content visible during load */
#compare-chart-left-container .dash-graph,
#compare-chart-right-container .dash-graph {
    transition: opacity 0.2s ease;
}
/* Prevent flash during updates */
.dash-graph-container {
    min-height: 320px;
}
/* Smooth plotly transitions */
.js-plotly-plot .plotly {
    transition: opacity 0.2s ease;
}
[data-theme='dark'] #compare-chart-left .Select-control,
[data-theme='dark'] #compare-chart-right .Select-control {
    background-color: #1f2937 !important;
    border-color: #374151 !important;
}
[data-theme='dark'] #compare-chart-left .Select-menu-outer,
[data-theme='dark'] #compare-chart-right .Select-menu-outer {
    background-color: #1f2937 !important;
    border-color: #374151 !important;
}
[data-theme='dark'] #compare-chart-left .Select-option,
[data-theme='dark'] #compare-chart-right .Select-option {
    color: #e5e7eb !important;
}
[data-theme='dark'] #compare-chart-left .Select-value-label,
[data-theme='dark'] #compare-chart-right .Select-value-label {
    color: #e5e7eb !important;
}
/* Compare KPI compact - reduced height */
.compare-kpi-row {
    padding: 4px 0 !important;
}
.compare-kpi-row .kpi-card-compact {
    padding: 6px 8px !important;
    min-height: unset !important;
}
.compare-kpi-row .kpi-compact-row1 {
    font-size: 0.95rem !important;
}
.compare-kpi-row .kpi-compact-row2 {
    font-size: 0.65rem !important;
    margin-top: 1px !important;
}
/* Delta badge inside KPI - larger size */
.kpi-delta-badge {
    font-size: 0.65rem !important;
    padding: 2px 6px !important;
    margin-left: 6px;
    vertical-align: middle;
    font-weight: 600;
}
/* Compare summary - dark mode fix */
.compare-summary-box {
    background-color: var(--card-bg) !important;
    border: 1px solid var(--border-color) !important;
    color: var(--text-color) !important;
}
[data-theme='dark'] .compare-summary-box {
    background-color: #1e293b !important;
    border-color: #334155 !important;
}
[data-theme='dark'] .compare-summary-box .text-muted,
[data-theme='dark'] .compare-summary-box span.text-muted {
    color: #cbd5e1 !important;
}
[data-theme='dark'] .compare-summary-box h6,
[data-theme='dark'] .compare-summary-box .fw-bold {
    color: #f1f5f9 !important;
}
[data-theme='dark'] .compare-summary-box .text-success {
    color: #4ade80 !important;
}
[data-theme='dark'] .compare-summary-box .text-danger {
    color: #f87171 !important;
}
[data-theme='dark'] .compare-summary-box .text-warning {
    color: #fbbf24 !important;
}

/* === GLOBAL Dark Theme Text Color Overrides === */
/* Fix low-contrast text colors across the entire application */
[data-theme='dark'] .text-success {
    color: #4ade80 !important;
}
[data-theme='dark'] .text-danger {
    color: #f87171 !important;
}
[data-theme='dark'] .text-warning {
    color: #fbbf24 !important;
}
[data-theme='dark'] .text-info {
    color: #38bdf8 !important;
}
[data-theme='dark'] .text-primary {
    color: #60a5fa !important;
}
[data-theme='dark'] .text-secondary {
    color: #a1a1aa !important;
}
[data-theme='dark'] .text-muted {
    color: #9ca3af !important;
}

/* Badge colors for dark mode */
[data-theme='dark'] .badge.bg-success {
    background-color: #22c55e !important;
    color: #ffffff !important;
}
[data-theme='dark'] .badge.bg-danger {
    background-color: #ef4444 !important;
    color: #ffffff !important;
}
[data-theme='dark'] .badge.bg-warning {
    background-color: #f59e0b !important;
    color: #1f2937 !important;
}
[data-theme='dark'] .badge.bg-info {
    background-color: #0ea5e9 !important;
    color: #ffffff !important;
}
[data-theme='dark'] .badge.bg-primary {
    background-color: #3b82f6 !important;
    color: #ffffff !important;
}
[data-theme='dark'] .badge.bg-secondary {
    background-color: #6b7280 !important;
    color: #ffffff !important;
}

/* Small and muted text */
[data-theme='dark'] small.text-muted,
[data-theme='dark'] .small.text-muted {
    color: #9ca3af !important;
}

/* Compare chart dropdown - comprehensive dark mode fix */
/* Remove border/frame around dropdown SELECT element */
#compare-chart-left .Select-control,
#compare-chart-right .Select-control {
    border: none !important;
    box-shadow: none !important;
    background-color: transparent !important;
}
#compare-chart-left,
#compare-chart-right {
    border: none !important;
}
[data-theme='dark'] #compare-chart-left .Select-control,
[data-theme='dark'] #compare-chart-right .Select-control {
    border: none !important;
    box-shadow: none !important;
    background-color: #374151 !important;
}
/* Dropdown styling for dark mode */
[data-theme='dark'] #compare-chart-left,
[data-theme='dark'] #compare-chart-right {
    background-color: #1f2937 !important;
}
[data-theme='dark'] #compare-chart-left .Select-control,
[data-theme='dark'] #compare-chart-right .Select-control,
[data-theme='dark'] #compare-chart-left .Select-input,
[data-theme='dark'] #compare-chart-right .Select-input {
    background-color: #1f2937 !important;
    border-color: #4b5563 !important;
    color: #f3f4f6 !important;
}
[data-theme='dark'] #compare-chart-left .Select-placeholder,
[data-theme='dark'] #compare-chart-right .Select-placeholder,
[data-theme='dark'] #compare-chart-left .Select-value-label,
[data-theme='dark'] #compare-chart-right .Select-value-label,
[data-theme='dark'] #compare-chart-left .Select-input input,
[data-theme='dark'] #compare-chart-right .Select-input input {
    color: #f3f4f6 !important;
}
/* Dropdown menu options - CRITICAL: light text on dark background */
[data-theme='dark'] #compare-chart-left .Select-menu-outer,
[data-theme='dark'] #compare-chart-right .Select-menu-outer,
[data-theme='dark'] #compare-chart-left .Select-menu,
[data-theme='dark'] #compare-chart-right .Select-menu {
    background-color: #1f2937 !important;
    border-color: #4b5563 !important;
}
[data-theme='dark'] #compare-chart-left .Select-option,
[data-theme='dark'] #compare-chart-right .Select-option,
[data-theme='dark'] #compare-chart-left .VirtualizedSelectOption,
[data-theme='dark'] #compare-chart-right .VirtualizedSelectOption {
    background-color: #1f2937 !important;
    color: #f9fafb !important;
}
[data-theme='dark'] #compare-chart-left .Select-option:hover,
[data-theme='dark'] #compare-chart-right .Select-option:hover,
[data-theme='dark'] #compare-chart-left .Select-option.is-focused,
[data-theme='dark'] #compare-chart-right .Select-option.is-focused,
[data-theme='dark'] #compare-chart-left .VirtualizedSelectOption:hover,
[data-theme='dark'] #compare-chart-right .VirtualizedSelectOption:hover,
[data-theme='dark'] #compare-chart-left .VirtualizedSelectFocusedOption,
[data-theme='dark'] #compare-chart-right .VirtualizedSelectFocusedOption {
    background-color: #374151 !important;
    color: #ffffff !important;
}
[data-theme='dark'] #compare-chart-left .Select-option.is-selected,
[data-theme='dark'] #compare-chart-right .Select-option.is-selected {
    background-color: #4f46e5 !important;
    color: #ffffff !important;
}
/* Generic dropdown dark mode fix for ALL dropdowns */
[data-theme='dark'] .Select-menu-outer,
[data-theme='dark'] .Select-menu {
    background-color: #1f2937 !important;
    border-color: #4b5563 !important;
}
[data-theme='dark'] .Select-option,
[data-theme='dark'] .VirtualizedSelectOption {
    background-color: #1f2937 !important;
    color: #f9fafb !important;
}
[data-theme='dark'] .Select-option:hover,
[data-theme='dark'] .Select-option.is-focused,
[data-theme='dark'] .VirtualizedSelectOption:hover,
[data-theme='dark'] .VirtualizedSelectFocusedOption {
    background-color: #374151 !important;
    color: #ffffff !important;
}
#compare-filter-container .filter-label {
    font-size: 0.75rem;
    margin-top: 0.5rem;
    margin-bottom: 0.25rem;
}
#compare-filter-container small {
    font-size: 0.7rem;
}
/* Compare period colors */
#compare-filter-container .text-primary {
    color: #3b82f6 !important;
}
#compare-filter-container .text-success {
    color: #10b981 !important;
}

/* ── 09_forms.css ────────────────────────────────────── */
/* ============================================================
   09_forms.css — Dropdowns · Checklist · Alerts · Bell Notifications
   Auto-refactored from custom.css
   ============================================================ */

/* === Dropdown Styling === */
.Select-control {
    border-radius: 8px !important;
    border: 2px solid #e2e8f0 !important;
    transition: all var(--transition-fast) !important;
}
.Select-control:hover {
    border-color: var(--primary-light) !important;
}
.Select.is-focused > .Select-control {
    border-color: var(--primary-color) !important;
    box-shadow: 0 0 0 3px rgba(79,70,229,0.15) !important;
}
.Select-menu-outer {
    border-radius: 8px !important;
    box-shadow: var(--shadow-lg) !important;
    border: 1px solid #e2e8f0 !important;
    margin-top: 4px;
    animation: slideDown 0.2s ease;
}
@keyframes slideDown {
    from { opacity: 0; transform: translateY(-10px); }
    to { opacity: 1; transform: translateY(0); }
}
.Select-option {
    padding: 10px 12px !important;
    transition: all var(--transition-fast);
}
.Select-option:hover,
.Select-option.is-focused {
    background: linear-gradient(135deg, rgba(79,70,229,0.1) 0%, rgba(14,165,233,0.1) 100%) !important;
}
.Select-option.is-selected {
    background: var(--primary-color) !important;
    color: white !important;
}
.Select--multi .Select-value {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%) !important;
    border: none !important;
    border-radius: 6px !important;
    color: white !important;
    direction: ltr !important;
}
.Select--multi .Select-value-icon {
    border-right: 1px solid rgba(255,255,255,0.3) !important;
}
.Select--multi .Select-value-icon:hover {
    background: rgba(255,255,255,0.2) !important;
    color: white !important;
}
/* Bug 7 Fix: Force scrollbar to stay fixed on the right */
.Select--multi .Select-multi-value-wrapper {
    direction: ltr !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
}

/* === Checklist Styling === */
.form-check-input {
    width: 18px;
    height: 18px;
    border: 2px solid #cbd5e1;
    border-radius: 4px;
    transition: all var(--transition-fast);
}
.form-check-input:checked {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
}
.form-check-input:focus {
    box-shadow: 0 0 0 3px rgba(79,70,229,0.15);
}
.form-check-label {
    font-weight: 500;
    color: #475569;
}

/* === Alert Styling === */
.alert {
    border-radius: var(--border-radius);
    border: none;
    box-shadow: var(--shadow-sm);
}
.alert-info {
    background: linear-gradient(135deg, rgba(14,165,233,0.1) 0%, rgba(79,70,229,0.1) 100%);
    color: #0369a1;
}
.alert-warning {
    background: linear-gradient(135deg, rgba(245,158,11,0.15) 0%, rgba(234,88,12,0.1) 100%);
    color: #92400e;
}
.alert-success {
    background: linear-gradient(135deg, rgba(34,197,94,0.15) 0%, rgba(16,185,129,0.1) 100%);
    color: #15803d;
}
.alert-danger {
    background: linear-gradient(135deg, rgba(239,68,68,0.15) 0%, rgba(220,38,38,0.1) 100%);
    color: #b91c1c;
}

/* === Bell Notification Styling === */
.notification-bell {
    position: relative;
    cursor: pointer;
    padding: 8px 12px;
    border-radius: 12px;
    background: linear-gradient(145deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
    border: 1px solid rgba(255,255,255,0.1);
    transition: all 0.3s ease;
}
.notification-bell:hover {
    background: linear-gradient(145deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%);
    transform: scale(1.05);
}
.notification-bell i {
    font-size: 1.2rem;
    color: #94a3b8;
    transition: color 0.3s ease;
}
.notification-bell.has-alerts i {
    color: #f59e0b;
    animation: bell-shake 0.5s ease-in-out infinite;
}
@keyframes bell-shake {
    0%, 100% { transform: rotate(0deg); }
    25% { transform: rotate(10deg); }
    75% { transform: rotate(-10deg); }
}
.notification-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 18px;
    height: 18px;
    border-radius: 50%;
    background: linear-gradient(145deg, #ef4444 0%, #dc2626 100%);
    color: white;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 8px rgba(239,68,68,0.5);
}
.notification-popup {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 10px;
    width: 380px;
    max-height: 450px;
    overflow-y: auto;
    background: linear-gradient(145deg, #1e293b 0%, #0f172a 100%);
    border: 2px solid;
    border-image: linear-gradient(135deg, #6366f1, #8b5cf6, #a855f7) 1;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.5), 0 0 40px rgba(99,102,241,0.2);
    z-index: 9999;
    padding: 0;
}
.notification-popup::before {
    content: '';
    position: absolute;
    top: -8px;
    right: 20px;
    width: 16px;
    height: 16px;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    transform: rotate(45deg);
    border-radius: 2px;
}
.notification-header {
    padding: 16px 20px;
    background: linear-gradient(90deg, rgba(99,102,241,0.2) 0%, rgba(139,92,246,0.2) 100%);
    border-bottom: 1px solid rgba(255,255,255,0.1);
    border-radius: 14px 14px 0 0;
}
.notification-header h6 {
    margin: 0;
    color: #f8fafc;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
}
.notification-body {
    padding: 12px;
}
.alert-item {
    padding: 14px 16px;
    margin-bottom: 10px;
    border-radius: 12px;
    border-left: 4px solid;
    transition: all 0.2s ease;
}
.alert-item:hover {
    transform: translateX(4px);
}
.alert-item.critical {
    background: linear-gradient(145deg, rgba(239,68,68,0.15) 0%, rgba(185,28,28,0.1) 100%);
    border-left-color: #ef4444;
}
.alert-item.warning {
    background: linear-gradient(145deg, rgba(245,158,11,0.15) 0%, rgba(217,119,6,0.1) 100%);
    border-left-color: #f59e0b;
}
.alert-item .alert-title {
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.alert-item.critical .alert-title { color: #fca5a5; }
.alert-item.warning .alert-title { color: #fcd34d; }
.alert-item .alert-value {
    font-size: 0.85rem;
    color: #94a3b8;
    margin-bottom: 8px;
}
.alert-item .alert-solution {
    font-size: 0.8rem;
    color: #64748b;
    padding: 8px 10px;
    background: rgba(0,0,0,0.2);
    border-radius: 6px;
    margin-top: 8px;
}
.alert-item .alert-solution i {
    color: #10b981;
    margin-right: 6px;
}
.no-alerts {
    text-align: center;
    padding: 30px 20px;
    color: #64748b;
}
.no-alerts i {
    font-size: 2.5rem;
    color: #10b981;
    margin-bottom: 12px;
    display: block;
}

/* ── 10_tables.css ───────────────────────────────────── */
/* ============================================================
   10_tables.css — Table Styling · DataTable
   Auto-refactored from custom.css
   ============================================================ */

/* === Table Styling === */
.table {
    border-radius: var(--border-radius);
    overflow: hidden;
    box-shadow: var(--shadow-md);
}
.table thead th {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
    color: white;
    font-weight: 600;
    border: none;
    padding: 14px 12px;
}
.table tbody tr {
    transition: all var(--transition-fast);
}
.table tbody tr:hover {
    background: rgba(79,70,229,0.05);
    color: var(--text-primary);
}
/* Dark mode table row hover - improve contrast significantly for HTML tables */
[data-theme="dark"] .table tbody tr:hover {
    background: rgba(129,140,248,0.4) !important;
    color: #f1f5f9 !important;
    font-weight: 500;
}

/* Dark mode Dash DataTable row hover - improve contrast
   (FIX: loại trừ #shift-grid-table / #shift-worktime-grid-table — 2 bảng
   này có mã màu RIÊNG cho từng ô (S19OT/OFF/AL...) được Dash set qua
   inline style; rule "!important" ở đây từng đè mất màu ô + highlight
   NGUYÊN CẢ HÀNG khi hover thay vì chỉ 1 ô. 2 bảng này giờ tự xử lý hover
   riêng ở 31_shift_grid.css — chỉ highlight đúng ô đang hover.) */
[data-theme="dark"] .dash-table-container .dash-spreadsheet-inner tbody tr:hover td:not(#shift-grid-table *):not(#shift-worktime-grid-table *),
[data-theme="dark"] .dash-table-container tbody tr:hover td:not(#shift-grid-table *):not(#shift-worktime-grid-table *),
[data-theme="dark"] .dash-spreadsheet-inner tbody tr:hover:not(#shift-grid-table *):not(#shift-worktime-grid-table *) {
    background-color: rgba(129,140,248,0.4) !important;
    background: rgba(129,140,248,0.4) !important;
    color: #f1f5f9 !important;
    font-weight: 500;
}

/* Additional fallback for any table hover in dark mode */
[data-theme="dark"] tbody tr:hover:not(#shift-grid-table *):not(#shift-worktime-grid-table *),
[data-theme="dark"] tbody tr:hover td:not(#shift-grid-table *):not(#shift-worktime-grid-table *),
[data-theme="dark"] tr:hover td:not(#shift-grid-table *):not(#shift-worktime-grid-table *) {
    background-color: rgba(129,140,248,0.4) !important;
    color: #f1f5f9 !important;
}
.table td {
    padding: 12px;
    vertical-align: middle;
}
.table thead th {
    text-align: center;
    vertical-align: middle;
}
.table tbody td {
    text-align: center;
    vertical-align: middle;
}

/* === Checklist PM stat tables: fix white rows in dark mode + force center align === */
.cl-pm-table,
.cl-pm-table > :not(caption) > * > * {
    background-color: transparent !important;
    color: var(--text-primary) !important;
}
.cl-pm-table th,
.cl-pm-table td {
    text-align: center !important;
    vertical-align: middle !important;
    border-color: var(--border-color) !important;
}
.cl-pm-table tbody tr.table-active,
.cl-pm-table tbody tr.table-active > * {
    background-color: rgba(129, 140, 248, 0.12) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .cl-pm-table tbody tr:hover,
[data-theme="dark"] .cl-pm-table tbody tr:hover td {
    background-color: rgba(129,140,248,0.25) !important;
    color: #f1f5f9 !important;
}

/* === Backup DB history table: fix white rows in dark mode (Admin Settings) === */
.backup-db-history-table,
.backup-db-history-table > :not(caption) > * > * {
    background-color: transparent !important;
    color: var(--text-primary) !important;
}
.backup-db-history-table th,
.backup-db-history-table td {
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .backup-db-history-table tbody tr:hover,
[data-theme="dark"] .backup-db-history-table tbody tr:hover td {
    background-color: rgba(129,140,248,0.25) !important;
    color: #f1f5f9 !important;
}

/* === DataTable Styling === */
.dash-table-container {
    border-radius: var(--border-radius);
    overflow: visible;
    box-shadow: var(--shadow-md);
}
/* Data tables wrapper */
.dash-spreadsheet-container {
    background: var(--bg-card);
    border-radius: 12px;
    border: 1px solid var(--border-color);
    overflow-x: hidden; /* chỉ chặn ngang – không clip scroll Y */
    max-width: 100%;
    box-sizing: border-box;
    width: 100%;
}
/* Ensure spread sheet never overflows horizontally – vertical scroll must work */
.dash-spreadsheet {
    max-width: 100% !important;
    width: 100% !important;
    overflow-x: hidden !important;  /* chỉ chặn X – Dash inject overflowY trên inline style */
    box-sizing: border-box !important;
}
.dash-spreadsheet-inner {
    max-width: 100% !important;
    width: 100% !important;
    overflow-x: hidden !important;  /* chỉ chặn X */
    box-sizing: border-box !important;
}
/* table-layout:fixed is controlled by Dash; only enforce width containment */
.dash-spreadsheet-inner table {
    max-width: 100% !important;
    box-sizing: border-box !important;
}
.dash-table-container .dash-spreadsheet {
    border: none !important;
}
.dash-table-container .dash-header {
    border-radius: var(--border-radius) var(--border-radius) 0 0;
}
/* Remove outer border from header row */
.dash-spreadsheet-inner table,
.dash-spreadsheet-inner thead,
.dash-spreadsheet-inner thead tr {
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
}
.dash-spreadsheet-inner th {
    border: none !important;
    border-right: 1px solid rgba(255,255,255,0.2) !important;
}
.dash-spreadsheet-inner th:last-child {
    border-right: none !important;
}
/* Filter placeholder visibility */
.dash-spreadsheet .dash-filter input::placeholder {
    color: #94a3b8 !important;
    opacity: 1 !important;
}
.dash-table-container .cell-markdown {
    font-family: inherit;
}
.previous-next-container {
    padding: 10px 0;
    justify-content: center;
}
.page-number {
    font-weight: 600;
    color: var(--primary-color);
}
/* Fix for Case Sensitivity Button visibility */
.dash-spreadsheet .dash-filter--case {
    color: #94a3b8 !important;
    opacity: 0.7;
    border-radius: 3px;
    transition: all 0.2s;
    border: 1px solid transparent;
}
.dash-spreadsheet .dash-filter--case:hover {
    color: var(--primary-color) !important;
    background-color: rgba(79, 70, 229, 0.1);
    opacity: 1;
}
/* Active state (Case Sensitive) */
.dash-spreadsheet .dash-filter--case--sensitive {
    color: #ffffff !important;
    background-color: var(--primary-color) !important;
    border: 1px solid var(--primary-dark) !important;
    opacity: 1 !important;
    font-weight: bold;
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

/* Dark mode adjustments for Case Sensitivity Button */
[data-theme="dark"] .dash-spreadsheet .dash-filter--case {
    color: #64748b !important;
}
[data-theme="dark"] .dash-spreadsheet .dash-filter--case:hover {
    color: #818cf8 !important; /* primary-light */
    background-color: rgba(129, 140, 248, 0.15);
}
[data-theme="dark"] .dash-spreadsheet .dash-filter--case--sensitive {
    color: #ffffff !important;
    background-color: var(--primary-color) !important;
    border-color: var(--primary-light) !important;
    box-shadow: 0 0 8px rgba(129, 140, 248, 0.4);
}

/* === Shift tab: "Mã ca" sub-tab tables (Tech/BPO code panels + leave-code
   table) — force dark-mode-friendly transparent background instead of the
   bright white Bootstrap default (Fix item #6). Mirrors .cl-pm-table. === */
.shift-codes-card {
    background-color: var(--bg-card) !important;
}
.shift-codes-table,
.shift-codes-table > :not(caption) > * > * {
    background-color: transparent !important;
    color: var(--text-primary) !important;
}
.shift-codes-table th,
.shift-codes-table td {
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .shift-codes-table tbody tr:hover,
[data-theme="dark"] .shift-codes-table tbody tr:hover td {
    background-color: rgba(129,140,248,0.25) !important;
    color: #f1f5f9 !important;
}

/* ── 11_charts.css ───────────────────────────────────── */
/* ============================================================
   11_charts.css — Chart Containers · Section Wrappers · Action Buttons · Export
   Auto-refactored from custom.css
   ============================================================ */

/* === Chart Container === */
.js-plotly-plot {
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-md);
    background: var(--bg-card, white);
    transition: all var(--transition-normal);
    overflow: hidden;
}
.js-plotly-plot .main-svg {
    border-radius: var(--border-radius);
}
.js-plotly-plot:hover {
    box-shadow: var(--shadow-lg);
}

/* === Section Wrappers for Better Visual Separation === */
.chart-container {
    position: relative;
    background: transparent;
    border-radius: 12px;
    border: none;
    box-shadow: none;
    padding: 8px;
    margin-bottom: 8px;
}

/* Row containers for charts */
.row.g-4, .row.g-3 {
    padding: 8px;
    background: transparent;
    border-radius: 12px;
    margin-bottom: 12px;
}

/* Analysis summary sections */
.border-start.border-primary,
.border-start.border-success {
    background: var(--bg-card);
    border-radius: 8px;
    padding: 12px 16px !important;
    box-shadow: var(--shadow-sm);
}

/* Compare tab specific styling */
.compare-kpi-row {
    background: transparent;
    padding: 8px 0;
}

/* Tab content wrapper */
.tab-pane .py-3 {
    background: transparent;
    border-radius: 12px;
    padding: 16px !important;
}

/* === Chart Action Buttons (Fullscreen & Export) === */
.chart-container .chart-action-btn {
    opacity: 0;
    transition: all 0.25s ease;
    pointer-events: none;
}
.chart-container:hover .chart-action-btn {
    opacity: 0.85;
    pointer-events: auto;
}
.chart-container .chart-action-btn:hover {
    opacity: 1 !important;
}
/* Fullscreen button - vibrant purple background với white icon để nổi bật */
.chart-container .fullscreen-btn,
.chart-container [id*="fullscreen-btn"] {
    background: #6366f1 !important;
    color: white !important;
    border: 1px solid #6366f1 !important;
}
.chart-container .fullscreen-btn:hover,
.chart-container [id*="fullscreen-btn"]:hover {
    background: #4f46e5 !important;
    color: white !important;
    border-color: #4f46e5 !important;
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
}
/* Info button (nếu có) */
.chart-container [id*="chart-info-btn"]:hover {
    background: #0ea5e9 !important;
    color: white !important;
    border-color: #0ea5e9 !important;
}

/* === Export Button Styles === */
.chart-export-dropdown {
    position: absolute;
    top: 8px;
    z-index: 100;
}
.chart-export-dropdown .dropdown-toggle {
    opacity: 0;
    transition: all 0.25s ease;
    pointer-events: none;
    padding: 5px 8px;
    font-size: 12px;
    border-radius: 4px;
    width: 30px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Export button - vibrant green background với white icon để nổi bật */
    background: #10b981 !important;
    border: 1px solid #10b981 !important;
    color: white !important;
}
.chart-container:hover .chart-export-dropdown .dropdown-toggle {
    opacity: 0.85;
    pointer-events: auto;
}
.chart-container:hover .chart-export-dropdown .dropdown-toggle:hover {
    opacity: 1 !important;
    background: #059669 !important;
    color: white !important;
    border-color: #059669 !important;
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
}
.export-dropdown-btn .btn {
    padding: 5px 8px;
    font-size: 12px;
    border-radius: 4px;
    width: 30px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.export-dropdown-btn .btn:hover {
    background: #10b981;
    border-color: #10b981;
}
.export-dropdown-btn .dropdown-menu {
    min-width: 140px;
    font-size: 13px;
}
.export-dropdown-menu {
    min-width: 160px;
    font-size: 13px;
}
.export-dropdown-menu .dropdown-header {
    font-weight: 600;
    color: var(--text-muted);
    font-size: 11px;
    text-transform: uppercase;
}
.export-dropdown-menu .dropdown-item {
    padding: 6px 16px;
}
.export-dropdown-menu .dropdown-item i {
    width: 18px;
    margin-right: 8px;
}

/* Table export dropdown - align button vertically center */
.table-export-dropdown .btn {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 30px;
}
.table-export-dropdown .dropdown-toggle {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* Hide export buttons for viewer role */
html[data-user-role="viewer"] .chart-export-dropdown,
html[data-user-role="viewer"] .table-export-btn,
html[data-user-role="viewer"] .batch-export-btn {
    display: none !important;
}

/* Hide watermark option in batch export for non-admin roles */
html[data-user-role="viewer"] .watermark-option-wrapper,
html[data-user-role="tech"] .watermark-option-wrapper,
html[data-user-role="export"] .watermark-option-wrapper {
    display: none !important;
}

/* Batch Export Button in Header */
.batch-export-btn {
    margin-right: 8px;
}

/* === sync-log-pre: desktop font size (inline style removed from Python) === */
.sync-log-pre {
    font-size: 11px;
    line-height: 1.5;
}

/* ── 12_cards.css ────────────────────────────────────── */
/* ============================================================
   12_cards.css — Contact Cards · KPI Tooltip · Multiselect · KPI Cards Compact
   Auto-refactored from custom.css
   ============================================================ */

/* === Contact Card Styling === */
/* === CONTACT CARDS - LUNG LINH EDITION === */
.contact-card {
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
    position: relative;
    overflow: hidden;
}

/* Shimmer effect overlay */
.contact-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    transition: left 0.6s ease;
}

.contact-card:hover::before {
    left: 100%;
}

.contact-card:hover {
    transform: translateY(-6px) scale(1.02);
    box-shadow: 
        0 20px 40px rgba(59, 130, 246, 0.15),
        0 0 0 1px rgba(59, 130, 246, 0.1),
        0 0 20px rgba(59, 130, 246, 0.1) !important;
    border-color: #3b82f6 !important;
    background: linear-gradient(135deg, 
        rgba(59,130,246,0.05) 0%, 
        rgba(139,92,246,0.05) 50%,
        rgba(236,72,153,0.05) 100%) !important;
}

/* Contact link with gradient underline */
.contact-link {
    position: relative;
    display: inline-block;
    background: linear-gradient(135deg, #1e293b 0%, #3b82f6 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    transition: all 0.3s ease;
}

.contact-link::after {
    content: '';
    position: absolute;
    width: 0;
    height: 2px;
    bottom: -2px;
    left: 0;
    background: linear-gradient(90deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%);
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 0 0 8px rgba(59, 130, 246, 0.5);
}

.contact-link:hover {
    transform: translateX(2px);
}

.contact-link:hover::after {
    width: 100%;
}

/* Contact card icon animations */
.contact-card .fa-envelope,
.contact-card .fa-comments {
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.contact-card:hover .fa-envelope,
.contact-card:hover .fa-comments {
    animation: iconFloat 0.6s ease-in-out;
    filter: drop-shadow(0 4px 8px rgba(59, 130, 246, 0.3));
}

@keyframes iconFloat {
    0%, 100% {
        transform: translateY(0) scale(1);
    }
    50% {
        transform: translateY(-4px) scale(1.15);
    }
}

/* Icon background glow on hover */
.contact-card:hover .fa-envelope {
    color: #3b82f6;
    text-shadow: 0 0 12px rgba(59, 130, 246, 0.6);
}

.contact-card:hover .fa-comments {
    color: #10b981;
    text-shadow: 0 0 12px rgba(16, 185, 129, 0.6);
}

/* Sticky contact section in modal - Always visible at bottom */
.contact-section-sticky {
    position: sticky;
    bottom: 0;
    z-index: 100;
    background: rgba(255, 255, 255, 0.98);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border-radius: 16px;
    animation: fadeInUp 0.7s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 
        0 -8px 32px rgba(59, 130, 246, 0.08),
        0 -2px 8px rgba(0, 0, 0, 0.04),
        0 0 0 1px rgba(59, 130, 246, 0.05);
    margin-top: auto;
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.contact-section-sticky:hover {
    box-shadow: 
        0 -12px 48px rgba(59, 130, 246, 0.12),
        0 -4px 16px rgba(0, 0, 0, 0.06),
        0 0 0 1px rgba(59, 130, 246, 0.1);
    transform: translateY(-2px);
}

@keyframes fadeInDown {
    from {
        opacity: 0;
        transform: translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Heart beat animation */
.fa-heart {
    animation: heartBeat 1.5s ease-in-out infinite;
    display: inline-block;
}

@keyframes heartBeat {
    0%, 100% {
        transform: scale(1);
    }
    10%, 30% {
        transform: scale(1.1);
    }
    20%, 40% {
        transform: scale(0.9);
    }
}

/* Gradient text for team name */
.team-name-gradient {
    background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: gradientShift 3s ease infinite;
    background-size: 200% 200%;
}

@keyframes gradientShift {
    0% {
        background-position: 0% 50%;
    }
    50% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0% 50%;
    }
}

/* Dark mode contact cards */
[data-theme="dark"] .contact-card {
    background: rgba(30, 41, 59, 0.8) !important;
    border-color: rgba(71, 85, 105, 0.6) !important;
}

[data-theme="dark"] .contact-card:hover {
    background: linear-gradient(135deg, 
        rgba(59,130,246,0.15) 0%, 
        rgba(139,92,246,0.15) 50%,
        rgba(236,72,153,0.15) 100%) !important;
    border-color: #60a5fa !important;
    box-shadow: 
        0 20px 40px rgba(96, 165, 250, 0.2),
        0 0 0 1px rgba(96, 165, 250, 0.2),
        0 0 20px rgba(96, 165, 250, 0.2) !important;
}

[data-theme="dark"] .contact-link {
    background: linear-gradient(135deg, #e2e8f0 0%, #60a5fa 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

[data-theme="dark"] .contact-link:hover {
    background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

[data-theme="dark"] .contact-section-sticky {
    background: rgba(15, 23, 42, 0.98);
    box-shadow: 
        0 -8px 32px rgba(96, 165, 250, 0.12),
        0 -2px 8px rgba(0, 0, 0, 0.2),
        0 0 0 1px rgba(96, 165, 250, 0.1);
}

[data-theme="dark"] .contact-section-sticky:hover {
    box-shadow: 
        0 -12px 48px rgba(96, 165, 250, 0.18),
        0 -4px 16px rgba(0, 0, 0, 0.3),
        0 0 0 1px rgba(96, 165, 250, 0.15);
}

[data-theme="dark"] .contact-card:hover .fa-envelope {
    color: #60a5fa;
    text-shadow: 0 0 12px rgba(96, 165, 250, 0.6);
}

[data-theme="dark"] .contact-card:hover .fa-comments {
    color: #34d399;
    text-shadow: 0 0 12px rgba(52, 211, 153, 0.6);
}

/* === Custom KPI Tooltip Styling === */
.tooltip {
    z-index: 2147483647 !important;
    pointer-events: auto !important;
    opacity: 0 !important;
    visibility: hidden !important;
    transition: opacity 0.2s ease, visibility 0.2s ease !important;
}
.tooltip .tooltip-inner {
    font-size: 13px !important;
    padding: 12px 16px !important;
    border-radius: 10px !important;
    max-width: 320px !important;
    text-align: left !important;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15) !important;
    line-height: 1.6 !important;
    white-space: pre-line !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip.show {
    opacity: 1 !important;
    visibility: visible !important;
    display: block !important;
}
.tooltip-arrow::before {
    opacity: 1 !important;
}

/* Show tooltip when target element is hovered */
#kpi-total-inc:hover ~ .bs-tooltip-bottom,
#kpi-total-downtime:hover ~ .bs-tooltip-bottom,
#kpi-total-maint:hover ~ .bs-tooltip-bottom,
#kpi-availability:hover ~ .bs-tooltip-bottom,
#kpi-pph-loss:hover ~ .bs-tooltip-bottom,
#kpi-avg-inc:hover ~ .bs-tooltip-bottom,
#kpi-maint-ratio:hover ~ .bs-tooltip-bottom,
#kpi-mttr:hover ~ .bs-tooltip-bottom,
#kpi-mtbf:hover ~ .bs-tooltip-bottom,
#kpi-sp-total-qty:hover ~ .bs-tooltip-bottom,
#kpi-sp-parts-used:hover ~ .bs-tooltip-bottom,
#kpi-sp-cost:hover ~ .bs-tooltip-bottom,
#kpi-sp-low-stock:hover ~ .bs-tooltip-bottom,
[id*="info-icon"]:hover ~ .bs-tooltip-right,
.chart-info-icon:hover ~ .bs-tooltip-right,
#online-users-btn:hover ~ .bs-tooltip-bottom,
#user-logs-btn:hover ~ .bs-tooltip-bottom,
#sync-logs-btn:hover ~ .bs-tooltip-bottom,
#alert-bell-btn:hover ~ .bs-tooltip-bottom,
#about-btn:hover ~ .bs-tooltip-bottom {
    opacity: 1 !important;
    visibility: visible !important;
}
/* KPI Tooltip Colors - matching KPI card themes */
.tooltip-kpi-incidents .tooltip-inner {
    background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%) !important;
    color: #991b1b !important;
    border: 1px solid #fca5a5 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-incidents .tooltip-arrow::before { 
    border-bottom-color: #fecaca !important;
    opacity: 1 !important;
}

.tooltip-kpi-downtime .tooltip-inner {
    background: linear-gradient(135deg, #fff7ed 0%, #fed7aa 100%) !important;
    color: #9a3412 !important;
    border: 1px solid #fdba74 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-downtime .tooltip-arrow::before { 
    border-bottom-color: #fed7aa !important;
    opacity: 1 !important;
}

.tooltip-kpi-maintenance .tooltip-inner {
    background: linear-gradient(135deg, #ecfdf5 0%, #a7f3d0 100%) !important;
    color: #065f46 !important;
    border: 1px solid #6ee7b7 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-maintenance .tooltip-arrow::before { 
    border-bottom-color: #a7f3d0 !important;
    opacity: 1 !important;
}

.tooltip-kpi-pph .tooltip-inner {
    background: linear-gradient(135deg, #fffbeb 0%, #fde68a 100%) !important;
    color: #92400e !important;
    border: 1px solid #fcd34d !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-pph .tooltip-arrow::before { 
    border-bottom-color: #fde68a !important;
    opacity: 1 !important;
}

.tooltip-kpi-daily .tooltip-inner {
    background: linear-gradient(135deg, #f5f3ff 0%, #ddd6fe 100%) !important;
    color: #5b21b6 !important;
    border: 1px solid #c4b5fd !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-daily .tooltip-arrow::before { 
    border-bottom-color: #ddd6fe !important;
    opacity: 1 !important;
}

.tooltip-kpi-ratio .tooltip-inner {
    background: linear-gradient(135deg, #ecfeff 0%, #a5f3fc 100%) !important;
    color: #155e75 !important;
    border: 1px solid #67e8f9 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-ratio .tooltip-arrow::before { 
    border-bottom-color: #a5f3fc !important;
    opacity: 1 !important;
}

.tooltip-kpi-avg .tooltip-inner {
    background: linear-gradient(135deg, #fdf2f8 0%, #fbcfe8 100%) !important;
    color: #9d174d !important;
    border: 1px solid #f9a8d4 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-avg .tooltip-arrow::before { 
    border-bottom-color: #fbcfe8 !important;
    opacity: 1 !important;
}

.tooltip-kpi-sp .tooltip-inner {
    background: linear-gradient(135deg, #f0fdf4 0%, #bbf7d0 100%) !important;
    color: #166534 !important;
    border: 1px solid #86efac !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-sp .tooltip-arrow::before { 
    border-bottom-color: #bbf7d0 !important;
    opacity: 1 !important;
}

/* New KPI Tooltip Colors */
.tooltip-kpi-mttr .tooltip-inner {
    background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%) !important;
    color: #1e40af !important;
    border: 1px solid #93c5fd !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-mttr .tooltip-arrow::before { 
    border-bottom-color: #dbeafe !important;
    opacity: 1 !important;
}

.tooltip-kpi-mtbf .tooltip-inner {
    background: linear-gradient(135deg, #eef2ff 0%, #e0e7ff 100%) !important;
    color: #3730a3 !important;
    border: 1px solid #a5b4fc !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-mtbf .tooltip-arrow::before { 
    border-bottom-color: #e0e7ff !important;
    opacity: 1 !important;
}

.tooltip-kpi-parts .tooltip-inner {
    background: linear-gradient(135deg, #f5f3ff 0%, #ede9fe 100%) !important;
    color: #5b21b6 !important;
    border: 1px solid #ddd6fe !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-parts .tooltip-arrow::before { 
    border-bottom-color: #ede9fe !important;
    opacity: 1 !important;
}

.tooltip-kpi-alert .tooltip-inner {
    background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%) !important;
    color: #991b1b !important;
    border: 1px solid #fecaca !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-kpi-alert .tooltip-arrow::before { 
    border-bottom-color: #fee2e2 !important;
    opacity: 1 !important;
}

/* Dark mode KPI Tooltips - high contrast */
[data-theme="dark"] .tooltip-kpi-incidents .tooltip-inner {
    background: linear-gradient(135deg, #7f1d1d 0%, #991b1b 100%) !important;
    color: #fef2f2 !important;
    border: 1px solid #dc2626 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-incidents .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-incidents .tooltip-inner strong { color: #fecaca !important; }

[data-theme="dark"] .tooltip-kpi-downtime .tooltip-inner {
    background: linear-gradient(135deg, #7c2d12 0%, #9a3412 100%) !important;
    color: #fff7ed !important;
    border: 1px solid #ea580c !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-downtime .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-downtime .tooltip-inner strong { color: #fed7aa !important; }

[data-theme="dark"] .tooltip-kpi-maintenance .tooltip-inner {
    background: linear-gradient(135deg, #064e3b 0%, #065f46 100%) !important;
    color: #ecfdf5 !important;
    border: 1px solid #10b981 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-maintenance .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-maintenance .tooltip-inner strong { color: #a7f3d0 !important; }

[data-theme="dark"] .tooltip-kpi-pph .tooltip-inner {
    background: linear-gradient(135deg, #78350f 0%, #92400e 100%) !important;
    color: #fffbeb !important;
    border: 1px solid #f59e0b !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-pph .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-pph .tooltip-inner strong { color: #fde68a !important; }

[data-theme="dark"] .tooltip-kpi-daily .tooltip-inner {
    background: linear-gradient(135deg, #4c1d95 0%, #5b21b6 100%) !important;
    color: #f5f3ff !important;
    border: 1px solid #8b5cf6 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-daily .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-daily .tooltip-inner strong { color: #ddd6fe !important; }

[data-theme="dark"] .tooltip-kpi-ratio .tooltip-inner {
    background: linear-gradient(135deg, #164e63 0%, #155e75 100%) !important;
    color: #ecfeff !important;
    border: 1px solid #22d3ee !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-ratio .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-ratio .tooltip-inner strong { color: #a5f3fc !important; }

[data-theme="dark"] .tooltip-kpi-avg .tooltip-inner {
    background: linear-gradient(135deg, #831843 0%, #9d174d 100%) !important;
    color: #fdf2f8 !important;
    border: 1px solid #ec4899 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-avg .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-avg .tooltip-inner strong { color: #fbcfe8 !important; }

[data-theme="dark"] .tooltip-kpi-sp .tooltip-inner {
    background: linear-gradient(135deg, #14532d 0%, #166534 100%) !important;
    color: #f0fdf4 !important;
    border: 1px solid #22c55e !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-sp .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-sp .tooltip-inner strong { color: #bbf7d0 !important; }

[data-theme="dark"] .tooltip-kpi-mttr .tooltip-inner {
    background: linear-gradient(135deg, #1e3a5f 0%, #1e40af 100%) !important;
    color: #dbeafe !important;
    border: 1px solid #3b82f6 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-mttr .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-mttr .tooltip-inner strong { color: #bfdbfe !important; }

[data-theme="dark"] .tooltip-kpi-mtbf .tooltip-inner {
    background: linear-gradient(135deg, #312e81 0%, #4338ca 100%) !important;
    color: #e0e7ff !important;
    border: 1px solid #6366f1 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-mtbf .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-mtbf .tooltip-inner strong { color: #c7d2fe !important; }

[data-theme="dark"] .tooltip-kpi-parts .tooltip-inner {
    background: linear-gradient(135deg, #2e1065 0%, #5b21b6 100%) !important;
    color: #f5f3ff !important;
    border: 1px solid #7c3aed !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-parts .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-parts .tooltip-inner strong { color: #ddd6fe !important; }

[data-theme="dark"] .tooltip-kpi-alert .tooltip-inner {
    background: linear-gradient(135deg, #7f1d1d 0%, #991b1b 100%) !important;
    color: #fef2f2 !important;
    border: 1px solid #dc2626 !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
[data-theme="dark"] .tooltip-kpi-alert .tooltip-inner h2,
[data-theme="dark"] .tooltip-kpi-alert .tooltip-inner strong { color: #fecaca !important; }

/* Chart Info Tooltip - soft blue theme */
.tooltip-chart-info .tooltip-inner {
    background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%) !important;
    color: #1e40af !important;
    border: 1px solid #93c5fd !important;
    font-size: 13px !important;
    padding: 12px 16px !important;
    border-radius: 10px !important;
    max-width: 350px !important;
    text-align: left !important;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12) !important;
    line-height: 1.6 !important;
    white-space: pre-line !important;
    opacity: 1 !important;
    display: block !important;
    visibility: visible !important;
}
.tooltip-chart-info .tooltip-arrow::before { 
    border-right-color: #dbeafe !important;
    opacity: 1 !important;
}
/* Chart info icon hover effect */
.chart-info-icon:hover {
    opacity: 1 !important;
    color: #4f46e5 !important;
}
/* Dark mode chart info tooltip */
[data-theme="dark"] .tooltip-chart-info .tooltip-inner {
    background: linear-gradient(135deg, #1e3a5f 0%, #1e40af 100%) !important;
    color: #e0f2fe !important;
    border: 1px solid #3b82f6 !important;
    opacity: 1 !important;
    display: block !important;
}
[data-theme="dark"] .tooltip-chart-info .tooltip-arrow::before { 
    border-right-color: #1e40af !important;
    opacity: 1 !important;
}
[data-theme="dark"] .chart-info-icon {
    color: #818cf8 !important;
}

/* Chart Info Markdown Styling */
.chart-info-md {
    margin: 0 !important;
    padding: 0 !important;
}
.chart-info-md p {
    margin: 0 0 8px 0 !important;
    line-height: 1.5 !important;
}
.chart-info-md p:last-child {
    margin-bottom: 0 !important;
}
/* Title line - h2 heading with emoji */
.chart-info-md h2 {
    font-size: 16px !important;
    font-weight: 700 !important;
    color: #1e3a8a !important;
    border-bottom: 1px solid rgba(59, 130, 246, 0.3);
    padding-bottom: 8px !important;
    margin: 0 0 10px 0 !important;
}
[data-theme="dark"] .chart-info-md h2 {
    color: #bfdbfe !important;
    border-bottom-color: rgba(96, 165, 250, 0.3);
}
/* Bold text styling (labels like Purpose:, How to read:) */
.chart-info-md strong {
    font-weight: 600 !important;
    font-style: italic !important;
    color: #1d4ed8 !important;
}
[data-theme="dark"] .chart-info-md strong {
    color: #93c5fd !important;
}

/* === Loading Animation === */
._dash-loading {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
}

/* === Horizontal Rule === */
hr {
    border: none;
    height: 1px;
    background: linear-gradient(90deg, transparent, #cbd5e1, transparent);
    margin: 1rem 0;
}

/* === MULTISELECT DROPDOWN CUSTOMIZATION === */
/* 1. Hide the "clear all" (x) button */
.Select-clear-zone {
    display: none !important;
}
.Select--multi .Select-clear {
    display: none !important;
}

/* 2. Limit display box to max 3 lines with scroll */
.Select-value-label,
.Select--multi .Select-value {
    max-width: 100%;
}
/* Ensure scrollbar always on right side for all Select components */
.Select,
.Select-control,
.Select-input,
.Select-placeholder,
.Select--multi,
.Select--multi .Select-control,
.Select--multi .Select-input,
.Select--multi .Select-placeholder,
.Select--multi .Select-multi-value-wrapper {
    direction: ltr !important;
}
.Select--multi .Select-multi-value-wrapper {
    max-height: 78px; /* approximately 3 lines */
    overflow-y: auto !important;
    overflow-x: hidden;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    /* <7> Fix scrollbar jumping to left */
    width: 100% !important;
    padding-right: 4px; 
}

/* 3. Truncate long option text with ellipsis - no wrap */
/* In display box (selected tags) - keep x and text on same line */
.Select--multi .Select-value {
    max-width: 95%;
    overflow: hidden;
    display: inline-flex !important;
    align-items: center !important;
    flex-wrap: nowrap !important;
}
.Select--multi .Select-value-icon {
    flex-shrink: 0;
    order: 2;
}
.Select--multi .Select-value-label {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    display: inline-block !important;
    max-width: 180px;
    flex-shrink: 1;
    order: 1;
}
/* In dropdown list */
.Select-option,
.VirtualizedSelectOption {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}
.Select-menu-outer {
    max-width: 100%;
}
/* Fix 14: Multiselect Dropdown Scroll Fixed to Right */
.Select-menu-outer {
    right: 0 !important;
    left: auto !important;
}
/* Fix 11: Ensure multiselect menu aligns properly */
.Select-menu-outer {
    min-width: 100%;
    width: auto;
}

/* === ENHANCED KPI CARDS - COMPACT === */
.kpi-card {
    background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
    border-radius: 12px;
    padding: 12px 14px;
    text-align: center;
    box-shadow: 
        0 4px 15px rgba(0, 0, 0, 0.08),
        0 1px 3px rgba(0, 0, 0, 0.05),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    transition: transform 0.15s ease-out, box-shadow 0.15s ease-out;
    position: relative;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.8);
}
.kpi-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    border-radius: 12px 12px 0 0;
}
.kpi-card:hover {
    transform: translateY(-4px) scale(1.02);
    box-shadow: 
        0 12px 30px rgba(0, 0, 0, 0.15),
        0 4px 10px rgba(0, 0, 0, 0.1),
        0 0 20px rgba(59, 130, 246, 0.15),
        inset 0 1px 0 rgba(255, 255, 255, 1);
}
/* KPI card shimmer on hover */
.kpi-card::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
    transition: left 0.5s ease;
    pointer-events: none;
}
.kpi-card:hover::after {
    left: 100%;
}
.kpi-card .kpi-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 6px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15);
}
.kpi-card .kpi-value {
    font-size: 1.4rem;
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1.1;
    margin-bottom: 2px;
}
.kpi-card .kpi-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    opacity: 0.85;
}

/* KPI Color Themes - Soft pastel backgrounds */
.kpi-card.kpi-incidents { background: linear-gradient(145deg, #fef2f2 0%, #fee2e2 100%); border-color: #fecaca; }
.kpi-card.kpi-incidents::before { background: linear-gradient(90deg, #ef4444, #f97316); }
.kpi-card.kpi-incidents .kpi-icon { background: linear-gradient(135deg, #ef4444, #dc2626); color: white; }
.kpi-card.kpi-incidents .kpi-value { color: #dc2626; }
.kpi-card.kpi-incidents .kpi-label { color: #991b1b; }

.kpi-card.kpi-maintenance { background: linear-gradient(145deg, #ecfdf5 0%, #d1fae5 100%); border-color: #a7f3d0; }
.kpi-card.kpi-maintenance::before { background: linear-gradient(90deg, #10b981, #059669); }
.kpi-card.kpi-maintenance .kpi-icon { background: linear-gradient(135deg, #10b981, #059669); color: white; }
.kpi-card.kpi-maintenance .kpi-value { color: #059669; }
.kpi-card.kpi-maintenance .kpi-label { color: #065f46; }

.kpi-card.kpi-pph { background: linear-gradient(145deg, #fffbeb 0%, #fef3c7 100%); border-color: #fde68a; }
.kpi-card.kpi-pph::before { background: linear-gradient(90deg, #f59e0b, #d97706); }
.kpi-card.kpi-pph .kpi-icon { background: linear-gradient(135deg, #f59e0b, #d97706); color: white; }
.kpi-card.kpi-pph .kpi-value { color: #b45309; }
.kpi-card.kpi-pph .kpi-label { color: #92400e; }

.kpi-card.kpi-daily { background: linear-gradient(145deg, #f5f3ff 0%, #ede9fe 100%); border-color: #ddd6fe; }
.kpi-card.kpi-daily::before { background: linear-gradient(90deg, #8b5cf6, #7c3aed); }
.kpi-card.kpi-daily .kpi-icon { background: linear-gradient(135deg, #8b5cf6, #7c3aed); color: white; }
.kpi-card.kpi-daily .kpi-value { color: #7c3aed; }
.kpi-card.kpi-daily .kpi-label { color: #5b21b6; }

.kpi-card.kpi-ratio { background: linear-gradient(145deg, #ecfeff 0%, #cffafe 100%); border-color: #a5f3fc; }
.kpi-card.kpi-ratio::before { background: linear-gradient(90deg, #06b6d4, #0891b2); }
.kpi-card.kpi-ratio .kpi-icon { background: linear-gradient(135deg, #06b6d4, #0891b2); color: white; }
.kpi-card.kpi-ratio .kpi-value { color: #0891b2; }
.kpi-card.kpi-ratio .kpi-label { color: #155e75; }

.kpi-card.kpi-avg { background: linear-gradient(145deg, #fdf2f8 0%, #fce7f3 100%); border-color: #fbcfe8; }
.kpi-card.kpi-avg::before { background: linear-gradient(90deg, #ec4899, #db2777); }
.kpi-card.kpi-avg .kpi-icon { background: linear-gradient(135deg, #ec4899, #db2777); color: white; }
.kpi-card.kpi-avg .kpi-value { color: #db2777; }
.kpi-card.kpi-avg .kpi-label { color: #9d174d; }

/* ============================================================
   PERF FIX: Disable card animations on low-end machines.
   heartBeat (1.5s infinite), gradientShift (3s infinite),
   iconFloat (on hover) all run on the main thread.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .fa-heart {
        animation: none !important;
    }
    .team-name-gradient {
        animation: none !important;
        background-position: 0% 50% !important;
    }
    .contact-card:hover .fa-envelope,
    .contact-card:hover .fa-comments {
        animation: none !important;
        transform: none !important;
    }
    /* Disable card entrance animations */
    .fadeInDown, .fadeInUp {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf .fa-heart {
    animation: none !important;
}
html.low-perf .team-name-gradient {
    animation: none !important;
    background-position: 0% 50% !important;
}
html.low-perf .contact-card:hover .fa-envelope,
html.low-perf .contact-card:hover .fa-comments {
    animation: none !important;
    transform: none !important;
}

/* ── 13_kpi_overview.css ─────────────────────────────── */
/* ============================================================
   13_kpi_overview.css — Compact KPI Cards Overview · Spare Parts Sub-header
   Auto-refactored from custom.css
   ============================================================ */

/* === COMPACT KPI CARDS (Overview Tab) - Icon + Value same row === */
.kpi-card-compact {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
    border-radius: 10px;
    padding: 8px 12px;
    text-align: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.9);
    transition: transform 0.15s ease-out, box-shadow 0.15s ease-out;
    position: relative;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.8);
    min-height: 68px; /* Fixed height for 2-line labels */
    height: 68px; /* Ensure all cards same height */
}
.kpi-card-compact::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    border-radius: 10px 10px 0 0;
}
.kpi-card-compact {
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
}

/* Shimmer sweep on hover */
.kpi-card-compact::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    transition: left 0.55s ease;
    pointer-events: none;
    z-index: 1;
}
.kpi-card-compact:hover::after {
    left: 100%;
}

.kpi-card-compact:hover {
    transform: translateY(-6px) scale(1.02);
    box-shadow:
        0 20px 40px rgba(59, 130, 246, 0.15),
        0 0 0 1px rgba(59, 130, 246, 0.1),
        0 0 20px rgba(59, 130, 246, 0.1) !important;
}

/* Per-type colored glow on hover */
.kpi-card-compact.kpi-incidents:hover {
    box-shadow:
        0 20px 40px rgba(239, 68, 68, 0.2),
        0 0 0 1px rgba(239, 68, 68, 0.15),
        0 0 20px rgba(239, 68, 68, 0.15) !important;
    border-color: #ef4444 !important;
}
.kpi-card-compact.kpi-downtime:hover {
    box-shadow:
        0 20px 40px rgba(249, 115, 22, 0.2),
        0 0 0 1px rgba(249, 115, 22, 0.15),
        0 0 20px rgba(249, 115, 22, 0.15) !important;
    border-color: #f97316 !important;
}
.kpi-card-compact.kpi-maintenance:hover {
    box-shadow:
        0 20px 40px rgba(16, 185, 129, 0.2),
        0 0 0 1px rgba(16, 185, 129, 0.15),
        0 0 20px rgba(16, 185, 129, 0.15) !important;
    border-color: #10b981 !important;
}
.kpi-card-compact.kpi-pph:hover {
    box-shadow:
        0 20px 40px rgba(245, 158, 11, 0.2),
        0 0 0 1px rgba(245, 158, 11, 0.15),
        0 0 20px rgba(245, 158, 11, 0.15) !important;
    border-color: #f59e0b !important;
}
.kpi-card-compact.kpi-daily:hover {
    box-shadow:
        0 20px 40px rgba(139, 92, 246, 0.2),
        0 0 0 1px rgba(139, 92, 246, 0.15),
        0 0 20px rgba(139, 92, 246, 0.15) !important;
    border-color: #8b5cf6 !important;
}
.kpi-card-compact.kpi-ratio:hover {
    box-shadow:
        0 20px 40px rgba(6, 182, 212, 0.2),
        0 0 0 1px rgba(6, 182, 212, 0.15),
        0 0 20px rgba(6, 182, 212, 0.15) !important;
    border-color: #06b6d4 !important;
}
.kpi-card-compact.kpi-avg:hover {
    box-shadow:
        0 20px 40px rgba(236, 72, 153, 0.2),
        0 0 0 1px rgba(236, 72, 153, 0.15),
        0 0 20px rgba(236, 72, 153, 0.15) !important;
    border-color: #ec4899 !important;
}
.kpi-card-compact.kpi-mttr:hover {
    box-shadow:
        0 20px 40px rgba(59, 130, 246, 0.2),
        0 0 0 1px rgba(59, 130, 246, 0.15),
        0 0 20px rgba(59, 130, 246, 0.15) !important;
    border-color: #3b82f6 !important;
}
.kpi-card-compact.kpi-mtbf:hover {
    box-shadow:
        0 20px 40px rgba(99, 102, 241, 0.2),
        0 0 0 1px rgba(99, 102, 241, 0.15),
        0 0 20px rgba(99, 102, 241, 0.15) !important;
    border-color: #6366f1 !important;
}
.kpi-card-compact.kpi-availability:hover {
    box-shadow:
        0 20px 40px rgba(52, 211, 153, 0.2),
        0 0 0 1px rgba(52, 211, 153, 0.15),
        0 0 20px rgba(52, 211, 153, 0.15) !important;
    border-color: #34d399 !important;
}
.kpi-compact-row1 {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
    font-weight: 700;
    gap: 3px;
    white-space: nowrap;
    overflow: hidden;
    flex-wrap: nowrap;
}
.kpi-compact-row1 i {
    font-size: 0.9rem;
}
.kpi-compact-row2 {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    opacity: 0.85;
    margin-top: 2px;
}

/* Compact KPI Color Themes */
.kpi-card-compact.kpi-incidents { background: linear-gradient(145deg, #fef2f2 0%, #fee2e2 100%); border-color: #fecaca; }
.kpi-card-compact.kpi-incidents::before { background: linear-gradient(90deg, #ef4444, #f97316); }
.kpi-card-compact.kpi-incidents .kpi-compact-row1 { color: #dc2626; }
.kpi-card-compact.kpi-incidents .kpi-compact-row2 { color: #991b1b; }

/* Downtime KPI - Orange/Amber theme */
.kpi-card-compact.kpi-downtime { background: linear-gradient(145deg, #fff7ed 0%, #ffedd5 100%); border-color: #fed7aa; }
.kpi-card-compact.kpi-downtime::before { background: linear-gradient(90deg, #f97316, #ea580c); }
.kpi-card-compact.kpi-downtime .kpi-compact-row1 { color: #ea580c; }
.kpi-card-compact.kpi-downtime .kpi-compact-row2 { color: #9a3412; }

.kpi-card-compact.kpi-maintenance { background: linear-gradient(145deg, #ecfdf5 0%, #d1fae5 100%); border-color: #a7f3d0; }
.kpi-card-compact.kpi-maintenance::before { background: linear-gradient(90deg, #10b981, #059669); }
.kpi-card-compact.kpi-maintenance .kpi-compact-row1 { color: #059669; }
.kpi-card-compact.kpi-maintenance .kpi-compact-row2 { color: #065f46; }

.kpi-card-compact.kpi-pph { background: linear-gradient(145deg, #fffbeb 0%, #fef3c7 100%); border-color: #fde68a; }
.kpi-card-compact.kpi-pph::before { background: linear-gradient(90deg, #f59e0b, #d97706); }
.kpi-card-compact.kpi-pph .kpi-compact-row1 { color: #b45309; }
.kpi-card-compact.kpi-pph .kpi-compact-row2 { color: #92400e; }

.kpi-card-compact.kpi-daily { background: linear-gradient(145deg, #f5f3ff 0%, #ede9fe 100%); border-color: #ddd6fe; }
.kpi-card-compact.kpi-daily::before { background: linear-gradient(90deg, #8b5cf6, #7c3aed); }
.kpi-card-compact.kpi-daily .kpi-compact-row1 { color: #7c3aed; }
.kpi-card-compact.kpi-daily .kpi-compact-row2 { color: #5b21b6; }

.kpi-card-compact.kpi-ratio { background: linear-gradient(145deg, #ecfeff 0%, #cffafe 100%); border-color: #a5f3fc; }
.kpi-card-compact.kpi-ratio::before { background: linear-gradient(90deg, #06b6d4, #0891b2); }
.kpi-card-compact.kpi-ratio .kpi-compact-row1 { color: #0891b2; }
.kpi-card-compact.kpi-ratio .kpi-compact-row2 { color: #155e75; }

.kpi-card-compact.kpi-avg { background: linear-gradient(145deg, #fdf2f8 0%, #fce7f3 100%); border-color: #fbcfe8; }
.kpi-card-compact.kpi-avg::before { background: linear-gradient(90deg, #ec4899, #db2777); }
.kpi-card-compact.kpi-avg .kpi-compact-row1 { color: #db2777; }
.kpi-card-compact.kpi-avg .kpi-compact-row2 { color: #9d174d; }

/* MTTR KPI - Blue theme */
.kpi-card-compact.kpi-mttr { background: linear-gradient(145deg, #eff6ff 0%, #dbeafe 100%); border-color: #93c5fd; }
.kpi-card-compact.kpi-mttr::before { background: linear-gradient(90deg, #3b82f6, #2563eb); }
.kpi-card-compact.kpi-mttr .kpi-compact-row1 { color: #2563eb; }
.kpi-card-compact.kpi-mttr .kpi-compact-row2 { color: #1e40af; }

/* MTBF KPI - Indigo theme */
.kpi-card-compact.kpi-mtbf { background: linear-gradient(145deg, #eef2ff 0%, #e0e7ff 100%); border-color: #a5b4fc; }
.kpi-card-compact.kpi-mtbf::before { background: linear-gradient(90deg, #6366f1, #4f46e5); }
.kpi-card-compact.kpi-mtbf .kpi-compact-row1 { color: #4f46e5; }
.kpi-card-compact.kpi-mtbf .kpi-compact-row2 { color: #3730a3; }

/* Availability KPI - Emerald theme */
.kpi-card-compact.kpi-availability { background: linear-gradient(145deg, #ecfdf5 0%, #d1fae5 100%); border-color: #6ee7b7; }
.kpi-card-compact.kpi-availability::before { background: linear-gradient(90deg, #34d399, #10b981); }
.kpi-card-compact.kpi-availability .kpi-compact-row1 { color: #059669; }
.kpi-card-compact.kpi-availability .kpi-compact-row2 { color: #047857; }

/* Spare Parts KPI badges */
.kpi-badge {
    display: flex;
    flex-direction: column;
    align-items: center;
    background: linear-gradient(145deg, #ffffff 0%, #f1f5f9 100%);
    border-radius: 10px;
    padding: 8px 16px;
    box-shadow: 
        0 3px 10px rgba(0, 0, 0, 0.08),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.8);
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
    position: relative;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* Shimmer sweep on hover */
.kpi-badge::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    transition: left 0.55s ease;
    pointer-events: none;
    z-index: 1;
}
.kpi-badge:hover::after {
    left: 100%;
}

.kpi-badge:hover {
    transform: translateY(-6px) scale(1.02);
    box-shadow:
        0 20px 40px rgba(59, 130, 246, 0.15),
        0 0 0 1px rgba(59, 130, 246, 0.1),
        0 0 20px rgba(59, 130, 246, 0.1) !important;
}

/* Per-type colored glow on hover */
.kpi-badge.kpi-qty:hover {
    box-shadow:
        0 20px 40px rgba(16, 185, 129, 0.2),
        0 0 0 1px rgba(16, 185, 129, 0.15),
        0 0 20px rgba(16, 185, 129, 0.15) !important;
    border-color: #10b981 !important;
}
.kpi-badge.kpi-parts:hover {
    box-shadow:
        0 20px 40px rgba(139, 92, 246, 0.2),
        0 0 0 1px rgba(139, 92, 246, 0.15),
        0 0 20px rgba(139, 92, 246, 0.15) !important;
    border-color: #8b5cf6 !important;
}
.kpi-badge.kpi-alert:hover {
    box-shadow:
        0 20px 40px rgba(239, 68, 68, 0.2),
        0 0 0 1px rgba(239, 68, 68, 0.15),
        0 0 20px rgba(239, 68, 68, 0.15) !important;
    border-color: #ef4444 !important;
}

/* Chi phí phụ tùng - override inline style on hover */
#kpi-sp-cost:hover {
    box-shadow:
        0 20px 40px rgba(16, 185, 129, 0.2),
        0 0 0 1px rgba(16, 185, 129, 0.15),
        0 0 20px rgba(16, 185, 129, 0.15) !important;
    border-color: #10b981 !important;
    transform: translateY(-6px) scale(1.02);
}
.kpi-badge .kpi-badge-row1 {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 1.1rem;
    font-weight: 700;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
.kpi-badge .kpi-badge-row2 {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-top: 2px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* Compact KPI badges inside the unified sub-header bar */
.sub-header-wrapper.d-flex .kpi-badge {
    padding: 5px 12px;
    border-radius: 8px;
}
.sub-header-wrapper.d-flex .kpi-badge .kpi-badge-row1 {
    font-size: 0.95rem;
}
.sub-header-wrapper.d-flex .kpi-badge .kpi-badge-row2 {
    font-size: 0.58rem;
}


.kpi-badge.kpi-qty .kpi-badge-row1 { color: #059669; }
.kpi-badge.kpi-qty .kpi-badge-row2 { color: #065f46; }
.kpi-badge.kpi-parts { background: linear-gradient(145deg, #f5f3ff 0%, #ede9fe 100%); border-color: #ddd6fe; }
.kpi-badge.kpi-parts .kpi-badge-row1 { color: #7c3aed; }
.kpi-badge.kpi-parts .kpi-badge-row2 { color: #5b21b6; }
.kpi-badge.kpi-alert { background: linear-gradient(145deg, #fef2f2 0%, #fee2e2 100%); border-color: #fecaca; }
.kpi-badge.kpi-alert .kpi-badge-row1 { color: #dc2626; }
.kpi-badge.kpi-alert .kpi-badge-row2 { color: #b91c1c; }

/* Spare Parts Tab - Dynamic Sticky */
.sp-sticky-header {
    position: -webkit-sticky;
    position: sticky;
    top: 60px; /* Will be set dynamically by JS */
    background: linear-gradient(180deg, white 0%, rgba(255,255,255,0.98) 100%);
    backdrop-filter: blur(8px);
    z-index: 1008;
    border-bottom: none;
    margin-bottom: 0;
}
.sp-tabs-wrapper .nav-tabs {
    position: -webkit-sticky;
    position: sticky;
    top: 110px; /* Will be set dynamically by JS */
    background: linear-gradient(180deg, white 0%, rgba(255,255,255,0.98) 100%);
    backdrop-filter: blur(8px);
    z-index: 1007;
}

/* === Spare Parts unified sub-header bar (tabs + KPI badges seamless) === */
.sub-header-wrapper.d-flex {
    position: -webkit-sticky;
    position: sticky;
    top: var(--sticky-tabs-top, 0px);
    /* background & backdrop-filter intentionally not set here — inherited from shared rule above (transparent wrapper) */
    z-index: 1007;
    padding: 0 0 0 0;
    border-bottom: 1px solid rgba(99, 102, 241, 0.35) !important;
    box-shadow: 0 1px 0 rgba(99, 102, 241, 0.15);
    align-items: stretch !important;
}

/* Tabs side: nav-tabs align to bottom edge; frosted bg comes from shared .sub-header-wrapper .nav-tabs rule */
.sub-header-wrapper.d-flex > div:first-child {
    display: flex;
    align-items: flex-end;
    min-width: 0;
}

/* KPI badges side: same frosted background as nav-tabs so the bar looks seamless */
.sub-header-wrapper.d-flex > div:last-child {
    padding: 6px 14px 6px 18px;
    align-items: center;
    flex-shrink: 0;
    background: rgba(30, 41, 59, 0.72);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
}

/* All sticky elements - ensure proper stacking and sharp rendering */
.sticky-header,
.sticky-metrics,
.sub-header-wrapper > h5,
.sub-header-wrapper .nav-tabs,
.sp-sticky-header,
.sp-tabs-wrapper .nav-tabs {
    /* Remove will-change to prevent blur */
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* ============================================================
   PERF FIX: Disable heavy backdrop-filter on KPI cards
   for low-end machines / reduced-motion preference.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .kpi-card,
    .kpi-card-wrapper,
    .kpi-glass-card {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(20, 30, 50, 0.95) !important;
        animation: none !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf .kpi-card,
html.low-perf .kpi-card-wrapper,
html.low-perf .kpi-glass-card {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(20, 30, 50, 0.95) !important;
    animation: none !important;
}

/* ── 14_dark_mode.css ────────────────────────────────── */
/* ============================================================
   14_dark_mode.css — Dark Mode Toggle · Dark Mode Overrides
   Auto-refactored from custom.css
   ============================================================ */

/* === DARK MODE THEME TOGGLE BUTTON === */
/* Navbar right items - consistent spacing */
/* Lang dropdown fills remaining width so left edge aligns with the clock row */
.lang-dropdown-wrapper {
    flex: 1;
    min-width: 0;
}
.lang-dropdown-wrapper .Select,
.lang-dropdown-wrapper .Select-control,
.lang-dropdown-wrapper > div {
    width: 100% !important;
}

.theme-toggle-btn {
    background: rgba(255,255,255,0.15) !important;
    border: 1px solid rgba(255,255,255,0.3) !important;
    color: white !important;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: 50% !important;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.3s ease;
    font-size: 1.1rem;
}
.theme-toggle-btn:hover {
    background: rgba(255,255,255,0.25) !important;
    transform: rotate(15deg);
}

/* === DARK MODE OVERRIDES === */
[data-theme="dark"] body,
[data-theme="dark"] html {
    background-color: var(--bg-light) !important;
}

/* Navbar styling unified in main .navbar rule above */

[data-theme="dark"] .sidebar {
    background: var(--bg-sidebar) !important;
    border-right: 1px solid var(--border-color);
}

[data-theme="dark"] .sidebar-sticky-section {
    background: linear-gradient(180deg, #1e293b 0%, #1e293b 100%) !important;
    border-bottom: 1px solid var(--border-color) !important;
}

[data-theme="dark"] .sidebar-scrollable-section {
    background: transparent !important;
}

/* Sidebar text - dark mode high contrast */
[data-theme="dark"] .sidebar h6,
[data-theme="dark"] .sidebar-scrollable-section h6 {
    color: #ffffff !important;
}

/* Sidebar action buttons - consistent sizing and styling */
.sidebar-action-btn {
    height: 36px !important;
    padding: 0 14px !important;
    font-size: 16px !important;
    font-weight: 600 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    white-space: nowrap !important;
    text-align: center !important;
    overflow: hidden !important;
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%) !important;
    border: none !important;
    border-radius: 8px !important;
    color: white !important;
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3) !important;
    transition: all 0.2s ease !important;
}

.sidebar-action-btn:hover {
    background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4) !important;
    transform: translateY(-1px) !important;
    color: white !important;
}

.sidebar-action-btn:active {
    transform: translateY(0) !important;
}

/* Admin button styling */
.admin-btn {
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%) !important;
    border: none !important;
    font-weight: 600 !important;
    font-size: 20px !important;
    padding: 10px 16px !important;
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3) !important;
    transition: all 0.2s ease !important;
}
.admin-btn:hover {
    background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4) !important;
    transform: translateY(-1px) !important;
}

[data-theme="dark"] #main-content-container {
    background: linear-gradient(180deg, var(--bg-main) 0%, var(--bg-light) 100%) !important;
}

[data-theme="dark"] .sticky-header,
[data-theme="dark"] .sub-header-wrapper > h5,
[data-theme="dark"] .sp-sticky-header {
    background: var(--bg-sticky) !important;
}
/* nav-tabs inside sub-header-wrapper must stay transparent so wrapper border shows */
[data-theme="dark"] .sub-header-wrapper .nav-tabs {
    background: transparent !important;
}
[data-theme="dark"] .sticky-metrics {
    background: linear-gradient(-45deg, 
        rgba(59, 130, 246, 0.25), 
        rgba(139, 92, 246, 0.22), 
        rgba(236, 72, 153, 0.18), 
        rgba(245, 158, 11, 0.15),
        rgba(16, 185, 129, 0.20),
        rgba(6, 182, 212, 0.22),
        rgba(59, 130, 246, 0.25)) !important;
    background-size: 400% 400% !important;
    animation: kpiBgShift 10s ease infinite, kpiPulse 4s ease-in-out infinite !important;
    box-shadow: 0 0 25px rgba(59, 130, 246, 0.5), 0 0 50px rgba(139, 92, 246, 0.3), 0 4px 30px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.08) !important;
}
[data-theme="dark"] .sticky-metrics::before {
    opacity: 1;
}
[data-theme="dark"] .sticky-metrics::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
}


[data-theme="dark"] .accordion {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
}
[data-theme="dark"] .accordion-item {
    background: #283548 !important;
    border: 1px solid var(--border-color) !important;
}
[data-theme="dark"] .accordion-button {
    background: #283548 !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .accordion-button::after {
    filter: invert(1) brightness(2);
}
[data-theme="dark"] .accordion-button:not(.collapsed) {
    background: linear-gradient(135deg, rgba(129,140,248,0.2) 0%, rgba(56,189,248,0.15) 100%) !important;
    color: var(--primary-light) !important;
}
[data-theme="dark"] .accordion-body {
    background: #1e293b !important;
    color: var(--text-secondary);
    border-top: 1px solid var(--border-color);
}

[data-theme="dark"] .filter-label {
    color: var(--text-secondary) !important;
}

[data-theme="dark"] .form-check-label {
    color: var(--text-secondary) !important;
}

[data-theme="dark"] .alert-info {
    background: linear-gradient(135deg, rgba(56,189,248,0.15) 0%, rgba(129,140,248,0.15) 100%) !important;
    color: var(--secondary-color) !important;
    border-color: var(--border-color) !important;
}

[data-theme="dark"] .alert-success {
    background: linear-gradient(135deg, rgba(34,197,94,0.18) 0%, rgba(16,185,129,0.15) 100%) !important;
    color: #86efac !important;
    border-color: var(--border-color) !important;
}

[data-theme="dark"] .alert-danger {
    background: linear-gradient(135deg, rgba(239,68,68,0.18) 0%, rgba(220,38,38,0.15) 100%) !important;
    color: #fca5a5 !important;
    border-color: var(--border-color) !important;
}

/* Dark mode Plotly charts - instant dark background */
[data-theme="dark"] .js-plotly-plot {
    border-radius: var(--border-radius);
    background: var(--bg-card) !important;
}
[data-theme="dark"] .js-plotly-plot .modebar-btn path {
    fill: #94a3b8 !important;
}
[data-theme="dark"] .js-plotly-plot .modebar-btn:hover path {
    fill: #a5b4fc !important;
}

/* Dark mode chart text - high contrast - comprehensive selectors */
[data-theme="dark"] .js-plotly-plot .gtitle,
[data-theme="dark"] .js-plotly-plot .infolayer .gtitle {
    fill: #f1f5f9 !important;
}
/* X-axis tick labels - multiple selector patterns */
[data-theme="dark"] .js-plotly-plot .xtick text,
[data-theme="dark"] .js-plotly-plot .xaxislayer-above text,
[data-theme="dark"] .js-plotly-plot .xaxislayer text,
[data-theme="dark"] .js-plotly-plot g.xtick > text {
    fill: #cbd5e1 !important;
}
/* Y-axis tick labels - multiple selector patterns */
[data-theme="dark"] .js-plotly-plot .ytick text,
[data-theme="dark"] .js-plotly-plot .yaxislayer-above text,
[data-theme="dark"] .js-plotly-plot .yaxislayer text,
[data-theme="dark"] .js-plotly-plot g.ytick > text {
    fill: #cbd5e1 !important;
}
/* Axis titles */
[data-theme="dark"] .js-plotly-plot .g-xtitle text,
[data-theme="dark"] .js-plotly-plot .g-ytitle text,
[data-theme="dark"] .js-plotly-plot .xaxislayer-above .xtitle,
[data-theme="dark"] .js-plotly-plot .yaxislayer-above .ytitle {
    fill: #e2e8f0 !important;
}
/* Value labels on bars/points */
[data-theme="dark"] .js-plotly-plot .textpoint text,
[data-theme="dark"] .js-plotly-plot .bartext text,
[data-theme="dark"] .js-plotly-plot .points text,
[data-theme="dark"] .js-plotly-plot text.bartext {
    fill: #ffffff !important;
}
/* Legend text */
[data-theme="dark"] .js-plotly-plot .legendtext,
[data-theme="dark"] .js-plotly-plot .legend text {
    fill: #cbd5e1 !important;
}
[data-theme="dark"] .js-plotly-plot .legend .bg {
    fill: rgba(30, 41, 59, 0.9) !important;
    stroke: rgba(71, 85, 105, 0.5) !important;
}
/* Grid lines */
[data-theme="dark"] .js-plotly-plot .xgrid line,
[data-theme="dark"] .js-plotly-plot .ygrid line,
[data-theme="dark"] .js-plotly-plot .gridlayer line {
    stroke: rgba(148, 163, 184, 0.15) !important;
}
/* Axis lines */
[data-theme="dark"] .js-plotly-plot .xlines line,
[data-theme="dark"] .js-plotly-plot .ylines line,
[data-theme="dark"] .js-plotly-plot .zerolines line {
    stroke: rgba(148, 163, 184, 0.3) !important;
}
/* Colorbar text */
[data-theme="dark"] .js-plotly-plot .colorbar text,
[data-theme="dark"] .js-plotly-plot .colorbar .cb-ticks text {
    fill: #cbd5e1 !important;
}
[data-theme="dark"] .js-plotly-plot .colorbar .cb-title text {
    fill: #e2e8f0 !important;
}

/* Light mode - white background */
[data-theme="light"] .js-plotly-plot,
:root .js-plotly-plot {
    background: white;
}

[data-theme="dark"] .dash-table-container {
    background: var(--bg-card) !important;
}
[data-theme="dark"] .dash-spreadsheet-container {
    background: var(--bg-card) !important;
}
/* FIX <wp-datatable-white-cells>: cần !important để thắng CSS mặc định
   trắng của thư viện dash_table (load SAU css của mình trong <head> nên
   thắng nếu không có !important) — đây là nguyên nhân các bảng như
   wp-groups-table / wp-approvers-table / wp-reasons-table / wp-matrix-table
   (tab Admin > Work Permit) bị nền TRẮNG không đọc được ở dark mode dù đã
   khai báo background ở trên. NHƯNG !important cũng sẽ đè luôn màu nền
   inline (style_data_conditional) của các ô mã ca trong Shift Schedule
   (#shift-grid-table / #shift-worktime-grid-table) — nên loại trừ 2 bảng
   đó bằng :not() để giữ nguyên hành vi tô màu ca làm việc đã fix trước đó.

   FIX <report-heatmap-tables-lost-color>: cùng lý do trên, !important này
   cũng đang đè luôn màu nền heatmap (style_data_conditional tô màu theo
   giá trị) của 3 bảng pivot trong tab Report — "NUMBER OF INCIDENT TYPE /
   SYSTEM LABEL" (table-last-day-count / table-7d-count) và "DOWNTIME
   DURATION TYPE / SYSTEM LABEL" (table-7d-downtime) — khiến các ô heatmap
   luôn hiện màu nền mặc định thay vì màu theo giá trị. Các bảng này dùng
   id dạng pattern-matching (dict) nên không thể loại trừ bằng #id đơn giản
   như shift-grid; Dash render id dict thành chuỗi JSON trong thuộc tính
   id của DOM nên dùng selector [id*="..."] để loại trừ theo tên bảng.

   FIX <thermal-delta-t-cells-lost-color>: cùng lý do trên, !important này
   cũng đang đè luôn màu nền tô theo threshold (style_data_conditional, xem
   THERMAL_DELTA_T_STYLES / delta_t_style_data_conditional trong
   modules/utils/thermal_rules.py) của 2 cột ΔT Input/ΔT Output trong bảng
   "Electrical Cabinet Thermal Checklist" (#maint-thermal-table) — khiến toàn
   bộ ô ΔT luôn hiện nền xám mặc định (--bg-card) bất kể mức OK/Warning/NG/
   Critical. Loại trừ bảng này bằng #id giống shift-grid. */
[data-theme="dark"] .dash-table-container:not(#shift-grid-table):not(#shift-worktime-grid-table):not(#maint-thermal-table):not([id*="table-last-day-count"]):not([id*="table-7d-count"]):not([id*="table-7d-downtime"]) .dash-spreadsheet-inner td {
    background: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
}
/* Nền + màu chữ mặc định cho các ô KHÔNG khớp rule tô màu ΔT nào của bảng
   thermal checklist (vd cột Device/Name-Location/R/S/T/...) — KHÔNG dùng
   !important để màu ΔT inline (style_data_conditional) vẫn thắng được. */
[data-theme="dark"] .dash-table-container#maint-thermal-table .dash-spreadsheet-inner td {
    background: var(--bg-card);
    color: var(--text-primary);
    border-color: var(--border-color);
}
/* Nền + màu chữ mặc định cho các ô KHÔNG khớp rule heatmap nào (vd cột
   nhãn hệ thống ở bảng pivot) — KHÔNG dùng !important để màu heatmap
   inline (style_data_conditional) của Python vẫn thắng được rule này. */
[data-theme="dark"] .dash-table-container[id*="table-last-day-count"] .dash-spreadsheet-inner td,
[data-theme="dark"] .dash-table-container[id*="table-7d-count"] .dash-spreadsheet-inner td,
[data-theme="dark"] .dash-table-container[id*="table-7d-downtime"] .dash-spreadsheet-inner td {
    background: var(--bg-card);
    color: var(--text-primary);
    border-color: var(--border-color);
}
/* Generic odd row styling for all Dash tables (Light & Dark) */
.dash-table-container:not(#shift-grid-table):not(#shift-worktime-grid-table):not([id*="table-last-day-count"]):not([id*="table-7d-count"]):not([id*="table-7d-downtime"]) .dash-spreadsheet-inner tr:nth-child(odd) td {
    background-color: var(--table-row-odd);
}
/* FIX <thermal-delta-t-cells-lost-color>: loại trừ thêm #maint-thermal-table
   khỏi bản dark-mode !important bên dưới, cùng lý do đã ghi chú ở rule nền ô
   phía trên (~dòng 300) — nếu không, các dòng LẺ trong bảng thermal checklist
   sẽ luôn bị ép về màu nền zebra-stripe mặc định, đè mất màu ΔT theo
   threshold dù dòng đó là dòng lẻ. */
[data-theme="dark"] .dash-table-container:not(#shift-grid-table):not(#shift-worktime-grid-table):not(#maint-thermal-table):not([id*="table-last-day-count"]):not([id*="table-7d-count"]):not([id*="table-7d-downtime"]) .dash-spreadsheet-inner tr:nth-child(odd) td {
    background-color: var(--table-row-odd) !important;
}

[data-theme="dark"] .dash-spreadsheet .dash-filter input {
    background: var(--bg-main) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
}
/* Dark mode table header */
/* FIX <shift-grid-sunday-header-not-yellow>: cùng nguyên nhân với rule loại
   trừ #shift-grid-table/#shift-worktime-grid-table ở phần "td" phía trên
   (đã fix từ trước cho Ô DỮ LIỆU) — nhưng rule "th" (header) này khi đó lại
   bị BỎ SÓT, không được loại trừ tương tự. Hậu quả: !important ở đây luôn
   thắng bất kể specificity (kể cả style_header_conditional do Python tạo ra
   để tô vàng cột Chủ nhật ở HÀNG HEADER, xem weekend_style trong
   build_shift_table()/build_shift_worktime_table() tại ui_shift.py) — nên
   toàn bộ ô header (kể cả cột Chủ nhật) luôn bị ép về màu gradient chàm mặc
   định, không bao giờ hiện được màu vàng. Sửa: thêm 2 loại trừ giống hệt
   dòng "td" ở trên, để header của riêng 2 bảng lịch ca dùng đúng màu do
   Python style_header/style_header_conditional quyết định (vốn đã tự đặt
   nền chàm #3730a3 mặc định cho mọi cột, chỉ ghi đè vàng cho cột Chủ nhật). */
[data-theme="dark"] .dash-table-container:not(#shift-grid-table):not(#shift-worktime-grid-table) .dash-spreadsheet-inner th,
[data-theme="dark"] .dash-table-container:not(#shift-grid-table):not(#shift-worktime-grid-table) .dash-header {
    background: linear-gradient(135deg, #4338ca 0%, #3730a3 100%) !important;
    color: #f1f5f9 !important;
    border: none !important;
    box-shadow: none !important;
}
[data-theme="dark"] .dash-table-container .dash-spreadsheet-inner th {
    border-right: 1px solid rgba(255,255,255,0.1) !important;
    border-bottom: none !important;
}
[data-theme="dark"] .dash-table-container .dash-spreadsheet-inner th:first-child {
    border-left: none !important;
}
[data-theme="dark"] .dash-table-container .dash-spreadsheet-inner th:last-child {
    border-right: none !important;
}
/* Remove outer border from header row */
[data-theme="dark"] .dash-spreadsheet-inner table,
[data-theme="dark"] .dash-spreadsheet-inner thead,
[data-theme="dark"] .dash-spreadsheet-inner thead tr {
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
}
[data-theme="dark"] .dash-spreadsheet {
    border: none !important;
    box-shadow: none !important;
}
/* Dark mode filter row */
[data-theme="dark"] .dash-spreadsheet .dash-filter {
    background: #1e293b !important;
    border-color: #334155 !important;
}
[data-theme="dark"] .dash-spreadsheet .dash-filter input {
    background: #0f172a !important;
    border: 1px solid #334155 !important;
    border-radius: 4px !important;
}
[data-theme="dark"] .dash-spreadsheet .dash-filter input::placeholder {
    color: #64748b !important;
}

[data-theme="dark"] .Select-control {
    background: #283548 !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .Select-input input {
    color: var(--text-primary) !important;
}
[data-theme="dark"] .Select-value-label,
[data-theme="dark"] .Select-placeholder {
    color: var(--text-primary) !important;
}
[data-theme="dark"] .Select-menu-outer {
    background: #283548 !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .Select-option {
    background: #283548 !important;
    color: #f1f5f9 !important;
}
[data-theme="dark"] .Select-option:hover,
[data-theme="dark"] .Select-option.is-focused {
    background: rgba(129,140,248,0.4) !important;
    color: #ffffff !important;
}
/* Language dropdown - fills available width in both modes */
[data-theme="dark"] .lang-dropdown-wrapper {
    flex: 1;
    min-width: 0;
}
[data-theme="dark"] .lang-dropdown-wrapper .Select,
[data-theme="dark"] .lang-dropdown-wrapper .Select-control,
[data-theme="dark"] .lang-dropdown-wrapper > div {
    width: 100% !important;
}
[data-theme="dark"] .theme-toggle-btn {
    width: 40px !important;
    height: 40px !important;
}

/* Language dropdown dark mode - high contrast (multiple selectors for compatibility) */
[data-theme="dark"] .lang-dropdown-wrapper .Select-menu-outer,
[data-theme="dark"] .lang-dropdown-wrapper .Select-menu,
[data-theme="dark"] .lang-dropdown-wrapper .VirtualizedSelectFocusedOption,
[data-theme="dark"] .lang-dropdown-wrapper [class*="menu"] {
    background: #1e293b !important;
}
[data-theme="dark"] .lang-dropdown-wrapper .Select-option,
[data-theme="dark"] .lang-dropdown-wrapper .VirtualizedSelectOption,
[data-theme="dark"] .lang-dropdown-wrapper [class*="option"] {
    background: #1e293b !important;
    color: #f8fafc !important;
}
[data-theme="dark"] .lang-dropdown-wrapper .Select-option:hover,
[data-theme="dark"] .lang-dropdown-wrapper .Select-option.is-focused,
[data-theme="dark"] .lang-dropdown-wrapper .VirtualizedSelectFocusedOption,
[data-theme="dark"] .lang-dropdown-wrapper [class*="option"]:hover {
    background: #3b82f6 !important;
    color: #ffffff !important;
}
[data-theme="dark"] .lang-dropdown-wrapper .Select-option.is-selected,
[data-theme="dark"] .lang-dropdown-wrapper [class*="option"][class*="selected"] {
    background: #2563eb !important;
    color: #ffffff !important;
}
[data-theme="dark"] .Select-option.is-selected {
    background: var(--primary-color) !important;
    color: white !important;
}

/* Dark mode KPI Cards - keep distinct colors */
[data-theme="dark"] .kpi-card {
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3) !important;
}
[data-theme="dark"] .kpi-card.kpi-incidents {
    background: linear-gradient(145deg, #451a1a 0%, #7f1d1d 100%) !important;
    border-color: #991b1b !important;
}
[data-theme="dark"] .kpi-card.kpi-incidents .kpi-value { color: #fca5a5 !important; }
[data-theme="dark"] .kpi-card.kpi-incidents .kpi-label { color: #fecaca !important; }

[data-theme="dark"] .kpi-card.kpi-maintenance {
    background: linear-gradient(145deg, #14412a 0%, #166534 100%) !important;
    border-color: #15803d !important;
}
[data-theme="dark"] .kpi-card.kpi-maintenance .kpi-value { color: #86efac !important; }
[data-theme="dark"] .kpi-card.kpi-maintenance .kpi-label { color: #bbf7d0 !important; }

[data-theme="dark"] .kpi-card.kpi-pph {
    background: linear-gradient(145deg, #451a03 0%, #92400e 100%) !important;
    border-color: #b45309 !important;
}
[data-theme="dark"] .kpi-card.kpi-pph .kpi-value { color: #fcd34d !important; }
[data-theme="dark"] .kpi-card.kpi-pph .kpi-label { color: #fde68a !important; }

[data-theme="dark"] .kpi-card.kpi-daily {
    background: linear-gradient(145deg, #2e1065 0%, #5b21b6 100%) !important;
    border-color: #7c3aed !important;
}
[data-theme="dark"] .kpi-card.kpi-daily .kpi-value { color: #c4b5fd !important; }
[data-theme="dark"] .kpi-card.kpi-daily .kpi-label { color: #ddd6fe !important; }

[data-theme="dark"] .kpi-card.kpi-ratio {
    background: linear-gradient(145deg, #083344 0%, #155e75 100%) !important;
    border-color: #0891b2 !important;
}
[data-theme="dark"] .kpi-card.kpi-ratio .kpi-value { color: #67e8f9 !important; }
[data-theme="dark"] .kpi-card.kpi-ratio .kpi-label { color: #a5f3fc !important; }

[data-theme="dark"] .kpi-card.kpi-avg {
    background: linear-gradient(145deg, #500724 0%, #9d174d 100%) !important;
    border-color: #be185d !important;
}
[data-theme="dark"] .kpi-card.kpi-avg .kpi-value { color: #f9a8d4 !important; }
[data-theme="dark"] .kpi-card.kpi-avg .kpi-label { color: #fbcfe8 !important; }

/* Dark mode KPI card hover glow */
[data-theme="dark"] .kpi-card:hover {
    box-shadow: 
        0 12px 30px rgba(0, 0, 0, 0.4),
        0 4px 10px rgba(0, 0, 0, 0.3),
        0 0 25px rgba(59, 130, 246, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}
[data-theme="dark"] .kpi-card::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
}

/* Dark mode Compact KPI Cards */
[data-theme="dark"] .kpi-card-compact {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
}
[data-theme="dark"] .kpi-card-compact::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
}
[data-theme="dark"] .kpi-card-compact.kpi-incidents:hover {
    box-shadow:
        0 20px 40px rgba(252, 165, 165, 0.25),
        0 0 0 1px rgba(252, 165, 165, 0.2),
        0 0 25px rgba(252, 165, 165, 0.2) !important;
    border-color: #fca5a5 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-downtime:hover {
    box-shadow:
        0 20px 40px rgba(253, 186, 116, 0.25),
        0 0 0 1px rgba(253, 186, 116, 0.2),
        0 0 25px rgba(253, 186, 116, 0.2) !important;
    border-color: #fdba74 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-maintenance:hover {
    box-shadow:
        0 20px 40px rgba(134, 239, 172, 0.25),
        0 0 0 1px rgba(134, 239, 172, 0.2),
        0 0 25px rgba(134, 239, 172, 0.2) !important;
    border-color: #86efac !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-pph:hover {
    box-shadow:
        0 20px 40px rgba(252, 211, 77, 0.25),
        0 0 0 1px rgba(252, 211, 77, 0.2),
        0 0 25px rgba(252, 211, 77, 0.2) !important;
    border-color: #fcd34d !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-daily:hover {
    box-shadow:
        0 20px 40px rgba(196, 181, 253, 0.25),
        0 0 0 1px rgba(196, 181, 253, 0.2),
        0 0 25px rgba(196, 181, 253, 0.2) !important;
    border-color: #c4b5fd !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-ratio:hover {
    box-shadow:
        0 20px 40px rgba(103, 232, 249, 0.25),
        0 0 0 1px rgba(103, 232, 249, 0.2),
        0 0 25px rgba(103, 232, 249, 0.2) !important;
    border-color: #67e8f9 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-avg:hover {
    box-shadow:
        0 20px 40px rgba(249, 168, 212, 0.25),
        0 0 0 1px rgba(249, 168, 212, 0.2),
        0 0 25px rgba(249, 168, 212, 0.2) !important;
    border-color: #f9a8d4 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-mttr:hover {
    box-shadow:
        0 20px 40px rgba(147, 197, 253, 0.25),
        0 0 0 1px rgba(147, 197, 253, 0.2),
        0 0 25px rgba(147, 197, 253, 0.2) !important;
    border-color: #93c5fd !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-mtbf:hover {
    box-shadow:
        0 20px 40px rgba(165, 180, 252, 0.25),
        0 0 0 1px rgba(165, 180, 252, 0.2),
        0 0 25px rgba(165, 180, 252, 0.2) !important;
    border-color: #a5b4fc !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-availability:hover {
    box-shadow:
        0 20px 40px rgba(110, 231, 183, 0.25),
        0 0 0 1px rgba(110, 231, 183, 0.2),
        0 0 25px rgba(110, 231, 183, 0.2) !important;
    border-color: #6ee7b7 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-incidents {
    background: linear-gradient(145deg, #451a1a 0%, #7f1d1d 100%) !important;
    border-color: #991b1b !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-incidents .kpi-compact-row1 { color: #fca5a5 !important; }
[data-theme="dark"] .kpi-card-compact.kpi-incidents .kpi-compact-row2 { color: #fecaca !important; }

[data-theme="dark"] .kpi-card-compact.kpi-downtime {
    background: linear-gradient(145deg, #431407 0%, #7c2d12 100%) !important;
    border-color: #c2410c !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-downtime .kpi-compact-row1 { color: #fdba74 !important; }
[data-theme="dark"] .kpi-card-compact.kpi-downtime .kpi-compact-row2 { color: #fed7aa !important; }

[data-theme="dark"] .kpi-card-compact.kpi-maintenance {
    background: linear-gradient(145deg, #14412a 0%, #166534 100%) !important;
    border-color: #15803d !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-maintenance .kpi-compact-row1 { color: #86efac !important; }
[data-theme="dark"] .kpi-card-compact.kpi-maintenance .kpi-compact-row2 { color: #bbf7d0 !important; }

[data-theme="dark"] .kpi-card-compact.kpi-pph {
    background: linear-gradient(145deg, #451a03 0%, #92400e 100%) !important;
    border-color: #b45309 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-pph .kpi-compact-row1 { color: #fcd34d !important; }
[data-theme="dark"] .kpi-card-compact.kpi-pph .kpi-compact-row2 { color: #fde68a !important; }

[data-theme="dark"] .kpi-card-compact.kpi-daily {
    background: linear-gradient(145deg, #2e1065 0%, #5b21b6 100%) !important;
    border-color: #7c3aed !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-daily .kpi-compact-row1 { color: #c4b5fd !important; }
[data-theme="dark"] .kpi-card-compact.kpi-daily .kpi-compact-row2 { color: #ddd6fe !important; }

[data-theme="dark"] .kpi-card-compact.kpi-ratio {
    background: linear-gradient(145deg, #083344 0%, #155e75 100%) !important;
    border-color: #0891b2 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-ratio .kpi-compact-row1 { color: #67e8f9 !important; }
[data-theme="dark"] .kpi-card-compact.kpi-ratio .kpi-compact-row2 { color: #a5f3fc !important; }

[data-theme="dark"] .kpi-card-compact.kpi-avg {
    background: linear-gradient(145deg, #500724 0%, #9d174d 100%) !important;
    border-color: #be185d !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-avg .kpi-compact-row1 { color: #f9a8d4 !important; }
[data-theme="dark"] .kpi-card-compact.kpi-avg .kpi-compact-row2 { color: #fbcfe8 !important; }

[data-theme="dark"] .kpi-card-compact.kpi-mttr {
    background: linear-gradient(145deg, #1e3a5f 0%, #1e40af 100%) !important;
    border-color: #3b82f6 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-mttr .kpi-compact-row1 { color: #93c5fd !important; }
[data-theme="dark"] .kpi-card-compact.kpi-mttr .kpi-compact-row2 { color: #bfdbfe !important; }

[data-theme="dark"] .kpi-card-compact.kpi-mtbf {
    background: linear-gradient(145deg, #312e81 0%, #4338ca 100%) !important;
    border-color: #6366f1 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-mtbf .kpi-compact-row1 { color: #a5b4fc !important; }
[data-theme="dark"] .kpi-card-compact.kpi-mtbf .kpi-compact-row2 { color: #c7d2fe !important; }

[data-theme="dark"] .kpi-card-compact.kpi-availability {
    background: linear-gradient(145deg, #064e3b 0%, #047857 100%) !important;
    border-color: #10b981 !important;
}
[data-theme="dark"] .kpi-card-compact.kpi-availability .kpi-compact-row1 { color: #6ee7b7 !important; }
[data-theme="dark"] .kpi-card-compact.kpi-availability .kpi-compact-row2 { color: #a7f3d0 !important; }

[data-theme="dark"] .kpi-badge {
    background: var(--bg-card) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .kpi-badge::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
}
[data-theme="dark"] .kpi-badge.kpi-qty:hover {
    box-shadow:
        0 20px 40px rgba(134, 239, 172, 0.25),
        0 0 0 1px rgba(134, 239, 172, 0.2),
        0 0 25px rgba(134, 239, 172, 0.2) !important;
    border-color: #86efac !important;
}
[data-theme="dark"] .kpi-badge.kpi-parts:hover {
    box-shadow:
        0 20px 40px rgba(196, 181, 253, 0.25),
        0 0 0 1px rgba(196, 181, 253, 0.2),
        0 0 25px rgba(196, 181, 253, 0.2) !important;
    border-color: #c4b5fd !important;
}
[data-theme="dark"] .kpi-badge.kpi-alert:hover {
    box-shadow:
        0 20px 40px rgba(252, 165, 165, 0.25),
        0 0 0 1px rgba(252, 165, 165, 0.2),
        0 0 25px rgba(252, 165, 165, 0.2) !important;
    border-color: #fca5a5 !important;
}

/* Chi phí phụ tùng dark mode - override inline style on hover */
[data-theme="dark"] #kpi-sp-cost:hover {
    box-shadow:
        0 20px 40px rgba(134, 239, 172, 0.25),
        0 0 0 1px rgba(134, 239, 172, 0.2),
        0 0 25px rgba(134, 239, 172, 0.2) !important;
    border-color: #86efac !important;
    transform: translateY(-6px) scale(1.02);
}
[data-theme="dark"] .kpi-badge.kpi-qty {
    background: linear-gradient(145deg, #14412a 0%, #166534 100%) !important;
    border-color: #15803d !important;
}
[data-theme="dark"] .kpi-badge.kpi-qty .kpi-badge-row1 {
    color: #86efac !important;
}
[data-theme="dark"] .kpi-badge.kpi-qty .kpi-badge-row2 {
    color: #bbf7d0 !important;
}
[data-theme="dark"] .kpi-badge.kpi-parts {
    background: linear-gradient(145deg, #2e1065 0%, #5b21b6 100%) !important;
    border-color: #7c3aed !important;
}
[data-theme="dark"] .kpi-badge.kpi-parts .kpi-badge-row1 {
    color: #c4b5fd !important;
}
[data-theme="dark"] .kpi-badge.kpi-parts .kpi-badge-row2 {
    color: #ddd6fe !important;
}
[data-theme="dark"] .kpi-badge.kpi-alert {
    background: linear-gradient(145deg, #7f1d1d 0%, #991b1b 100%) !important;
    border-color: #dc2626 !important;
}
[data-theme="dark"] .kpi-badge.kpi-alert .kpi-badge-row1 {
    color: #fca5a5 !important;
}
[data-theme="dark"] .kpi-badge.kpi-alert .kpi-badge-row2 {
    color: #fecaca !important;
}

/* Dark mode scrollbars - sidebar and main content */
/* Dark mode multiselect values */
[data-theme="dark"] .Select-multi-value-wrapper .Select-value {
    background-color: #475569 !important;
    border-color: #64748b !important;
    color: #f1f5f9 !important;
}
[data-theme="dark"] .Select-multi-value-wrapper .Select-value-label {
    color: #f1f5f9 !important;
}
[data-theme="dark"] .Select-multi-value-wrapper .Select-value-icon {
    border-color: #64748b !important;
    color: #cbd5e1 !important;
}
[data-theme="dark"] .Select-multi-value-wrapper .Select-value-icon:hover {
    background-color: #64748b !important;
    color: #ffffff !important;
}

/* Modal border styling - cyan accent */
.modal-content {
    border: 2px solid #06b6d4 !important;
    border-radius: 8px !important;
    box-shadow: 0 4px 20px rgba(6, 182, 212, 0.15) !important;
}
[data-theme="dark"] .modal-content {
    background: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border: 2px solid #06b6d4 !important;
    box-shadow: 0 4px 25px rgba(6, 182, 212, 0.3) !important;
}
[data-theme="dark"] .modal-header {
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .modal-header .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%) !important;
    opacity: 0.8 !important;
}
[data-theme="dark"] .modal-header .btn-close:hover {
    opacity: 1 !important;
}
[data-theme="dark"] .modal-body {
    color: #e2e8f0 !important;
}
/* Admin order list items - high contrast in dark mode */
[data-theme="dark"] .admin-order-item {
    background-color: #1e293b !important;
    border-color: #475569 !important;
}
[data-theme="dark"] .admin-order-item span,
[data-theme="dark"] .admin-order-item strong {
    color: #f1f5f9 !important;
}
[data-theme="dark"] .admin-order-item .text-primary {
    color: #60a5fa !important;
}
/* Admin logout button - high contrast */
[data-theme="dark"] #admin-logout-btn,
[data-theme="dark"] .btn-danger {
    background-color: #dc2626 !important;
    border-color: #dc2626 !important;
    color: #ffffff !important;
}
[data-theme="dark"] #admin-logout-btn:hover,
[data-theme="dark"] .btn-danger:hover {
    background-color: #ef4444 !important;
    border-color: #ef4444 !important;
    color: #ffffff !important;
}
/* Admin empty list text - high contrast for dark mode */
.admin-empty-list-text {
    color: #6b7280;
}
[data-theme="dark"] .admin-empty-list-text {
    color: #9ca3af !important;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 4px;
    padding: 8px 12px !important;
}

/* ── Admin Modal: Report tab – dark mode contrast fix ──────────────────────
   Bootstrap form-text (.form-text), html.Small (.small), dbc.Label (.form-label),
   html.Code (code), dbc.FormText — tất cả đều cần màu sáng hơn trong dark mode.
   Áp dụng cho toàn bộ #admin-modal để bao phủ mọi tab, không chỉ Report.
──────────────────────────────────────────────────────────────────────────── */
[data-theme="dark"] #admin-modal .form-text,
[data-theme="dark"] #admin-modal small,
[data-theme="dark"] #admin-modal .small {
    color: #94a3b8 !important;
}
[data-theme="dark"] #admin-modal small.text-muted,
[data-theme="dark"] #admin-modal .small.text-muted,
[data-theme="dark"] #admin-modal .text-muted {
    color: #94a3b8 !important;
}
/* Label trong form — đảm bảo dễ đọc */
[data-theme="dark"] #admin-modal .form-label,
[data-theme="dark"] #admin-modal label {
    color: #e2e8f0 !important;
}
/* Code inline (github.com/settings/tokens, workflow, v.v.) */
[data-theme="dark"] #admin-modal code {
    color: #7dd3fc !important;
    background-color: rgba(125, 211, 252, 0.1) !important;
    border-radius: 3px;
    padding: 1px 4px;
}
/* Link trong form hint */
[data-theme="dark"] #admin-modal .form-text a,
[data-theme="dark"] #admin-modal small a {
    color: #38bdf8 !important;
}
[data-theme="dark"] #admin-modal .form-text a:hover,
[data-theme="dark"] #admin-modal small a:hover {
    color: #7dd3fc !important;
}
/* FormText có inline style fontSize — override color */
[data-theme="dark"] #admin-modal [style*="fontSize"] {
    color: #94a3b8;
}
/* Section hint boxes (background var(--card-bg) + border) */
[data-theme="dark"] #admin-modal .p-2.mb-2 {
    background: rgba(30, 41, 59, 0.8) !important;
    border-color: #334155 !important;
}
[data-theme="dark"] #admin-modal .p-2.mb-2 .text-muted,
[data-theme="dark"] #admin-modal .p-2.mb-2 small,
[data-theme="dark"] #admin-modal .p-2.mb-2 .small {
    color: #94a3b8 !important;
}
/* Holiday label */
[data-theme="dark"] #admin-modal .text-muted.small,
[data-theme="dark"] #admin-modal small.fw-bold {
    color: #cbd5e1 !important;
}
/* Strong/bold hint text */
[data-theme="dark"] #admin-modal .form-text strong,
[data-theme="dark"] #admin-modal small strong {
    color: #e2e8f0 !important;
}
/* Admin action buttons - uniform height */
.admin-action-btn {
    min-height: 32px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    white-space: nowrap !important;
    font-size: 12px !important;
    padding: 4px 10px !important;
}
/* Admin main tabs - with arrow navigation - MAXIMUM SPECIFICITY */
#admin-modal .modal-body #admin-settings-section #admin-tabs-wrapper {
    display: block !important;
    position: relative !important;
    max-width: 100% !important;
    background: var(--modal-bg, #ffffff) !important;
    z-index: 10 !important;
    padding-bottom: 10px !important;
    border-bottom: 1px solid var(--border-color, #dee2e6) !important;
    margin-bottom: 10px !important;
}
/* Admin modal body - no scroll, only content wrapper scrolls */
#admin-modal .modal-body {
    padding-bottom: 0 !important;
    overflow: hidden !important;
}
/* Admin sub-tabs content wrapper - scrollable like Batch Export */
#admin-tabs-scroll-container > .tab-content {
    max-height: none !important;
    overflow-y: visible !important;
    overflow-x: hidden !important;
    padding-right: 5px !important;
}
/* Nav row with arrows - position at top */
#admin-tabs-wrapper::before {
    content: '';
    display: block;
    height: 0;
}
/* Position arrows absolutely at the nav row level */
#admin-tabs-scroll-left,
#admin-tabs-scroll-right {
    position: absolute !important;
    top: 6px !important;
    z-index: 100 !important;
}
#admin-tabs-scroll-left {
    left: 0 !important;
}
#admin-tabs-scroll-right {
    right: 0 !important;
}
/* Scroll container needs padding for arrows */
#admin-tabs-scroll-container {
    padding-left: 32px !important;
    padding-right: 32px !important;
}
/* Arrow buttons - HIGH SPECIFICITY */
#admin-modal .modal-body .admin-tabs-arrow,
#admin-tabs-wrapper > .admin-tabs-arrow,
button.admin-tabs-arrow {
    background: var(--primary-color, #6366f1) !important;
    color: white !important;
    border: none !important;
    border-radius: 4px !important;
    width: 28px !important;
    height: 28px !important;
    min-width: 28px !important;
    max-width: 28px !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 12px !important;
    flex-shrink: 0 !important;
    flex-grow: 0 !important;
    transition: all 0.2s !important;
    opacity: 1 !important;
    visibility: visible !important;
    padding: 0 !important;
    margin: 0 2px !important;
}
#admin-modal .modal-body .admin-tabs-arrow.hidden,
button.admin-tabs-arrow.hidden {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    width: 0 !important;
    min-width: 0 !important;
    max-width: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
}
.admin-tabs-arrow:hover {
    background: var(--primary-dark, #4f46e5) !important;
}
.admin-tabs-arrow:active {
    transform: scale(0.95);
}
/* Scroll container - DOES scroll horizontally, holds tabs + content */
/* (overflow settings moved to the main ADMIN TABS section below) */
/* Alert tab - hide horizontal scrollbar completely */
#admin-main-tabs .tab-pane,
#admin-main-tabs .tab-content {
    overflow-x: hidden !important;
    max-width: 100% !important;
}
.tab-pane[id*="alerts"],
[data-tab-id="admin-main-alerts"] {
    overflow-x: hidden !important;
}

/* ============================================================
   DARK MODE FIXES — Bổ sung (added for UI consistency)
   Fixes: modal cards, report filter, planning/checklist filter,
   user logs filter, và các thành phần chưa đồng bộ dark mode.
   ============================================================ */

/* ── 1. Modal Admin / PM Notice / Database: card backgrounds ── */
[data-theme="dark"] #admin-modal .card,
[data-theme="dark"] #admin-modal .card-body,
[data-theme="dark"] #admin-modal .card-header {
    background-color: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] #admin-modal .card .text-muted,
[data-theme="dark"] #admin-modal .card small,
[data-theme="dark"] #admin-modal .card .small {
    color: var(--text-muted) !important;
}
[data-theme="dark"] #admin-modal .card h5,
[data-theme="dark"] #admin-modal .card h6,
[data-theme="dark"] #admin-modal .card strong,
[data-theme="dark"] #admin-modal .card span,
[data-theme="dark"] #admin-modal .card p,
[data-theme="dark"] #admin-modal .card label {
    color: var(--text-primary) !important;
}
/* PM Notice tab cards */
[data-theme="dark"] #admin-pm-notify-tab .card,
[data-theme="dark"] [id*="pm-notify"] .card,
[data-theme="dark"] [id*="pm_notify"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
/* Database tab cards */
[data-theme="dark"] #admin-database-tab .card,
[data-theme="dark"] [id*="database"] .card,
[data-theme="dark"] [id*="db-"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}

/* ── 2. Tab Báo cáo — Bộ lọc báo cáo ── */
[data-theme="dark"] #report-filter-wrapper,
[data-theme="dark"] #report-filter-wrapper .card,
[data-theme="dark"] #report-filter-wrapper .card-body {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] #report-filter-wrapper label,
[data-theme="dark"] #report-filter-wrapper .fw-bold,
[data-theme="dark"] #report-filter-wrapper h6 {
    color: var(--text-primary) !important;
}
[data-theme="dark"] #report-filter-wrapper .text-muted,
[data-theme="dark"] #report-filter-wrapper small {
    color: var(--text-muted) !important;
}

/* ── 3. Tab Báo cáo — card nội dung (ca/ngày/tuần/tháng) ── */
/* Báo cáo ca */
[data-theme="dark"] .shift-report-card,
[data-theme="dark"] [id*="shift-report"] .card,
[data-theme="dark"] [id*="report-shift"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
/* Báo cáo ngày */
[data-theme="dark"] .daily-report-card,
[data-theme="dark"] [id*="daily-report"] .card,
[data-theme="dark"] [id*="report-daily"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
/* Báo cáo tuần */
[data-theme="dark"] .weekly-report-card,
[data-theme="dark"] [id*="weekly-report"] .card,
[data-theme="dark"] [id*="report-weekly"] .card,
[data-theme="dark"] .weekly-col2-card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
/* Báo cáo tháng */
[data-theme="dark"] .monthly-trend-status-card,
[data-theme="dark"] .monthly-trend-compare-card,
[data-theme="dark"] .monthly-top-card,
[data-theme="dark"] .monthly-analysis-card,
[data-theme="dark"] [id*="monthly-report"] .card,
[data-theme="dark"] [id*="report-monthly"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
/* Generic: mọi card trong report sub-content */
[data-theme="dark"] #report-sub-content .card,
[data-theme="dark"] #tab-content-reports .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] #report-sub-content .card .text-muted,
[data-theme="dark"] #tab-content-reports .card .text-muted,
[data-theme="dark"] #report-sub-content .card small,
[data-theme="dark"] #tab-content-reports .card small {
    color: var(--text-muted) !important;
}
[data-theme="dark"] #report-sub-content .card-header,
[data-theme="dark"] #tab-content-reports .card-header {
    background-color: rgba(30, 41, 59, 0.8) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}

/* ── 4. Tab Bảo trì / Planning — Bộ lọc Planning ── */
[data-theme="dark"] #maint-planning-filter,
[data-theme="dark"] #maint-details-filter {
    background: transparent !important;
}
[data-theme="dark"] #maint-planning-filter .card,
[data-theme="dark"] #maint-details-filter .card,
[data-theme="dark"] #maint-planning-filter .card-body,
[data-theme="dark"] #maint-details-filter .card-body {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] #maint-planning-filter label,
[data-theme="dark"] #maint-details-filter label,
[data-theme="dark"] #maint-planning-filter .fw-bold,
[data-theme="dark"] #maint-details-filter .fw-bold,
[data-theme="dark"] #maint-planning-filter h6,
[data-theme="dark"] #maint-details-filter h6 {
    color: var(--text-primary) !important;
}
[data-theme="dark"] #maint-planning-filter .text-muted,
[data-theme="dark"] #maint-details-filter .text-muted {
    color: var(--text-muted) !important;
}
/* Filter container chứa Select dropdowns + inputs */
[data-theme="dark"] #maint-planning-filter .form-control,
[data-theme="dark"] #maint-details-filter .form-control,
[data-theme="dark"] #maint-planning-filter input,
[data-theme="dark"] #maint-details-filter input {
    background-color: #1e293b !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}

/* ── 5. Tab Bảo trì / Chi tiết Checklist — Bộ lọc checklist ── */
[data-theme="dark"] #maint-cl-filter,
[data-theme="dark"] [id*="checklist-filter"],
[data-theme="dark"] [id*="cl-filter"] {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] #maint-cl-filter .card,
[data-theme="dark"] [id*="checklist-filter"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] #maint-cl-filter label,
[data-theme="dark"] [id*="checklist-filter"] label {
    color: var(--text-primary) !important;
}

/* ── 6. Modal User Logs — card thống kê + card lựa chọn ── */
[data-theme="dark"] #user-logs-modal .card,
[data-theme="dark"] #user-logs-modal .card-body {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .user-logs-stats-card {
    background: var(--bg-section) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .user-logs-stats-card-title {
    color: var(--text-muted) !important;
}
[data-theme="dark"] .user-logs-stats-list .stat-name {
    color: var(--text-primary) !important;
}
[data-theme="dark"] .user-logs-stats-list li {
    border-color: var(--border-color) !important;
}
/* Filter / option cards bên trong user logs */
[data-theme="dark"] #user-logs-modal .bg-light,
[data-theme="dark"] #user-logs-modal [class*="filter"],
[data-theme="dark"] #user-logs-modal [class*="option"] {
    background-color: var(--bg-section) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] #user-logs-modal label,
[data-theme="dark"] #user-logs-modal .fw-bold,
[data-theme="dark"] #user-logs-modal h6,
[data-theme="dark"] #user-logs-modal .form-label {
    color: var(--text-primary) !important;
}
[data-theme="dark"] #user-logs-modal .text-muted,
[data-theme="dark"] #user-logs-modal small {
    color: var(--text-muted) !important;
}
[data-theme="dark"] #user-logs-modal .form-control,
[data-theme="dark"] #user-logs-modal input[type="number"],
[data-theme="dark"] #user-logs-modal input[type="text"] {
    background-color: #1e293b !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}

/* ── 7. Form controls chung trong dark mode (input, select) ── */
[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select,
[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="number"],
[data-theme="dark"] input[type="email"],
[data-theme="dark"] input[type="password"],
[data-theme="dark"] textarea,
[data-theme="dark"] select {
    background-color: #1e293b !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .form-control::placeholder,
[data-theme="dark"] input::placeholder,
[data-theme="dark"] textarea::placeholder {
    color: var(--text-muted) !important;
    opacity: 0.7;
}

/* ── 8. Bảng API Key (Admin > Cài đặt > API Key) — dbc.Table mặc định
   dùng nền/màu Bootstrap trắng-đen, không theo biến theme -> chữ trắng
   trên nền trắng, không đọc được ở dark mode. Ép theo biến theme. ── */
[data-theme="dark"] table.apikey-table {
    background-color: var(--bg-card) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] table.apikey-table > thead > tr > th {
    background-color: var(--table-header-bg, #4f46e5) !important;
    color: #ffffff !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] table.apikey-table > tbody > tr > td {
    background-color: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] table.apikey-table > tbody > tr:hover > td {
    background-color: var(--table-row-odd, rgba(255,255,255,0.05)) !important;
}
[data-theme="dark"] table.apikey-table code {
    color: var(--secondary-color, #0ea5e9) !important;
    background: transparent !important;
}
[data-theme="dark"] table.apikey-table .text-muted {
    color: var(--text-muted) !important;
}

/* (FIX — giảm font size toàn bộ bảng API Key cho gọn, đỡ chiếm diện tích:
   áp dụng chung cho cả light/dark mode, không phụ thuộc theme) */
table.apikey-table {
    font-size: 12.5px !important;
}
table.apikey-table > thead > tr > th {
    font-size: 12.5px !important;
    padding: 0.5rem 0.6rem !important;
}
table.apikey-table > tbody > tr > td {
    font-size: 12.5px !important;
    padding: 0.45rem 0.6rem !important;
    vertical-align: middle !important;
}
table.apikey-table .badge {
    font-size: 11px !important;
}
table.apikey-table code {
    font-size: 11.5px !important;
}
table.apikey-table .btn {
    font-size: 11.5px !important;
    padding: 0.2rem 0.5rem !important;
}

/* ── 15_admin.css ────────────────────────────────────── */
/* ============================================================
   15_admin.css — Admin Tabs · Sidebar Login Section · User List
   Auto-refactored from custom.css
   ============================================================ */

/* === ADMIN TABS - SCROLL ONLY NAV HEADER, NOT CONTENT === */
/* Container scrolls horizontally, tab-content uses position:sticky to stay in place */
#admin-tabs-scroll-container {
    overflow-x: auto !important;
    overflow-y: hidden !important;
    scrollbar-width: none !important;
    -ms-overflow-style: none !important;
}
#admin-tabs-scroll-container::-webkit-scrollbar {
    display: none !important;
    height: 0 !important;
}
/* #admin-main-tabs is inline-flex to size to content, not shrink */
#admin-main-tabs,
#admin-main-tabs.admin-main-tabs-horizontal,
#admin-main-tabs.nav.nav-tabs {
    display: inline-flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow: visible !important;
    white-space: nowrap !important;
    padding-bottom: 0 !important;
    margin-bottom: 0 !important;
    border-bottom: 1px solid var(--border-color, #dee2e6) !important;
}
/* Nav items (direct children) don't shrink */
#admin-main-tabs > .nav-item {
    flex: 0 0 auto !important;
    flex-shrink: 0 !important;
}
#admin-main-tabs > .nav-item > .nav-link {
    white-space: nowrap !important;
    padding: 10px 16px !important;
    font-size: 16px !important;
}
/* FORCE main tabs font size - highest specificity */
#admin-modal .modal-body #admin-tabs-wrapper #admin-tabs-scroll-container #admin-main-tabs > .nav-item > .nav-link,
#admin-modal #admin-main-tabs > .nav-item > .nav-link,
#admin-main-tabs.nav.nav-tabs > .nav-item > .nav-link,
.modal #admin-main-tabs .nav-link {
    font-size: 16px !important;
    padding: 10px 16px !important;
}
/* Tab content stays full width, no scroll - it's a sibling of #admin-main-tabs */
/* Use position:sticky so it doesn't scroll with nav when container scrolls */
#admin-tabs-scroll-container > .tab-content {
    display: block !important;
    width: 100% !important;
    overflow-x: hidden !important;
    position: sticky !important;
    left: 0 !important;
}
.admin-main-tabs-horizontal > .nav > .nav-item {
    flex: 0 0 auto !important;
}
.admin-main-tabs-horizontal > .nav > .nav-item > .nav-link {
    padding: 10px 16px !important;
    font-size: 16px !important;
    white-space: nowrap !important;
}
#admin-modal .modal-body #admin-main-tabs > .nav.nav-tabs > .nav-item,
#admin-main-tabs > .nav.nav-tabs > .nav-item {
    flex: 0 0 auto !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
}
#admin-modal .modal-body #admin-main-tabs > .nav.nav-tabs > .nav-item > .nav-link,
#admin-main-tabs > .nav.nav-tabs > .nav-item > .nav-link {
    white-space: nowrap !important;
    padding: 10px 16px !important;
    font-size: 16px !important;
}
#admin-main-tabs > .nav.nav-tabs > .nav-item,
.admin-tabs-scrollable > .nav.nav-tabs > .nav-item {
    flex: 0 0 auto !important;
    flex-shrink: 0 !important;
}
#admin-main-tabs > .nav.nav-tabs > .nav-item > .nav-link,
.admin-tabs-scrollable > .nav.nav-tabs > .nav-item > .nav-link {
    white-space: nowrap !important;
    padding: 10px 16px !important;
    font-size: 16px !important;
}
/* Admin sub-tabs - smaller font, FORCE single line */
#admin-main-tabs .tab-content .nav.nav-tabs,
.admin-tabs-scrollable .tab-content .nav.nav-tabs {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    scrollbar-width: thin;
    scrollbar-color: rgba(100,100,100,0.4) transparent;
    padding-bottom: 4px;
    max-width: 100%;
}
#admin-main-tabs .tab-content .nav.nav-tabs .nav-item,
.admin-tabs-scrollable .tab-content .nav.nav-tabs .nav-item {
    flex: 0 0 auto !important;
    flex-shrink: 0 !important;
}
#admin-main-tabs .tab-content .nav.nav-tabs .nav-link,
.admin-tabs-scrollable .tab-content .nav.nav-tabs .nav-link {
    font-size: 16px !important;
    padding: 8px 14px !important;
    white-space: nowrap !important;
}
/* Admin button containers - hide by default, show with class */
#admin-display-buttons,
#admin-mapping-buttons,
#admin-export-buttons,
#admin-users-buttons,
#admin-alerts-buttons,
#admin-settings-buttons,
#admin-factory-buttons,
#admin-report-buttons,
#admin-asm-buttons,
#admin-pm-notify-buttons,
#admin-wo-notify-buttons,
#admin-shift-notify-buttons,
#admin-seatalk-bot-buttons,
#admin-work-permit-buttons {
    display: none !important;
}
#admin-asm-buttons.show-btns {
    display: flex !important;
    gap: 0.5rem;
    flex-wrap: wrap;
}
#admin-display-buttons.show-btns {
    display: block !important;
}
#admin-mapping-buttons.show-btns {
    display: block !important;
}
#admin-export-buttons.show-btns {
    display: block !important;
}
#admin-factory-buttons.show-btns {
    display: block !important;
}
/* Fix #7: admin-users-buttons must be visible when Users tab active */
#admin-users-buttons.show-btns {
    display: flex !important;
    flex-direction: column;
    width: 100%;
    min-height: 24px;
}
#admin-alerts-buttons.show-btns,
#admin-settings-buttons.show-btns {
    display: flex !important;
    gap: 0.5rem;
    flex-wrap: wrap;
}
#admin-report-buttons.show-btns {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}
#admin-pm-notify-buttons.show-btns,
#admin-wo-notify-buttons.show-btns,
#admin-shift-notify-buttons.show-btns,
#admin-seatalk-bot-buttons.show-btns,
#admin-work-permit-buttons.show-btns {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

[data-theme="dark"] .text-muted {
    color: var(--text-muted) !important;
}

[data-theme="dark"] h5, 
[data-theme="dark"] h4 {
    color: var(--text-primary) !important;
}

/* Dark mode chart containers */
[data-theme="dark"] .chart-container {
    background: transparent !important;
    border-radius: var(--border-radius);
    padding: 4px;
    box-shadow: none;
}

/* Dark mode sub-header wrapper */
[data-theme="dark"] .sub-header-wrapper {
    background: rgba(30, 41, 59, 0.72) !important;
}
[data-theme="dark"] .sub-header-wrapper > h5 {
    color: var(--text-primary) !important;
    background: var(--bg-sticky) !important;
}

/* Dark mode tab content area */
[data-theme="dark"] .tab-content {
    background: transparent;
}
[data-theme="dark"] .tab-pane {
    background: transparent;
}

/* Dark mode button styles */
/* FIX <wp-btn-no-hover-effect>: rule gốc chỉ set background/border cho
   .btn-primary với !important nhưng KHÔNG có state :hover đi kèm. Bootstrap
   mặc định có .btn-primary:hover đổi background-color, nhưng vì rule dark-
   mode dùng !important áp dụng CẢ LÚC HOVER (không phân biệt trạng thái),
   nó luôn thắng và đè mất hiệu ứng hover của Bootstrap -> nút trông như
   "chết", bấm được nhưng hover không có phản hồi gì, cũng không có
   transition mượt. Sửa: thêm transition cho background/transform + 1 state
   :hover (sáng hơn 1 chút bằng filter brightness) và :active (tối hơn khi
   đang giữ chuột) — áp dụng cho MỌI .btn-primary dark mode trong toàn app
   (bao gồm nút "Gửi yêu cầu duyệt" của Work Permit), không cần sửa gì thêm
   ở từng trang riêng lẻ. */
[data-theme="dark"] .btn-primary {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%) !important;
    border: none !important;
    transition: filter 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease !important;
}
[data-theme="dark"] .btn-primary:hover:not(:disabled) {
    filter: brightness(1.15) !important;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(79, 70, 229, 0.35) !important;
}
[data-theme="dark"] .btn-primary:active:not(:disabled) {
    filter: brightness(0.92) !important;
    transform: translateY(0);
    box-shadow: none !important;
}
[data-theme="dark"] .btn-outline-secondary {
    color: var(--text-muted) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .btn-outline-secondary:hover {
    background: var(--primary-color) !important;
    color: white !important;
}
[data-theme="dark"] .btn-outline-info {
    color: var(--secondary-color) !important;
    border-color: var(--secondary-color) !important;
}

/* Dark mode Card & Backgrounds for Reports */
[data-theme="dark"] .card {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
    color: var(--text-primary) !important;
}
[data-theme="dark"] .bg-light {
    background-color: var(--bg-light) !important;
    color: var(--text-primary) !important;
}

/* Dark mode dropdown arrow */
[data-theme="dark"] .Select-arrow {
    border-color: var(--text-muted) transparent transparent !important;
}

/* Dark mode form controls */
[data-theme="dark"] .form-check-input {
    background-color: var(--bg-card) !important;
    border-color: var(--border-color) !important;
}
[data-theme="dark"] .form-check-input:checked {
    background-color: var(--primary-color) !important;
    border-color: var(--primary-color) !important;
}

/* Dark mode Select multi-value tags */
[data-theme="dark"] .Select--multi .Select-value {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%) !important;
    border: none !important;
    color: white !important;
}
[data-theme="dark"] .Select--multi .Select-value-label {
    color: white !important;
}

/* === Sidebar Login Section Styling === */
/* Light mode */
#sidebar-login-section {
    background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);
    border: 2px solid var(--primary-color);
}
.sidebar-username {
    color: #1e293b !important;
}
.sidebar-login-btn {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%) !important;
    color: white !important;
    border: none !important;
    box-shadow: 0 2px 8px rgba(79, 70, 229, 0.3);
}
.sidebar-login-btn:hover {
    filter: brightness(1.1);
    transform: translateY(-1px);
}
.sidebar-pwd-btn {
    background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
    color: white !important;
    border: 2px solid #059669 !important;
    box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
    min-width: 36px;
    min-height: 32px;
}
.sidebar-pwd-btn:hover {
    filter: brightness(1.15);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.5);
}

/* Dark mode */
[data-theme="dark"] #sidebar-login-section {
    background: linear-gradient(135deg, #312e81 0%, #1e1b4b 100%);
    border: 2px solid #6366f1;
}
[data-theme="dark"] .sidebar-username {
    color: #e0e7ff !important;
}
[data-theme="dark"] .sidebar-login-btn {
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%) !important;
    color: #1e1b4b !important;
    border: none !important;
    box-shadow: 0 2px 8px rgba(245, 158, 11, 0.4);
}
[data-theme="dark"] .sidebar-login-btn:hover {
    filter: brightness(1.1);
}
[data-theme="dark"] .sidebar-pwd-btn {
    background: linear-gradient(135deg, #34d399 0%, #10b981 100%) !important;
    color: #064e3b !important;
    border: 2px solid #34d399 !important;
    box-shadow: 0 2px 10px rgba(52, 211, 153, 0.5);
}
[data-theme="dark"] .sidebar-pwd-btn:hover {
    filter: brightness(1.1);
    box-shadow: 0 4px 14px rgba(52, 211, 153, 0.6);
}

/* === User List Styling - Flexbox Layout === */
.user-list-container {
    padding: 0 8px;
}
.user-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    padding: 10px 8px;
    margin-bottom: 8px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    gap: 4px;
    width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}
.user-row:hover {
    border-color: var(--primary-color);
    box-shadow: 0 2px 8px rgba(79, 70, 229, 0.1);
}
.user-header-row {
    background: transparent !important;
    border: none !important;
    padding: 8px 8px 4px 8px;
    margin-bottom: 4px;
}
.user-header-row:hover {
    box-shadow: none !important;
}
.user-header-text {
    font-size: 10px;
    font-weight: 700;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.user-col {
    flex-shrink: 1;
    flex-grow: 1;
    min-width: 0;
    overflow: hidden;
}
.user-info-col {
    flex: 0 0 12%;
    max-width: 12%;
}
.user-display-col {
    flex: 0 0 10%;
    max-width: 10%;
}
.user-pwd-col {
    flex: 0 0 10%;
    max-width: 10%;
    overflow: visible !important;
}
.user-pwd-col .user-edit-input {
    width: 100% !important;
    padding-right: 26px !important;
}
.user-email-col {
    flex: 0 0 14%;
    max-width: 14%;
}
.user-timeout-col {
    flex: 0 0 6%;
    max-width: 6%;
}
.user-role-col {
    flex: 0 0 10%;
    max-width: 10%;
}
/* Enable checkbox column */
.user-enable-col {
    flex: 0 0 5%;
    max-width: 5%;
    justify-content: center;
}
/* Status Online/Offline column */
.user-status-col {
    flex: 0 0 9%;
    max-width: 9%;
}
.user-action-col {
    flex: 0 0 16%;
    max-width: 16%;
    text-align: right;
    white-space: nowrap;
    display: flex;
    justify-content: flex-end;
    gap: 2px;
}
/* Disabled account row styling */
.user-row-disabled {
    opacity: 0.55;
    background: repeating-linear-gradient(
        135deg,
        transparent,
        transparent 8px,
        rgba(180,0,0,0.04) 8px,
        rgba(180,0,0,0.04) 10px
    ) !important;
    border-color: #f0a0a0 !important;
}
/* Online / Offline status badge */
.user-status-badge {
    display: inline-flex;
    align-items: center;
    font-size: 11px;
    font-weight: 700;
    border-radius: 4px;
    padding: 3px 7px;
    white-space: nowrap;
    letter-spacing: 0.3px;
}
/* Online: solid vivid green background, white text */
.user-status-badge-online {
    background: #16a34a;
    color: #ffffff;
    box-shadow: 0 0 8px rgba(22, 163, 74, 0.5);
}
/* Offline: dark muted background, gray text */
.user-status-badge-offline {
    background: #334155;
    color: #94a3b8;
}
.user-status-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}
.user-status-online {
    background: #4ade80;
    animation: pulse-online 1.8s infinite;
}
.user-status-offline {
    background: #64748b;
}
@keyframes pulse-online {
    0%, 100% { box-shadow: 0 0 0 0px rgba(74, 222, 128, 0.6); }
    50%       { box-shadow: 0 0 0 4px rgba(74, 222, 128, 0.0); }
}
/* Ensure inputs inside columns don't overflow */
.user-col .user-edit-input, 
.user-col .user-role-dropdown,
.user-col .user-role-dropdown .Select-control {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
}
/* Responsive adjustments for very small screens */
@media (max-width: 600px) {
    .user-header-text { font-size: 8px; }
    .user-display-name { font-size: 11px; }
    .user-row { padding: 8px 4px; gap: 2px; }
    .user-action-col { flex: 0 0 50px; max-width: 50px; }
    .user-action-col .btn { padding: 0.2rem 0.3rem; font-size: 10px; }
    .user-enable-col { flex: 0 0 28px; max-width: 28px; }
    .user-status-badge { font-size: 9px; padding: 1px 4px; }
}
/* User display name - high contrast */
.user-display-name {
    color: #0f172a !important;
    font-weight: 700 !important;
    font-size: 12px !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.user-username-text {
    color: #2563eb !important;
    font-size: 10px !important;
    font-weight: 600 !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: inline-block;
    max-width: 100%;
}
/* Form inputs */
.user-edit-input {
    background: #ffffff !important;
    color: #1e293b !important;
    border: 1px solid #cbd5e1 !important;
    font-size: 11px !important;
    padding: 0.2rem 0.3rem !important;
    height: 30px !important;
}
.user-edit-input:focus {
    border-color: var(--primary-color) !important;
    box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2) !important;
}
.user-edit-input::placeholder {
    color: #94a3b8 !important;
}
.pwd-toggle-btn {
    border-color: #cbd5e1 !important;
    padding: 0.25rem 0.5rem !important;
}
.user-role-dropdown .Select-control {
    min-height: 30px !important;
}
    
    /* Image in DataTable styling */
    .dash-table-container .cell-markdown img {
        max-width: 80px;
        max-height: 60px;
        border-radius: 4px;
        cursor: pointer;
        transition: transform 0.2s ease;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .dash-table-container .cell-markdown img:hover {
        transform: scale(2.5);
        z-index: 1000;
        box-shadow: 0 10px 25px rgba(0,0,0,0.2);
        position: relative;
    }
    
/* Dark mode */
[data-theme="dark"] .user-row {
    background: #0f172a;
    border-color: #334155;
}
[data-theme="dark"] .user-row-disabled {
    background: repeating-linear-gradient(
        135deg,
        #0f172a,
        #0f172a 8px,
        rgba(239,68,68,0.06) 8px,
        rgba(239,68,68,0.06) 10px
    ) !important;
    border-color: #7f1d1d !important;
}
[data-theme="dark"] .user-status-badge-online {
    background: #15803d;
    color: #ffffff;
    box-shadow: 0 0 8px rgba(74, 222, 128, 0.4);
}
[data-theme="dark"] .user-status-badge-offline {
    background: #1e293b;
    color: #64748b;
}
[data-theme="dark"] .user-row:hover {
    border-color: #6366f1;
}
[data-theme="dark"] .user-header-text {
    color: #94a3b8 !important;
}
[data-theme="dark"] .user-display-name {
    color: #ffffff !important;
    font-weight: 700 !important;
}
[data-theme="dark"] .user-username-text {
    color: #60a5fa !important;
}
[data-theme="dark"] .user-edit-input {
    background: #1e293b !important;
    color: #f1f5f9 !important;
    border: 1px solid #475569 !important;
}
[data-theme="dark"] .user-edit-input::placeholder {
    color: #64748b !important;
}
[data-theme="dark"] .pwd-toggle-btn {
    border-color: #475569 !important;
    color: #94a3b8 !important;
}

/* Confirm Modal Styling */
.confirm-modal .modal-content {
    border: 2px solid #06b6d4 !important;
    border-radius: 12px !important;
    box-shadow: 0 10px 40px rgba(6, 182, 212, 0.3) !important;
}
.confirm-modal .modal-header {
    border-bottom: 1px solid #e2e8f0 !important;
    background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%) !important;
    border-radius: 10px 10px 0 0 !important;
}
.confirm-modal .modal-body {
    padding: 1.25rem !important;
    font-size: 16px !important;
}
.confirm-modal .modal-footer {
    border-top: 1px solid #e2e8f0 !important;
    background: #f8fafc !important;
    border-radius: 0 0 10px 10px !important;
}
[data-theme="dark"] .confirm-modal .modal-content {
    border: 2px solid #06b6d4 !important;
    background: #1e293b !important;
    box-shadow: 0 10px 40px rgba(6, 182, 212, 0.35) !important;
}
[data-theme="dark"] .confirm-modal .modal-header {
    border-bottom: 1px solid #334155 !important;
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
}
[data-theme="dark"] .confirm-modal .modal-header .modal-title {
    color: #f1f5f9 !important;
}
[data-theme="dark"] .confirm-modal .modal-header .btn-close {
    filter: invert(1) brightness(2) !important;
}
[data-theme="dark"] .confirm-modal .modal-body {
    background: #1e293b !important;
    color: #e2e8f0 !important;
}
[data-theme="dark"] .confirm-modal .modal-footer {
    border-top: 1px solid #334155 !important;
    background: #0f172a !important;
}

/* Unsaved Changes Confirm Modal - 3D Effect */
.confirm-unsaved-modal .modal-content {
    border: 3px solid #ffc107 !important;
    border-radius: 12px !important;
    box-shadow: 0 8px 32px rgba(255, 193, 7, 0.4), 
                0 0 0 4px rgba(255, 193, 7, 0.15),
                0 20px 60px rgba(0, 0, 0, 0.3) !important;
    animation: popIn 0.2s ease-out !important;
}
.confirm-unsaved-modal .modal-header {
    border-bottom: 1px solid rgba(255, 193, 7, 0.3) !important;
    background: linear-gradient(135deg, #fff8e1 0%, #fff3cd 100%) !important;
    border-radius: 9px 9px 0 0 !important;
}
.confirm-unsaved-modal .modal-footer {
    border-top: 1px solid rgba(255, 193, 7, 0.3) !important;
    background: #fffbf0 !important;
    border-radius: 0 0 9px 9px !important;
}
[data-theme="dark"] .confirm-unsaved-modal .modal-content {
    border: 3px solid #ffc107 !important;
    background: #1a1a2e !important;
    box-shadow: 0 8px 32px rgba(255, 193, 7, 0.5), 
                0 0 0 4px rgba(255, 193, 7, 0.2),
                0 20px 60px rgba(0, 0, 0, 0.5) !important;
}
[data-theme="dark"] .confirm-unsaved-modal .modal-header {
    border-bottom: 1px solid rgba(255, 193, 7, 0.3) !important;
    background: linear-gradient(135deg, #2d2d44 0%, #1a1a2e 100%) !important;
}
[data-theme="dark"] .confirm-unsaved-modal .modal-body {
    background: #1a1a2e !important;
    color: #e2e8f0 !important;
}
[data-theme="dark"] .confirm-unsaved-modal .modal-footer {
    border-top: 1px solid rgba(255, 193, 7, 0.3) !important;
    background: #12121f !important;
}
@keyframes popIn {
    0% { transform: scale(0.9); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}

/* Dark mode main content padding */
[data-theme="dark"] .main-content {
    background: transparent;
}

/* Dark mode hr */
[data-theme="dark"] hr {
    background: linear-gradient(90deg, transparent, var(--border-color), transparent) !important;
}

/* ============================================================
   Admin DB Tables — compact rows, sticky header, dark mode
   ============================================================ */

/* Scrollable wrapper — overflow-y only so sticky thead works */
.admin-db-table-scroll {
    max-height: 300px;
    overflow-y: auto !important;
    overflow-x: visible !important;
    border-radius: 8px;
    border: 1px solid var(--border-color, #dee2e6);
}

/* The table itself — border-collapse:separate is REQUIRED for sticky thead */
.admin-db-table {
    margin-bottom: 0 !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
    overflow: visible !important;
    width: 100%;
}

/* Sticky header — works because scroll root has overflow-y:auto */
.admin-db-table-scroll .admin-db-thead .admin-db-th {
    position: sticky !important;
    top: 0 !important;
    z-index: 10 !important;
    background: linear-gradient(135deg, var(--primary-color, #4f46e5) 0%, var(--primary-dark, #3730a3) 100%) !important;
    color: #fff !important;
    font-weight: 600 !important;
    font-size: 12px !important;
    padding: 7px 10px !important;
    border: none !important;
    border-bottom: 1px solid rgba(255,255,255,0.2) !important;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgba(0,0,0,0.15);
}

/* Compact data rows */
.admin-db-td {
    padding: 5px 10px !important;
    font-size: 12px !important;
    vertical-align: middle !important;
    border-color: var(--border-color, #dee2e6) !important;
}

/* Compact action buttons */
.admin-db-action-btn {
    padding: 2px 7px !important;
    font-size: 11px !important;
    line-height: 1.4 !important;
}

/* Count badge compact */
.admin-db-count-badge {
    font-size: 10px !important;
    padding: 3px 6px !important;
}

/* Row styling */
.admin-db-row {
    transition: background 0.15s;
}

/* ── DARK MODE ── */
[data-theme="dark"] .admin-db-table-scroll {
    border-color: #334155 !important;
}

[data-theme="dark"] .admin-db-table {
    background: transparent !important;
    color: #e2e8f0 !important;
}

/* Sticky header dark — must override Bootstrap */
[data-theme="dark"] .admin-db-table-scroll .admin-db-thead .admin-db-th {
    background: linear-gradient(135deg, #4f46e5 0%, #3730a3 100%) !important;
    color: #fff !important;
    border-bottom: 1px solid #6366f1 !important;
}

/* Body cells dark */
[data-theme="dark"] .admin-db-td {
    background: #1e293b !important;
    color: #e2e8f0 !important;
    border-color: #334155 !important;
}

[data-theme="dark"] .admin-db-td .text-muted {
    color: #94a3b8 !important;
}

[data-theme="dark"] .admin-db-td code {
    color: #7dd3fc !important;
    background: rgba(125,211,252,0.08) !important;
    padding: 1px 4px;
    border-radius: 3px;
}

/* Row hover dark */
[data-theme="dark"] .admin-db-row:hover .admin-db-td {
    background: rgba(129,140,248,0.18) !important;
    color: #f1f5f9 !important;
}

/* Action buttons dark */
[data-theme="dark"] .admin-db-action-btn.btn-outline-secondary {
    color: #94a3b8 !important;
    border-color: #475569 !important;
}
[data-theme="dark"] .admin-db-action-btn.btn-outline-secondary:hover {
    background: #475569 !important;
    color: #f1f5f9 !important;
}
[data-theme="dark"] .admin-db-action-btn.btn-outline-info {
    color: #38bdf8 !important;
    border-color: #38bdf8 !important;
}
[data-theme="dark"] .admin-db-action-btn.btn-outline-info:hover {
    background: rgba(56,189,248,0.15) !important;
}
[data-theme="dark"] .admin-db-action-btn.btn-outline-danger {
    color: #f87171 !important;
    border-color: #f87171 !important;
}
[data-theme="dark"] .admin-db-action-btn.btn-outline-danger:hover {
    background: rgba(248,113,113,0.15) !important;
}

/* Alternate row tint dark */
[data-theme="dark"] .admin-db-row:nth-child(even) .admin-db-td {
    background: #1a2535 !important;
}

/* ── Fix double scrollbar in user-list role dropdown ───────────────────────
   .Select-menu-outer provides the outer scroll; disable inner .Select-menu scroll */
.user-role-dropdown .Select-menu-outer {
    overflow: hidden !important;
}
.user-role-dropdown .Select-menu {
    overflow-y: auto !important;
    max-height: 200px !important;
}
.user-role-dropdown .Select-menu::-webkit-scrollbar { width: 5px; }
.user-role-dropdown .Select-menu::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #555);
    border-radius: 4px;
}

/* ── Fix double scrollbar in "Add New User" Role dropdown (same issue as above) ── */
.new-user-role-dropdown .Select-menu-outer {
    overflow: hidden !important;
}
.new-user-role-dropdown .Select-menu {
    overflow-y: auto !important;
    max-height: 200px !important;
}
.new-user-role-dropdown .Select-menu::-webkit-scrollbar { width: 5px; }
.new-user-role-dropdown .Select-menu::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #555);
    border-radius: 4px;
}

/* ── (FIX) Backup/Restore action buttons: outline buttons trong quá "basic"
   khi chưa hover (không có màu nền) — thêm nền màu nhạt sẵn theo màu của
   button (success/secondary/danger) để dễ nhận biết, đậm hơn khi hover. ── */
.backup-action-btn.btn-outline-success {
    background: rgba(34, 197, 94, 0.14) !important;
    border-color: rgba(34, 197, 94, 0.55) !important;
}
.backup-action-btn.btn-outline-success:hover {
    background: rgba(34, 197, 94, 0.30) !important;
    border-color: #22c55e !important;
}
.backup-action-btn.btn-outline-secondary {
    background: rgba(148, 163, 184, 0.16) !important;
    border-color: rgba(148, 163, 184, 0.55) !important;
}
.backup-action-btn.btn-outline-secondary:hover {
    background: rgba(148, 163, 184, 0.32) !important;
    border-color: #94a3b8 !important;
}
.backup-action-btn.btn-outline-danger {
    background: rgba(239, 68, 68, 0.14) !important;
    border-color: rgba(239, 68, 68, 0.55) !important;
}
.backup-action-btn.btn-outline-danger:hover {
    background: rgba(239, 68, 68, 0.30) !important;
    border-color: #ef4444 !important;
}

/* ── (FEATURE 2026-08 <filter Reopen theo tháng/năm>) Hàng filter Tháng/Năm
   + dropdown chọn session trong Administration > Reopen a locked session.
   Dùng cùng component dcc.Dropdown (class plan-dropdown) như các dropdown
   khác trong app để menu xổ xuống theo đúng theme dark/light hiện có,
   thay vì <select> gốc của trình duyệt (không style được, không đồng bộ
   dark mode). ── */
.reopen-filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: flex-start;
}
.reopen-filter-field {
    min-width: 0;
}
.reopen-session-dropdown .Select-menu-outer {
    max-height: 260px !important;
}
.reopen-session-dropdown .Select-menu {
    max-height: 258px !important;
}
/* Scroll Y ben trong dropdown: dung chung bien --scrollbar-track/
   --scrollbar-thumb/--scrollbar-thumb-hover nhu cac khung scroll khac
   trong app (modal-body, sidebar, tab-content-wrapper...) - dam bao
   dong bo ca 2 theme sang/toi, thay vi scrollbar mac dinh cua trinh
   duyet (khong dong bo dark mode). */
.reopen-session-dropdown .Select-menu-outer::-webkit-scrollbar {
    width: 8px;
}
.reopen-session-dropdown .Select-menu-outer::-webkit-scrollbar-track {
    background: var(--scrollbar-track);
}
.reopen-session-dropdown .Select-menu-outer::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 4px;
}
.reopen-session-dropdown .Select-menu-outer::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}
.reopen-session-dropdown .Select-menu-outer {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}
@media (max-width: 576px) {
    .reopen-filter-row {
        flex-direction: column;
    }
    .reopen-filter-row .reopen-filter-field {
        flex: 1 1 100% !important;
        min-width: 100% !important;
    }
}

/* ── 16_misc.css ─────────────────────────────────────── */
/* ============================================================
   16_misc.css — Final Overrides · Navbar Reset
   Auto-refactored from custom.css
   ============================================================ */

/* === FINAL OVERRIDE - Navbar container padding reset === */
/* This rule must be at the end to have highest priority */
#navbar-container-fluid,
#navbar-container-fluid.container-fluid,
html #navbar-container-fluid,
body #navbar-container-fluid,
[data-theme] #navbar-container-fluid,
[data-theme="dark"] #navbar-container-fluid,
[data-theme="light"] #navbar-container-fluid,
html[data-theme="dark"] #navbar-container-fluid,
html[data-theme="light"] #navbar-container-fluid {
    --bs-gutter-x: 0 !important;
    --bs-gutter-y: 0 !important;
    padding: 0 0 0 0 !important;
    padding-top: 0 !important;
    padding-right: 0 !important;
    padding-bottom: 0 !important;
    padding-left: 0 !important;
    margin: 0 0 0 0 !important;
}

/* ── Disable tab interactions khi modal login đang mở ────────────────── */
/* Khi login-modal mở (body.modal-open), main-tabs-container vẫn bị disable */
body.modal-open #main-tabs-container {
    pointer-events: none !important;
    opacity: 0.5 !important;
}
/* Trừ login-lock-screen ra */
body.modal-open #login-lock-screen {
    pointer-events: auto !important;
    opacity: 1 !important;
}

/* ── Work Order SLA banner pulse animation ─────────────────────────────── */
@keyframes wo-sla-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.55); }
    50%  { box-shadow: 0 0 0 8px rgba(220, 53, 69, 0); }
    100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); }
}

/* ── Work Order sticky toolbar ─────────────────────────────────────────── */
/* top được set ĐỘNG bởi updateStickyPositions() trong utils_js.py
   (cùng cơ chế với .sub-header-wrapper của tab Bảo trì) → tự điều chỉnh
   theo chiều cao thực của .sticky-header kể cả khi wrap 2 dòng.
   Fallback top:60px phòng khi JS chưa chạy.
   Background/màu áp dụng giống hệt .sub-header-wrapper .nav-tabs (tab Bảo trì)
   — xem 06_tabs.css — để đồng bộ giao diện toàn hệ thống. */
.wo-sticky-toolbar {
    position: -webkit-sticky;
    position: sticky;
    top: 60px; /* fallback — JS override bằng giá trị đo thực */
    z-index: 950;
    /* Không bleed ra ngoài main-content nữa — width bằng đúng vùng nội dung
       (giống hàng main-tab phía trên). Padding trong tạo khoảng cách rõ
       ràng giữa filter/dropdown và viền box. */
    margin-left: 0;
    margin-right: 0;
    padding: 14px 18px;
    border-radius: 10px;

    /* ── Background/màu đồng bộ với .sub-header-wrapper .nav-tabs ── */
    background: var(--bg-main) !important;
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.15);
    border-bottom: 1px solid rgba(99, 102, 241, 0.35);
}
[data-theme="light"] .wo-sticky-toolbar {
    background: rgba(248, 250, 252, 0.95) !important;
    box-shadow: 0 1px 0 rgba(79, 70, 229, 0.1) !important;
}
@media (max-width: 767px) {
    .wo-sticky-toolbar {
        padding: 10px 12px;
    }
}
/* Đồng bộ với perf-mode (00_perf.css / 06_tabs.css): tắt blur trên máy yếu */
@media (prefers-reduced-motion: reduce) {
    .wo-sticky-toolbar {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(25, 35, 55, 0.97) !important;
    }
}
html.low-perf .wo-sticky-toolbar,
html.low-perf-manual .wo-sticky-toolbar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(25, 35, 55, 0.97) !important;
}

/* ── Assets: thanh công cụ dính (sticky) gộp filter/nút/phân trang ─────── */
/* top được set ĐỘNG bởi updateStickyPositions() trong utils_js.py, cùng cơ
   chế và cùng bảng màu với .wo-sticky-toolbar (tab Work Order) để đồng bộ
   giao diện toàn hệ thống. Fallback top:60px phòng khi JS chưa chạy. */
.asset-sticky-toolbar {
    position: -webkit-sticky;
    position: sticky;
    top: 60px; /* fallback — JS override bằng giá trị đo thực */
    z-index: 950;
    margin-left: 0;
    margin-right: 0;
    margin-bottom: 14px;
    padding: 14px 18px;
    border-radius: 10px;

    background: var(--bg-main) !important;
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.15);
    border-bottom: 1px solid rgba(99, 102, 241, 0.35);
}
[data-theme="light"] .asset-sticky-toolbar {
    background: rgba(248, 250, 252, 0.95) !important;
    box-shadow: 0 1px 0 rgba(79, 70, 229, 0.1) !important;
}
@media (max-width: 767px) {
    .asset-sticky-toolbar {
        padding: 10px 12px;
    }
}
@media (prefers-reduced-motion: reduce) {
    .asset-sticky-toolbar {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(25, 35, 55, 0.97) !important;
    }
}
html.low-perf .asset-sticky-toolbar,
html.low-perf-manual .asset-sticky-toolbar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(25, 35, 55, 0.97) !important;
}

/* <2> Ẩn thanh phân trang MẶC ĐỊNH của DataTable — đã có thanh phân trang
   tự viết (asset-page-*-btn) gộp chung 1 dòng trong .asset-sticky-toolbar. */
#asset-table .previous-next-container {
    display: none !important;
}

/* ── Work Order table header row (sticky) ──────────────────────────────── */
/* top được set động bởi updateStickyPositions() = top của toolbar + chiều
   cao thực của toolbar (+ chiều cao banner SLA nếu đang hiện), để header
   bảng luôn dính ngay dưới toolbar/banner dù chiều cao thay đổi thế nào.
   Fallback ~120px. Màu nền tím nhạt đồng bộ accent color hệ thống. */
.wo-row-header {
    position: -webkit-sticky;
    position: sticky;
    top: 120px; /* fallback — JS override */
    z-index: 940;
    /* Màu ĐẶC (không dùng rgba/alpha) — tránh nội dung các row bên dưới
       hiện xuyên qua khi cuộn (bug đã fix). Giá trị = blend thủ công của
       --bg-main với accent tím ở cùng tỉ lệ alpha trước đây. */
    background: #293358 !important;
}
[data-theme="light"] .wo-row-header {
    background: #e9eafa !important;
}

/* ── SLA banner sticky (dính ngay dưới toolbar, tự ẩn/hiện không để lại
   khoảng trống vì div rỗng khi không có cảnh báo = cao 0px) ───────────── */
#wo-sla-banner {
    position: -webkit-sticky;
    position: sticky;
    top: 120px; /* fallback — JS override */
    z-index: 945;
    /* Ngăn margin-bottom của Alert bên trong "thoát" ra khỏi wrapper
       (margin collapsing) để JS đo đúng chiều cao thực khi tính vị trí
       cho .wo-row-header phía dưới. */
    overflow: hidden;
}

/* ══════════════════════════════════════════════════════════════════════
   ASSET MANAGEMENT — Custom html.Table (thay thế Dash DataTable)
   Áp dụng cùng UI pattern với tab "Chi tiết Bảo trì" (maint-planning-table)
   ══════════════════════════════════════════════════════════════════════ */

/* Scroll container — sticky thead hoạt động vì scroll root là div này
   FIX: overflow:overlay → scrollbar Y nổi trên content, không chiếm layout width
        → tổng width cột không bị ép nhỏ bởi thanh scroll Y
        Chrome/Edge hỗ trợ overlay; Firefox fallback về auto với scrollbar-width:thin
   FIX: overflow-x:auto → scroll X luôn hiện khi table > container width */
.asset-table-scroll {
    overflow-x: auto !important;
    overflow-y: overlay !important;   /* scrollbar Y nổi, không chiếm width */
    scrollbar-width: thin;            /* Firefox fallback: scrollbar nhỏ, không chiếm layout */
    -webkit-overflow-scrolling: touch !important;
    max-height: calc(var(--app-height, 100vh) - var(--navbar-height, 98px) - var(--sticky-header-height, 60px) - 160px);
    border: 1px solid var(--border-color);
    border-radius: 8px;
}

/* Webkit scrollbar cho asset-table-scroll: mỏng + trong suốt track */
.asset-table-scroll::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
.asset-table-scroll::-webkit-scrollbar-track {
    background: transparent;
}
.asset-table-scroll::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #cbd5e1);
    border-radius: 3px;
}
.asset-table-scroll::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover, #94a3b8);
}
.asset-table-scroll::-webkit-scrollbar-corner {
    background: transparent;
}

/* Table chính */
.asset-custom-table {
    font-size: 0.875rem;
    border-collapse: collapse !important;
    border-spacing: 0 !important;
    overflow: visible !important;
    width: 100%;
    min-width: 700px;      /* table không bị bóp nhỏ hơn mức này — scroll wrapper xử lý phần còn lại */
    margin-bottom: 0 !important;
    table-layout: auto;    /* browser tự tính column width theo nội dung, không cần width cứng */
}

/* Đường phân chia cột — giúp nhìn rõ vị trí để kéo resize */
.asset-custom-table th,
.asset-custom-table td {
    border-right: 1px solid var(--border-color, #dee2e6);
}
.asset-custom-table th:last-child,
.asset-custom-table td:last-child {
    border-right: none;
}
[data-theme="dark"] .asset-custom-table th,
[data-theme="dark"] .asset-custom-table td,
body.dark-mode .asset-custom-table th,
body.dark-mode .asset-custom-table td {
    border-right-color: rgba(255,255,255,0.12);
}

/* Sticky thead */
.asset-custom-table .asset-thead-row th {
    position: sticky !important;
    top: 0 !important;
    z-index: 10 !important;
    white-space: nowrap;   /* giữ nowrap nhưng scroll container xử lý overflow */
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--bs-light, #f8f9fa);
    font-weight: 600;
    padding: 8px 10px;
    border-bottom: 2px solid var(--border-color, #dee2e6);
    border-right: 1px solid var(--border-color, #dee2e6);
    color: var(--text-primary);
    user-select: none;
}
.asset-custom-table .asset-thead-row th:last-child {
    border-right: none;
}
.asset-custom-table .asset-thead-row th:hover {
    background: rgba(99, 102, 241, 0.10);
}

/* Body rows — set bg trực tiếp trên td (tránh trắng cứng ở dark mode) */
.asset-custom-table tbody .asset-row {
    transition: background 0.13s;
    cursor: default;
}
.asset-custom-table td {
    padding: 7px 10px;
    vertical-align: middle;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-color, #dee2e6);
    overflow: hidden;   /* FIX <badge-overflow-on-column-resize>: xem giải
        thích chi tiết ở cùng fix trong .wo-custom-table td phía trên. */
}

/* Zebra striping */
.asset-custom-table tbody .asset-row:nth-child(odd) td {
    background: var(--card-bg, #ffffff);
}
.asset-custom-table tbody .asset-row:nth-child(even) td {
    background: var(--bg-secondary, #f8f9fa);
}
.asset-custom-table tbody .asset-row:hover td {
    background: rgba(13, 110, 253, 0.08) !important;
}

/* Orphaned row highlight */
.asset-custom-table .asset-row-orphaned td {
    background: #fff8e1 !important;
    color: #7c5c00 !important;
}
[data-theme="dark"] .asset-custom-table .asset-row-orphaned td,
body.dark-mode .asset-custom-table .asset-row-orphaned td {
    background: rgba(245,158,11,0.14) !important;
    color: #fcd34d !important;
}

/* Archived row */
.asset-custom-table .asset-row-archived td {
    background: rgba(100,116,139,0.09) !important;
    color: var(--text-muted, #6c757d) !important;
}
[data-theme="dark"] .asset-custom-table .asset-row-archived td,
body.dark-mode .asset-custom-table .asset-row-archived td {
    background: rgba(148,163,184,0.10) !important;
    color: #94a3b8 !important;
}

/* Detail button */
.asset-detail-btn {
    opacity: 0.7;
    font-size: 1rem;
    transition: opacity 0.15s, transform 0.1s;
}
.asset-detail-btn:hover {
    opacity: 1;
    transform: scale(1.15);
}

/* Dark mode overrides */
body.dark-mode .asset-custom-table .asset-thead-row th,
[data-theme="dark"] .asset-custom-table .asset-thead-row th {
    background: #2a2a2a;
    color: #e0e0e0;
    border-color: #444;
}
body.dark-mode .asset-custom-table tbody .asset-row:nth-child(odd) td,
[data-theme="dark"] .asset-custom-table tbody .asset-row:nth-child(odd) td {
    background: var(--card-bg, #1e293b);
    color: var(--text-primary, #e2e8f0);
    border-bottom-color: rgba(255,255,255,0.12);
}
body.dark-mode .asset-custom-table tbody .asset-row:nth-child(even) td,
[data-theme="dark"] .asset-custom-table tbody .asset-row:nth-child(even) td {
    background: var(--bg-secondary, #162032);
    color: var(--text-primary, #e2e8f0);
    border-bottom-color: rgba(255,255,255,0.12);
}
body.dark-mode .asset-custom-table tbody .asset-row:hover td,
[data-theme="dark"] .asset-custom-table tbody .asset-row:hover td {
    background: rgba(99,102,241,0.20) !important;
}
body.dark-mode .asset-table-scroll,
[data-theme="dark"] .asset-table-scroll {
    border-color: #444;
}
body.dark-mode .asset-table-scroll::-webkit-scrollbar-thumb,
[data-theme="dark"] .asset-table-scroll::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #475569);
}
body.dark-mode .asset-table-scroll::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] .asset-table-scroll::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover, #94a3b8);
}

/* ── Sort icon (click header để sort). Resize dùng chung .col-resize-handle
   (assets/css/26_incidents_table.css) — được inject tự động bởi
   assets/js/inc_table_colresize.js, giống hệt bảng "Chi tiết Bảo trì". ── */
.asset-custom-table .asset-thead-row th.asset-th-sortable {
    cursor: pointer;
    position: relative;
    padding-right: 18px !important;
}
.asset-custom-table .asset-sort-icon {
    font-size: 0.72rem;
    opacity: 0.35;
    margin-left: 4px;
    vertical-align: middle;
}
.asset-custom-table .asset-sort-icon.asset-sort-active {
    opacity: 1;
    color: var(--primary-color, #6366f1);
}

/* ══════════════════════════════════════════════════════════════════════
   WORK ORDER — Custom html.Table (giống pattern Asset Management)
   Thay thế card-grid → bảng có sort, resize, sticky thead, zebra rows
   ══════════════════════════════════════════════════════════════════════ */

/* Scroll container — cho phép sticky thead hoạt động
   FIX: overflow:overlay → scrollbar Y nổi, không chiếm layout width
        → tổng width cột không bị ép nhỏ bởi thanh scroll Y
   FIX: overflow-x:auto → scroll X luôn hiện khi table > container width */
.wo-table-scroll {
    overflow-x: auto !important;
    overflow-y: overlay !important;   /* scrollbar Y nổi, không chiếm width */
    scrollbar-width: thin;            /* Firefox fallback */
    -webkit-overflow-scrolling: touch !important;
    max-height: calc(var(--app-height, 100vh) - var(--navbar-height, 98px) - var(--sticky-header-height, 60px) - 160px);
    border: 1px solid var(--border-color);
    border-radius: 8px;
}

/* Webkit scrollbar cho wo-table-scroll */
.wo-table-scroll::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
.wo-table-scroll::-webkit-scrollbar-track {
    background: transparent;
}
.wo-table-scroll::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #cbd5e1);
    border-radius: 3px;
}
.wo-table-scroll::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover, #94a3b8);
}
.wo-table-scroll::-webkit-scrollbar-corner {
    background: transparent;
}

/* Table chính */
.wo-custom-table {
    font-size: 0.875rem;
    border-collapse: collapse !important;  /* collapse: không cộng thêm border width */
    border-spacing: 0 !important;
    overflow: visible !important;
    width: 100%;
    min-width: 750px;      /* table không bị bóp nhỏ hơn mức này — scroll wrapper xử lý phần còn lại */
    margin-bottom: 0 !important;
    table-layout: auto;    /* browser tự tính column width theo nội dung */
}

/* Đường phân cột */
.wo-custom-table th,
.wo-custom-table td {
    border-right: 1px solid var(--border-color, #dee2e6);
}
.wo-custom-table th:last-child,
.wo-custom-table td:last-child {
    border-right: none;
}
[data-theme="dark"] .wo-custom-table th,
[data-theme="dark"] .wo-custom-table td,
body.dark-mode .wo-custom-table th,
body.dark-mode .wo-custom-table td {
    border-right-color: rgba(255,255,255,0.12);
}

/* Sticky thead */
.wo-custom-table .wo-thead-row th {
    position: sticky !important;
    top: 0 !important;
    z-index: 10 !important;
    white-space: nowrap;   /* giữ nowrap nhưng scroll container xử lý overflow */
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--bs-light, #f8f9fa);
    font-weight: 600;
    padding: 8px 10px;
    border-bottom: 2px solid var(--border-color, #dee2e6);
    border-right: 1px solid var(--border-color, #dee2e6);
    color: var(--text-primary);
    user-select: none;
}
.wo-custom-table .wo-thead-row th:last-child {
    border-right: none;
}
.wo-custom-table .wo-thead-row th:hover {
    background: rgba(99, 102, 241, 0.10);
}

/* Body rows */
.wo-custom-table tbody .wo-row {
    transition: background 0.13s;
    cursor: default;
}
.wo-custom-table td {
    padding: 7px 10px;
    vertical-align: middle;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-color, #dee2e6);
    overflow: hidden;   /* FIX <badge-overflow-on-column-resize>: trước đây td
        không có overflow:hidden nên khi cột bị kéo nhỏ hơn nội dung (badge,
        text dài...), nội dung tràn thẳng ra ngoài đè lên cột kế bên thay vì
        bị giữ gọn trong ô. th đã có overflow:hidden từ trước, giờ td cũng
        vậy để nhất quán — nội dung con (badge) tự ellipsis, xem quy tắc
        .badge-ellipsis bên dưới. */
}
/* Fix: row đầu tiên của tbody cần border-top để ngăn cách với thead */
.wo-custom-table tbody .wo-row:first-child td {
    border-top: 1px solid var(--border-color, #dee2e6);
}

/* ── Documents tab: canh CENTER-MIDDLE toàn bộ cell (th + td) của các
   bảng OPL/WI/ASM/Manuals — dùng class riêng "doc-custom-table" (song
   song với "wo-custom-table") để KHÔNG ảnh hưởng bảng Work Order / các
   bảng khác đang tái dùng chung class "wo-custom-table". */
.doc-custom-table th,
.doc-custom-table td {
    text-align: center;
    vertical-align: middle;
}
/* name_cell (icon + tên file) là 1 <div> block bình thường -> center
   được luôn nhờ text-align:center ở td cha (icon + span đều inline). */
.doc-custom-table td > div {
    justify-content: center;
}
/* Cột "Thao tác" (Xem/Tải xuống/Xóa) dùng className="d-flex" -> Bootstrap
   .d-flex chỉ set display:flex, KHÔNG tự canh giữa (mặc định
   justify-content: flex-start) -> phải ép justify-content: center riêng. */
.doc-custom-table td.d-flex {
    justify-content: center;
    align-items: center;
}

/* FIX <badge-overflow-on-column-resize>: dùng chung cho mọi badge trạng thái
   (Work Permit, Work Order, Bảo trì, Thiết bị...). Badge tự co theo cột,
   cắt chữ bằng "..." khi hết chỗ thay vì tràn/vỡ layout. Text đầy đủ vẫn
   xem được qua thuộc tính title (tooltip khi hover) — xem các hàm
   _status_badge()/_wp_status_badge()/... trong modules/ui/*.py đã thêm
   title=<text gốc>. */
.badge-ellipsis {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* Zebra striping */
.wo-custom-table tbody .wo-row:nth-child(odd) td {
    background: var(--card-bg, #ffffff);
}
.wo-custom-table tbody .wo-row:nth-child(even) td {
    background: var(--bg-secondary, #f8f9fa);
}
.wo-custom-table tbody .wo-row:hover td {
    background: rgba(13, 110, 253, 0.08) !important;
}

/* Row highlight theo stage */
.wo-custom-table .wo-row-closed td {
    background: rgba(100,116,139,0.09) !important;
    color: var(--text-muted, #6c757d) !important;
}
[data-theme="dark"] .wo-custom-table .wo-row-closed td,
body.dark-mode .wo-custom-table .wo-row-closed td {
    background: rgba(148,163,184,0.10) !important;
    color: #94a3b8 !important;
}
.wo-custom-table .wo-row-open td {
    /* không highlight đặc biệt */
}
.wo-custom-table .wo-row-inprogress td {
    background: rgba(245,158,11,0.07) !important;
}
[data-theme="dark"] .wo-custom-table .wo-row-inprogress td,
body.dark-mode .wo-custom-table .wo-row-inprogress td {
    background: rgba(245,158,11,0.12) !important;
}

/* Dark mode overrides */
body.dark-mode .wo-custom-table .wo-thead-row th,
[data-theme="dark"] .wo-custom-table .wo-thead-row th {
    background: #2a2a2a;
    color: #e0e0e0;
    border-color: #444;
}
body.dark-mode .wo-custom-table tbody .wo-row:nth-child(odd) td,
[data-theme="dark"] .wo-custom-table tbody .wo-row:nth-child(odd) td {
    background: var(--card-bg, #1e293b);
    color: var(--text-primary, #e2e8f0);
    border-bottom-color: rgba(255,255,255,0.12);
}
body.dark-mode .wo-custom-table tbody .wo-row:nth-child(even) td,
[data-theme="dark"] .wo-custom-table tbody .wo-row:nth-child(even) td {
    background: var(--bg-secondary, #162032);
    color: var(--text-primary, #e2e8f0);
    border-bottom-color: rgba(255,255,255,0.12);
}
body.dark-mode .wo-custom-table tbody .wo-row:hover td,
[data-theme="dark"] .wo-custom-table tbody .wo-row:hover td {
    background: rgba(99,102,241,0.20) !important;
}
body.dark-mode .wo-table-scroll,
[data-theme="dark"] .wo-table-scroll {
    border-color: #444;
}
body.dark-mode .wo-table-scroll::-webkit-scrollbar-thumb,
[data-theme="dark"] .wo-table-scroll::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #475569);
}
body.dark-mode .wo-table-scroll::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] .wo-table-scroll::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover, #94a3b8);
}

/* Sort icon */
.wo-custom-table .wo-thead-row th.wo-th-sortable {
    cursor: pointer;
    position: relative;
    padding-right: 18px !important;
}
.wo-custom-table .wo-sort-icon {
    font-size: 0.72rem;
    opacity: 0.35;
    margin-left: 4px;
    vertical-align: middle;
}
.wo-custom-table .wo-sort-icon.wo-sort-active {
    opacity: 1;
    color: var(--primary-color, #6366f1);
}

/* Ghi chú cột — truncate text, không tràn ra ngoài */
.wo-td-note {
    overflow: hidden;
    max-width: 0;   /* table-layout:fixed trick: buộc truncate trong width đã set */
}
.wo-td-note .text-truncate {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* ── FIX TOOLBAR: bỏ backdrop-filter để tránh stacking context mới ──────
   backdrop-filter tạo stacking context → nhốt .Select-menu-outer bên trong,
   không thể thoát ra dù z-index cao bao nhiêu. Thay bằng màu nền đặc.
   ────────────────────────────────────────────────────────────────────── */
.wo-sticky-toolbar {
    margin-bottom: 10px;
    padding-top: 8px !important;
    padding-bottom: 8px !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: var(--bg-main, #1a2337) !important;
}
[data-theme="light"] .wo-sticky-toolbar {
    background: #f8fafc !important;
}
html.low-perf .wo-sticky-toolbar,
html.low-perf-manual .wo-sticky-toolbar {
    background: rgba(25, 35, 55, 0.97) !important;
}

/* ── FIX DROPDOWN: z-index + single-line ────────────────────────────────── */

/* 1) Menu list nằm trên mọi thứ — không còn bị nhốt trong stacking context */
.wo-sticky-toolbar .Select-menu-outer,
.wo-dropdown-singleline .Select-menu-outer {
    z-index: 9999 !important;
    position: absolute !important;
}

/* ── COLLAPSED STATE (bình thường): 1 dòng cố định 36px ── */
/* Collapsed: chỉ áp dụng khi KHÔNG ở trạng thái force-expanded và react không mở */
.wo-dropdown-singleline:not(.wo-force-expanded) .Select:not(.is-open) .Select-control {
    min-height: 36px;
    max-height: 36px;
    height: 36px;
    overflow: hidden;
    cursor: pointer;
}
.wo-dropdown-singleline:not(.wo-force-expanded) .Select:not(.is-open) .Select-multi-value-wrapper {
    flex-wrap: nowrap;
    overflow: hidden;
    height: 34px;
    max-height: 34px;
    align-items: center;
    display: flex;
}
/* Ẩn tag thứ 2 trở đi khi collapsed */
.wo-dropdown-singleline:not(.wo-force-expanded) .Select:not(.is-open) .Select-value ~ .Select-value {
    display: none !important;
}
.wo-dropdown-singleline .Select-value:first-of-type {
    max-width: calc(100% - 40px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.wo-dropdown-singleline .Select-value-label {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}
.wo-dropdown-singleline .Select-placeholder {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    line-height: 34px !important;
}

/* ── EXPANDED STATE ────────────────────────────────────────────────────────
   Ba cách trigger expand:
   (a) .Select.is-open          — còn option chưa chọn, react-select tự mở
   (b) :focus-within            — focus nhưng menu chưa mở
   (c) .wo-force-expanded       — JS toggle khi đã chọn hết option (click
                                   vào control hoặc arrow khi menu không mở)
   ────────────────────────────────────────────────────────────────────────── */

/* Expand control — chung cho cả 3 trường hợp */
.wo-dropdown-singleline .Select.is-open .Select-control,
.wo-dropdown-singleline:focus-within .Select-control,
.wo-dropdown-singleline.wo-force-expanded .Select-control {
    min-height: 36px !important;
    max-height: calc(36px * 3 + 10px) !important;
    height: auto !important;
    overflow: visible !important;
}

/* Expand wrapper — wrap + scroll */
.wo-dropdown-singleline .Select.is-open .Select-multi-value-wrapper,
.wo-dropdown-singleline:focus-within .Select-multi-value-wrapper,
.wo-dropdown-singleline.wo-force-expanded .Select-multi-value-wrapper {
    flex-wrap: wrap !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    max-height: calc(36px * 3) !important;
    height: auto !important;
    align-items: flex-start !important;
    padding: 2px 2px 2px 4px;
}

/* Hiện tất cả tag */
.wo-dropdown-singleline .Select.is-open .Select-value,
.wo-dropdown-singleline:focus-within .Select-value,
.wo-dropdown-singleline.wo-force-expanded .Select-value {
    display: inline-flex !important;
    max-width: 100%;
}

.wo-dropdown-singleline .Select.is-open .Select-value-label,
.wo-dropdown-singleline:focus-within .Select-value-label,
.wo-dropdown-singleline.wo-force-expanded .Select-value-label {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

/* Ẩn menu-outer khi wo-force-expanded nhưng không có .is-open
   (tránh menu trống hiện ra) */
.wo-dropdown-singleline.wo-force-expanded .Select:not(.is-open) .Select-menu-outer {
    display: none !important;
}

/* Arrow vẫn clickable kể cả khi collapsed */
.wo-dropdown-singleline .Select-arrow-zone {
    pointer-events: auto !important;
    cursor: pointer !important;
    z-index: 1;
    position: relative;
}

/* ── AUTO-DISMISS: thông báo Save/Test tạm thời (VD "Đã lưu cài đặt...")
   Áp dụng cho mọi Div/Span có class "auto-dismiss-msg" — tự mờ dần sau ~3.4s
   rồi biến mất hẳn sau 4s (nội dung xoá bởi JS ở auto_dismiss_alerts.js).
   Cùng cơ chế với #session-details-msg (xem 22_report_grid.css) nhưng dùng
   chung 1 class để không phải viết CSS riêng cho từng id mới. ─────────── */
.auto-dismiss-msg:not(:empty) {
    animation: autoDismissMsgFadeOut 0.6s ease-in 3.4s forwards;
}
@keyframes autoDismissMsgFadeOut {
    from { opacity: 1; }
    to   { opacity: 0; pointer-events: none; }
}

/* (FIX) Sau khi mờ hẳn, nội dung cũ vẫn được GIỮ LẠI trong DOM (xem lý do
   trong auto_dismiss_alerts.js — tránh bug React không render lại được nếu
   xoá thẳng node) nhưng trước đây phần KHÔNG GIAN (height) mà nó chiếm vẫn
   còn nguyên dù đã vô hình -> để lại khoảng trống thừa trên UI. Giờ thêm
   transition max-height/margin/padding riêng (độc lập với animation opacity
   ở trên) — JS (auto_dismiss_alerts.js) sẽ set max-height khớp đúng chiều
   cao nội dung khi có toast mới, rồi thêm class "auto-dismiss-msg--collapsed"
   đúng lúc animation mờ vừa kết thúc để tự thu gọn khoảng trống lại. */
.auto-dismiss-msg {
    transition: max-height 0.35s ease, margin-top 0.35s ease, margin-bottom 0.35s ease,
                padding-top 0.35s ease, padding-bottom 0.35s ease;
    overflow: hidden;
}
.auto-dismiss-msg.auto-dismiss-msg--collapsed {
    max-height: 0 !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-width: 0 !important;
}

/* ── FIX PAGINATION: no-wrap ──────────────────────────────────────────── */
#wo-page-total,
#asset-page-total {
    white-space: nowrap !important;
    text-align: center;
}
#wo-row-count {
    white-space: nowrap !important;
}
#wo-pagination-bar {
    flex-wrap: nowrap !important;
}

/* ── Ô nhập số trang (nhảy trang tay) — WO + Asset ───────────────────────
   Ẩn spinner mũi tên tăng/giảm mặc định của input[type=number] để gọn UI,
   người dùng gõ số rồi nhấn Enter để nhảy trang. */
.wo-page-jump-input::-webkit-outer-spin-button,
.wo-page-jump-input::-webkit-inner-spin-button,
.asset-page-jump-input::-webkit-outer-spin-button,
.asset-page-jump-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.wo-page-jump-input,
.asset-page-jump-input {
    -moz-appearance: textfield;
    appearance: textfield;
}
.wo-page-jump-input:focus,
.asset-page-jump-input:focus {
    border-color: var(--primary-color, #6366f1) !important;
    box-shadow: 0 0 0 0.15rem rgba(99, 102, 241, 0.25) !important;
}
[data-theme="dark"] .wo-page-jump-input,
[data-theme="dark"] .asset-page-jump-input,
body.dark-mode .wo-page-jump-input,
body.dark-mode .asset-page-jump-input {
    background-color: var(--bg-secondary, #162032);
    color: var(--text-primary, #e2e8f0);
    border-color: #444;
}

/* ============================================================
   Asset Detail Modal — History sub-tab tables (dark mode safe)
   ============================================================ */

/* Scroll container for each sub-tab content div */
/* Tab divs are the single scroll container for both axes.
   overflow-y:auto + maxHeight set via inline style in Python.
   overflow-x:hidden: table uses table-layout:fixed with % widths → always fits. */
#asset-detail-incidents,
#asset-detail-maint,
#asset-detail-parts {
    overflow-x: hidden;
}

/* Empty state alert */
.asset-hist-empty {
    margin-top: 0.5rem;
    font-size: 0.875rem;
}

/* Section wrapper: NO overflow — must be transparent so sticky propagates to tab div scroll container */
.asset-hist-section {
    padding-bottom: 8px;
    overflow: visible !important;
    width: 100%;
}

/* .asset-hist-scroll removed — tab div now handles both X and Y scroll */

/* Table base */
.asset-hist-table {
    width: 100%;
    table-layout: fixed;      /* forces columns to respect % widths, no X scroll needed */
    border-collapse: collapse;
    font-size: 0.8rem;
    margin-bottom: 0;
    /* Neutralize Bootstrap 5 table CSS variables */
    --bs-table-bg: transparent;
    --bs-table-striped-bg: transparent;
    --bs-table-hover-bg: transparent;
    --bs-table-color: inherit;
}

/* ── Sticky topbar: sticks to top of tab scroll container ── */
.asset-hist-topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    flex-wrap: nowrap;
    gap: 4px;
    padding: 5px 6px;
    margin-bottom: 4px !important;
    background-color: #1a1f35;
    border: 1px solid #3a4060;
    border-radius: 6px 6px 0 0;
    overflow-x: visible;
}

/* Light mode topbar — only apply when data-theme=light is explicitly set */
[data-theme="light"] .asset-hist-topbar {
    background-color: #f1f5f9;
    border-color: #cbd5e1;
}

/* ── Sticky thead: sticks below topbar ── */
/* topbar height ≈ 38px (5px pad top + 28px input + 5px pad bottom) */
.asset-hist-thead {
    position: sticky;
    top: 47px;
    z-index: 9;
}

/* Header cell */
.asset-hist-th {
    padding: 7px 10px;
    font-weight: 600;
    font-size: 0.77rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: #4338ca;
    color: #fff;
    border-bottom: 2px solid rgba(255,255,255,0.15);
    user-select: none;
}

/* Light mode header — only apply when data-theme=light */
[data-theme="light"] .asset-hist-th {
    background: #4f46e5;
    color: #fff;
    border-bottom: 2px solid rgba(255,255,255,0.2);
}

/* Body cell */
.asset-hist-td {
    padding: 6px 10px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    vertical-align: middle;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Row colors ────────────────────────────────────────────────────────────
   Use BOTH bare class selector AND [data-theme="dark"] prefixed selector
   to maximize specificity and defeat any Bootstrap or later CSS rule.
   data-theme is on <html> element. */

/* DARK MODE — unconditional default + explicit dark selector */
.asset-hist-odd .asset-hist-td,
[data-theme="dark"] .asset-hist-odd .asset-hist-td {
    background-color: #1e2130 !important;
    color: #cbd5e1 !important;
}
.asset-hist-even .asset-hist-td,
[data-theme="dark"] .asset-hist-even .asset-hist-td {
    background-color: #252a40 !important;
    color: #cbd5e1 !important;
}
.asset-hist-row:hover .asset-hist-td,
[data-theme="dark"] .asset-hist-row:hover .asset-hist-td {
    background-color: #2d3555 !important;
    color: #e2e8f0 !important;
}

/* Light mode row override — must come AFTER the dark defaults above */
[data-theme="light"] .asset-hist-odd .asset-hist-td {
    background-color: #ffffff !important;
    color: #1e293b !important;
}
[data-theme="light"] .asset-hist-even .asset-hist-td {
    background-color: #f8fafc !important;
    color: #1e293b !important;
}
[data-theme="light"] .asset-hist-row:hover .asset-hist-td {
    background-color: #ede9fe !important;
    color: #1e293b !important;
}

/* ── Search + filter inputs: dark default ── */
.asset-hist-search,
.asset-hist-filter {
    background-color: #1e293b !important;
    color: #e2e8f0 !important;
    border-color: #475569 !important;
    font-size: 0.82rem;
    padding: 2px 8px;
}
.asset-hist-search { min-width: 120px; }
.asset-hist-filter { min-width: 90px; padding: 2px 6px; }

/* Light mode inputs */
[data-theme="light"] .asset-hist-search,
[data-theme="light"] .asset-hist-filter {
    background-color: #ffffff !important;
    color: #1e293b !important;
    border-color: #cbd5e1 !important;
}

/* ── Topbar buttons: dark default ── */
.asset-hist-topbar .btn {
    min-width: 28px;
    padding: 2px 7px;
    font-size: 0.82rem;
    line-height: 1.4;
}
.asset-hist-topbar .btn-outline-secondary {
    color: #94a3b8;
    border-color: #475569;
}
.asset-hist-topbar .btn-outline-secondary:hover:not(:disabled) {
    background-color: #334155;
    color: #e2e8f0;
}

/* Default (dark) topbar pager buttons */
.asset-hist-topbar .btn-outline-secondary {
    color: #94a3b8;
    border-color: #475569;
}

.asset-hist-topbar .btn-outline-secondary:hover:not(:disabled) {
    background-color: #334155;
    color: #e2e8f0;
}

/* ── Asset detail modal — đồng bộ chiều cao nút Export (dropdown) với các nút footer khác ── */
.asset-detail-export-dropdown .dropdown-toggle {
    padding: 0.375rem 0.75rem !important;
    font-size: 1rem !important;
    line-height: 1.5 !important;
}

/* ── WO Actions column — icon-only buttons (Take/Start/Close/Quick-close/PDF) ──
   FIX: các nút outline (đặc biệt outline-secondary của nút PDF) dùng viền
   xám mặc định Bootstrap, gần như hòa vào nền tối của bảng ở trạng thái
   bình thường (chỉ rõ khi hover) — trông như không phải nút. Thêm nền mờ +
   viền rõ hơn cho TRẠNG THÁI BÌNH THƯỜNG, và độ sáng rõ rệt hơn cho hover,
   để mọi nút đều có "hình dạng nút" ngay cả khi chưa hover. */
.wo-icon-btn {
    border-width: 1.5px !important;
    transition: background-color .15s ease, border-color .15s ease, filter .15s ease;
}

/* Nút PDF (outline-secondary) — viền/nền mờ đủ để thấy rõ trên nền tối */
.wo-icon-btn.btn-outline-secondary {
    color: #cbd5e1 !important;
    border-color: rgba(203, 213, 225, 0.55) !important;
    background-color: rgba(203, 213, 225, 0.08) !important;
}
.wo-icon-btn.btn-outline-secondary:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(203, 213, 225, 0.85) !important;
    background-color: rgba(203, 213, 225, 0.22) !important;
}

/* Nút Quick-close outline (warning/danger) — thêm nền mờ cùng tông màu để
   rõ hình khối ngay ở trạng thái bình thường, không chỉ dựa vào viền */
.wo-icon-btn.btn-outline-warning {
    background-color: rgba(255, 193, 7, 0.10) !important;
}
.wo-icon-btn.btn-outline-warning:hover:not(:disabled) {
    background-color: rgba(255, 193, 7, 0.28) !important;
    filter: brightness(1.1);
}
.wo-icon-btn.btn-outline-danger {
    background-color: rgba(220, 53, 69, 0.10) !important;
}
.wo-icon-btn.btn-outline-danger:hover:not(:disabled) {
    background-color: rgba(220, 53, 69, 0.28) !important;
    filter: brightness(1.1);
}

/* Nút đặc (info/warning/success — Take/Start/Close) đã có nền màu sẵn theo
   Bootstrap, chỉ cần thêm hiệu ứng hover rõ rệt hơn cho nhất quán */
.wo-icon-btn.btn-info:hover:not(:disabled),
.wo-icon-btn.btn-warning:hover:not(:disabled),
.wo-icon-btn.btn-success:hover:not(:disabled) {
    filter: brightness(1.12);
}

/* ── 17_layout_editor.css ────────────────────────────── */
/* ============================================================
   17_layout_editor.css — Layout Editor
   Auto-refactored from custom.css
   ============================================================ */

/* ============== LAYOUT EDITOR STYLES ============== */

.layout-editor-item {
    background: #1e293b;
    border: 1px solid #334155;
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: move;
    transition: all 0.2s;
}

.layout-editor-item:hover {
    border-color: #6366f1;
    background: #334155;
}



.layout-editor-item .item-icon {
    width: 32px;
    height: 32px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 10px;
    font-size: 0.9rem;
}

.layout-editor-item .item-label {
    flex: 1;
    font-weight: 500;
    color: #e2e8f0;
}

.layout-editor-item .item-drag {
    color: #64748b;
    margin-right: 10px;
    cursor: grab;
    padding: 5px;
}

.layout-editor-item .item-drag:active {
    cursor: grabbing;
}



.layout-editor-item .visibility-btn {
    background: none;
    border: none;
    padding: 4px 8px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
}

.layout-editor-item .visibility-btn.visible {
    color: #10b981;
}

.layout-editor-item .visibility-btn.hidden {
    color: #6b7280;
}

.layout-editor-item .visibility-btn:hover {
    background: rgba(255,255,255,0.1);
}

.layout-editor-section {
    background: #0f172a;
    border-radius: 10px;
    padding: 15px;
    margin-bottom: 15px;
}

.layout-editor-section-title {
    font-size: 0.85rem;
    font-weight: 600;
    color: #94a3b8;
    margin-bottom: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

[data-theme="light"] .layout-editor-item {
    background: #f8fafc;
    border-color: #e2e8f0;
}

[data-theme="light"] .layout-editor-item:hover {
    background: #e2e8f0;
}

[data-theme="light"] .layout-editor-item .item-label {
    color: #1e293b;
}

[data-theme="light"] .layout-editor-section {
    background: #ffffff;
    border: 1px solid #e2e8f0;
}

.edit-layout-btn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 1050;
    box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4);
}

/* Row-based Layout Editor Styles */
.layout-row-editor {
    border: 1px solid #334155 !important;
    transition: all 0.2s;
}

.layout-row-editor:hover {
    border-color: #6366f1 !important;
}

.layout-chart-item {
    transition: all 0.2s;
}

.layout-chart-item:hover {
    border-color: #6366f1 !important;
}

/* Drag handle cursor */
.drag-handle {
    cursor: grab !important;
}

.drag-handle:active {
    cursor: grabbing !important;
}

/* Sortable styles for KPI drag-drop */
.sortable-kpi-container {
    min-height: 40px;
    padding: 4px;
    border-radius: 6px;
    transition: background-color 0.2s;
}

.sortable-kpi-container:empty::after {
    content: "Drop KPIs here";
    color: #64748b;
    font-style: italic;
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 40px;
}

.sortable-kpi-item {
    cursor: move;
    user-select: none;
}

.sortable-ghost {
    opacity: 0.4;
    background: #6366f1 !important;
}

.sortable-chosen {
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
    transform: scale(1.02);
}

.sortable-drag {
    opacity: 0.9;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

/* Layout Modal: Sticky tabs and header */
#layout-editor-modal .modal-content {
    display: flex;
    flex-direction: column;
    max-height: 90vh;
}

#layout-editor-modal .modal-header {
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 20;
    background-color: var(--modal-bg, #1e293b);
}

#layout-editor-modal .modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 0;
}

/* FIX 5: Layout tabs wrapper with arrows like Admin modal */
#layout-tabs-wrapper {
    display: flex !important;
    align-items: center !important;
    position: relative !important;
    max-width: 100% !important;
}

/* Position arrows static for flex layout */
#layout-tabs-scroll-left,
#layout-tabs-scroll-right {
    position: static !important;
    z-index: 100 !important;
}

/* Scroll container with padding for arrows */
#layout-tabs-scroll-container {
    padding-left: 0 !important;
    padding-right: 0 !important;
    flex: 1;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    scrollbar-width: none !important;
    -ms-overflow-style: none !important;
}

#layout-tabs-scroll-container::-webkit-scrollbar {
    display: none !important;
    height: 0 !important;
}

/* Arrow buttons for Layout modal */
.layout-tabs-arrow {
    background: var(--primary-color, #6366f1) !important;
    color: white !important;
    border: none !important;
    border-radius: 4px !important;
    width: 28px !important;
    height: 28px !important;
    min-width: 28px !important;
    max-width: 28px !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 12px !important;
    flex-shrink: 0 !important;
    flex-grow: 0 !important;
    transition: all 0.2s !important;
    opacity: 1 !important;
    visibility: visible !important;
    padding: 0 !important;
    margin: 0 2px !important;
}

.layout-tabs-arrow.hidden {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    width: 0 !important;
    min-width: 0 !important;
    max-width: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
}

.layout-tabs-arrow:hover {
    background: var(--primary-dark, #4f46e5) !important;
}

.layout-tabs-arrow:active {
    transform: scale(0.95);
}

/* Layout tabs should be inline-flex and not wrap */
#layout-editor-tabs,
#layout-editor-tabs.nav.nav-tabs {
    display: inline-flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow: visible !important;
    white-space: nowrap !important;
    padding-bottom: 0 !important;
    margin-bottom: 0 !important;
    border-bottom: 2px solid #334155 !important;
}

#layout-editor-tabs > .nav-item {
    flex: 0 0 auto !important;
    flex-shrink: 0 !important;
}

#layout-editor-tabs > .nav-item > .nav-link {
    white-space: nowrap !important;
    padding: 10px 20px !important;
}

#layout-editor-modal .nav-tabs {
    position: sticky;
    top: 0;
    z-index: 15;
    background-color: var(--modal-bg, #1e293b);
    border-bottom: 2px solid #334155;
    margin: 0 !important;
    margin-bottom: 0 !important;
    padding: 8px 16px 0 !important;
}

#layout-editor-modal .tab-content {
    padding: 16px;
    padding-top: 0 !important;
    margin-top: 0 !important;
    overflow-y: visible;
}

#layout-editor-modal .nav-tabs .nav-link {
    color: #94a3b8;
    border: none;
    padding: 10px 20px;
}

#layout-editor-modal .nav-tabs .nav-link:hover {
    color: #e2e8f0;
}

#layout-editor-modal .nav-tabs .nav-link.active {
    color: #6366f1;
    background: transparent;
    border-bottom: 2px solid #6366f1;
}

#layout-editor-modal .rc-slider-track {
    background-color: #6366f1;
}

#layout-editor-modal .rc-slider-handle {
    border-color: #6366f1;
    background-color: #6366f1;
}

#layout-editor-modal .rc-slider-rail {
    background-color: #334155;
}

[data-theme="light"] .layout-row-editor {
    background: #ffffff !important;
    border-color: #e2e8f0 !important;
}

[data-theme="light"] .layout-chart-item {
    background: #f8fafc !important;
}

[data-theme="light"] #layout-editor-modal .nav-tabs {
    border-bottom-color: #e2e8f0;
}

[data-theme="light"] #layout-editor-modal .nav-tabs .nav-link {
    color: #64748b;
}

[data-theme="light"] #layout-editor-modal .nav-tabs .nav-link:hover {
    color: #1e293b;
}

[data-theme="light"] #layout-editor-modal .rc-slider-rail {
    background-color: #e2e8f0;
}

.edit-layout-floating {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 1050;
    display: flex;
    gap: 10px;
}

/* Image in DataTable styling */
.dash-table-container .cell-markdown img {
    max-width: 80px;
    max-height: 60px;
    border-radius: 4px;
    cursor: zoom-in;
    transition: all 0.2s ease;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    display: block;
    margin: 0 auto;
}
.dash-table-container .cell-markdown img:hover {
    transform: scale(1.05);
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
    opacity: 0.95;
}

/* ── 18_modals.css ───────────────────────────────────── */
/* ============================================================
   18_modals.css — User Logs Modal · Button & Modal Styles
   Auto-refactored from custom.css
   ============================================================ */

/* ============================================================================
   USER LOGS BUTTON & MODAL STYLES
   ============================================================================ */

/* User Logs Button Container (Matching Notification Bell) */
.user-logs-container {
    position: relative;
    cursor: pointer;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: linear-gradient(145deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%);
    box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4), 
                0 2px 4px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border: 1px solid rgba(255, 255, 255, 0.2);
}
.user-logs-container:hover {
    transform: scale(1.1) translateY(-2px);
    box-shadow: 0 8px 25px rgba(99, 102, 241, 0.5),
                0 4px 8px rgba(0, 0, 0, 0.15),
                inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.user-logs-container:active {
    transform: scale(0.95);
}
.user-logs-container i {
    color: white !important;
    font-size: 1.2rem !important;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
[data-theme="dark"] .user-logs-container {
    background: linear-gradient(145deg, #4f46e5 0%, #6366f1 50%, #818cf8 100%);
    box-shadow: 0 4px 20px rgba(79, 70, 229, 0.5),
                0 2px 4px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.user-logs-wrapper {
    display: inline-flex;
    align-items: center;
}

/* User Logs Modal */
#user-logs-modal .modal-dialog {
    max-width: 95%;
    margin: 90px auto 1.75rem auto; /* Further increased top margin to 90px to clear navbar */
}

#user-logs-modal .modal-content {
    height: calc(100vh - 200px); /* Adjusted height to account for navbar */
    max-height: calc(100vh - 200px);
    border-radius: 12px;
    border: none;
    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

#user-logs-modal .modal-header {
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
    color: white;
    border-radius: 12px 12px 0 0;
    padding: 1rem 1.5rem;
    flex-shrink: 0;
}

#user-logs-modal .modal-title {
    font-weight: 600;
    font-size: 1.25rem;
}

#user-logs-modal .modal-body {
    padding: 1rem 1.5rem;
    background: var(--card-bg);
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

#user-logs-modal .modal-footer {
    padding: 0.75rem 1.5rem;
    border-top: 1px solid var(--border-color);
    flex-shrink: 0;
    background: var(--card-bg);
}

/* Fix DatePicker dropdown positioning */
#user-logs-modal .DateRangePicker {
    position: relative !important;
    width: 100% !important;
}

#user-logs-modal .DateRangePickerInput {
    background: var(--card-bg);
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    width: 100% !important;
    justify-content: space-between;
}

#user-logs-modal .DateRangePicker_picker {
    position: absolute !important;
    top: 100% !important;
    left: 0 !important;
    z-index: 9999 !important;
}

.DateInput_input {
    font-size: 13px;
}

.DateRangePickerInput {
    background: var(--card-bg);
}

.DayPickerNavigation_button {
    border: none;
}

#user-logs-modal .DateRangePickerInput__withBorder {
    border-radius: 4px;
}

#user-logs-modal .DateInput {
    width: 48% !important;
    flex: 1;
}

#user-logs-modal .DateInput_input {
    padding: 4px 8px;
    font-size: 12px;
}

/* Logs Table - No horizontal scroll, fit within wrapper */
#user-logs-table {
    font-size: 0.85rem;
    border-radius: 8px;
    overflow: hidden;
    width: 100%;
    table-layout: fixed;
}

#user-logs-table .dash-table-container {
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    width: 100%;
}

#user-logs-table .dash-spreadsheet-container {
    overflow-y: auto;
    overflow-x: hidden !important;
}

#user-logs-table .dash-spreadsheet {
    width: 100% !important;
}

#user-logs-table .dash-spreadsheet .dash-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--primary-color) !important;
}

/* Hide horizontal scrollbar */

/* Logs table wrapper - flex to fill remaining space */
#user-logs-modal .logs-table-wrapper {
    flex: 1 1 auto;
    min-height: 100px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

#user-logs-modal .logs-table-wrapper #user-logs-table {
    flex: 1;
    display: flex;
    flex-direction: column;
}

#user-logs-modal .logs-table-wrapper #user-logs-table .dash-table-container {
    flex: 1;
    display: flex;
    flex-direction: column;
}

#user-logs-modal .logs-table-wrapper #user-logs-table .dash-spreadsheet-container {
    flex: 1;
    max-height: none !important;
}

/* Hide pagination controls at bottom of table */
#user-logs-modal .logs-table-wrapper .previous-next-container,
#user-logs-modal .logs-table-wrapper button.previous-page,
#user-logs-modal .logs-table-wrapper button.next-page,
#user-logs-modal .logs-table-wrapper button.first-page,
#user-logs-modal .logs-table-wrapper button.last-page,
#user-logs-modal .logs-table-wrapper .dash-table-container > .row:last-child {
    display: none !important;
    visibility: hidden !important;
}

/* Statistics section - improved UI */
#user-logs-statistics-collapse {
    margin-bottom: 12px;
    flex-shrink: 0;
}

#user-logs-statistics-collapse .card {
    border: none;
    background: transparent;
}

#user-logs-statistics-collapse .card-body {
    padding: 0 !important;
}

/* Statistics summary badges row */
.user-logs-stats-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}

.user-logs-stats-badges .badge {
    font-size: 0.85rem;
    padding: 8px 14px;
    border-radius: 20px;
    font-weight: 500;
}

/* Statistics detail cards */
.user-logs-stats-detail {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}

.user-logs-stats-card {
    background: var(--bg-section);
    border-radius: 10px;
    padding: 12px 16px;
    border: 1px solid var(--border-color);
}

.user-logs-stats-card-title {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.user-logs-stats-card-title i {
    font-size: 0.9rem;
}

.user-logs-stats-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.user-logs-stats-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.85rem;
}

.user-logs-stats-list li:last-child {
    border-bottom: none;
}

.user-logs-stats-list .stat-name {
    color: var(--text-primary);
    font-weight: 500;
}

.user-logs-stats-list .stat-value {
    background: var(--primary-color);
    color: white;
    padding: 2px 10px;
    border-radius: 12px;
    font-size: 0.8rem;
    font-weight: 600;
    min-width: 35px;
    text-align: center;
}

/* Button group styling */
#user-logs-modal .btn-group {
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

#user-logs-modal .btn-group .btn {
    border-radius: 0;
}

#user-logs-modal .btn-group .btn:first-child {
    border-radius: 6px 0 0 6px;
}

#user-logs-modal .btn-group .btn:last-child {
    border-radius: 0 6px 6px 0;
}

/* Dark mode */
[data-theme="dark"] #user-logs-modal .modal-header {
    background: linear-gradient(135deg, #4c1d95 0%, #6b21a8 100%);
}

[data-theme="dark"] .user-logs-stats-card {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.1);
}

[data-theme="dark"] #user-logs-table .dash-table-container {
    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}

/* Responsive */
@media (max-width: 768px) {
    #user-logs-modal .modal-dialog {
        max-width: 100%;
        margin: 0.5rem;
    }
    
    #user-logs-table {
        font-size: 0.75rem;
    }
    
    .user-logs-stats-detail {
        grid-template-columns: 1fr;
    }
}

/* Clear days input styling */
#user-logs-clear-days-input {
    max-width: 65px;
}

/* FIX 4: User Logs Buttons - Responsive scaling để không bị chồng khi zoom out */
#user-logs-modal .btn-group {
    display: flex !important;
    flex-wrap: nowrap !important;
}

#user-logs-modal .btn-group .btn {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    font-size: clamp(0.7rem, 0.8rem, 0.875rem) !important;
    padding: 0.25rem 0.4rem !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

#user-logs-modal .btn-group .btn i {
    margin-right: 0.2rem !important;
}

/* Zoom-specific adjustments */
@media (max-width: 1200px), (min-width: 1400px) {
    #user-logs-modal .btn-group .btn {
        font-size: 0.75rem !important;
        padding: 0.2rem 0.3rem !important;
    }
}

/* FIX 7: User Logs Clear Section - Responsive scaling */
#user-logs-modal .user-logs-clear-group {
    flex-wrap: nowrap !important;
}

#user-logs-modal .user-logs-clear-group .form-control {
    min-width: 40px !important;
    flex: 0 0 50px !important;
    width: 50px !important;
    padding: 0.25rem 0.2rem !important;
}

#user-logs-modal .user-logs-clear-group .input-group-text {
    font-size: 0.7rem !important;
    padding: 0.25rem 0.4rem !important;
    white-space: nowrap !important;
}

#user-logs-modal .user-logs-clear-group .btn {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    padding: 0.25rem 0.4rem !important;
    font-size: clamp(0.7rem, 0.8rem, 0.875rem) !important;
}

#user-logs-modal .user-logs-clear-group .btn i {
    margin-right: 0.2rem !important;
}

/* Restart Server Button Styling (Matches Sync Button) */
.sidebar .btn-warning {
    background: linear-gradient(135deg, var(--warning-color) 0%, #d97706 100%);
    border: none;
    border-radius: 10px;
    font-weight: 600;
    padding: 12px 20px;
    box-shadow: var(--shadow-md);
    transition: all var(--transition-normal);
    color: #fff;
}
.sidebar .btn-warning:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    filter: brightness(1.1);
    color: #fff;
}
.sidebar .btn-warning:active {
    transform: translateY(0);
}
.sidebar .btn-warning:disabled {
    opacity: 0.65;
    transform: none;
    box-shadow: none;
}

/* Stop Sync Button Styling (Matches Sync/Restart Button) */
.sidebar .btn-danger {
    background: linear-gradient(135deg, var(--danger-color) 0%, #b91c1c 100%);
    border: none;
    border-radius: 10px;
    font-weight: 600;
    padding: 12px 20px;
    box-shadow: var(--shadow-md);
    transition: all var(--transition-normal);
    color: #fff;
}
.sidebar .btn-danger:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    filter: brightness(1.1);
    color: #fff;
}
.sidebar .btn-danger:active {
    transform: translateY(0);
}
.sidebar .btn-danger:disabled {
    opacity: 0.65;
    transform: none;
    box-shadow: none;
}

/* Header Tooltip - Custom Style */
.header-tooltip .tooltip-inner {
    background: linear-gradient(135deg, #4f46e5 0%, #3730a3 100%) !important;
    color: #ffffff !important;
    border: 1px solid #6366f1 !important;
    box-shadow: 0 4px 15px rgba(79, 70, 229, 0.3) !important;
    font-weight: 600 !important;
    padding: 8px 12px !important;
    font-size: 0.85rem !important;
    border-radius: 8px !important;
}
/* Dark mode for header tooltip */
[data-theme="dark"] .header-tooltip .tooltip-inner {
    background: linear-gradient(135deg, #312e81 0%, #1e1b4b 100%) !important;
    color: #e0e7ff !important;
    border: 1px solid #6366f1 !important;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5) !important;
}

/* <1.1> FIX: Chart container layout to prevent Bootstrap grid conflicts */
.scrollable-content {
    display: flex !important;
    flex-direction: column !important;
    width: 100% !important;
    box-sizing: border-box !important;
    padding: 0 !important;
    margin: 0 !important;
    gap: 0 !important;
}

/* <1.1> FIX: Ensure chart row containers use pure flexbox */
.scrollable-content > div {
    display: flex !important;
    flex-wrap: nowrap !important;
    width: 100% !important;
    box-sizing: border-box !important;
    margin: 0 0 16px 0 !important;
    gap: 8px !important;
}

/* <1.1> FIX: Chart columns within rows */
.scrollable-content > div > div {
    display: flex !important;
    flex-direction: column !important;
    flex: 0 0 auto !important;
    box-sizing: border-box !important;
    padding: 0 8px !important;
    overflow: hidden !important;
}

/* Ensure dcc_graph fills the chart container */
.scrollable-content .dcc_graph {
    width: 100% !important;
    height: 100% !important;
    flex: 1 !important;
}

/* ✅ FIX #7: Weekly Report Dynamic Height */
#weekly-chart-table-row {
    align-items: stretch;
}

#weekly-chart-table-row > .col {
    display: flex;
    flex-direction: column;
}

.weekly-chart-col,
.weekly-table-col {
    display: flex;
    flex-direction: column;
}

.weekly-chart-col > div,
.weekly-table-col > div {
    flex: 1;
    min-height: 350px;
    display: flex;
    flex-direction: column;
}

.weekly-chart-col > div > .chart-container,
.weekly-table-col > div > .chart-container {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.weekly-chart-col .dcc_graph,
.weekly-table-col .dash-table-container {
    flex: 1;
    min-height: 350px !important;
}

/* Chart iframe / graph fills full height of weekly chart col */
.weekly-chart-col .dcc_graph > div {
    height: 100% !important;
}

/* table-7d-part1 pagination approach - table height = pie chart container height */
#table-7d-part1-col .chart-container {
    display: flex;
    flex-direction: column;
    height: 100%;
}


/* ── Incident Report Modal ──────────────────────────────────────── */
.incident-report-modal .modal-dialog {
    max-width: min(96vw, 1100px);
}

.incident-upload-zone:hover {
    border-color: var(--primary-color) !important;
    background: rgba(99, 102, 241, 0.04) !important;
}

/* Mobile: stack form cols on small screens */
@media (max-width: 575px) {
    .incident-report-modal .modal-body {
        padding: 10px;
    }
    .incident-report-modal .row > .col {
        margin-bottom: 6px;
    }
}

/* ── incident-report-modal: full-height, controlled by modal_layout.js ── */
/* modal_layout.js sets dialog height/marginTop dynamically (same as about-modal, user-logs-modal) */
/* CSS chỉ cần đảm bảo modal-content + body fill 100% của dialog */

#incident-report-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
    border-radius: 12px;
    border: none;
    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}

#incident-report-modal .modal-header,
#incident-report-modal .modal-footer {
    flex-shrink: 0 !important;
}

#incident-report-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
}

/* ── rootcause-modal: full-height controlled by modal_layout.js ── */
#rootcause-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#rootcause-modal .modal-header,
#rootcause-modal .modal-footer {
    flex-shrink: 0 !important;
}

#rootcause-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
}

/* ── maint-detail-modal: scrollable body (same pattern as incident modal) ── */
/* body { overflow: hidden } blocks Bootstrap scrollable=True — must use explicit flex+overflow */
#maint-detail-modal .modal-dialog {
    max-height: 92vh !important;
    height: 92vh !important;
    display: flex !important;
    flex-direction: column !important;
    margin-top: 4vh !important;
    margin-bottom: 4vh !important;
}

#maint-detail-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#maint-detail-modal .modal-header,
#maint-detail-modal .modal-footer {
    flex-shrink: 0 !important;
}

#maint-detail-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
}

/* ── apikey-edit-modal: scrollable body (same pattern as maint-detail-modal) ── */
/* body { overflow: hidden } blocks Bootstrap scrollable=True — must use explicit flex+overflow */
#apikey-edit-modal .modal-dialog {
    max-height: 92vh !important;
    height: 92vh !important;
    display: flex !important;
    flex-direction: column !important;
    margin-top: 4vh !important;
    margin-bottom: 4vh !important;
}

#apikey-edit-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#apikey-edit-modal .modal-header,
#apikey-edit-modal .modal-footer {
    flex-shrink: 0 !important;
}

#apikey-edit-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
}

/* ── +Thêm sự cố button hover/active effects ── */
.inc-add-btn {
    transition: background-color 0.18s ease, transform 0.12s ease, box-shadow 0.18s ease;
}
.inc-add-btn:hover {
    background-color: #4f46e5 !important;
    border-color: #4f46e5 !important;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.45) !important;
}
.inc-add-btn:active {
    transform: translateY(0px) scale(0.97);
    box-shadow: 0 1px 4px rgba(99, 102, 241, 0.3) !important;
}

/* ── Alt+Enter textarea hint ── */
.inc-alt-enter-hint {
    font-size: 10px;
    color: var(--text-muted, #6c757d);
    margin-top: 2px;
}

/* ── Fix: disabled/auto-calculate input fields readable on dark theme ── */
.incident-report-modal .form-control:disabled,
.incident-report-modal .form-control[readonly],
#incident-report-modal .form-control:disabled,
#incident-report-modal .form-control[readonly] {
    background-color: var(--bg-section, #1e293b) !important;
    color: var(--text-secondary, #e2e8f0) !important;
    opacity: 1 !important;
    -webkit-text-fill-color: var(--text-secondary, #e2e8f0) !important;
    border-color: var(--border-color, #334155) !important;
}

/* Placeholder text for auto fields */
.incident-report-modal .form-control:disabled::placeholder,
#incident-report-modal .form-control:disabled::placeholder {
    color: var(--text-muted, #94a3b8) !important;
    opacity: 1 !important;
}

/* Light theme override */
[data-theme="light"] .incident-report-modal .form-control:disabled,
[data-theme="light"] #incident-report-modal .form-control:disabled {
    background-color: #f1f5f9 !important;
    color: #475569 !important;
    -webkit-text-fill-color: #475569 !important;
}

/* ── Fix: 4M row delete button always visible ── */
.rootcause-modal .rc-4m-row .btn,
#rootcause-modal [id*="rc-del-"] {
    min-width: 28px !important;
    flex-shrink: 0 !important;
}

/* ── Fix #1: đồng bộ height TẤT CẢ input + dropdown (Select) trong incident modal ── */
#incident-report-modal .form-control,
#incident-report-modal .form-select,
.incident-report-modal .form-control,
.incident-report-modal .form-select {
    min-height: 31px !important;
    height: 31px !important;
    padding-top: 4px !important;
    padding-bottom: 4px !important;
    line-height: 1.5 !important;
    box-sizing: border-box !important;
}

/* Textarea giữ nguyên height auto */
#incident-report-modal textarea.form-control,
.incident-report-modal textarea.form-control {
    height: auto !important;
    min-height: 60px !important;
}

/* ── Fix height v2: target cả datetime-local và tất cả input types ── */
#incident-report-modal input.form-control,
#incident-report-modal input[type="text"].form-control,
#incident-report-modal input[type="datetime-local"].form-control {
    height: 31px !important;
    min-height: 31px !important;
    max-height: 31px !important;
    padding-top: 4px !important;
    padding-bottom: 4px !important;
    font-size: 13px !important;
    line-height: 1.4 !important;
    box-sizing: border-box !important;
}

/* ── Fix #1 (v3): Dash dcc.Dropdown Select control height sync ── */
/* Dash Dropdown renders as .Select-control (react-select v1/v2) */
#incident-report-modal .Select-control,
.incident-report-modal .Select-control {
    min-height: 31px !important;
    height: 31px !important;
    line-height: 29px !important;
    border-radius: 4px !important;
}
#incident-report-modal .Select--single > .Select-control .Select-value,
.incident-report-modal .Select--single > .Select-control .Select-value,
#incident-report-modal .Select-placeholder,
.incident-report-modal .Select-placeholder {
    line-height: 29px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
#incident-report-modal .Select-arrow-zone,
.incident-report-modal .Select-arrow-zone {
    padding-top: 0 !important;
    vertical-align: middle !important;
}
#incident-report-modal .Select-input,
.incident-report-modal .Select-input {
    height: 29px !important;
    line-height: 29px !important;
}
/* Dash newer react-select v5 (VirtualizedSelect wrapper) */
#incident-report-modal .dash-dropdown .Select__control,
.incident-report-modal .dash-dropdown .Select__control {
    min-height: 31px !important;
    height: 31px !important;
}

/* ── Fix #5: Upload zone giữ style sau khi đã add ảnh ── */
.incident-upload-zone {
    border-radius: 6px !important;
    border: 2px dashed #6366f1 !important;
    padding: 12px 10px !important;
    cursor: pointer !important;
    background: rgba(99,102,241,0.08) !important;
    min-height: 48px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    transition: border-color 0.2s, background 0.2s !important;
}
.incident-upload-zone:hover {
    border-color: #818cf8 !important;
    background: rgba(99,102,241,0.14) !important;
}
/* Override Dash dcc.Upload styles that wipe our styling */
#inc-form-upload {
    border-radius: 6px !important;
    border: 2px dashed #6366f1 !important;
    padding: 12px 10px !important;
    cursor: pointer !important;
    background: rgba(99,102,241,0.08) !important;
    min-height: 48px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
#inc-form-upload:hover {
    border-color: #818cf8 !important;
    background: rgba(99,102,241,0.14) !important;
}

/* ── maint-sp-mini-modal (Modal Vật tư - Checklist): full-height controlled by modal_layout.js ── */
#maint-sp-mini-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
    border-radius: 12px;
}

#maint-sp-mini-modal .modal-header,
#maint-sp-mini-modal .modal-footer {
    flex-shrink: 0 !important;
}

#maint-sp-mini-modal .modal-body {
    overflow: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

/* ── incident-spare-modal (Modal Vật tư - Incident): full-height controlled by modal_layout.js ── */
#incident-spare-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
    border-radius: 12px;
}

#incident-spare-modal .modal-header,
#incident-spare-modal .modal-footer {
    flex-shrink: 0 !important;
}

#incident-spare-modal .modal-body {
    overflow: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

/* ── planning-import-export-modal: scrollable body (same pattern as maint-detail-modal) ── */
/* body { overflow: hidden } blocks Bootstrap scrollable=True — must use explicit flex+overflow */
#planning-import-export-modal .modal-dialog {
    max-height: 88vh !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    margin-top: 6vh !important;
    margin-bottom: 6vh !important;
}

#planning-import-export-modal .modal-content {
    max-height: 88vh !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#planning-import-export-modal .modal-header,
#planning-import-export-modal .modal-footer {
    flex-shrink: 0 !important;
}

#planning-import-export-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
}

/* ── Close (X) button — Incident / Rootcause / Maintenance modals ────────────
   Dùng class .modal-close-x thay vì Bootstrap .btn-close vì Bootstrap override
   màu bằng filter:invert() + opacity:0.5 → không thể customize được.
   ─────────────────────────────────────────────────────────────────────────── */
.modal-close-x {
    /* Reset hoàn toàn Bootstrap btn-close */
    background-image: none !important;
    filter: none !important;
    opacity: 1 !important;

    /* Style custom */
    color: #475569 !important;       /* slate-600 — rõ ràng trên nền sáng */
    font-size: 1.5rem !important;
    line-height: 1 !important;
    background: none !important;
    border: none !important;
    cursor: pointer !important;
    padding: 0 2px !important;
    margin-left: auto !important;
    transition: color 0.15s ease, transform 0.12s ease;
}

.modal-close-x:hover {
    color: #dc2626 !important;       /* đỏ khi hover — signal rõ "đóng" */
    transform: scale(1.15);
}

.modal-close-x:active {
    transform: scale(0.95);
}

/* Dark mode: nền tối → dùng màu sáng hơn */
[data-theme="dark"] .modal-close-x {
    color: #cbd5e1 !important;       /* slate-300 — dễ thấy trên nền tối */
}

[data-theme="dark"] .modal-close-x:hover {
    color: #f87171 !important;       /* đỏ nhạt cho dark mode */
}

/* ══════════════════════════════════════════════════════════════
   GLOBAL FIX: Modal z-index > Sidebar z-index
   Sidebar = position:fixed z-index:1100 → all modals must be
   above 1100 so they are never hidden behind the sidebar.
   Bootstrap defaults: .modal-backdrop = 1050, .modal = 1055
   → raise both above 1100.
   ══════════════════════════════════════════════════════════════ */
.modal-backdrop {
    z-index: 1150 !important;
}
.modal {
    z-index: 1200 !important;
}

/* ══════════════════════════════════════════════════════════════
   Asset Detail Modal — Export dropdown fix
   (Moved to AUTO-HEIGHT MODALS section below)
   ══════════════════════════════════════════════════════════════ */
/* Dropdown menu của Export mở lên trên (dropup) trong modal footer */
#asset-detail-modal .asset-detail-export-dropdown .dropdown-menu {
    bottom: 100% !important;
    top: auto !important;
    margin-bottom: 4px !important;
    margin-top: 0 !important;
}

/* ══════════════════════════════════════════════════════════════
   AUTO-HEIGHT MODALS
   Shrink-to-fit content khi ít nội dung,
   expand tới max-height khi nội dung dài.
   marginTop + maxHeight được inject bởi modal_layout.js.
   ══════════════════════════════════════════════════════════════ */

/* Base pattern: tất cả auto-height modal */
#drilldown-modal .modal-content,
#maint-settings-modal .modal-content,
#planning-planned-status-modal .modal-content,
#sp-add-modal .modal-content,
#sp-in-modal .modal-content,
#sp-out-modal .modal-content,
#asset-detail-modal .modal-content,
#online-users-modal .modal-content,
#batch-export-modal .modal-content,
#shift-add-code-modal .modal-content,
#shift-add-employee-modal .modal-content,
#shift-schedule-guide-modal .modal-content,
#role-edit-modal .modal-content,
#wp-edit-modal .modal-content {
    /* Không fixed height — shrink tự nhiên theo nội dung */
    height: auto !important;
    /* max-height được set bởi JS (modal_layout.js fixAutoHeightModalPosition) */
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
    border-radius: 12px;
    border: none;
    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}

/* modal-dialog: không fixed height, chỉ có max-height từ JS */
#drilldown-modal .modal-dialog,
#maint-settings-modal .modal-dialog,
#planning-planned-status-modal .modal-dialog,
#sp-add-modal .modal-dialog,
#sp-in-modal .modal-dialog,
#sp-out-modal .modal-dialog,
#asset-detail-modal .modal-dialog,
#online-users-modal .modal-dialog,
#batch-export-modal .modal-dialog,
#shift-add-code-modal .modal-dialog,
#shift-add-employee-modal .modal-dialog,
#shift-schedule-guide-modal .modal-dialog,
#role-edit-modal .modal-dialog,
#wp-edit-modal .modal-dialog {
    height: auto !important;
    min-height: 0 !important;
    /* max-height injected by JS */
    display: flex !important;
    flex-direction: column !important;
}

/* Header & footer: không co dãn */
#drilldown-modal .modal-header,
#drilldown-modal .modal-footer,
#maint-settings-modal .modal-header,
#maint-settings-modal .modal-footer,
#planning-planned-status-modal .modal-header,
#planning-planned-status-modal .modal-footer,
#sp-add-modal .modal-header,
#sp-add-modal .modal-footer,
#sp-in-modal .modal-header,
#sp-in-modal .modal-footer,
#sp-out-modal .modal-header,
#sp-out-modal .modal-footer,
#asset-detail-modal .modal-header,
#asset-detail-modal .modal-footer,
#online-users-modal .modal-header,
#online-users-modal .modal-footer,
#batch-export-modal .modal-header,
#batch-export-modal .modal-footer,
#shift-add-code-modal .modal-header,
#shift-add-code-modal .modal-footer,
#shift-add-employee-modal .modal-header,
#shift-add-employee-modal .modal-footer,
#shift-schedule-guide-modal .modal-header,
#shift-schedule-guide-modal .modal-footer,
#role-edit-modal .modal-header,
#role-edit-modal .modal-footer,
#wp-edit-modal .modal-header,
#wp-edit-modal .modal-footer {
    flex-shrink: 0 !important;
}

/* Body: chiếm phần còn lại, scroll nếu tràn */
#drilldown-modal .modal-body,
#maint-settings-modal .modal-body,
#planning-planned-status-modal .modal-body,
#sp-add-modal .modal-body,
#sp-in-modal .modal-body,
#sp-out-modal .modal-body,
#asset-detail-modal .modal-body,
#online-users-modal .modal-body,
#batch-export-modal .modal-body,
#shift-add-code-modal .modal-body,
#shift-add-employee-modal .modal-body,
#shift-schedule-guide-modal .modal-body,
#role-edit-modal .modal-body,
#wp-edit-modal .modal-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    max-height: none !important;
}

/* Banner "Đã lưu quyền..." không bao giờ bị flexbox co nhỏ bởi khung
   danh sách permission bên cạnh (xem modules/utils/utils_js.py
   applyLargeModalStyle — cùng 1 nguyên nhân, fix ở cả 2 nơi cho chắc). */
#role-edit-modal .modal-body > .auto-dismiss-msg {
    flex-shrink: 0 !important;
}

/* ── asset-detail-modal: giữ overflow visible cho dropdown export ── */
#asset-detail-modal .modal-content {
    overflow: visible !important;
}
#asset-detail-modal .modal-footer {
    overflow: visible !important;
    position: relative;
    z-index: 10;
}
#asset-detail-modal .modal-body {
    overflow: hidden !important;
}

/* ── batch-export-modal: extra wide trên màn lớn ── */
#batch-export-modal .modal-dialog {
    max-width: min(90vw, 900px) !important;
}

/* ── online-users-modal: vừa phải ── */
#online-users-modal .modal-dialog {
    max-width: min(85vw, 700px) !important;
}

/* ── shift-add-code-modal / shift-add-employee-modal / shift-schedule-guide-modal:
   fix #1/#2/#3 — width co giãn theo % viewport (min(vw, px)) giống các modal
   chuẩn khác (incident-report-modal, batch-export-modal...) thay vì để
   Bootstrap default width cố định theo px không đổi trên mọi màn hình. ── */
#shift-add-code-modal .modal-dialog,
#shift-add-employee-modal .modal-dialog {
    max-width: min(92vw, 700px) !important;
}
#shift-schedule-guide-modal .modal-dialog {
    max-width: min(92vw, 800px) !important;
}

/* ── Responsive: mobile ── */
@media (max-width: 576px) {
    #drilldown-modal .modal-dialog,
    #maint-settings-modal .modal-dialog,
    #planning-planned-status-modal .modal-dialog,
    #sp-add-modal .modal-dialog,
    #sp-in-modal .modal-dialog,
    #sp-out-modal .modal-dialog,
    #asset-detail-modal .modal-dialog,
    #online-users-modal .modal-dialog,
    #batch-export-modal .modal-dialog,
    #shift-add-code-modal .modal-dialog,
    #shift-add-employee-modal .modal-dialog,
    #shift-schedule-guide-modal .modal-dialog {
        max-width: 100% !important;
        margin-left: 4px !important;
        margin-right: 4px !important;
    }
}

/* ── Fix: scrollable=True modals (Bootstrap .modal-dialog-scrollable) ──
   dialog.height = inflatedH (JS) → content cần fill toàn bộ dialog.
   dialog là flex container → dùng flex:1 1 auto trên content (KHÔNG dùng height:100%
   vì % trong flex context resolve không đúng).
   modal-body cũng flex:1 để fill content.
   Wrapper div bên trong modal-body (#maint-settings-modal-body, v.v.)
   cũng cần height:100% để pass height xuống dbc.Tabs.
   ── */
#maint-settings-modal .modal-dialog.modal-dialog-scrollable {
    /* JS đã set height: inflatedH — CSS hỗ trợ thêm */
    display: flex !important;
    flex-direction: column !important;
}
#maint-settings-modal .modal-dialog.modal-dialog-scrollable .modal-content,
#planning-planned-status-modal .modal-dialog.modal-dialog-scrollable .modal-content,
#sp-out-modal .modal-dialog.modal-dialog-scrollable .modal-content {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    /* KHÔNG set height hay max-height — JS lo */
}

/* maint-settings modal-body: flex column để ul nav-tabs + tab-content stack dọc
   scrollable=False → modal shrink-to-fit, modal-body KHÔNG cần flex:1
   Chỉ cần display:flex + flex-direction:column để chain chiều cao hoạt động */
#maint-settings-modal .modal-body {
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
    /* scrollable=False: bootstrap không set max-height trên body, để content tự quyết */
}

/* maint-settings-modal-body: flex column chứa ul.nav-tabs và .tab-content
   scrollable=False: KHÔNG dùng flex:1 1 auto (sẽ force expand)
   Dùng flex:0 1 auto để shrink-to-fit, max chiều cao bị giới hạn bởi modal-content max-height */
#maint-settings-modal-body {
    flex: 0 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding-top: 4px !important;
}

/* planning-planned-status modal: scroll phải nằm trên từng .planned-status-panel,
   KHÔNG phải .modal-body. Chain: modal-body(overflow:hidden) →
   #planning-planned-status-body(flex:1) → .planned-status-grid(flex:1) →
   .planned-status-panel(overflow:hidden) → .planned-status-body-wrapper(overflow-y:auto) */
#planning-planned-status-modal .modal-body {
    overflow: hidden !important;
    overflow-y: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}
#planning-planned-status-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
#planning-planned-status-body .planned-status-grid {
    flex: 1 1 auto;
    min-height: 0;
    /* height: 100% buộc grid không vượt quá #planning-planned-status-body */
    height: 100%;
    overflow: hidden;
    align-items: stretch;
}
#planning-planned-status-body .planned-status-panel {
    overflow: hidden;
    min-height: 0;
    /* max-height: 100% buộc panel không vượt quá grid */
    max-height: 100%;
}
#planning-planned-status-body .planned-status-body-wrapper {
    flex: 1 1 auto;
    min-height: 0;
    /* max-height: 0 để flex shrink hoạt động — thực tế sẽ expand đến phần còn lại */
    overflow-y: auto;
    overflow-x: hidden;
}
/* Header sticky: hoạt động khi scroll container là .planned-status-body-wrapper */
#planning-planned-status-body .planned-status-header-wrapper {
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 2;
}

/* dbc.Tabs bên trong maint-settings:
   DOM thực tế (từ debug): #maint-settings-tabs LÀ chính <ul class="nav nav-tabs">
   .tab-content là SIBLING của ul, nằm trong #maint-settings-modal-body
   => Dùng #maint-settings-modal-body làm flex column container
   => Reset ul#maint-settings-tabs về flex-direction: row (horizontal)
   => Target .tab-content qua #maint-settings-modal-body > .tab-content */

/* (FIX-ROOT-CAUSE) Dòng tab bị cắt mất phần trên/dưới của icon emoji +
   chữ — xác nhận qua debug console: script tab_scroll_arrows.js (thêm
   mũi tên ◀▶ cuộn ngang) tự động bọc ul#maint-settings-tabs trong
   .tab-scroll-wrapper > .tab-scroll-inner với "flex: 1 1 auto;
   overflow: hidden" (xem assets/tab_scroll_arrows.js).
   #maint-settings-modal-body là flex-direction: COLUMN, nên
   "flex: 1 1 auto" trên wrapper điều khiển CHIỀU CAO (main axis) chứ
   không phải chiều rộng như ở các thanh tab NẰM NGANG khác (main-tabs,
   sub-tabs...) vốn sống trong 1 flex ROW.
   Theo spec CSS Flexbox, một flex-item có "overflow: hidden" sẽ có
   "automatic minimum size" = 0 thay vì bằng kích thước nội dung (đây là
   quy tắc chính thức, không phải bug trình duyệt) — nên khi tổng chiều
   cao ul (~47px) + .tab-content (~663px) vượt quá chiều cao khả dụng
   của modal-body, trình duyệt được phép co wrapper xuống gần 0 (thực tế
   ~8px) thay vì co đều/co ít — kết quả: hàng tab bị nén còn ~8px,
   overflow:hidden cắt mất phần trên/dưới của icon+chữ.
   Fix: ép .tab-scroll-wrapper/.tab-scroll-inner bao quanh RIÊNG
   #maint-settings-tabs không được co (flex-shrink:0) và có chiều cao
   tối thiểu bằng đúng nội dung — dùng :has() để CHỈ áp dụng cho thanh
   tab này, không ảnh hưởng các thanh tab ngang khác (main-tabs, sub-tabs
   ở các modal khác vẫn cần flex:1 1 auto để cuộn ngang đúng theo
   chiều rộng). */
.tab-scroll-wrapper:has(#maint-settings-tabs) {
    flex: 0 0 auto !important;
    min-height: 48px !important;
    overflow: visible !important;
}
.tab-scroll-wrapper:has(#maint-settings-tabs) .tab-scroll-inner {
    flex: 0 0 auto !important;
    min-height: 48px !important;
    overflow-y: visible !important;
}

/* ul#maint-settings-tabs: reset flex về horizontal (Bootstrap nav-tabs) */
#maint-settings-tabs {
    flex-shrink: 0 !important;
    flex-direction: row !important;  /* tabs nằm ngang, không dọc */
    min-height: unset !important;
    overflow: visible !important;
    flex-wrap: nowrap;
}

/* (FIX) Dòng tab bị cắt mất phần trên/dưới của icon emoji + chữ
   (📂 Area, 📋 Details, ⏰ Break Time...) — nguyên nhân: container cha
   #maint-settings-modal-body có overflow:hidden, còn dòng tab
   (#maint-settings-tabs) lại không có đủ padding/line-height để chứa
   trọn chiều cao icon emoji (emoji thường cao hơn line-height mặc định
   của chữ thường) -> phần thừa bị cắt bởi overflow:hidden của cha.
   Thêm padding dọc + line-height rộng rãi hơn cho cả ul lẫn từng
   .nav-link để icon/chữ luôn nằm trọn trong khung, không còn bị crop. */
#maint-settings-tabs {
    padding-top: 6px !important;
    padding-bottom: 2px !important;
    align-items: center;
}
#maint-settings-tabs .nav-link {
    line-height: 1.6 !important;
    padding: 8px 16px !important;
    display: inline-flex !important;
    align-items: center;
}

/* (FIX) Chữ tab (Area/Details/Break Time/Staff/Type/Status/Period Type)
   gần như "biến mất" trên nền tối của modal này — nguyên nhân là rule
   chung ".nav-tabs .nav-link { color: #64748b; }" (07_components.css)
   dùng màu xám tối, vốn được thiết kế cho nền SÁNG, không có override
   riêng cho modal này như các modal khác (Admin, Layout Editor...) nên
   bị chìm vào nền tối của #maint-settings-modal. Thêm màu sáng hơn cho
   tab chưa chọn + màu nổi bật rõ cho tab đang active, đồng bộ với các
   tab khác trong app. */
#maint-settings-tabs .nav-link {
    color: #cbd5e1 !important;
    background: transparent;
    border: none;
}
#maint-settings-tabs .nav-link:hover:not(.active) {
    color: #fff !important;
    background: rgba(148, 163, 184, 0.12);
}
#maint-settings-tabs .nav-link.active {
    color: #fff !important;
    background: rgba(99, 102, 241, 0.22);
    border-bottom: 2px solid #6366f1 !important;
    font-weight: 700;
}

/* tab-content là sibling của ul trong #maint-settings-modal-body
   scrollable=False: dùng flex:0 1 auto để shrink-to-fit thay vì force expand */
#maint-settings-modal-body > .tab-content {
    flex: 0 1 auto;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
#maint-settings-modal-body > .tab-content > .tab-pane {
    min-height: 0;
    overflow: hidden;
    display: none;
    flex-direction: column;
}
#maint-settings-modal-body > .tab-content > .tab-pane.active {
    display: flex;
    flex: 0 1 auto;
}

/* ============================================================
   (FIX) Shift import/mass-upload preview modals — không cuộn được
   ============================================================
   4 modal: shift-import-modal (Import Shift), shift-import-ot-modal
   (Import Shift Info-OT/mã ca), shift-import-dsnv-modal (Import DS NV),
   shift-mass-upload-modal (Upload/Download hàng loạt) đã được set
   scrollable=True (dbc.Modal) ở ui_shift.py để .modal-body tự cuộn dọc
   khi nội dung preview/diff dài — nhưng scrollable=True CHỈ có tác
   dụng khi .modal-dialog có max-height giới hạn (mặc định Bootstrap
   modal-dialog-scrollable đã tự set max-height: calc(100% - margin)
   dựa trên chiều cao cửa sổ, nên bình thường không cần thêm gì). Tuy
   nhiên để chắc chắn 100% (đề phòng theme/CSS khác trong app này can
   thiệp), khai báo tường minh ở đây luôn — đồng thời giới hạn chiều
   cao bảng preview/diff bên trong không vượt quá phần còn lại của
   modal-body trên các màn hình thấp. */
#shift-import-modal .modal-dialog,
#shift-import-ot-modal .modal-dialog,
#shift-import-dsnv-modal .modal-dialog,
#shift-mass-upload-modal .modal-dialog {
    max-height: calc(100vh - 3.5rem);
}
#shift-import-modal .modal-content,
#shift-import-ot-modal .modal-content,
#shift-import-dsnv-modal .modal-content,
#shift-mass-upload-modal .modal-content {
    max-height: calc(100vh - 3.5rem);
}
#shift-import-modal .modal-body,
#shift-import-ot-modal .modal-body,
#shift-import-dsnv-modal .modal-body,
#shift-mass-upload-modal .modal-body {
    overflow-y: auto !important;
}

/* ── ASM Info: bảng chèn qua cú pháp {{table}}...{{/table}} (xem
   _parse_table_block trong modules/ui/ui_asm_info_modal.py) ──
   (FIX 2026-08-25 <bảng dùng nền/chữ màu sáng cứng, lệch tông dark mode>)
   Bootstrap mặc định tô bảng nền trắng/chữ đen bất kể theme app đang sáng
   hay tối -> dùng đúng biến màu CSS của app (--card-bg/--text-primary/
   --border-color, xem assets/css/01_variables.css) để bảng luôn khớp theme
   hiện tại, không hardcode màu sáng nữa. */
#asm-info-modal table.asm-info-table {
    color: var(--text-primary) !important;
    background-color: var(--card-bg) !important;
    border-color: var(--border-color) !important;
}
#asm-info-modal table.asm-info-table > thead {
    background-color: rgba(79, 70, 229, 0.18) !important;
}
#asm-info-modal table.asm-info-table > thead > tr > th {
    color: var(--text-primary) !important;
    background-color: transparent !important;
    border-color: var(--border-color) !important;
}
#asm-info-modal table.asm-info-table > tbody > tr > td {
    color: var(--text-primary) !important;
    background-color: var(--card-bg) !important;
    border-color: var(--border-color) !important;
    vertical-align: top !important;
}
/* table-sm/table-bordered của Bootstrap có sẵn hiệu ứng "striped/hover" nền
   sáng cứng qua biến --bs-table-*; ghi đè luôn các biến đó trong phạm vi
   bảng này để không bị lộ màu sáng ở hàng chẵn/lẻ hoặc khi hover. */
#asm-info-modal table.asm-info-table {
    --bs-table-bg: var(--card-bg);
    --bs-table-color: var(--text-primary);
    --bs-table-border-color: var(--border-color);
    --bs-table-striped-bg: var(--card-bg);
    --bs-table-striped-color: var(--text-primary);
    --bs-table-hover-bg: var(--card-bg);
    --bs-table-hover-color: var(--text-primary);
}

/* ── 19_datepicker.css ───────────────────────────────── */
/* ============================================================
   19_datepicker.css — Enhanced Sidebar DatePicker
   Auto-refactored from custom.css
   ============================================================ */

/* === Enhanced Sidebar DatePicker Styling (User Request) === */
/* Apply to Sidebar, Compare tab, and Report tab datepickers */
#custom-date-pickers .SingleDatePicker, #custom-date-pickers .SingleDatePickerInput,
.compare-datepicker .SingleDatePicker, .compare-datepicker .SingleDatePickerInput,
#report-filter-wrapper .SingleDatePicker, #report-filter-wrapper .SingleDatePickerInput {
    width: 100%;
    border: none;
    background: transparent;
}

#custom-date-pickers .DateInput,
.compare-datepicker .DateInput,
#report-filter-wrapper .DateInput {
    width: 100%;
    background: transparent;
    position: relative;
    z-index: 1; /* Không che calendar */
}

#custom-date-pickers .DateInput_input,
.compare-datepicker .DateInput_input,
#report-filter-wrapper .DateInput_input {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary);
    background-color: #ffffff;
    border: 1px solid #cbd5e1;
    border-radius: 8px;
    padding: 10px 12px;
    text-align: center;
    transition: all 0.3s ease;
    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
    font-family: 'Inter', sans-serif;
    height: 42px; /* Fixed height for consistency */
}

#custom-date-pickers .DateInput_input:hover,
.compare-datepicker .DateInput_input:hover,
#report-filter-wrapper .DateInput_input:hover {
    border-color: var(--primary-light);
    box-shadow: 0 4px 8px rgba(0,0,0,0.08);
    transform: translateY(-1px);
}

#custom-date-pickers .DateInput_input__focused,
.compare-datepicker .DateInput_input__focused,
#report-filter-wrapper .DateInput_input__focused {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
    border-bottom: 1px solid var(--primary-color);
}

/* Calendar Popup Modernization */
.SingleDatePicker_picker {
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    border-radius: 16px;
    border: 1px solid rgba(0,0,0,0.05);
    overflow: hidden;
    margin-top: 10px;
    font-family: 'Inter', sans-serif;
    z-index: 999999 !important;
}

.DayPicker {
    border-radius: 16px;
    background: white;
    box-shadow: none;
}

.CalendarMonth_caption {
    color: var(--primary-color);
    font-weight: 800;
    font-size: 1.1rem;
    padding-top: 20px;
    padding-bottom: 45px;
    text-transform: capitalize;
}

.DayPicker_weekHeader {
    top: 55px;
    font-weight: 600;
    color: #64748b;
}

.DayPicker_weekHeader small {
    font-size: 0.8rem;
}

/* Fix DatePicker row hover highlight issue */
.CalendarMonth_table tbody tr:hover,
.CalendarMonth_table tbody tr:hover td,
[data-theme="dark"] .CalendarMonth_table tbody tr:hover,
[data-theme="dark"] .CalendarMonth_table tbody tr:hover td {
    background-color: transparent !important;
    color: inherit !important;
}

.CalendarDay {
    border: none;
    font-size: 0.9rem;
    font-weight: 500;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    vertical-align: middle;
}

.CalendarDay__default:hover {
    background: linear-gradient(135deg, rgba(79, 70, 229, 0.4) 0%, rgba(14, 165, 233, 0.1) 100%) !important;
    border-radius: 50%;
    color: var(--primary-color);
    border: none;
    transform: scale(1.1);
}

.CalendarDay__selected,
.CalendarDay__selected:active,
.CalendarDay__selected:hover {
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%) !important;
    border: none;
    color: white;
    border-radius: 50%;
    font-weight: bold;
    box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4);
    transform: scale(1.05);
}

.CalendarDay__today {
    background: #f1f5f9 !important;
    border-radius: 50%;
    font-weight: 700;
    color: var(--primary-color);
}

.CalendarDay__today:hover {
    background: #e2e8f0;
}

.DayPickerNavigation_button__default {
    border: 1px solid #f1f5f9;
    background: white;
    border-radius: 8px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    top: 14px; /* Vertically center with caption */
    transition: all 0.2s;
}

.DayPickerNavigation_button__default:hover {
    background: #f8fafc;
    border-color: #e2e8f0;
    transform: scale(1.1);
    color: var(--primary-color);
}

.DayPickerNavigation_svg__horizontal {
    fill: #64748b;
    height: 12px;
    width: 12px;
}

.DayPickerNavigation_button__default:hover .DayPickerNavigation_svg__horizontal {
    fill: var(--primary-color);
}

/* Dark Mode Adjustments for DatePicker */
[data-theme="dark"] #custom-date-pickers .DateInput_input,
[data-theme="dark"] .compare-datepicker .DateInput_input,
[data-theme="dark"] #report-filter-wrapper .DateInput_input {
    background-color: #1e293b;
    color: #f1f5f9;
    border-color: #334155;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

[data-theme="dark"] #custom-date-pickers .DateInput_input:hover,
[data-theme="dark"] .compare-datepicker .DateInput_input:hover,
[data-theme="dark"] #report-filter-wrapper .DateInput_input:hover {
    border-color: #6366f1;
    background-color: #2d3748;
}

[data-theme="dark"] #custom-date-pickers .DateInput_input__focused,
[data-theme="dark"] .compare-datepicker .DateInput_input__focused,
[data-theme="dark"] #report-filter-wrapper .DateInput_input__focused {
    border-color: #818cf8;
    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
}

[data-theme="dark"] .SingleDatePicker_picker {
    background-color: #1e293b !important;
    border: 1px solid #334155 !important;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6) !important;
    border-radius: 12px !important;
}

[data-theme="dark"] .DayPicker {
    background: #1e293b !important;
    box-shadow: none !important;
    border: none !important;
    border-radius: 12px !important;
}

[data-theme="dark"] .CalendarMonth {
    background: #1e293b !important;
}

[data-theme="dark"] .CalendarMonthGrid {
    background-color: #1e293b !important;
}

[data-theme="dark"] .CalendarMonth_caption {
    color: #818cf8;
}

[data-theme="dark"] .DayPicker_weekHeader {
    color: #94a3b8;
}

/* Remove default 3D borders in dark mode */
[data-theme="dark"] .DayPicker__withBorder {
    box-shadow: none !important;
    border: none !important;
    background: #1e293b !important;
}

[data-theme="dark"] .CalendarDay {
    background: #1e293b;
    color: #cbd5e1;
    border: none;
}

[data-theme="dark"] .CalendarMonth_table .CalendarDay__default:hover {
    background: var(--primary-color) !important;
    border-radius: 50%;
    color: #ffffff !important;
    border: none;
    transform: scale(1.1);
    box-shadow: 0 0 10px rgba(129, 140, 248, 0.5);
}

[data-theme="dark"] .CalendarMonth_table .CalendarDay__selected,
[data-theme="dark"] .CalendarMonth_table .CalendarDay__selected:active,
[data-theme="dark"] .CalendarMonth_table .CalendarDay__selected:hover {
    background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%) !important;
    color: white;
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
}

[data-theme="dark"] .CalendarDay__today {
    background: #334155 !important;
    color: #818cf8;
}

[data-theme="dark"] .DayPickerNavigation_button__default {
    background: #0f172a;
    border-color: #334155;
}

[data-theme="dark"] .DayPickerNavigation_button__default:hover {
    background: #334155;
    border-color: #475569;
}

[data-theme="dark"] .DayPickerNavigation_svg__horizontal {
    fill: #94a3b8;
}

[data-theme="dark"] .DayPickerNavigation_button__default:hover .DayPickerNavigation_svg__horizontal {
    fill: #e2e8f0;
}

/* Hide keyboard shortcuts panel */
.DayPickerKeyboardShortcuts_show__bottomRight {
    display: none;
}

/* ============================================================
   NEW 2026-08 <native date/time/datetime-local calendar icon>
   ============================================================
   Áp dụng cho MỌI input HTML gốc kiểu type="date" / "time" /
   "datetime-local" trong toàn app (checklist đo nhiệt độ, checklist
   IB and Matrix, form Maintenance, Incident, Work Permit, Spare
   Parts...) — không phải react-dates SingleDatePicker (đã style riêng
   ở trên), mà là icon lịch/đồng hồ do CHÍNH TRÌNH DUYỆT vẽ ra qua
   pseudo-element ::-webkit-calendar-picker-indicator (Chrome/Edge/
   các trình duyệt nền Chromium). Trước đây KHÔNG có rule nào style
   pseudo-element này trong toàn bộ codebase → icon luôn hiện màu đen
   mặc định của hệ điều hành, không đổi theo theme, khó nhìn trên nền
   tối và không đồng bộ với bộ màu (--primary-color) của app.
   Lưu ý: ::-webkit-calendar-picker-indicator chỉ tồn tại ở trình
   duyệt Chromium (Firefox/Safari vẽ icon theo cách khác, không có
   pseudo-element này để can thiệp qua CSS) — rule dưới đây chỉ có tác
   dụng trên Chrome/Edge, không ảnh hưởng/không lỗi ở trình duyệt khác
   (unsupported pseudo-element bị trình duyệt tự bỏ qua). */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    cursor: pointer;
    border-radius: 5px;
    padding: 3px;
    margin-left: 4px;
    opacity: 0.6;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}
input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator,
input[type="date"]:focus::-webkit-calendar-picker-indicator,
input[type="time"]:focus::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:focus::-webkit-calendar-picker-indicator {
    opacity: 1;
    background-color: rgba(79, 70, 229, 0.14);
}

/* Dark mode: icon gốc của trình duyệt luôn vẽ đen tuyền bất kể theme —
   filter:invert() để đổi thành xám sáng, hợp với nền tối của input
   (khớp tông --text-primary dark mode dùng ở các nơi khác trong app).
   Không dùng "color" (pseudo-element này không nhận màu qua "color"/
   "fill" như SVG thường, chỉ đổi được bằng filter trên chính hình icon
   trình duyệt vẽ). */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator,
body.dark-mode input[type="date"]::-webkit-calendar-picker-indicator,
body.dark-mode input[type="time"]::-webkit-calendar-picker-indicator,
body.dark-mode input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(1) brightness(1.6);
}
[data-theme="dark"] input[type="date"]:hover::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]:hover::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="date"]:focus::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]:focus::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]:focus::-webkit-calendar-picker-indicator,
body.dark-mode input[type="date"]:hover::-webkit-calendar-picker-indicator,
body.dark-mode input[type="time"]:hover::-webkit-calendar-picker-indicator,
body.dark-mode input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator,
body.dark-mode input[type="date"]:focus::-webkit-calendar-picker-indicator,
body.dark-mode input[type="time"]:focus::-webkit-calendar-picker-indicator,
body.dark-mode input[type="datetime-local"]:focus::-webkit-calendar-picker-indicator {
    background-color: rgba(129, 140, 248, 0.22);
}

/* ── 20_column_resize.css ────────────────────────────── */
/* ============================================================
   20_column_resize.css — Column Resize (crh handles)
   Auto-refactored from custom.css
   ============================================================ */

/* ============================================================
   COLUMN RESIZE  –  v4.0
   Handle class: .crh  (injected by column_resize.js)
   Width rules: injected via <style id="crh-styles"> by JS
   ============================================================ */

/*
 * th: overflow visible so .crh handle is never clipped.
 * white-space: normal → text wraps to next line (không bị cut).
 * JS also sets these via inline style when injecting handles.
 */
.dash-spreadsheet-inner th {
    overflow   : visible !important;
    position   : sticky !important;
    top        : 0 !important;
    z-index    : 999 !important;
    white-space: normal !important;
    word-break : break-word !important;
    line-height: 1.3 !important;
    padding-right: 10px !important;  /* room for handle */
    box-sizing : border-box !important;
}

/*
 * td cells: keep nowrap + ellipsis (data cells should not wrap).
 */
.dash-spreadsheet-inner td {
    overflow      : hidden !important;
    text-overflow : ellipsis !important;
    white-space   : nowrap !important;
}

/*
 * Last column th: also wrap + hidden so long titles don't break layout.
 */
/* FIX: Removed th:last-child override to allow it to inherit wrapping from the general 'th' rule. */
/*
 * Last column td: clip as usual.
 */
.dash-spreadsheet-inner th:last-child {
    white-space: normal !important;
    overflow: visible !important;
}
.dash-spreadsheet-inner td:last-child {
    overflow      : hidden !important;
    text-overflow : ellipsis !important;
    white-space   : nowrap !important;
}

/* ── Resize handle ─────────────────────────────────────────── */
.crh {
    position   : absolute !important;
    top        : 0 !important;
    right      : -3px !important;
    width      : 7px !important;
    height     : 100% !important;
    cursor     : col-resize !important;
    z-index    : 9999 !important;
    background : transparent;
    transition : background 0.12s ease;
    flex-shrink: 0 !important;
}

/*
 * FIX: .crh giờ có "pointer-events: none" (xem column_resize.js) nên
 * không còn tự nhận :hover từ trình duyệt nữa — việc phát hiện "đang ở
 * đúng biên phải hay không" do JS đảm nhiệm (dựa theo HIT_MARGIN, tính
 * bằng getBoundingClientRect() nên luôn đúng vị trí thật kể cả khi app
 * bị scale/zoom) và JS toggle class .crh-hover tương ứng.
 */
.crh.crh-hover {
    background: linear-gradient(
        to right,
        transparent 2px,
        rgba(99, 102, 241, 0.65) 2px,
        rgba(99, 102, 241, 0.65) 5px,
        transparent 5px
    ) !important;
}

[data-theme="dark"] .crh.crh-hover {
    background: linear-gradient(
        to right,
        transparent 2px,
        rgba(129, 140, 248, 0.75) 2px,
        rgba(129, 140, 248, 0.75) 5px,
        transparent 5px
    ) !important;
}

/* ── Indicator line khi đang kéo ───────────────────────────── */
#crh-indicator {
    position       : fixed !important;
    top            : 0 !important;
    width          : 2px !important;
    height         : 100vh !important;
    background     : #6366f1 !important;
    z-index        : 2147483647 !important;
    pointer-events : none !important;
    opacity        : 0.85;
}

[data-theme="dark"] #crh-indicator {
    background: #818cf8 !important;
}


/* ════════════════════════════════════════════════════════════════
   SLIDE SIDEBAR – v1.0
   3 modes: pinned | unpinned | autohide
   Controlled by JS (SIDEBAR_JS) via classes on #sidebar-panel
   ════════════════════════════════════════════════════════════════ */

/* ── Base sidebar (tất cả modes) ─────────────────────────────── */
#sidebar-panel {
    position: fixed;
    top: var(--navbar-height);
    left: 0;
    bottom: 0;
    width: 300px;
    /* transition được set bởi JS */
}

/* ── PINNED mode: sidebar cố định, main content có margin ─────── */
#sidebar-panel.sb-pinned {
    transform: translateX(0);
    box-shadow: 4px 0 15px rgba(0,0,0,0.08);
    z-index: 1100;
}

/* ── FLOAT mode: sidebar hidden (closed) ─────────── */
#sidebar-panel.sb-float {
    z-index: 1200;
    box-shadow: 6px 0 24px rgba(0,0,0,0.18);
}
#sidebar-panel.sb-float.sb-open  { transform: translateX(0); }
#sidebar-panel.sb-float.sb-closed { transform: translateX(-100%); }

/* ── AUTOHIDE mode: sidebar ẩn, chỉ hiện khi hover edge ──────── */
#sidebar-panel.sb-autohide {
    z-index: 1200;
    box-shadow: 6px 0 24px rgba(0,0,0,0.22);
}
#sidebar-panel.sb-autohide.sb-open   { transform: translateX(0); }
#sidebar-panel.sb-autohide.sb-closed { transform: translateX(-100%); }

/* ── Overlay (unpinned mode – mờ nền khi sidebar mở) ─────────── */
#sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 1199;
    pointer-events: none;
    transition: background 0.28s ease;
}
#sidebar-overlay.sb-ov-visible {
    /* Chỉ block mouse events khi cần, background trong suốt */
    pointer-events: auto;
}

/* ── Edge trigger zone (autohide mode) ───────────────────────── */
#sidebar-edge-trigger {
    display: none;
    position: fixed;
    top: var(--navbar-height);
    left: 0;
    bottom: 0;
    width: 8px;
    z-index: 1201;
    cursor: pointer;
    background: linear-gradient(90deg, rgba(99,102,241,0.25) 0%, transparent 100%);
    transition: background 0.2s ease;
}
#sidebar-edge-trigger:hover {
    background: linear-gradient(90deg, rgba(99,102,241,0.5) 0%, transparent 100%);
}

/* ── Toggle tab (luôn hiển thị, nằm bên phải sidebar) ─────────── */
#sidebar-toggle-tab {
    position: absolute;
    top: 50%;
    right: -28px;
    transform: translateY(-50%);
    width: 28px;
    min-height: 48px;
    background: var(--primary-color, #4f46e5);
    color: white;
    border-radius: 0 8px 8px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 10;
    padding: 5px 3px;
    box-shadow: 3px 0 10px rgba(0,0,0,0.15);
    transition: background 0.2s ease, box-shadow 0.2s ease, right 0.28s cubic-bezier(0.4,0,0.2,1);
    user-select: none;
    gap: 3px;
}
#sidebar-toggle-tab i {
    font-size: 11px;
    transition: transform 0.3s ease;
}
#sidebar-toggle-tab:hover {
    background: var(--primary-dark, #3730a3);
    box-shadow: 4px 0 14px rgba(0,0,0,0.25);
}

/* Khi sidebar đóng (unpinned/autohide closed), tab vẫn hiện */
#sidebar-panel.sb-closed #sidebar-toggle-tab {
    right: -28px;  /* vẫn nhô ra ngoài */
}

/* Tooltip mode nhỏ trên tab */
#sidebar-toggle-tab[data-mode=pinned]   { background: #4f46e5; }
#sidebar-toggle-tab[data-mode=float]    { background: #0ea5e9; }
#sidebar-toggle-tab[data-mode=autohide] { background: #64748b; }

#sidebar-toggle-tab[data-mode=pinned]:hover   { background: #3730a3; }
#sidebar-toggle-tab[data-mode=float]:hover    { background: #0284c7; }
#sidebar-toggle-tab[data-mode=autohide]:hover { background: #475569; }

/* ── Dark mode overrides ─────────────────────────────────────── */
[data-theme=dark] #sidebar-toggle-tab[data-mode=pinned]   { background: #6366f1; }
[data-theme=dark] #sidebar-toggle-tab[data-mode=float]    { background: #38bdf8; }
[data-theme=dark] #sidebar-toggle-tab[data-mode=autohide] { background: #475569; }

/* ── Main content transition khi đổi mode ──────────────────────── */
#main-content-container {
    transition: margin-left 0.28s cubic-bezier(0.4,0,0.2,1);
}

/* z-index override for slide sidebar modes (beat .sidebar { z-index: 1100 !important }) */
#sidebar-panel.sb-float,
#sidebar-panel.sb-autohide {
    z-index: 1200 !important;
}
#sidebar-panel.sb-pinned {
    z-index: 1100 !important;
}
/* Ensure sidebar-container doesn't clip toggle tab */
#sidebar-container {
    overflow: visible !important;
    position: static !important;
}
/* ═══════════════════════════════════════════════════════════════
   ABOUT MODAL — README / Markdown content styling
═══════════════════════════════════════════════════════════════ */
#about-readme-content .markdown-content {
    font-size: 0.83rem;
    line-height: 1.75;
    color: var(--text-primary);
    word-break: break-word;
    overflow-x: hidden;
}
#about-readme-content .markdown-content h1 {
    font-size: 1.05rem;
    font-weight: 800;
    margin: 0 0 10px;
    padding-bottom: 6px;
    border-bottom: 2px solid var(--border-color);
    color: var(--text-primary);
}
#about-readme-content .markdown-content h2 {
    font-size: 0.9rem;
    font-weight: 700;
    margin: 18px 0 8px;
    padding: 6px 0 6px 10px;
    border-left: 3px solid #3b82f6;
    color: var(--text-primary);
    background: rgba(59,130,246,0.05);
    border-radius: 0 6px 6px 0;
}
#about-readme-content .markdown-content h3 {
    font-size: 0.82rem;
    font-weight: 700;
    margin: 14px 0 6px;
    color: #8b5cf6;
}
#about-readme-content .markdown-content h4 {
    font-size: 0.78rem;
    font-weight: 600;
    margin: 10px 0 4px;
    color: #10b981;
}
#about-readme-content .markdown-content p {
    margin: 0 0 8px;
}
#about-readme-content .markdown-content ul,
#about-readme-content .markdown-content ol {
    padding-left: 18px;
    margin: 4px 0 8px;
}
#about-readme-content .markdown-content li {
    margin-bottom: 3px;
}
/* Tables — clean, no pipe characters */
#about-readme-content .markdown-content table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
    margin: 8px 0 14px;
    table-layout: fixed;
    word-break: break-word;
}
#about-readme-content .markdown-content th {
    background: rgba(59,130,246,0.12);
    color: var(--text-primary);
    font-weight: 700;
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    text-align: left;
}
#about-readme-content .markdown-content td {
    padding: 5px 10px;
    border: 1px solid var(--border-color);
    vertical-align: top;
}
#about-readme-content .markdown-content tr:nth-child(even) td {
    background: rgba(99,102,241,0.04);
}
#about-readme-content .markdown-content tr:hover td {
    background: rgba(59,130,246,0.07);
}
/* Code blocks */
#about-readme-content .markdown-content code {
    font-size: 0.75rem;
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(99,102,241,0.12);
    color: #a78bfa;
    font-family: "Fira Code", "Consolas", monospace;
}
#about-readme-content .markdown-content pre {
    background: rgba(15,23,42,0.6);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 10px 14px;
    overflow-x: auto;
    margin: 6px 0 12px;
}
#about-readme-content .markdown-content pre code {
    background: none;
    color: #e2e8f0;
    padding: 0;
}
/* Blockquote (> notes) */
#about-readme-content .markdown-content blockquote {
    margin: 8px 0;
    padding: 6px 12px;
    border-left: 3px solid #f59e0b;
    background: rgba(245,158,11,0.06);
    border-radius: 0 8px 8px 0;
    color: var(--text-muted);
    font-size: 0.78rem;
}
/* Hr */
#about-readme-content .markdown-content hr {
    border: none;
    border-top: 1px solid var(--border-color);
    margin: 14px 0;
}
/* DB info section — no horizontal scroll */
#about-db-info-content {
    overflow-x: hidden;
}
/* Custom scrollbar for readme */

/* ═══════════════════════════════════════════════════════════════
   LARGE MODAL — Fixed 90vh height regardless of zoom / resize
   Applies to: about, admin, user-logs, layout-editor, batch-export
═══════════════════════════════════════════════════════════════ */

/* Shared rule: XL and LG modals that need fixed height */
#about-modal .modal-dialog,
#admin-modal .modal-dialog,
#user-logs-modal .modal-dialog,
#layout-editor-modal .modal-dialog,
#batch-export-modal .modal-dialog,
#asm-info-modal .modal-dialog {
    max-width: min(95vw, 1400px) !important;
    width: 95vw !important;
    margin: 120px auto 4px !important;
    height: calc(100vh - 128px) !important;
    max-height: calc(100vh - 128px) !important;
    /* FIX (2026-07-24): dbc.Modal(centered=True) adds Bootstrap class
       "modal-dialog-centered" = `display:flex; align-items:center;`. With
       that, .modal-content (a flex item) gets vertically CENTERED and
       sized to its own content instead of stretching to fill the fixed
       height above — so on tabs with less content the dialog box visibly
       shrinks, leaving a gap that reveals the page behind the modal
       (reported as "modal height doesn't expand to fill the available
       space"). Forcing block layout here cancels that centering; the
       .modal-content rule below then fills 100% of this height normally. */
    display: block !important;
}

#about-modal .modal-content,
#admin-modal .modal-content,
#user-logs-modal .modal-content,
#layout-editor-modal .modal-content,
#batch-export-modal .modal-content,
#asm-info-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Modal body flex-fills remaining space after header */
#about-modal .modal-body,
#admin-modal .modal-body,
#user-logs-modal .modal-body,
#layout-editor-modal .modal-body,
#batch-export-modal .modal-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow: hidden !important;
}

/* ASM Info modal: header + static toolbar (hint/toggle-btn) stay fixed,
   only the modal-body (entries list) scrolls vertically. */
#asm-info-modal .modal-header {
    flex-shrink: 0 !important;
}
#asm-info-modal > .modal-dialog > .modal-content > div:not(.modal-header):not(.modal-body) {
    flex-shrink: 0 !important;
}
#asm-info-modal .modal-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
}

/* The inner Row inside about-modal body must fill the body */
#about-modal .modal-body > .row {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: stretch !important;
}

/* Each column fills its parent height via flex stretch */
#about-modal .modal-body > .row > [class*="col-"] {
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
    min-height: 0 !important;
}

/* ── About modal col1 inner div fills exactly, flex column so spacer pushes footer down ── */
#about-modal .modal-body > .row > [class*="col-"]:first-child > div {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
}

/* ── Readme content in col3 — fills remaining height after heading ── */
#about-readme-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}
#about-readme-content > div:last-child {
    flex: 1;
    min-height: 0;
    overflow-y: auto !important;
    overflow-x: hidden !important;
}
/* ═══════════════════════════════════════════════════════════════
   CUSTOM SCROLLBAR — All modals (dark & light mode)
   Thin, rounded, semi-transparent — premium UI feel
═══════════════════════════════════════════════════════════════ */



/* batch-export: cap at 90vh body */
#batch-export-modal .modal-body {
    max-height: 82vh;
    overflow-y: auto !important;
}

/* user-logs — override the old calc-based heights to use flex */
#user-logs-modal .modal-content {
    height: 100% !important;
    max-height: 100% !important;
}
#user-logs-modal .modal-dialog {
    height: 96vh !important;
    max-height: 96vh !important;
    margin: 2vh auto !important;
}

/* Responsive: on small screens keep a tiny top margin */
@media (max-height: 600px) {
    #about-modal .modal-dialog,
    #admin-modal .modal-dialog,
    #user-logs-modal .modal-dialog,
    #layout-editor-modal .modal-dialog,
    #batch-export-modal .modal-dialog {
        margin: 100px auto 4px;
        height: calc(100vh - 108px);
        max-height: calc(100vh - 108px);
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   FIX: Modal nhỏ — base styles (không dùng !important trên width/max-width
   vì JS trong utils.py/SCALING_JS sẽ tính và inject đúng max-width theo
   scale của từng thiết bị/màn hình).
   CSS ở đây chỉ đặt fallback + height/overflow behavior.
   ═══════════════════════════════════════════════════════════════════════ */

/* Tất cả modal nhỏ: height auto, overflow tốt */
#change-pwd-modal .modal-dialog,
#login-modal .modal-dialog,
#confirm-delete-modal .modal-dialog,
#confirm-save-modal .modal-dialog,
#admin-confirm-modal .modal-dialog,
#admin-action-confirm-modal .modal-dialog,
#layout-editor-confirm-modal .modal-dialog,
#online-users-modal .modal-dialog,
#drilldown-modal .modal-dialog {
    height: auto;
    min-height: unset;
    margin-left: auto;
    margin-right: auto;
}

#change-pwd-modal .modal-content,
#login-modal .modal-content,
#confirm-delete-modal .modal-content,
#confirm-save-modal .modal-content,
#admin-confirm-modal .modal-content,
#admin-action-confirm-modal .modal-content,
#layout-editor-confirm-modal .modal-content,
#online-users-modal .modal-content,
#drilldown-modal .modal-content {
    height: auto;
    min-height: unset;
    overflow: hidden;
}

/* Admin modal khi ở login state — JS sẽ đặt max-width đúng,
   CSS chỉ đảm bảo height không bị stretch */
#admin-modal.admin-modal--login-state .modal-dialog {
    height: auto !important;
    min-height: unset !important;
    margin-left: auto !important;
    margin-right: auto !important;
}
#admin-modal.admin-modal--login-state .modal-content {
    height: auto !important;
    min-height: unset !important;
}

/* ── 21_report_cards.css ─────────────────────────────── */
/* ============================================================
   21_report_cards.css — Report Cards · Weekly/Monthly Comparison · Unified Card System
   Auto-refactored from custom.css
   ============================================================ */

/* === Weekly Report Comparison Card - Dark/Light Mode Support === */
.report-comparison-card {
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}
.report-comparison-label {
    color: #1e293b;
    font-size: 0.9rem;
}
.report-comparison-value {
    color: #1e293b;
    font-size: 1.5rem;
}
.report-comparison-arrow {
    color: #1e293b;
}
[data-theme="dark"] .report-comparison-card {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
}
[data-theme="dark"] .report-comparison-label {
    color: #e2e8f0;
}
[data-theme="dark"] .report-comparison-value {
    color: #f8fafc;
}
[data-theme="dark"] .report-comparison-arrow {
    color: #94a3b8;
}

/* ===================================================================
   MONTHLY REPORT - Dark/Light Mode Adaptive Classes
   =================================================================== */

/* monthly-card-text: adapts to theme */
.monthly-card-text {
    color: #1e293b;
}
[data-theme="dark"] .monthly-card-text {
    color: #e2e8f0 !important;
}

/* monthly-analysis-text: body text in analysis panels */
.monthly-analysis-text {
    color: #1e293b;
}
[data-theme="dark"] .monthly-analysis-text {
    color: #e2e8f0 !important;
}

/* monthly-analysis-card: analysis/recommendations panel */
.monthly-analysis-card {
    background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
}
[data-theme="dark"] .monthly-analysis-card {
    background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%) !important;
}
[data-theme="dark"] .monthly-analysis-card .monthly-card-text,
[data-theme="dark"] .monthly-analysis-card .monthly-analysis-text {
    color: #cbd5e1 !important;
}

/* monthly-trend-status-card: trend icon+% card */
.monthly-trend-status-card {
    background: #ffffff;
}
[data-theme="dark"] .monthly-trend-status-card {
    background: #1e293b !important;
}

/* monthly-trend-compare-card: 3-month comparison card */
.monthly-trend-compare-card {
    background: #ffffff;
}
[data-theme="dark"] .monthly-trend-compare-card {
    background: #1e293b !important;
}

/* monthly-top-card: top 3 issues/downtime cards */
.monthly-top-card {
    background: var(--card-bg, #ffffff);
}
[data-theme="dark"] .monthly-top-card {
    background: #1e293b !important;
}
[data-theme="dark"] .monthly-top-card .monthly-card-text {
    color: #e2e8f0 !important;
}

/* Section 2: chart + analysis col equal height */
.monthly-top-chart-col,
.monthly-top-analysis-col {
    display: flex;
    flex-direction: column;
}
.monthly-top-chart-col > div,
.monthly-top-analysis-col > div {
    flex: 1;
    display: flex;
    flex-direction: column;
}
.monthly-top-chart-col .chart-container {
    flex: 1;
    display: flex;
    flex-direction: column;
}
.monthly-top-chart-col .dcc_graph {
    flex: 1;
    min-height: 300px;
}

/* monthly-kpi-col equal height with analysis col */
.monthly-kpi-col,
.monthly-analysis-col {
    display: flex;
    flex-direction: column;
}
.monthly-kpi-col > *,
.monthly-analysis-col > * {
    flex: 1;
}
.monthly-analysis-col .monthly-analysis-card {
    height: 100% !important;
}

/* table-7d-part1-col: match pie chart container height */
#table-7d-part1-col {
    display: flex;
    flex-direction: column;
}
#table-7d-part1-col > div {
    flex: 1;
    display: flex;
    flex-direction: column;
}
#table-7d-part1-col .report-table-wrapper {
    flex: 1;
    overflow: hidden;
}

/* ===================================================================
   WEEKLY REPORT - Dark/Light Mode Adaptive Classes (Fix 1 & 2)
   =================================================================== */

/* weekly-card-text: general text in weekly analysis cards */
.weekly-card-text {
    color: #1e293b;
}
[data-theme="dark"] .weekly-card-text {
    color: #e2e8f0 !important;
}

/* weekly-trend-card: trend status card (➡️ / 📈 / 📉) */
.weekly-trend-card {
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}
[data-theme="dark"] .weekly-trend-card {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
}
[data-theme="dark"] .weekly-trend-card .weekly-card-text {
    color: #f1f5f9 !important;
}

/* weekly-analysis-card: analysis details card (blue bg) */
.weekly-analysis-card {
    background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
}
[data-theme="dark"] .weekly-analysis-card {
    background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%) !important;
}
[data-theme="dark"] .weekly-analysis-card .weekly-card-text {
    color: #cbd5e1 !important;
}

/* weekly-action-card: actions card (yellow bg) */
.weekly-action-card {
    background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%);
}
[data-theme="dark"] .weekly-action-card {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
}
[data-theme="dark"] .weekly-action-card .weekly-card-text {
    color: #e2e8f0 !important;
}

/* weekly-warning-card: top systems downtime card (amber bg) */
.weekly-warning-card {
    background: linear-gradient(135deg, #fff8e5 0%, #ffeacc 100%);
}
[data-theme="dark"] .weekly-warning-card {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
}
[data-theme="dark"] .weekly-warning-card .weekly-card-text {
    color: #e2e8f0 !important;
}

/* ===================================================================
   UNIFIED REPORT CARD SYSTEM - All report sections
   =================================================================== */

/* Base card: all report analysis/info cards share this */
.report-card {
    border-radius: 12px;
    padding: 14px;
    height: 100%;
    display: flex;
    flex-direction: column;
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: break-word;
}
.report-card * {
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: break-word;
    text-overflow: unset !important;
}
.report-card h4, .report-card h5, .report-card h6 {
    font-weight: 700;
    margin-bottom: 10px;
}

/* Neutral / Overview card */
.report-card--neutral {
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
    border: 2px solid #6c757d;
}
[data-theme="dark"] .report-card--neutral {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    border-color: #475569;
}

/* Blue / Analysis card */
.report-card--blue {
    background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
    border: 2px solid #2196f3;
}
[data-theme="dark"] .report-card--blue {
    background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
    border-color: #3b82f6;
}

/* Amber / Warning card */
.report-card--amber {
    background: linear-gradient(135deg, #fff8e5 0%, #ffeacc 100%);
    border: 2px solid #f59e0b;
}
[data-theme="dark"] .report-card--amber {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    border-color: #d97706;
}

/* Red / Alert card */
.report-card--red {
    background: linear-gradient(135deg, #ffe5e5 0%, #ffcccc 100%);
    border: 2px solid #dc3545;
}
[data-theme="dark"] .report-card--red {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    border-color: #ef4444;
}

/* Green / Good card */
.report-card--green {
    background: linear-gradient(135deg, #e5ffe5 0%, #ccffcc 100%);
    border: 2px solid #28a745;
}
[data-theme="dark"] .report-card--green {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    border-color: #22c55e;
}

/* Gold / Actions card */
.report-card--gold {
    background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%);
    border: 2px solid #ffc107;
}
[data-theme="dark"] .report-card--gold {
    background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
    border-color: #eab308;
}

/* Adaptive text inside all report-cards */
.report-card .rc-text {
    color: #1e293b;
    font-size: 0.9rem;
    line-height: 1.5;
}
[data-theme="dark"] .report-card .rc-text {
    color: #e2e8f0 !important;
}
.report-card .rc-label {
    color: #475569;
    font-size: 0.8rem;
}
[data-theme="dark"] .report-card .rc-label {
    color: #94a3b8 !important;
}
.report-card .rc-value {
    color: #1e293b;
    font-weight: 700;
}
[data-theme="dark"] .report-card .rc-value {
    color: #f1f5f9 !important;
}
.report-card .rc-title {
    color: #1e293b;
    font-weight: 700;
}
[data-theme="dark"] .report-card .rc-title {
    color: #f8fafc !important;
}

/* Weekly chart = table height using JS-free flex approach */
#weekly-chart-table-row {
    display: flex;
    align-items: stretch;
}
#weekly-chart-table-row > [class*="col"] {
    display: flex;
    flex-direction: column;
}
.weekly-chart-col {
    display: flex;
    flex-direction: column;
}
.weekly-chart-col .chart-container,
.weekly-table-col .chart-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    height: 100% !important;
    min-height: 400px;
}
.weekly-chart-col .dcc_graph {
    flex: 1;
    min-height: 400px;
    height: 100% !important;
}
/* Force Plotly to fill parent */
.weekly-chart-col .dcc_graph > div,
.weekly-chart-col .dcc_graph .js-plotly-plot,
.weekly-chart-col .dcc_graph .plot-container {
    height: 100% !important;
}
/* Table fills its column too */
.weekly-table-col {
    display: flex;
    flex-direction: column;
}
.weekly-table-col .chart-container {
    flex: 1;
    min-height: 400px;
}
.weekly-table-col .dash-table-container {
    flex: 1;
}

/* Monthly section 2: chart col = stacked cards col height */
.monthly-top-chart-col {
    display: flex;
    flex-direction: column;
}
.monthly-top-chart-col .chart-container {
    flex: 1;
    height: 100% !important;
    min-height: 450px;
    display: flex;
    flex-direction: column;
}
.monthly-top-chart-col .dcc_graph {
    flex: 1;
    height: 100% !important;
    min-height: 450px;
}
.monthly-top-chart-col .dcc_graph > div,
.monthly-top-chart-col .dcc_graph .js-plotly-plot,
.monthly-top-chart-col .dcc_graph .plot-container {
    height: 100% !important;
}
.monthly-top-analysis-col {
    display: flex;
    flex-direction: column;
    min-height: 450px;
}
.monthly-top-analysis-col > div {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* ── 22_report_grid.css ──────────────────────────────── */
/* ============================================================
   22_report_grid.css — Monthly & Weekly Report Grid Layouts
   Auto-refactored from custom.css
   ============================================================ */

/* =====================================================
   MONTHLY REPORT - EQUAL HEIGHT 2-COLUMN GRID
   Using CSS Grid: the ONLY reliable way to get 2 columns
   with identical height regardless of content.
   ===================================================== */

/* Outer grid: 2 equal columns, rows stretch to tallest cell */
.monthly-2col-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    align-items: stretch;    /* both cols = height of tallest */
    width: 100%;
}

/* Col1: flex column so chart + bottom cards stack vertically */
.monthly-grid-col1 {
    display: flex;
    flex-direction: column;
}

/* Col2: flex column so 2 cards split height equally */
.monthly-grid-col2 {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* Each card slot in col2 sizes to its OWN content (not forced 50/50 split) —
   so a card with more AI bullets grows taller instead of clipping/overflowing
   a fixed equal-share box. Overall col2 height (sum of both slots) still
   determines the row height via .monthly-2col-grid's align-items:stretch,
   which stretches col1 (chart) to match. */
.monthly-grid-col2 > .monthly-card-slot {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}

/* report-card inside slot: no forced height, grows to fit its own content */
.monthly-grid-col2 .monthly-card-slot > .report-card {
    flex: 0 0 auto;
    height: auto !important;
}

/* ---- Section 1 Col2: analysis_layout (card1+card2 top, card3+card4 grow below) ---- */
.monthly-analysis-layout {
    display: flex;
    flex-direction: column;
    height: auto;
    min-height: 100%;
}

.monthly-analysis-layout .monthly-col-cards {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.monthly-analysis-layout .monthly-col-cards > .monthly-card-slot {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}

.monthly-analysis-layout .monthly-col-cards .monthly-card-slot > .report-card {
    flex: 0 0 auto;
    height: auto !important;
}

/* =====================================================
   WEEKLY REPORT - 2-COLUMN CSS GRID
   Left col = chart (full height of grid row)
   Right col = 3 stacked rows: top-row + card + card
   ===================================================== */

/* Outer grid: 50/50 columns, both cells same height */
.weekly-2col-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    align-items: stretch;
    width: 100%;
    margin-bottom: 1rem;
}

/* Col 1: chart fills full grid-cell height */
.weekly-grid-col1 {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Make chart-container inside col1 fill 100% */
.weekly-grid-col1 .chart-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    height: 100% !important;
}

.weekly-grid-col1 .chart-container .js-plotly-plot,
.weekly-grid-col1 .chart-container .dcc-graph,
.weekly-grid-col1 .chart-container .dcc-graph > div {
    flex: 1;
    height: 100% !important;
    min-height: 420px;
}

/* Col 2: flex column, 3 rows stacked */
.weekly-grid-col2 {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-height: 0;
}

/* Top mini-row: trend + compare side by side, fixed/auto height */
.weekly-col2-top {
    display: flex;
    gap: 1rem;
    flex: 0 0 auto;
    align-items: stretch;
}

.weekly-col2-top > div {
    display: flex;
    flex-direction: column;
}

/* Card rows below top: each sizes to its OWN content (not forced equal split).
   Previously "flex:1; min-height:0" forced "Phân tích" and "Hành động" cards
   to always be the same height regardless of how many bullets AI/hardcode
   generated — causing the taller one to overflow past its rounded border
   instead of the card auto-expanding to contain all text. Now each row grows
   to fit its content; the grid's align-items:stretch on .weekly-2col-grid
   stretches col1 (chart) to match the resulting total height of col2. */
.weekly-col2-card {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}

.weekly-col2-card > .report-card {
    flex: 0 0 auto;
    height: auto !important;
}
/* ── Fix: Eye icon show/hide password state visibility ────────────────────── */
#new-user-pwd-eye-btn {
    opacity: 1 !important;
    transition: color 0.2s ease;
}
#new-user-pwd-eye-btn:hover {
    color: var(--primary-color) !important;
}
/* fa-eye = hide mode: muted; fa-eye-slash = show mode: active/bright */
#new-user-pwd-eye-icon.fa-eye {
    color: var(--text-secondary);
}
#new-user-pwd-eye-icon.fa-eye-slash {
    color: var(--primary-color) !important;
    opacity: 1 !important;
}

/* User list pwd toggle button: same treatment */
[id*="toggle-pwd-btn"] .fa-eye {
    color: var(--text-secondary);
}
[id*="toggle-pwd-btn"] .fa-eye-slash {
    color: var(--primary-color) !important;
}

/* ── Fix 2: New user role dropdown — force height = sm input (31px) ── */
/* Target every layer of react-select v1 inside the new-user-role-dropdown */
.new-user-role-dropdown,
.new-user-role-dropdown .Select,
.new-user-role-dropdown .Select-control,
.new-user-role-dropdown .Select-multi-value-wrapper,
.new-user-role-dropdown .Select--single {
    min-height: 31px !important;
    height: 31px !important;
    max-height: 31px !important;
}
.new-user-role-dropdown .Select-control {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    box-sizing: border-box !important;
}
.new-user-role-dropdown .Select-multi-value-wrapper {
    display: table-cell !important;
    vertical-align: middle !important;
    overflow: hidden !important;
}
.new-user-role-dropdown .Select-value,
.new-user-role-dropdown .Select-placeholder {
    height: 29px !important;
    line-height: 29px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
.new-user-role-dropdown .Select-input {
    height: 29px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
.new-user-role-dropdown .Select-arrow-zone {
    display: table-cell !important;
    vertical-align: middle !important;
    text-align: center !important;
    width: 25px !important;
    padding-top: 0 !important;
    padding-right: 5px !important;
}
.new-user-role-dropdown .Select-arrow {
    display: inline-block !important;
    border-color: #999 transparent transparent !important;
    border-style: solid !important;
    border-width: 5px 4px 2px !important;
    margin-top: 2px !important;
}
.new-user-role-dropdown .Select-value-label {
    line-height: 29px !important;
}
/* Make add-user form row a flex container so all children align at bottom */
#admin-main-users .row.mb-2 {
    align-items: flex-end !important;
}
/* Each col: flex column, push content to bottom */
#admin-main-users .row.mb-2 > [class*="col-"] {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
#admin-main-users .row.mb-2 > [class*="col-"] label {
    margin-bottom: 4px;
}
/* Nudge the dropdown wrapper up by 1px to align visually with sm inputs */
#admin-main-users .row.mb-2 .new-user-role-dropdown {
    margin-bottom: 1px !important;
}
/* Ensure inputs inside the form row are same height */
#admin-main-users .row.mb-2 .form-control,
#admin-main-users .row.mb-2 input.form-control {
    height: 31px !important;
    min-height: 31px !important;
    padding-top: 4px !important;
    padding-bottom: 4px !important;
}

/* ── Fix 5: Hover effects for action buttons in user list ── */
.user-action-col .btn {
    transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease !important;
}
.user-action-col .btn:hover:not(:disabled) {
    transform: translateY(-2px) !important;
    box-shadow: 0 4px 10px rgba(0,0,0,0.25) !important;
    filter: brightness(1.15) !important;
}
.user-action-col .btn:active:not(:disabled) {
    transform: translateY(0px) !important;
    box-shadow: 0 1px 4px rgba(0,0,0,0.2) !important;
    filter: brightness(0.95) !important;
}

/* ── Fix 4: Force logout button distinct color ── */
.btn-force-logout {
    background-color: #f59e0b !important;
    border-color: #d97706 !important;
    color: #1a1a1a !important;
}
.btn-force-logout:hover:not(:disabled) {
    background-color: #fbbf24 !important;
    border-color: #f59e0b !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   UNIFIED SCROLLBAR SYSTEM — consistent across entire application
   Sizes:  8px = main content & sidebar
           6px = dropdowns / multiselect / select menus
           4px = modals & small panels
   Colors: automatically adapt to dark/light mode via CSS variables
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Firefox (scrollbar-width + scrollbar-color) ─────────────────────── */
:root, [data-theme="light"] {
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
    scrollbar-width: thin;
}
[data-theme="dark"] {
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
    scrollbar-width: thin;
}

/* ── MAIN CONTENT (8px) ──────────────────────────────────────────────── */
#main-content-container::-webkit-scrollbar { width: 8px; }
#main-content-container::-webkit-scrollbar-track {
    background: var(--scrollbar-track);
    border-radius: 10px;
}
#main-content-container::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    border: 2px solid var(--scrollbar-track);
    transition: background 0.2s ease;
}
#main-content-container::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}

/* ── SIDEBAR (8px) ───────────────────────────────────────────────────── */
.sidebar::-webkit-scrollbar,
.sidebar-scrollable-section::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-track,
.sidebar-scrollable-section::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
}
.sidebar::-webkit-scrollbar-thumb,
.sidebar-scrollable-section::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: content-box;
    transition: background 0.2s ease;
}
.sidebar::-webkit-scrollbar-thumb:hover,
.sidebar-scrollable-section::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
    background-clip: content-box;
}

/* ── DROPDOWNS / SELECT MENUS (6px) ─────────────────────────────────── */
.Select-menu-outer::-webkit-scrollbar,
.Select-menu::-webkit-scrollbar,
.Select-multi-value-wrapper::-webkit-scrollbar,
.Select--multi .Select-control::-webkit-scrollbar,
.Select--multi .Select-multi-value-wrapper::-webkit-scrollbar { width: 6px; height: 6px; }

.Select-menu-outer::-webkit-scrollbar-track,
.Select-menu::-webkit-scrollbar-track,
.Select-multi-value-wrapper::-webkit-scrollbar-track,
.Select--multi .Select-control::-webkit-scrollbar-track,
.Select--multi .Select-multi-value-wrapper::-webkit-scrollbar-track {
    background: var(--scrollbar-track);
    border-radius: 10px;
}
.Select-menu-outer::-webkit-scrollbar-thumb,
.Select-menu::-webkit-scrollbar-thumb,
.Select-multi-value-wrapper::-webkit-scrollbar-thumb,
.Select--multi .Select-control::-webkit-scrollbar-thumb,
.Select--multi .Select-multi-value-wrapper::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    border: 1px solid var(--scrollbar-track);
    transition: background 0.2s ease;
}
.Select-menu-outer::-webkit-scrollbar-thumb:hover,
.Select-menu::-webkit-scrollbar-thumb:hover,
.Select-multi-value-wrapper::-webkit-scrollbar-thumb:hover,
.Select--multi .Select-control::-webkit-scrollbar-thumb:hover,
.Select--multi .Select-multi-value-wrapper::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}

/* ── USER LOGS TABLE (6px) ───────────────────────────────────────────── */
#user-logs-table .dash-spreadsheet-container::-webkit-scrollbar { width: 6px; height: 0; }
#user-logs-table .dash-spreadsheet-container::-webkit-scrollbar-track {
    background: var(--scrollbar-track);
    border-radius: 10px;
}
#user-logs-table .dash-spreadsheet-container::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    transition: background 0.2s ease;
}
#user-logs-table .dash-spreadsheet-container::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}

/* ── MODALS (4px) ────────────────────────────────────────────────────── */
#change-pwd-modal *::-webkit-scrollbar,
#login-modal *::-webkit-scrollbar,
#sync-logs-modal *::-webkit-scrollbar,
#online-users-modal *::-webkit-scrollbar,
#restart-confirm-modal *::-webkit-scrollbar,
#admin-confirm-modal *::-webkit-scrollbar,
#admin-action-confirm-modal *::-webkit-scrollbar,
#layout-confirm-modal *::-webkit-scrollbar,
#about-modal *::-webkit-scrollbar,
#admin-modal *::-webkit-scrollbar,
#user-logs-modal *::-webkit-scrollbar,
#layout-editor-modal *::-webkit-scrollbar,
#batch-export-modal *::-webkit-scrollbar { width: 4px; height: 4px; }

#change-pwd-modal *::-webkit-scrollbar-track,
#login-modal *::-webkit-scrollbar-track,
#sync-logs-modal *::-webkit-scrollbar-track,
#online-users-modal *::-webkit-scrollbar-track,
#restart-confirm-modal *::-webkit-scrollbar-track,
#admin-confirm-modal *::-webkit-scrollbar-track,
#admin-action-confirm-modal *::-webkit-scrollbar-track,
#layout-confirm-modal *::-webkit-scrollbar-track,
#about-modal *::-webkit-scrollbar-track,
#admin-modal *::-webkit-scrollbar-track,
#user-logs-modal *::-webkit-scrollbar-track,
#layout-editor-modal *::-webkit-scrollbar-track,
#batch-export-modal *::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
}
#change-pwd-modal *::-webkit-scrollbar-thumb,
#login-modal *::-webkit-scrollbar-thumb,
#sync-logs-modal *::-webkit-scrollbar-thumb,
#online-users-modal *::-webkit-scrollbar-thumb,
#restart-confirm-modal *::-webkit-scrollbar-thumb,
#admin-confirm-modal *::-webkit-scrollbar-thumb,
#admin-action-confirm-modal *::-webkit-scrollbar-thumb,
#layout-confirm-modal *::-webkit-scrollbar-thumb,
#about-modal *::-webkit-scrollbar-thumb,
#admin-modal *::-webkit-scrollbar-thumb,
#user-logs-modal *::-webkit-scrollbar-thumb,
#layout-editor-modal *::-webkit-scrollbar-thumb,
#batch-export-modal *::-webkit-scrollbar-thumb {
    background: rgba(100, 116, 139, 0.4);
    border-radius: 10px;
    transition: background 0.2s ease;
}
#change-pwd-modal *::-webkit-scrollbar-thumb:hover,
#login-modal *::-webkit-scrollbar-thumb:hover,
#sync-logs-modal *::-webkit-scrollbar-thumb:hover,
#online-users-modal *::-webkit-scrollbar-thumb:hover,
#restart-confirm-modal *::-webkit-scrollbar-thumb:hover,
#admin-confirm-modal *::-webkit-scrollbar-thumb:hover,
#admin-action-confirm-modal *::-webkit-scrollbar-thumb:hover,
#layout-confirm-modal *::-webkit-scrollbar-thumb:hover,
#about-modal *::-webkit-scrollbar-thumb:hover,
#admin-modal *::-webkit-scrollbar-thumb:hover,
#user-logs-modal *::-webkit-scrollbar-thumb:hover,
#layout-editor-modal *::-webkit-scrollbar-thumb:hover,
#batch-export-modal *::-webkit-scrollbar-thumb:hover {
    background: rgba(100, 116, 139, 0.7);
}

[data-theme="dark"] #change-pwd-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #login-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #sync-logs-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #online-users-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #restart-confirm-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #admin-confirm-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #admin-action-confirm-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #layout-confirm-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #about-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #admin-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #user-logs-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #layout-editor-modal *::-webkit-scrollbar-thumb,
[data-theme="dark"] #batch-export-modal *::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.25);
}
[data-theme="dark"] #change-pwd-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #login-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #sync-logs-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #online-users-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #restart-confirm-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #admin-confirm-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #admin-action-confirm-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #layout-confirm-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #about-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #admin-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #user-logs-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #layout-editor-modal *::-webkit-scrollbar-thumb:hover,
[data-theme="dark"] #batch-export-modal *::-webkit-scrollbar-thumb:hover {
    background: rgba(148, 163, 184, 0.55);
}

/* Corner */
#change-pwd-modal *::-webkit-scrollbar-corner,
#login-modal *::-webkit-scrollbar-corner,
#sync-logs-modal *::-webkit-scrollbar-corner,
#online-users-modal *::-webkit-scrollbar-corner,
#restart-confirm-modal *::-webkit-scrollbar-corner,
#admin-confirm-modal *::-webkit-scrollbar-corner,
#admin-action-confirm-modal *::-webkit-scrollbar-corner,
#layout-confirm-modal *::-webkit-scrollbar-corner,
#about-modal *::-webkit-scrollbar-corner,
#admin-modal *::-webkit-scrollbar-corner,
#user-logs-modal *::-webkit-scrollbar-corner,
#layout-editor-modal *::-webkit-scrollbar-corner,
#batch-export-modal *::-webkit-scrollbar-corner {
    background: transparent;
}

/* ── ABOUT README (4px) ──────────────────────────────────────────────── */
#about-readme-content::-webkit-scrollbar { width: 4px; }
#about-readme-content::-webkit-scrollbar-track { background: transparent; }
#about-readme-content::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    transition: background 0.2s ease;
}
#about-readme-content::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}

/* ── ADMIN SUB-TABS HORIZONTAL SCROLLBAR (4px height) ───────────────── */
#admin-main-tabs .tab-content .nav.nav-tabs::-webkit-scrollbar,
.admin-tabs-scrollable .tab-content .nav.nav-tabs::-webkit-scrollbar { height: 4px; }
#admin-main-tabs .tab-content .nav.nav-tabs::-webkit-scrollbar-track,
.admin-tabs-scrollable .tab-content .nav.nav-tabs::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
}
#admin-main-tabs .tab-content .nav.nav-tabs::-webkit-scrollbar-thumb,
.admin-tabs-scrollable .tab-content .nav.nav-tabs::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border-radius: 10px;
    transition: background 0.2s ease;
}
#admin-main-tabs .tab-content .nav.nav-tabs::-webkit-scrollbar-thumb:hover,
.admin-tabs-scrollable .tab-content .nav.nav-tabs::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
}

/* ── ALERT POPUP (6px) ───────────────────────────────────────────────── */
.alert-popup-content::-webkit-scrollbar,
.notification-popup::-webkit-scrollbar { width: 6px; }
.alert-popup-content::-webkit-scrollbar-track,
.notification-popup::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
}
.alert-popup-content::-webkit-scrollbar-thumb,
.notification-popup::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.4);
    border-radius: 10px;
    transition: background 0.2s ease;
}
.alert-popup-content::-webkit-scrollbar-thumb:hover,
.notification-popup::-webkit-scrollbar-thumb:hover {
    background: rgba(148, 163, 184, 0.7);
}

/* END UNIFIED SCROLLBAR SYSTEM */
/* ── MAX SESSIONS + SESSION COUNT FEATURES ─────────────────────────── */

/* New user form row - flex layout to fit all columns on one line */
.new-user-form-row {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    width: 100%;
    box-sizing: border-box;
}
.new-user-field {
    flex-shrink: 1;
    min-width: 0;
    box-sizing: border-box;
}
.new-user-field label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 11px;
    display: block;
    margin-bottom: 3px;
}

/* Max sessions column in user list */
.user-maxsessions-col {
    flex: 0 0 9%;
    max-width: 9%;
    overflow: visible !important;
}

/* Adjust other columns to make room for max sessions */
.user-info-col { flex: 0 0 11%; max-width: 11%; }
.user-display-col { flex: 0 0 9%; max-width: 9%; }
.user-pwd-col { flex: 0 0 9%; max-width: 9%; }
.user-email-col { flex: 0 0 12%; max-width: 12%; }
.user-timeout-col { flex: 0 0 5%; max-width: 5%; }
.user-role-col { flex: 0 0 9%; max-width: 9%; }
.user-enable-col { flex: 0 0 5%; max-width: 5%; }
.user-status-col { flex: 0 0 8%; max-width: 8%; }
.user-action-col { flex: 0 0 17%; max-width: 17%; }

/* Session count button (x/max) */
.session-count-btn {
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 1px 7px;
    cursor: pointer;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
    transition: all 0.15s ease;
    line-height: 1.4;
    min-width: 36px;
    text-align: center;
}
.session-count-btn:hover {
    border-color: var(--primary-color);
    background: rgba(99, 102, 241, 0.08);
    transform: scale(1.05);
}
.session-count-text {
    font-size: 11px;
    font-weight: 700;
}

/* Session detail item in session modal */
.session-detail-item {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    transition: border-color 0.15s ease;
}
.session-detail-item:hover {
    border-color: var(--primary-color);
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.1);
}
.session-index-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--primary-color);
    color: white;
    font-size: 10px;
    font-weight: 700;
    flex-shrink: 0;
}

/* Dark mode adjustments for sessions */
[data-theme="dark"] .session-count-btn {
    border-color: #475569;
    color: var(--text-primary);
}
[data-theme="dark"] .session-count-btn:hover {
    border-color: #818cf8;
    background: rgba(129, 140, 248, 0.1);
}
[data-theme="dark"] .session-detail-item {
    background: #1e293b;
    border-color: #334155;
}
[data-theme="dark"] .session-detail-item:hover {
    border-color: #818cf8;
}

/* Max sessions warning */
#new-user-max-sessions-warning {
    font-size: 10px;
    margin-top: 2px;
}

/* Session details modal list */
#session-details-list .session-detail-item {
    margin-bottom: 8px;
}

/* Responsive: shrink max sessions column on small screens instead of hiding */
@media (max-width: 700px) {
    .user-maxsessions-col { min-width: 60px !important; flex: 0 0 60px !important; }
}

/* Admin users footer: show the message area */
#admin-users-buttons {
    min-height: 20px;
}
#admin-users-buttons #add-user-message {
    font-size: 13px;
    font-weight: 500;
}

/* ── FORCE LOGOUT ALL SESSIONS BUTTON ───────────────────────────────── */
.btn-force-logout {
    white-space: nowrap;
    /* Match btn-sm sizing of neighbouring Save/Key/Trash buttons */
    font-size: 0.875rem !important;
    line-height: 1.5 !important;
    padding: 0.25rem 0.5rem !important;
    min-width: 30px;
}
.btn-force-logout-session {
    white-space: nowrap;
    min-width: unset;
    background-color: #dc3545 !important;
    border-color: #dc3545 !important;
    color: #fff !important;
}
.btn-force-logout-session:hover {
    background-color: #bb2d3b !important;
    border-color: #b02a37 !important;
}

/* ── SESSION DETAILS MODAL – IP code style ───────────────────────────── */
.session-ip-code {
    background: rgba(99,102,241,0.08);
    border-radius: 3px;
    padding: 1px 5px;
    color: var(--text-primary);
    font-family: monospace;
}
[data-theme="dark"] .session-ip-code {
    background: rgba(129,140,248,0.12);
    color: #c7d2fe;
}

/* ── ONLINE USERS MODAL – session chip ──────────────────────────────── */
.online-sess-chip {
    background: rgba(99,102,241,0.07);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 2px 8px;
    font-size: 11px;
}
.online-sess-index {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--primary-color);
    color: white;
    font-size: 9px;
    font-weight: 700;
    flex-shrink: 0;
}
[data-theme="dark"] .online-sess-chip {
    background: rgba(129,140,248,0.08);
    border-color: #334155;
}

/* ── SESSION COUNT BUTTON – at max capacity ──────────────────────────── */
.session-count-btn.at-max {
    border-color: #ef4444;
    animation: pulse-danger 1.5s infinite;
}
@keyframes pulse-danger {
    0%, 100% { box-shadow: 0 0 0 0px rgba(239,68,68,0.4); }
    50%       { box-shadow: 0 0 0 4px rgba(239,68,68,0.0); }
}
[data-theme="dark"] .session-count-btn.at-max {
    border-color: #f87171;
}

/* ── MAX SESSIONS RANGE WARNING – visible in dark mode ──────────────── */
#new-user-max-sessions-warning {
    color: #d97706 !important;
}
[data-theme="dark"] #new-user-max-sessions-warning {
    color: #fbbf24 !important;
}

/* ── LOGIN PAGE – max session reached message ───────────────────────── */
.login-max-session-msg {
    font-size: 13px;
    font-weight: 500;
    padding: 8px 12px;
    background: rgba(239,68,68,0.08);
    border: 1px solid rgba(239,68,68,0.25);
    border-radius: 6px;
    margin-top: 8px;
    line-height: 1.5;
}
[data-theme="dark"] .login-max-session-msg {
    background: rgba(239,68,68,0.12);
    border-color: rgba(239,68,68,0.3);
}


/* ═══════════════════════════════════════════════════════════════════════════
   SESSION DETAILS MODAL — single-row layout, dark/light mode
   ═══════════════════════════════════════════════════════════════════════════ */
.session-detail-item {
    background: var(--card-bg, #f8f9fa);
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    gap: 6px;
    flex-wrap: nowrap;
    overflow: hidden;
}
[data-theme="dark"] .session-detail-item {
    background: #1e293b;
    border-color: #334155;
}

.session-index-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--primary-color, #6366f1);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    flex-shrink: 0;
}

.session-info-icon {
    font-size: 12px !important;
    color: var(--text-muted, #6c757d);
}
.session-info-label {
    font-size: 13px;
    color: var(--text-muted, #6c757d);
}
.session-info-value {
    font-size: 13px;
    color: var(--text-primary, #212529);
}
[data-theme="dark"] .session-info-value {
    color: #e2e8f0;
}
[data-theme="dark"] .session-info-label,
[data-theme="dark"] .session-info-icon {
    color: #94a3b8;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ONLINE USERS MODAL — single-row layout, dark/light mode, proper colors
   ═══════════════════════════════════════════════════════════════════════════ */
.online-users-list {
    padding: 4px 0;
}
.online-user-item {
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-color, #e2e8f0);
    background: transparent;
}
.online-user-item:last-child {
    border-bottom: none;
}
[data-theme="dark"] .online-user-item {
    border-color: #334155;
    background: transparent;
}

.online-user-avatar {
    font-size: 18px;
    color: #22c55e;
}
.online-user-name {
    font-size: 15px;
    color: var(--text-primary, #212529);
}
[data-theme="dark"] .online-user-name {
    color: #f1f5f9;
}
.online-user-handle {
    font-size: 12px;
    color: var(--text-muted, #6c757d);
}
[data-theme="dark"] .online-user-handle {
    color: #94a3b8;
}
.online-duration-text {
    font-size: 13px;
    color: var(--text-muted, #6c757d);
    font-weight: 500;
}
[data-theme="dark"] .online-duration-text {
    color: #94a3b8;
}

/* Session sub-rows inside online user item */
.online-sess-row {
    padding: 4px 6px;
    border-radius: 6px;
    background: rgba(99,102,241,0.05);
    border: 1px solid var(--border-color, #dee2e6);
    font-size: 13px;
    gap: 6px;
}
[data-theme="dark"] .online-sess-row {
    background: rgba(99,102,241,0.08);
    border-color: #334155;
}
.online-sess-device {
    font-size: 13px;
    color: var(--text-primary, #212529);
}
[data-theme="dark"] .online-sess-device {
    color: #e2e8f0;
}
.online-info-muted {
    font-size: 12px;
    color: var(--text-muted, #6c757d);
}
[data-theme="dark"] .online-info-muted {
    color: #94a3b8;
}
.online-info-icon {
    font-size: 11px;
    color: var(--text-muted, #6c757d);
}
[data-theme="dark"] .online-info-icon {
    color: #94a3b8;
}
.online-ip-code {
    font-size: 12px;
    background: rgba(99,102,241,0.08);
    border-radius: 3px;
    padding: 1px 5px;
    color: var(--text-primary, #212529);
    font-family: monospace;
}
[data-theme="dark"] .online-ip-code {
    background: rgba(129,140,248,0.12);
    color: #c7d2fe;
}

/* ListGroupItem white background override for dark mode */
[data-theme="dark"] #online-users-modal .list-group-item {
    background-color: transparent !important;
    border-color: #334155 !important;
    color: #e2e8f0 !important;
}
[data-theme="dark"] #online-users-modal .modal-body {
    background: var(--card-bg, #1e293b);
}

/* ── Fix role dropdown menu z-index — shows above modal content ── */
.new-user-role-dropdown .Select-menu-outer,
.new-user-role-dropdown .VirtualizedSelectFocusedOption,
#new-user-role .Select-menu-outer {
    z-index: 99999 !important;
    position: absolute !important;
}
/* Dash dcc.Dropdown menu portal fix for admin modal */
#admin-modal #new-user-role .Select-menu-outer,
#admin-modal .new-user-role-dropdown .Select-menu-outer {
    z-index: 99999 !important;
}
/* Ensure the role field parent has z-index to create stacking context */
.new-user-field:has(#new-user-role),
.new-user-field:has(.new-user-role-dropdown) {
    z-index: 9999;
    position: relative;
}
/* Session detail modal — compact single row */
.session-detail-item {
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 6px;
    background: var(--card-bg, #f8f9fa);
    flex-wrap: nowrap !important;
    min-height: 36px;
}
[data-theme="dark"] .session-detail-item {
    background: #1e293b;
    border-color: #334155;
}
.session-index-badge {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted, #6c757d);
    min-width: 22px;
}

/* ══════════════════════════════════════════════════════════════════════
   FIX #3 & #4: Admin Users Tab - Scroll X/Y and Role Dropdown z-index
   ══════════════════════════════════════════════════════════════════════ */

/* Fix #3a: The entire users tab wrapper must not overflow horizontally */
#admin-main-users > div {
    overflow-x: hidden !important;
    overflow-y: visible !important;
    min-width: 0 !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
}

/* Fix #3b: Form row wraps instead of scrolling */
.new-user-form-row {
    flex-wrap: wrap !important;
    overflow: visible !important;
    max-width: 100% !important;
}

/* Fix #3c: Each field shrinks instead of overflowing */
.new-user-field {
    min-width: 0 !important;
    box-sizing: border-box !important;
    overflow: visible !important;
}

/* Fix #3d: Add user card container must be overflow visible for dropdown */
#admin-main-users .p-3.mb-3 {
    overflow: visible !important;
}

/* Fix #4: Role dropdown - use position:fixed for menu so it escapes overflow:hidden ancestor */
/* The key problem: #admin-modal .modal-body has overflow:hidden which clips dropdown menus */
/* Solution: Use a very high z-index + ensure parent creates correct stacking context */
.new-user-role-dropdown .Select-menu-outer,
#new-user-role .Select-menu-outer,
#admin-modal #new-user-role .Select-menu-outer,
#admin-modal .new-user-role-dropdown .Select-menu-outer {
    position: absolute !important;
    z-index: 999999 !important;
    top: 100% !important;
    left: 0 !important;
    right: 0 !important;
    min-width: 100% !important;
}

/* Fix #4b: All dropdowns inside user edit rows too */
#user-list-container .Select-menu-outer {
    position: absolute !important;
    z-index: 999999 !important;
}

/* Fix #4c: Raise stacking context on the users tab so dropdowns are on top */
#admin-modal .modal-body #admin-main-tabs > div > #admin-main-users {
    position: relative;
    z-index: 1;
}

/* Fix #4d: The Add User card block needs relative + z-index on self */
#admin-main-users .new-user-field:last-of-type,
#admin-main-users .new-user-field:has(#new-user-role),
#admin-main-users .new-user-field:has(.new-user-role-dropdown) {
    position: relative !important;
    z-index: 9999 !important;
    overflow: visible !important;
}

/* Fix #4e: User list edit role dropdowns */
.user-role-dropdown .Select-menu-outer,
#user-list-container .user-role-dropdown .Select-menu-outer,
#admin-modal .user-role-dropdown .Select-menu-outer {
    position: absolute !important;
    z-index: 999999 !important;
    min-width: 120px !important;
}

/* ══════════════════════════════════════════════════════════════════════
   USER LIST TABLE — unified column layout (fixes header misalignment
   and overlap at narrow viewports). Single source of truth: all prior
   scattered overrides are superseded by this block.
   ══════════════════════════════════════════════════════════════════════ */

/* Container: horizontal scroll when modal is too narrow */
#user-list-container {
    overflow-x: auto !important;
    overflow-y: auto !important;
}

/* Both header and data rows share identical flex layout */
.user-row,
.user-header-row {
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    /* ← identical horizontal padding so columns line up */
    padding: 8px 8px !important;
    gap: 4px !important;
    width: 100% !important;
    box-sizing: border-box !important;
    min-width: 0 !important;
}

/* Remove extra bottom-margin from header row */
.user-header-row {
    margin-bottom: 2px !important;
    background: transparent !important;
    border: none !important;
}

/* Every column can shrink; no overflow by default */
.user-col {
    flex-shrink: 1 !important;
    min-width: 0 !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

/* ── Column widths (flex-basis as % + min-width floor) ── */
.user-info-col        { flex: 1 1 11% !important; min-width: 80px  !important; }
.user-display-col     { flex: 1 1  9% !important; min-width: 70px  !important; }
.user-pwd-col         { flex: 1 1  9% !important; min-width: 70px  !important; overflow: visible !important; }
.user-email-col       { flex: 1 1 12% !important; min-width: 80px  !important; }
.user-timeout-col     { flex: 1 1  5% !important; min-width: 44px  !important; }
.user-maxsessions-col { flex: 1 1  8% !important; min-width: 72px  !important; overflow: visible !important; }
.user-role-col        { flex: 1 1  9% !important; min-width: 80px  !important; overflow: visible !important; }

/* Enable col: fixed, wide enough for the "ENABLE" header text */
.user-enable-col {
    flex: 0 0 46px !important;
    min-width: 46px !important;
    max-width: 52px !important;
    justify-content: center !important;
    text-align: center !important;
}

/* Status col: fixed width, header text right-aligned */
.user-status-col {
    flex: 0 0 70px !important;
    min-width: 60px !important;
    max-width: 80px !important;
}
/* Header text in status column wraps to 2 lines, right-aligned */
.user-status-col.user-header-text,
.user-header-row .user-status-col {
    text-align: right !important;
    line-height: 1.2 !important;
    white-space: normal !important;
    word-break: break-word !important;
}

/* Action col: fills remaining space, buttons pushed to the right */
.user-action-col {
    flex: 1 1 auto !important;
    min-width: 108px !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    display: flex !important;
    justify-content: flex-end !important;
    align-items: center !important;
    gap: 3px !important;
    text-align: right !important;
}
/* Header cell of action col: right-aligned text */
.user-header-row .user-action-col {
    justify-content: flex-end !important;
}

/* Inputs inside cols fill available width */
.user-col .user-edit-input,
.user-col input.form-control {
    min-width: 0 !important;
    width: 100% !important;
}

/* Role dropdown: overflow visible so the menu isn't clipped */
.user-role-col {
    position: relative !important;
    z-index: 100 !important;
}
.user-role-col:focus-within,
.user-role-col:has(.is-open) {
    z-index: 9999 !important;
}
.user-role-col .Select.is-open { z-index: 9999 !important; }
.user-role-col .Select-menu-outer,
.user-role-col .user-role-dropdown .Select-menu-outer,
#user-list-container .user-role-col .Select-menu-outer,
#admin-modal #user-list-container .user-role-dropdown .Select-menu-outer {
    position: absolute !important;
    z-index: 999999 !important;
    top: 100% !important;
    left: 0 !important;
    min-width: 120px !important;
    width: max-content !important;
}
.user-list-container > div { overflow: visible !important; }

/* ── Responsive: at narrow modal widths, hide low-priority cols ── */
@media (max-width: 860px) {
    .user-email-col   { display: none !important; }
}
@media (max-width: 720px) {
    .user-maxsessions-col { min-width: 60px !important; flex: 0 0 60px !important; }
    .user-timeout-col { min-width: 55px !important; flex: 0 0 55px !important; }
}
@media (max-width: 600px) {
    .user-status-col  { min-width: 65px !important; flex: 0 0 65px !important; }
    .user-header-text { font-size: 8px !important; }
    .user-row         { padding: 6px 4px !important; gap: 2px !important; }
    .user-action-col  { min-width: 80px !important; }
    .user-action-col .btn { padding: 0.2rem 0.3rem; font-size: 10px; }
}
/* Mobile: enable horizontal scroll on user list so all columns are visible */
@media (max-width: 720px) {
    #user-list-container {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
    }
    .user-list-container {
        min-width: 600px;
    }
}


/* Session logout message auto-fade after 4s */
#session-details-msg:not(:empty) {
    animation: sessionMsgFadeOut 0.6s ease-in 3.4s forwards;
}
@keyframes sessionMsgFadeOut {
    from { opacity: 1; }
    to   { opacity: 0; pointer-events: none; }
}

/* ── Copyright footer ─────────────────────────────────────────────────────── */
#copyright-footer {
    background: rgba(248, 250, 252, 0.88);   /* light mode default */
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-top: 1px solid rgba(0, 0, 0, 0.07);
}
#copyright-footer-text {
    font-size: 0.68rem;
    color: #64748b;                           /* text-muted light */
    opacity: 0.85;
    letter-spacing: 0.02em;
}
[data-theme="dark"] #copyright-footer {
    background: rgba(15, 23, 42, 0.88);      /* dark mode */
    border-top: 1px solid rgba(255, 255, 255, 0.055);
}
[data-theme="dark"] #copyright-footer-text {
    color: #94a3b8;                           /* text-muted dark */
    opacity: 0.7;
}
/* ═══════════════════════════════════════════════════════════════════════════
   UNIFIED MODAL BUTTON HOVER & ACTIVE EFFECTS
   Applied globally to ALL modals: btn-close (X), and all dbc.Button inside modals
   ═══════════════════════════════════════════════════════════════════════════ */

/* Base transition for ALL buttons inside any modal */
.modal .btn,
.modal .btn-close {
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1) !important;
    position: relative !important;
    overflow: hidden !important;
}

/* ── Close (X) button ─────────────────────────────────────────────────────── */
.modal .modal-header .btn-close {
    border-radius: 50% !important;
    width: 32px !important;
    height: 32px !important;
    opacity: 0.65 !important;
    background-color: transparent !important;
    border: 1.5px solid transparent !important;
    transition: all 0.18s ease !important;
}
.modal .modal-header .btn-close:hover {
    opacity: 1 !important;
    background-color: rgba(220, 53, 69, 0.12) !important;
    border-color: rgba(220, 53, 69, 0.35) !important;
    transform: rotate(90deg) scale(1.1) !important;
}
.modal .modal-header .btn-close:active {
    transform: rotate(90deg) scale(0.92) !important;
    background-color: rgba(220, 53, 69, 0.22) !important;
}

/* Dark mode X button */
[data-theme="dark"] .modal .modal-header .btn-close:hover {
    background-color: rgba(239, 68, 68, 0.18) !important;
    border-color: rgba(239, 68, 68, 0.4) !important;
}

/* ── Secondary / Cancel buttons ───────────────────────────────────────────── */
.modal .btn-secondary,
.modal .btn-outline-secondary,
.modal [class*="btn-secondary"] {
    transition: all 0.18s ease !important;
}
.modal .btn-secondary:hover,
.modal .btn-outline-secondary:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 12px rgba(108, 117, 125, 0.35) !important;
    filter: brightness(1.12) !important;
}
.modal .btn-secondary:active,
.modal .btn-outline-secondary:active {
    transform: translateY(0px) scale(0.97) !important;
    box-shadow: 0 1px 4px rgba(108, 117, 125, 0.25) !important;
    filter: brightness(0.95) !important;
    transition-duration: 0.08s !important;
}

/* ── Danger / Delete buttons ─────────────────────────────────────────────── */
.modal .btn-danger {
    transition: all 0.18s ease !important;
}
.modal .btn-danger:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 14px rgba(220, 53, 69, 0.45) !important;
    filter: brightness(1.1) !important;
}
.modal .btn-danger:active {
    transform: translateY(0px) scale(0.97) !important;
    box-shadow: 0 1px 4px rgba(220, 53, 69, 0.3) !important;
    transition-duration: 0.08s !important;
}

/* ── Primary buttons ─────────────────────────────────────────────────────── */
.modal .btn-primary {
    transition: all 0.18s ease !important;
}
.modal .btn-primary:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 14px rgba(13, 110, 253, 0.45) !important;
    filter: brightness(1.1) !important;
}
.modal .btn-primary:active {
    transform: translateY(0px) scale(0.97) !important;
    box-shadow: 0 1px 4px rgba(13, 110, 253, 0.3) !important;
    transition-duration: 0.08s !important;
}

/* ── Success / Info / Warning buttons ───────────────────────────────────── */
.modal .btn-success:hover { transform: translateY(-1px) !important; box-shadow: 0 4px 12px rgba(25, 135, 84, 0.4) !important; filter: brightness(1.1) !important; transition: all 0.18s ease !important; }
.modal .btn-success:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }
.modal .btn-info:hover    { transform: translateY(-1px) !important; box-shadow: 0 4px 12px rgba(13, 202, 240, 0.4) !important; filter: brightness(1.1) !important; transition: all 0.18s ease !important; }
.modal .btn-info:active   { transform: scale(0.97) !important; transition-duration: 0.08s !important; }
.modal .btn-warning:hover { transform: translateY(-1px) !important; box-shadow: 0 4px 12px rgba(255, 193, 7, 0.45) !important; filter: brightness(1.08) !important; transition: all 0.18s ease !important; }
.modal .btn-warning:active{ transform: scale(0.97) !important; transition-duration: 0.08s !important; }

/* ── Click ripple effect (pure CSS) ─────────────────────────────────────── */
.modal .btn::after {
    content: '' !important;
    position: absolute !important;
    inset: 0 !important;
    background: rgba(255, 255, 255, 0.18) !important;
    opacity: 0 !important;
    border-radius: inherit !important;
    transition: opacity 0.25s ease !important;
    pointer-events: none !important;
}
.modal .btn:active::after {
    opacity: 1 !important;
    transition: none !important;
}

/* Dark mode button tweaks */
[data-theme="dark"] .modal .btn-secondary:hover,
[data-theme="dark"] .modal .btn-outline-secondary:hover {
    background-color: #475569 !important;
    border-color: #64748b !important;
    color: #f1f5f9 !important;
}

/* ── Focus ring (accessibility) ──────────────────────────────────────────── */
.modal .btn:focus-visible {
    outline: 2px solid #06b6d4 !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.25) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   UNIFIED MODAL BUTTON INTERACTIONS — v10 comprehensive patch
   Covers: all btn variants, outline variants, btn-close (X), btn:disabled
   ═══════════════════════════════════════════════════════════════════════════ */

/* Base transition on ALL modal buttons (ensures smooth animation both ways) */
.modal .btn {
    transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease, background-color 0.18s ease, border-color 0.18s ease, opacity 0.18s ease !important;
    position: relative !important;
    overflow: hidden !important;
}

/* ── Success base transition (was missing) ───────────────────────────────── */
.modal .btn-success,
.modal .btn-outline-success {
    transition: all 0.18s ease !important;
}
.modal .btn-outline-success:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 12px rgba(25, 135, 84, 0.4) !important;
    filter: brightness(1.1) !important;
}
.modal .btn-outline-success:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }

/* ── Info base transition ────────────────────────────────────────────────── */
.modal .btn-info,
.modal .btn-outline-info {
    transition: all 0.18s ease !important;
}
.modal .btn-outline-info:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 12px rgba(13, 202, 240, 0.4) !important;
    filter: brightness(1.1) !important;
}
.modal .btn-outline-info:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }

/* ── Warning base transition ─────────────────────────────────────────────── */
.modal .btn-warning,
.modal .btn-outline-warning {
    transition: all 0.18s ease !important;
}
.modal .btn-outline-warning:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 12px rgba(255, 193, 7, 0.45) !important;
    filter: brightness(1.08) !important;
}
.modal .btn-outline-warning:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }

/* ── Outline primary/danger ──────────────────────────────────────────────── */
.modal .btn-outline-primary { transition: all 0.18s ease !important; }
.modal .btn-outline-primary:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 14px rgba(13, 110, 253, 0.4) !important;
}
.modal .btn-outline-primary:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }

.modal .btn-outline-danger { transition: all 0.18s ease !important; }
.modal .btn-outline-danger:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 14px rgba(220, 53, 69, 0.4) !important;
}
.modal .btn-outline-danger:active { transform: scale(0.97) !important; transition-duration: 0.08s !important; }

/* ── Link buttons (e.g. X close as link) ────────────────────────────────── */
.modal .btn-link {
    transition: all 0.18s ease !important;
}
.modal .btn-link:hover {
    transform: scale(1.15) !important;
    filter: brightness(1.3) !important;
}
.modal .btn-link:active {
    transform: scale(0.9) !important;
    transition-duration: 0.08s !important;
}

/* ── Bootstrap close button (X) ─────────────────────────────────────────── */
.modal .btn-close {
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.15s ease, box-shadow 0.18s ease !important;
    border-radius: 50% !important;
    padding: 0.4rem !important;
}
.modal .btn-close:hover {
    transform: rotate(90deg) scale(1.15) !important;
    opacity: 1 !important;
    background-color: rgba(220, 53, 69, 0.12) !important;
    box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.2) !important;
}
.modal .btn-close:active {
    transform: rotate(90deg) scale(0.9) !important;
    transition-duration: 0.08s !important;
}

/* ── Disabled state ──────────────────────────────────────────────────────── */
.modal .btn:disabled,
.modal .btn.disabled {
    transform: none !important;
    box-shadow: none !important;
    filter: none !important;
    cursor: not-allowed !important;
    opacity: 0.55 !important;
}
.modal .btn:disabled:hover,
.modal .btn.disabled:hover {
    transform: none !important;
    box-shadow: none !important;
}

/* ── Ripple click effect (reinforce with stronger flash) ─────────────────── */
.modal .btn:not(:disabled):active::after {
    opacity: 0.22 !important;
    transition: none !important;
}

/* ── Dark mode close button ──────────────────────────────────────────────── */
[data-theme="dark"] .modal .btn-close:hover {
    background-color: rgba(220, 53, 69, 0.25) !important;
    box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.3) !important;
}

/* ── Small/icon-only buttons (session force-logout, admin action icons) ──── */
.modal .btn-sm { transition: all 0.15s ease !important; }
.modal .btn-sm:hover { transform: translateY(-1px) scale(1.04) !important; }
.modal .btn-sm:active { transform: scale(0.93) !important; transition-duration: 0.07s !important; }

/* ── Yield incoming modal buttons (larger, more prominent) ───────────────── */
#yield-incoming-accept-btn,
#yield-incoming-reject-btn {
    min-width: 110px !important;
    font-weight: 600 !important;
}
#yield-incoming-accept-btn:hover {
    transform: translateY(-2px) !important;
    box-shadow: 0 6px 18px rgba(25, 135, 84, 0.5) !important;
}
#yield-incoming-reject-btn:hover {
    transform: translateY(-2px) !important;
    box-shadow: 0 6px 18px rgba(220, 53, 69, 0.5) !important;
}

/* ── Request Logout (yield request) buttons ──────────────────────────────── */
.yield-req-btn:hover {
    transform: translateY(-1px) scale(1.03) !important;
    box-shadow: 0 3px 10px rgba(255, 193, 7, 0.45) !important;
}

/* ============================================================
   PERF FIX: Disable report card animations & backdrop-filter
   on low-end machines.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .report-card,
    .report-card-header,
    .report-modal-overlay {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        animation: none !important;
    }
    .pulse-danger {
        animation: none !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf .report-card,
html.low-perf .report-card-header,
html.low-perf .report-modal-overlay {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    animation: none !important;
}
html.low-perf .pulse-danger {
    animation: none !important;
}

/* ── 23_maintenance_planning.css ─────────────────────── */
/* ============================================================
   23_maintenance_planning.css
   Styles for Planning, Details (Checklist) sub-tabs and Settings Modal
   Supports both Light and Dark mode via CSS variables
   ============================================================ */

/* ── Planning Table ───────────────────────────────────────── */
/* Scroll container riêng cho planning table — giống pattern tab chi tiết.
   Sticky thead hoạt động vì scroll root là .maint-planning-table-scroll,
   không phải #main-content-container ngoài cùng. */
/* Scroll container — copy exact pattern từ #maint-cl-modal-table */
/* ── Planning scroll container ──────────────────────────────────────────────
   max-height = viewport - navbar - sticky-header - title-bar - padding - form
   --plan-form-h: đo thực tế bởi maint_planning_form_height.js (default 0px).
   Khi form ẩn:  --plan-form-h = 0px   → offset tổng ~148px
   Khi form hiện: --plan-form-h = height form thực tế (thường 110-160px)
   JS đo sau mỗi lần Dash toggle style của #maint-plan-form-container, bao gồm
   cả margin-bottom 12px (.mb-3 = 1rem).
   ──────────────────────────────────────────────────────────────────────────── */
.maint-planning-content {
  /* Khởi tạo variable mặc định = 0px khi form ẩn */
  --plan-form-h: 0px;
  overflow: visible;
}
.maint-planning-table-scroll {
  overflow: auto !important;
  /* 96px = mb-2(~8px) + padding-top/bottom(~16px) + filter-bar(~68px) + extra(~4px)
     (title-bar ~40px đã bị xóa, padding p-3→p-2 giảm ~8px, mb-3→mb-2 giảm ~4px)
     --plan-form-h được JS cập nhật mỗi khi form toggle → không cần :has() */
  max-height: calc(var(--app-height, 100vh) - var(--navbar-height, 98px) - var(--sticky-header-height, 60px) - 96px - var(--plan-form-h, 0px));
  min-height: 200px;
}
/* Table: border-collapse:separate + overflow:visible — bắt buộc để sticky thead hoạt động */
.maint-planning-table {
  font-size: 0.875rem;
  border-collapse: separate !important;
  border-spacing: 0 !important;
  overflow: visible !important;
  width: 100%;
}
/* Sticky thead — hoạt động vì scroll root là .maint-planning-table-scroll */
.maint-planning-table-scroll .planning-thead-row th {
  position: sticky !important;
  top: 0 !important;
  z-index: 10 !important;
  white-space: nowrap;
}
.maint-planning-table thead th {
  background: var(--bs-light, #f8f9fa);
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 2px solid var(--bs-border-color, #dee2e6);
  white-space: nowrap;
}
.maint-planning-table tbody tr {
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  transition: background 0.15s;
}
.maint-planning-table tbody tr:hover {
  background: rgba(13, 110, 253, 0.05);
}
.maint-planning-table td {
  padding: 7px 10px;
  vertical-align: middle;
}

/* ── Add/Edit Form Card ───────────────────────────────────── */
.maint-add-form-card {
  border-left: 4px solid #4f46e5;
  border-radius: 8px;
  background: var(--bg-card, var(--bs-body-bg, #fff));
}

/* ── Checklist List ───────────────────────────────────────── */
/* Chi tiết Checklist sub-tab: dùng outer scroll của #tab-content-wrapper.
   Đảm bảo #maint-content-cl-details không bị overflow:hidden từ :has() rule
   → nội dung danh sách được scroll bình thường qua #tab-content-wrapper. */
#maint-content-cl-details {
  overflow: visible;
}

/* ── Checklist List — outer scroll handled by #tab-content-wrapper ──────────*/
.maint-cl-controls-bar {
  padding: 4px 4px;
}

.maint-checklist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.maint-checklist-list-item {
  background: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 8px;
  padding: 10px 14px;
  cursor: pointer;
  transition: box-shadow 0.15s, border-color 0.15s, background 0.15s;
  border-left: 4px solid transparent;   /* coloured left accent per status */
}
.maint-checklist-list-item:hover {
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
  border-color: #0d6efd;
  border-left-color: inherit;
}

/* ── Status-coloured card backgrounds ── */
/* Pending / Not Started → cool slate tint */
.maint-cl-status-pending {
  background: rgba(100, 116, 139, 0.08) !important;   /* slate-500 @8% */
  border-left-color: #64748b !important;
}
.maint-cl-status-pending:hover {
  background: rgba(100, 116, 139, 0.14) !important;
  border-color: #64748b !important;
}

/* In-Progress → warm amber tint */
.maint-cl-status-inprogress {
  background: rgba(245, 158, 11, 0.08) !important;    /* amber-500 @8% */
  border-left-color: #f59e0b !important;
}
.maint-cl-status-inprogress:hover {
  background: rgba(245, 158, 11, 0.14) !important;
  border-color: #f59e0b !important;
}

/* Done → fresh emerald tint */
.maint-cl-status-done {
  background: rgba(16, 185, 129, 0.08) !important;    /* emerald-500 @8% */
  border-left-color: #10b981 !important;
}
.maint-cl-status-done:hover {
  background: rgba(16, 185, 129, 0.14) !important;
  border-color: #10b981 !important;
}

/* ── Dark mode variants (slightly more opaque for contrast) ── */
[data-theme="dark"] .maint-cl-status-pending,
body.dark-mode      .maint-cl-status-pending {
  background: rgba(100, 116, 139, 0.15) !important;
  border-left-color: #94a3b8 !important;
}
[data-theme="dark"] .maint-cl-status-pending:hover,
body.dark-mode      .maint-cl-status-pending:hover {
  background: rgba(100, 116, 139, 0.24) !important;
  border-color: #94a3b8 !important;
}

[data-theme="dark"] .maint-cl-status-inprogress,
body.dark-mode      .maint-cl-status-inprogress {
  background: rgba(245, 158, 11, 0.13) !important;
  border-left-color: #fbbf24 !important;
}
[data-theme="dark"] .maint-cl-status-inprogress:hover,
body.dark-mode      .maint-cl-status-inprogress:hover {
  background: rgba(245, 158, 11, 0.22) !important;
  border-color: #fbbf24 !important;
}

[data-theme="dark"] .maint-cl-status-done,
body.dark-mode      .maint-cl-status-done {
  background: rgba(16, 185, 129, 0.13) !important;
  border-left-color: #34d399 !important;
}
[data-theme="dark"] .maint-cl-status-done:hover,
body.dark-mode      .maint-cl-status-done:hover {
  background: rgba(16, 185, 129, 0.22) !important;
  border-color: #34d399 !important;
}

/* ── Checklist Detail Table ───────────────────────────────── */
.maint-cl-detail-table {
  font-size: 0.82rem;
  white-space: nowrap;
}
.maint-cl-detail-table th {
  font-size: 0.78rem;
  background: var(--bs-light, #f8f9fa);
  font-weight: 600;
  padding: 6px 8px;
}
/* Generic th sticky only for non-modal table contexts */
.maint-cl-detail-table:not(#maint-cl-modal-table *) th {
  position: sticky;
  top: 0;
  z-index: 1;
}
.maint-cl-detail-table td {
  padding: 5px 8px;
  vertical-align: middle;
}
.maint-cl-dropdown {
  font-size: 0.8rem !important;
  min-width: 80px;
}
.maint-cl-dropdown .Select-control {
  height: 28px !important;
  min-height: 28px !important;
}


/* ── Checklist Summary Box ────────────────────────────────── */
.maint-cl-summary {
  background: rgba(13, 110, 253, 0.06);
  border: 1px solid rgba(13, 110, 253, 0.2);
  font-size: 0.875rem;
}

/* ── Area Tree Table ──────────────────────────────────────── */
.maint-area-tree-table {
  font-size: 0.85rem;
}
.maint-area-tree-header th {
  background: var(--bs-light, #f8f9fa);
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 2px solid var(--bs-border-color, #dee2e6);
}

/* ── Settings Modal ───────────────────────────────────────── */
/* max-height được set bởi JS (applyAutoHeightXlModalStyle) — KHÔNG hardcode vh ở đây */
#maint-settings-modal .modal-dialog {
  max-width: 85vw;
}
#maint-settings-modal .modal-body {
  padding: 0;
  /* overflow được kiểm soát bởi 18_modals.css (hidden + flex column) */
}
/* Dash inject thêm 1 wrapper div ẩn danh giữa tab-pane và div.p-2
   Chain thực tế: tab-pane.active > div(ẩn danh) > div.p-2 > .maint-settings-table-wrap
   scrollable=False: flex:0 1 auto để shrink-to-fit, max-height giới hạn bởi modal */
#maint-settings-modal-body > .tab-content > .tab-pane.active > div,
#maint-settings-modal-body > .tab-content > .tab-pane.active > div > div {
  display: flex !important;
  flex-direction: column !important;
  flex: 0 1 auto !important;
  min-height: 0 !important;
  overflow: hidden !important;
  padding: 0 !important;
}
/* div.p-2 là Dash content wrapper — giữ padding nhưng vẫn flex column */
#maint-settings-modal-body > .tab-content > .tab-pane.active > div > div.p-2 {
  padding: 8px !important;
}

/* ── Planning Filter bar ──────────────────────────────────── */
#maint-planning-filter,
#maint-details-filter {
  background: rgba(248, 249, 250, 0.95);
  padding: 0;
}

/* Vertical filter rows: label left, dropdown right */
#maint-planning-filter .row,
#maint-details-filter .row {
  flex-wrap: nowrap;
}
#maint-planning-filter .row > [class*="col-"],
#maint-details-filter .row > [class*="col-"] {
  min-width: 0;
}
#maint-planning-filter .report-filter-dropdown,
#maint-details-filter .report-filter-dropdown {
  width: 100%;
  font-size: 0.82rem;
}
#maint-planning-filter .report-filter-dropdown .Select-control,
#maint-details-filter .report-filter-dropdown .Select-control {
  min-height: 30px;
  height: 30px;
}

/* ── Dark mode overrides ──────────────────────────────────── */
body.dark-mode .maint-planning-table thead th,
body.dark-mode .maint-area-tree-header th {
  background: #2a2a2a;
  color: #e0e0e0;
  border-color: #444;
}
body.dark-mode .maint-planning-table tbody tr:hover {
  background: rgba(255, 255, 255, 0.05);
}
body.dark-mode .maint-planning-table tbody tr,
body.dark-mode .maint-planning-table td {
  border-color: #444;
  color: #e0e0e0;
}
body.dark-mode .maint-add-form-card {
  background: #1e1e1e;
  border-color: #3a7bd5;
}
/* Only apply dark bg to cards without a status class */
body.dark-mode .maint-checklist-list-item:not(.maint-cl-status-pending):not(.maint-cl-status-inprogress):not(.maint-cl-status-done) {
  background: #1e2130 !important;
  border-color: #3a3f50 !important;
  color: #c9d1d9 !important;
}
body.dark-mode .maint-checklist-list-item:not(.maint-cl-status-pending):not(.maint-cl-status-inprogress):not(.maint-cl-status-done):hover {
  background: #232840 !important;
  border-color: #3a7bd5 !important;
}
body.dark-mode .maint-cl-detail-table th {
  background: #2a2a2a;
  color: #e0e0e0;
}
body.dark-mode .maint-cl-detail-table td {
  color: #e0e0e0;
  border-color: #444;
}
body.dark-mode .maint-cl-summary {
  background: rgba(58, 123, 213, 0.12);
  border-color: rgba(58, 123, 213, 0.3);
}
body.dark-mode #maint-planning-filter,
body.dark-mode #maint-details-filter {
  background: rgba(30, 30, 30, 0.95);
}

/* Fix: Details tab "Danh sách Checklist" title visible in dark mode */
body.dark-mode .maint-details-content .fw-bold {
  color: #e2e8f0 !important;
}
[data-theme="dark"] .maint-details-content .fw-bold {
  color: #e2e8f0 !important;
}

/* Locked checklist item */
.maint-cl-item-locked {
  cursor: not-allowed !important;
}
.maint-cl-item-locked:hover {
  box-shadow: none !important;
  border-color: #e74c3c !important;
}
body.dark-mode .maint-cl-item-locked:hover {
  border-color: #e74c3c !important;
}

/* ═══════════════════════════════════════════════════════════
   MAINTENANCE SETTINGS — Custom Table (dark/light compatible)
   ═══════════════════════════════════════════════════════════ */

.maint-settings-table-wrap {
  overflow-y: auto;
  overflow-x: hidden;
  /* flex: 1 để fill phần còn lại của tab-pane sau toolbar + msg + pag */
  flex: 1 1 auto;
  /* min-height: 0 BẮT BUỘC — không có nó flex item sẽ expand vô hạn thay vì scroll */
  min-height: 0;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 6px;
}

.maint-settings-table {
  border-collapse: separate !important;
  border-spacing: 0 !important;
  font-size: 0.85rem;
}

.maint-settings-thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: var(--bs-primary, #4f46e5);
  color: #fff;
  padding: 8px 10px;
  font-weight: 600;
  border: none;
  text-align: left;
}

.maint-settings-row td {
  padding: 4px 6px;
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  vertical-align: middle;
}

/* Base (app này luôn hiển thị theme tối trong modal Settings — đổi nền dòng
   chẵn sang lớp phủ sáng nhẹ trên nền tối thay vì giả định nền sáng, để
   khớp với màu chữ sáng cố định ở .maint-settings-cell phía dưới). */
.maint-settings-row:nth-child(even) {
  background-color: rgba(255,255,255,0.04);
}
.maint-settings-row:hover {
  background-color: rgba(79, 70, 229, 0.06);
}

/* Dark mode */
[data-bs-theme="dark"] .maint-settings-row:nth-child(even),
.dark-mode .maint-settings-row:nth-child(even),
[data-theme="dark"] .maint-settings-row:nth-child(even) {
  background-color: rgba(255,255,255,0.04);
}
[data-bs-theme="dark"] .maint-settings-row:hover,
.dark-mode .maint-settings-row:hover,
[data-theme="dark"] .maint-settings-row:hover {
  background-color: rgba(79, 70, 229, 0.15);
}
[data-bs-theme="dark"] .maint-settings-table-wrap,
.dark-mode .maint-settings-table-wrap,
[data-theme="dark"] .maint-settings-table-wrap {
  border-color: rgba(255,255,255,0.12);
}
[data-bs-theme="dark"] .maint-settings-row td,
.dark-mode .maint-settings-row td,
[data-theme="dark"] .maint-settings-row td {
  border-color: rgba(255,255,255,0.08);
  color: var(--bs-body-color, #e2e8f0);
}

/* ================================================================
   PERF FIX: input/textarea/cell styles hoàn toàn bằng CSS vars.
   Không cần JS tính màu per-cell → giảm hàng chục nghìn JS ops
   khi render bảng 4000+ dòng.
   ================================================================ */

/* Editable inputs inside table */
.maint-settings-input {
  width: 100%;
  height: 28px;
  padding: 3px 7px;
  border-radius: 4px;
  font-size: 0.84rem;
  font-family: inherit;
  /* Màu tự động theo theme qua CSS variables */
  background: var(--bs-body-bg, #ffffff);
  color: var(--bs-body-color, #1e293b);
  border: 1px solid var(--bs-border-color, rgba(0,0,0,0.15));
  box-sizing: border-box;
}

/* ================================================================
   Custom Component Combo (tab Area) — thay thế hoàn toàn <select> gốc
   của trình duyệt để kiểm soát được height/font/dark-mode của dropdown,
   thứ mà popup native của <select> không cho phép chỉnh chính xác.
   ================================================================ */
.maint-combo-trigger {
  width: 100%;
  height: 28px;
  padding: 3px 7px;
  border-radius: 4px;
  font-size: 0.84rem;
  font-family: inherit;
  background: var(--bs-body-bg, #ffffff);
  color: var(--bs-body-color, #1e293b);
  border: 1px solid var(--bs-border-color, rgba(0,0,0,0.15));
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  cursor: pointer;
  text-align: left;
}
.maint-combo-trigger:hover { border-color: rgba(99,102,241,0.5); }
.maint-combo-trigger:focus-visible { outline: 2px solid #6366f1; outline-offset: 1px; }
.maint-combo-trigger-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.maint-combo-trigger-label.is-placeholder { color: var(--bs-secondary-color, #94a3b8); }
.maint-combo-caret { font-size: 0.62rem; opacity: 0.6; flex-shrink: 0; }

[data-bs-theme="dark"] .maint-combo-trigger,
.dark-mode .maint-combo-trigger,
[data-theme="dark"] .maint-combo-trigger {
  background: #1e293b;
  color: #e2e8f0;
  border-color: rgba(255,255,255,0.15);
}

/* Panel nổi — append vào <body>, position:fixed nên luôn nổi trên modal */
.maint-combo-panel {
  position: fixed;
  z-index: 3000;
  background: #ffffff;
  color: #1e293b;
  border: 1px solid rgba(0,0,0,0.15);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
  max-height: 240px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
[data-bs-theme="dark"] .maint-combo-panel,
.dark-mode .maint-combo-panel,
[data-theme="dark"] .maint-combo-panel {
  background: #1e293b;
  color: #e2e8f0;
  border-color: rgba(255,255,255,0.18);
  box-shadow: 0 8px 24px rgba(0,0,0,0.55);
}
.maint-combo-search-wrap {
  padding: 6px;
  border-bottom: 1px solid rgba(0,0,0,0.1);
  flex-shrink: 0;
}
[data-bs-theme="dark"] .maint-combo-search-wrap,
.dark-mode .maint-combo-search-wrap,
[data-theme="dark"] .maint-combo-search-wrap {
  border-bottom-color: rgba(255,255,255,0.1);
}
.maint-combo-search {
  width: 100%;
  height: 26px;
  padding: 2px 8px;
  font-size: 0.78rem;
  border-radius: 4px;
  border: 1px solid var(--bs-border-color, rgba(0,0,0,0.15));
  background: var(--bs-body-bg, #ffffff);
  color: var(--bs-body-color, #1e293b);
  box-sizing: border-box;
}
[data-bs-theme="dark"] .maint-combo-search,
.dark-mode .maint-combo-search,
[data-theme="dark"] .maint-combo-search {
  background: #0f172a;
  color: #e2e8f0;
  border-color: rgba(255,255,255,0.15);
}
.maint-combo-list { overflow-y: auto; padding: 4px 0; }
.maint-combo-item {
  padding: 5px 10px;
  font-size: 0.78rem;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.maint-combo-item:hover { background: rgba(99, 102, 241, 0.14); }
.maint-combo-item.active { background: rgba(99, 102, 241, 0.2); font-weight: 600; }
.maint-combo-item-blank { font-style: italic; opacity: 0.8; }
.maint-combo-empty { padding: 10px; font-size: 0.78rem; text-align: center; opacity: 0.6; }

/* Textarea for detail_text */
.maint-settings-textarea {
  width: 100%;
  min-height: 56px;
  padding: 3px 7px;
  border-radius: 4px;
  font-size: 0.84rem;
  font-family: inherit;
  resize: vertical;
  line-height: 1.4;
  white-space: pre-wrap;
  background: var(--bs-body-bg, #ffffff);
  color: var(--bs-body-color, #1e293b);
  border: 1px solid var(--bs-border-color, rgba(0,0,0,0.15));
  box-sizing: border-box;
}

/* Pre tag for readonly multiline display */
.maint-settings-pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  font-family: inherit;
  font-size: 0.84rem;
  background: transparent;
  border: none;
  padding: 0;
  color: var(--bs-body-color, #1e293b);
}

/* Cell base styles. FIX THẬT SỰ: --bs-body-color đã được Bootstrap định
   nghĩa sẵn ở :root (thường là màu tối, VD #212529) — nên var(--bs-body-color, fallback)
   KHÔNG BAO GIỜ dùng tới fallback (fallback chỉ áp dụng khi biến chưa được
   định nghĩa, không phải khi giá trị "không hợp"). Set CỨNG màu sáng, bỏ
   hẳn var(), để chắc chắn chữ luôn đọc được trên nền tối của modal này. */
.maint-settings-cell {
  font-size: 0.84rem;
  padding: 4px 7px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  color: #e2e8f0 !important;
  vertical-align: middle;
}

/* PERF: hover highlight dùng CSS class + event delegation.
   Thay thế 8000+ JS mouseenter/mouseleave listeners per-row.
   1 listener trên tbody xử lý toàn bộ. */
.maint-settings-row {
  /* No transition on all rows — causes browser to evaluate transition on every
     scroll tick across all rendered rows, even in virtual scroll. */
}
.maint-settings-row.maint-row-hover {
  background-color: rgba(79, 70, 229, 0.07) !important;
}
/* Dark mode */
[data-bs-theme=dark] .maint-settings-input,
.dark-mode .maint-settings-input,
[data-theme=dark] .maint-settings-input,
[data-bs-theme=dark] .maint-settings-textarea,
.dark-mode .maint-settings-textarea,
[data-theme=dark] .maint-settings-textarea {
  background: #1e293b;
  color: #e2e8f0;
  border-color: rgba(255,255,255,0.15);
}
[data-bs-theme=dark] .maint-settings-pre,
.dark-mode .maint-settings-pre,
[data-theme=dark] .maint-settings-pre {
  color: #e2e8f0;
}
[data-bs-theme=dark] .maint-settings-cell,
.dark-mode .maint-settings-cell,
[data-theme=dark] .maint-settings-cell {
  border-color: rgba(255,255,255,0.08);
  color: #e2e8f0;
}
[data-bs-theme=dark] .maint-settings-row.maint-row-hover,
.dark-mode .maint-settings-row.maint-row-hover,
[data-theme=dark] .maint-settings-row.maint-row-hover {
  background-color: rgba(99, 102, 241, 0.15) !important;
}

/* Empty/loading row in table */
.maint-settings-empty-cell {
  text-align: center;
  padding: 16px;
  color: var(--bs-secondary-color, #64748b);
}
[data-bs-theme="dark"] .maint-settings-empty-cell,
.dark-mode .maint-settings-empty-cell,
[data-theme="dark"] .maint-settings-empty-cell {
  color: #94a3b8;
}

/* ── Fix #5: Upload progress bar ── */
.maint-progress-wrap {
  height: 18px;
  background: rgba(128,128,128,0.2);
  border-radius: 9px;
  overflow: hidden;
  display: inline-block;
  width: 220px;
  vertical-align: middle;
}
.maint-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, #4f46e5, #7c3aed);
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: width 0.2s ease;
  min-width: 28px;
}
.maint-progress-bar span {
  color: #fff;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1;
}

/* ═══════════════════════════════════════════════════════════
   NEW: Planning table — purple header + new column classes
   ═══════════════════════════════════════════════════════════ */

/* ── Planning sticky: form container + thead ──────────────── */
/* Form container: sticky, background phủ nội dung bên dưới */
#maint-plan-form-container {
  background: var(--bs-body-bg, #fff);
  padding-top: 4px;
  padding-bottom: 2px;
}
[data-theme="dark"] #maint-plan-form-container {
  background: var(--bg-main, #0f1117);
}
body.dark-mode #maint-plan-form-container {
  background: var(--bg-main, #0f1117);
}

.planning-thead-row th {
  background: #4f46e5;
  color: #fff !important;
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 2px solid rgba(255,255,255,0.15);
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
.planning-row-filled td { background: rgba(79,70,229,0.04); }
.planning-row-empty  td { color: var(--bs-secondary-color, #6c757d); }
.planning-cell-month  { font-size: 0.78rem; white-space: nowrap; }
.planning-cell-weekday{ font-weight: 600; }
.planning-cell-day    { font-weight: 600; }
.planning-cell-time   { font-weight: 600; color: #4f46e5; white-space: nowrap; }

/* Planning title — readable in dark mode */
.planning-title { color: var(--text-primary, var(--bs-body-color, #212529)); }

/* Card header visible in dark mode */
.maint-add-form-card .card-header {
  background: var(--bg-card, var(--bs-body-bg, #fff));
  border-bottom: 1px solid var(--border-color, var(--bs-border-color, #dee2e6));
  color: var(--text-primary, var(--bs-body-color, #212529));
}

/* Form 1-line layout */
.plan-form-field { display: flex; flex-direction: column; }

/* DatePicker inside planning form — match sidebar style */
.planning-datepicker-wrap .SingleDatePicker,
.planning-datepicker-wrap .SingleDatePickerInput {
  width: 100%; border: none; background: transparent;
}
.planning-datepicker-wrap .DateInput { width: 100%; background: transparent; }
.planning-datepicker-wrap .DateInput_input {
  font-size: 0.9rem; font-weight: 600;
  color: var(--bs-body-color, #212529);
  background-color: var(--bs-body-bg, #fff);
  border: 1px solid #cbd5e1; border-radius: 8px;
  padding: 8px 10px; text-align: center;
  transition: all 0.2s; height: 38px; width: 100%;
}
.planning-datepicker-wrap .DateInput_input:hover   { border-color: #4f46e5; }
.planning-datepicker-wrap .DateInput_input__focused {
  border-color: #4f46e5;
  box-shadow: 0 0 0 3px rgba(79,70,229,0.15);
}

/* ═══════════════════════════════════════════════════════════
   NEW: Dark mode using [data-theme="dark"] (app's actual selector)
   ═══════════════════════════════════════════════════════════ */

/* Planning table */
[data-theme="dark"] .maint-planning-table thead th,
[data-theme="dark"] .planning-thead-row th {
  background: #4f46e5;
  color: #fff !important;
  border-color: rgba(255,255,255,0.15);
  z-index: 15;
}
[data-theme="dark"] .maint-planning-table tbody tr,
[data-theme="dark"] .maint-planning-table td {
  border-color: var(--border-color, rgba(255,255,255,0.08));
  color: var(--text-primary, #e2e8f0);
  background-color: transparent;
}
[data-theme="dark"] .maint-planning-table tbody tr:hover { background: rgba(99,102,241,0.12) !important; }
[data-theme="dark"] .planning-row-filled td {
  background: rgba(99,102,241,0.06) !important;
  color: var(--text-primary, #e2e8f0);
}
[data-theme="dark"] .planning-row-empty  td { color: var(--text-muted, #64748b); }
[data-theme="dark"] .planning-cell-time      { color: var(--primary-color, #818cf8) !important; }

/* Title */
[data-theme="dark"] .planning-title { color: var(--text-primary, #e2e8f0) !important; }

/* Form card */
[data-theme="dark"] .maint-add-form-card {
  border-color: var(--primary-dark, #6366f1);
  background: var(--bg-card, #1e293b) !important;
}
[data-theme="dark"] .maint-add-form-card .card-header {
  background: var(--bg-card, #1e293b) !important;
  color: var(--text-primary, #f1f5f9);
  border-color: var(--border-color, #334155);
}
[data-theme="dark"] .maint-add-form-card .card-body {
  background: var(--bg-card, #1e293b) !important;
  color: var(--text-primary, #f1f5f9);
}

/* DatePicker */
[data-theme="dark"] .planning-datepicker-wrap .DateInput_input {
  background-color: #1e293b; color: #f1f5f9; border-color: #334155;
}
[data-theme="dark"] .planning-datepicker-wrap .DateInput_input:hover {
  border-color: #6366f1; background-color: #2d3748;
}
[data-theme="dark"] .planning-datepicker-wrap .DateInput_input__focused { border-color: #818cf8; }

/* Checklist */
[data-theme="dark"] .maint-checklist-list-item:not(.maint-cl-status-pending):not(.maint-cl-status-inprogress):not(.maint-cl-status-done) { background: #1e2130 !important; border-color: #3a3f50 !important; color: #c9d1d9 !important; }
[data-theme="dark"] .maint-checklist-list-item:not(.maint-cl-status-pending):not(.maint-cl-status-inprogress):not(.maint-cl-status-done):hover { background: #232840 !important; border-color: #6366f1 !important; }
[data-theme="dark"] .maint-checklist-list-item .text-muted { color: #8892a4 !important; }
[data-theme="dark"] .maint-checklist-list-item small,
[data-theme="dark"] .maint-checklist-list-item .small { color: #8892a4 !important; }
body.dark-mode .maint-checklist-list-item .text-muted { color: #8892a4 !important; }
body.dark-mode .maint-checklist-list-item small,
body.dark-mode .maint-checklist-list-item .small      { color: #8892a4 !important; }
[data-theme="dark"] .maint-cl-detail-table th {
  background: #1e293b; color: #e2e8f0;
  border-color: rgba(255,255,255,0.08);
}
[data-theme="dark"] .maint-cl-detail-table td { color: #e2e8f0; border-color: rgba(255,255,255,0.08); }
[data-theme="dark"] .maint-cl-summary { background: rgba(99,102,241,0.12); border-color: rgba(99,102,241,0.3); }
[data-theme="dark"] .maint-area-tree-header th { background: #1e293b; color: #e2e8f0; }

/* Filter — no white background */
[data-theme="dark"] #maint-planning-filter,
[data-theme="dark"] #maint-details-filter { background: transparent; }
#maint-planning-filter, #maint-details-filter { background: transparent; padding: 0; }

/* Settings table dark mode (supplement existing selectors) */
[data-theme="dark"] .maint-settings-thead th { background: #4f46e5; color: #fff; }

/* ═══════════════════════════════════════════════════════════
   OVERRIDE FINAL — Form card + Table rows dark mode fix
   Dùng !important để override mọi rule cũ
   ═══════════════════════════════════════════════════════════ */

/* ── Form card: background + title trong dark mode ───────── */
[data-theme="dark"] .maint-add-form-card,
[data-theme="dark"] .maint-add-form-card .card {
  background-color: #1e293b !important;
  border-color: #6366f1 !important;
}
[data-theme="dark"] .maint-add-form-card .card-header {
  background-color: #1e293b !important;
  border-bottom-color: #334155 !important;
  color: #f1f5f9 !important;
}
[data-theme="dark"] .maint-add-form-card .card-header strong,
[data-theme="dark"] .maint-add-form-card .card-header span,
[data-theme="dark"] .maint-add-form-card .card-header * {
  color: #f1f5f9 !important;
}
[data-theme="dark"] .maint-add-form-card .card-body {
  background-color: #1e293b !important;
  color: #e2e8f0 !important;
}
[data-theme="dark"] .maint-add-form-card label {
  color: #cbd5e1 !important;
}

/* ── Planning table rows — fix white text in dark ─────────── */
[data-theme="dark"] .maint-planning-table td,
[data-theme="dark"] .maint-planning-table tr td {
  color: #e2e8f0 !important;
  background-color: transparent !important;
  border-color: rgba(255,255,255,0.07) !important;
}
[data-theme="dark"] .maint-planning-table .planning-row-empty td {
  color: #64748b !important;
}
[data-theme="dark"] .maint-planning-table .planning-row-filled td {
  background-color: rgba(99,102,241,0.07) !important;
  color: #e2e8f0 !important;
}
[data-theme="dark"] .maint-planning-table td.planning-cell-time {
  color: #818cf8 !important;
  font-weight: 600;
}
[data-theme="dark"] .maint-planning-table tbody tr:hover td {
  background-color: rgba(99,102,241,0.14) !important;
}

/* ── Planning title ───────────────────────────────────────── */
[data-theme="dark"] .planning-title,
[data-theme="dark"] .planning-title * {
  color: #f1f5f9 !important;
}

/* ── Tất cả text trong table sáng trong dark mode ─────────── */
[data-theme="dark"] .maint-planning-table .text-muted,
[data-theme="dark"] .maint-planning-table .text-muted.small {
  color: #475569 !important;
}
/* ═══════════════════════════════════════════════════════════
   FIX #4: Checklist detail table — dark mode content rows
   FIX #6: Detail text cell — multiline / wrap
   ═══════════════════════════════════════════════════════════ */

/* FIX #6: Detail text pre tag — wrap multiline like Settings/Details */
.maint-cl-detail-pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  font-family: inherit;
  font-size: 0.82rem;
  background: transparent;
  border: none;
  padding: 0;
  line-height: 1.5;
}

/* Detail cell allows wrapping */
.cl-detail-cell {
  white-space: normal !important;
  vertical-align: top;
  padding-top: 6px !important;
}

/* FIX #4: Group cells (System / Equipment / Area / Component) — dark mode */
.cl-group-cell {
  vertical-align: middle;
  font-size: 0.82rem;
}
.cl-group-empty {
  border-left: none !important;
  border-right: none !important;
}
/* ── Căn giữa nội dung các cột: Đã KT?, KQ KT?, KQ sau SC?, Hình ảnh ─────── */
.maint-cl-center-cell {
  text-align: center !important;
  vertical-align: middle !important;
  padding-left: 4px !important;
  padding-right: 4px !important;
  overflow: hidden;
}
.maint-cl-center-cell .maint-cl-native-select {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}
.maint-cl-center-cell .maint-cl-img-cell {
  align-items: center;
  width: 100%;
  min-width: 0;
}
.maint-cl-center-cell .maint-cl-img-upload-wrap {
  display: flex;
  justify-content: center;
}

.cl-comp-cell {
  vertical-align: middle;
  white-space: normal;
  word-wrap: break-word;
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Light mode: subtle color for group identifier cells */
.cl-sys-cell   { color: #4f46e5; font-weight: 600; }
.cl-eq-cell    { color: #0891b2; font-weight: 600; }
.cl-area-cell  {
  color: #059669;
  white-space: normal;
  word-wrap: break-word;
  overflow-wrap: break-word;
  word-break: break-word;
  text-align: center;
}
.cl-text       { color: inherit; }

/* FIX #4: Dark mode — all checklist content cells readable */
[data-theme="dark"] .maint-cl-detail-table tbody td,
[data-theme="dark"] .maint-cl-detail-table .maint-cl-row td {
  color: #e2e8f0 !important;
  border-color: rgba(255,255,255,0.07) !important;
  background-color: transparent !important;
}

[data-theme="dark"] .cl-sys-cell   { color: #818cf8 !important; }
[data-theme="dark"] .cl-eq-cell    { color: #38bdf8 !important; }
[data-theme="dark"] .cl-area-cell  { color: #34d399 !important; }
[data-theme="dark"] .cl-group-empty {
  background-color: transparent !important;
  border-color: rgba(255,255,255,0.04) !important;
}

/* FIX #4: Dark mode — pre inside detail cell */
[data-theme="dark"] .maint-cl-detail-pre {
  color: #cbd5e1 !important;
}

/* FIX #4: Row hover in dark mode */
[data-theme="dark"] .maint-cl-detail-table tbody tr:hover td {
  background-color: rgba(99,102,241,0.1) !important;
}

/* FIX #4: Modal footer dark mode */
[data-theme="dark"] .maint-cl-detail-modal .modal-footer {
  background: #1e293b;
  border-top-color: #334155;
}
[data-theme="dark"] .maint-cl-detail-modal .modal-footer .text-success {
  color: #4ade80 !important;
}

/* Checklist thead — purple like planning */
.maint-cl-thead th {
  background: #4f46e5 !important;
  color: #fff !important;
  font-weight: 600;
  font-size: 0.78rem;
  white-space: nowrap;
}
[data-theme="dark"] .maint-cl-thead th {
  background: #4338ca !important;
}

/* ═══════════════════════════════════════════════════════════
   Fullscreen checklist modal + rowspan merged cells
   ═══════════════════════════════════════════════════════════ */

/* ── Checklist detail modal — LARGE modal (JS sets height = viewport - navbar) ── */

/* Dialog width: 95vw (JS sets height via dialog.style.height) */
#maint-cl-detail-modal .modal-dialog {
  max-width: 95vw !important;
  width: 95vw !important;
}

/* Modal content: flex column to fill JS-set dialog height */
#maint-cl-detail-modal .modal-content {
  height: 100% !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
}

/* ── CHECKLIST DETAIL MODAL LAYOUT ────────────────────────────────────────
   Architecture:
     modal-body
       └─ wrapper (flex column, full height)
            ├─ #maint-cl-modal-summary  ← FIXED: never scrolls X or Y
            └─ #maint-cl-modal-table    ← scrolls BOTH X and Y independently
                 └─ table               ← thead sticky inside Y-scroll container

   Key insight: summary sits in normal flow ABOVE the scroll box,
   so it is never part of the scrollable area. thead is sticky at
   top:0 inside #maint-cl-modal-table which is the scroll root.
──────────────────────────────────────────────────────────────────────── */

/* Modal itself: flex column so body fills remaining space */
#maint-cl-detail-modal .modal-dialog {
  display: flex !important;
  flex-direction: column !important;
  /* height được JS (modal_layout.js fixLargeModalPosition) set động
     theo viewport thực tế — KHÔNG hard-code vh ở đây để tránh bị giới hạn
     trên màn 14" nhỏ */
  margin: auto !important;
}
#maint-cl-detail-modal .modal-content {
  display: flex !important;
  flex-direction: column !important;
  /* Lấy 100% chiều cao dialog được JS set — không giới hạn thêm */
  height: 100% !important;
  overflow: hidden !important;
}
#maint-cl-detail-modal .modal-header,
#maint-cl-detail-modal .modal-footer {
  flex-shrink: 0 !important;
}

/* Body: flex column, fills all remaining height, NO overflow of its own */
#maint-cl-detail-modal .modal-body {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  padding: 8px 12px !important;
  overflow: hidden !important;
  display: flex !important;
  flex-direction: column !important;
}

/* Dash wraps children in an extra div — make it flex column, no scroll */
#maint-cl-detail-modal .modal-body > div {
  display: flex !important;
  flex-direction: column !important;
  flex: 1 1 auto !important;
  min-height: 0 !important;
  overflow: hidden !important;
}
/* Dash wraps table children too — use display:contents to be invisible */
#maint-cl-modal-table > div {
  display: contents !important;
}

/* ── Summary bar: FIXED — never scrolls X or Y ──────────────────────── */
#maint-cl-modal-summary {
  flex-shrink: 0 !important;
  /* No position:sticky — it sits above the scroll container so it
     naturally stays put regardless of X or Y scrolling inside #maint-cl-modal-table */
  background: var(--card-bg, #1e2a3a) !important;
  border-bottom: 1px solid var(--border-color, rgba(255,255,255,0.1)) !important;
  padding: 4px 2px !important;
  margin-bottom: 4px !important;
  z-index: 10 !important;
}

/* #maint-cl-modal-table == .maint-cl-table-wrapper */
#maint-cl-modal-table {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  /* overflow:overlay = scrollbar nổi lên trên content, không chiếm layout space
     → vertical scrollbar không tạo khoảng trắng bên phải
     Chrome/Edge support overlay; Firefox fallback về auto (scrollbar-width:thin thu nhỏ gap) */
  overflow: overlay !important;
  scrollbar-width: thin;
}

/* Webkit: scrollbar nhỏ + trong suốt track */
#maint-cl-modal-table::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
#maint-cl-modal-table::-webkit-scrollbar-track {
  background: transparent;
}
#maint-cl-modal-table::-webkit-scrollbar-thumb {
  background: rgba(148, 163, 184, 0.5);
  border-radius: 4px;
}
#maint-cl-modal-table::-webkit-scrollbar-thumb:hover {
  background: rgba(148, 163, 184, 0.8);
}
#maint-cl-modal-table::-webkit-scrollbar-corner {
  background: transparent;
}

/* FIX khoảng trắng khi app scale < 1:
   1. Hidden INPUT của React-Select (position:absolute; inset:0): scrollWidth=175 > offsetWidth=68
      → browser tính scrollWidth của ancestor bao gồm cả input ẩn này
      Fix: width:0 + overflow:hidden để input không đóng góp scrollWidth
   2. white-space:nowrap trên th text làm cột expand
      Fix: normal wrap trên header */

/* Header: cho phép wrap text thay vì nowrap */
#maint-cl-modal-table .maint-cl-detail-table thead th {
  white-space: normal !important;
}

/* Hidden input của React-Select có position:absolute; inset:0; opacity:1e-5
   scrollWidth > offsetWidth → đóng góp vào scrollWidth của table
   Fix: max-width:1px để input không expand scrollWidth, nhưng vẫn functional */
#maint-cl-modal-table .Select-input {
  max-width: 1px !important;
  overflow: hidden !important;
}
#maint-cl-modal-table .Select-input > input {
  max-width: 1px !important;
}

/* Table: fill wrapper khi đủ rộng, scroll X khi quá hẹp
   - width: 100%      → luôn fill wrapper (không khoảng trắng bên phải)
   - min-width: 2159px → giữ cột đủ rộng, scroll X khi wrapper < 2159px
   - table-layout: fixed → cột chia theo width% trên th, không expand theo content
*/
#maint-cl-modal-table .maint-cl-detail-table {
  width: 100% !important;
  table-layout: fixed !important;
  border-collapse: separate !important;
  border-spacing: 0 !important;
  overflow: visible !important;
  border-radius: 0 !important;
}

/* overflow:hidden via CSS (không inline) để clip content tràn cột
   Áp dụng 1 lần cho toàn bảng, không per-cell → không gây thrashing */
#maint-cl-modal-table .maint-cl-detail-table td {
  overflow: hidden !important;
  max-width: 0; /* trick: với table-layout:fixed, max-width:0 + overflow:hidden clips đúng */
}

/* Dropdown menu KHÔNG bị clip — cần visible để menu hiện ra */
#maint-cl-modal-table .maint-cl-detail-table td .Select-menu-outer,
#maint-cl-modal-table .maint-cl-detail-table td .Select-menu {
  overflow: visible !important;
  white-space: normal !important;
}

/* dcc.Dropdown trong td: fill 100% width td, không tràn ra ngoài */
#maint-cl-modal-table .maint-cl-detail-table td .Select,
#maint-cl-modal-table .maint-cl-detail-table td .Select-control {
  width: 100% !important;
  min-width: 0 !important;
  max-width: 100% !important;
  box-sizing: border-box !important;
}
#maint-cl-modal-table .maint-cl-detail-table td .Select-input > input {
  min-width: 0 !important;
  width: 5px !important;
}

/* Restore cell borders lost when border-collapse:separate replaces :collapse.
   Use outline/box-shadow trick: right+bottom border on every cell,
   top+left on first row/col gives full grid appearance. */
/* Light mode cell borders */
#maint-cl-modal-table .maint-cl-detail-table td,
#maint-cl-modal-table .maint-cl-detail-table th {
  border: 1px solid rgba(0,0,0,0.15) !important;
}
/* Dark mode cell borders */
[data-theme="dark"] #maint-cl-modal-table .maint-cl-detail-table td,
[data-theme="dark"] #maint-cl-modal-table .maint-cl-detail-table th,
body.dark-mode #maint-cl-modal-table .maint-cl-detail-table td,
body.dark-mode #maint-cl-modal-table .maint-cl-detail-table th {
  border-color: rgba(255,255,255,0.18) !important;
}

/* ── Thead: sticky inside .maint-cl-table-scroll (the Y-scroll root) ──
   .maint-cl-table-wrapper handles X-scroll only (overflow-y:visible)
   .maint-cl-table-scroll handles Y-scroll only (overflow-x:visible)
   sticky works because inner scroll root has only overflow-y set ── */
/* Sticky works because border-collapse:separate (not collapse) */
#maint-cl-modal-table .maint-cl-thead th,
#maint-cl-modal-table .maint-cl-detail-table thead th {
  position: sticky !important;
  top: 0 !important;
  z-index: 4 !important;
  background: #4f46e5 !important;
  color: #fff !important;
  font-weight: 600 !important;
  font-size: 0.78rem !important;
  white-space: nowrap !important;
  border-bottom: 2px solid #3730a3 !important;
  box-shadow: 0 2px 4px rgba(0,0,0,0.25) !important;
}
[data-theme="dark"] #maint-cl-modal-table .maint-cl-thead th,
[data-theme="dark"] #maint-cl-modal-table .maint-cl-detail-table thead th,
body.dark-mode #maint-cl-modal-table .maint-cl-thead th,
body.dark-mode #maint-cl-modal-table .maint-cl-detail-table thead th {
  background: #4338ca !important;
  border-bottom-color: #312e81 !important;
}

/* Ghi chú textarea: wrap text, alt+enter supported via JS */
.maint-cl-notes-ta {
  resize: vertical !important;
  min-height: 34px !important;
  white-space: pre-wrap !important;
  word-break: break-word !important;
  overflow-y: auto !important;
  line-height: 1.3 !important;
}

/* Merged group cells — vertical center + gentle left border accent */
.cl-group-cell {
  vertical-align: middle !important;
  text-align: center !important;
  border-right: 2px solid rgba(99,102,241,0.25) !important;
}
.cl-sys-cell   { border-left: 3px solid #6366f1 !important; }
.cl-eq-cell    { border-left: 3px solid #0891b2 !important; }
.cl-area-cell  { border-left: 3px solid #059669 !important; }

/* Trạng thái merged cell */
[data-theme="dark"] .maint-cl-detail-table td[rowspan] {
  background-color: rgba(255,255,255,0.02) !important;
}
.maint-cl-detail-table td[rowspan] {
  background-color: rgba(0,0,0,0.015);
}

/* Checklist table — no hover background on merged cells (looks odd with rowspan) */
.maint-cl-detail-table tr:hover .cl-group-cell {
  background-color: transparent !important;
}

/* ── Vật tư thay thế: parts management modal list ─────────────────────── */
.maint-sp-parts-list {
  max-height: 260px;
  overflow-y: auto;
}
.maint-sp-parts-list .btn-xs {
  font-size: 0.72rem !important;
  padding: 1px 6px !important;
  line-height: 1.4 !important;
}

/* Vật tư summary cell in main table — compact chips display */
[id*="maint-cl-sp-cell"] .text-success {
  font-size: 0.78rem;
  letter-spacing: 0.01em;
}


/* ══════════════════════════════════════════════════════════════
   CHECKLIST DETAIL MODAL — Layout: summary cố định + scroll bảng
   ══════════════════════════════════════════════════════════════ */

/* Modal body: flex column, không tự scroll */
#maint-cl-detail-modal .modal-body {
  overflow: hidden !important;   /* clip — X scroll lives in .maint-cl-modal-body-inner */
  padding: 10px 14px 6px;
  display: flex;
  flex-direction: column;
  /* KHÔNG set max-height cứng — để flex: 1 1 auto fill hết chiều cao còn lại */
}

/* Wrapper toàn bộ body content */
.maint-cl-modal-body-inner {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}

/* Summary: cố định phía trên, không scroll */
.maint-cl-summary-wrapper {
  flex: 0 0 auto;
  margin-bottom: 6px;
}

/* Fix <2>: Summary box — màu phù hợp với cả light + dark mode */
.maint-cl-summary-wrapper .maint-cl-summary {
  background: rgba(13, 110, 253, 0.08);
  border: 1px solid rgba(13, 110, 253, 0.25);
  border-radius: 6px;
  padding: 6px 12px;
}
.maint-cl-summary-wrapper .maint-cl-summary span,
.maint-cl-summary-wrapper .maint-cl-summary .small {
  color: var(--bs-body-color, #212529) !important;
}
[data-theme="dark"] .maint-cl-summary-wrapper .maint-cl-summary {
  background: rgba(99, 102, 241, 0.12) !important;
  border-color: rgba(99, 102, 241, 0.35) !important;
}
[data-theme="dark"] .maint-cl-summary-wrapper .maint-cl-summary span,
[data-theme="dark"] .maint-cl-summary-wrapper .maint-cl-summary .small {
  color: #e2e8f0 !important;
}
body.dark-mode .maint-cl-summary-wrapper .maint-cl-summary {
  background: rgba(99, 102, 241, 0.12) !important;
  border-color: rgba(99, 102, 241, 0.35) !important;
}
body.dark-mode .maint-cl-summary-wrapper .maint-cl-summary span,
body.dark-mode .maint-cl-summary-wrapper .maint-cl-summary .small {
  color: #e2e8f0 !important;
}

/* Fix <3>&<4>: Bảng scroll container — CHỈ 1 scroll Y + X luôn visible
   overflow-x: scroll (luôn hiện scrollX ngay cả khi chưa cần)
   overflow-y: auto   (scroll Y chỉ khi cần)
   flex: 1 1 auto     (chiếm hết chiều cao còn lại)
   min-height: 0      (quan trọng: cho phép flex item co lại) */
/* Layout approach: 
   - .maint-cl-modal-body-inner handles X-scroll (overflow-x: auto)
   - .maint-cl-table-wrapper handles Y-scroll only (overflow-y: auto, overflow-x: visible)
   This way thead sticky works because the Y-scroll container only has overflow-y set.
   The X-scroll is pushed up to the modal body level. */

/* Table wrapper: SINGLE scroll container.
   border-collapse:separate (not collapse) is REQUIRED for sticky thead to work in Chrome. */
.maint-cl-table-wrapper {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  width: 100%;           /* fill hết chiều ngang modal */
}
/* Dash wraps callback children in extra div — make it passthrough */
.maint-cl-table-wrapper > div {
  display: contents;
}

/* Đảm bảo modal body và table wrapper fill 100% width của dialog */
#maint-cl-detail-modal .modal-content,
#maint-cl-detail-modal .modal-body,
#maint-cl-detail-modal .maint-cl-modal-body-inner {
  width: 100% !important;
  box-sizing: border-box !important;
}

/* Table wrapper fill 100% — không để khoảng trắng bên phải */
#maint-cl-modal-table {
  width: 100% !important;
  box-sizing: border-box !important;
}

/* .maint-cl-table-scroll — passthrough, scroll is on .maint-cl-table-wrapper */

/* thead sticky rules consolidated into #maint-cl-modal-table block above */

/* ══════════════════════════════════════════════════════════════
   FIX <1 badge>: Badge "Có thay đổi chưa lưu" trong footer
   ══════════════════════════════════════════════════════════════ */
#maint-cl-unsaved-badge {
  font-size: 0.82rem;
  padding: 2px 10px;
  border-radius: 4px;
  background: rgba(255, 193, 7, 0.15);
  border: 1px solid rgba(255, 193, 7, 0.45);
}

/* ══════════════════════════════════════════════════════════════
   FIX <save toast>: Thông báo "Đã lưu" tự ẩn sau 4s
   ══════════════════════════════════════════════════════════════ */
@keyframes maint-save-fadeout {
  0%   { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}
.maint-cl-save-fadeout {
  animation: maint-save-fadeout 4s ease forwards;
  display: inline-block;
}

/* ══════════════════════════════════════════════════════════════
   Modal Vật tư — sticky header trong bảng tồn kho
   ══════════════════════════════════════════════════════════════ */
#maint-sp-mini-modal .table-responsive {
  overflow-x: auto;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
#maint-sp-mini-modal .table thead th {
  position: sticky !important;
  top: 0 !important;
  z-index: 2 !important;
  background: var(--bs-light, #f8f9fa) !important;
  white-space: nowrap;
}
[data-theme="dark"] #maint-sp-mini-modal .table thead th,
body.dark-mode      #maint-sp-mini-modal .table thead th {
  background: #1e293b !important;
  color: #e2e8f0 !important;
}

/* Fix <1>: Dropdown tự lật lên trên khi gần đáy bảng
   JS sẽ thêm class .dd-menu-top vào .Select container khi phát hiện không đủ chỗ bên dưới */
.maint-cl-table-wrapper .maint-cl-dropdown.dd-menu-top .Select-menu-outer {
  top: auto !important;
  bottom: 100% !important;
  border-radius: 4px 4px 0 0 !important;
  border-top: 1px solid #ccc !important;
  border-bottom: none !important;
  box-shadow: 0 -4px 10px rgba(0,0,0,0.12) !important;
}
/* Ensure menu z-index is high enough to not be clipped */
.maint-cl-table-wrapper .maint-cl-dropdown .Select-menu-outer {
  z-index: 100 !important;
}

/* ══════════════════════════════════════════════════════════════
   FIX: Cột Người hỗ trợ — dcc.Dropdown multiselect
   ══════════════════════════════════════════════════════════════ */

/* TD helper: overflow visible để dropdown menu không bị clip */
.maint-cl-helper-td {
  overflow: visible !important;
  position: relative;
}
/* Override mọi rule set overflow:hidden trên TD trong modal table */
#maint-cl-modal-table .maint-cl-helper-td,
#maint-cl-detail-modal .maint-cl-helper-td {
  overflow: visible !important;
}

/* Dropdown control: fill TD width */
.maint-cl-helper-dropdown {
  width: 100% !important;
  min-width: 0 !important;
  font-size: 0.78rem !important;
}
.maint-cl-helper-dropdown .Select-control {
  width: 100% !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
  font-size: 0.78rem !important;
}

/* Dropdown menu: z-index đủ cao để nổi trên modal content và các TD khác */
.maint-cl-helper-dropdown .Select-menu-outer {
  z-index: 9999 !important;
  position: absolute !important;
  min-width: 180px !important;
  max-width: 320px !important;
  width: max-content !important;
  left: 0 !important;
}

/* Flip lên trên khi gần đáy — JS thêm class dd-menu-top */
.maint-cl-helper-dropdown.dd-menu-top .Select-menu-outer {
  top: auto !important;
  bottom: 100% !important;
  border-radius: 4px 4px 0 0 !important;
  border-top: 1px solid #ccc !important;
  border-bottom: none !important;
  box-shadow: 0 -4px 10px rgba(0,0,0,0.12) !important;
}

/* Dark mode */
[data-theme="dark"] .maint-cl-helper-dropdown .Select-menu-outer,
body.dark-mode      .maint-cl-helper-dropdown .Select-menu-outer {
  background-color: #1e293b !important;
  border-color: #334155 !important;
}
[data-theme="dark"] .maint-cl-helper-dropdown .Select-option,
body.dark-mode      .maint-cl-helper-dropdown .Select-option {
  background-color: #1e293b !important;
  color: #e2e8f0 !important;
}
[data-theme="dark"] .maint-cl-helper-dropdown .Select-option.is-focused,
body.dark-mode      .maint-cl-helper-dropdown .Select-option.is-focused {
  background-color: #334155 !important;
}

/* ── Native multi-select cho cột Người hỗ trợ ───────────────────────────── */
.maint-cl-helper-select {
  min-width: 0 !important;
  width: 100% !important;
  max-width: 100% !important;
  box-sizing: border-box !important;
  font-size: 0.78rem !important;
  height: auto !important;
  min-height: 28px !important;
  padding: 2px 4px !important;
  cursor: pointer;
}
[data-theme="dark"] .maint-cl-helper-select,
body.dark-mode      .maint-cl-helper-select {
  background-color: #1e293b;
  color: #e2e8f0;
  border-color: #334155;
}
[data-theme="dark"] .maint-cl-helper-select option,
body.dark-mode      .maint-cl-helper-select option {
  background-color: #1e293b;
  color: #e2e8f0;
}

/* ── Custom Multiselect Dropdown — cột Người hỗ trợ ─────────────────────── */
.cl-ms-wrap {
  position: relative;
  width: 100%;
  font-size: 0.78rem;
  user-select: none;
}
.cl-ms-wrap-disabled {
  pointer-events: none;
  opacity: 0.4;
}

/* Control bar: hiển thị selected + mũi tên */
.cl-ms-ctrl {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 4px;
  padding: 2px 6px;
  min-height: 28px;
  max-height: 56px;        /* ~3 dòng × ~18px */
  border: 1px solid var(--border-color, #cbd5e1);
  border-radius: 4px;
  background: var(--input-bg, #fff);
  color: var(--text-primary, #1e293b);
  cursor: pointer;
  transition: border-color 0.15s;
  box-sizing: border-box;
  width: 100%;
  font-size: 0.82rem;
}
.cl-ms-ctrl:hover   { border-color: #6366f1; }
.cl-ms-ctrl.cl-ms-open { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,0.18); }
.cl-ms-ctrl.cl-ms-disabled { opacity: 0.5; cursor: not-allowed; }

.cl-ms-display {
  flex: 1;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  white-space: normal;
  word-break: break-word;
  line-height: 1.4;
  font-size: 0.82rem;
  color: var(--text-primary, #1e293b);
}
.cl-ms-display.is-placeholder { color: var(--text-muted, #94a3b8); }
.cl-ms-arrow {
  flex-shrink: 0;
  font-size: 0.6rem;
  color: var(--text-muted, #94a3b8);
  transition: transform 0.15s;
  margin-top: 3px;
}
.cl-ms-ctrl.cl-ms-open .cl-ms-arrow { transform: rotate(180deg); }

/* Tags hiển thị selected items */
.cl-ms-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.cl-ms-tag {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: rgba(99,102,241,0.12);
  color: #4338ca;
  border-radius: 3px;
  padding: 1px 4px;
  font-size: 0.72rem;
  white-space: nowrap;
  max-width: 80px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cl-ms-tag-x {
  cursor: pointer;
  font-size: 0.8rem;
  line-height: 1;
  flex-shrink: 0;
  opacity: 0.7;
}
.cl-ms-tag-x:hover { opacity: 1; }

/* Dropdown menu */
.cl-ms-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 160px;
  max-width: 280px;
  width: max-content;
  max-height: 200px;
  overflow-y: auto;
  background: var(--input-bg, #fff);
  border: 1px solid var(--border-color, #cbd5e1);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  z-index: 9999;
  margin-top: 2px;
}
.cl-ms-menu.cl-ms-open { display: block; }
.cl-ms-menu.cl-ms-flip {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: 2px;
}

/* Option items */
.cl-ms-option {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 3px 7px;
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--text-primary, #1e293b);
  white-space: nowrap;
  transition: background 0.1s;
}
.cl-ms-option:hover    { background: rgba(99,102,241,0.08); }
.cl-ms-option.selected { background: rgba(99,102,241,0.14); color: #4338ca; font-weight: 500; }
.cl-ms-option-check {
  width: 14px; height: 14px;
  border: 1.5px solid #cbd5e1;
  border-radius: 3px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px;
  transition: all 0.1s;
}
.cl-ms-option.selected .cl-ms-option-check {
  background: #6366f1;
  border-color: #6366f1;
  color: #fff;
}

/* (FEATURE 2026-08 <Popup chọn phiên checklist — widget đứng độc lập>)
   Biến thể standalone của .cl-ms-wrap dùng trong popup "Chọn phiên checklist"
   (assets/session_picker_widget.js) — không nằm trong 1 ô bảng nhỏ hẹp như
   cột Người hỗ trợ nên có thể to hơn 1 chút cho dễ bấm, và menu rộng bằng
   đúng bề ngang control thay vì chỉ min-width 160px. */
.cl-ms-wrap-standalone .cl-ms-ctrl {
  min-height: 34px;
  font-size: 0.88rem;
  padding: 6px 10px;
}
.cl-ms-wrap-standalone .cl-ms-display { font-size: 0.88rem; }
.cl-ms-wrap-standalone .cl-ms-menu {
  width: 100%;
  max-width: none;
  max-height: 240px;
}
.cl-ms-wrap-standalone .cl-ms-option { font-size: 0.88rem; padding: 6px 10px; }

/* (FIX 2026-08 <Chọn nhiều session — control không giãn ra, chữ tràn ra
   ngoài khung>) .cl-ms-ctrl (dùng chung cho ô Người hỗ trợ trong bảng) có
   max-height:56px cứng + .cl-ms-display clamp 3 dòng (overflow:hidden) —
   hợp lý cho 1 ô bảng chật, nhưng trong popup này có đủ chỗ nên khi chọn
   nhiều session, nội dung cần nhiều hơn 3 dòng bị ép tràn ra khỏi khung.
   Fix: cho control ở đây được cao hơn nhiều (giãn theo nội dung tới ~180px)
   trước khi mới cần cuộn, và bỏ line-clamp 3 dòng của .cl-ms-display. */
.cl-ms-wrap-standalone .cl-ms-ctrl {
  max-height: 180px;
  overflow-y: auto;
  align-items: flex-start;
}
.cl-ms-wrap-standalone .cl-ms-display {
  display: block;
  -webkit-line-clamp: unset;
  -webkit-box-orient: unset;
  overflow: visible;
  white-space: normal;
}
/* Scrollbar (chỉ xuất hiện khi số session chọn quá nhiều, vượt 180px) —
   dùng chung biến --scrollbar-track/--scrollbar-thumb như các khung scroll
   khác trong app để đồng bộ theme sáng/tối. */
.cl-ms-wrap-standalone .cl-ms-ctrl::-webkit-scrollbar { width: 6px; }
.cl-ms-wrap-standalone .cl-ms-ctrl::-webkit-scrollbar-track { background: var(--scrollbar-track); }
.cl-ms-wrap-standalone .cl-ms-ctrl::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 3px;
}
.cl-ms-wrap-standalone .cl-ms-ctrl::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }
.cl-ms-wrap-standalone .cl-ms-ctrl {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}

/* (FIX 2026-08 <Menu portal ra body — scrollbar mặc định gần như vô hình
   trên nền tối>) Style riêng scrollbar của .cl-ms-menu cho rõ ràng, để user
   nhận biết được là danh sách có thể cuộn (khi menu bị portal ra body, JS
   set overflow-y:auto + max-height bằng inline style — xem positionMenu()
   trong assets/session_picker_widget.js). */
.cl-ms-menu::-webkit-scrollbar { width: 8px; }
.cl-ms-menu::-webkit-scrollbar-track { background: transparent; }
.cl-ms-menu::-webkit-scrollbar-thumb {
  background: rgba(99,102,241,0.45);
  border-radius: 4px;
}
.cl-ms-menu::-webkit-scrollbar-thumb:hover { background: rgba(99,102,241,0.7); }
.cl-ms-menu { scrollbar-width: thin; scrollbar-color: rgba(99,102,241,0.45) transparent; }

/* Dark mode */
[data-theme="dark"] .cl-ms-ctrl,
body.dark-mode      .cl-ms-ctrl {
  background: #1e293b;
  border-color: #334155;
  color: #e2e8f0;
}
[data-theme="dark"] .cl-ms-menu,
body.dark-mode      .cl-ms-menu {
  background: #1e293b;
  border-color: #334155;
}
[data-theme="dark"] .cl-ms-option,
body.dark-mode      .cl-ms-option { color: #e2e8f0; }
[data-theme="dark"] .cl-ms-option:hover,
body.dark-mode      .cl-ms-option:hover  { background: rgba(99,102,241,0.2); }
[data-theme="dark"] .cl-ms-option.selected,
body.dark-mode      .cl-ms-option.selected { color: #a5b4fc; }
[data-theme="dark"] .cl-ms-tag,
body.dark-mode      .cl-ms-tag { background: rgba(99,102,241,0.25); color: #a5b4fc; }
[data-theme="dark"] .cl-ms-display.is-placeholder,
body.dark-mode      .cl-ms-display.is-placeholder { color: #475569; }

/* ══════════════════════════════════════════════════════════════
   FIX <3>: Row bị khóa — người KT là người khác
   ══════════════════════════════════════════════════════════════ */
.maint-cl-row-locked td {
  opacity: 0.55;
  pointer-events: none;
}
/* Vẫn hiển thị thông tin rõ ràng dù bị mờ */
.maint-cl-row-locked .cl-group-cell,
.maint-cl-row-locked .cl-comp-cell,
.maint-cl-row-locked .cl-detail-cell,
.maint-cl-row-locked .maint-cl-checked-by {
  opacity: 1;
}
/* Tooltip nhỏ trên row locked */
.maint-cl-row-locked {
  cursor: not-allowed;
}
.maint-cl-row-locked td[title] {
  cursor: help;
}

/* Editing lock badge — light mode */
.maint-cl-editing-badge,
.maint-cl-editing-badge.badge {
    background-color: #2563eb !important;
    background:       #2563eb !important;
    color:            #ffffff !important;
    border:           1px solid #93c5fd !important;
    font-size:        0.7rem !important;
    font-weight:      700 !important;
    opacity:          1 !important;
    letter-spacing:   0.02em;
    text-shadow:      none !important;
    -webkit-text-fill-color: #ffffff !important;
}

/* Editing lock badge — dark mode */
[data-theme='dark'] .maint-cl-editing-badge,
[data-theme='dark'] .maint-cl-editing-badge.badge,
body.dark-mode .maint-cl-editing-badge,
body.dark-mode .maint-cl-editing-badge.badge {
    background-color: #3b82f6 !important;
    background:       #3b82f6 !important;
    color:            #ffffff !important;
    border:           1px solid #93c5fd !important;
    font-size:        0.7rem !important;
    font-weight:      700 !important;
    opacity:          1 !important;
    -webkit-text-fill-color: #ffffff !important;
}

/* Settings button aligned with top-right button group (sticky-header padding-right: 14px) */
#maint-settings-btn {
    margin-right: 14px;
    align-self: center;   /* FIX <2>: canh giữa theo chiều dọc trong sub-header row */
}

/* "Thêm kế hoạch" button hover & active effects */
#maint-plan-add-btn {
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
}
#maint-plan-add-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(99, 102, 241, 0.5);
    filter: brightness(1.12);
}
#maint-plan-add-btn:active {
    transform: translateY(0px) scale(0.96);
    box-shadow: 0 1px 4px rgba(99, 102, 241, 0.3);
    filter: brightness(0.95);
}

/* ══════════════════════════════════════════════════════════════
   CHECKLIST DETAIL MODAL — Cột Hình ảnh
   ══════════════════════════════════════════════════════════════ */

/* Cell container */
.maint-cl-img-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  max-width: 100%;
  width: 100%;
  box-sizing: border-box;
}

/* Thumbnail strip — hàng ngang */
.maint-cl-img-thumbs {
  display: grid;
  grid-template-columns: repeat(2, 44px); /* 2 ảnh mỗi hàng */
  gap: 4px;
}

/* Mỗi thumbnail + nút xóa */
.maint-cl-img-thumb-wrap {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 44px;
}

/* Ảnh thumbnail */
.maint-cl-img-thumb {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid rgba(99,102,241,0.35);
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.15s;
  display: block;
}
.maint-cl-img-thumb:hover {
  transform: scale(1.08);
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}

/* Nút xóa — góc trên phải mỗi thumbnail */
.maint-cl-img-del-btn {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: none;
  background: rgba(220, 53, 69, 0.85);
  color: #fff;
  font-size: 8px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0;
  transition: opacity 0.15s;
  z-index: 2;
}
.maint-cl-img-thumb-wrap:hover .maint-cl-img-del-btn {
  opacity: 1;
}

/* Upload wrap (dcc.Upload) */
.maint-cl-img-upload-wrap {
  display: inline-block;
}

/* Upload button visual */
.maint-cl-img-upload-btn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  border-radius: 4px;
  border: 1px dashed rgba(99,102,241,0.55);
  color: rgba(99,102,241,0.9);
  font-size: 0.78rem;
  cursor: pointer;
  white-space: nowrap;
  background: rgba(99,102,241,0.06);
  transition: background 0.15s, border-color 0.15s;
  user-select: none;
}
.maint-cl-img-upload-btn:hover {
  background: rgba(99,102,241,0.14);
  border-color: rgba(99,102,241,0.85);
  box-shadow: 0 2px 8px rgba(99,102,241,0.25);
  transform: translateY(-1px);
}
/* (NEW 2026-08 <thêm hiệu ứng nhấn + focus cho nút "Thêm" ảnh>) Trước đây
   chỉ có hover đổi màu nền/viền, chưa có hiệu ứng khi bấm (active) hay khi
   focus bằng bàn phím — không đồng bộ với "ngôn ngữ thị giác" hover/active/
   focus của .icon-action-btn (xem 32_icon_action_buttons.css) dùng cho các
   nút khác trong app (nhích lên khi hover, lún xuống khi bấm, có shadow). */
.maint-cl-img-upload-btn:active {
  transform: translateY(1px) scale(0.96);
  box-shadow: none;
}
.maint-cl-img-upload-wrap:focus-within .maint-cl-img-upload-btn {
  box-shadow: 0 0 0 0.2rem rgba(99,102,241,0.35);
  border-color: rgba(99,102,241,0.9);
}

[data-theme="dark"] .maint-cl-img-thumb,
body.dark-mode      .maint-cl-img-thumb {
  border-color: rgba(99,102,241,0.45);
}
[data-theme="dark"] .maint-cl-img-upload-btn,
body.dark-mode      .maint-cl-img-upload-btn {
  color: #a5b4fc;
  border-color: rgba(165,180,252,0.45);
  background: rgba(99,102,241,0.1);
}
[data-theme="dark"] .maint-cl-img-upload-btn:hover,
body.dark-mode      .maint-cl-img-upload-btn:hover {
  box-shadow: 0 2px 8px rgba(165,180,252,0.3);
}

/* ══════════════════════════════════════════════════════════════
   (NEW 2026-08) Nút "🌡️ Nhiệt độ" — mở modal checklist đo nhiệt
   độ tủ điện (xem thermal_btn_desktop trong ui_maintenance.py).
   Trước đây chỉ dùng class Bootstrap trần "btn btn-sm" (không có
   hover/active/focus riêng) — màu viền/chữ set ĐỘNG theo mức cảnh
   báo (OK/Warning/NG/Critical) qua inline style, nên CSS ở đây
   dùng currentColor/color-mix để nền + shadow LUÔN tự khớp đúng
   màu trạng thái hiện tại của từng nút, thay vì hard-code 1 màu.
   ══════════════════════════════════════════════════════════════ */
.maint-cl-thermal-btn {
  background-color: rgba(var(--th-rgb, 14,165,233), 0.16);
  border-width: 1.5px !important;
  border-radius: 4px;
  font-weight: 500;
  line-height: 1.25;
  transition: background-color .15s ease, border-color .15s ease,
              box-shadow .15s ease, transform .1s ease, filter .15s ease;
}
.maint-cl-thermal-btn:hover:not(:disabled) {
  background-color: rgba(var(--th-rgb, 14,165,233), 0.30);
  border-color: currentColor;
  box-shadow: 0 2px 8px rgba(var(--th-rgb, 14,165,233), 0.4);
  transform: translateY(-1px);
}
.maint-cl-thermal-btn:active:not(:disabled) {
  transform: translateY(1px) scale(0.97);
  box-shadow: none;
}
.maint-cl-thermal-btn:focus {
  box-shadow: 0 0 0 0.2rem rgba(var(--th-rgb, 14,165,233), 0.35) !important;
}
.maint-cl-thermal-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
/* Dòng "(n)" nhỏ hơn dòng nhãn chính để phân cấp rõ, vẫn canh giữa */
.maint-cl-thermal-btn > div + div {
  font-size: 0.9em;
  opacity: 0.9;
  line-height: 1.15;
}


/* ══════════════════════════════════════════════════════════════
   FIX Modal Vật tư — Dark mode + Height + Sticky header
   ══════════════════════════════════════════════════════════════ */

/* <1> Dark mode: search input */
[data-theme="dark"] #maint-sp-mini-modal .form-control,
body.dark-mode      #maint-sp-mini-modal .form-control {
  background-color: #1e293b !important;
  color: #e2e8f0 !important;
  border-color: #334155 !important;
}
[data-theme="dark"] #maint-sp-mini-modal .form-control::placeholder,
body.dark-mode      #maint-sp-mini-modal .form-control::placeholder {
  color: #64748b !important;
}
[data-theme="dark"] #maint-sp-mini-modal .form-control:focus,
body.dark-mode      #maint-sp-mini-modal .form-control:focus {
  background-color: #1e293b !important;
  color: #e2e8f0 !important;
  border-color: #6366f1 !important;
  box-shadow: 0 0 0 0.2rem rgba(99,102,241,0.25) !important;
}

/* ══════════════════════════════════════════════════════════════════
   Inventory table — row borders, sticky header, page nav
   ══════════════════════════════════════════════════════════════════ */

/* ── Row borders (light mode) ─────────────────────────────────────── */
.sp-inv-row > td {
  border-top: 1px solid #e2e8f0 !important;
  border-bottom: 1px solid #e2e8f0 !important;
  border-left: 1px solid #e2e8f0 !important;
  border-right: 1px solid #e2e8f0 !important;
  padding: 5px 8px !important;
}
.sp-inv-row:hover > td {
  background-color: #f0f4ff !important;
}

[data-theme="dark"] .sp-inv-row > td,
body.dark-mode      .sp-inv-row > td {
  background-color: #1a2235 !important;
  color: #e2e8f0 !important;
  border-color: #2d3f55 !important;
}
[data-theme="dark"] .sp-inv-row:hover > td,
body.dark-mode      .sp-inv-row:hover > td {
  background-color: #243350 !important;
  color: #f0f6ff !important;
}

/* Inventory table: border-collapse:separate required for sticky thead in Chrome.
   overflow:visible BẮTBUỘC — Bootstrap set overflow:hidden trên .table để handle
   border-radius, nhưng điều này phá sticky thead vì browser dùng TABLE làm
   scroll context thay vì .sp-inv-table-scroll.                              */
.sp-inv-table-scroll .table,
.sp-inv-table-scroll table {
  border-collapse: separate !important;
  border-spacing: 0;
  overflow: visible !important;   /* override Bootstrap overflow:hidden */
}

/* ── Sticky header light mode ──────────────────────────────────────── */
.sp-inv-th {
  background-color: #3b5bdb !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  border-bottom: 2px solid #2f4ac8 !important;
  border-right: 1px solid #4f6ae6 !important;
  position: sticky !important;
  top: 0 !important;
  z-index: 3 !important;
  white-space: nowrap !important;
  text-align: center !important;
  padding: 6px 10px !important;
}
/* ── Sticky header dark mode ───────────────────────────────────────── */
[data-theme="dark"] .sp-inv-th,
body.dark-mode      .sp-inv-th {
  background-color: #1e3a5f !important;
  color: #93c5fd !important;
  border-color: #2d3f55 !important;
  border-bottom: 2px solid #3b82f6 !important;
  border-right: 1px solid #2d4a6e !important;
  position: sticky !important;
  top: 0 !important;
  z-index: 3 !important;
  white-space: nowrap !important;
  text-align: center !important;
  padding: 6px 10px !important;
}

/* ── Page navigation buttons ───────────────────────────────────────── */
.sp-page-btn {
  line-height: 1 !important;
  min-width: 26px !important;
}
.sp-page-btn:disabled {
  opacity: 0.35 !important;
  cursor: not-allowed !important;
}
/* Table container border */
[data-theme="dark"] #maint-sp-mini-modal .table,
body.dark-mode      #maint-sp-mini-modal .table {
  --bs-table-bg: #1a2235;
  --bs-table-striped-bg: #1e2a3d;
  --bs-table-hover-bg: #243350;
  --bs-table-color: #e2e8f0;
  --bs-table-border-color: #2d3f55;
  border-color: #2d3f55 !important;
}
/* Override Bootstrap table-hover's CSS variable on dark */
[data-theme="dark"] #maint-sp-mini-modal .table-hover > tbody > tr:hover,
body.dark-mode      #maint-sp-mini-modal .table-hover > tbody > tr:hover {
  --bs-table-hover-color: #f0f6ff;
  --bs-table-hover-bg: #243350;
}
/* table-bordered borders in dark */
[data-theme="dark"] #maint-sp-mini-modal .table-bordered > :not(caption) > * > *,
body.dark-mode      #maint-sp-mini-modal .table-bordered > :not(caption) > * > * {
  border-color: #2d3f55 !important;
}
/* Dark mode: modal body + parts list area */
[data-theme="dark"] #maint-sp-mini-modal .modal-body,
body.dark-mode      #maint-sp-mini-modal .modal-body {
  background-color: #0f172a !important;
  color: #e2e8f0 !important;
}
[data-theme="dark"] #maint-sp-mini-modal .modal-header,
body.dark-mode      #maint-sp-mini-modal .modal-header {
  background-color: #1e293b !important;
  border-color: #334155 !important;
  color: #e2e8f0 !important;
}
[data-theme="dark"] #maint-sp-mini-modal .modal-footer,
body.dark-mode      #maint-sp-mini-modal .modal-footer {
  background-color: #1e293b !important;
  border-color: #334155 !important;
}
[data-theme="dark"] #maint-sp-mini-modal label,
body.dark-mode      #maint-sp-mini-modal label {
  color: #cbd5e1 !important;
}
[data-theme="dark"] #maint-sp-mini-modal hr,
body.dark-mode      #maint-sp-mini-modal hr {
  border-color: #334155 !important;
}
/* Dark mode: parts-list badges/chips */
[data-theme="dark"] #maint-sp-mini-modal .maint-sp-parts-list .badge,
body.dark-mode      #maint-sp-mini-modal .maint-sp-parts-list .badge {
  background-color: #1e3a5f !important;
  color: #93c5fd !important;
}

/* ══════════════════════════════════════════════════════════════════
   SP Modal layout — chiều cao do modal_layout.js kiểm soát hoàn toàn
   (giống about-modal, user-logs-modal: JS set marginTop + height trên
   .modal-dialog dựa vào navbar height thực tế → luôn sát mép viewport).
   CSS chỉ đảm bảo flex chain để nội dung fill đúng.
   Tự quản lý scroll qua flex chain:
     .modal-dialog   (height do JS set)
       modal-content (height: 100%)
         modal-header (shrink 0)
         modal-body   (flex 1, overflow hidden, flex col)
           maint-sp-loading-wrapper / inc wrapper (flex 1)
             sp-inv-table-scroll (flex 1, overflow-y auto) ← scroll ở đây
         modal-footer (shrink 0)
   ══════════════════════════════════════════════════════════════════ */

#maint-sp-mini-modal .modal-dialog,
#incident-spare-modal .modal-dialog {
  /* margin-top/bottom và height do modal_layout.js set — KHÔNG override ở đây */
  display: flex !important;
  flex-direction: column !important;
}

#maint-sp-mini-modal .modal-content,
#incident-spare-modal .modal-content {
  height: 100% !important;
  max-height: 100% !important;
  overflow: hidden !important;
  display: flex !important;
  flex-direction: column !important;
}

#maint-sp-mini-modal .modal-header,
#maint-sp-mini-modal .modal-footer,
#incident-spare-modal .modal-header,
#incident-spare-modal .modal-footer {
  flex: 0 0 auto !important;
}

#maint-sp-mini-modal .modal-body,
#incident-spare-modal .modal-body {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  overflow: hidden !important;
  max-height: none !important;
  padding-bottom: 8px !important;
  display: flex !important;
  flex-direction: column !important;
}

/* .sp-inv-table-scroll: flex child trực tiếp — flex:1 hoạt động đúng
   vì parent là display:flex. overflow-y:auto tạo scroll nội dung. */
.sp-inv-table-scroll {
  flex: 1 1 auto !important;
  overflow-x: auto  !important;
  overflow-y: auto  !important;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 4px;
  min-height: 80px;
}

/* ── SP modal: loading state ─────────────────────────────────────── */
#maint-sp-table-container [data-dash-is-loading="true"],
#inc-sp-table-container [data-dash-is-loading="true"] {
  opacity: 1 !important;
  visibility: visible !important;
}


/* ── Planning tab: yesterday row highlight (auto-scroll target) ─────── */
.planning-row-yesterday > td {
  animation: planning-yesterday-flash 2.5s ease-out forwards;
}
@keyframes planning-yesterday-flash {
  0%   { background-color: rgba(251, 191, 36, 0.30) !important; }
  30%  { background-color: rgba(251, 191, 36, 0.22) !important; }
  100% { background-color: transparent !important; }
}
[data-theme="dark"] .planning-row-yesterday > td,
body.dark-mode      .planning-row-yesterday > td {
  animation: planning-yesterday-flash-dark 2.5s ease-out forwards;
}
@keyframes planning-yesterday-flash-dark {
  0%   { background-color: rgba(251, 191, 36, 0.18) !important; }
  30%  { background-color: rgba(251, 191, 36, 0.12) !important; }
  100% { background-color: transparent !important; }
}



/* ── <5> Planning table: merged date cells ──────────────────────────── */
.planning-merged-cell {
  border-right: 1px solid rgba(99, 102, 241, 0.25) !important;
  font-weight: 600;
}
[data-theme="dark"] .planning-merged-cell,
body.dark-mode      .planning-merged-cell {
  border-right-color: rgba(99, 102, 241, 0.2) !important;
}
/* Bottom border on last row of each date group */
.maint-planning-table tbody tr:not([data-plan-date]) + tr[data-plan-date] > td,
.maint-planning-table tbody tr[data-plan-date]:first-child > td {
  border-top: 2px solid rgba(99, 102, 241, 0.18) !important;
}

/* ── PERF REWRITE: Native HTML select/input/textarea in checklist table ─── */
/* Replaces dcc.Dropdown / dcc.Input / dcc.Textarea — removes React overhead */

.maint-cl-native-select {
  font-size: 0.82rem;
  padding: 2px 4px;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  border-radius: 4px;
  cursor: pointer;
  background-color: var(--input-bg, #fff);
  color: var(--text-primary, #1e293b);
  border: 1px solid var(--border-color, #cbd5e1);
  transition: border-color 0.15s, box-shadow 0.15s;
  display: block;
}
.maint-cl-native-select:focus {
  outline: none;
  border-color: #6366f1;
  box-shadow: 0 0 0 2px rgba(99,102,241,0.18);
}
.maint-cl-native-select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: var(--input-disabled-bg, #f1f5f9);
}

/* Dark mode */
[data-theme="dark"] .maint-cl-native-select,
body.dark-mode      .maint-cl-native-select {
  background-color: #1e293b;
  color: #e2e8f0;
  border-color: #334155;
}
[data-theme="dark"] .maint-cl-native-select:disabled,
body.dark-mode      .maint-cl-native-select:disabled {
  background-color: #0f172a;
  color: #64748b;
}

/* ── UI FIX (2026-08 <Session filter dropdown: width + khung nền đen>) ──
   dcc.Dropdown (react-select) tự vẽ 1 khung .Select-control có nền/border
   riêng (đã bị dark-mode global tô nền #283548 + border ở 14_dark_mode.css)
   — trong header của modal chi tiết checklist (nền đã tối sẵn) khung này
   nổi lên như 1 hộp đen lạc quẻ. Bỏ hẳn nền/border/box-shadow của khung,
   cho nó "chìm" vào thanh header, chỉ còn chữ + mũi tên; đồng thời cho cột
   cha giãn hết khoảng trống còn lại (flex-grow) để không bị cắt chữ session
   dài (VD "16:30-18:30"). !important vì phải đè global .Select-control. */
.maint-cl-session-filter-col {
  flex: 1 1 auto;
  min-width: 220px;
}
.maint-cl-session-filter-select {
  width: 100%;
}
.maint-cl-session-filter-select .Select-control,
[data-theme="dark"] .maint-cl-session-filter-select .Select-control,
body.dark-mode      .maint-cl-session-filter-select .Select-control {
  background: transparent !important;
  border: 1px solid rgba(148, 163, 184, 0.35) !important;
  box-shadow: none !important;
  border-radius: 6px !important;
}
.maint-cl-session-filter-select .Select-control:hover {
  border-color: rgba(148, 163, 184, 0.6) !important;
}
.maint-cl-session-filter-select.is-focused .Select-control {
  border-color: #6366f1 !important;
  box-shadow: 0 0 0 2px rgba(99,102,241,0.18) !important;
}
.maint-cl-session-filter-select .Select-value-label,
.maint-cl-session-filter-select .Select-placeholder,
[data-theme="dark"] .maint-cl-session-filter-select .Select-value-label,
body.dark-mode      .maint-cl-session-filter-select .Select-value-label {
  color: var(--text-primary, #e2e8f0) !important;
}
.maint-cl-session-filter-select .Select-menu-outer {
  min-width: 100%;
  width: max-content !important;
  max-width: 320px;
}

/* Native datetime-local and textarea already styled by form-control,
   but ensure consistent height with the select */
.maint-cl-detail-table td input.form-control-sm,
.maint-cl-detail-table td textarea.form-control-sm {
  font-size: 0.82rem;
}

/* ══════════════════════════════════════════════════════════════════════════
   CHECKLIST STATUS BADGES — distinct, high-contrast background colours
   Scoped to: (1) list-view card  .maint-checklist-list-item
              (2) detail table     .maint-cl-detail-table
              (3) detail modal     #maint-cl-detail-modal
   Does NOT affect buttons or other badges elsewhere in the app.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Not Started → slate blue-grey ──────────────────────────────────────── */
.maint-checklist-list-item .badge.bg-secondary,
.maint-cl-detail-table     .badge.bg-secondary,
#maint-cl-detail-modal     .badge.bg-secondary {
  background-color: #64748b !important;   /* slate-500  */
  color: #ffffff !important;
}

/* ── In-Progress → vivid amber ──────────────────────────────────────────── */
.maint-checklist-list-item .badge.bg-warning,
.maint-cl-detail-table     .badge.bg-warning,
#maint-cl-detail-modal     .badge.bg-warning {
  background-color: #f59e0b !important;   /* amber-500  */
  color: #1c1917 !important;
}

/* ── Done → vibrant emerald ─────────────────────────────────────────────── */
.maint-checklist-list-item .badge.bg-success,
.maint-cl-detail-table     .badge.bg-success,
#maint-cl-detail-modal     .badge.bg-success {
  background-color: #10b981 !important;   /* emerald-500 */
  color: #ffffff !important;
}

/* ── Dark mode — slightly brighter for readability on dark panels ─────────── */
[data-theme="dark"] .maint-checklist-list-item .badge.bg-secondary,
body.dark-mode      .maint-checklist-list-item .badge.bg-secondary,
[data-theme="dark"] .maint-cl-detail-table     .badge.bg-secondary,
body.dark-mode      .maint-cl-detail-table     .badge.bg-secondary,
[data-theme="dark"] #maint-cl-detail-modal     .badge.bg-secondary,
body.dark-mode      #maint-cl-detail-modal     .badge.bg-secondary {
  background-color: #94a3b8 !important;   /* slate-400  */
  color: #0f172a !important;
}

[data-theme="dark"] .maint-checklist-list-item .badge.bg-warning,
body.dark-mode      .maint-checklist-list-item .badge.bg-warning,
[data-theme="dark"] .maint-cl-detail-table     .badge.bg-warning,
body.dark-mode      .maint-cl-detail-table     .badge.bg-warning,
[data-theme="dark"] #maint-cl-detail-modal     .badge.bg-warning,
body.dark-mode      #maint-cl-detail-modal     .badge.bg-warning {
  background-color: #fbbf24 !important;   /* amber-400  */
  color: #1c1917 !important;
}

[data-theme="dark"] .maint-checklist-list-item .badge.bg-success,
body.dark-mode      .maint-checklist-list-item .badge.bg-success,
[data-theme="dark"] .maint-cl-detail-table     .badge.bg-success,
body.dark-mode      .maint-cl-detail-table     .badge.bg-success,
[data-theme="dark"] #maint-cl-detail-modal     .badge.bg-success,
body.dark-mode      #maint-cl-detail-modal     .badge.bg-success {
  background-color: #34d399 !important;   /* emerald-400 */
  color: #022c22 !important;
}

/* ── Progress bars inside checklist list-item — match badge colours ───────── */
.maint-checklist-list-item .progress-bar.bg-secondary { background-color: #64748b !important; }
.maint-checklist-list-item .progress-bar.bg-warning   { background-color: #f59e0b !important; }
.maint-checklist-list-item .progress-bar.bg-success   { background-color: #10b981 !important; }

[data-theme="dark"] .maint-checklist-list-item .progress-bar.bg-secondary,
body.dark-mode      .maint-checklist-list-item .progress-bar.bg-secondary {
  background-color: #94a3b8 !important;
}
[data-theme="dark"] .maint-checklist-list-item .progress-bar.bg-warning,
body.dark-mode      .maint-checklist-list-item .progress-bar.bg-warning {
  background-color: #fbbf24 !important;
}
[data-theme="dark"] .maint-checklist-list-item .progress-bar.bg-success,
body.dark-mode      .maint-checklist-list-item .progress-bar.bg-success {
  background-color: #34d399 !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   CHECKLIST LIST — Sort / Search / Filter controls + number colour fix
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Theme-aware text colour for system/equipment labels and progress numbers
   Explicit color rules — no CSS vars, guarantees correct result in all modes.
   ─────────────────────────────────────────────────────────────────────── */

/* LIGHT MODE: dark text on light/tinted card backgrounds */
.maint-checklist-list-item .maint-cl-label-text,
.maint-checklist-list-item .maint-cl-num-text {
  color: #1e293b !important;
}

/* DARK MODE: light text on dark/tinted card backgrounds */
[data-theme="dark"] .maint-checklist-list-item .maint-cl-label-text,
body.dark-mode      .maint-checklist-list-item .maint-cl-label-text,
[data-theme="dark"] .maint-checklist-list-item .maint-cl-num-text,
body.dark-mode      .maint-checklist-list-item .maint-cl-num-text {
  color: #e2e8f0 !important;
}

/* Sort / Filter button active state */
.maint-cl-sort-btn.active-sort,
.maint-cl-filter-btn.active-filter,
.maint-cl-period-btn.active-period {
  background-color: #6366f1 !important;
  border-color: #6366f1 !important;
  color: #fff !important;
  font-weight: 600;
}
[data-theme="dark"] .maint-cl-sort-btn,
body.dark-mode      .maint-cl-sort-btn,
[data-theme="dark"] .maint-cl-filter-btn,
body.dark-mode      .maint-cl-filter-btn {
  border-color: rgba(255,255,255,0.2);
  color: #c9d1d9;
}

/* Hidden card (filtered out) */
.maint-checklist-list-item.cl-hidden {
  display: none !important;
}

/* ── Reopen button / panel (Auto PM Planning) — always clickable, ──────────
   never covered by neighbouring fixed-width columns (session badge, etc.) ── */
.maint-checklist-list-item [data-reopen-btn="true"] {
  position: relative;
  z-index: 2;
  flex-shrink: 0;
  pointer-events: auto;
}
.maint-checklist-list-item [data-reopen-btn="true"] button {
  white-space: nowrap;
}
[data-reopen-panel="true"] {
  position: relative;
  z-index: 2;
  pointer-events: auto;
}
/* Reopen panel background — light mode (default) */
.maint-cl-reopen-panel {
  background-color: #fffbeb;
  border: 1px solid #fde68a;
}
/* Reopen panel background — dark mode (FIX 2026-08 <panel sáng trắng trong dark mode>) */
[data-theme="dark"] .maint-cl-reopen-panel,
body.dark-mode      .maint-cl-reopen-panel {
  background-color: #2a2410 !important;
  border: 1px solid #6b5a1e !important;
}
[data-theme="dark"] .maint-cl-reopen-panel .form-label,
body.dark-mode      .maint-cl-reopen-panel .form-label {
  color: #f1f5f9 !important;
}

/* ── Checklist PDF button — hover + active effects ── */
.maint-cl-pdf-btn {
  background-color: #ef4444 !important;
  color: #fff !important;
  border: none !important;
  border-radius: 6px !important;
  font-weight: 600;
  transition: background-color 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease !important;
}
.maint-cl-pdf-btn:hover {
  background-color: #dc2626 !important;
  box-shadow: 0 2px 8px rgba(239,68,68,0.45) !important;
  transform: translateY(-1px) !important;
  color: #fff !important;
}
.maint-cl-pdf-btn:active {
  background-color: #b91c1c !important;
  transform: translateY(0px) scale(0.96) !important;
  box-shadow: none !important;
}
[data-theme="dark"] .maint-cl-pdf-btn,
body.dark-mode      .maint-cl-pdf-btn {
  background-color: #ef4444 !important;
  color: #fff !important;
}
[data-theme="dark"] .maint-cl-pdf-btn:hover,
body.dark-mode      .maint-cl-pdf-btn:hover {
  background-color: #f87171 !important;
  box-shadow: 0 2px 10px rgba(239,68,68,0.5) !important;
}

/* ── Custom break-time row highlight ─────────────────────────────────────── */
tr.planning-row-custom td {
  background-color: rgba(251, 191, 36, 0.07) !important;
}
/* Fix 4: dùng class thay vì nth-child để tránh lệch cột khi merge rowspan */
tr.planning-row-custom td.planning-cell-system {
  border-left: 3px solid #f59e0b !important;
}

/* Badge "Custom" inline next to time */
.planning-custom-badge {
  display: inline-block;
  margin-left: 5px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #92400e;
  background-color: #fde68a;
  border: 1px solid #f59e0b;
  border-radius: 4px;
  vertical-align: middle;
  line-height: 1.5;
  white-space: nowrap;
}

/* Dark mode */
[data-theme="dark"] tr.planning-row-custom td,
body.dark-mode      tr.planning-row-custom td {
  background-color: rgba(251, 191, 36, 0.09) !important;
}
[data-theme="dark"] tr.planning-row-custom td.planning-cell-system,
body.dark-mode      tr.planning-row-custom td.planning-cell-system {
  border-left-color: #d97706 !important;
}
[data-theme="dark"] .planning-custom-badge,
body.dark-mode      .planning-custom-badge {
  color: #fef3c7;
  background-color: rgba(245, 158, 11, 0.25);
  border-color: #d97706;
}

/* Hide No./Hệ thống/Thiết bị columns via CSS — simple display:none */
#maint-cl-modal-table .maint-cl-detail-table .cl-sys-cell,
#maint-cl-modal-table .maint-cl-detail-table .cl-eq-cell {
  display: none !important;
}

/* Fix: dcc.Dropdown trong table-layout:fixed — Select-placeholder position:absolute
   tạo ghost width bên phải. Constrain tất cả Select elements trong modal table. */
#maint-cl-modal-table .maint-cl-detail-table .Select,
#maint-cl-modal-table .maint-cl-detail-table .Select-control {
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
  overflow: hidden !important;
}
#maint-cl-modal-table .maint-cl-detail-table .Select-placeholder,
#maint-cl-modal-table .maint-cl-detail-table .Select-input {
  max-width: 100% !important;
  min-width: 0 !important;
  width: auto !important;
  overflow: hidden !important;
}
#maint-cl-modal-table .maint-cl-detail-table .Select-input > input {
  min-width: 0 !important;
  width: 5px !important;
}
#maint-cl-modal-table .maint-cl-detail-table .Select-value-label {
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  min-width: 0 !important;
}

/* ── CHECKLIST TABLE: RESPONSIVE / MOBILE CARD LAYOUT ─────────────────────
   Desktop (≥700px): normal table với % widths, fit modal
   Mobile  (<700px): mỗi row thành card, data-label làm label trái
─────────────────────────────────────────────────────────────────────────── */

/* Desktop: bỏ min-width cứng, dùng % */
#maint-cl-modal-table .maint-cl-detail-table {
  min-width: 0 !important;
}

/* Mobile card layout */
@media (max-width: 700px) {
  #maint-cl-detail-modal .modal-dialog {
    margin: 4px !important;
    max-width: calc(100vw - 8px) !important;
  }

  #maint-cl-modal-table .cl-mobile-cards thead {
    display: none !important;
  }

  #maint-cl-modal-table .cl-mobile-cards,
  #maint-cl-modal-table .cl-mobile-cards tbody,
  #maint-cl-modal-table .cl-mobile-cards tr,
  #maint-cl-modal-table .cl-mobile-cards td {
    display: block !important;
    width: 100% !important;
  }

  #maint-cl-modal-table .cl-mobile-cards tr {
    border: 1px solid rgba(99,102,241,0.3) !important;
    border-radius: 8px !important;
    margin-bottom: 8px !important;
    padding: 4px !important;
    background: var(--card-bg, #1e2a3a) !important;
  }

  #maint-cl-modal-table .cl-mobile-cards td {
    display: flex !important;
    align-items: flex-start !important;
    gap: 8px !important;
    padding: 5px 8px !important;
    border: none !important;
    border-bottom: 1px solid rgba(255,255,255,0.05) !important;
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: unset !important;
    min-height: 32px !important;
  }

  #maint-cl-modal-table .cl-mobile-cards td:last-child {
    border-bottom: none !important;
  }

  /* Label từ data-label */
  #maint-cl-modal-table .cl-mobile-cards td::before {
    content: attr(data-label);
    min-width: 110px;
    max-width: 110px;
    flex-shrink: 0;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-muted, #94a3b8);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-top: 2px;
  }

  /* Ẩn các cột hidden (No., Hệ thống, Thiết bị) */
  #maint-cl-modal-table .cl-mobile-cards td[data-label=""],
  #maint-cl-modal-table .cl-mobile-cards td:not([data-label]) {
    display: none !important;
  }

  /* Input/select full width trong mobile */
  #maint-cl-modal-table .cl-mobile-cards td .Select,
  #maint-cl-modal-table .cl-mobile-cards td input,
  #maint-cl-modal-table .cl-mobile-cards td textarea {
    flex: 1 !important;
    min-width: 0 !important;
    width: 100% !important;
    font-size: 0.8rem !important;
  }
}

/* Tablet (700–1100px): giảm font size và padding để fit */
@media (max-width: 1100px) and (min-width: 701px) {
  #maint-cl-modal-table .maint-cl-detail-table th,
  #maint-cl-modal-table .maint-cl-detail-table td {
    font-size: 0.72rem !important;
    padding: 3px 4px !important;
  }

  #maint-cl-modal-table .maint-cl-detail-table .Select-value-label,
  #maint-cl-modal-table .maint-cl-detail-table .Select-placeholder {
    font-size: 0.72rem !important;
  }
}

/* ── Planning Import/Export Upload Zone ─────────────────────────────────── */
.planning-upload-zone {
    transition: border-color 0.2s, background-color 0.2s;
}
.planning-upload-zone:hover {
    border-color: var(--primary-color, #4F46E5) !important;
    background-color: rgba(79, 70, 229, 0.05) !important;
}
[data-theme="dark"] .planning-upload-zone {
    border-color: #475569 !important;
}
[data-theme="dark"] .planning-upload-zone:hover {
    border-color: #818CF8 !important;
    background-color: rgba(129, 140, 248, 0.08) !important;
}

/* ── Bulk-delete checkbox column ────────────────────────────────────────── */
.planning-cell-chk {
    width: 6% !important;
    padding: 0.25rem 0.5rem !important;
    vertical-align: middle !important;
}

/* Fix 3.1: tăng khoảng cách giữa checkbox và nút delete trong mỗi hàng */
.planning-cell-chk .d-flex {
    gap: 0.5rem !important;
}

.planning-row-chk {
    width: 1.1rem;
    height: 1.1rem;
    cursor: pointer;
    accent-color: var(--danger-color, #dc3545);
    flex-shrink: 0;
}

/* Select-all: html.Button với icon checkbox thay cho dcc.Input */
/* Nằm trong header màu tím #4f46e5 → dùng màu trắng để dễ nhìn */
.maint-select-all-btn {
    font-size: 17px !important;
    line-height: 1 !important;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding: 2px 4px !important;
    color: rgba(255, 255, 255, 0.85) !important;
    flex-shrink: 0;
}
.maint-select-all-btn:hover {
    color: #fff !important;
    background: rgba(255,255,255,0.15) !important;
    border-radius: 3px !important;
}
.maint-select-all-btn:focus {
    box-shadow: none !important;
    outline: none !important;
}
/* Khi đang chọn-tất-cả: icon đổi sang màu vàng nổi bật */
.maint-select-all-btn.is-checked {
    color: #fde68a !important;
}

/* Tăng gap giữa icon select-all và nút delete trong header */
.planning-thead-row .d-flex {
    gap: 10px !important;
}

/* Nút delete selected: solid đỏ, padding đủ lớn */
#maint-plan-bulk-delete-hdr-btn {
    font-size: 13px !important;
    padding: 4px 8px !important;
    line-height: 1.4 !important;
    min-width: 30px !important;
    min-height: 28px !important;
    background-color: #dc3545 !important;
    border-color: #dc3545 !important;
    color: #fff !important;
    border-radius: 4px !important;
}
#maint-plan-bulk-delete-hdr-btn:hover {
    background-color: #bb2d3b !important;
    border-color: #b02a37 !important;
    color: #fff !important;
}

/* Highlight selected rows */
.maint-planning-table tr:has(.planning-row-chk:checked) {
    background-color: rgba(220, 53, 69, 0.07) !important;
}

/* Bulk action bar */
#maint-plan-bulk-bar {
    padding: 0.35rem 0.5rem;
    border-radius: 6px;
    background: var(--bg-secondary, #f8f9fa);
    border: 1px solid var(--border-color, #dee2e6);
}


/* ══════════════════════════════════════════════════════════════
   FIX: Parent plan dropdown — menu popup + marquee scroll
   ══════════════════════════════════════════════════════════════ */

/* Menu popup tự mở rộng theo text dài nhất */
.maint-add-form-card .plan-dropdown .Select-menu-outer {
    min-width: 100% !important;
    width: max-content !important;
    max-width: 640px !important;
    z-index: 10000 !important;
    position: absolute !important;
    left: 0 !important;
}

/* Option text trong menu: không bị wrap/truncate */
.maint-add-form-card .plan-dropdown .Select-option {
    white-space: nowrap !important;
    padding-right: 16px !important;
}

/* Control box: clip overflow */
.maint-add-form-card .plan-dropdown .Select-control {
    overflow: hidden !important;
    position: relative !important;
}
.maint-add-form-card .plan-dropdown .Select-value {
    overflow: hidden !important;
    max-width: 100% !important;
    display: block !important;
}
.maint-add-form-card .plan-dropdown .Select-value-label {
    display: inline-block !important;
    white-space: nowrap !important;
}

/* ── JS sẽ set --dd-overflow px vào style, CSS dùng để animate ── */
.maint-add-form-card .plan-dropdown .Select-control.dd-marquee-active .Select-value-label {
    animation: plan-dd-marquee-px 4s linear 0.3s infinite alternate !important;
}
@keyframes plan-dd-marquee-px {
    0%,15%  { transform: translateX(0px); }
    85%,100%{ transform: translateX(calc(-1px * var(--dd-overflow, 0))); }
}

/* ── Tooltip box: hiện nội dung đầy đủ khi hover ── */
.plan-dd-tooltip {
    display: none;
    position: fixed;
    background: #1a2035;
    color: #c8d8ff;
    border: 1px solid #3d5afe;
    border-radius: 7px;
    padding: 6px 12px;
    font-size: 12.5px;
    white-space: nowrap;
    z-index: 999999;
    pointer-events: none;
    box-shadow: 0 4px 20px rgba(0,0,0,0.6);
    max-width: 640px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.plan-dd-tooltip.visible {
    display: block;
}

/* ══════════════════════════════════════════════════════════════
   Modal "Tình trạng Kế hoạch theo Hệ thống / Thiết bị"
   2 panel song song (mỗi panel 3 cột) + scrollY + tương thích dark mode
   ══════════════════════════════════════════════════════════════ */
.planned-status-grid {
    display: flex;
    gap: 14px;
    align-items: stretch; /* các panel cùng chiều cao nhau */
    /* Không set height ở đây — để modal-body quyết định */
    min-height: 0;
}
.planned-status-panel {
    flex: 1 1 50%;
    min-width: 0;
    min-height: 0;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 6px;
    overflow: hidden; /* clip border-radius */
    display: flex;
    flex-direction: column;
    /* KHÔNG set max-height cứng — fill theo modal-body */
}
/* Header wrapper: cố định, không scroll */
.planned-status-header-wrapper {
    flex-shrink: 0;
    overflow: hidden;
    border-bottom: 2px solid #cbd5e0;
}
/* Body wrapper: scroll dọc riêng từng panel (giữ sticky header) */
.planned-status-body-wrapper {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}
.planned-status-table {
    width: 100%;
    margin-bottom: 0;
    border-collapse: separate;
    border-spacing: 0;
    table-layout: fixed;
}
/* Column widths — đồng bộ giữa header table và body table (3 cột: 35% / 30% / 35%) */
.planned-status-table th:nth-child(1),
.planned-status-table td:nth-child(1) { width: 35%; }
.planned-status-table th:nth-child(2),
.planned-status-table td:nth-child(2) { width: 30%; }
.planned-status-table th:nth-child(3),
.planned-status-table td:nth-child(3) { width: 35%; }
/* Header table */
.planned-status-header-table thead th {
    background: #f0f4f8 !important;
    color: #1a202c;
    white-space: nowrap;
    border-bottom: none !important;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
}
/* Body table: bỏ border-top để không trùng với header border-bottom */
.planned-status-body-table {
    border-top: none !important;
}
@media (max-width: 768px) {
    .planned-status-grid {
        flex-direction: column;
    }
    .planned-status-panel {
        max-height: 40vh;
    }
}

/* Light mode badge / row colors */
.planned-status-badge-ok {
    background-color: #198754;
    color: #fff;
}
.planned-status-badge-missing {
    background-color: #dc3545;
    color: #fff;
}
.planned-status-row-missing td {
    background-color: #fff3cd;
}

/* Dark mode overrides */
[data-theme="dark"] .planned-status-panel,
body.dark-mode .planned-status-panel {
    border-color: #2d3748;
}
[data-theme="dark"] .planned-status-header-wrapper,
body.dark-mode .planned-status-header-wrapper {
    border-bottom-color: #2d3748;
}
/* FIX: Bootstrap's .table sets cell backgrounds via the --bs-table-bg
   CSS custom property, inherited by every <td>/<th> through the rule
   `.table > :not(caption) > * > * { background-color: var(--bs-table-bg); }`.
   Overriding background-color on td alone keeps losing to that variable,
   so we also reset the variable itself on the table — same technique
   already proven to work for #maint-sp-mini-modal .table. */
[data-theme="dark"] .planned-status-table,
body.dark-mode .planned-status-table {
    --bs-table-bg: #161b2c;
    --bs-table-striped-bg: #1c2438;
    --bs-table-hover-bg: #243350;
    --bs-table-color: #e2e8f0;
    --bs-table-border-color: #2d3748;
}
[data-theme="dark"] .planned-status-header-table thead th,
body.dark-mode .planned-status-header-table thead th {
    background: #1e293b !important;
    color: #e2e8f0 !important;
    border-color: #2d3748 !important;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5) !important;
}
[data-theme="dark"] .planned-status-table td,
body.dark-mode .planned-status-table td {
    background-color: #161b2c !important;
    color: #e2e8f0 !important;
    border-color: #2d3748 !important;
}
[data-theme="dark"] .planned-status-row-missing,
body.dark-mode .planned-status-row-missing {
    --bs-table-bg: #2e2410;
}
[data-theme="dark"] .planned-status-row-missing td,
body.dark-mode .planned-status-row-missing td {
    background-color: #2e2410 !important;
    color: #ffe7a8 !important;
}
[data-theme="dark"] .planned-status-row-ok,
body.dark-mode .planned-status-row-ok {
    --bs-table-bg: #161b2c;
}
[data-theme="dark"] .planned-status-row-ok td,
body.dark-mode .planned-status-row-ok td {
    background-color: #161b2c !important;
    color: #e2e8f0 !important;
}
[data-theme="dark"] .planned-status-table tbody tr:hover td,
body.dark-mode .planned-status-table tbody tr:hover td {
    background-color: #243350 !important;
}
[data-theme="dark"] .planned-status-badge-ok,
body.dark-mode .planned-status-badge-ok {
    background-color: #1f9d63 !important;
    color: #eafff3 !important;
}
[data-theme="dark"] .planned-status-badge-missing,
body.dark-mode .planned-status-badge-missing {
    background-color: #c0392b !important;
    color: #ffeaea !important;
}

/* ── Planning header buttons in sub-header (moved from content area) ── */
#maint-planning-header-btns {
    gap: 4px;
}
#maint-planning-header-btns .btn {
    white-space: nowrap;
    font-size: 0.82rem;
}

/* ── Hover transition for Planning header buttons ────────────────────────── */
#maint-planning-header-btns .btn {
    transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease, background-color 0.18s ease;
    position: relative;
}
#maint-planning-header-btns .btn:hover {
    transform: translateY(-2px) scale(1.04);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
    filter: brightness(1.12);
}
#maint-planning-header-btns .btn:active {
    transform: translateY(0px) scale(0.97);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
    filter: brightness(0.96);
    transition-duration: 0.08s;
}

/* Riêng nút Planned (btn-info) — glow xanh cyan khi hover */
#planning-planned-status-btn.btn-info:hover {
    box-shadow: 0 6px 20px rgba(13, 202, 240, 0.45);
}

/* Riêng nút Thêm kế hoạch (btn-primary) — glow xanh indigo khi hover */
#maint-plan-add-btn.btn-primary:hover {
    box-shadow: 0 6px 20px rgba(99, 102, 241, 0.45);
}

/* ── Cảnh báo "hệ thống chưa có kế hoạch bảo trì trong kỳ" ──────────────
   Nằm trong sub-tab bar của tab Bảo trì, chỉ hiện khi Planning sub-tab
   active (toggle hiển thị/ẩn do JS clientside callback đảm nhiệm cùng
   lúc với #maint-planning-header-btns). */
.maint-planning-no-plan-msg:empty {
    display: none !important;
}
.maint-planning-no-plan-msg {
    display: flex;
    align-items: center;
    gap: 6px;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    border-radius: 6px;
    padding: 5px 12px;
    font-size: 13px;
    color: #92400e;
    font-weight: 600;
    /* FIX (2026-08-10 v2): badge giờ luôn nằm gọn TRÊN 1 DÒNG duy nhất
       (không tự xuống dòng, không để lại khoảng trống thừa ở cuối dòng
       như trước). Nếu sub-header quá chật, text sẽ bị cắt gọn bằng "..."
       (ellipsis) thay vì wrap xuống dòng thứ 2 — badge co giãn theo chỗ
       trống còn lại (flex-shrink) nhưng không bao giờ quá 1 dòng. */
    /* FIX (2026-08-10 v4): v3 từng cho badge flex-grow:1 để hút hết khoảng
       trống thừa, nhưng kết quả là 1 khoảng trắng vô nghĩa nằm TRONG badge
       (giữa text và viền phải) và badge bị tách xa cụm nút Planned/+Add
       Plan. Đổi lại flex-grow:0 để badge chỉ rộng vừa đủ nội dung, đồng
       thời dùng margin-left:auto để dồn hết khoảng trống thừa sang bên
       TRÁI badge (giữa tab-scroll-wrapper và badge) thay vì bên trong nó —
       badge nhờ vậy luôn nằm sát ngay cạnh cụm nút bên phải. */
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.35;
    margin-left: auto;
    margin-right: 8px;
    margin-top: 4px;
    margin-bottom: 4px;
}
.maint-planning-no-plan-msg span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.maint-planning-no-plan-msg.maint-planning-no-plan-msg--ok {
    background: #d1fae5;
    border-color: #10b981;
    color: #065f46;
}
body.dark-mode .maint-planning-no-plan-msg,
[data-theme="dark"] .maint-planning-no-plan-msg {
    background: rgba(245, 158, 11, 0.18);
    border-color: rgba(245, 158, 11, 0.55);
    color: #fbbf24;
}
body.dark-mode .maint-planning-no-plan-msg.maint-planning-no-plan-msg--ok,
[data-theme="dark"] .maint-planning-no-plan-msg.maint-planning-no-plan-msg--ok {
    background: rgba(16, 185, 129, 0.16);
    border-color: rgba(16, 185, 129, 0.5);
    color: #34d399;
}

/* FIX (2026-08-10): thanh sub-header của tab Bảo trì giữ nguyên 1 hàng
   (không tự xuống dòng) — badge cảnh báo co giãn bên trong hàng đó, chữ
   được phép wrap nội bộ (xem .maint-planning-no-plan-msg) thay vì cắt bằng
   "..." — không cần tách badge/nút xuống hàng riêng. */
#maint-sub-header-sticky {
    flex-wrap: nowrap;
}
#maint-sub-header-sticky #maint-sub-tabs,
#maint-sub-header-sticky #maint-planning-header-btns,
#maint-sub-header-sticky #maint-settings-btn {
    flex-shrink: 0;
}

/* FIX (2026-08-10 v3): nguyên nhân gốc badge không giãn dù còn nhiều chỗ
   trống — .tab-scroll-wrapper (bọc các tab Activities/Maintenance Details/
   Planning/Checklist Details) bị tab_scroll_arrows.js inject CSS toàn cục
   "flex: 1 1 auto !important" nên nó luôn hút HẾT khoảng trống dư trong
   #maint-sub-header-sticky, kể cả khi nội dung tab không cần nhiều vậy —
   badge phía sau (dù có flex-grow) không còn gì để giãn vào.
   Selector có ID (#maint-sub-header-sticky .tab-scroll-wrapper) có độ đặc
   thù cao hơn selector class-only ".tab-scroll-wrapper" trong style inject
   bởi JS, nên override này thắng bất kể thứ tự nạp CSS.
   → Chặn wrapper tab không giãn quá kích thước nội dung của nó
     (flex-grow: 0), chỉ vẫn được co lại khi chật (flex-shrink: 1) để mũi
     tên cuộn hoạt động bình thường khi không đủ chỗ. */
#maint-sub-header-sticky .tab-scroll-wrapper {
    flex-grow: 0 !important;
    flex-shrink: 1 !important;
    flex-basis: auto !important;
    max-width: max-content !important;
}

/* (FIX 2026-08 <toggle text không đổi>) Nhãn "Active"/"Inactive" cạnh
   Switch tab PM Frequency — đổi màu theo trạng thái để dễ phân biệt, tách
   riêng khỏi label tĩnh cũ của dbc.Switch (xem ui_maintenance.py::
   _render_pmfreq_rows + cb_pm_frequency.py clientside_callback). */
.maint-pmfreq-active-label-on {
    color: #2ecc71;
    font-size: 0.8rem;
    font-weight: 500;
}
.maint-pmfreq-active-label-off {
    color: #8a94a6;
    font-size: 0.8rem;
    font-weight: 500;
}

/* ══════════════════════════════════════════════════════════════
   (FIX 2026-08 <disable session không phải hiện tại>) Badge + tint cho row
   thuộc session quá hạn / chưa tới hạn trong modal Chi tiết Checklist —
   phân biệt với row bị khoá do người khác đang điền (maint-cl-row-locked
   dùng chung style mờ + pointer-events:none, chỉ thêm badge riêng ở đây).
   ══════════════════════════════════════════════════════════════ */
/* (FIX 2026-08 <dời tag Plan date cùng hàng với badge>) Hàng flex chứa
   tag "📅 Plan: ..." (trái) + badge Quá hạn/Chưa đến hạn (phải) — thay cho
   2 span xếp dọc trước đây. */
.maint-cl-plandate-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
}
.maint-cl-session-badge {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 999px;
  white-space: nowrap;
  flex-shrink: 0;
}
.maint-cl-session-badge-overdue {
  background: rgba(239, 68, 68, 0.15);
  color: #ef4444;
}
.maint-cl-session-badge-upcoming {
  background: rgba(100, 116, 139, 0.15);
  color: #64748b;
}
.maint-cl-row-session-locked td {
  background: rgba(148, 163, 184, 0.06);
}

/* (FEATURE 2026-08 <hiện ngày Plan PM luôn hiện, không chỉ hover>)
   Tag nhỏ hiện plan_date dưới phần Detail Item cho MỌI dòng — không phụ
   thuộc trạng thái overdue/upcoming/bình thường. */
.maint-cl-plandate-tag {
  display: block;
  font-size: 0.66rem;
  font-weight: 500;
  color: #94a3b8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ══════════════════════════════════════════════════════════════
   (FIX 2026-08 <re-order + card hoá tab Auto PM>) Mỗi nhóm field trong
   tab Auto PM (Maintenance Settings) được bọc trong 1 "card" nhỏ để phân
   tách trực quan — thay cho chuỗi html.Hr() rời rạc trước đây khiến các
   field trông "lung tung", không rõ nhóm.
   ══════════════════════════════════════════════════════════════ */
.maint-apm-section {
  background: rgba(148, 163, 184, 0.06);
  border: 1px solid rgba(148, 163, 184, 0.14);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 12px;
}
.maint-apm-section-title {
  font-size: 0.85rem;
  color: #cbd5e1;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(148, 163, 184, 0.14);
}
.maint-apm-section-title .fw-bold {
  letter-spacing: 0.02em;
}
.maint-apm-subtitle {
  font-size: 0.8rem;
  margin-bottom: 4px;
}
.maint-apm-inner-hr {
  margin: 12px 0;
  border-color: rgba(148, 163, 184, 0.12);
}

/* (FEATURE 2026-08 <hover transition cho nut Reopen/Đóng lại>) B yêu cầu
   thêm hiệu ứng transition mượt khi hover vào 2 nút "Mở lại" (reopen) và
   "Đóng lại" (reclose) trong tab Maint. / Checklist details. */
.maint-cl-reopen-btn,
.maint-cl-reclose-btn {
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.maint-cl-reopen-btn:hover,
.maint-cl-reclose-btn:hover {
  transform: translateY(-1px) scale(1.04);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.18);
  filter: brightness(1.06);
}
.maint-cl-reopen-btn:active,
.maint-cl-reclose-btn:active {
  transform: translateY(0) scale(0.98);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}

/* ── Cabinet Thermal Checklist table — restyled to visually match the
   checklist-detail modal's table (.maint-cl-detail-table): same purple
   sticky header, same cell border treatment, light zebra striping.
   The thermal table is a dash_table.DataTable, so it renders its own
   markup (.dash-spreadsheet-container / .dash-header / .dash-cell) —
   different DOM than the hand-built .maint-cl-detail-table, so we target
   those DataTable classes directly rather than reuse the same selectors. */
#maint-thermal-table-wrap {
  max-height: 45vh;
  overflow: auto;
  border-radius: 6px;
}
/* (FIX 2026-08 <NGUYÊN NHÂN GỐC khiến sticky header bị cuộn trôi mất>)
   dash_table tự sinh 1 div con ".dash-spreadsheet-container" NẰM GIỮA
   wrapper ngoài (#maint-thermal-table-wrap, chỗ đặt scroll Y ở trên) và
   <table> thật bên trong. Trước đây style_table.overflowX="auto" gắn lên
   ĐÚNG div con này — theo spec CSS Overflow, khi 1 trục (overflow-x) khác
   "visible" thì trình duyệt TỰ ÉP trục còn lại (overflow-y) đang "visible"
   (mặc định) thành "auto" luôn (không cho phép 1 trục scroll, 1 trục
   visible cùng lúc) — nên div con này ngoài ý muốn TRỞ THÀNH 1 scroll
   container thứ 2 (dù bản thân nó không có max-height nên không tự cuộn
   nhìn thấy được), và "position: sticky" trên các th bên trong nó bám
   theo ĐÚNG div con này (nearest scrolling ancestor) chứ không phải
   wrapper ngoài — nên khi wrapper ngoài cuộn, div con (và header sticky
   bên trong nó) cuộn trôi theo luôn, y hệt lỗi "header bị cuộn mất".
   Đã thử đổi sang fixed_rows={"headers": True} (cơ chế "chuẩn" khác của
   dash_table) nhưng bị lỗi hiển thị khác (cột giãn/lệch width, ô trống)
   do xung đột với merge_duplicate_headers (header 2 tầng INPUT/OUTPUT) —
   đã revert, xem ui_maint_detail_modal.py.
   Fix ĐÚNG gốc: ép overflow của chính div con này về "visible" cả 2 trục
   (không cho nó trở thành scroll container nữa) — !important vì dash_table
   có thể tự set lại inline style overflow-x theo style_table Python (đã
   đổi Python sang "visible" luôn, đây là lớp phòng hờ thứ 2). Khi đó
   #maint-thermal-table-wrap (CSS "overflow: auto" ở trên) là scroll
   container DUY NHẤT cho cả 2 chiều X/Y — sticky th bám đúng vào nó. */
#maint-thermal-table-wrap .dash-spreadsheet-container {
  border: none !important;
  overflow: visible !important;
}
#maint-thermal-table-wrap .dash-spreadsheet-inner {
  overflow: visible !important;
}
/* border-collapse:separate (KHÔNG phải collapse) là điều kiện BẮT BUỘC
   để "position: sticky" trên <th> hoạt động đúng trong Chrome — đã áp
   dụng quy tắc này cho MỌI bảng sticky khác trong cùng codebase (xem
   #maint-cl-modal-table, 15_admin.css, 26_incidents_table.css...), nay
   áp lại cho bảng nhiệt độ vì lý do kỹ thuật giống hệt. */
#maint-thermal-table-wrap table {
  border-collapse: separate !important;
  border-spacing: 0 !important;
}
/* Sticky header — 2 tầng thật sự (INPUT/OUTPUT ở tầng 1 dùng colSpan
   ngang qua R/S/T hoặc U/V/W/DC; 6 cột còn lại — Thiết bị/Tên-Vị trí/ΔT
   Input/ΔT Output/Đánh giá/Ghi chú — KHÔNG có rowSpan dọc, tầng 1 của
   chúng là 1 ô trống riêng, tầng 2 mới chứa tên cột thật; xem ghi chú
   revert [label,label] trong ui_maint_detail_modal.py để biết lý do
   không gộp dọc được). Rule bên dưới tô nền tím + chữ trắng ĐỒNG NHẤT
   cho MỌI ô header (áp dụng chung cho cả 2 tầng, kể cả các ô trống của
   6 cột kia) để 2 tầng nhìn liền 1 khối màu dù vẫn là 2 ô riêng biệt về
   mặt DOM. "top: 0" áp dụng chung; tầng 2 cần "top" = đúng chiều cao
   tầng 1 để không đè lên tầng 1 — khớp với style_header height="32px"
   khai báo tường minh trong Python. */
#maint-thermal-table-wrap thead th,
#maint-thermal-table-wrap .dash-header {
  position: sticky !important;
  top: 0 !important;
  z-index: 4 !important;
  background: #4f46e5 !important;
  color: #fff !important;
  font-weight: 600 !important;
  border-color: rgba(255, 255, 255, 0.18) !important;
}
#maint-thermal-table-wrap thead tr:nth-child(2) th {
  top: 32px !important;
  z-index: 3 !important;
}
#maint-thermal-table-wrap .dash-cell,
#maint-thermal-table-wrap .dash-spreadsheet-container td {
  border: 1px solid rgba(0, 0, 0, 0.15) !important;
}
/* (FIX 2026-08-v2 <2 cot DeltaT van khong len mau threshold o dark mode>)
   Ban fix truoc dung "background-color: revert !important" cho rieng 2
   cot DeltaT - SAI: "revert" khong co nghia "tra lai mau inline ma
   Python da set", no tra property ve gia tri mac dinh cua trinh duyet
   (coi nhu KHONG co style tac gia nao ca, ke ca inline), nen o van mat
   mau status (chi doi tu "mat mau do bi ep transparent" sang "mat mau
   do bi revert xoa trang"). Cach dung: loai 2 cot delta_t_in/delta_t_out
   ra khoi NGAY TU rule ep !important goc bang
   ":not([data-dash-column=...])", de 2 cot nay hoan toan khong bi bat
   ky rule !important nao cua file nay dung toi - mau nen/chu status do
   style_data_conditional (THERMAL_DELTA_T_STYLES, thermal_rules.py)
   render ra dang inline style tren <td> se tu nhien duoc ap dung binh
   thuong (khong co rule !important nao canh tranh nua). */
/* (FIX 2026-08 <ô field bị disable theo device_type không tô xám được ở
   dark mode>) 2 dòng "color"/"background-color" ở rule này TRƯỚC ĐÂY dùng
   !important — điều đó vô tình đè mất TOÀN BỘ màu nền/màu chữ inline mà
   style_data_conditional phía Python set cho từng ô (không chỉ 2 cột ΔT
   đã được loại trừ ở trên): cụ thể là _thermal_disabled_style
   (ui_maint_detail_modal.py) tô nền xám + chữ mờ cho các ô KHÔNG áp dụng
   với device_type của dòng đó (VD chọn "MCCB" thì cột U/V/W/DC bị tô xám)
   — ở dark mode, !important khiến các ô này vẫn hiện trong suốt/màu chữ
   sáng bình thường y hệt ô cho phép nhập, người dùng không phân biệt được
   ô nào bị khoá. Bỏ !important ở "color"/"background-color" (giữ lại ở
   "border-color", không liên quan) để inline style của Python (ưu tiên
   cao hơn CSS ngoài không có !important, bất kể độ đặc hiệu selector)
   được áp dụng bình thường — áp dụng luôn cho zebra-stripe dòng lẻ (cũng
   set qua inline style, trước đây cùng bị đè mất). */
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell:not([data-dash-column="delta_t_in"]):not([data-dash-column="delta_t_out"]),
[data-theme="dark"] #maint-thermal-table-wrap .dash-spreadsheet-container td:not([data-dash-column="delta_t_in"]):not([data-dash-column="delta_t_out"]),
body.dark-mode #maint-thermal-table-wrap .dash-cell:not([data-dash-column="delta_t_in"]):not([data-dash-column="delta_t_out"]),
body.dark-mode #maint-thermal-table-wrap .dash-spreadsheet-container td:not([data-dash-column="delta_t_in"]):not([data-dash-column="delta_t_out"]) {
  border-color: rgba(255, 255, 255, 0.18) !important;
  color: #e2e8f0;
  background-color: transparent;
}
[data-theme="dark"] #maint-thermal-table-wrap .dash-spreadsheet-container,
body.dark-mode #maint-thermal-table-wrap .dash-spreadsheet-container {
  --maint-thermal-row-alt: rgba(255, 255, 255, 0.04);
  --maint-thermal-border: rgba(255, 255, 255, 0.18);
  /* (NEW 2026-08 <field disable theo device_type>) Override 2 biến CSS
     mà style_data_conditional phía Python dùng làm màu ô disable
     (--maint-thermal-readonly-bg / --maint-thermal-disabled-fg) — bản
     fallback mặc định (rgba đen mờ) chỉ hợp nền sáng, ở dark mode gần
     như vô hình trên nền tối. Định nghĩa lại bằng tông sáng cho dark
     mode để vẫn tương phản rõ với ô đang cho phép nhập. */
  --maint-thermal-readonly-bg: rgba(255, 255, 255, 0.08);
  --maint-thermal-disabled-fg: rgba(226, 232, 240, 0.35);
}
#maint-thermal-table-wrap .dash-spreadsheet-container tr:hover td:not([data-dash-column="delta_t_in"]):not([data-dash-column="delta_t_out"]) {
  background-color: rgba(79, 70, 229, 0.08) !important;
}

/* (FIX 2026-08 <mất viền khi click vào ô>) Rule border !important ở trên
   áp dụng đồng nhất cho MỌI ô — kể cả ô đang được focus/edit — nên viền
   highlight mặc định của DataTable (.dash-cell.focused) bị đè mất, nhìn
   như click vào ô không có phản hồi gì. Thêm rule riêng, độ ưu tiên cao
   hơn (đặt sau + selector cụ thể hơn), cho ô đang focus một viền nổi bật
   rõ ràng khác hẳn ô thường. */
#maint-thermal-table-wrap .dash-cell.focused,
#maint-thermal-table-wrap .dash-cell.dash-cell--selected,
#maint-thermal-table-wrap .dash-cell.cell--selected {
  border: 2px solid #4f46e5 !important;
  box-shadow: 0 0 0 1px #4f46e5 inset !important;
  outline: none !important;
}
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell.focused,
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell.dash-cell--selected,
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell.cell--selected,
body.dark-mode #maint-thermal-table-wrap .dash-cell.focused,
body.dark-mode #maint-thermal-table-wrap .dash-cell.dash-cell--selected,
body.dark-mode #maint-thermal-table-wrap .dash-cell.cell--selected {
  border: 2px solid #818cf8 !important;
  box-shadow: 0 0 0 1px #818cf8 inset !important;
}

/* (FIX 2026-08 <ô input dòng lẻ vô hình do trùng màu nền>) Khi 1 ô vào
   chế độ edit, DataTable tự render 1 <input> con bên trong — input này
   mặc định KHÔNG có background riêng (inherit từ ô cha), nên ở các dòng
   lẻ (style_data_conditional row_index:"odd" phía Python đặt màu nền
   riêng cho ô cha) input bị chìm hẳn vào màu nền, gần như không thấy con
   trỏ/giá trị đang gõ. Ép input luôn có nền + viền tách biệt HẲN khỏi
   toàn bộ palette nền của modal (không dùng lại --bg-card / các màu nền
   card có sẵn — bản fix trước lỡ chọn đúng #1e293b trùng y hệt
   --bg-card dark mode nên vẫn bị chìm y như cũ), dùng !important vì
   DataTable tự set inline style background lên input theo màu ô cha.
   CHỈ áp dụng cho input nhập liệu THẬT (text/number) — input ẩn bên
   trong ô dropdown (.Select-control, dùng để tìm kiếm option chứ không
   phải nơi hiển thị giá trị) bị rule này áp nhầm khiến ô dropdown "Đánh
   giá" hiện 1 khung xanh trống dù chưa chọn gì — xem rule override riêng
   phía dưới (".Select-input input") dùng để loại trừ lại. */
#maint-thermal-table-wrap .dash-cell input,
#maint-thermal-table-wrap .dash-cell textarea {
  background-color: #dcfce7 !important;
  color: #14532d !important;
  border: 1px solid #4f46e5 !important;
  padding: 0 6px !important;
  height: 26px !important;
  line-height: 26px !important;
  box-sizing: border-box !important;
  vertical-align: middle !important;
}
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell input,
[data-theme="dark"] #maint-thermal-table-wrap .dash-cell textarea,
body.dark-mode #maint-thermal-table-wrap .dash-cell input,
body.dark-mode #maint-thermal-table-wrap .dash-cell textarea {
  background-color: #bbf7d0 !important;
  color: #14532d !important;
  border: 1px solid #818cf8 !important;
  padding: 0 6px !important;
  height: 26px !important;
  line-height: 26px !important;
  box-sizing: border-box !important;
  vertical-align: middle !important;
}

/* (FIX 2026-08 <input vẫn lệch xuống dưới dù đã set height/line-height>)
   ĐÃ XÁC ĐỊNH nguyên nhân thật qua debug console (không phải do padding
   hay display:flex như 2 lần thử trước): input do DataTable render có
   position:absolute; top:0, neo vào div cha ".dash-input-cell-value-
   container" (position:relative) — nhưng div cha đó chỉ cao ~15px (tự
   tính theo 1 div "shadow" ẩn dùng để đo bề rộng text, KHÔNG liên quan gì
   đến chiều cao input thật 26px). Input neo top:0 vào 1 container 15px
   trong khi bản thân nó cao 26px → tràn xuống dưới ~11px, trông như bị
   lệch xuống dưới ô. Fix: bỏ neo top:0, thay bằng top:50% +
   translateY(-50%) để input tự căn giữa theo TÂM của div cha thay vì
   theo cạnh trên của nó — không phụ thuộc chiều cao internal 15px kia
   nữa, luôn đúng giữa bất kể DataTable tính lại kích thước container ra
   sao. Chỉ target input trong ".dash-input-cell-value-container" — đúng
   cấu trúc DOM riêng của ô nhập liệu số/text, loại trừ input ẩn của ô
   dropdown Select (position:static, không cần và không nên đụng vào). */
#maint-thermal-table-wrap .dash-cell .dash-input-cell-value-container input {
  top: 50% !important;
  transform: translateY(-50%) !important;
}

/* Loại trừ input tìm-kiếm ẩn bên trong ô dropdown (Device/Evaluation) —
   input này KHÔNG phải nơi hiển thị giá trị đã chọn (giá trị hiển thị ở
   .Select-value bên cạnh), luôn tồn tại trong DOM kể cả khi ô chưa chọn
   gì, nên nếu áp cùng style ở trên sẽ hiện 1 khung xanh trống thừa thãi.
   Reset về trong suốt, không viền, không padding thêm. */
#maint-thermal-table-wrap .dash-cell .Select-input input,
#maint-thermal-table-wrap .dash-cell .dash-dropdown-cell-value-container input {
  background-color: transparent !important;
  border: none !important;
  padding: 0 !important;
  box-sizing: content-box !important;
}

/* (FIX 2026-08 <căn giữa toàn bộ nội dung ô: text/number/dropdown>)
   style_cell textAlign:"center" (phía Python) chỉ căn giữa nội dung ô
   khi KHÔNG ở chế độ edit. Khi 1 ô vào edit mode, DataTable tự chèn
   <input> con — input này KHÔNG tự thừa hưởng textAlign của ô cha (UA
   stylesheet của input có thể ghi đè), nên phải set text-align riêng.
   Tương tự, ô dropdown (Device/Evaluation) render qua react-select
   (.Select-control > .Select-value), mặc định canh trái theo flex — cần
   ép justify-content/text-align để giá trị đã chọn hiển thị giữa ô,
   khớp với các cột text/number khác. */
#maint-thermal-table-wrap .dash-cell input,
#maint-thermal-table-wrap .dash-cell textarea {
  text-align: center !important;
}
/* (FIX 2026-08 <mũi tên dropdown bị lệch khỏi mép phải — v71 sửa sai>)
   Bản v71 dùng display:flex + flex:1/flex:0 để tách text/mũi tên, NHƯNG
   trong react-select v1 (thư viện DataTable dùng cho cột dropdown),
   .Select-value/.Select-placeholder vốn đã là position:absolute (đè kín
   toàn bộ .Select-control, xem rule tương tự ở
   "#maint-cl-modal-table .maint-cl-detail-table .Select-placeholder" phía
   trên) — flex-basis KHÔNG có tác dụng gì trên phần tử absolute, nên
   .Select-value vẫn tự trải rộng full-width ĐÈ LUÔN LÊN vùng mũi tên,
   khiến chữ bị canh giữa theo toàn bộ chiều rộng ô (kể cả phần dưới mũi
   tên) → nhìn như mũi tên trôi vào sát/trước chữ. Bỏ hẳn flex/display
   (không cần thiết vì Select-value vốn tự đè kín theo absolute có sẵn),
   quay lại cách đơn giản đã đúng ở v70: canh giữa chữ NHƯNG chừa khoảng
   trống bên phải bằng đúng bề rộng khu vực mũi tên (~20px) để chữ không
   tràn xuống dưới mũi tên nữa. */
#maint-thermal-table-wrap .dash-cell .Select-value,
#maint-thermal-table-wrap .dash-cell .Select-placeholder {
  text-align: center !important;
  padding-left: 0 !important;
  padding-right: 20px !important; /* = đúng bề rộng .Select-arrow-zone, tránh đè lên mũi tên */
  box-sizing: border-box !important;
  width: 100% !important;
}

/* (FIX 2026-08-v2 <dọn CSS chết sau khi bỏ required 2 field ambient>)
   Class ".maint-thermal-input-invalid" (viền đỏ khi thiếu field bắt buộc)
   không còn callback Python nào gắn vào ô nữa (đã xoá cùng lúc bỏ ràng
   buộc bắt buộc — xem cb_maintenance.py) nên xoá luôn rule CSS cho gọn. */

/* ── 24_permissions.css ──────────────────────────────── */
/*
 * 24_permissions.css  –  Permission-based UI visibility
 *
 * THREE states per feature key:
 *   allowed  → key in data-user-permissions  → shown & interactive
 *   disabled → key in data-user-disabled     → shown, greyed, pointer-events:none
 *   hidden   → key in data-user-hidden       → display:none
 *   absent   → in none of the 3              → hidden (buttons & tabs)
 *
 * Tab selectors use id="nav-tab-xxx" added to each dbc.Tab in Python.
 * dbc.Tab with id="x" renders as: <li id="x" class="nav-item"><a class="nav-link">
 *
 * BASE HIDE: absent from all 3 → display:none
 *   html:not([perm~="x"]):not([dis~="x"]):not([hid~="x"]) #nav-tab-x
 *
 * DISABLED: html[dis~="x"] #nav-tab-x .nav-link  → opacity + pointer-events:none
 * HIDDEN:   html[hid~="x"] #nav-tab-x             → display:none
 */

/* ═══ HELPER SHORTHAND ══════════════════════════════════════════════════════
   [P~="x"] = data-user-permissions~="x"
   [D~="x"] = data-user-disabled~="x"
   [H~="x"] = data-user-hidden~="x"
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════
   BUTTONS — BASE HIDE (absent from all 3 lists)
   ═══════════════════════════════════════════════════════════════════ */
html:not([data-user-permissions~="btn_online_users"]):not([data-user-disabled~="btn_online_users"]):not([data-user-hidden~="btn_online_users"]) #online-users-btn { display: none !important; }
html:not([data-user-permissions~="btn_user_logs"]):not([data-user-disabled~="btn_user_logs"]):not([data-user-hidden~="btn_user_logs"]) #user-logs-wrapper { display: none !important; }
html:not([data-user-permissions~="btn_app_logs"]):not([data-user-disabled~="btn_app_logs"]):not([data-user-hidden~="btn_app_logs"]) #sync-logs-wrapper { display: none !important; }
html:not([data-user-permissions~="btn_seatalk_bot_log"]):not([data-user-disabled~="btn_seatalk_bot_log"]):not([data-user-hidden~="btn_seatalk_bot_log"]) #seatalk-bot-log-wrapper { display: none !important; }
html:not([data-user-permissions~="btn_notification"]):not([data-user-disabled~="btn_notification"]):not([data-user-hidden~="btn_notification"]) #alert-bell-btn { display: none !important; }
html:not([data-user-permissions~="btn_about"]):not([data-user-disabled~="btn_about"]):not([data-user-hidden~="btn_about"]) #about-btn { display: none !important; }
html:not([data-user-permissions~="btn_restart"]):not([data-user-disabled~="btn_restart"]):not([data-user-hidden~="btn_restart"]) #restart-server-btn { display: none !important; }
html:not([data-user-permissions~="btn_admin"]):not([data-user-disabled~="btn_admin"]):not([data-user-hidden~="btn_admin"]) #admin-settings-btn { display: none !important; }
html:not([data-user-permissions~="btn_layout"]):not([data-user-disabled~="btn_layout"]):not([data-user-hidden~="btn_layout"]) #open-layout-editor-btn { display: none !important; }
html:not([data-user-permissions~="btn_asm_info"]):not([data-user-disabled~="btn_asm_info"]):not([data-user-hidden~="btn_asm_info"]) #asm-info-wrapper { display: none !important; }
html:not([data-user-permissions~="btn_batch_export"]):not([data-user-disabled~="btn_batch_export"]):not([data-user-hidden~="btn_batch_export"]) #open-batch-export-btn { display: none !important; }
html:not([data-user-permissions~="btn_batch_export"]):not([data-user-disabled~="btn_batch_export"]):not([data-user-hidden~="btn_batch_export"]) .batch-export-btn { display: none !important; }
html:not([data-user-permissions~="btn_maint_setting"]):not([data-user-disabled~="btn_maint_setting"]):not([data-user-hidden~="btn_maint_setting"]) #maint-settings-btn { display: none !important; }
html:not([data-user-permissions~="btn_add_plan"]):not([data-user-disabled~="btn_add_plan"]):not([data-user-hidden~="btn_add_plan"]) #maint-plan-add-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_upload"]):not([data-user-disabled~="maint_set_upload"]):not([data-user-hidden~="maint_set_upload"]) #maint-area-upload,
html:not([data-user-permissions~="maint_set_upload"]):not([data-user-disabled~="maint_set_upload"]):not([data-user-hidden~="maint_set_upload"]) #maint-details-upload { display: none !important; }
html:not([data-user-permissions~="maint_set_add_system"]):not([data-user-disabled~="maint_set_add_system"]):not([data-user-hidden~="maint_set_add_system"]) #maint-area-add-system-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_add_row"]):not([data-user-disabled~="maint_set_add_row"]):not([data-user-hidden~="maint_set_add_row"]) #maint-details-add-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_add_break"]):not([data-user-disabled~="maint_set_add_break"]):not([data-user-hidden~="maint_set_add_break"]) #maint-bt-add-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_export"]):not([data-user-disabled~="maint_set_export"]):not([data-user-hidden~="maint_set_export"]) #maint-settings-export-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_save"]):not([data-user-disabled~="maint_set_save"]):not([data-user-hidden~="maint_set_save"]) #maint-area-save-btn,
html:not([data-user-permissions~="maint_set_save"]):not([data-user-disabled~="maint_set_save"]):not([data-user-hidden~="maint_set_save"]) #maint-details-save-btn,
html:not([data-user-permissions~="maint_set_save"]):not([data-user-disabled~="maint_set_save"]):not([data-user-hidden~="maint_set_save"]) #maint-bt-save-btn { display: none !important; }
html:not([data-user-permissions~="maint_set_cancel"]):not([data-user-disabled~="maint_set_cancel"]):not([data-user-hidden~="maint_set_cancel"]) #maint-area-cancel-btn,
html:not([data-user-permissions~="maint_set_cancel"]):not([data-user-disabled~="maint_set_cancel"]):not([data-user-hidden~="maint_set_cancel"]) #maint-details-cancel-btn,
html:not([data-user-permissions~="maint_set_cancel"]):not([data-user-disabled~="maint_set_cancel"]):not([data-user-hidden~="maint_set_cancel"]) #maint-bt-cancel-btn { display: none !important; }
html:not([data-user-permissions~="toggle_watermark"]):not([data-user-disabled~="toggle_watermark"]):not([data-user-hidden~="toggle_watermark"]) .watermark-toggle-wrapper { display: none !important; }
html:not([data-user-permissions~="btn_add_incident"]):not([data-user-disabled~="btn_add_incident"]):not([data-user-hidden~="btn_add_incident"]) #btn-add-incident { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   MAIN TABS — BASE HIDE  (uses id="nav-tab-xxx" on dbc.Tab)
   ═══════════════════════════════════════════════════════════════════ */
html:not([data-user-permissions~="tab_overview"]):not([data-user-disabled~="tab_overview"]):not([data-user-hidden~="tab_overview"]) #nav-tab-overview { display: none !important; }
html:not([data-user-permissions~="tab_compare"]):not([data-user-disabled~="tab_compare"]):not([data-user-hidden~="tab_compare"]) #nav-tab-compare { display: none !important; }
html:not([data-user-permissions~="tab_incidents"]):not([data-user-disabled~="tab_incidents"]):not([data-user-hidden~="tab_incidents"]) #nav-tab-incidents { display: none !important; }
html:not([data-user-permissions~="tab_report"]):not([data-user-disabled~="tab_report"]):not([data-user-hidden~="tab_report"]) #nav-tab-reports { display: none !important; }
html:not([data-user-permissions~="tab_maintenance"]):not([data-user-disabled~="tab_maintenance"]):not([data-user-hidden~="tab_maintenance"]) #nav-tab-maintenance { display: none !important; }
html:not([data-user-permissions~="tab_spare_parts"]):not([data-user-disabled~="tab_spare_parts"]):not([data-user-hidden~="tab_spare_parts"]) #tab-spare-parts-item { display: none !important; }
/* (Yêu cầu mới) 3 tab trước đây THIẾU rule "BASE HIDE" ở đây (Assets/Work
   Order/Lịch ca) — dù đã có class_name="d-none" lúc render lần đầu ở Python
   (ui_layout.py) và có JS ẩn theo permissions-store (cb_clientside.py), 3
   tab này vẫn "chớp sáng" vài giây lúc F5/mở app trước khi bị ẩn, khác hẳn
   6 tab còn lại (Tổng quan/So sánh/Sự cố/Báo cáo/Bảo trì/Phụ tùng) đã có
   rule CSS BASE HIDE ngay phía trên — rule này dựa vào thuộc tính
   data-user-permissions gắn trên <html> ngay khi trang vừa tải (không cần
   đợi vòng round-trip Client->Server->Client của permissions-store), nên
   ẩn được NGAY LẬP TỨC, không có độ trễ nào. Thêm 3 rule còn thiếu để đồng
   bộ với các tab khác.*/
html:not([data-user-permissions~="tab_assets"]):not([data-user-disabled~="tab_assets"]):not([data-user-hidden~="tab_assets"]) #nav-tab-assets { display: none !important; }
html:not([data-user-permissions~="tab_assets"]):not([data-user-disabled~="tab_assets"]):not([data-user-hidden~="tab_assets"]) #nav-tab-work-orders { display: none !important; }
html:not([data-user-permissions~="tab_shift"]):not([data-user-disabled~="tab_shift"]):not([data-user-hidden~="tab_shift"]) #nav-tab-shift { display: none !important; }
html:not([data-user-permissions~="tab_work_permit"]):not([data-user-disabled~="tab_work_permit"]):not([data-user-hidden~="tab_work_permit"]) #nav-tab-work-permit { display: none !important; }
html:not([data-user-permissions~="tab_documents"]):not([data-user-disabled~="tab_documents"]):not([data-user-hidden~="tab_documents"]) #nav-tab-documents { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   SUBTABS — BASE HIDE
   ═══════════════════════════════════════════════════════════════════ */
html:not([data-user-permissions~="subtab_inc_chart"]):not([data-user-disabled~="subtab_inc_chart"]):not([data-user-hidden~="subtab_inc_chart"]) #nav-inc-charts { display: none !important; }
html:not([data-user-permissions~="subtab_inc_detail"]):not([data-user-disabled~="subtab_inc_detail"]):not([data-user-hidden~="subtab_inc_detail"]) #nav-inc-details { display: none !important; }
html:not([data-user-permissions~="subtab_rpt_shift"]):not([data-user-disabled~="subtab_rpt_shift"]):not([data-user-hidden~="subtab_rpt_shift"]) #nav-rpt-shift { display: none !important; }
html:not([data-user-permissions~="subtab_rpt_day"]):not([data-user-disabled~="subtab_rpt_day"]):not([data-user-hidden~="subtab_rpt_day"]) #nav-rpt-daily { display: none !important; }
html:not([data-user-permissions~="subtab_rpt_week"]):not([data-user-disabled~="subtab_rpt_week"]):not([data-user-hidden~="subtab_rpt_week"]) #nav-rpt-weekly { display: none !important; }
html:not([data-user-permissions~="subtab_rpt_month"]):not([data-user-disabled~="subtab_rpt_month"]):not([data-user-hidden~="subtab_rpt_month"]) #nav-rpt-monthly { display: none !important; }
html:not([data-user-permissions~="subtab_maint_activity"]):not([data-user-disabled~="subtab_maint_activity"]):not([data-user-hidden~="subtab_maint_activity"]) #nav-maint-charts { display: none !important; }
html:not([data-user-permissions~="subtab_maint_detail"]):not([data-user-disabled~="subtab_maint_detail"]):not([data-user-hidden~="subtab_maint_detail"]) #nav-maint-details-old { display: none !important; }
html:not([data-user-permissions~="subtab_maint_planning"]):not([data-user-disabled~="subtab_maint_planning"]):not([data-user-hidden~="subtab_maint_planning"]) #nav-maint-planning { display: none !important; }
html:not([data-user-permissions~="subtab_maint_details"]):not([data-user-disabled~="subtab_maint_details"]):not([data-user-hidden~="subtab_maint_details"]) #nav-maint-details { display: none !important; }
html:not([data-user-permissions~="subtab_sp_stats"]):not([data-user-disabled~="subtab_sp_stats"]):not([data-user-hidden~="subtab_sp_stats"]) #nav-sp-charts { display: none !important; }
html:not([data-user-permissions~="subtab_sp_log"]):not([data-user-disabled~="subtab_sp_log"]):not([data-user-hidden~="subtab_sp_log"]) #nav-sp-details { display: none !important; }
html:not([data-user-permissions~="subtab_sp_inventory"]):not([data-user-disabled~="subtab_sp_inventory"]):not([data-user-hidden~="subtab_sp_inventory"]) #nav-sp-inventory { display: none !important; }
html:not([data-user-permissions~="subtab_sp_jit"]):not([data-user-disabled~="subtab_sp_jit"]):not([data-user-hidden~="subtab_sp_jit"]) #nav-sp-jit { display: none !important; }
html:not([data-user-permissions~="subtab_sp_forecast"]):not([data-user-disabled~="subtab_sp_forecast"]):not([data-user-hidden~="subtab_sp_forecast"]) #nav-sp-forecast { display: none !important; }
html:not([data-user-permissions~="subtab_sp_alert"]):not([data-user-disabled~="subtab_sp_alert"]):not([data-user-hidden~="subtab_sp_alert"]) #nav-sp-alerts { display: none !important; }
html:not([data-user-permissions~="subtab_shift_codes"]):not([data-user-disabled~="subtab_shift_codes"]):not([data-user-hidden~="subtab_shift_codes"]) #nav-shift-codes { display: none !important; }
html:not([data-user-permissions~="subtab_shift_employees"]):not([data-user-disabled~="subtab_shift_employees"]):not([data-user-hidden~="subtab_shift_employees"]) #nav-shift-employees { display: none !important; }
html:not([data-user-permissions~="subtab_shift_schedule"]):not([data-user-disabled~="subtab_shift_schedule"]):not([data-user-hidden~="subtab_shift_schedule"]) #nav-shift-schedule { display: none !important; }
html:not([data-user-permissions~="subtab_shift_stats"]):not([data-user-disabled~="subtab_shift_stats"]):not([data-user-hidden~="subtab_shift_stats"]) #nav-shift-stats { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   Graceful degradation — before login don't flash-hide
   ═══════════════════════════════════════════════════════════════════ */
html:not([data-user-permissions]) #online-users-btn,
html:not([data-user-permissions]) #user-logs-btn,
html:not([data-user-permissions]) #sync-logs-btn,
html:not([data-user-permissions]) #admin-settings-btn,
html:not([data-user-permissions]) #restart-server-btn,
html:not([data-user-permissions]) #open-layout-editor-btn,
html:not([data-user-permissions]) #open-batch-export-btn,
html:not([data-user-permissions]) #maint-settings-btn,
html:not([data-user-permissions]) #maint-plan-add-btn,
html:not([data-user-permissions]) #about-btn { display: unset; }

/* ═══════════════════════════════════════════════════════════════════
   DISABLED state — buttons, maint, watermark
   ═══════════════════════════════════════════════════════════════════ */
html[data-user-disabled~="btn_online_users"] #online-users-btn,
html[data-user-disabled~="btn_user_logs"]    #user-logs-btn,
html[data-user-disabled~="btn_user_logs"]    #user-logs-wrapper,
html[data-user-disabled~="btn_app_logs"]     #sync-logs-btn,
html[data-user-disabled~="btn_app_logs"]     #sync-logs-wrapper,
html[data-user-disabled~="btn_seatalk_bot_log"] #seatalk-bot-log-btn,
html[data-user-disabled~="btn_seatalk_bot_log"] #seatalk-bot-log-wrapper,
html[data-user-disabled~="btn_notification"] #alert-bell-btn,
html[data-user-disabled~="btn_about"]        #about-btn,
html[data-user-disabled~="btn_restart"]      #restart-server-btn,
html[data-user-disabled~="btn_admin"]        #admin-settings-btn,
html[data-user-disabled~="btn_layout"]       #open-layout-editor-btn,
html[data-user-disabled~="btn_asm_info"]     #asm-info-btn,
html[data-user-disabled~="btn_asm_info"]     #asm-info-wrapper,
html[data-user-disabled~="btn_batch_export"] #open-batch-export-btn,
html[data-user-disabled~="btn_batch_export"] .batch-export-btn,
html[data-user-disabled~="btn_maint_setting"] #maint-settings-btn,
html[data-user-disabled~="btn_add_plan"]      #maint-plan-add-btn,
html[data-user-disabled~="btn_add_incident"]  #btn-add-incident,
html[data-user-disabled~="maint_set_upload"]      #maint-area-upload,
html[data-user-disabled~="maint_set_upload"]      #maint-details-upload,
html[data-user-disabled~="maint_set_add_system"]  #maint-area-add-system-btn,
html[data-user-disabled~="maint_set_add_row"]     #maint-details-add-btn,
html[data-user-disabled~="maint_set_add_break"]   #maint-bt-add-btn,
html[data-user-disabled~="maint_set_export"]      #maint-settings-export-btn,
html[data-user-disabled~="maint_set_save"]        #maint-area-save-btn,
html[data-user-disabled~="maint_set_save"]        #maint-details-save-btn,
html[data-user-disabled~="maint_set_save"]        #maint-bt-save-btn,
html[data-user-disabled~="maint_set_cancel"]      #maint-area-cancel-btn,
html[data-user-disabled~="maint_set_cancel"]      #maint-details-cancel-btn,
html[data-user-disabled~="maint_set_cancel"]      #maint-bt-cancel-btn {
    opacity: 0.38 !important;
    pointer-events: none !important;
    cursor: not-allowed !important;
    filter: grayscale(0.5) !important;
}
html[data-user-disabled~="toggle_watermark"] .watermark-toggle-wrapper {
    opacity: 0.38 !important;
    pointer-events: none !important;
    cursor: not-allowed !important;
}

/* ═══════════════════════════════════════════════════════════════════
   ENABLED override — FIX: các nút toolbar này được Python render 1 LẦN
   DUY NHẤT lúc trang tải (server-side, is_logged_in lúc đó = False vì
   session/login chưa xác định được ở request đầu), nên nhận inline
   style "pointer-events:none;opacity:0.5" cứng luôn trong HTML.
   Sau đó user login qua SPA (không F5/reload trang) → permissions-store
   được cập nhật đầy đủ (data-user-permissions có key tương ứng) NHƯNG
   không có gì re-render lại đoạn HTML gốc đó → inline style disable bị
   "đóng băng" vĩnh viễn, nút nhìn/bấm vẫn như chưa đăng nhập dù đã có
   quyền. CSS !important dưới đây ghi đè lại inline style ngay khi
   quyền tương ứng đã có trong data-user-permissions.
   ═══════════════════════════════════════════════════════════════════ */
html[data-user-permissions~="btn_online_users"]    #online-users-btn,
html[data-user-permissions~="btn_user_logs"]       #user-logs-btn,
html[data-user-permissions~="btn_app_logs"]        #sync-logs-btn,
html[data-user-permissions~="btn_seatalk_bot_log"] #seatalk-bot-log-btn,
html[data-user-permissions~="btn_asm_info"]        #asm-info-btn,
html[data-user-permissions~="btn_notification"]    #alert-bell-btn,
html[data-user-permissions~="btn_about"]           #about-btn {
    pointer-events: auto !important;
    opacity: 1 !important;
}
/* Nếu admin đã CHỦ ĐỘNG disable quyền này cho role, vẫn phải mờ đi —
   rule bên dưới đứng SAU trong file nên thắng rule "ENABLED override"
   ở trên khi cả 2 cùng match (data-user-permissions và
   data-user-disabled cùng chứa key). */
html[data-user-disabled~="btn_online_users"]    #online-users-btn,
html[data-user-disabled~="btn_user_logs"]       #user-logs-btn,
html[data-user-disabled~="btn_app_logs"]        #sync-logs-btn,
html[data-user-disabled~="btn_seatalk_bot_log"] #seatalk-bot-log-btn,
html[data-user-disabled~="btn_asm_info"]        #asm-info-btn,
html[data-user-disabled~="btn_notification"]    #alert-bell-btn,
html[data-user-disabled~="btn_about"]           #about-btn {
    pointer-events: none !important;
    opacity: 0.38 !important;
    cursor: not-allowed !important;
}

/* ═══════════════════════════════════════════════════════════════════
   HIDDEN state — buttons, maint, watermark
   ═══════════════════════════════════════════════════════════════════ */
html[data-user-hidden~="btn_online_users"] #online-users-btn { display: none !important; }
html[data-user-hidden~="btn_user_logs"]    #user-logs-wrapper { display: none !important; }
html[data-user-hidden~="btn_app_logs"]     #sync-logs-wrapper { display: none !important; }
html[data-user-hidden~="btn_seatalk_bot_log"] #seatalk-bot-log-wrapper { display: none !important; }
html[data-user-hidden~="btn_notification"] #alert-bell-btn   { display: none !important; }
html[data-user-hidden~="btn_about"]        #about-btn        { display: none !important; }
html[data-user-hidden~="btn_restart"]      #restart-server-btn     { display: none !important; }
html[data-user-hidden~="btn_admin"]        #admin-settings-btn     { display: none !important; }
html[data-user-hidden~="btn_layout"]       #open-layout-editor-btn { display: none !important; }
html[data-user-hidden~="btn_asm_info"]     #asm-info-wrapper { display: none !important; }
html[data-user-hidden~="btn_batch_export"] #open-batch-export-btn  { display: none !important; }
html[data-user-hidden~="btn_batch_export"] .batch-export-btn       { display: none !important; }
html[data-user-hidden~="btn_maint_setting"] #maint-settings-btn { display: none !important; }
html[data-user-hidden~="btn_add_plan"]      #maint-plan-add-btn { display: none !important; }
html[data-user-hidden~="btn_add_incident"]  #btn-add-incident   { display: none !important; }
html[data-user-hidden~="maint_set_upload"]     #maint-area-upload,
html[data-user-hidden~="maint_set_upload"]     #maint-details-upload      { display: none !important; }
html[data-user-hidden~="maint_set_add_system"] #maint-area-add-system-btn { display: none !important; }
html[data-user-hidden~="maint_set_add_row"]    #maint-details-add-btn     { display: none !important; }
html[data-user-hidden~="maint_set_add_break"]  #maint-bt-add-btn          { display: none !important; }
html[data-user-hidden~="maint_set_export"]     #maint-settings-export-btn { display: none !important; }
html[data-user-hidden~="maint_set_save"]       #maint-area-save-btn,
html[data-user-hidden~="maint_set_save"]       #maint-details-save-btn,
html[data-user-hidden~="maint_set_save"]       #maint-bt-save-btn         { display: none !important; }
html[data-user-hidden~="maint_set_cancel"]     #maint-area-cancel-btn,
html[data-user-hidden~="maint_set_cancel"]     #maint-details-cancel-btn,
html[data-user-hidden~="maint_set_cancel"]     #maint-bt-cancel-btn       { display: none !important; }
html[data-user-hidden~="toggle_watermark"] .watermark-toggle-wrapper { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   TABS DISABLED — nav-link inside the tab's li greyed & unclickable
   ═══════════════════════════════════════════════════════════════════ */
html[data-user-disabled~="tab_overview"]    #nav-tab-overview .nav-link,
html[data-user-disabled~="tab_compare"]     #nav-tab-compare .nav-link,
html[data-user-disabled~="tab_incidents"]   #nav-tab-incidents .nav-link,
html[data-user-disabled~="tab_report"]      #nav-tab-reports .nav-link,
html[data-user-disabled~="tab_maintenance"] #nav-tab-maintenance .nav-link,
html[data-user-disabled~="tab_spare_parts"] #tab-spare-parts-item .nav-link,
html[data-user-disabled~="tab_assets"] #nav-tab-assets .nav-link,
html[data-user-disabled~="tab_assets"] #nav-tab-work-orders .nav-link,
html[data-user-disabled~="tab_shift"] #nav-tab-shift .nav-link,
html[data-user-disabled~="tab_work_permit"] #nav-tab-work-permit .nav-link,
html[data-user-disabled~="tab_documents"] #nav-tab-documents .nav-link {
    opacity: 0.4 !important;
    pointer-events: none !important;
    cursor: not-allowed !important;
    filter: grayscale(0.6) !important;
}

/* Subtabs disabled */
html[data-user-disabled~="subtab_inc_chart"]  #nav-inc-charts .nav-link,
html[data-user-disabled~="subtab_inc_detail"] #nav-inc-details .nav-link,
html[data-user-disabled~="subtab_rpt_shift"]  #nav-rpt-shift .nav-link,
html[data-user-disabled~="subtab_rpt_day"]    #nav-rpt-daily .nav-link,
html[data-user-disabled~="subtab_rpt_week"]   #nav-rpt-weekly .nav-link,
html[data-user-disabled~="subtab_rpt_month"]  #nav-rpt-monthly .nav-link,
html[data-user-disabled~="subtab_maint_activity"]  #nav-maint-charts .nav-link,
html[data-user-disabled~="subtab_maint_detail"]    #nav-maint-details-old .nav-link,
html[data-user-disabled~="subtab_maint_planning"]  #nav-maint-planning .nav-link,
html[data-user-disabled~="subtab_maint_details"]   #nav-maint-details .nav-link,
html[data-user-disabled~="subtab_sp_stats"]     #nav-sp-charts .nav-link,
html[data-user-disabled~="subtab_sp_log"]       #nav-sp-details .nav-link,
html[data-user-disabled~="subtab_sp_inventory"] #nav-sp-inventory .nav-link,
html[data-user-disabled~="subtab_sp_jit"]       #nav-sp-jit .nav-link,
html[data-user-disabled~="subtab_sp_forecast"]  #nav-sp-forecast .nav-link,
html[data-user-disabled~="subtab_sp_alert"]     #nav-sp-alerts .nav-link,
html[data-user-disabled~="subtab_shift_codes"]     #nav-shift-codes .nav-link,
html[data-user-disabled~="subtab_shift_employees"] #nav-shift-employees .nav-link,
html[data-user-disabled~="subtab_shift_schedule"]  #nav-shift-schedule .nav-link,
html[data-user-disabled~="subtab_shift_stats"]     #nav-shift-stats .nav-link {
    opacity: 0.4 !important;
    pointer-events: none !important;
    cursor: not-allowed !important;
}

/* ═══════════════════════════════════════════════════════════════════
   TABS HIDDEN — hide the entire li element
   ═══════════════════════════════════════════════════════════════════ */
html[data-user-hidden~="tab_overview"]    #nav-tab-overview    { display: none !important; }
html[data-user-hidden~="tab_compare"]     #nav-tab-compare     { display: none !important; }
html[data-user-hidden~="tab_incidents"]   #nav-tab-incidents   { display: none !important; }
html[data-user-hidden~="tab_report"]      #nav-tab-reports     { display: none !important; }
html[data-user-hidden~="tab_maintenance"] #nav-tab-maintenance { display: none !important; }
html[data-user-hidden~="tab_spare_parts"] #tab-spare-parts-item { display: none !important; }
html[data-user-hidden~="tab_assets"] #nav-tab-assets { display: none !important; }
html[data-user-hidden~="tab_assets"] #nav-tab-work-orders { display: none !important; }
html[data-user-hidden~="tab_shift"] #nav-tab-shift { display: none !important; }
html[data-user-hidden~="tab_work_permit"] #nav-tab-work-permit { display: none !important; }
html[data-user-hidden~="tab_documents"] #nav-tab-documents { display: none !important; }

html[data-user-hidden~="subtab_inc_chart"]  #nav-inc-charts    { display: none !important; }
html[data-user-hidden~="subtab_inc_detail"] #nav-inc-details   { display: none !important; }
html[data-user-hidden~="subtab_rpt_shift"]  #nav-rpt-shift     { display: none !important; }
html[data-user-hidden~="subtab_rpt_day"]    #nav-rpt-daily     { display: none !important; }
html[data-user-hidden~="subtab_rpt_week"]   #nav-rpt-weekly    { display: none !important; }
html[data-user-hidden~="subtab_rpt_month"]  #nav-rpt-monthly   { display: none !important; }
html[data-user-hidden~="subtab_maint_activity"]  #nav-maint-charts      { display: none !important; }
html[data-user-hidden~="subtab_maint_detail"]    #nav-maint-details-old { display: none !important; }
html[data-user-hidden~="subtab_maint_planning"]  #nav-maint-planning    { display: none !important; }
html[data-user-hidden~="subtab_maint_details"]   #nav-maint-details     { display: none !important; }
html[data-user-hidden~="subtab_sp_stats"]     #nav-sp-charts    { display: none !important; }
html[data-user-hidden~="subtab_sp_log"]       #nav-sp-details   { display: none !important; }
html[data-user-hidden~="subtab_sp_inventory"] #nav-sp-inventory { display: none !important; }
html[data-user-hidden~="subtab_sp_jit"]       #nav-sp-jit       { display: none !important; }
html[data-user-hidden~="subtab_sp_forecast"]  #nav-sp-forecast  { display: none !important; }
html[data-user-hidden~="subtab_sp_alert"]     #nav-sp-alerts    { display: none !important; }
html[data-user-hidden~="subtab_shift_codes"]     #nav-shift-codes     { display: none !important; }
html[data-user-hidden~="subtab_shift_employees"] #nav-shift-employees { display: none !important; }
html[data-user-hidden~="subtab_shift_schedule"]  #nav-shift-schedule  { display: none !important; }
html[data-user-hidden~="subtab_shift_stats"]     #nav-shift-stats     { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   Role management list layout
   ═══════════════════════════════════════════════════════════════════ */
.rl-container { font-size: 0.82rem; }
.rl-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--border-color, #e2e8f0); }
.rl-header.rl-row { background: var(--card-header-bg, #f8fafc); font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted, #64748b); }
.rl-row:hover:not(.rl-header) { background: var(--hover-bg, rgba(0,0,0,0.03)); }
[data-theme="dark"] .rl-header.rl-row { background: #1e293b !important; color: #94a3b8 !important; border-bottom-color: #334155 !important; }
[data-theme="dark"] .rl-row { border-bottom-color: #334155 !important; color: #e2e8f0 !important; }
[data-theme="dark"] .rl-row:hover:not(.rl-header) { background: rgba(99,102,241,0.12) !important; }
.rl-col { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rl-name  { flex: 2 1 140px; }
.rl-label { flex: 2 1 100px; display: none; }
.rl-perms { flex: 0 0 60px; }
.rl-type  { flex: 0 0 80px; }
.rl-act   { flex: 0 0 68px; gap: 4px; }
@media (min-width: 600px) { .rl-label { display: block; } }
.role-perm-row { flex-wrap: nowrap; }
.role-perm-row:hover { background: var(--hover-bg, rgba(0,0,0,0.03)); border-radius: 4px; }
.role-perm-cat-btn { text-decoration: none !important; font-size: 0.75rem !important; }
.role-perm-col { white-space: nowrap; cursor: pointer; user-select: none; flex-shrink: 0; }
.role-perm-col:hover { opacity: 0.85; }

/* ═══════════════════════════════════════════════════════════════════
   Sidebar button rows — flex auto-expand when sibling is hidden
   Each button uses class "sidebar-flex-btn" — flex:1 fills available space.
   When a sibling is hidden by CSS permissions, remaining button fills full width.
   ═══════════════════════════════════════════════════════════════════ */
.sidebar-btn-row {
    display: flex !important;
    flex-direction: row !important;
    gap: 4px;
    width: 100%;
    align-items: stretch;
}
/* sidebar-flex-btn overrides w-100 (width:100%) with flex:1 so siblings share space */
.sidebar-flex-btn {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    width: auto !important;   /* override w-100 */
}

/* ── 25_mobile.css ───────────────────────────────────── */
/* ============================================================
   25_mobile.css — Mobile Responsive Layout
   Chỉ áp dụng khi body.is-mobile-device (set bởi JS).
   ============================================================ */

body.is-mobile-device {
    --navbar-height: 62px;
    --sidebar-width-mobile: 285px;
    overflow: auto !important;
}
body.is-mobile-device #react-entry-point {
    width: 100% !important;
    height: auto !important;
    min-height: 100vh !important;
    transform: none !important;
}

/* ════════════════════════════════════════════════════════════
   NAVBAR — 56px, overflow:visible để dropdown thoát ra
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device #main-navbar,
body.is-mobile-device #main-navbar.navbar,
body.is-mobile-device .navbar {
    position: fixed !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    height: var(--navbar-height) !important;
    min-height: var(--navbar-height) !important;
    max-height: var(--navbar-height) !important;
    padding: 0 !important;
    z-index: 2000 !important;
    overflow: visible !important;
}
body.is-mobile-device #navbar-flex-container {
    flex-wrap: nowrap !important;
    gap: 3px !important;
    height: 100% !important;
    align-items: center !important;
    overflow: visible !important;
}

/* === LEFT: Logo + Dept text — giữ layout desktop, thu nhỏ kích thước === */
body.is-mobile-device #navbar-flex-container > div:nth-child(1) {
    flex-shrink: 0 !important;
    text-align: center !important;
}
body.is-mobile-device #company-logo {
    height: 28px !important; width: auto !important; display: block !important;
}
body.is-mobile-device .navbar p {
    display: block !important;  /* hiện lại "Dept.: HCM Tech" */
    font-size: 0.52rem !important;
    margin-top: 1px !important;
    letter-spacing: 0.8px !important;
}

/* === CENTER: Title H2 + H3 — thu nhỏ font === */
body.is-mobile-device #navbar-flex-container > div:nth-child(2) h2 {
    display: block !important;
    font-size: 0.95rem !important;
    letter-spacing: 0.5px !important;
    line-height: 1.1 !important;
    margin-bottom: 0 !important;
}
body.is-mobile-device #navbar-flex-container > div:nth-child(2) h3 {
    display: block !important;
    font-size: 0.6rem !important;
    letter-spacing: 0.5px !important;
    margin-top: 1px !important;
}
/* Xóa ::after text "HCM 1 ASM" đã inject trước */
body.is-mobile-device #navbar-flex-container > div:nth-child(2)::after {
    content: none !important;
}

/* === RIGHT: 2-row layout — width = dòng time (dài nhất), dòng 2 canh theo mép trái time === */
body.is-mobile-device #navbar-flex-container > div:nth-child(3) {
    min-width: 0 !important;
    width: auto !important;
    max-width: none !important;
    flex-shrink: 0 !important;
    overflow: visible !important;
    align-items: flex-end !important;  /* cả 2 row canh phải */
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    gap: 3px !important;
}
/* Ẩn icon clock/globe */
body.is-mobile-device #navbar-flex-container .fa-clock,
body.is-mobile-device #navbar-flex-container .fa-globe { display: none !important; }
/* Dòng 1: time — width = fit-content (text), định nghĩa chiều rộng cả panel */
body.is-mobile-device #navbar-flex-container > div:nth-child(3) > div:first-child {
    display: flex !important;
    justify-content: flex-end !important;
    align-items: center !important;
    width: auto !important;
    white-space: nowrap !important;
    margin-bottom: 0 !important;
}
body.is-mobile-device #current-time {
    font-size: 0.62rem !important; white-space: nowrap !important;
    margin-left: 0 !important; line-height: 1.2 !important;
}
/* Dòng 2: lang + theme — width: 100% → stretch bằng đúng width panel (= width dòng time) */
body.is-mobile-device #navbar-flex-container > div:nth-child(3) > div:last-child {
    width: 100% !important; display: flex !important;
    align-items: center !important;
    justify-content: flex-start !important;
    gap: 3px !important;
}

/* === LANG DROPDOWN: flex:1 fill khoảng trống, font nhỏ === */
body.is-mobile-device .lang-dropdown-wrapper {
    width: auto !important; min-width: 0 !important; max-width: none !important;
    flex: 1 1 auto !important;
    position: relative !important; overflow: visible !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select,
body.is-mobile-device .lang-dropdown-wrapper .Select.is-open {
    height: 24px !important; min-height: 24px !important; max-height: 24px !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-control {
    display: flex !important; align-items: center !important;
    height: 24px !important; min-height: 24px !important; max-height: 24px !important;
    width: 100% !important; padding: 0 !important;
    border-radius: 5px !important; overflow: hidden !important; box-sizing: border-box !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-multi-value-wrapper {
    display: flex !important; align-items: center !important;
    flex: 1 !important; min-width: 0 !important;
    height: 24px !important; overflow: hidden !important; padding-left: 5px !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-value {
    display: flex !important; align-items: center !important; padding: 0 !important; margin: 0 !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-value-label,
body.is-mobile-device .lang-dropdown-wrapper .Select-placeholder {
    font-size: 0.6rem !important; white-space: nowrap !important;
    overflow: hidden !important; text-overflow: ellipsis !important;
    line-height: 24px !important; padding: 0 !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-input {
    height: 22px !important; padding: 0 !important; width: 1px !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-arrow-zone {
    display: flex !important; align-items: center !important; justify-content: center !important;
    flex-shrink: 0 !important; width: 18px !important; min-width: 18px !important;
    height: 24px !important; padding: 0 !important;
}
/* Menu dropdown đủ rộng để hiển thị đầy đủ tên ngôn ngữ */
body.is-mobile-device .lang-dropdown-wrapper .Select-menu-outer {
    position: fixed !important;
    width: 130px !important;
    max-height: 180px !important;
    overflow-y: auto !important;
    z-index: 9999 !important;
    border-radius: 6px !important;
    box-shadow: 0 4px 16px rgba(0,0,0,0.4) !important;
}
body.is-mobile-device .lang-dropdown-wrapper .Select-option {
    font-size: 0.7rem !important; padding: 6px 10px !important; white-space: nowrap !important;
}

/* === THEME BUTTON — nhỏ gọn, cùng height với lang dropdown === */
body.is-mobile-device #navbar-flex-container > div:nth-child(3) > div:last-child > div[style*="10px"] {
    display: none !important; /* ẩn spacer */
}
body.is-mobile-device .theme-toggle-btn {
    width: 20px !important; height: 20px !important; min-height: 20px !important;
    font-size: 0.55rem !important; padding: 0 !important;
    flex-shrink: 0 !important; margin-left: 3px !important;
    display: flex !important; align-items: center !important; justify-content: center !important;
    border-radius: 50% !important;
}

/* ════════════════════════════════════════════════════════════
   HAMBURGER
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device #mobile-hamburger-btn {
    position: fixed !important;
    top: calc(var(--navbar-height) + 5px) !important; left: 8px !important;
    width: 28px !important; height: 28px !important;
    z-index: 1700 !important; border-radius: 6px !important;
    background: var(--primary-color) !important; color: white !important;
    display: flex !important; align-items: center !important; justify-content: center !important;
    cursor: pointer !important; box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
    border: none !important; font-size: 0.75rem !important;
    transition: background 0.15s, transform 0.1s !important;
}
body.is-mobile-device #mobile-hamburger-btn:active { transform: scale(0.93) !important; }
body.is-mobile-device #sidebar-toggle-tab { display: none !important; }

/* ════════════════════════════════════════════════════════════
   SIDEBAR
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device .sidebar, body.is-mobile-device #sidebar-panel {
    position: fixed !important; top: var(--navbar-height) !important;
    left: 0 !important; bottom: 0 !important;
    width: var(--sidebar-width-mobile) !important; z-index: 1500 !important;
    transform: translateX(-100%) !important;
    transition: transform 0.28s cubic-bezier(0.4,0,0.2,1) !important;
    box-shadow: none !important; overflow-y: auto !important; overflow-x: hidden !important;
}
body.is-mobile-device .sidebar.mobile-sidebar-open,
body.is-mobile-device #sidebar-panel.mobile-sidebar-open {
    transform: translateX(0) !important; box-shadow: 6px 0 24px rgba(0,0,0,0.3) !important;
}
body.is-mobile-device #mobile-sidebar-overlay {
    display: none; position: fixed !important;
    top: var(--navbar-height) !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
    background: rgba(0,0,0,0.45) !important; z-index: 1499 !important; cursor: pointer !important;
}
body.is-mobile-device #mobile-sidebar-overlay.active { display: block !important; }
body.is-mobile-device #sidebar-overlay { display: none !important; pointer-events: none !important; }

/* Modal trên sidebar */
body.is-mobile-device .modal { z-index: 2100 !important; padding-top: var(--navbar-height) !important; overflow-y: auto !important; }
body.is-mobile-device .modal-backdrop { z-index: 2090 !important; }
body.is-mobile-device .modal-dialog { margin: 0 auto !important; max-width: 100vw !important; width: 100vw !important; }
body.is-mobile-device .modal-content { border-radius: 0 !important; max-height: calc(100vh - var(--navbar-height)) !important; overflow-y: auto !important; }

/* ════════════════════════════════════════════════════════════
   MAIN CONTENT
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device #main-content-container {
    margin-left: 0 !important; margin-top: var(--navbar-height) !important;
    height: calc(100vh - var(--navbar-height)) !important;
    overflow-y: auto !important; overflow-x: hidden !important; padding-bottom: 40px !important;
}
/* FIX <1>: Trên mobile, #main-content-container là scroll root (overflow-y:auto).
   .main-content KHÔNG được là scroll container — reset lại các giá trị desktop. */
body.is-mobile-device .main-content {
    padding: 0 0.5rem 2rem !important;
    height: auto !important;
    overflow-y: visible !important;
    overflow-x: visible !important;
}

/* ════════════════════════════════════════════════════════════
   FIX TAB — DEBUG INFO:
   #main-tabs = UL (tag:UL), parent = div[flex:1] no id
   fc.clientWidth: 49px → bị squish bởi main-header-icons
   
   GIẢI PHÁP:
   1. Ẩn tất cả icon buttons bằng CSS
   2. JS inject 1 nút "⋮" collapsible thay thế (FIX 2)
   3. #main-tabs UL tự scroll → div[flex:1] lấy hết width
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device #main-tabs-container,
body.is-mobile-device .sticky-header {
    position: sticky !important; top: 0 !important; z-index: 1010 !important;
    display: flex !important; align-items: center !important;
    padding: 4px 6px 4px 42px !important;   /* 42px left = hamburger 28px + 8px left offset + 6px gap */
    background: var(--bg-sticky) !important;
    backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;
    border-bottom: 1px solid var(--border-color) !important;
    flex-wrap: nowrap !important; gap: 4px !important; overflow: visible !important;
}

/* FIX 2 — Ẩn tất cả icon buttons gốc, JS sẽ inject nút "⋮" */
body.is-mobile-device .main-header-icons {
    display: none !important;
}

/* JS-injected more-menu button */
body.is-mobile-device #mobile-more-btn {
    flex-shrink: 0 !important;
    width: 30px !important; height: 30px !important;
    border-radius: 50% !important;
    background: rgba(99,102,241,0.25) !important;
    color: white !important; border: 1px solid rgba(99,102,241,0.5) !important;
    display: flex !important; align-items: center !important; justify-content: center !important;
    font-size: 1rem !important; cursor: pointer !important;
    flex-shrink: 0 !important;
    transition: background 0.15s !important;
    -webkit-tap-highlight-color: transparent !important;
}
body.is-mobile-device #mobile-more-btn:active { background: rgba(99,102,241,0.5) !important; }

/* Dropdown menu của "⋮" */
body.is-mobile-device #mobile-more-menu {
    display: none;
    position: fixed !important;
    top: calc(var(--navbar-height) + 52px) !important;  /* dưới sticky-header */
    right: 6px !important;
    min-width: 170px !important;
    background: var(--card-bg, #1e293b) !important;
    border: 1px solid rgba(99,102,241,0.4) !important;
    border-radius: 10px !important;
    box-shadow: 0 6px 24px rgba(0,0,0,0.45) !important;
    z-index: 1600 !important;
    overflow: hidden !important;
    flex-direction: column !important;
}
body.is-mobile-device #mobile-more-menu.open { display: flex !important; }

body.is-mobile-device .mobile-more-item {
    display: flex !important; align-items: center !important; gap: 10px !important;
    padding: 10px 14px !important;
    color: var(--text-primary, #e2e8f0) !important;
    font-size: 0.82rem !important; cursor: pointer !important;
    border-bottom: 1px solid rgba(255,255,255,0.06) !important;
    background: transparent !important; border-left: none !important;
    border-right: none !important; border-top: none !important;
    text-align: left !important; width: 100% !important;
    -webkit-tap-highlight-color: transparent !important;
    transition: background 0.12s !important;
}
body.is-mobile-device .mobile-more-item:last-child { border-bottom: none !important; }
body.is-mobile-device .mobile-more-item:active { background: rgba(99,102,241,0.2) !important; }
body.is-mobile-device .mobile-more-item .mobile-more-badge {
    margin-left: auto !important;
    background: #ef4444 !important; color: white !important;
    border-radius: 10px !important; font-size: 0.65rem !important;
    padding: 1px 5px !important; min-width: 16px !important; text-align: center !important;
}

/* FIX 3 — Scale tabs + sub-tabs nhỏ hơn */
/* div[flex:1] bọc UL — chiếm hết width còn lại */
body.is-mobile-device #main-tabs-container > div:first-child {
    flex: 1 !important; min-width: 0 !important;
    overflow-x: auto !important; overflow-y: visible !important;
    -webkit-overflow-scrolling: touch !important; scrollbar-width: none !important;
}
body.is-mobile-device #main-tabs-container > div:first-child::-webkit-scrollbar { display: none !important; }

/* #main-tabs UL — FIX 3: nhỏ gọn hơn */
body.is-mobile-device #main-tabs.nav {
    flex-wrap: nowrap !important;
    width: max-content !important;
    margin-bottom: 0 !important;
    padding-bottom: 1px !important;
    gap: 1px !important;
}
body.is-mobile-device #main-tabs .nav-link {
    white-space: nowrap !important;
    font-size: 0.72rem !important;   /* FIX 3: nhỏ hơn */
    padding: 4px 8px !important;     /* FIX 3: padding nhỏ hơn */
}

/* Sub-tabs: nhỏ gọn — FIX <5>: dùng selector đủ specificity để override 06_tabs.css (15px !important) */
body.is-mobile-device .sub-header-wrapper {
    /* position/top overridden by v6 block below */
    z-index: 1008 !important; overflow: visible !important;
    background: var(--bg-sticky) !important;
}
body.is-mobile-device .sub-header-wrapper .nav.nav-tabs {
    flex-wrap: nowrap !important;
    overflow-x: auto !important; -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important; width: 100% !important; padding-bottom: 2px !important;
}
body.is-mobile-device .sub-header-wrapper .nav.nav-tabs::-webkit-scrollbar { display: none !important; }
/* Ẩn arrow buttons trong sub-tabs trên mobile */
body.is-mobile-device .sub-header-wrapper .tab-scroll-arrow { display: none !important; }
body.is-mobile-device .sub-header-wrapper .tab-scroll-inner {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
}
/* Selector khớp chính xác với 06_tabs.css để !important thắng */
body.is-mobile-device .sub-header-wrapper .nav-tabs .nav-link,
body.is-mobile-device .sub-header-wrapper.d-flex .nav-tabs .nav-link {
    white-space: nowrap !important;
    font-size: 0.65rem !important;   /* nhỏ hơn main tab (0.72rem) */
    padding: 3px 8px !important;
}

/* ════════════════════════════════════════════════════════════
   KPI + CONTENT + MISC
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device .sticky-metrics {
    /* position/top overridden by v6 block below */
    z-index: 1007 !important;
    padding: 8px !important; margin-bottom: 8px !important;
}
/* KPI grid 33.333% — handled by v6 block at bottom of file */

/* ── Charts: mỗi chart 1 dòng full-width trên mobile ── */
/* Override inline flex styles bằng class mới .chart-flex-row / .chart-flex-col */
body.is-mobile-device .chart-flex-row {
    flex-wrap: wrap !important;        /* override "nowrap" inline */
    gap: 0 !important;
}
body.is-mobile-device .chart-flex-col {
    flex: 0 0 100% !important;         /* override "0 0 {width}%" inline */
    width: 100% !important;
    min-width: 100% !important;
    max-width: 100% !important;
}
/* Bootstrap dbc.Row dbc.Col - mỗi col 100% */
body.is-mobile-device .main-content > .row > [class*="col-"],
body.is-mobile-device #tab-content-wrapper .row > [class*="col-"],
body.is-mobile-device .g-4 > [class*="col-"],
body.is-mobile-device .g-3 > [class*="col-"],
body.is-mobile-device .g-2 > [class*="col-"] {
    flex: 0 0 100% !important;
    max-width: 100% !important;
}
body.is-mobile-device .js-plotly-plot,
body.is-mobile-device .plotly-graph-div { width: 100% !important; }

/* ── Tables: KHÔNG scale — giữ kích thước gốc, scroll ngang ── */
/* Wrapper ngoài: scroll ngang */
body.is-mobile-device .dash-table-container {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    max-width: 100vw !important;
    width: 100% !important;
}
/* KHÔNG set width/minWidth trên spreadsheet-container vì gây treo */
body.is-mobile-device .dash-spreadsheet-container {
    overflow: visible !important;
}
/* Cell không wrap text */
body.is-mobile-device .dash-spreadsheet td,
body.is-mobile-device .dash-spreadsheet th {
    white-space: nowrap !important;
}
/* Global btn: NGOẠI TRỪ pagination buttons + dash-filter case button */
body.is-mobile-device .btn:not(.first-page):not(.last-page):not(.previous-page):not(.next-page):not(.dash-filter--case) { min-height: 36px !important; font-size: 0.82rem !important; }
/* Pagination buttons: override global .btn min-height */
body.is-mobile-device .first-page,
body.is-mobile-device .last-page,
body.is-mobile-device .previous-page,
body.is-mobile-device .next-page,
body.is-mobile-device .previous-next-container button {
    min-height: unset !important;
    min-width: unset !important;
    height: 26px !important;
    max-height: 26px !important;
    font-size: 0.68rem !important;
    padding: 0 7px !important;
    line-height: 26px !important;
    border-radius: 4px !important;
    flex-shrink: 0 !important;
}
/* Pagination input (page number) — KHÔNG bị overwrite bởi global input { font-size:16px } */
body.is-mobile-device .current-page input,
body.is-mobile-device .previous-next-container input[type="text"],
body.is-mobile-device .previous-next-container input[type="number"] {
    font-size: 0.68rem !important;
    height: 26px !important;
    min-height: unset !important;
    width: 38px !important;
    max-width: 42px !important;
    padding: 0 3px !important;
    text-align: center !important;
    box-sizing: border-box !important;
}
/* Pagination container */
body.is-mobile-device .previous-next-container {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 3px !important;
    padding: 4px 4px !important;
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
}
/* Page count text */
body.is-mobile-device .page-number,
body.is-mobile-device .previous-next-container span {
    font-size: 0.68rem !important;
    line-height: 26px !important;
    white-space: nowrap !important;
}
/* Global inputs: 16px để tránh zoom trên iOS — NGOẠI TRỪ pagination input */
body.is-mobile-device input:not(.current-page input):not([class*="page"]),
body.is-mobile-device select,
body.is-mobile-device textarea { font-size: 16px !important; }
/* Pagination input: nhỏ, không zoom */
body.is-mobile-device .current-page input,
body.is-mobile-device .previous-next-container input {
    font-size: 0.68rem !important;
    touch-action: manipulation !important;
}
body.is-mobile-device .card { margin-bottom: 8px !important; }
body.is-mobile-device .card-body { padding: 10px !important; }
body.is-mobile-device .column-resize-handle { display: none !important; }
body.is-mobile-device #copyright-footer { font-size: 0.6rem !important; padding: 3px 8px !important; }
/* ════════════════════════════════════════════════════════════
   FIX <2+3>: Maint-settings-btn — scale nhỏ + canh giữa đúng
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device #maint-settings-btn {
    width: 28px !important;
    height: 28px !important;
    border-radius: 7px !important;
    margin-right: 4px !important;
    flex-shrink: 0 !important;
    align-self: center !important;   /* FIX <3>: canh giữa theo chiều dọc trong sub-header row */
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
body.is-mobile-device #maint-settings-btn i {
    font-size: 0.78rem !important;
    line-height: 1 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
/* Đảm bảo sub-header-wrapper.d-flex canh giữa tất cả items theo chiều dọc */
body.is-mobile-device .sub-header-wrapper.d-flex {
    align-items: center !important;
}

/* ════════════════════════════════════════════════════════════
   FIX <3>: Spare Parts sub-header — ẩn KPI badges trên mobile,
   chỉ giữ sub-tabs (scroll ngang) + thêm nút ⓘ KPI dropdown
   ════════════════════════════════════════════════════════════ */

/* Ẩn toàn bộ cụm KPI badges bên phải sub-header */
body.is-mobile-device .sub-header-wrapper.d-flex .d-flex.gap-3.align-items-center.ms-3 {
    display: none !important;
}

/* Sub-tabs flex:1 chiếm toàn bộ width khi KPI đã ẩn */
body.is-mobile-device .sub-header-wrapper.d-flex > div:first-child {
    flex: 1 !important;
    min-width: 0 !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
}
body.is-mobile-device .sub-header-wrapper.d-flex > div:first-child::-webkit-scrollbar {
    display: none !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — DataTable: thu nhỏ font + cell padding + header
   Giữ scroll ngang, không làm hỏng layout Dash
   ════════════════════════════════════════════════════════════ */

/* Bật lại overflow-x scroll cho dash-spreadsheet trên mobile */
body.is-mobile-device .dash-spreadsheet-container {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
}
body.is-mobile-device .dash-spreadsheet {
    overflow-x: auto !important;
    max-width: none !important;
    width: auto !important;
}
body.is-mobile-device .dash-spreadsheet-inner {
    overflow-x: auto !important;
    max-width: none !important;
    width: auto !important;
}

/* Header cells (th) — thu nhỏ font + padding */
body.is-mobile-device .dash-spreadsheet-inner th,
body.is-mobile-device .dash-spreadsheet-inner .dash-header th {
    font-size: 0.62rem !important;
    padding: 5px 6px !important;
    white-space: nowrap !important;
    min-width: 60px !important;
    max-width: 180px !important;
}

/* Filter row input — thu nhỏ */
body.is-mobile-device .dash-spreadsheet-inner .dash-filter input,
body.is-mobile-device .dash-spreadsheet-inner .dash-filter {
    font-size: 0.60rem !important;
    padding: 2px 4px !important;
    height: 22px !important;
}
/* "Aa" case-sensitivity button — thu nhỏ đồng bộ với filter input */
body.is-mobile-device .dash-spreadsheet .dash-filter--case {
    font-size: 0.58rem !important;
    width: 20px !important;
    height: 20px !important;
    min-width: 20px !important;
    padding: 1px 2px !important;
    line-height: 1 !important;
}
/* ── OVERRIDE: filter input bị overwrite bởi rule "input { 16px }" (iOS anti-zoom)
   Dùng html + body để tăng specificity cao hơn rule đó ── */
html body.is-mobile-device .dash-spreadsheet-container .dash-spreadsheet-inner .dash-filter input {
    font-size: 0.60rem !important;
    height: 22px !important;
    padding: 2px 4px !important;
    min-height: unset !important;
    touch-action: manipulation !important;
}
/* ── OVERRIDE: "Aa" button bị overwrite bởi rule ".btn { 0.82rem }" (global btn rule)
   Dùng html + body để tăng specificity cao hơn rule đó ── */
html body.is-mobile-device .dash-spreadsheet-container .dash-spreadsheet .dash-filter--case {
    font-size: 0.60rem !important;
    width: 20px !important;
    height: 20px !important;
    min-width: 20px !important;
    min-height: unset !important;
    padding: 1px 3px !important;
    line-height: 1 !important;
}

/* Data cells (td) — thu nhỏ font + padding */
body.is-mobile-device .dash-spreadsheet-inner td,
body.is-mobile-device .dash-spreadsheet-inner .dash-cell td,
body.is-mobile-device .dash-spreadsheet td {
    font-size: 0.62rem !important;
    padding: 4px 6px !important;
    white-space: nowrap !important;
    min-width: 60px !important;
    max-width: 200px !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

/* "Hiển thị X/trang" row — thu nhỏ */
body.is-mobile-device .dash-table-container .row-count-select,
body.is-mobile-device .dash-table-container .dash-table-tooltip,
body.is-mobile-device .dash-table-container [class*="page"] {
    font-size: 0.65rem !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — KPI Cards (Overview tab): thu nhỏ toàn bộ
   ════════════════════════════════════════════════════════════ */

body.is-mobile-device .kpi-card-compact {
    min-height: 48px !important;
    height: auto !important;
    padding: 5px 8px !important;
    border-radius: 7px !important;
}

/* Row 1: icon + value */
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 {
    font-size: 0.78rem !important;
    gap: 3px !important;
    line-height: 1.2 !important;
}
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 i {
    font-size: 0.72rem !important;
}

/* Row 2: label */
body.is-mobile-device .kpi-card-compact .kpi-compact-row2 {
    font-size: 0.50rem !important;
    line-height: 1.2 !important;
    margin-top: 1px !important;
}

/* KPI grid: cố định 3 per row — bắt cả className="col" (không có "-") lẫn className="col-4" */
body.is-mobile-device .sticky-metrics .row > [class*="col-"],
body.is-mobile-device .sticky-metrics .row > .col,
body.is-mobile-device .sticky-metrics .row > div {
    flex: 0 0 33.333% !important;
    max-width: 33.333% !important;
    width: 33.333% !important;
    padding-left: 2px !important;
    padding-right: 2px !important;
    box-sizing: border-box !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — KPI Badges (Spare Parts sub-header)
   ════════════════════════════════════════════════════════════ */

body.is-mobile-device .kpi-badge {
    padding: 4px 8px !important;
    border-radius: 7px !important;
    min-width: 0 !important;
}
body.is-mobile-device .kpi-badge .kpi-badge-row1 {
    font-size: 0.78rem !important;
    line-height: 1.2 !important;
}
body.is-mobile-device .kpi-badge .kpi-badge-row2 {
    font-size: 0.48rem !important;
    line-height: 1.2 !important;
}

/* Compact badges inside sub-header bar */
body.is-mobile-device .sub-header-wrapper.d-flex .kpi-badge {
    padding: 3px 7px !important;
}
body.is-mobile-device .sub-header-wrapper.d-flex .kpi-badge .kpi-badge-row1 {
    font-size: 0.68rem !important;
}
body.is-mobile-device .sub-header-wrapper.d-flex .kpi-badge .kpi-badge-row2 {
    font-size: 0.44rem !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — Charts: thu nhỏ font trong chart title/axis/legend
   (Plotly tự render svg text — cần override qua layout trong Python
    Ở đây chỉ scale container và modebar)
   ════════════════════════════════════════════════════════════ */

/* Chart wrapper: giảm padding */
body.is-mobile-device .chart-container {
    padding: 4px !important;
    margin-bottom: 6px !important;
}

/* Plotly modebar — thu nhỏ */
body.is-mobile-device .modebar {
    transform: scale(0.75) !important;
    transform-origin: top right !important;
}

/* Plotly chart title text — thu nhỏ (áp dụng cho svg text) */
body.is-mobile-device .js-plotly-plot .gtitle,
body.is-mobile-device .js-plotly-plot text.gtitle {
    font-size: 11px !important;
}
body.is-mobile-device .js-plotly-plot .xtitle,
body.is-mobile-device .js-plotly-plot .ytitle {
    font-size: 9px !important;
}

/* Giảm padding card-body bọc chart */
body.is-mobile-device .card-body {
    padding: 6px !important;
}

/* Chart info icon */
body.is-mobile-device .chart-info-icon {
    font-size: 0.65rem !important;
    top: 4px !important;
    left: 4px !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — Forecast chart section title + legend text
   ════════════════════════════════════════════════════════════ */

/* Section heading bên trong tab content */
body.is-mobile-device .tab-pane h4,
body.is-mobile-device .tab-pane h5,
body.is-mobile-device #tab-content-wrapper h4,
body.is-mobile-device #tab-content-wrapper h5 {
    font-size: 0.82rem !important;
    margin-bottom: 4px !important;
}

/* Alert / badge text bên trong content */
body.is-mobile-device .tab-pane .badge,
body.is-mobile-device #tab-content-wrapper .badge {
    font-size: 0.55rem !important;
    padding: 2px 5px !important;
}

/* Analysis text blocks */
body.is-mobile-device .border-start.border-primary,
body.is-mobile-device .border-start.border-success {
    font-size: 0.65rem !important;
    padding: 6px 10px !important;
}
body.is-mobile-device .border-start p,
body.is-mobile-device .border-start li,
body.is-mobile-device .border-start span {
    font-size: 0.65rem !important;
    line-height: 1.4 !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX — General content font scale
   ════════════════════════════════════════════════════════════ */

/* Main content area base font */
body.is-mobile-device .main-content {
    font-size: 0.72rem !important;
}

/* Dropdown / select labels */
body.is-mobile-device .Select-value-label,
body.is-mobile-device .Select-placeholder {
    font-size: 0.68rem !important;
}

/* Dropdown options */
body.is-mobile-device .Select-option {
    font-size: 0.68rem !important;
    padding: 5px 8px !important;
}

/* dcc.Dropdown */
body.is-mobile-device .VirtualizedSelectOption {
    font-size: 0.68rem !important;
    padding: 4px 8px !important;
}

/* Label/text above filters */
body.is-mobile-device label,
body.is-mobile-device .form-label {
    font-size: 0.65rem !important;
    margin-bottom: 2px !important;
}

/* Filter row inputs */
body.is-mobile-device .filter-row input,
body.is-mobile-device .filter-row .Select-control {
    font-size: 0.68rem !important;
    height: 28px !important;
    min-height: 28px !important;
}

/* Tabs inside content panes */
body.is-mobile-device .nav-tabs .nav-link {
    font-size: 0.62rem !important;
    padding: 3px 7px !important;
}


/* ════════════════════════════════════════════════════════════
   SCALE FIX v2 — Sidebar width + tất cả Modals trên mobile
   ════════════════════════════════════════════════════════════ */

/* ── SIDEBAR: thu nhỏ width + nội dung bên trong ─────────── */
body.is-mobile-device {
    --sidebar-width-mobile: 230px;   /* giảm từ 285px xuống 230px */
}

/* Sidebar scrollable + sticky sections: giảm padding */
body.is-mobile-device .sidebar-sticky-section {
    padding: 0.6rem 0.75rem 0.4rem 0.75rem !important;
}
body.is-mobile-device .sidebar-scrollable-section {
    padding: 0.5rem 0.75rem 0.75rem 0.75rem !important;
}

/* Accordion button trong sidebar */
body.is-mobile-device .sidebar .accordion-button {
    font-size: 0.72rem !important;
    padding: 8px 10px !important;
}
body.is-mobile-device .sidebar .accordion-body {
    padding: 8px !important;
}

/* Sync / Restart / Stop buttons trong sidebar */
body.is-mobile-device .sidebar .btn-primary,
body.is-mobile-device .sidebar .btn-warning,
body.is-mobile-device .sidebar .btn-danger {
    padding: 7px 12px !important;
    font-size: 0.68rem !important;
    border-radius: 7px !important;
}

/* Select / Dropdown trong sidebar */
body.is-mobile-device .sidebar .Select-control {
    height: 26px !important;
    min-height: 26px !important;
}
body.is-mobile-device .sidebar .Select-value-label,
body.is-mobile-device .sidebar .Select-placeholder {
    font-size: 0.65rem !important;
    line-height: 26px !important;
}
body.is-mobile-device .sidebar label,
body.is-mobile-device .sidebar .form-label {
    font-size: 0.60rem !important;
    margin-bottom: 2px !important;
}
body.is-mobile-device .sidebar input,
body.is-mobile-device .sidebar .form-control {
    font-size: 0.68rem !important;
    padding: 3px 6px !important;
    height: 26px !important;
    min-height: 26px !important;
}

/* ── MODAL TOÀN CỤC: full-width + max-height trên mobile ──── */
/* Tất cả modal dialog: chiều ngang = 100vw, sát cạnh */
body.is-mobile-device .modal-dialog {
    max-width: 100vw !important;
    width: 100vw !important;
    margin: 0 !important;
    padding: 0 !important;
}
/* Modal content: max-height = màn hình trừ navbar */
body.is-mobile-device .modal-content {
    border-radius: 0 !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    overflow-y: auto !important;
}
body.is-mobile-device .modal-header {
    padding: 8px 12px !important;
}
body.is-mobile-device .modal-title {
    font-size: 0.82rem !important;
}
body.is-mobile-device .modal-body {
    padding: 8px 10px !important;
    font-size: 0.70rem !important;
}
body.is-mobile-device .modal-footer {
    padding: 6px 10px !important;
    gap: 4px !important;
}
body.is-mobile-device .modal-footer .btn {
    font-size: 0.65rem !important;
    padding: 4px 8px !important;
    min-height: 28px !important;
}

/* ── MODAL: Admin (tabs + bảng user) ─────────────────────── */
/* height: auto — được handle bởi :has() rule ở cuối file */
body.is-mobile-device #admin-modal #admin-main-tabs .nav-link,
body.is-mobile-device .modal #admin-main-tabs .nav-link {
    font-size: 0.60rem !important;
    padding: 4px 7px !important;
}
body.is-mobile-device #admin-modal .modal-body {
    padding: 4px !important;
}

/* ── MODAL: User Logs ─────────────────────────────────────── */
body.is-mobile-device #user-logs-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
    max-width: 100vw !important;
    width: 100vw !important;
}
body.is-mobile-device #user-logs-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}
body.is-mobile-device #user-logs-modal .modal-header {
    padding: 6px 10px !important;
}
body.is-mobile-device #user-logs-modal .modal-title {
    font-size: 0.78rem !important;
}
body.is-mobile-device #user-logs-modal .modal-body {
    padding: 6px 8px !important;
    font-size: 0.65rem !important;
}
body.is-mobile-device .user-logs-stats-badges .badge {
    font-size: 0.58rem !important;
    padding: 4px 8px !important;
}
body.is-mobile-device .user-logs-stats-card-title {
    font-size: 0.62rem !important;
}
body.is-mobile-device .user-logs-stats-list li {
    font-size: 0.60rem !important;
}

/* ── MODAL: App/Sync Logs ─────────────────────────────────── */
body.is-mobile-device #sync-logs-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
}
body.is-mobile-device #sync-logs-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}

/* ── MODAL: Online Users ──────────────────────────────────── */
body.is-mobile-device #online-users-modal .modal-dialog {
    max-width: 95vw !important;
    width: 95vw !important;
    margin: calc(var(--navbar-height, 62px) + 8px) auto 0 auto !important;
}
body.is-mobile-device #online-users-modal .modal-content {
    max-height: 70vh !important;
    height: auto !important;
    border-radius: 8px !important;
}

/* ── MODAL: About ─────────────────────────────────────────── */
body.is-mobile-device #about-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
}
body.is-mobile-device #about-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}
body.is-mobile-device #about-modal .modal-body p,
body.is-mobile-device #about-modal .modal-body li,
body.is-mobile-device #about-modal .modal-body span {
    font-size: 0.68rem !important;
    line-height: 1.5 !important;
}
body.is-mobile-device #about-modal .modal-body h4,
body.is-mobile-device #about-modal .modal-body h5 {
    font-size: 0.80rem !important;
}

/* ── MODAL: Layout Editor ─────────────────────────────────── */
body.is-mobile-device #layout-editor-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
}
body.is-mobile-device #layout-editor-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}
/* Layout editor tabs */
body.is-mobile-device #layout-editor-tabs .nav-link {
    font-size: 0.58rem !important;
    padding: 3px 5px !important;
}
/* Layout item rows */
body.is-mobile-device .layout-kpi-item,
body.is-mobile-device .layout-chart-item {
    font-size: 0.60rem !important;
    padding: 4px 6px !important;
}

/* ── MODAL: Maint Checklist Detail ────────────────────────── */
body.is-mobile-device #maint-cl-detail-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
}
body.is-mobile-device #maint-cl-detail-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}
/* Bảng chi tiết checklist */
body.is-mobile-device .maint-cl-detail-table th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}
body.is-mobile-device .maint-cl-detail-table td {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
}
body.is-mobile-device .maint-cl-dropdown .Select-control {
    height: 24px !important;
    min-height: 24px !important;
}
body.is-mobile-device .maint-cl-dropdown {
    font-size: 0.60rem !important;
}
body.is-mobile-device .maint-cl-summary {
    font-size: 0.60rem !important;
    padding: 5px 8px !important;
}

/* ── MODAL: Maint Settings ────────────────────────────────── */
body.is-mobile-device #maint-settings-modal .modal-dialog {
    margin: var(--navbar-height, 62px) 0 0 0 !important;
    max-width: 100vw !important;
    width: 100vw !important;
}
body.is-mobile-device #maint-settings-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    border-radius: 0 !important;
}
/* Tabs trong maint settings */
body.is-mobile-device #maint-settings-modal .nav-link {
    font-size: 0.60rem !important;
    padding: 4px 7px !important;
}
/* Planning + Details bảng bên trong settings modal */
body.is-mobile-device #maint-settings-modal th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}
body.is-mobile-device #maint-settings-modal td {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
}
body.is-mobile-device #maint-settings-modal .btn {
    font-size: 0.60rem !important;
    padding: 3px 7px !important;
}
body.is-mobile-device #maint-settings-modal input,
body.is-mobile-device #maint-settings-modal .form-control {
    font-size: 0.68rem !important;
    padding: 3px 6px !important;
    height: 26px !important;
}
body.is-mobile-device #maint-settings-modal label {
    font-size: 0.60rem !important;
}

/* ── MODAL: Spare Parts mini-modal ────────────────────────── */
body.is-mobile-device #maint-sp-mini-modal {
    max-width: 95vw !important;
    width: 95vw !important;
    margin: calc(var(--navbar-height, 62px) + 8px) auto 0 auto !important;
}
body.is-mobile-device #maint-sp-mini-modal > .modal-content {
    max-height: 80vh !important;
    border-radius: 8px !important;
}
body.is-mobile-device .sp-inv-th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}
body.is-mobile-device #maint-sp-mini-modal td {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
}

/* ── MODAL: Batch Export ──────────────────────────────────── */
body.is-mobile-device #batch-export-modal .modal-dialog {
    margin: calc(var(--navbar-height, 62px) + 4px) 0 0 0 !important;
}
body.is-mobile-device #batch-export-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px) - 4px) !important;
    max-height: calc(100vh - var(--navbar-height, 62px) - 4px) !important;
    border-radius: 0 !important;
}
body.is-mobile-device #batch-export-modal label {
    font-size: 0.65rem !important;
}
body.is-mobile-device #batch-export-modal .form-check-label {
    font-size: 0.62rem !important;
}

/* ── PLANNING sub-tab: thu nhỏ bảng + form ────────────────── */
body.is-mobile-device .maint-planning-table {
    font-size: 0.62rem !important;
}
body.is-mobile-device .maint-planning-table thead th {
    font-size: 0.60rem !important;
    padding: 4px 5px !important;
}
body.is-mobile-device .maint-planning-table td {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
}
/* Form thêm/sửa planning */
body.is-mobile-device .maint-add-form-card {
    padding: 6px 8px !important;
}
body.is-mobile-device .maint-add-form-card label {
    font-size: 0.60rem !important;
}
body.is-mobile-device .maint-add-form-card input,
body.is-mobile-device .maint-add-form-card .form-control {
    font-size: 0.65rem !important;
    height: 26px !important;
    padding: 2px 6px !important;
}
body.is-mobile-device .maint-add-form-card .btn {
    font-size: 0.60rem !important;
    padding: 3px 7px !important;
}

/* ── DETAILS sub-tab: checklist list items ─────────────────── */
body.is-mobile-device .maint-checklist-list-item {
    padding: 6px 8px !important;
    font-size: 0.65rem !important;
    border-radius: 6px !important;
}
body.is-mobile-device .maint-checklist-list-item .badge {
    font-size: 0.52rem !important;
    padding: 2px 5px !important;
}

/* ── AREA TREE TABLE ──────────────────────────────────────── */
body.is-mobile-device .maint-area-tree-table {
    font-size: 0.60rem !important;
}
body.is-mobile-device .maint-area-tree-header th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}

/* ── SESSION DETAILS MODAL ────────────────────────────────── */
body.is-mobile-device #session-details-modal .modal-dialog {
    max-width: 95vw !important;
    width: 95vw !important;
    margin: calc(var(--navbar-height, 62px) + 8px) auto 0 auto !important;
}
body.is-mobile-device #session-details-modal .modal-content {
    border-radius: 8px !important;
    max-height: 80vh !important;
}

/* ── SESSIONS LIST MODAL (active sessions / request logout) ── */
body.is-mobile-device #sessions-list-modal .modal-dialog {
    max-width: 96vw !important;
    width: 96vw !important;
    margin: calc(var(--navbar-height, 62px) + 8px) auto 0 auto !important;
}
body.is-mobile-device #sessions-list-modal .modal-content {
    border-radius: 8px !important;
    max-height: 85vh !important;
    overflow: hidden !important;
}
body.is-mobile-device #sessions-list-modal .modal-body {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    padding: 10px 10px !important;
}
/* Each session row: wrap nội dung, không bị tràn ra ngoài */
body.is-mobile-device #sessions-list-modal .session-detail-item {
    flex-wrap: wrap !important;
    row-gap: 4px !important;
    padding: 8px 8px !important;
    overflow: hidden !important;
}
/* Các span info trong session row: thu nhỏ font */
body.is-mobile-device #sessions-list-modal .session-detail-item span,
body.is-mobile-device #sessions-list-modal .session-detail-item code {
    font-size: 0.70rem !important;
}
/* Nút Request Logout: luôn hiển thị, không bị đẩy ra ngoài */
body.is-mobile-device #sessions-list-modal .yield-req-btn {
    flex-shrink: 0 !important;
    margin-left: auto !important;
    font-size: 0.70rem !important;
    padding: 3px 8px !important;
}
/* Title trong header: wrap thay vì overflow */
body.is-mobile-device #sessions-list-modal .modal-title {
    width: 100% !important;
    overflow: hidden !important;
}
/* Footer buttons: đủ khoảng cách */
body.is-mobile-device #sessions-list-modal .modal-footer {
    padding: 8px 12px !important;
    gap: 8px !important;
}
body.is-mobile-device #sessions-list-modal .modal-footer .btn {
    font-size: 0.75rem !important;
    padding: 4px 12px !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX v3 — Sidebar thu nhỏ hơn + Containers + Notification
   + Planning/Details wrapper + Modal còn thiếu
   ════════════════════════════════════════════════════════════ */

/* ── SIDEBAR: giảm thêm width và toàn bộ nội dung ─────────── */
body.is-mobile-device {
    --sidebar-width-mobile: 210px;
}

/* Logo trong sidebar + dept text */
body.is-mobile-device .sidebar-sticky-section img,
body.is-mobile-device .sidebar img[id*="logo"] {
    max-height: 28px !important;
    width: auto !important;
}
body.is-mobile-device .sidebar-sticky-section p,
body.is-mobile-device .sidebar-sticky-section small {
    font-size: 0.55rem !important;
}

/* Accordion trong sidebar: label font, icon, spacing */
body.is-mobile-device .sidebar .accordion-button {
    font-size: 0.68rem !important;
    padding: 7px 8px !important;
    gap: 5px !important;
}
body.is-mobile-device .sidebar .accordion-button i {
    font-size: 0.68rem !important;
}
body.is-mobile-device .sidebar .accordion-body {
    padding: 6px 8px !important;
}
body.is-mobile-device .sidebar .accordion-item {
    border-radius: 6px !important;
}

/* Sidebar label + input + select */
body.is-mobile-device .sidebar label,
body.is-mobile-device .sidebar .form-label {
    font-size: 0.58rem !important;
    margin-bottom: 1px !important;
}
body.is-mobile-device .sidebar .form-control,
body.is-mobile-device .sidebar input:not([type="checkbox"]):not([type="radio"]) {
    font-size: 0.65rem !important;
    padding: 2px 5px !important;
    height: 24px !important;
    min-height: 24px !important;
}
body.is-mobile-device .sidebar .Select-control {
    height: 24px !important;
    min-height: 24px !important;
}
body.is-mobile-device .sidebar .Select-value-label,
body.is-mobile-device .sidebar .Select-placeholder,
body.is-mobile-device .sidebar .Select-option {
    font-size: 0.62rem !important;
    line-height: 24px !important;
}
body.is-mobile-device .sidebar .Select-arrow-zone {
    width: 16px !important;
}

/* Sidebar buttons */
body.is-mobile-device .sidebar .btn {
    font-size: 0.62rem !important;
    padding: 5px 8px !important;
    border-radius: 6px !important;
    min-height: 28px !important;
}

/* Date picker input trong sidebar */
body.is-mobile-device .sidebar .DateInput_input,
body.is-mobile-device .sidebar .DateRangePickerInput {
    font-size: 0.60rem !important;
    padding: 2px 4px !important;
}
body.is-mobile-device .sidebar .DateRangePicker_picker {
    transform: scale(0.82) !important;
    transform-origin: top left !important;
}

/* ── NOTIFICATION POPUP (Alert bell) ──────────────────────── */
body.is-mobile-device .alert-popup {
    width: calc(100vw - 12px) !important;
    max-width: calc(100vw - 12px) !important;
    right: -4px !important;
    max-height: 70vh !important;
    border-radius: 8px !important;
}
body.is-mobile-device .alert-popup-header {
    padding: 8px 12px !important;
    font-size: 0.72rem !important;
}
body.is-mobile-device .alert-popup-close {
    font-size: 1.1rem !important;
}
body.is-mobile-device .alert-popup-content {
    padding: 8px 10px !important;
    max-height: calc(70vh - 60px) !important;
    font-size: 0.65rem !important;
}
body.is-mobile-device .alert-popup-content * {
    font-size: 0.65rem !important;
}
body.is-mobile-device .no-alerts-msg {
    font-size: 0.65rem !important;
    padding: 12px !important;
}

/* ── PLANNING sub-tab: container + filter bar ─────────────── */
body.is-mobile-device #maint-planning-filter,
body.is-mobile-device #maint-details-filter {
    padding: 4px 6px !important;
    gap: 4px !important;
}
body.is-mobile-device #maint-planning-filter .form-control,
body.is-mobile-device #maint-details-filter .form-control,
body.is-mobile-device #maint-planning-filter input,
body.is-mobile-device #maint-details-filter input {
    font-size: 0.62rem !important;
    height: 24px !important;
    padding: 2px 6px !important;
}
body.is-mobile-device #maint-planning-filter .btn,
body.is-mobile-device #maint-details-filter .btn {
    font-size: 0.60rem !important;
    padding: 2px 7px !important;
    height: 24px !important;
    min-height: 24px !important;
}
body.is-mobile-device #maint-planning-filter label,
body.is-mobile-device #maint-details-filter label {
    font-size: 0.58rem !important;
}
body.is-mobile-device #maint-planning-filter .Select-control,
body.is-mobile-device #maint-details-filter .Select-control {
    height: 24px !important;
    min-height: 24px !important;
}
body.is-mobile-device #maint-planning-filter .Select-value-label,
body.is-mobile-device #maint-details-filter .Select-value-label {
    font-size: 0.60rem !important;
    line-height: 24px !important;
}

/* Planning scroll container: giảm max-height cho mobile */
body.is-mobile-device .maint-planning-table-scroll {
    max-height: calc(100vh - var(--navbar-height, 62px) - 140px) !important;
}

/* ══ PLANNING HEADER: tiêu đề + nút "Thêm kế hoạch" ══════════ */
/* <1> Giảm font tiêu đề "Kế hoạch Bảo trì" */
body.is-mobile-device .planning-title,
body.is-mobile-device .planning-title * {
    font-size: 0.85rem !important;
}
/* <2> Giảm kích thước button "Thêm kế hoạch" */
html body.is-mobile-device #maint-plan-add-btn {
    font-size: 0.70rem !important;
    padding: 4px 10px !important;
    min-height: unset !important;
    height: auto !important;
    line-height: 1.4 !important;
}

/* ══ PLANNING FORM: layout gọn 2 cột + datepicker nhỏ ════════ */
/* <3> Giảm font ô chọn ngày */
body.is-mobile-device .planning-datepicker-wrap .DateInput_input {
    font-size: 0.68rem !important;
    padding: 4px 6px !important;
    height: 28px !important;
    text-align: center !important;
}
/* Form container: 2-column grid thay vì 1 field/dòng */
body.is-mobile-device .maint-add-form-card .d-flex.flex-wrap {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 5px 8px !important;
    align-items: end !important;
}
/* Ngày: chiếm 1 cột */
body.is-mobile-device .maint-add-form-card .plan-form-field {
    min-width: unset !important;
    flex: unset !important;
    width: 100% !important;
}
/* Buttons (Lưu + Hủy): chiếm 1 cột, align cuối hàng */
body.is-mobile-device .maint-add-form-card .plan-form-field:last-child {
    grid-column: 2 / 3 !important;
    align-self: end !important;
}
/* Label trong form */
body.is-mobile-device .maint-add-form-card .form-label {
    font-size: 0.60rem !important;
    margin-bottom: 2px !important;
}
/* Dropdown options */
body.is-mobile-device .maint-add-form-card .plan-dropdown .Select-control,
body.is-mobile-device .maint-add-form-card .plan-dropdown .Select-placeholder,
body.is-mobile-device .maint-add-form-card .plan-dropdown .Select-value-label {
    font-size: 0.65rem !important;
    min-height: 28px !important;
    line-height: 28px !important;
}
body.is-mobile-device .maint-add-form-card .plan-dropdown .Select-input {
    height: 28px !important;
}
/* Lưu / Hủy button trong form */
html body.is-mobile-device .maint-add-form-card .plan-form-field .btn {
    font-size: 0.65rem !important;
    padding: 4px 8px !important;
    min-height: unset !important;
    height: auto !important;
}
/* Card header "Thêm kế hoạch mới" */
body.is-mobile-device .maint-add-form-card .card-header {
    font-size: 0.68rem !important;
    padding: 5px 10px !important;
}

/* Planning form card: thu nhỏ */
body.is-mobile-device .maint-add-form-card {
    font-size: 0.62rem !important;
}
body.is-mobile-device .maint-add-form-card .row > [class*="col-"] {
    flex: 0 0 100% !important;
    max-width: 100% !important;
    padding: 2px 4px !important;
}

/* ── DETAILS sub-tab: checklist list ─────────────────────── */
body.is-mobile-device .maint-checklist-list {
    gap: 4px !important;
}
body.is-mobile-device .maint-checklist-list-item {
    padding: 5px 7px !important;
    font-size: 0.62rem !important;
}
body.is-mobile-device .maint-checklist-list-item h6,
body.is-mobile-device .maint-checklist-list-item .fw-semibold {
    font-size: 0.62rem !important;
}
body.is-mobile-device .maint-checklist-list-item small,
body.is-mobile-device .maint-checklist-list-item .small {
    font-size: 0.55rem !important;
}

/* ── MODAL: Checklist Detail (nội dung bên trong) ─────────── */
body.is-mobile-device #maint-cl-detail-modal .modal-body {
    padding: 6px !important;
}
/* Summary box */
body.is-mobile-device .maint-cl-modal-body-inner .maint-cl-summary {
    font-size: 0.58rem !important;
    padding: 4px 7px !important;
    margin-bottom: 4px !important;
}
/* Bảng checklist bên trong modal */
body.is-mobile-device #maint-cl-modal-table {
    overflow-x: auto !important;
}
body.is-mobile-device #maint-cl-modal-table th {
    font-size: 0.56rem !important;
    padding: 3px 4px !important;
    white-space: nowrap !important;
}
body.is-mobile-device #maint-cl-modal-table td {
    font-size: 0.58rem !important;
    padding: 2px 4px !important;
}

/* ── MODAL: Maint Settings – tabs + content bên trong ─────── */
body.is-mobile-device #maint-settings-modal .modal-body {
    padding: 4px !important;
}
/* Các sub-tab row trong settings */
body.is-mobile-device #maint-settings-modal .row > [class*="col-"] {
    padding: 2px 4px !important;
}
/* Table trong settings area-tree / equipment list */
body.is-mobile-device #maint-settings-modal table th {
    font-size: 0.56rem !important;
    padding: 3px 4px !important;
}
body.is-mobile-device #maint-settings-modal table td {
    font-size: 0.58rem !important;
    padding: 2px 4px !important;
}

/* ── MODAL: Admin – user list table ──────────────────────── */
body.is-mobile-device #admin-modal .modal-body {
    padding: 4px !important;
}
body.is-mobile-device #admin-modal table th,
body.is-mobile-device #admin-modal .user-header-text {
    font-size: 0.55rem !important;
    padding: 3px 4px !important;
}
body.is-mobile-device #admin-modal table td,
body.is-mobile-device #admin-modal .user-row {
    font-size: 0.58rem !important;
    padding: 4px 3px !important;
}
body.is-mobile-device #admin-modal .user-display-name {
    font-size: 0.60rem !important;
}
body.is-mobile-device #admin-modal .badge,
body.is-mobile-device #admin-modal .user-status-badge {
    font-size: 0.50rem !important;
    padding: 1px 4px !important;
}
body.is-mobile-device #admin-modal .btn {
    font-size: 0.55rem !important;
    padding: 2px 5px !important;
    min-height: 22px !important;
}

/* ── MODAL: Online Users ─────────────────────────────────── */
body.is-mobile-device #online-users-modal .modal-body {
    padding: 6px 8px !important;
    font-size: 0.65rem !important;
}
body.is-mobile-device #online-users-modal table th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}
body.is-mobile-device #online-users-modal table td {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
}
body.is-mobile-device #online-users-modal .badge {
    font-size: 0.50rem !important;
    padding: 2px 5px !important;
}

/* ── MODAL: App / Sync Logs – log text ──────────────────── */
body.is-mobile-device #sync-logs-modal .modal-body {
    padding: 6px 8px !important;
    font-size: 0.60rem !important;
}
body.is-mobile-device #sync-logs-modal pre,
body.is-mobile-device #sync-logs-modal code,
body.is-mobile-device #sync-logs-modal .log-line {
    font-size: 0.58rem !important;
    line-height: 1.4 !important;
}

/* ── MODAL: About – version info + text ─────────────────── */
body.is-mobile-device #about-modal .modal-body {
    padding: 8px 10px !important;
}
body.is-mobile-device #about-modal h3 {
    font-size: 0.85rem !important;
}
body.is-mobile-device #about-modal .card {
    margin-bottom: 6px !important;
}
body.is-mobile-device #about-modal .card-body {
    padding: 6px 8px !important;
}

/* ── MODAL: Layout Editor – drag-drop items ─────────────── */
body.is-mobile-device #layout-editor-modal .modal-body {
    padding: 4px !important;
}
body.is-mobile-device .layout-kpi-item,
body.is-mobile-device .layout-chart-item {
    font-size: 0.58rem !important;
    padding: 3px 5px !important;
}
body.is-mobile-device #layout-editor-modal .card-body {
    padding: 5px !important;
}
body.is-mobile-device #layout-editor-modal .card-title,
body.is-mobile-device #layout-editor-modal h6 {
    font-size: 0.62rem !important;
}

/* ── MODAL: User Logs – thêm các element chưa scale ─────── */
body.is-mobile-device #user-logs-modal .DateInput_input {
    font-size: 0.60rem !important;
    padding: 2px 4px !important;
}
body.is-mobile-device #user-logs-modal .btn-group .btn {
    font-size: 0.60rem !important;
    padding: 2px 5px !important;
    min-height: 24px !important;
}
body.is-mobile-device #user-logs-modal .input-group-text {
    font-size: 0.60rem !important;
    padding: 2px 5px !important;
}
body.is-mobile-device #user-logs-modal label {
    font-size: 0.60rem !important;
}

/* ── CARD containers trong main content ──────────────────── */
body.is-mobile-device .card {
    margin-bottom: 6px !important;
}
body.is-mobile-device .card-header {
    padding: 5px 8px !important;
    font-size: 0.68rem !important;
}
body.is-mobile-device .card-title {
    font-size: 0.68rem !important;
    margin-bottom: 3px !important;
}

/* ── Bootstrap row/col gap reduction ─────────────────────── */
body.is-mobile-device .g-4 { --bs-gutter-x: 0.5rem !important; --bs-gutter-y: 0.5rem !important; }
body.is-mobile-device .g-3 { --bs-gutter-x: 0.4rem !important; --bs-gutter-y: 0.4rem !important; }
body.is-mobile-device .g-2 { --bs-gutter-x: 0.3rem !important; --bs-gutter-y: 0.3rem !important; }
body.is-mobile-device .gap-3 { gap: 0.4rem !important; }
body.is-mobile-device .gap-2 { gap: 0.3rem !important; }
body.is-mobile-device .py-3 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
body.is-mobile-device .py-2 { padding-top: 0.35rem !important; padding-bottom: 0.35rem !important; }
body.is-mobile-device .px-3 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; }
body.is-mobile-device .mb-3 { margin-bottom: 0.4rem !important; }
body.is-mobile-device .mb-4 { margin-bottom: 0.5rem !important; }
body.is-mobile-device .mt-3 { margin-top: 0.4rem !important; }

/* ════════════════════════════════════════════════════════════
   SCALE FIX v4 — Toàn diện: confirm modals, checklist cols,
   app logs, sidebar headings, greeting
   ════════════════════════════════════════════════════════════ */

/* ── FIX 1: Small confirm/alert modals — height: auto (không expand full viewport) ── */
/* Global rule: chỉ set max-height, KHÔNG set height cứng */
body.is-mobile-device .modal-content {
    height: auto !important;                                        /* override các rule height:calc(...) cũ */
    max-height: calc(100vh - var(--navbar-height, 62px)) !important;
    overflow-y: auto !important;
}

/* Các modal LỚN cần full height — ghi đè lại height: auto ở trên */
/* admin-modal KHÔNG vào đây — nó cần auto height khi đang login */
body.is-mobile-device #user-logs-modal .modal-content,
body.is-mobile-device #sync-logs-modal .modal-content,
body.is-mobile-device #about-modal .modal-content,
body.is-mobile-device #layout-editor-modal .modal-content,
body.is-mobile-device #maint-cl-detail-modal .modal-content,
body.is-mobile-device #maint-settings-modal .modal-content,
body.is-mobile-device #batch-export-modal .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
}

/* admin-modal: full height CHỈ khi đã authenticated (settings section visible) */
body.is-mobile-device #admin-modal:has(#admin-settings-section[style*="flex"]) .modal-content {
    height: calc(100vh - var(--navbar-height, 62px)) !important;
}

/* ── FIX 2: Sidebar — greeting text (inline style fontSize:0.9rem — override bằng !important) ── */
body.is-mobile-device #navbar-username,
body.is-mobile-device .sidebar-username {
    font-size: 0.62rem !important;
    font-weight: 600 !important;
}
body.is-mobile-device #sidebar-welcome-row {
    margin-bottom: 4px !important;
}

/* ── FIX 3: Sidebar — tất cả H6, section headings, filter titles ── */
body.is-mobile-device .sidebar h6,
body.is-mobile-device .sidebar .h6,
body.is-mobile-device #sidebar-header-container h6,
body.is-mobile-device #sidebar-header-container .fw-bold,
body.is-mobile-device .sidebar .fw-bold.text-uppercase,
body.is-mobile-device .sidebar .text-primary.fw-bold,
body.is-mobile-device .sidebar .text-success.fw-bold,
body.is-mobile-device .sidebar .mb-2.fw-bold,
body.is-mobile-device .sidebar .mb-3.fw-bold {
    font-size: 0.62rem !important;
    margin-bottom: 3px !important;
}
body.is-mobile-device .sidebar h6 i,
body.is-mobile-device #sidebar-header-container i {
    font-size: 0.62rem !important;
}

/* Filter section headings bên trong Planning / Details filter bars */
body.is-mobile-device #maint-planning-filter h6,
body.is-mobile-device #maint-planning-filter .fw-bold,
body.is-mobile-device #maint-details-filter h6,
body.is-mobile-device #maint-details-filter .fw-bold,
body.is-mobile-device #maint-planning-filter .text-primary,
body.is-mobile-device #maint-details-filter .text-primary {
    font-size: 0.60rem !important;
}

/* Report filter title bên trong sidebar */
body.is-mobile-device .sidebar .fw-bold.text-primary i,
body.is-mobile-device .sidebar [class*="filter"] .fw-bold {
    font-size: 0.60rem !important;
}

/* Bộ lọc / Bộ lọc Details / Bộ lọc Báo cáo headings (H6 class trong sidebar) */
body.is-mobile-device .sidebar .accordion-button span,
body.is-mobile-device .sidebar .accordion-button {
    font-size: 0.65rem !important;
}

/* ── FIX 4: Checklist detail modal — col "Hạng mục chi tiết" (maint-cl-detail-pre) ── */
/* Pre có font-size: 0.82rem desktop nhưng minWidth 330px — trên mobile scale nhỏ */
body.is-mobile-device .maint-cl-detail-pre {
    font-size: 0.58rem !important;
    line-height: 1.4 !important;
}
body.is-mobile-device .cl-detail-cell {
    min-width: 120px !important;
    max-width: 200px !important;
}

/* All other checklist group cells */
body.is-mobile-device .cl-group-cell,
body.is-mobile-device .cl-comp-cell,
body.is-mobile-device .cl-sys-cell,
body.is-mobile-device .cl-eq-cell,
body.is-mobile-device .cl-area-cell {
    font-size: 0.58rem !important;
    padding: 3px 4px !important;
    min-width: 60px !important;
    max-width: 120px !important;
}

/* Checklist dropdown cells */
body.is-mobile-device #maint-cl-modal-table .maint-cl-dropdown .Select-control {
    height: 22px !important;
    min-height: 22px !important;
}
body.is-mobile-device #maint-cl-modal-table .maint-cl-dropdown .Select-value-label,
body.is-mobile-device #maint-cl-modal-table .maint-cl-dropdown .Select-placeholder {
    font-size: 0.56rem !important;
    line-height: 22px !important;
}

/* Checklist textarea (ghi chú) */
body.is-mobile-device .maint-cl-notes-ta {
    font-size: 0.58rem !important;
    min-height: 28px !important;
    padding: 2px 4px !important;
}

/* Checklist datetime input */
body.is-mobile-device #maint-cl-modal-table .form-control-sm {
    font-size: 0.56rem !important;
    padding: 1px 4px !important;
    height: 22px !important;
    min-height: 22px !important;
}

/* Checklist status badge */
body.is-mobile-device #maint-cl-modal-table .badge {
    font-size: 0.50rem !important;
    padding: 1px 4px !important;
}

/* Checked-by span */
body.is-mobile-device #maint-cl-modal-table .cl-text {
    font-size: 0.56rem !important;
}

/* SP button (Thêm vật tư / Sửa) */
body.is-mobile-device #maint-cl-modal-table .btn-xs,
body.is-mobile-device #maint-cl-modal-table .btn-outline-primary,
body.is-mobile-device #maint-cl-modal-table .btn-outline-secondary {
    font-size: 0.54rem !important;
    padding: 1px 4px !important;
}

/* Image upload button */
body.is-mobile-device .maint-cl-img-upload-btn {
    font-size: 0.54rem !important;
    padding: 1px 4px !important;
}

/* ── FIX 4b: Maint Settings modal — Chi tiết tab "Hạng mục chi tiết" column ── */
body.is-mobile-device #maint-settings-modal .maint-cl-detail-pre {
    font-size: 0.56rem !important;
}
body.is-mobile-device #maint-settings-modal .cl-detail-cell {
    min-width: 100px !important;
    max-width: 160px !important;
}
body.is-mobile-device #maint-settings-modal .cl-group-cell,
body.is-mobile-device #maint-settings-modal .cl-comp-cell {
    font-size: 0.56rem !important;
    min-width: 50px !important;
    max-width: 100px !important;
}

/* ── FIX 5: App Logs modal — Pre inline style has fontSize:11px ── */
/* Cannot override inline style with !important on same element,
   but we can target Pre inside sync-logs-modal via CSS attribute selector trick
   and the parent container to force inheritance */
body.is-mobile-device #sync-logs-modal pre {
    font-size: 0.58rem !important;
    line-height: 1.35 !important;
    padding: 6px 8px !important;
}
/* AccordionItem header trong sync logs */
body.is-mobile-device #sync-logs-modal .accordion-button {
    font-size: 0.62rem !important;
    padding: 6px 10px !important;
}
body.is-mobile-device #sync-logs-modal .accordion-button strong {
    font-size: 0.62rem !important;
}
body.is-mobile-device #sync-logs-modal .accordion-button span,
body.is-mobile-device #sync-logs-modal .accordion-button .small {
    font-size: 0.58rem !important;
}
/* Source badge (ImageKit / Cloudinary) inline styled — đặt max font qua parent */
body.is-mobile-device #sync-logs-modal .d-flex.align-items-center span {
    font-size: 0.54rem !important;
}
/* Download btn */
body.is-mobile-device #sync-logs-modal .btn-sm {
    font-size: 0.56rem !important;
    padding: 1px 5px !important;
}

/* ── FIX 6: Maint Settings modal — tab Chi tiết checklist list bên trong ── */
/* Checklist list item bên trong settings modal */
body.is-mobile-device #maint-settings-modal .maint-checklist-list-item {
    padding: 4px 6px !important;
    font-size: 0.58rem !important;
}
body.is-mobile-device #maint-settings-modal .maint-checklist-list-item h6 {
    font-size: 0.58rem !important;
}
body.is-mobile-device #maint-settings-modal .maint-checklist-list-item small,
body.is-mobile-device #maint-settings-modal .maint-checklist-list-item .small {
    font-size: 0.52rem !important;
}

/* ── FIX 7: Planning sub-tab — H6 / section title headers ── */
body.is-mobile-device #maint-planning-content h6,
body.is-mobile-device .maint-planning-content h6,
body.is-mobile-device .maint-add-form-card h6 {
    font-size: 0.62rem !important;
    margin-bottom: 3px !important;
}
body.is-mobile-device .maint-planning-content .text-primary.fw-bold,
body.is-mobile-device .maint-planning-content .mb-2.fw-bold {
    font-size: 0.60rem !important;
}

/* ── FIX 5b: sync-log-pre — class thêm vào Python để override inline style ── */
/* Inline style fontSize:11px được override bằng !important qua class selector */
body.is-mobile-device .sync-log-pre {
    font-size: 0.56rem !important;
    line-height: 1.3 !important;
    padding: 6px 8px !important;
    max-height: 60vh !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX v5 — date-range-info, sidebar fs-5 headings,
   admin modal login height, checklist detail remaining cells
   ════════════════════════════════════════════════════════════ */

/* ── Sidebar date range display (dbc.Alert inline fontSize:0.8rem) ── */
body.is-mobile-device #date-range-info {
    font-size: 0.58rem !important;
    padding: 3px 6px !important;
    line-height: 1.4 !important;
}

/* ── Sidebar fs-5 / fs-6 section title headings ── */
body.is-mobile-device .sidebar .fs-5,
body.is-mobile-device .sidebar .fs-6 {
    font-size: 0.65rem !important;
}

/* ── Sidebar accordion title spans (have inline style từ JS) ── */
body.is-mobile-device .sidebar .accordion-button > span,
body.is-mobile-device .sidebar .accordion-button > i {
    font-size: 0.65rem !important;
}

/* ── Sidebar planning/details filter H6 titles (text-primary mb-3 fw-bold) ── */
body.is-mobile-device #maint-planning-filter .text-primary.mb-3,
body.is-mobile-device #maint-details-filter .text-primary.mb-3,
body.is-mobile-device .sidebar .text-primary.mb-3 {
    font-size: 0.60rem !important;
    margin-bottom: 4px !important;
}

/* ── Sidebar report filter title wrapper ── */
body.is-mobile-device .sidebar [class*="report"] .fw-bold,
body.is-mobile-device .sidebar .fw-bold.text-success {
    font-size: 0.60rem !important;
}

/* ── Maint Settings modal: Details tab - pre/textarea from JS (via applyInputStyle) ── */
/* These are now controlled by JS isMobile() - but add CSS as fallback */
body.is-mobile-device #maint-details-js-tbody td,
body.is-mobile-device #maint-area-js-tbody td,
body.is-mobile-device #maint-bt-js-tbody td {
    font-size: 0.60rem !important;
    padding: 2px 4px !important;
}
body.is-mobile-device #maint-details-js-tbody pre,
body.is-mobile-device #maint-area-js-tbody pre {
    font-size: 0.60rem !important;
}
body.is-mobile-device #maint-details-js-tbody input,
body.is-mobile-device #maint-details-js-tbody textarea,
body.is-mobile-device #maint-area-js-tbody input,
body.is-mobile-device #maint-bt-js-tbody input {
    font-size: 0.60rem !important;
    min-height: unset !important;
}

/* ── Maint Settings table headers (thead) ── */
body.is-mobile-device .maint-settings-thead th {
    font-size: 0.58rem !important;
    padding: 4px 5px !important;
}

/* ── sync-log-pre: ensure mobile size wins over base .sync-log-pre rule ── */
body.is-mobile-device .sync-log-pre {
    font-size: 0.56rem !important;
    line-height: 1.3 !important;
    padding: 5px 7px !important;
}

/* ── Admin modal: when login state, keep compact ── */
/* Login section itself: constrain to content height */
body.is-mobile-device #admin-login-section {
    max-width: 320px;
    margin: 0 auto;
}
body.is-mobile-device #admin-login-section .form-label,
body.is-mobile-device #admin-login-section label {
    font-size: 0.70rem !important;
}
body.is-mobile-device #admin-login-section .form-control,
body.is-mobile-device #admin-login-section input {
    font-size: 0.72rem !important;
    padding: 5px 8px !important;
    height: 34px !important;
}
body.is-mobile-device #admin-login-section .btn {
    font-size: 0.72rem !important;
    padding: 5px 12px !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX v6 — KPI badge no-wrap, pagination, sticky tabs
   ════════════════════════════════════════════════════════════ */

/* ── FIX 1: KPI cards — Tổng quan + So sánh: 3 per row, no text wrap ── */

/* Overview sticky-metrics: giữ 3/row, kpi-card height nhỏ gọn */
body.is-mobile-device .sticky-metrics .kpi-card-compact,
body.is-mobile-device .compare-kpi-row .kpi-card-compact {
    min-height: 46px !important;
    height: auto !important;
    padding: 4px 3px !important;  /* padding trái/phải nhỏ để tăng space */
}

/* Overview + Compare: cố định 3 KPI / dòng, chia đều width
   dbc.Col dùng className="col" (không có "-") → phải dùng > .col và > div */
body.is-mobile-device .sticky-metrics .row > .col,
body.is-mobile-device .sticky-metrics .row > [class*="col-"],
body.is-mobile-device .sticky-metrics .row > div,
body.is-mobile-device .compare-kpi-row > .col,
body.is-mobile-device .compare-kpi-row > [class*="col-"],
body.is-mobile-device .compare-kpi-row > div {
    flex: 0 0 33.333% !important;
    max-width: 33.333% !important;
    width: 33.333% !important;
    padding-left: 2px !important;
    padding-right: 2px !important;
    box-sizing: border-box !important;
}

/* Row1 (icon + value + badge): NO wrap, overflow hidden, single line */
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    flex-wrap: nowrap !important;
    font-size: 0.72rem !important;
    gap: 2px !important;
    max-width: 100% !important;
}

/* Row2 (label): single line, no wrap */
body.is-mobile-device .kpi-card-compact .kpi-compact-row2 {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    font-size: 0.46rem !important;
    letter-spacing: 0.2px !important;
    max-width: 100% !important;
}

/* Delta badge (▲ / ▼ %): shrink as much as possible */
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 .kpi-delta-badge,
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 .badge {
    font-size: 0.42rem !important;
    padding: 1px 3px !important;
    flex-shrink: 0 !important;
    line-height: 1.3 !important;
    white-space: nowrap !important;
}

/* Icon */
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 i {
    font-size: 0.64rem !important;
    flex-shrink: 0 !important;
}

/* pagination — handled by early block above */

/* ── FIX 4: Sticky tab-menu + sub-menu khi scroll trên mobile ── */
/*
  Vấn đề: #main-content-container trên mobile có overflow-y: visible
  → CSS position:sticky không hoạt động vì không có scroll container
  → Thực ra trang scroll qua body/window
  → sticky cần top = chiều cao navbar (62px) thay vì 0
*/

/* Main tab bar: dán ở đầu scroll container (#main-content-container) */
body.is-mobile-device #main-tabs-container,
body.is-mobile-device .sticky-header {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 0 !important;
    z-index: 1010 !important;
}

/* Sub-tabs / sub-header-wrapper: dán dưới main tab bar (~44px) */
body.is-mobile-device .sub-header-wrapper {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 44px !important;
    z-index: 1008 !important;
}

/* KPI sticky-metrics: dưới tab bar (khi không có sub-header) */
body.is-mobile-device .sticky-metrics {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 44px !important;
    z-index: 1007 !important;
}

/* ════════════════════════════════════════════════════════════
   SCALE FIX v6 — KPI 3/dòng, Pagination gọn, Sticky tabs
   (Block này LUÔN ở cuối file để thắng mọi rule trên)
   ════════════════════════════════════════════════════════════ */

/* ── KPI card compact: height gọn ── */
body.is-mobile-device .sticky-metrics .kpi-card-compact,
body.is-mobile-device .compare-kpi-row .kpi-card-compact {
    min-height: 46px !important;
    height: auto !important;
    padding: 4px 3px !important;
}

/* ── KPI: Row1 (icon + value) no-wrap ── */
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    flex-wrap: nowrap !important;
    font-size: 0.72rem !important;
    gap: 2px !important;
    max-width: 100% !important;
}
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 i {
    font-size: 0.64rem !important;
    flex-shrink: 0 !important;
}
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 .kpi-delta-badge,
body.is-mobile-device .kpi-card-compact .kpi-compact-row1 .badge {
    font-size: 0.42rem !important;
    padding: 1px 3px !important;
    flex-shrink: 0 !important;
    line-height: 1.3 !important;
    white-space: nowrap !important;
}
/* ── KPI: Row2 (label) no-wrap ── */
body.is-mobile-device .kpi-card-compact .kpi-compact-row2 {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    font-size: 0.46rem !important;
    letter-spacing: 0.2px !important;
    max-width: 100% !important;
}

/* ══════════════════════════════════════════════════════════
   PAGINATION FIX — override mọi rule cũ và .btn global
   Dùng selector đủ specificity: body.is-mobile-device + class
   ══════════════════════════════════════════════════════════ */
body.is-mobile-device .previous-next-container {
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 3px !important;
    padding: 3px 2px !important;
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
}
/* Navigation buttons <<, <, >, >> */
body.is-mobile-device .previous-next-container .first-page,
body.is-mobile-device .previous-next-container .last-page,
body.is-mobile-device .previous-next-container .previous-page,
body.is-mobile-device .previous-next-container .next-page,
body.is-mobile-device .previous-next-container button.first-page,
body.is-mobile-device .previous-next-container button.last-page,
body.is-mobile-device .previous-next-container button.previous-page,
body.is-mobile-device .previous-next-container button.next-page {
    min-height: unset !important;
    height: 22px !important;
    max-height: 22px !important;
    width: auto !important;
    min-width: 22px !important;
    max-width: 36px !important;
    font-size: 0.58rem !important;
    padding: 0 4px !important;
    line-height: 22px !important;
    border-radius: 4px !important;
    flex-shrink: 0 !important;
    box-sizing: border-box !important;
}
/* Page number input box */
body.is-mobile-device .previous-next-container .current-page,
body.is-mobile-device .previous-next-container .current-page input {
    min-height: unset !important;
    height: 22px !important;
    max-height: 22px !important;
    width: 34px !important;
    min-width: 22px !important;
    max-width: 38px !important;
    font-size: 0.58rem !important;
    padding: 0 2px !important;
    text-align: center !important;
    box-sizing: border-box !important;
    line-height: 22px !important;
}
/* Span text "/ 7" */
body.is-mobile-device .previous-next-container .page-number,
body.is-mobile-device .previous-next-container span {
    font-size: 0.58rem !important;
    line-height: 22px !important;
    white-space: nowrap !important;
    flex-shrink: 1 !important;
}

/* ── STICKY: Main tab bar + sub-header + kpi-metrics ── */
body.is-mobile-device #main-tabs-container,
body.is-mobile-device .sticky-header {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 0 !important;
    z-index: 1010 !important;
    background: var(--bg-sticky, rgba(15,23,42,0.92)) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
}
body.is-mobile-device .sub-header-wrapper {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 44px !important;
    z-index: 1008 !important;
    background: rgba(30, 41, 59, 0.85) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
}
body.is-mobile-device .sticky-metrics {
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 44px !important;
    z-index: 1007 !important;
    background: var(--bg-sticky, rgba(15,23,42,0.92)) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
}
/* Scroll container đúng cho sticky */
body.is-mobile-device #main-content-container {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    height: calc(100vh - var(--navbar-height, 62px)) !important;
}
/* Parent wrappers: không block sticky */
body.is-mobile-device #tab-content-wrapper,
body.is-mobile-device .tab-content,
body.is-mobile-device .tab-pane {
    overflow: visible !important;
}

/* ════════════════════════════════════════════════════════════
   FIX FINAL — portrait 3kpi/dòng, landscape 5kpi/dòng,
   bỏ sticky cho sticky-metrics (Tab Tổng quan)
   ════════════════════════════════════════════════════════════ */

/* <3> BỎ STICKY cho sticky-metrics (KPI Overview) trên mobile
   — giữ nguyên padding/z-index nhưng xóa position:sticky */
body.is-mobile-device .sticky-metrics {
    position: relative !important;
    top: auto !important;
}

/* <2> PORTRAIT (màn hình dọc): 3 KPI / dòng — mọi col trong sticky-metrics & compare */
@media screen and (orientation: portrait) {
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        flex: 0 0 33.333% !important;
        max-width: 33.333% !important;
        width: 33.333% !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
        box-sizing: border-box !important;
    }
}

/* <2> LANDSCAPE (màn hình ngang): 5 KPI / dòng */
@media screen and (orientation: landscape) {
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        flex: 0 0 20% !important;
        max-width: 20% !important;
        width: 20% !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
        box-sizing: border-box !important;
    }
    /* Landscape: KPI card hơi cao hơn tí vì màn hình rộng hơn */
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        padding: 5px 4px !important;
    }
}

/* ════════════════════════════════════════════════════════════
   FIX PAGINATION — Custom dbc.Button pagination (table-page-btn)
   Inline style có width/height/minWidth/minHeight/fontSize đã được
   đặt trong Python. CSS dùng !important để override trên mobile.
   ════════════════════════════════════════════════════════════ */

/* Container pagination custom */
body.is-mobile-device .table-pagination-controls {
    gap: 2px !important;
    margin-right: 6px !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
}

/* Các nút <<, <, >, >> — thu nhỏ bằng CSS specificity cao hơn inline */
body.is-mobile-device .table-page-btn,
body.is-mobile-device .table-page-btn.btn,
body.is-mobile-device .table-page-btn.btn-light,
body.is-mobile-device .table-page-btn.btn-sm {
    width: 22px !important;
    height: 22px !important;
    min-width: 22px !important;
    min-height: 22px !important;
    max-width: 22px !important;
    max-height: 22px !important;
    padding: 0 !important;
    font-size: 0.55rem !important;
    line-height: 22px !important;
    flex-shrink: 0 !important;
    border-radius: 4px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
body.is-mobile-device .table-page-btn i,
body.is-mobile-device .table-page-btn.btn i {
    font-size: 0.55rem !important;
    line-height: 1 !important;
}

/* Page number input */
body.is-mobile-device .table-page-input,
body.is-mobile-device .table-page-input.form-control,
body.is-mobile-device .table-page-input.form-control-sm {
    width: 32px !important;
    min-width: 32px !important;
    max-width: 36px !important;
    height: 22px !important;
    min-height: 22px !important;
    max-height: 22px !important;
    font-size: 0.58rem !important;
    padding: 0 2px !important;
    text-align: center !important;
    box-sizing: border-box !important;
}

/* "/ N" total pages span */
body.is-mobile-device .table-page-total {
    font-size: 0.58rem !important;
    white-space: nowrap !important;
    line-height: 22px !important;
}

/* Wrapper of input + total pages */
body.is-mobile-device .table-page-info {
    margin-left: 2px !important;
    margin-right: 2px !important;
}

/* Row header of table (Show X /page + pagination + export) */
body.is-mobile-device .dash-table-container > div:first-child,
body.is-mobile-device .dash-table-container > .d-flex:first-child {
    flex-wrap: wrap !important;
    gap: 3px !important;
    padding: 3px 0 !important;
}

/* Page size dropdown "Hiển thị: [25] /trang" — thu nhỏ */
body.is-mobile-device .dash-table-container .d-inline-block .Select-control,
body.is-mobile-device .dash-table-container .dcc-dropdown .Select-control {
    height: 22px !important;
    min-height: 22px !important;
    width: 56px !important;
}
body.is-mobile-device .dash-table-container .d-inline-block .Select-value-label,
body.is-mobile-device .dash-table-container .dcc-dropdown .Select-value-label {
    font-size: 0.60rem !important;
    line-height: 22px !important;
}

/* ════════════════════════════════════════════════════════════
   FIX KPI ROW — dòng cuối ít KPI hơn tự căn đều full row
   Dùng justify-content: space-between kết hợp flex-grow
   ════════════════════════════════════════════════════════════ */

/* Portrait: 3/row → mỗi col chiếm đúng 1/3 */
@media screen and (orientation: portrait) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        margin-left: -2px !important;
        margin-right: -2px !important;
        width: 100% !important;
    }
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        flex: 0 0 33.333% !important;
        max-width: 33.333% !important;
        width: 33.333% !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
        box-sizing: border-box !important;
    }
    /* KPI card bên trong: full width của col */
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
    }
}

/* Landscape: 5/row */
@media screen and (orientation: landscape) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        margin-left: -2px !important;
        margin-right: -2px !important;
        width: 100% !important;
    }
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        flex: 0 0 20% !important;
        max-width: 20% !important;
        width: 20% !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
        box-sizing: border-box !important;
    }
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
        padding: 5px 4px !important;
    }
}

/* ════════════════════════════════════════════════════════════
   FIX FINAL v2 — Table header scroll ngang + KPI stretch
   ════════════════════════════════════════════════════════════ */

/* ── TABLE HEADER: scroll ngang toàn bộ trên mobile ── */
body.is-mobile-device .table-header-wrapper {
    width: 100% !important;
    overflow: hidden !important;   /* outer: clip */
}
body.is-mobile-device .table-header-scrollable {
    overflow-x: auto !important;
    overflow-y: visible !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
    flex-wrap: nowrap !important;
    width: max-content !important;     /* co giãn theo nội dung */
    min-width: 100% !important;        /* tối thiểu full width */
    padding-bottom: 2px !important;
    gap: 0 !important;
    align-items: center !important;
}
body.is-mobile-device .table-header-scrollable::-webkit-scrollbar {
    display: none !important;
}

/* Label "Hiển thị:" và "/trang" */
body.is-mobile-device .table-header-label {
    white-space: nowrap !important;
    font-size: 0.60rem !important;
    flex-shrink: 0 !important;
}

/* Dropdown page size */
body.is-mobile-device .table-page-size-dropdown .Select-control {
    height: 22px !important;
    min-height: 22px !important;
    width: 54px !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-value-label,
body.is-mobile-device .table-page-size-dropdown .Select-placeholder {
    font-size: 0.60rem !important;
    line-height: 22px !important;
}

/* ── PAGINATION BUTTONS: override inline style bằng CSS specificity cao ── */
body.is-mobile-device .table-page-btn,
body.is-mobile-device .table-page-btn.btn,
body.is-mobile-device .table-page-btn.btn-light,
body.is-mobile-device .table-page-btn.btn-sm {
    width: 22px !important;
    height: 22px !important;
    min-width: 22px !important;
    min-height: 22px !important;
    max-width: 22px !important;
    max-height: 22px !important;
    padding: 0 !important;
    font-size: 0.52rem !important;
    line-height: 1 !important;
    flex-shrink: 0 !important;
    border-radius: 4px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
body.is-mobile-device .table-page-btn i {
    font-size: 0.52rem !important;
    pointer-events: none !important;
}

/* Pagination container gap */
body.is-mobile-device .table-pagination-controls {
    gap: 2px !important;
    flex-shrink: 0 !important;
    flex-wrap: nowrap !important;
}

/* Page number input */
body.is-mobile-device .table-page-input,
body.is-mobile-device .table-page-input.form-control,
body.is-mobile-device .table-page-input.form-control-sm {
    width: 30px !important;
    min-width: 28px !important;
    max-width: 34px !important;
    height: 22px !important;
    min-height: 22px !important;
    max-height: 22px !important;
    font-size: 0.58rem !important;
    padding: 0 2px !important;
    text-align: center !important;
    box-sizing: border-box !important;
}

/* "/ N" total pages */
body.is-mobile-device .table-page-total {
    font-size: 0.58rem !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
}

/* Export dropdown */
body.is-mobile-device .table-export-dropdown .btn,
body.is-mobile-device .table-export-dropdown > .btn {
    height: 22px !important;
    min-height: 22px !important;
    padding: 0 6px !important;
    font-size: 0.58rem !important;
    white-space: nowrap !important;
    display: flex !important;
    align-items: center !important;
}

/* Row count */
body.is-mobile-device .table-row-count {
    white-space: nowrap !important;
    font-size: 0.58rem !important;
    flex-shrink: 0 !important;
}

/* ── KPI STRETCH: dòng cuối ít card hơn tự stretch đều full row ──
   Dùng flex-grow:1 thay vì fixed %, kết hợp min/max để giới hạn
   Portrait: tối đa 3/row → mỗi col grow đều
   Landscape: tối đa 5/row → mỗi col grow đều
   ── */
@media screen and (orientation: portrait) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding: 4px !important;
        gap: 4px !important;
    }
    /* Mỗi col: flex-grow để dòng cuối stretch đều, max 33.333% */
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        /* Chiếm tối thiểu ~31% (dưới 33.333% để fit 3/row),
           flex-grow:1 để dòng cuối stretch đều lấp đầy khoảng trống */
        flex: 1 1 calc(33.333% - 4px) !important;
        max-width: calc(33.333% - 4px) !important;
        min-width: calc(33.333% - 4px) !important;
        padding: 0 !important;
        box-sizing: border-box !important;
    }
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
        padding: 4px 3px !important;
    }
}

@media screen and (orientation: landscape) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding: 4px !important;
        gap: 4px !important;
    }
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        flex: 1 1 calc(20% - 4px) !important;
        max-width: calc(20% - 4px) !important;
        min-width: calc(20% - 4px) !important;
        padding: 0 !important;
        box-sizing: border-box !important;
    }
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
        padding: 5px 4px !important;
    }
}
/* ════════════════════════════════════════════════════════════
   FIX <1> — KPI dòng cuối tự stretch đều full row
   ROOT CAUSE: max-width cứng (calc 33.333% hoặc 20%) block flex-grow
   SOLUTION: bỏ max-width, dùng flex-grow:1 + chỉ giới hạn bằng flex-basis
   ════════════════════════════════════════════════════════════ */

/* Portrait: tối đa 3/row — flex-grow:1 để dòng cuối stretch */
@media screen and (orientation: portrait) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        width: 100% !important;
        margin: 0 !important;
        padding: 4px !important;
        gap: 4px !important;
        /* justify-content: flex-start → flex-grow sẽ fill khoảng trống */
        justify-content: flex-start !important;
        align-items: stretch !important;
    }
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        /* flex-basis < 33.333% để đảm bảo fit 3/row */
        /* flex-grow:1 để các item ở dòng cuối stretch đều lấp đầy */
        /* KHÔNG set max-width → cho phép grow */
        flex: 1 1 calc(33.333% - 5px) !important;
        max-width: none !important;
        min-width: calc(33.333% - 5px) !important;
        padding: 0 !important;
        box-sizing: border-box !important;
    }
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
        height: 100% !important;  /* stretch card chiều dọc đều nhau */
        padding: 4px 3px !important;
    }
}

/* Landscape: tối đa 5/row — flex-grow:1 để dòng cuối stretch */
@media screen and (orientation: landscape) {
    body.is-mobile-device .sticky-metrics .row,
    body.is-mobile-device .compare-kpi-row {
        display: flex !important;
        flex-wrap: wrap !important;
        width: 100% !important;
        margin: 0 !important;
        padding: 4px !important;
        gap: 4px !important;
        justify-content: flex-start !important;
        align-items: stretch !important;
    }
    body.is-mobile-device .sticky-metrics .row > [class*="col-"],
    body.is-mobile-device .sticky-metrics .row > .col,
    body.is-mobile-device .sticky-metrics .row > div,
    body.is-mobile-device .compare-kpi-row > [class*="col-"],
    body.is-mobile-device .compare-kpi-row > .col,
    body.is-mobile-device .compare-kpi-row > div {
        /* flex-basis < 20% để fit 5/row */
        /* flex-grow:1 để dòng cuối (3 hoặc 4 item) stretch đều */
        /* KHÔNG set max-width → cho phép grow */
        flex: 1 1 calc(20% - 5px) !important;
        max-width: none !important;
        min-width: calc(20% - 5px) !important;
        padding: 0 !important;
        box-sizing: border-box !important;
    }
    body.is-mobile-device .sticky-metrics .kpi-card-compact,
    body.is-mobile-device .compare-kpi-row .kpi-card-compact {
        width: 100% !important;
        min-width: 0 !important;
        height: 100% !important;
        padding: 5px 4px !important;
    }
}

/* ════════════════════════════════════════════════════════════
   FIX <2> — Navigation buttons height gọn hơn
   + Export button không bị che (touch scroll ngang)
   ════════════════════════════════════════════════════════════ */

/* Giảm height toàn bộ nav-link trong main-tabs trên mobile */
body.is-mobile-device #main-tabs .nav-link {
    padding: 5px 10px !important;      /* giảm từ 8px 16px → 5px 10px */
    font-size: 0.72rem !important;     /* override 18px desktop */
    line-height: 1.3 !important;
    border-radius: 6px !important;
}

/* Container #main-tabs-container: giảm padding top/bottom */
body.is-mobile-device #main-tabs-container,
body.is-mobile-device .sticky-header {
    padding: 3px 6px 3px 42px !important;   /* giảm từ 4px → 3px */
    min-height: 36px !important;
    max-height: 40px !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
}

/* Div wrapper bọc UL#main-tabs: cho phép scroll ngang + touch swipe
   Selector áp dụng cho cả wrapper gốc lẫn .tab-scroll-wrapper mới */
body.is-mobile-device #main-tabs-container > div:first-child,
body.is-mobile-device #main-tabs-container .tab-scroll-wrapper,
body.is-mobile-device #main-tabs-container .tab-scroll-inner {
    flex: 1 !important;
    min-width: 0 !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    -webkit-overflow-scrolling: touch !important;
    scroll-behavior: smooth !important;
    scrollbar-width: none !important;
    touch-action: pan-x !important;
    -webkit-tap-highlight-color: transparent !important;
}
body.is-mobile-device #main-tabs-container > div:first-child::-webkit-scrollbar,
body.is-mobile-device #main-tabs-container .tab-scroll-inner::-webkit-scrollbar {
    display: none !important;
}
/* Ẩn arrow buttons trong main-tabs trên mobile (dùng touch scroll) */
body.is-mobile-device #main-tabs-container .tab-scroll-arrow {
    display: none !important;
}

/* #main-tabs UL: width = max-content để không bị wrap, cho phép scroll */
body.is-mobile-device #main-tabs.nav {
    flex-wrap: nowrap !important;
    width: max-content !important;
    margin: 0 !important;
    padding: 0 !important;
    gap: 2px !important;
    align-items: center !important;
}

/* #mobile-more-btn (nút ⋮): giảm kích thước, flex-shrink:0 luôn visible */
body.is-mobile-device #mobile-more-btn {
    width: 26px !important;
    height: 26px !important;
    flex-shrink: 0 !important;
    font-size: 0.9rem !important;
    margin-left: 2px !important;
}

/* Mobile more menu: đảm bảo export button hiển thị đủ */
body.is-mobile-device #mobile-more-menu {
    min-width: 180px !important;
    max-height: calc(100vh - var(--navbar-height, 62px) - 48px) !important;
    overflow-y: auto !important;
}

/* Export button trong more menu: đủ chiều cao, không bị clip */
body.is-mobile-device .mobile-more-item {
    padding: 11px 14px !important;
    min-height: 40px !important;
}

/* Đảm bảo .main-header-icons ẩn hoàn toàn (không ảnh hưởng width) */
body.is-mobile-device .main-header-icons {
    display: none !important;
    width: 0 !important;
    overflow: hidden !important;
    flex: 0 0 0 !important;
}

/* ════════════════════════════════════════════════════════════
   FIX <3> — Table header row: scroll ngang bằng vuốt touch
   + căn giữa input/button + height đồng đều
   ════════════════════════════════════════════════════════════ */

/* Outer wrapper: clip overflow, không scroll */
body.is-mobile-device .table-header-wrapper {
    width: 100% !important;
    overflow: hidden !important;
    position: relative !important;
}

/* Inner scrollable row: scroll ngang, touch swipe */
body.is-mobile-device .table-header-scrollable {
    display: flex !important;
    flex-wrap: nowrap !important;             /* QUAN TRỌNG: không wrap → tất cả inline */
    align-items: center !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    -webkit-overflow-scrolling: touch !important;
    touch-action: pan-x !important;           /* iOS/Android nhận vuốt ngang */
    scroll-behavior: smooth !important;
    scrollbar-width: none !important;
    width: 100% !important;
    padding: 3px 2px !important;
    gap: 4px !important;
    box-sizing: border-box !important;
    height: 36px !important;                  /* chiều cao cố định cho cả row */
    -webkit-tap-highlight-color: transparent !important;
}
body.is-mobile-device .table-header-scrollable::-webkit-scrollbar {
    display: none !important;
}

/* Label "Hiển thị:", "/trang", "Tổng:" */
body.is-mobile-device .table-header-label {
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    font-size: 0.60rem !important;
    line-height: 36px !important;
    display: flex !important;
    align-items: center !important;
}

/* Dropdown page size */
body.is-mobile-device .table-page-size-dropdown {
    flex-shrink: 0 !important;
    height: 26px !important;
    display: flex !important;
    align-items: center !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-control {
    height: 26px !important;
    min-height: 26px !important;
    width: 56px !important;
    display: flex !important;
    align-items: center !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-value-label,
body.is-mobile-device .table-page-size-dropdown .Select-placeholder {
    font-size: 0.60rem !important;
    line-height: 26px !important;
}

/* Pagination controls container */
body.is-mobile-device .table-pagination-controls {
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    gap: 3px !important;
    flex-shrink: 0 !important;
    height: 28px !important;
}

/* Pagination buttons — override inline style bằng !important */
body.is-mobile-device .table-page-btn,
body.is-mobile-device .table-page-btn.btn,
body.is-mobile-device .table-page-btn.btn-light,
body.is-mobile-device .table-page-btn.btn-sm {
    width: 28px !important;
    height: 28px !important;
    min-width: 26px !important;
    max-width: 32px !important;
    min-height: 26px !important;
    max-height: 30px !important;
    padding: 0 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex-shrink: 0 !important;
    font-size: 0.68rem !important;
    line-height: 1 !important;
    border-radius: 5px !important;
    box-sizing: border-box !important;
}
body.is-mobile-device .table-page-btn i,
body.is-mobile-device .table-page-btn.btn i {
    font-size: 0.68rem !important;
    line-height: 1 !important;
    pointer-events: none !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}

/* Page input + "/ N" wrapper */
body.is-mobile-device .table-pagination-controls > .d-flex.align-items-center.mx-1 {
    height: 28px !important;
    align-items: center !important;
    display: flex !important;
    flex-shrink: 0 !important;
}

/* Page number input */
body.is-mobile-device .table-page-input,
body.is-mobile-device .table-page-input.form-control,
body.is-mobile-device .table-page-input.form-control-sm {
    width: 36px !important;
    min-width: 30px !important;
    max-width: 40px !important;
    height: 26px !important;
    min-height: 26px !important;
    max-height: 28px !important;
    font-size: 0.75rem !important;
    padding: 0 2px !important;
    text-align: center !important;
    box-sizing: border-box !important;
    line-height: 26px !important;
    display: flex !important;
    align-items: center !important;
    flex-shrink: 0 !important;
    /* Override iOS zoom prevention without breaking layout */
    font-size: 16px !important;
    transform-origin: left center !important;
}

/* "/ N" span */
body.is-mobile-device .table-page-total {
    font-size: 0.70rem !important;
    white-space: nowrap !important;
    line-height: 26px !important;
    flex-shrink: 0 !important;
    display: flex !important;
    align-items: center !important;
}

/* Export dropdown button */
body.is-mobile-device .table-export-dropdown,
body.is-mobile-device .table-export-dropdown > .btn,
body.is-mobile-device .table-export-dropdown > button {
    flex-shrink: 0 !important;
    height: 28px !important;
    min-height: 28px !important;
    font-size: 0.62rem !important;
    padding: 0 8px !important;
    display: flex !important;
    align-items: center !important;
    white-space: nowrap !important;
}
body.is-mobile-device .table-export-dropdown .dropdown-toggle {
    height: 28px !important;
    min-height: 28px !important;
    padding: 0 8px !important;
    font-size: 0.62rem !important;
    display: flex !important;
    align-items: center !important;
    white-space: nowrap !important;
    line-height: 1 !important;
}

/* Row count text */
body.is-mobile-device .table-row-count {
    font-size: 0.60rem !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    line-height: 36px !important;
    padding-left: 6px !important;
    display: flex !important;
    align-items: center !important;
}

/* ════════════════════════════════════════════════════════════
   FIX <4> FINAL — Table header row: đồng đều height, canh giữa
   CHIẾN LƯỢC: dùng 1 height duy nhất = 30px cho mọi thứ,
   align-items: center trên tất cả containers
   ════════════════════════════════════════════════════════════ */

/* === OUTER WRAPPER === */
body.is-mobile-device .table-header-wrapper {
    width: 100% !important;
    overflow: hidden !important;
    padding: 4px 2px !important;
    box-sizing: border-box !important;
    /* Chiều cao outer = 30px item + 8px padding = 38px */
    min-height: 38px !important;
    display: flex !important;
    align-items: center !important;
}

/* === INNER SCROLLABLE ROW ===
   Đây là flex container chứa tất cả items.
   height:30px cố định → tất cả children tự align giữa */
body.is-mobile-device .table-header-scrollable {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center !important;     /* căn giữa theo chiều dọc */
    justify-content: flex-start !important;
    height: 30px !important;            /* 1 chiều cao duy nhất cho toàn row */
    overflow-x: auto !important;
    overflow-y: hidden !important;      /* clip mọi thứ nhô ra */
    -webkit-overflow-scrolling: touch !important;
    touch-action: pan-x !important;
    scroll-behavior: smooth !important;
    scrollbar-width: none !important;
    gap: 5px !important;
    padding: 0 2px !important;
    width: 100% !important;
    box-sizing: border-box !important;
    -webkit-tap-highlight-color: transparent !important;
}
body.is-mobile-device .table-header-scrollable::-webkit-scrollbar {
    display: none !important;
}

/* === LABEL TEXT ("Hiển thị:", "/trang", "Tổng:") === */
body.is-mobile-device .table-header-label {
    display: inline-flex !important;
    align-items: center !important;
    height: 30px !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    font-size: 0.60rem !important;
    line-height: 1 !important;
    margin: 0 !important;
    padding: 0 !important;
}

/* === DROPDOWN "25" (page size) ===
   dcc.Dropdown render ra div.Select → cần target cả wrapper và inner */
body.is-mobile-device .table-page-size-dropdown {
    display: inline-flex !important;
    align-items: center !important;
    height: 30px !important;
    flex-shrink: 0 !important;
}
/* Dash dcc.Dropdown wrapper div */
body.is-mobile-device .table-page-size-dropdown > div,
body.is-mobile-device .table-page-size-dropdown .Select {
    height: 28px !important;
    min-height: 28px !important;
    max-height: 28px !important;
    width: 62px !important;
    display: flex !important;
    align-items: center !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-control {
    height: 28px !important;
    min-height: 28px !important;
    max-height: 28px !important;
    width: 62px !important;
    display: flex !important;
    align-items: center !important;
    padding: 0 !important;
    box-sizing: border-box !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-multi-value-wrapper {
    display: flex !important;
    align-items: center !important;
    height: 28px !important;
    padding-left: 6px !important;
    flex: 1 !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-value,
body.is-mobile-device .table-page-size-dropdown .Select-placeholder {
    display: flex !important;
    align-items: center !important;
    height: 28px !important;
    line-height: 28px !important;
    padding: 0 !important;
    margin: 0 !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-value-label,
body.is-mobile-device .table-page-size-dropdown .Select-placeholder {
    font-size: 0.68rem !important;
    line-height: 28px !important;
    white-space: nowrap !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-arrow-zone {
    display: flex !important;
    align-items: center !important;
    height: 28px !important;
    width: 18px !important;
    flex-shrink: 0 !important;
}
body.is-mobile-device .table-page-size-dropdown .Select-input {
    height: 26px !important;
    padding: 0 !important;
}

/* === PAGINATION CONTROLS CONTAINER === */
body.is-mobile-device .table-pagination-controls {
    display: inline-flex !important;
    flex-direction: row !important;
    align-items: center !important;
    height: 30px !important;
    flex-shrink: 0 !important;
    flex-wrap: nowrap !important;
    gap: 3px !important;
    padding: 0 !important;
    margin: 0 !important;
}

/* === 4 BUTTONS: «  <  >  » ===
   inline style trong Python set width/height:28px → override bằng !important */
body.is-mobile-device .table-page-btn,
body.is-mobile-device .table-page-btn.btn,
body.is-mobile-device .table-page-btn.btn-light,
body.is-mobile-device .table-page-btn.btn-sm {
    width: 28px !important;
    height: 28px !important;
    min-width: 28px !important;
    max-width: 28px !important;
    min-height: 28px !important;
    max-height: 28px !important;
    padding: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex-shrink: 0 !important;
    border-radius: 5px !important;
    font-size: 0.68rem !important;
    line-height: 1 !important;
    box-sizing: border-box !important;
    vertical-align: middle !important;
}
body.is-mobile-device .table-page-btn i,
body.is-mobile-device .table-page-btn.btn i {
    font-size: 0.68rem !important;
    line-height: 1 !important;
    pointer-events: none !important;
}

/* === INPUT "1" + SPAN "/ 7" WRAPPER === */
body.is-mobile-device .table-pagination-controls .d-flex.align-items-center.mx-1 {
    display: inline-flex !important;
    align-items: center !important;
    height: 28px !important;
    flex-shrink: 0 !important;
    gap: 0 !important;
    margin: 0 2px !important;
    padding: 0 !important;
}

/* === INPUT SỐ TRANG "1" ===
   Ghi đè inline style Python: width:40px height:28px */
body.is-mobile-device .table-page-input,
body.is-mobile-device .table-page-input.form-control,
body.is-mobile-device .table-page-input.form-control-sm {
    width: 36px !important;
    height: 28px !important;
    min-height: 28px !important;
    max-height: 28px !important;
    padding: 0 !important;
    margin: 0 !important;
    font-size: 0.78rem !important;
    font-weight: bold !important;
    text-align: center !important;
    line-height: 28px !important;
    box-sizing: border-box !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex-shrink: 0 !important;
    vertical-align: middle !important;
    /* Override iOS font-size zoom */
    touch-action: manipulation !important;
}

/* === SPAN "/ 7" === */
body.is-mobile-device .table-page-total {
    display: inline-flex !important;
    align-items: center !important;
    height: 28px !important;
    font-size: 0.78rem !important;
    font-weight: bold !important;
    white-space: nowrap !important;
    line-height: 28px !important;
    flex-shrink: 0 !important;
    margin-left: 3px !important;
    padding: 0 !important;
    vertical-align: middle !important;
}

/* === EXPORT BUTTON ===
   dbc.DropdownMenu render ra div > button.dropdown-toggle */
body.is-mobile-device .table-export-dropdown {
    display: inline-flex !important;
    align-items: center !important;
    height: 30px !important;
    flex-shrink: 0 !important;
    margin: 0 !important;
}
body.is-mobile-device .table-export-dropdown > .btn,
body.is-mobile-device .table-export-dropdown .dropdown-toggle,
body.is-mobile-device .table-export-dropdown > button {
    height: 28px !important;
    min-height: 28px !important;
    max-height: 28px !important;
    padding: 0 10px !important;
    font-size: 0.65rem !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    white-space: nowrap !important;
    line-height: 1 !important;
    box-sizing: border-box !important;
    vertical-align: middle !important;
}

/* === ROW COUNT "Tổng: 158 dòng" === */
body.is-mobile-device .table-row-count {
    display: inline-flex !important;
    align-items: center !important;
    height: 30px !important;
    font-size: 0.62rem !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    padding: 0 0 0 4px !important;
    margin: 0 !important;
    line-height: 1 !important;
    vertical-align: middle !important;
}
/* ════════════════════════════════════════════════════════════
   FIX USER LOGS MODAL MOBILE — filter layout gọn 2 cột
   Override rule "g-2 > col-* = 100%" chỉ riêng cho modal này
   ════════════════════════════════════════════════════════════ */

/* DatePickerRange: không vượt quá container, full width */
body.is-mobile-device #user-logs-modal .DateRangePicker,
body.is-mobile-device #user-logs-modal .DateRangePickerInput {
    width: 100% !important;
    max-width: 100% !important;
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
}
body.is-mobile-device #user-logs-modal .DateInput {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    width: auto !important;
}
body.is-mobile-device #user-logs-modal .DateInput_input {
    font-size: 0.58rem !important;
    padding: 3px 4px !important;
    width: 100% !important;
    min-width: 0 !important;
}
body.is-mobile-device #user-logs-modal .DateRangePickerInput_arrow {
    flex-shrink: 0 !important;
    padding: 0 3px !important;
}

/* Row 1 filters: xs=12 (date), xs=6 (username, action type), xs=12 (search)
   xs=12 → 100% (default), xs=6 → 50% override */
body.is-mobile-device #user-logs-modal .col-6 {
    flex: 0 0 50% !important;
    max-width: 50% !important;
    width: 50% !important;
}
/* xs=12 cols tự full width (rule global đã xử lý) */

/* Row 2 buttons: xs=12 (apply/reset/refresh), xs=6 (stats+excel, clear), xs=12 (rows/page) */
/* Buttons: đảm bảo không cao quá */
body.is-mobile-device #user-logs-modal .btn-group .btn,
body.is-mobile-device #user-logs-modal .btn-group > .btn {
    font-size: 0.60rem !important;
    padding: 3px 5px !important;
    min-height: 28px !important;
    height: 28px !important;
    max-height: 28px !important;
    line-height: 1 !important;
    white-space: nowrap !important;
}

/* InputGroup clear logs + rows/page */
body.is-mobile-device #user-logs-modal .input-group {
    height: 28px !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
}
body.is-mobile-device #user-logs-modal .input-group .form-control,
body.is-mobile-device #user-logs-modal .input-group input {
    height: 28px !important;
    min-height: 28px !important;
    font-size: 0.60rem !important;
    padding: 2px 5px !important;
}
body.is-mobile-device #user-logs-modal .input-group-text {
    height: 28px !important;
    font-size: 0.58rem !important;
    padding: 2px 5px !important;
    white-space: nowrap !important;
}
body.is-mobile-device #user-logs-modal .input-group .btn {
    height: 28px !important;
    min-height: 28px !important;
    font-size: 0.58rem !important;
    padding: 2px 6px !important;
    white-space: nowrap !important;
}

/* Filter card: compact padding */
body.is-mobile-device #user-logs-modal .card-body {
    padding: 8px !important;
}

/* Dropdown trong filter */
body.is-mobile-device #user-logs-modal .Select-control {
    height: 28px !important;
    min-height: 28px !important;
}
body.is-mobile-device #user-logs-modal .Select-value-label,
body.is-mobile-device #user-logs-modal .Select-placeholder {
    font-size: 0.60rem !important;
    line-height: 28px !important;
}

/* Search input */
body.is-mobile-device #user-logs-modal #user-logs-search-input {
    height: 28px !important;
    font-size: 0.60rem !important;
    padding: 3px 6px !important;
}

/* Label */
body.is-mobile-device #user-logs-modal .col label,
body.is-mobile-device #user-logs-modal .col .form-label {
    font-size: 0.60rem !important;
    margin-bottom: 2px !important;
    display: block !important;
}

/* Pagination row: compact */
body.is-mobile-device #user-logs-modal #user-logs-page-input {
    font-size: 0.70rem !important;
    height: 22px !important;
    padding: 0 2px !important;
}
body.is-mobile-device #user-logs-modal .btn-group button {
    font-size: 0.58rem !important;
    padding: 2px 5px !important;
    min-height: 24px !important;
    height: 24px !important;
}

/* ModalBody: flex column để table chiếm phần còn lại */
body.is-mobile-device #user-logs-modal .modal-body {
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
    padding: 6px 8px !important;
}

/* Filter card: flex shrink không co lại */
body.is-mobile-device #user-logs-modal .modal-body > .mb-2.shadow-sm {
    flex-shrink: 0 !important;
}

/* Stats collapse: flex shrink */
body.is-mobile-device #user-logs-modal .modal-body > div[style*="flex: 0"] {
    flex-shrink: 0 !important;
}

/* Status msg + pagination row: flex shrink */
body.is-mobile-device #user-logs-modal #user-logs-status-msg,
body.is-mobile-device #user-logs-modal .modal-body > .mb-2.d-flex {
    flex-shrink: 0 !important;
}

/* Logs table wrapper: flex grow để chiếm phần còn lại, scroll */
body.is-mobile-device #user-logs-modal .logs-table-wrapper {
    flex: 1 1 auto !important;
    overflow: auto !important;
    min-height: 0 !important;
}

/* ════════════════════════════════════════════════════════════
   MOBILE FIX — DatePicker scale nhỏ toàn project
   Áp dụng cho sidebar, modal user logs, compare tab, report
   ════════════════════════════════════════════════════════════ */

/* === INPUT BOX: thu nhỏ ô nhập ngày === */
body.is-mobile-device .DateInput_input,
body.is-mobile-device .DateRangePickerInput .DateInput_input,
body.is-mobile-device .SingleDatePickerInput .DateInput_input {
    font-size: 0.68rem !important;
    height: 28px !important;
    padding: 2px 6px !important;
    text-align: center !important;
    min-width: 0 !important;
}

/* === ARROW giữa 2 ô ngày === */
body.is-mobile-device .DateRangePickerInput_arrow,
body.is-mobile-device .DateRangePickerInput_arrow_svg {
    width: 16px !important;
    height: 16px !important;
    flex-shrink: 0 !important;
    padding: 0 2px !important;
}

/* === WRAPPER bọc 2 ô ngày: co lại theo nội dung === */
body.is-mobile-device .DateRangePicker,
body.is-mobile-device .DateRangePickerInput,
body.is-mobile-device .SingleDatePicker,
body.is-mobile-device .SingleDatePickerInput {
    width: 100% !important;
    max-width: 100% !important;
}
body.is-mobile-device .DateRangePickerInput {
    display: flex !important;
    align-items: center !important;
    flex-wrap: nowrap !important;
}
body.is-mobile-device .DateRangePickerInput .DateInput {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    width: auto !important;
}

/* === CALENDAR POPUP: scale nhỏ toàn bộ lịch === */
body.is-mobile-device .DayPicker,
body.is-mobile-device .DayPicker__withBorder {
    transform: scale(0.82) !important;
    transform-origin: top left !important;
    box-shadow: 0 8px 24px rgba(0,0,0,0.35) !important;
    border-radius: 10px !important;
}

/* Z-index cao để calendar không bị che bởi modal */
body.is-mobile-device .SingleDatePicker_picker,
body.is-mobile-device .DateRangePicker_picker {
    z-index: 9999 !important;
    position: fixed !important;
    transform: none !important;
}

/* Calendar tiêu đề tháng */
body.is-mobile-device .CalendarMonth_caption {
    font-size: 0.80rem !important;
    padding-top: 12px !important;
    padding-bottom: 36px !important;
}

/* Ô ngày trong lịch */
body.is-mobile-device .CalendarDay {
    font-size: 0.68rem !important;
    padding: 0 !important;
}

/* Navigation buttons tháng */
body.is-mobile-device .DayPickerNavigation_button {
    padding: 4px 6px !important;
}

/* === SIDEBAR datepicker: giảm thêm vì cột hẹp === */
body.is-mobile-device .sidebar .DateInput_input,
body.is-mobile-device #custom-date-pickers .DateInput_input {
    font-size: 0.62rem !important;
    height: 24px !important;
    padding: 1px 4px !important;
}

/* === INPUT form-control toàn bộ modal user logs: thu nhỏ === */
body.is-mobile-device #user-logs-modal .form-control,
body.is-mobile-device #user-logs-modal input[type="text"],
body.is-mobile-device #user-logs-modal input[type="number"],
body.is-mobile-device #user-logs-modal input[type="search"] {
    font-size: 0.62rem !important;
    height: 28px !important;
    padding: 2px 6px !important;
    min-height: unset !important;
}

/* === DROPDOWN trong user logs modal: thu nhỏ === */
body.is-mobile-device #user-logs-modal .Select-control {
    height: 28px !important;
    min-height: 28px !important;
    font-size: 0.62rem !important;
}
body.is-mobile-device #user-logs-modal .Select-value-label,
body.is-mobile-device #user-logs-modal .Select-placeholder,
body.is-mobile-device #user-logs-modal .Select-option {
    font-size: 0.62rem !important;
    line-height: 28px !important;
}

/* === LABEL user logs modal: nhỏ hơn === */
body.is-mobile-device #user-logs-modal label,
body.is-mobile-device #user-logs-modal .form-label {
    font-size: 0.58rem !important;
    margin-bottom: 1px !important;
}

/* === BUTTONS trong user logs modal: đồng đều height 28px === */
body.is-mobile-device #user-logs-modal .btn {
    font-size: 0.62rem !important;
    padding: 3px 7px !important;
    min-height: 28px !important;
    height: 28px !important;
    line-height: 1 !important;
}

/* Sidebar filter datepicker wrapper: full width */
body.is-mobile-device .sidebar .DateRangePicker,
body.is-mobile-device .sidebar .SingleDatePicker {
    width: 100% !important;
}
body.is-mobile-device .sidebar .DateRangePickerInput {
    width: 100% !important;
    display: flex !important;
    align-items: center !important;
}

/* ════════════════════════════════════════════════════════════
   FIX USER-LOGS MOBILE v3 — input width, scrollY table
   ════════════════════════════════════════════════════════════ */

/* ── FIX 2: Bảng chi tiết scrollY trên mobile ── */
/* Modal body: flex column, overflow hidden */
body.is-mobile-device #user-logs-modal .modal-body {
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
    height: calc(100vh - var(--navbar-height, 62px) - 56px) !important;
    padding: 6px 8px !important;
}
/* Filter card: không shrink */
body.is-mobile-device #user-logs-modal .modal-body > .card {
    flex: 0 0 auto !important;
    overflow: visible !important;
}
/* Stats collapse section */
body.is-mobile-device #user-logs-modal #user-logs-statistics-collapse {
    flex: 0 0 auto !important;
}
/* Status + pagination row */
body.is-mobile-device #user-logs-modal #user-logs-status-msg,
body.is-mobile-device #user-logs-modal .modal-body > .mb-2.d-flex {
    flex: 0 0 auto !important;
}
/* Table wrapper: flex grow, overflow scroll */
body.is-mobile-device #user-logs-modal .logs-table-wrapper {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow: auto !important;
    -webkit-overflow-scrolling: touch !important;
}
/* DataTable container bên trong: không bị clip */
body.is-mobile-device #user-logs-modal .dash-table-container {
    height: 100% !important;
    overflow: visible !important;
}
body.is-mobile-device #user-logs-modal .dash-spreadsheet-container {
    overflow: auto !important;
    height: 100% !important;
    -webkit-overflow-scrolling: touch !important;
}
body.is-mobile-device #user-logs-modal .dash-spreadsheet-inner {
    overflow: auto !important;
}

/* ── FIX 3: DatePickerRange trong user-logs-modal — thu nhỏ ── */
/* dcc.DatePickerRange render ra: div#user-logs-date-range > .DateRangePicker > .DateRangePickerInput */
/* DateRangePickerInput có inline style width → cần !important mạnh */
html body.is-mobile-device #user-logs-date-range .DateRangePicker,
html body.is-mobile-device #user-logs-date-range .DateRangePickerInput {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    display: flex !important;
    align-items: center !important;
    flex-wrap: nowrap !important;
}
html body.is-mobile-device #user-logs-date-range .DateInput {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    width: auto !important;
    max-width: 46% !important;
}
html body.is-mobile-device #user-logs-date-range .DateInput_input {
    font-size: 0.60rem !important;
    height: 26px !important;
    padding: 2px 3px !important;
    width: 100% !important;
    min-width: 0 !important;
    text-align: center !important;
    box-sizing: border-box !important;
}
html body.is-mobile-device #user-logs-date-range .DateRangePickerInput_arrow {
    flex: 0 0 16px !important;
    width: 16px !important;
    min-width: 16px !important;
    padding: 0 1px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
html body.is-mobile-device #user-logs-date-range .DateRangePickerInput_arrow_svg {
    width: 14px !important;
    height: 14px !important;
}
/* Calendar popup: dùng fixed positioning để không bị clip bởi modal overflow */
html body.is-mobile-device #user-logs-date-range .DateRangePicker_picker {
    position: fixed !important;
    z-index: 9999 !important;
    top: auto !important;
    left: 8px !important;
    right: 8px !important;
    width: auto !important;
    max-width: calc(100vw - 16px) !important;
}
/* Scale nhỏ calendar */
html body.is-mobile-device #user-logs-date-range .DayPicker,
html body.is-mobile-device #user-logs-date-range .DayPicker__withBorder {
    transform: scale(0.85) !important;
    transform-origin: top left !important;
}

/* ── FIX 3b: Input/dropdown toàn modal: giảm width thực sự ── */
/* Col xs-12 chứa DatePicker: giảm padding để date picker không tràn */
html body.is-mobile-device #user-logs-modal .col-12,
html body.is-mobile-device #user-logs-modal [class*="col-"] {
    padding-left: 4px !important;
    padding-right: 4px !important;
    min-width: 0 !important;
}
/* Dropdown (dcc.Dropdown): constrain width */
html body.is-mobile-device #user-logs-modal #user-logs-username-filter,
html body.is-mobile-device #user-logs-modal #user-logs-action-filter {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
}
html body.is-mobile-device #user-logs-modal #user-logs-username-filter .Select,
html body.is-mobile-device #user-logs-modal #user-logs-action-filter .Select,
html body.is-mobile-device #user-logs-modal #user-logs-username-filter .Select-control,
html body.is-mobile-device #user-logs-modal #user-logs-action-filter .Select-control {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    font-size: 0.60rem !important;
    height: 26px !important;
    min-height: 26px !important;
}
html body.is-mobile-device #user-logs-modal #user-logs-username-filter .Select-value-label,
html body.is-mobile-device #user-logs-modal #user-logs-action-filter .Select-value-label,
html body.is-mobile-device #user-logs-modal #user-logs-username-filter .Select-placeholder,
html body.is-mobile-device #user-logs-modal #user-logs-action-filter .Select-placeholder {
    font-size: 0.60rem !important;
    line-height: 26px !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}
/* Search input */
html body.is-mobile-device #user-logs-modal #user-logs-search-input {
    font-size: 0.60rem !important;
    height: 26px !important;
    padding: 2px 5px !important;
    width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
}
/* InputGroup clear + page-size: nowrap, không tràn */
html body.is-mobile-device #user-logs-modal .input-group {
    flex-wrap: nowrap !important;
    width: 100% !important;
    min-width: 0 !important;
}
/* Card trong filter: overflow hidden để không tràn ra ngoài modal */
html body.is-mobile-device #user-logs-modal .card {
    overflow: visible !important;
}
html body.is-mobile-device #user-logs-modal .card-body {
    padding: 6px !important;
    overflow: visible !important;
}
/* Row trong filter card: không tràn */
html body.is-mobile-device #user-logs-modal .row {
    margin-left: -4px !important;
    margin-right: -4px !important;
    width: calc(100% + 8px) !important;
}

/* ════════════════════════════════════════════════════════════
   FIX <1> — Sidebar toggle switches: size đúng + align giữa
   dbc.Checklist switch=True render ra:
   .form-check.form-switch > input.form-check-input + label.form-check-label
   ════════════════════════════════════════════════════════════ */

/* Wrapper dòng switch */
body.is-mobile-device .sidebar .form-check.form-switch,
body.is-mobile-device .sidebar .form-check {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
    min-height: unset !important;
    padding-left: 0 !important;
    margin-bottom: 4px !important;
}

/* Toggle input (cái thanh trượt) */
body.is-mobile-device .sidebar .form-check-input[type="checkbox"] {
    width: 32px !important;
    height: 18px !important;
    min-width: 32px !important;
    min-height: 18px !important;
    flex-shrink: 0 !important;
    margin: 0 !important;
    cursor: pointer !important;
    border-radius: 10px !important;
    position: relative !important;
    float: none !important;
}

/* Label text bên phải */
body.is-mobile-device .sidebar .form-check-label {
    font-size: 0.72rem !important;
    line-height: 1.3 !important;
    margin: 0 !important;
    padding: 0 !important;
    cursor: pointer !important;
    flex: 1 1 auto !important;
    align-self: center !important;
}

/* Override global .btn min-height không ảnh hưởng switch */
body.is-mobile-device .sidebar .form-check .form-check-input {
    min-height: unset !important;
}

/* ============================================================
   PERF FIX: On mobile or low-end machines, backdrop-filter
   blur is extremely expensive. Replace with solid backgrounds.
   Mobile GPUs (especially older Android) cannot accelerate
   backdrop-filter — it falls back to slow software rendering.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    body.is-mobile-device .navbar,
    body.is-mobile-device #main-navbar {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background: rgba(10, 15, 30, 0.98) !important;
    }
    body.is-mobile-device .mobile-bottom-nav,
    body.is-mobile-device .mobile-sidebar,
    body.is-mobile-device .mobile-overlay {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
}

/* ── LOW-PERF AUTO MODE (perf_detect.js) ─── */
html.low-perf body.is-mobile-device .navbar,
html.low-perf body.is-mobile-device #main-navbar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: rgba(10, 15, 30, 0.98) !important;
}

/* ════════════════════════════════════════════════════════════
   CHECKLIST DETAIL MODAL — Mobile Card Layout
   Desktop: show table, hide cards
   Mobile:  hide table, show cards
   ════════════════════════════════════════════════════════════ */

/* ── DESKTOP: hide card list ── */
.maint-cl-mobile-cards {
    display: none;
}
/* ── DESKTOP: show table ── */
.maint-cl-desktop-table {
    display: block;
}

/* ── MOBILE: hide table, show cards ── */
body.is-mobile-device .maint-cl-desktop-table {
    display: none !important;
}
body.is-mobile-device .maint-cl-mobile-cards {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    padding: 4px 2px !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    /* height: fills remaining space after summary */
    flex: 1 1 auto !important;
    min-height: 0 !important;
}

/* ── CARD wrapper ── */
body.is-mobile-device .cl-mobile-card {
    border: 1px solid var(--border-color, rgba(99,102,241,0.25)) !important;
    border-radius: 10px !important;
    overflow: hidden !important;
    background: var(--card-bg, #1e293b) !important;
    box-shadow: 0 2px 8px rgba(0,0,0,0.18) !important;
    flex-shrink: 0 !important;
}
body.is-mobile-device .cl-mobile-card.cl-card-locked {
    opacity: 0.75 !important;
    border-color: rgba(239,68,68,0.35) !important;
}

/* ── CARD HEADER ── */
body.is-mobile-device .cl-card-header {
    display: flex !important;
    align-items: flex-start !important;
    gap: 8px !important;
    padding: 7px 10px !important;
    background: rgba(99,102,241,0.10) !important;
    border-bottom: 1px solid var(--border-color, rgba(99,102,241,0.18)) !important;
}
body.is-mobile-device .cl-card-idx {
    font-size: 0.65rem !important;
    font-weight: 700 !important;
    color: var(--primary-color, #6366f1) !important;
    flex-shrink: 0 !important;
    min-width: 24px !important;
    line-height: 1.6 !important;
}
body.is-mobile-device .cl-card-path {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    font-size: 0.68rem !important;
    line-height: 1.45 !important;
    word-break: break-word !important;
}
body.is-mobile-device .cl-card-area {
    font-weight: 700 !important;
    color: var(--text-primary, #e2e8f0) !important;
}
body.is-mobile-device .cl-card-sep {
    color: var(--text-secondary, #94a3b8) !important;
    padding: 0 2px !important;
}
body.is-mobile-device .cl-card-comp {
    font-weight: 600 !important;
    color: var(--text-primary, #e2e8f0) !important;
}
body.is-mobile-device .cl-card-detail {
    display: block !important;
    color: var(--text-secondary, #94a3b8) !important;
    font-size: 0.63rem !important;
    margin-top: 2px !important;
    white-space: pre-wrap !important;
}

/* ── CARD FIELDS GRID ── */
body.is-mobile-device .cl-card-fields {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 0 !important;
    padding: 0 !important;
}
body.is-mobile-device .cl-card-field {
    display: flex !important;
    flex-direction: column !important;
    padding: 6px 10px !important;
    border-bottom: 1px solid var(--border-color, rgba(99,102,241,0.1)) !important;
    border-right: 1px solid var(--border-color, rgba(99,102,241,0.1)) !important;
    min-width: 0 !important;
    overflow: hidden !important;
}
body.is-mobile-device .cl-card-field:nth-child(2n) {
    border-right: none !important;
}
/* Full-width fields (Vật tư, Hình ảnh, Ghi chú) */
body.is-mobile-device .cl-card-field.cl-card-f-full {
    grid-column: 1 / -1 !important;
    border-right: none !important;
}
/* Last row: no bottom border */
body.is-mobile-device .cl-card-field:last-child,
body.is-mobile-device .cl-card-field.cl-card-f-full:last-child {
    border-bottom: none !important;
}
/* Penultimate when last is full-width */
body.is-mobile-device .cl-card-field.cl-card-f-full:nth-last-child(2) {
    border-bottom: none !important;
}

/* ── LABEL ── */
body.is-mobile-device .cl-card-label {
    font-size: 0.56rem !important;
    font-weight: 600 !important;
    color: var(--text-secondary, #94a3b8) !important;
    text-transform: uppercase !important;
    letter-spacing: 0.4px !important;
    margin-bottom: 3px !important;
    white-space: nowrap !important;
}

/* ── CONTROL: select, input, textarea ── */
body.is-mobile-device .cl-card-ctrl select,
body.is-mobile-device .cl-card-ctrl .maint-cl-native-select {
    font-size: 16px !important;    /* iOS anti-zoom */
    width: 100% !important;
    min-height: 32px !important;
    padding: 4px 6px !important;
    border-radius: 6px !important;
    box-sizing: border-box !important;
}
body.is-mobile-device .cl-card-ctrl input[type="datetime-local"] {
    font-size: 13px !important;
    width: 100% !important;
    min-height: 32px !important;
    padding: 4px 5px !important;
    border-radius: 6px !important;
    box-sizing: border-box !important;
}
body.is-mobile-device .cl-card-ctrl textarea {
    font-size: 14px !important;
    width: 100% !important;
    min-height: 40px !important;
    padding: 5px 7px !important;
    border-radius: 6px !important;
    box-sizing: border-box !important;
    resize: vertical !important;
}
body.is-mobile-device .cl-card-ctrl .small.cl-text {
    font-size: 0.72rem !important;
    line-height: 2 !important;
    color: var(--text-primary, #e2e8f0) !important;
}

/* ── Helper multiselect inside card ── */
body.is-mobile-device .cl-card-ctrl .cl-ms-wrap {
    width: 100% !important;
    position: relative !important;
}
body.is-mobile-device .cl-card-ctrl .cl-ms-ctrl {
    min-height: 32px !important;
    font-size: 0.72rem !important;
}
body.is-mobile-device .cl-card-ctrl .cl-ms-menu {
    z-index: 9999 !important;
}

/* ── Image cell inside card ── */
body.is-mobile-device .cl-card-ctrl .maint-cl-img-cell {
    gap: 5px !important;
}
body.is-mobile-device .cl-card-ctrl .maint-cl-img-upload-btn {
    font-size: 0.70rem !important;
    padding: 5px 8px !important;
}

/* ── maint-cl-modal-body-inner: flex column so cards can fill height ── */
body.is-mobile-device .maint-cl-modal-body-inner {
    display: flex !important;
    flex-direction: column !important;
    height: 100% !important;
    overflow: hidden !important;
}
body.is-mobile-device .maint-cl-modal-body-inner .maint-cl-summary-wrapper {
    flex-shrink: 0 !important;
}
body.is-mobile-device #maint-cl-modal-table {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
}

/* ════════════════════════════════════════════════════════════
   FIX <1>: Mobile — reset #tab-content-wrapper scroll (desktop only)
   Trên mobile, #main-content-container là scroll root.
   #tab-content-wrapper KHÔNG được scroll — reset về visible/auto.
   .main-content cũng không dùng flexbox layout trên mobile.
   ════════════════════════════════════════════════════════════ */
body.is-mobile-device .main-content {
    display: block !important;
    height: auto !important;
    padding: 0 0.5rem 0 0.5rem !important;
    overflow: visible !important;
}
body.is-mobile-device #tab-content-wrapper {
    flex: unset !important;
    overflow-y: visible !important;
    overflow-x: visible !important;
    padding: 0 !important;
    height: auto !important;
    min-height: unset !important;
}
body.is-mobile-device #login-lock-screen {
    flex: unset !important;
    min-height: unset !important;
}

/* ── 26_asm_settings.css ─────────────────────────────── */
/* ============================================================
   26_asm_settings.css – ASM System tab in Admin modal
   Mirrors maintenance settings style for consistency.
   Dark / Light mode both supported.
   ============================================================ */

/* ── ASM Config Table ─────────────────────────────────────── */

.asm-config-table {
  table-layout: fixed;
}

.asm-config-row td {
  vertical-align: middle;
  padding: 4px 6px;
  font-size: 0.82rem;
  border-bottom: 1px solid var(--border-color, #dee2e6);
}

.asm-config-row:nth-child(even) {
  background: rgba(0, 0, 0, 0.02);
}

.asm-config-row:hover {
  background: rgba(99, 102, 241, 0.06);
}

/* ── Type Table ───────────────────────────────────────────── */

.asm-type-row td {
  vertical-align: middle;
  padding: 5px 6px;
  font-size: 0.83rem;
  border-bottom: 1px solid var(--border-color, #dee2e6);
}

.asm-type-row:hover {
  background: rgba(99, 102, 241, 0.06);
}

.asm-type-row.asm-drag-active {
  opacity: 0.55;
  outline: 2px dashed #6366f1;
}

.asm-drag-handle {
  cursor: grab;
  user-select: none;
  font-size: 1rem;
  color: var(--text-muted, #6c757d);
  padding: 0 4px;
}

.asm-drag-handle:active {
  cursor: grabbing;
}

/* ── Pagination bar ───────────────────────────────────────── */

#asm-config-pagination {
  padding: 6px 2px;
  gap: 8px;
}

#asm-config-pagination button {
  font-size: 0.78rem;
}

/* ── Unsaved badge ────────────────────────────────────────── */

#asm-config-unsaved-badge,
#asm-types-unsaved-badge {
  font-size: 0.75rem;
  vertical-align: middle;
}

/* ── Row count label ──────────────────────────────────────── */

#asm-config-row-count {
  font-size: 0.78rem;
}

/* ═══════════════════════════════════════════════════════════
   DARK MODE
   ═══════════════════════════════════════════════════════════ */

[data-bs-theme="dark"] .asm-config-row:nth-child(even),
.dark-mode               .asm-config-row:nth-child(even),
[data-theme="dark"]      .asm-config-row:nth-child(even) {
  background: rgba(255, 255, 255, 0.03);
}

[data-bs-theme="dark"] .asm-config-row:hover,
.dark-mode               .asm-config-row:hover,
[data-theme="dark"]      .asm-config-row:hover {
  background: rgba(99, 102, 241, 0.12);
}

[data-bs-theme="dark"] .asm-config-row td,
.dark-mode               .asm-config-row td,
[data-theme="dark"]      .asm-config-row td {
  border-color: rgba(255, 255, 255, 0.08);
}

[data-bs-theme="dark"] .asm-type-row td,
.dark-mode               .asm-type-row td,
[data-theme="dark"]      .asm-type-row td {
  border-color: rgba(255, 255, 255, 0.08);
}

[data-bs-theme="dark"] .asm-type-row:hover,
.dark-mode               .asm-type-row:hover,
[data-theme="dark"]      .asm-type-row:hover {
  background: rgba(99, 102, 241, 0.12);
}

[data-bs-theme="dark"] .asm-drag-handle,
.dark-mode               .asm-drag-handle,
[data-theme="dark"]      .asm-drag-handle {
  color: rgba(255, 255, 255, 0.45);
}

/* ── Admin DB table additions (for new asm_* tables) ─────── */

.admin-db-table .asm-new-badge {
  font-size: 0.68rem;
  margin-left: 4px;
}

/* ── 27_spare_parts_buttons.css ──────────────────────── */
/* ============================================================
   27_spare_parts_buttons.css — Spare Parts Action Buttons
   Hover, active, focus effects for Add / Nhập kho / Xuất kho
   ============================================================ */

/* ── Base shared style for all 3 SP action buttons ── */
#btn-sp-add,
#btn-sp-nhap-kho,
#btn-sp-xuat-kho,
[id*="btn-sp-nhap-kho-in-tab"],
[id*="btn-sp-xuat-kho-in-tab"] {
    position: relative;
    overflow: hidden;
    font-weight: 600;
    letter-spacing: 0.3px;
    border: none;
    transition:
        transform       0.18s cubic-bezier(0.4, 0, 0.2, 1),
        box-shadow      0.18s cubic-bezier(0.4, 0, 0.2, 1),
        filter          0.18s ease,
        background-color 0.18s ease;
}

/* Ripple pseudo-element */
#btn-sp-add::after,
#btn-sp-nhap-kho::after,
#btn-sp-xuat-kho::after,
[id*="btn-sp-nhap-kho-in-tab"]::after,
[id*="btn-sp-xuat-kho-in-tab"]::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0);
    transition: background 0.2s ease;
    border-radius: inherit;
    pointer-events: none;
}

/* ── ADD button (primary / indigo) ── */
#btn-sp-add {
    background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%);
    box-shadow: 0 2px 6px rgba(79, 70, 229, 0.35);
}
#btn-sp-add:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(79, 70, 229, 0.45);
    filter: brightness(1.08);
}
#btn-sp-add:hover::after {
    background: rgba(255, 255, 255, 0.08);
}
#btn-sp-add:active {
    transform: translateY(0px) scale(0.97);
    box-shadow: 0 2px 6px rgba(79, 70, 229, 0.3);
    filter: brightness(0.95);
}

/* ── NHẬP KHO button (success / green) ── */
#btn-sp-nhap-kho,
[id*="btn-sp-nhap-kho-in-tab"] {
    background: linear-gradient(135deg, #059669 0%, #10b981 100%);
    box-shadow: 0 2px 6px rgba(16, 185, 129, 0.35);
}
#btn-sp-nhap-kho:hover,
[id*="btn-sp-nhap-kho-in-tab"]:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(16, 185, 129, 0.45);
    filter: brightness(1.08);
}
#btn-sp-nhap-kho:hover::after,
[id*="btn-sp-nhap-kho-in-tab"]:hover::after {
    background: rgba(255, 255, 255, 0.08);
}
#btn-sp-nhap-kho:active,
[id*="btn-sp-nhap-kho-in-tab"]:active {
    transform: translateY(0px) scale(0.97);
    box-shadow: 0 2px 6px rgba(16, 185, 129, 0.3);
    filter: brightness(0.95);
}

/* ── XUẤT KHO button (warning / amber) ── */
#btn-sp-xuat-kho,
[id*="btn-sp-xuat-kho-in-tab"] {
    background: linear-gradient(135deg, #d97706 0%, #f59e0b 100%);
    box-shadow: 0 2px 6px rgba(245, 158, 11, 0.35);
    color: #fff !important;
}
#btn-sp-xuat-kho:hover,
[id*="btn-sp-xuat-kho-in-tab"]:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(245, 158, 11, 0.45);
    filter: brightness(1.08);
    color: #fff !important;
}
#btn-sp-xuat-kho:hover::after,
[id*="btn-sp-xuat-kho-in-tab"]:hover::after {
    background: rgba(255, 255, 255, 0.08);
}
#btn-sp-xuat-kho:active,
[id*="btn-sp-xuat-kho-in-tab"]:active {
    transform: translateY(0px) scale(0.97);
    box-shadow: 0 2px 6px rgba(245, 158, 11, 0.3);
    filter: brightness(0.95);
}

/* ── Dark mode adjustments ── */
[data-theme="dark"] #btn-sp-add {
    background: linear-gradient(135deg, #4338ca 0%, #6366f1 100%);
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
}
[data-theme="dark"] #btn-sp-nhap-kho,
[data-theme="dark"] [id*="btn-sp-nhap-kho-in-tab"] {
    background: linear-gradient(135deg, #047857 0%, #10b981 100%);
    box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
}
[data-theme="dark"] #btn-sp-xuat-kho,
[data-theme="dark"] [id*="btn-sp-xuat-kho-in-tab"] {
    background: linear-gradient(135deg, #b45309 0%, #f59e0b 100%);
    box-shadow: 0 2px 8px rgba(245, 158, 11, 0.4);
}

/* ── Disabled state ── */
#btn-sp-add:disabled,
#btn-sp-nhap-kho:disabled,
#btn-sp-xuat-kho:disabled,
[id*="btn-sp-nhap-kho-in-tab"]:disabled,
[id*="btn-sp-xuat-kho-in-tab"]:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none !important;
    box-shadow: none !important;
    filter: none !important;
}


/* ============================================================
   SPARE PARTS ADD MODAL — Upload button, image preview, dirty
   banner, formula hint, required field errors
   ============================================================ */

/* FIX <4>: Upload button — hover + click effects */
.sp-add-upload-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border: 2px dashed var(--border-color, #d1d5db);
    border-radius: 8px;
    background: var(--card-bg, #f9fafb);
    color: var(--text-muted, #6b7280);
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    transition: border-color 0.18s ease, background 0.18s ease,
                color 0.18s ease, transform 0.15s ease, box-shadow 0.18s ease;
    user-select: none;
    margin-top: 4px;
    min-height: 44px;
}
.sp-add-upload-btn:hover {
    border-color: #6366f1;
    background: rgba(99, 102, 241, 0.06);
    color: #6366f1;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.18);
}
.sp-add-upload-btn:active {
    transform: translateY(0) scale(0.98);
    box-shadow: 0 2px 6px rgba(99, 102, 241, 0.12);
}
[data-theme="dark"] .sp-add-upload-btn,
body.dark-mode       .sp-add-upload-btn {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.2);
    color: rgba(255, 255, 255, 0.55);
}
[data-theme="dark"] .sp-add-upload-btn:hover,
body.dark-mode       .sp-add-upload-btn:hover {
    border-color: #818cf8;
    background: rgba(129, 140, 248, 0.12);
    color: #818cf8;
}

/* FIX <5>: Image preview wrapper — flex row with × button */
.sp-add-img-preview-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}

.sp-add-img-clear-btn {
    position: relative;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: none;
    background: #ef4444;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background 0.15s ease, transform 0.12s ease;
}
.sp-add-img-clear-btn:hover {
    background: #dc2626;
    transform: scale(1.12);
}
.sp-add-img-clear-btn:active {
    transform: scale(0.95);
}

/* FIX <7>: Formula hint — visible text color */
.sp-add-formula-hint {
    display: block;
    font-size: 11px;
    margin-top: 3px;
    color: var(--text-muted, #6b7280) !important;
    font-style: italic;
}
[data-theme="dark"] .sp-add-formula-hint,
body.dark-mode       .sp-add-formula-hint {
    color: rgba(255, 255, 255, 0.5) !important;
}

/* FIX <8>: Dirty / unsaved-changes banner */
.sp-add-dirty-banner {
    display: none;   /* hidden by default; shown via inline style by callback */
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.45);
    border-radius: 6px;
    padding: 7px 12px;
    font-size: 13px;
    font-weight: 500;
    color: #92400e;
    margin-bottom: 10px;
    align-items: center;
    gap: 6px;
}
[data-theme="dark"] .sp-add-dirty-banner,
body.dark-mode       .sp-add-dirty-banner {
    background: #78350f;
    border-color: #f59e0b;
    color: #fef3c7;
}

/* FIX <9>: Required field error messages */
.sp-add-field-err {
    font-size: 11px;
    margin-top: 2px;
    color: #dc2626 !important;
}

/* FIX <2>: Force scrollable modal body for spare parts modals */
#sp-add-modal .modal-body,
#sp-in-modal .modal-body,
#sp-out-modal .modal-body {
    max-height: 70vh;
    overflow-y: auto !important;
}

/* FIX <5>: Min Qty display field — always readable text */
#sp-add-min-qty-display,
#sp-add-min-qty-display:disabled {
    color: var(--text-color, #1f2937) !important;
    -webkit-text-fill-color: var(--text-color, #1f2937) !important;
    opacity: 1 !important;
    background-color: var(--input-disabled-bg, #f3f4f6) !important;
}
[data-theme="dark"] #sp-add-min-qty-display,
[data-theme="dark"] #sp-add-min-qty-display:disabled,
body.dark-mode #sp-add-min-qty-display,
body.dark-mode #sp-add-min-qty-display:disabled {
    color: rgba(255,255,255,0.85) !important;
    -webkit-text-fill-color: rgba(255,255,255,0.85) !important;
    background-color: rgba(255,255,255,0.07) !important;
}

/* FIX <6>: Stock-out "Request By" (auto-filled) display field — always readable text */
#sp-out-request-by-display,
#sp-out-request-by-display:disabled {
    color: var(--text-color, #1f2937) !important;
    -webkit-text-fill-color: var(--text-color, #1f2937) !important;
    opacity: 1 !important;
    background-color: var(--input-disabled-bg, #f3f4f6) !important;
}
[data-theme="dark"] #sp-out-request-by-display,
[data-theme="dark"] #sp-out-request-by-display:disabled,
body.dark-mode #sp-out-request-by-display,
body.dark-mode #sp-out-request-by-display:disabled {
    color: rgba(255,255,255,0.85) !important;
    -webkit-text-fill-color: rgba(255,255,255,0.85) !important;
    background-color: rgba(255,255,255,0.07) !important;
}

/* ── 28_ai_loading_overlay.css ───────────────────────── */
/* ============================================================
   28_ai_loading_overlay.css — Popup "Đang chờ AI phân tích..."

   Hiện khi user chuyển sang 1 tab/sub-tab có dùng nhận xét AI
   (Báo cáo Tuần, Báo cáo Tháng, So sánh) VÀ nội dung AI đó cần
   thời gian để tải (chưa có cache / đang sinh lại). Được bật/tắt
   bởi các clientside callback trong modules/callbacks/cb_ai.py
   (toggle className "visible" trên #ai-loading-overlay).
   ============================================================ */

#ai-loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.55);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 10000; /* trên cả #loading-overlay (9999) */
    backdrop-filter: blur(3px);
}

#ai-loading-overlay.visible {
    display: flex;
}

#ai-loading-overlay .ai-loading-content {
    background: var(--modal-bg, #ffffff);
    color: var(--text-primary, #212529);
    padding: 28px 40px;
    border-radius: 16px;
    text-align: center;
    box-shadow: var(--shadow-xl, 0 10px 40px rgba(0, 0, 0, 0.35));
    max-width: 380px;
    border: 1px solid var(--border-color, rgba(0,0,0,0.08));
}

#ai-loading-overlay .ai-loading-icon {
    font-size: 2.6rem;
    line-height: 1;
    margin-bottom: 12px;
    animation: ai-loading-pulse 1.4s ease-in-out infinite;
    will-change: transform, opacity;
}

@keyframes ai-loading-pulse {
    0%, 100% { transform: scale(1);    opacity: 1;   }
    50%      { transform: scale(1.18); opacity: 0.65; }
}

#ai-loading-overlay .ai-loading-text {
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.45;
}

#ai-loading-overlay .ai-loading-subtext {
    font-size: 0.82rem;
    font-weight: 400;
    color: var(--text-secondary, #6c757d);
    margin-top: 6px;
}

/* Tôn trọng chế độ tiết kiệm hiệu năng / accessibility đã có sẵn trong app */
html.low-perf #ai-loading-overlay .ai-loading-icon,
html.low-perf-manual #ai-loading-overlay .ai-loading-icon {
    animation: none;
}

@media (prefers-reduced-motion: reduce) {
    #ai-loading-overlay .ai-loading-icon {
        animation: none;
    }
}

/* ── 29_layout_watermark.css ─────────────────────────── */
/* ============================================================
   29_layout_watermark.css — Full-layout UI watermark overlay
   Renders repeating diagonal watermark text over the entire
   main content area (all tabs). NOT printed on charts directly —
   export/fullscreen still uses add_watermark() in Python.
   ============================================================ */

/*
  Strategy: CSS custom properties drive everything.
  Python callback writes:
    --wm-display   : block | none
    --wm-content   : the repeating text (set via JS, see below)

  Because CSS `content` cannot reference a var() with arbitrary
  text safely across all browsers, we use a <div id="ui-watermark-overlay">
  injected into the DOM and position it with fixed positioning so it
  covers the full viewport above main content but below modals.
*/

#ui-watermark-overlay {
    position: fixed;
    inset: 0;                        /* top/right/bottom/left: 0 */
    pointer-events: none;            /* click-through */
    z-index: 10;                     /* above content, below modals (modals ~1050) */
    overflow: hidden;
    display: none;                   /* shown via JS when watermark active */
    user-select: none;
    -webkit-user-select: none;
}

#ui-watermark-overlay.wm-active {
    display: block;
}

/* FIX: when the fullscreen chart modal is open, raise the overlay above the
   modal. This app forces .modal to z-index:1200 (see 18_modals.css) and
   z-index:2100 on mobile, so we go above both to guarantee the watermark is
   still visible over the enlarged chart. pointer-events stays "none" so it
   never blocks interaction with the modal (close button, chart hover, etc.). */
#ui-watermark-overlay.wm-over-modal {
    z-index: 2500;
}

/* The inner tiling div — oversized + rotated so no edge gaps ever show */
#ui-watermark-overlay .wm-tile {
    position: absolute;
    /* FIX: extend well beyond all edges to guarantee full coverage after rotation */
    top: -80%;
    left: -80%;
    width: 260%;
    height: 260%;
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    transform: rotate(-30deg);
    transform-origin: center center;
}

#ui-watermark-overlay .wm-line {
    width: 100%;
    display: flex;
    flex-wrap: nowrap;              /* FIX: never wrap — each row fills full width */
    flex-shrink: 0;
    padding: 14px 0;
}

#ui-watermark-overlay .wm-item {
    font-size: 15px;
    font-weight: 600;
    /* FIX: use CSS variable for opacity so JS can update it live */
    color: rgba(160, 160, 160, var(--wm-opacity, 0.10));
    white-space: nowrap;
    padding: 0 44px;
    letter-spacing: 0.04em;
    font-family: var(--font-main, 'Inter', sans-serif);
    line-height: 1.4;
    flex-shrink: 0;
}

/* FIX: email rows properly interleaved — offset by half item-width for stagger effect */
#ui-watermark-overlay .wm-line.wm-line-offset {
    margin-left: -120px;             /* half-offset so rows don't align vertically */
}

/* Email lines slightly different style for visual alternation */
#ui-watermark-overlay .wm-item.wm-email {
    color: rgba(120, 160, 210, var(--wm-opacity-email, 0.08));
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.06em;
}

/* ── 30_logout_guard.css ─────────────────────────────── */
/**
 * 30_logout_guard.css
 *
 * Khi user logout, class "user-logged-out" được thêm vào <body>
 * bởi logout_sticky_guard.js.
 *
 * CSS này dùng !important để force-hide các sub-header WRAPPER DIVs.
 * Không touch các UL sub-tabs (chúng nằm bên trong wrapper → tự ẩn theo).
 *
 * Đây là tầng phòng thủ cuối — override mọi inline style Dash callback set.
 */

/* ── Khi logged out: ẩn toàn bộ sticky sub-header wrappers ── */
body.user-logged-out #sp-sub-header-sticky,
body.user-logged-out #inc-sub-header-sticky,
body.user-logged-out #report-sub-header-sticky,
body.user-logged-out #maint-sub-header-sticky,
body.user-logged-out #shift-sub-header-sticky,
body.user-logged-out #wp-sub-header-sticky,
body.user-logged-out #doc-sub-header-sticky,
body.user-logged-out #maint-cl-filter-sticky,
body.user-logged-out #maint-planning-filter,
body.user-logged-out #maint-details-filter,
body.user-logged-out #overview-kpi-sticky,
body.user-logged-out #maint-planning-header-btns,
body.user-logged-out #compare-filter-container,
body.user-logged-out #report-filter-wrapper,
body.user-logged-out #shift-filter-container {
    display: none !important;
    visibility: hidden !important;
    pointer-events: none !important;
}


/* ── Permission-controlled nav tabs: ẩn ngay từ đầu (trước khi JS load) ──
 *
 * 4 tabs này luôn có trong DOM (tránh main-tabs remount khi login gây mất
 * nội dung tab). CSS ẩn chúng ngay khi page render — không có flash.
 * JS trong permissions-store callback (cb_clientside.py) sẽ set
 * li.style.display = '' để show lại khi user có quyền tương ứng.
 * inline style (từ JS) thắng CSS rule này nên không cần !important.
 */
#nav-tab-maintenance,
#tab-spare-parts-item,
#nav-tab-assets,
#nav-tab-work-orders {
    display: none;
}


/* ── Sidebar "Cài đặt hiển thị" + "Filter" accordions: ẩn NGAY từ khi CSS
 * load (trước khi bất kỳ JS nào kịp chạy) — KHÔNG phụ thuộc class
 * "user-logged-out" trên body (class đó chỉ được gắn sau DOMContentLoaded
 * qua MutationObserver → vẫn có độ trễ vài chục ms → filter bị "chớp" hiện
 * ra lúc app đang loading trước khi ổn định).
 *
 * Cùng pattern với 4 nav-tab phía trên: mặc định ẩn bằng CSS thường (không
 * !important) → JS (window.applySidebarFilterVisibility trong
 * assets/sidebar_filter_visibility.js, gọi từ cb_clientside.py) sẽ set
 * inline style "display" để hiện đúng mục theo tab/trạng thái đăng nhập
 * ngay khi xác định được — inline style luôn thắng CSS thường (không cần
 * !important) nên không xung đột.
 */
#display-accordion,
#date-accordion,
#system-accordion,
#type-filter-accordion,
#category-filter-accordion,
#status-filter-accordion,
#sidebar-header-container {
    display: none;
}

/* ── 31_shift_grid.css ───────────────────────────────── */
/* ─────────────────────────────────────────────────────────────────────────
   Shift schedule grid (tab Lịch ca > Ca làm việc) — #shift-grid-table
   Yêu cầu: mỗi ô mã ca là 1 dropdown (Dash DataTable presentation:"dropdown",
   dùng react-select bên trong) nhưng hiển thị gọn như "chip" kiểu Google
   Sheet data-validation — KHÔNG có mũi tên dropdown, KHÔNG có padding/margin
   thừa bên trong ô, để tối đa không gian hiển thị mã ca (OFF/AL/11S.../...).
   ───────────────────────────────────────────────────────────────────────── */

/* 1. Ẩn hẳn mũi tên dropdown (Select-arrow-zone) trong toàn bộ grid */
#shift-grid-table .Select-arrow-zone,
#shift-worktime-grid-table .Select-arrow-zone,
#shift-grid-table .Select-arrow,
#shift-worktime-grid-table .Select-arrow {
    display: none !important;
    width: 0 !important;
    padding: 0 !important;
}

/* 2. Bỏ toàn bộ padding/margin trong ô + control để nội dung mã ca chiếm
      hết không gian ô, căn giữa như 1 "chip" */
#shift-grid-table .dash-cell,
#shift-worktime-grid-table .dash-cell {
    padding: 0 !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   1b. FIX (#2 + #4, lượt kiểm tra lại): "height"/"verticalAlign" khai báo
       trong style_cell (Python) KHÔNG có tác dụng thật sự — dash_table bọc
       nội dung mỗi ô trong 1 <div class="dash-cell-value..."> riêng bên
       trong <td>; "vertical-align" đặt trên <td> không ảnh hưởng tới 1 div
       con hiển thị kiểu block bên trong nó, và "height" trên style_cell chỉ
       áp cho <td> chứ không ép được <div> con co theo — nên dù đã khai báo
       ở Python, hàng vẫn cao và chữ vẫn lệch trên/dưới như cũ. Phải ép
       trực tiếp bằng CSS !important lên chính <td class="dash-cell"> VÀ
       div nội dung bên trong nó (dùng flexbox để việc căn giữa dọc thực sự
       có tác dụng bất kể nội dung là text thường hay dropdown). */
#shift-grid-table .dash-cell,
#shift-worktime-grid-table .dash-cell {
    height: 20px !important;
}
/* Chỉ ép flex/height cho div nội dung KHÔNG PHẢI react-select (".Select").
   Bản trước lỡ dùng "#shift-grid-table .dash-cell > div" (không loại trừ
   ".Select"), nên vô tình khớp luôn div gốc của react-select — ép
   display:flex + align-items:center lên chính nó khiến ".Select-control"
   con bên trong (vốn cũng có height:100% !important) bị co về 0 vì
   align-items:center đổi hành vi mặc định "stretch" của flex item, làm
   toàn bộ mã ca trong các ô dropdown biến mất (dù data/tooltip vẫn còn).
   Sửa: thêm ":not(.Select)" để loại trừ hẳn react-select ra khỏi rule
   này — các ô mã ca (đều là dropdown) đã có sẵn rule căn giữa riêng ở
   ".Select-control" bên dưới rồi, không cần và không nên đụng vào nữa. */
#shift-grid-table .dash-cell > div:not(.Select),
#shift-worktime-grid-table .dash-cell > div:not(.Select),
#shift-grid-table .dash-cell .dash-cell-value,
#shift-worktime-grid-table .dash-cell .dash-cell-value,
#shift-grid-table .dash-cell .dash-cell-value-container,
#shift-worktime-grid-table .dash-cell .dash-cell-value-container,
#shift-grid-table .dash-cell .input-cell-value-container,
#shift-worktime-grid-table .dash-cell .input-cell-value-container {
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-sizing: border-box !important;
}
/* Cột "Nhân viên" (cell đầu tiên mỗi hàng, KHÔNG phải dropdown, không có
   ".Select"): chỉ căn giữa DỌC, ngang vẫn để trái, và cho phép chữ xuống
   dòng (đã bật whiteSpace:normal ở Python). */
#shift-grid-table td:first-child .dash-cell-value,
#shift-worktime-grid-table td:first-child .dash-cell-value,
#shift-grid-table td:first-child .dash-cell-value-container,
#shift-worktime-grid-table td:first-child .dash-cell-value-container,
#shift-grid-table td:first-child .input-cell-value-container,
#shift-worktime-grid-table td:first-child .input-cell-value-container,
#shift-grid-table td:first-child > div:not(.Select),
#shift-worktime-grid-table td:first-child > div:not(.Select) {
    justify-content: flex-start !important;
    white-space: normal !important;
    text-align: left !important;
}
#shift-grid-table td:first-child,
#shift-worktime-grid-table td:first-child {
    height: auto !important;
    min-height: 20px !important;
}
/* FIX (theo yêu cầu mới): thêm khoảng cách bên trái cho tên nhân viên,
   không để chữ dính sát mép trái ô. "paddingLeft":"6px" đã khai báo ở
   style_cell_conditional (Python) nhưng bị rule "#shift-grid-table
   .dash-cell { padding: 0 !important; }" (mục 2, đầu file) ghi đè về 0 —
   !important trong CSS luôn thắng inline style bất kể specificity, nên
   phải ép lại rõ ràng ở đây, riêng cho cột đầu tiên, để không ảnh hưởng
   tới các ô mã ca khác (vẫn cần padding:0 để tối đa không gian hiển thị). */
#shift-grid-table td:first-child.dash-cell,
#shift-worktime-grid-table td:first-child.dash-cell {
    padding-left: 6px !important;
}

#shift-grid-table .dash-cell .Select,
#shift-worktime-grid-table .dash-cell .Select,
#shift-grid-table .dash-cell .Select-control,
#shift-worktime-grid-table .dash-cell .Select-control {
    height: 100% !important;
    min-height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}

#shift-grid-table .dash-cell .Select-control,
#shift-worktime-grid-table .dash-cell .Select-control {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#shift-grid-table .dash-cell .Select-value,
#shift-worktime-grid-table .dash-cell .Select-value,
#shift-grid-table .dash-cell .Select-value-label,
#shift-worktime-grid-table .dash-cell .Select-value-label,
#shift-grid-table .dash-cell .Select-placeholder,
#shift-worktime-grid-table .dash-cell .Select-placeholder {
    position: static !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 100% !important;
    padding: 0 2px !important;
    margin: 0 !important;
    line-height: normal !important;
    text-align: center !important;
    font-size: 10px !important;
    /* FIX (lượt kiểm tra mới nhất): BUG — các ô mã ca "nghỉ" (OFF/AL/PH/
       NPL/KL/SL/...) không được in đậm dù Python (non_normal_shift_weight_style
       trong ui_shift.py) đã set fontWeight="700" riêng cho đúng những ô đó,
       và fontWeight="500" cho các ca thường (Sx). Nguyên nhân: chữ mã ca
       không nằm trực tiếp trong <td> mà nằm trong span.Select-value-label
       lồng bên trong react-select — rule ở đây TRƯỚC ĐÂY ép cứng
       "500 !important" cho MỌI ô mã ca không phân biệt, nên luôn ghi đè
       giá trị 700 mà Python set riêng cho ô OFF/AL, khiến ca nghỉ không
       bao giờ đậm hơn ca thường.
       Sửa: dùng "inherit !important" thay vì ép cứng 1 con số cố định —
       vẫn thắng CSS mặc định (không !important) của react-select như cũ,
       nhưng để span con THỰC SỰ kế thừa đúng fontWeight đã tính trên
       <td> cha (500 cho ca thường, 700 cho ca nghỉ), thay vì luôn 1 mức. */
    font-weight: inherit !important;
    color: #212529 !important;
    /* FIX (#2, lượt kiểm tra thứ 4): dash_table tự nạp kèm 1 bản CSS mặc
       định của react-select (không phải do file này hay file nào khác của
       dự án) ép ".Select--single > .Select-control .Select-value" có
       position:absolute + line-height:34px + padding 10px, VÀ một rule
       khác ép "background-color:#fcfcfc; border:1px solid #e3e3e3" cho
       trạng thái multi/disabled — nhưng vì các rule đó không dùng
       !important trong khi rule của mình ở đây có !important, bản thân
       việc chỉ định lại "position/padding/line-height" ở trên ĐÃ đủ thắng.
       Phần "badge" màu xám còn sót lại (nếu có) là do border/background
       mặc định của trình duyệt/react-select rò rỉ vào — ép rõ ràng lại
       background/border/box-shadow = none ngay tại đây để chắc chắn ô mã
       ca luôn là text trần, không viền/không nền riêng. */
    background: none !important;
    background-color: transparent !important;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
}

/* 2c-2. FIX (#4): dash_table mặc định ép ".dash-spreadsheet-inner tr" cao
   tối thiểu 30px (không !important) và ".Select"/".Select-control" cao
   30px "để khớp với td" — nhưng khi mình đã thu gọn ô xuống 24px thì các
   giá trị 30px mặc định này (áp trên chính <tr>, không phải <td>) khiến
   trình duyệt vẫn kéo giãn hàng theo giá trị lớn hơn. Ép lại rõ ràng trên
   <tr> để hàng thực sự thấp xuống theo đúng ý muốn. */
#shift-grid-table .dash-spreadsheet-inner tr,
#shift-worktime-grid-table .dash-spreadsheet-inner tr {
    height: 20px !important;
    min-height: 20px !important;
}
#shift-grid-table td:first-child,
#shift-worktime-grid-table td:first-child,
#shift-grid-table .dash-spreadsheet-inner tr:has(td:first-child[rowspan]),
#shift-worktime-grid-table .dash-spreadsheet-inner tr:has(td:first-child[rowspan]) {
    height: auto !important;
}

/* 2e. SAFETY NET bổ sung (#2, lượt kiểm tra thứ 5): các state class của
   react-select (is-focused / is-open) có rule riêng trong CSS mặc định của
   dash_table ép "background: #fff" cho .Select-control khi đang mở menu
   hoặc đang focus — không phải màu badge nhưng vẫn là 1 nền trắng lộ ra
   khác với nền ô, nhìn giống "hộp" khi bấm vào. Ép transparent lại rõ ràng
   cho MỌI state để mã ca luôn là text trần kể cả khi đang mở dropdown. */
#shift-grid-table .dash-cell .Select.is-focused > .Select-control,
#shift-worktime-grid-table .dash-cell .Select.is-focused > .Select-control,
#shift-grid-table .dash-cell .Select.is-open > .Select-control,
#shift-worktime-grid-table .dash-cell .Select.is-open > .Select-control,
#shift-grid-table .dash-cell .Select.is-focused:not(.is-open) > .Select-control,
#shift-worktime-grid-table .dash-cell .Select.is-focused:not(.is-open) > .Select-control {
    background: transparent !important;
    box-shadow: none !important;
}

/* 2b. SAFETY NET: nếu vì lý do gì đó label dài hơn dự kiến (thay vì chỉ
      mã ngắn như "AL"/"OFF"), cắt gọn bằng "…" trên 1 dòng duy nhất thay
      vì để trình duyệt tự xuống dòng rồi bị chiều cao ô cắt cụt giữa chừng
      (đây chính là nguyên nhân gây hiển thị kiểu "y nghỉ l" trước khi fix
      label ở get_all_code_options()). */
#shift-grid-table .dash-cell .Select-value-label,
#shift-worktime-grid-table .dash-cell .Select-value-label {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    display: block !important;
}

/* 2c. Tooltip mô tả đầy đủ khi hover ô (thay cho việc nhồi mô tả vào label).
   FIX (#3, lượt 2): bản trước chỉ set "max-width" nên khung ngoài do
   dash_table tự thêm (thường có "width" inline cố định khá lớn) vẫn to
   hơn hẳn nội dung 1 dòng chữ ngắn, để lại 1 khoảng trắng thừa lớn bên
   phải. Ép luôn "width: fit-content"/"min-width: 0" (thắng cả style
   inline vì có !important) để khung tooltip co khít đúng theo chữ. Đồng
   thời đổi màu nền/chữ/viền cho tương phản rõ ràng, không bị chìm vào
   nền tối của bảng. */
#shift-grid-table .dash-table-tooltip,
#shift-worktime-grid-table .dash-table-tooltip {
    font-size: 12px;
    width: fit-content !important;
    min-width: 0 !important;
    max-width: 220px !important;
    white-space: normal;
    text-align: left;
    padding: 6px 10px !important;
    background-color: #1e2a4a !important;
    color: #f1f5f9 !important;
    border: 1px solid #818cf8 !important;
    border-radius: 6px !important;
    box-shadow: 0 4px 14px rgba(0,0,0,0.45) !important;
}
#shift-grid-table .dash-table-tooltip > div,
#shift-worktime-grid-table .dash-table-tooltip > div {
    width: fit-content !important;
    min-width: 0 !important;
    max-width: 220px !important;
    padding: 0 !important;
    margin: 0 !important;
    background-color: transparent !important;
    color: inherit !important;
}
/* Mũi tên nhỏ trỏ vào ô (dash_table tự vẽ bằng border-color) — đổi màu
   khớp với border tooltip ở trên để đồng bộ, không còn màu mặc định
   (thường là trắng/xám nhạt) lạc quẻ giữa nền tối. */
#shift-grid-table .dash-table-tooltip::before,
#shift-worktime-grid-table .dash-table-tooltip::before,
#shift-grid-table .dash-table-tooltip::after,
#shift-worktime-grid-table .dash-table-tooltip::after {
    border-top-color: #818cf8 !important;
    border-bottom-color: #818cf8 !important;
}

/* 2c-2. FIX (#2): chỉ highlight ĐÚNG 1 Ô đang hover, không còn sáng cả
   hàng. Trước đây rule chung ở 10_tables.css ("tr:hover td") tô màu toàn
   bộ ô trong hàng khi hover — giờ 2 bảng này đã được loại trừ khỏi rule
   đó (xem 10_tables.css), nên có thể tự định nghĩa hiệu ứng hover RIÊNG
   ở đây. Dùng "outline" (không phải background) để không đè mất màu mã
   ca (S19OT/OFF/AL...) vốn đang tô sẵn theo backgroundColor riêng của
   từng ô — ô hover chỉ nổi bật thêm viền + hơi sáng lên, màu gốc vẫn giữ
   nguyên, các ô khác trong cùng hàng KHÔNG bị ảnh hưởng gì. */
/* ─────────────────────────────────────────────────────────────────────────
   FIX GỐC THẬT SỰ (#1 + #2 + #3, xác nhận bằng script debug F12 do người
   dùng chạy — log cho thấy: click 1 lần đã mở ĐÚNG ô (mousedown của
   react-select mở menu trước cả khi sự kiện "click" kịp bắn ra — đây là
   hành vi gốc bình thường của react-select, không phải bug), và
   double-click chỉ đơn giản TOGGLE ĐÓNG lại menu vừa mở (click đầu mở,
   click thứ 2 trong thao tác double-click gặp menu đang mở → tự đóng —
   cũng là hành vi chuẩn của react-select, không phải bug). Menu luôn mở
   ĐÚNG Ô — nhưng lại HIỂN THỊ SAI VỊ TRÍ (thường lệch hẳn xuống góc dưới-
   phải màn hình), khiến người dùng tưởng lầm "hover ô khác cũng ra
   dropdown" (thực chất vẫn là menu của đúng ô đã click, chỉ là bị vẽ sai
   chỗ, đè lên các ô khác ở góc màn hình).
   Nguyên nhân sai vị trí: rule hover ngay bên dưới đây TRƯỚC ĐÂY dùng
   "filter: brightness(1.15)" trên ".dash-cell:hover" — theo đúng chuẩn
   CSS, "filter" (khác "none") trên 1 phần tử CHA sẽ khiến phần tử đó tự
   động trở thành "containing block" MỚI cho MỌI phần tử con có
   "position: fixed" nằm bên trong nó (giống hệt "transform"/"perspective"/
   "will-change: transform" — đây là 1 hành vi ít người biết của CSS,
   không phải bug của trình duyệt). Vì JS (attachMenuStyleGuard trong
   shift_grid_custom_tooltip.js) ép dropdown menu thành "position: fixed"
   để thoát khỏi việc bị cắt bởi overflow của bảng, và người dùng LUÔN
   đang hover ngay đúng ô vừa click (chuột đang ở đó) đúng vào lúc menu
   mở ra — ô đó khớp ":hover" → "filter" kích hoạt → dropdown menu (là con
   cháu trong DOM của chính ô này) đột nhiên bị tính lại vị trí theo
   containing-block là CÁI Ô 24px NHỎ XÍU đó thay vì theo viewport như JS
   đã tính bằng getBoundingClientRect(), dù giá trị top/left JS gán vào
   vẫn là toạ độ viewport bình thường — kết quả: menu bị đẩy lệch hẳn đi.
   Sửa: bỏ hẳn "filter", thay bằng "box-shadow: inset" để tạo hiệu ứng ô
   sáng lên tương đương khi hover — box-shadow KHÔNG nằm trong danh sách
   các thuộc tính tạo containing-block mới, nên không còn ảnh hưởng gì
   tới vị trí "position: fixed" của dropdown nữa. */
/* ─────────────────────────────────────────────────────────────────────────
   FIX (#4 — dropdown mã ca bị bảng "Thời gian làm việc" bên dưới che mất):
   rule hover này TRƯỚC ĐÂY có "position: relative; z-index: 3;" — bất kỳ
   z-index khác "auto" trên phần tử positioned đều tự tạo 1 stacking
   context MỚI cho chính ô <td> đó. Menu dropdown (JS ép "z-index: 999999")
   vẫn nằm LỒNG BÊN TRONG DOM của ô <td> này (chỉ "position: fixed" để
   thoát crop/overflow, KHÔNG di chuyển ra khỏi cây DOM) — nên toàn bộ nội
   dung con của ô, kể cả menu z-index 999999, bị "nhốt" trong stacking
   context z=3 của ô cha khi so sánh với các phần tử NGOÀI ô này (z-index
   cao chỉ thắng được trong CÙNG 1 stacking context, không "xuyên" qua
   được stacking context của tổ tiên). Trong khi đó sticky_header.js gắn
   "z-index: 99 !important" cho hàng filter (th) của CẢ 2 bảng ca làm việc
   — 99 > 3 — nên khi ô đang mở dropdown ở gần đáy bảng 1, dropdown xổ
   xuống chồng lên vùng bảng 2 phía dưới, bảng 2 (nhờ sticky header ở lớp
   z=99) vẽ đè lên toàn bộ ô + dropdown (đang bị nhốt ở lớp z=3).
   Sửa: bỏ hẳn "position: relative; z-index: 3;" khỏi rule hover — không
   cần thiết vì hiệu ứng nổi bật khi hover đã dùng "outline" với
   "outline-offset: -2px" (viền thụt VÀO TRONG ô, không tràn ra ngoài biên)
   nên không cần đẩy ô lên bằng z-index. Bỏ z-index ở đây giúp ô <td> (và
   dropdown menu con của nó) không còn tự tạo stacking context riêng nữa —
   dropdown lúc này chỉ còn bị giới hạn bởi stacking context gốc (viewport),
   nơi z-index 999999 mới thực sự có tác dụng so với MỌI phần tử khác trên
   trang, kể cả sticky header z=99 của bảng bên dưới. */
/* ─────────────────────────────────────────────────────────────────────────
   FIX (#4 — dropdown mã ca bị bảng bên dưới che mất, XÁC NHẬN QUA LOG DEBUG
   F12 THẬT do người dùng chạy — không phải suy đoán): log cho thấy đúng
   phần tử tạo stacking-context "nhốt" dropdown là
   "#shift-grid-table.dash-table-container" với "position: relative;
   z-index: 1;" — ĐÂY LÀ RULE GLOBAL bên 05_layout.css áp dụng cho MỌI
   bảng dash_table trên toàn bộ app (mục đích: giữ bảng luôn nằm DƯỚI các
   thanh sticky khác). Vì dropdown menu (dù JS ép z-index 999999) vẫn nằm
   lồng trong DOM của chính bảng #shift-grid-table, nó bị nhốt trong lớp
   z=1 đó khi so sánh với các phần tử NGOÀI bảng (như bảng "Thời gian làm
   việc" phía dưới) — z-index cao chỉ thắng trong CÙNG 1 stacking context.
   Sửa: loại riêng 2 bảng ca làm việc khỏi rule global đó — chúng không
   cần "nằm dưới sticky elements" theo cách này vì đã tự lo phần dropdown/
   tooltip bằng JS position:fixed riêng (không dùng đường sticky thường).
   Dùng ID selector (specificity cao hơn class ".dash-table-container") để
   ghi đè, không cần !important. */
#shift-grid-table.dash-table-container,
#shift-worktime-grid-table.dash-table-container {
    z-index: auto;
}

/* ─────────────────────────────────────────────────────────────────────────
   FIX (#4 tiếp, mục 2e ở trên): rule hover này TRƯỚC ĐÂY có "position:
   relative; z-index: 3;" — cùng 1 cơ chế "nhốt" stacking-context như trên,
   nhưng ở cấp ô <td> thay vì cấp cả bảng. Bỏ vì không cần thiết (hiệu ứng
   nổi bật khi hover đã dùng "outline" với "outline-offset: -2px", thụt
   vào trong, không cần đẩy lớp bằng z-index). */
#shift-grid-table .dash-cell:hover,
#shift-worktime-grid-table .dash-cell:hover {
    outline: 2px solid #818cf8 !important;
    outline-offset: -2px;
    box-shadow: inset 0 0 0 999px rgba(255, 255, 255, 0.18);
}

/* ─────────────────────────────────────────────────────────────────────────
   2d. FIX GỐC (#1 + #2, lượt kiểm tra thứ 3): bản cài đặt dash_table thực tế
   trong requirements.txt (dash 2.14–2.18) render mỗi ô KHÔNG dùng cấu trúc
   ".dash-cell-value-container"/".input-cell-value-container" như 2 bản fix
   trước đó giả định — nó dùng đúng các class sau (kiểm tra trực tiếp trong
   bundle async-table.js của dash_table):
     - Ô dropdown (mã ca):  td > div.dash-dropdown-cell-value-container.dash-cell-value-container
                              > div.dropdown-cell-value-shadow (LUÔN ẩn, opacity:0, chỉ để đo size)
                              > div.Select > div.Select-control > ... > span.Select-value-label (CHỮ THẬT)
     - Ô label (không editable): td > div.dash-cell-value...
   Vì 2 rule ở mục 1b/2 phía trên chỉ nhắm ".dash-cell-value"/".dash-cell-value-container"
   mà KHÔNG có ":not(.Select)" loại trừ đúng, và vì browser áp dụng rule theo
   thứ tự xuất hiện trong file, một số thuộc tính căn giữa bị nạp SAU rule
   ".Select-value/.Select-value-label" ở dưới (dòng ~91-106) nên bị ghi đè
   ngược lại thành text-align mặc định của ô cha. Ép lại 1 lần cuối, rõ ràng,
   với đúng tên class thật + !important để không phụ thuộc thứ tự nạp file. */
#shift-grid-table .dash-cell-value,
#shift-worktime-grid-table .dash-cell-value,
#shift-grid-table .dash-cell-value-container,
#shift-worktime-grid-table .dash-cell-value-container,
#shift-grid-table .dash-dropdown-cell-value-container,
#shift-worktime-grid-table .dash-dropdown-cell-value-container {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
    height: 100% !important;
    width: 100% !important;
}
/* Cột "Nhân viên" vẫn giữ căn trái theo chiều ngang (đã có rule riêng ở
   dưới với độ ưu tiên cao hơn nhờ đứng sau trong file — nhưng thêm lại ở
   đây cho chắc chắn vì rule trên vừa ép justify-content:center cho MỌI ô). */
#shift-grid-table td:first-child .dash-cell-value,
#shift-worktime-grid-table td:first-child .dash-cell-value,
#shift-grid-table td:first-child .dash-cell-value-container,
#shift-worktime-grid-table td:first-child .dash-cell-value-container {
    justify-content: flex-start !important;
    text-align: left !important;
}
/* Shadow đo kích thước của react-select — PHẢI luôn vô hình, không chiếm
   layout. LƯU Ý: KHÔNG đổi "position" của div này — dash_table dùng vị trí
   tương đối của các phần tử trong ô để tính toán vị trí hiển thị tooltip
   (hàm nội bộ đo khoảng cách tới <td> cha); đổi "position" ở đây từng làm
   MẤT tooltip hoàn toàn ở bản fix trước. Chỉ cần opacity:0 là đủ ẩn. */
#shift-grid-table .dropdown-cell-value-shadow,
#shift-worktime-grid-table .dropdown-cell-value-shadow,
#shift-grid-table .cell-value-shadow,
#shift-worktime-grid-table .cell-value-shadow {
    opacity: 0 !important;
    /* FIX (#1 + #2, lượt kiểm tra thứ 7): "opacity:0" chỉ làm vô hình chứ
       KHÔNG loại nó khỏi luồng layout bình thường — div shadow này vẫn
       chiếm chỗ theo chiều dọc (bản sao câu chữ, cùng font-size mặc định),
       nằm TRƯỚC phần tử ".Select" thật trong DOM. Trước đây hàng tự giãn
       cao hơn 24px để chứa đủ cả 2 (shadow ẩn + Select thật) nên chữ vẫn
       còn thấy được (dù dư chỗ). Sau khi thêm "overflow:hidden" + ép cứng
       24px ở bản fix trước, div shadow vô hình vẫn chiếm chỗ như cũ, đẩy
       phần ".Select" thật (chứa chữ mã ca) tụt xuống dưới vùng đang bị cắt
       -> chữ biến mất hoàn toàn dù data vẫn còn (tooltip đọc trực tiếp từ
       state, không phải từ DOM đang hiển thị, nên vẫn đúng). Sửa: ép luôn
       chiều cao div này về 0 (line-height/font-size/height đều 0 + overflow
       hidden) để nó không chiếm chỗ nữa — KHÔNG đổi "position" (giữ nguyên
       như ghi chú ở trên) để không lặp lại lỗi mất tooltip trước đây. */
    height: 0 !important;
    max-height: 0 !important;
    min-height: 0 !important;
    line-height: 0 !important;
    font-size: 0 !important;
    overflow: hidden !important;
    margin: 0 !important;
    padding: 0 !important;
    /* FIX (#1, lượt kiểm tra thứ 8 — nguyên nhân THẬT SỰ của "mã ca lệch
       trái"): div shadow này và div ".Select" (chứa chữ thật) là 2 phần tử
       CON CÙNG CẤP trong 1 flex-container "justify-content:center" (xem
       ".dash-dropdown-cell-value-container" ở mục 2d). flex "justify-
       content:center" canh giữa CẢ CỤM các flex-item cộng lại, không canh
       giữa riêng từng item — trước đây chỉ ép height:0 cho shadow (để nó
       không chiếm chỗ chiều DỌC) nhưng chưa ép width:0, nên shadow vẫn âm
       thầm chiếm đúng bằng độ rộng của chữ mã ca theo chiều NGANG (dù
       không nhìn thấy, vì opacity:0 không loại nó khỏi layout). Kết quả:
       cụm (shadow rộng X + Select rộng X) bị canh giữa như 1 khối duy
       nhất, đẩy phần Select thật (chữ mã ca) lệch sang TRÁI đúng bằng
       X/2 so với tâm ô — đây chính là lỗi lệch trái mà không phải lệch
       hẳn qua trái, khớp với những gì quan sát được trong ảnh chụp màn
       hình. Sửa: ép width:0 cho shadow (không đổi "position" — vẫn giữ
       đúng lưu ý ở trên để không lặp lại lỗi mất tooltip trước đây; chỉ
       riêng "width" không ảnh hưởng tới cách dash_table tính vị trí
       tooltip). */
    width: 0 !important;
    max-width: 0 !important;
    min-width: 0 !important;
    flex: 0 0 0 !important;
}
/* Đảm bảo chữ mã ca thật sự nằm TRÊN shadow (z-index) và luôn hiển thị,
   không bị component cha co về 0 chiều cao. */
#shift-grid-table .dash-dropdown-cell-value-container .Select,
#shift-worktime-grid-table .dash-dropdown-cell-value-container .Select {
    position: relative;
    z-index: 1;
    width: 100%;
}

/* ─────────────────────────────────────────────────────────────────────────
   2f. FIX GỐC THẬT SỰ của lỗi "row height 32px dù đã ép 24px" (kiểm tra qua
   script debug F12, lượt thứ 6): "height" đặt trên <tr> trong bảng HTML chỉ
   được trình duyệt coi là GIÁ TRỊ TỐI THIỂU, không phải giá trị ép cứng —
   nếu có phần tử con nào bên trong cần nhiều chỗ hơn, hàng vẫn tự giãn ra
   theo đúng nhu cầu của phần tử đó bất kể đã set height !important trên
   <tr>/<td>. Thủ phạm: chính react-select LUÔN render kèm 1 <input type=
   "text"> ẩn (dùng để gõ tìm kiếm) + 1 div "Autosize" đo độ rộng — cái
   <input> này có line-height/padding mặc định của trình duyệt (không phải
   do CSS nào của mình hay của project), tự nhiên cao hơn 24px và kéo giãn
   cả hàng theo. Trước đây mình chỉ ép padding/margin cho nó, CHƯA ép chiều
   cao/line-height — đây chính là phần còn thiếu. */
#shift-grid-table .dash-cell .Select-input,
#shift-worktime-grid-table .dash-cell .Select-input,
#shift-grid-table .dash-cell .Select-input > input,
#shift-worktime-grid-table .dash-cell .Select-input > input {
    height: 12px !important;
    min-height: 0 !important;
    line-height: 12px !important;
    font-size: 10px !important;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    box-shadow: none !important;
    vertical-align: middle !important;
}
/* ─────────────────────────────────────────────────────────────────────────
   2g. FIX GỐC THẬT SỰ của lỗi "mã ca lệch trái" (kiểm tra qua script debug
   F12, lượt thứ 9 — đã đo trực tiếp getBoundingClientRect() từng lớp DOM):
   ".Select-multi-value-wrapper" (div bọc value + input tìm kiếm) là 1 flex
   container KHÔNG có "justify-content" (mặc định = "normal"/flex-start),
   chứa 2 phần tử con nằm CÙNG HÀNG:
     - ".Select-value"  (chứa chữ mã ca thật, vd "S19", rộng ~24px)
     - ".Select-input"  (ô input ẩn dùng để gõ tìm kiếm của react-select,
       rộng thật ~5px — TRƯỚC ĐÂY chỉ ép height/line-height/font-size cho nó
       để không kéo giãn hàng theo chiều DỌC, nhưng CHƯA ép width, nên nó
       vẫn chiếm chỗ thật theo chiều NGANG)
   Vì 2 phần tử này cộng lại vừa khít bằng đúng độ rộng của
   ".Select-multi-value-wrapper" (không còn khoảng trống thừa), nên dù có
   set "justify-content" gì cũng vô nghĩa — độ lệch không đến từ canh giữa
   sai, mà đến từ CHÍNH "Select-input" chiếm mất 1 phần chỗ đứng bên phải
   của "Select-value", đẩy chữ mã ca lệch sang trái đúng bằng PHÂN NỬA độ
   rộng của nó (đo thực tế: input rộng ~4.98px → chữ lệch trái ~2.49px —
   khớp chính xác với centerOffsetFromTd đo được trong log debug).
   Sửa: đưa hẳn "Select-input" ra khỏi luồng flex bằng "position:absolute"
   + "width:0" (không còn chiếm chỗ ngang trong ".Select-multi-value-
   wrapper" nữa — input vẫn tồn tại và vẫn nhận focus/gõ được bình thường
   khi mở dropdown, react-select tự định vị lại bằng "Autosize" nội bộ khi
   cần, không phụ thuộc vào layout tĩnh này), để "Select-value" trở thành
   phần tử DUY NHẤT còn lại trong luồng flex của wrapper, từ đó
   "justify-content:center" mới thực sự canh giữa được nó. */
#shift-grid-table .dash-cell .Select-input,
#shift-worktime-grid-table .dash-cell .Select-input {
    position: absolute !important;
    width: 0 !important;
    max-width: 0 !important;
    min-width: 0 !important;
    flex: 0 0 0 !important;
    overflow: hidden !important;
}
/* Div bọc input + value (Select-multi-value-wrapper) cũng phải theo đúng
   chiều cao 100% của ô, canh giữa dọc, để không tự tính theo input ẩn.
   Sau khi "Select-input" đã bị đưa ra khỏi luồng flex (ở trên), thêm
   "justify-content:center" ở đây mới thực sự có tác dụng (trước đó dù có
   set cũng vô nghĩa vì không còn khoảng trống nào để phân bổ). */
#shift-grid-table .dash-cell .Select-multi-value-wrapper,
#shift-worktime-grid-table .dash-cell .Select-multi-value-wrapper {
    height: 100% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
/* Chốt cuối cùng: cắt cứng mọi phần tràn ra ngoài 24px, để dù còn sót phần
   tử con nào chưa ép được hết, hàng CŨNG KHÔNG THỂ giãn quá chiều cao đã
   định — đây là cách duy nhất đảm bảo tuyệt đối, không phụ thuộc đoán đúng
   hết mọi phần tử con của react-select. */
#shift-grid-table .dash-cell,
#shift-worktime-grid-table .dash-cell {
    overflow: hidden !important;
}
#shift-grid-table .dash-spreadsheet-inner tr,
#shift-worktime-grid-table .dash-spreadsheet-inner tr {
    overflow: hidden !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   9. FIX GỐC THẬT SỰ (#1, header dòng 1 "dd/Thứ" không canh giữa dọc):
   Đã cài thử đúng bản dash==2.18.2 (bản project đang pin trong
   requirements.txt) và soi trực tiếp file async-table.js để tìm cấu trúc
   DOM thật + CSS mặc định của chính dash_table (không phải do project):
     <th class="dash-header"> > <div> > <span class="column-header-name">
   CSS mặc định đi kèm sẵn trong dash_table:
     ".dash-header > div { display: flex; }"   (KHÔNG có flex-direction,
     align-items, justify-content — mặc định là flex-direction:row)
     ".column-header-name { flex-grow: 1; }"
   Vì <div> con là 1 flex-ROW (không phải column), và <span> bên trong chỉ
   là 1 flex-item bình thường (không tự thành flex-container) — nên 2 dòng
   chữ "01\nT4" (tạo bởi \n + whiteSpace:pre-line ở Python) vẫn chảy theo
   luồng TEXT thông thường bên trong span, luôn dính ở mép TRÊN của khối,
   bất kể đã ép "verticalAlign"/"height" trên <th> ở style_header/style_cell
   (7 lượt fix trước đều CHỈ nhắm vào .dash-cell/.Select-* của các Ô DỮ LIỆU,
   chưa ai từng sửa cấu trúc riêng .dash-header > div này của HÀNG HEADER
   — đây chính là lý do row 1 luôn bị lệch trên dù mọi cách khác đã thử).
   Sửa: ép <div> con của <th> thành flex COLUMN, canh giữa cả 2 chiều; và
   ép flex-grow:0 cho span (nếu vẫn để flex-grow:1 trong flex-column, span
   sẽ tự giãn full chiều cao còn lại rồi 2 dòng chữ lại dính top y hệt cũ). */
#shift-grid-table th.dash-header,
#shift-worktime-grid-table th.dash-header {
    padding: 0 !important;
    vertical-align: middle !important;
    box-sizing: border-box !important;
    /* FIX (theo yêu cầu mới, lượt kiểm tra thứ 12): "fixed_rows={'headers':
       True}" khiến dash_table tự dựng thêm 1 BẢNG HEADER NHÂN BẢN (dùng để
       dán dính/sticky khi cuộn dọc), tách biệt hoàn toàn với bảng chính.
       Bảng nhân bản này có thể KHÔNG được gán "height" cố định giống bảng
       gốc — khiến div chứa đường kẻ ::after (mục 10 bên dưới, định vị bằng
       "top: 50%" tính theo chính chiều cao của div cha) bị tính sai chiều
       cao, đẩy đường kẻ tụt xuống dưới ranh giới thật của ô header, lấn
       vào hàng dữ liệu ngay bên dưới (đây là lý do đường kẻ xuất hiện ở
       hàng đầu tiên mà KHÔNG cần click vào ô nào, khớp với mô tả của
       người dùng). Sửa: ép "overflow:hidden" ngay tại chính <th> — bất kể
       bảng nhân bản/clone có tính sai chiều cao thế nào, mọi thứ (kể cả
       đường kẻ ::after) đều bị cắt cứng trong đúng ranh giới của ô header,
       không thể tràn xuống hàng dưới được nữa. */
    overflow: hidden !important;
}
#shift-grid-table th.dash-header > div,
#shift-worktime-grid-table th.dash-header > div {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    height: 100% !important;
    width: 100% !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
}
#shift-grid-table th.dash-header .column-header-name,
#shift-worktime-grid-table th.dash-header .column-header-name {
    display: block !important;
    flex-grow: 0 !important;
    flex-shrink: 0 !important;
    width: 100% !important;
    text-align: center !important;
    white-space: pre-line !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   10. FIX (theo yêu cầu mới): thêm 1 ĐƯỜNG GẠCH NGANG (không phải ký tự
   "-" trong text) để phân chia trực quan giữa dòng "dd" (ngày) và dòng
   "Thứ" bên trong mỗi ô header ngày — vẫn giữ nguyên 2 dòng xuống hàng như
   cũ (không gộp lại thành 1 dòng).
   Cách làm: vì nội dung 2 dòng nằm chung trong 1 <span class="column-
   header-name"> (dùng "\n" + white-space:pre-line, không thể chèn CSS
   giữa 2 dòng của CÙNG 1 khối text bằng cách thông thường), ta vẽ đường kẻ
   bằng pseudo-element "::after".
   Loại trừ ô góc "full_name" (cột "Nhân viên", chỉ có 1 dòng "mm-yyyy",
   không cần đường kẻ) bằng "[data-dash-column='full_name']".
   FIX (theo phản hồi mới #2 — đường kẻ bị lệch, đặc biệt khi zoom): bản
   trước đặt ::after trên <div> cha (bọc ngoài span) với "top: 16px" (giá
   trị px cố định, giả định div cha luôn cao đúng 32px chia đôi). Cách này
   sai vì 2 lý do: (1) chiều cao THẬT của khối 2 dòng chữ (tổng của 2 lần
   line-height) không nhất thiết đúng bằng 32px — còn tuỳ font-metrics thực
   tế của 'Inter' render ra, nên "nửa của div cha" không trùng khớp hoàn
   toàn với "ranh giới giữa 2 dòng chữ"; (2) khi trình duyệt zoom, mọi kích
   thước tính bằng px được render lại theo tỷ lệ zoom nhưng KHÔNG LUÔN làm
   tròn giống nhau giữa chiều cao div cha (do CSS height cố định) và chiều
   cao thật của text bên trong (do font rendering) — độ lệch nhỏ (dưới
   1px) ở tỷ lệ 100% bị phóng to thành lệch rõ rệt ở các mức zoom khác.
   Sửa TẬN GỐC: chuyển "position:relative" + "::after" từ <div> cha sang
   ĐÚNG <span class="column-header-name"> (span này đang "display:block",
   chỉ chứa vừa khít 2 dòng chữ, không dư khoảng trống nào khác) — nên
   "top: 50%" tính theo chiều cao CỦA CHÍNH SPAN luôn trùng khớp TUYỆT ĐỐI
   với ranh giới giữa 2 dòng (vì 2 dòng có line-height bằng nhau, mỗi dòng
   chiếm đúng 1 nửa chiều cao span) — không còn phụ thuộc vào giả định
   chiều cao cố định 32px của div cha nữa, nên luôn đúng vị trí ở MỌI mức
   zoom và MỌI kích thước ô header. */
#shift-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name,
#shift-worktime-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name {
    position: relative !important;
}
#shift-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name::after,
#shift-worktime-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 15%;
    right: 15%;
    height: 1px;
    /* FIX v2 (bản dùng CSS custom property "--divider-color" gán qua
       dash_table style_header_conditional KHÔNG hoạt động — đã xác nhận
       qua debug F12: dash_table âm thầm loại bỏ mọi custom property khi
       build lại inline style attribute của <th>, nên biến luôn rỗng và
       luôn rơi về fallback trắng cho MỌI cột, kể cả Chủ nhật).
       Cách làm MỚI: KHÔNG phụ thuộc dash_table style dict cho việc này
       nữa. Thay vào đó, assets/shift_sunday_divider.js tự quét DOM (qua
       MutationObserver, tự chạy lại mỗi khi Dash re-render bảng) và gắn
       class "sunday-divider-th" trực tiếp vào đúng .column-header-name
       của cột Chủ nhật. Mặc định (không có class) vẫn dùng màu trắng mờ
       như cũ cho mọi cột khác. */
    background-color: rgba(255, 255, 255, 0.45);
    pointer-events: none;
    transform: translateY(-50%);
}
#shift-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name.sunday-divider-th::after,
#shift-worktime-grid-table th.dash-header:not([data-dash-column="full_name"]) .column-header-name.sunday-divider-th::after {
    /* Riêng cột Chủ nhật (nền vàng #ffff00): đổi đường kẻ sang màu tối mờ
       để nổi rõ trên nền vàng, thay vì trắng mờ gần như vô hình. */
    background-color: rgba(0, 0, 0, 0.35);
}


/* ─────────────────────────────────────────────────────────────────────────
   11. FIX (theo yêu cầu mới): xóa "gạch ngang" lạ xuất hiện bên trong 1 số
   ô mã ca (ô "S7", "AL", "AL" — đều là những ô VỪA MỚI ĐƯỢC CLICK/CHỌN).
   Nguyên nhân: dash_table tự nạp sẵn 1 rule CSS mặc định (không phải do
   project) cho ô đang ở trạng thái "focused" (đang được chọn để sửa):
     ".dash-spreadsheet-inner td.focused { margin: -1px; z-index: 200; }"
   Rule này kéo lệch ô đang chọn lên/trái 1px + đẩy nó nổi lên trên các ô
   khác, để viền của nó ĐÈ LÊN viền ô lân cận cho nổi bật hơn (thiết kế gốc
   của dash_table dành cho bảng "sửa dữ liệu" bình thường). Nhưng vì bảng
   ca làm việc của mình đã ép nhiều CSS khác (height cố định, overflow:
   hidden, padding:0...) để có giao diện "chip" phẳng gọn, sự lệch 1px này
   khi cộng dồn với các CSS override khác hiển thị thành 1 vệt kẻ ngang lạ
   mắt bên trong ô, thay vì hiệu ứng nổi bật viền như dự định gốc.
   Sửa: vô hiệu hóa hẳn margin/z-index này cho ô đang chọn, vì bảng dạng
   chip không cần hiệu ứng "viền nổi bật khi chọn". */
#shift-grid-table td.focused,
#shift-worktime-grid-table td.focused {
    margin: 0 !important;
    z-index: auto !important;
}

/* 2f. FIX (theo yêu cầu): tắt vệt "tô màu tối/đỏ" xuất hiện khi
   double-click 1 ô trong bảng Ca làm việc. Xác nhận bằng script debug F12:
   dash_table tự gắn class "cell--selected focused" cho MỌI ô vừa được
   chọn (kể cả single-click, không riêng double-click) kèm nền đỏ nhạt
   "rgba(255, 65, 54, 0.2)" + outline tím 2px — bình thường bị dropdown
   đang mở che khuất nên không thấy, nhưng double-click (lần click thứ 2
   đóng dropdown lại — hành vi chuẩn của react-select) làm lộ ra vệt đỏ
   phía dưới, trông như 1 lỗi hiển thị mới. Bảng này VẪN CẦN giữ nguyên cơ
   chế chọn ô (không thể tắt "cell_selectable" như bảng Thời gian làm việc)
   vì dropdown mã ca phụ thuộc vào đúng luồng click/mousedown đó — nên chỉ
   vô hiệu hoá riêng phần TÔ MÀU của trạng thái "đã chọn", không đụng tới
   bất kỳ hành vi click/mousedown nào khác.
   FIX TIẾP (bản trước làm mất màu mã ca): "background-color: transparent
   !important" ở bản fix đầu tiên đã VÔ TÌNH xoá luôn màu nền riêng của
   từng mã ca (vd cyan cho "12S3") — màu đó cũng được gán qua inline style
   ngay trên chính <td>, nên bị !important của mình đè mất, để lộ nền tối
   của trang phía sau (nhìn như ô bị "đen"). Bỏ hẳn dòng "background-color"
   ở đây — chỉ còn giữ lại phần tắt outline/box-shadow (không mang thông
   tin màu mã ca, tắt an toàn). Phần khôi phục ĐÚNG màu nền gốc khi ô bị
   chọn được xử lý riêng bằng JS trong shift_grid_custom_tooltip.js (đọc
   lại màu gốc đã cache sẵn cho từng ô rồi áp lại bằng "!important" ngay
   khi phát hiện class "cell--selected"/"focused" xuất hiện — !important
   trong JS mới đủ mạnh để thắng lại rule mặc định của dash_table). */
#shift-grid-table td.cell--selected,
#shift-grid-table td.focused,
#shift-grid-table td.cell--selected.focused {
    box-shadow: none !important;
    outline: none !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   2g. FIX (yêu cầu mới #1 + #3): ô ngày trong bảng "Ca làm việc" giờ là ô
   nhập chữ thường (KHÔNG còn dropdown react-select — xem ui_shift.py), nên
   khi được click để sửa, dash_table thay nội dung ô bằng 1 thẻ <input> thật
   để gõ chữ. Thẻ <input> này KHÔNG có màu nền riêng theo mã ca (đó là màu
   được tô cho <td> qua style_data_conditional, không "kế thừa" xuống được
   <input> con) — nên nó hiển thị đúng màu nền MẶC ĐỊNH của mọi thẻ <input>
   trong theme tối toàn trang (thường là nền rất tối/đen), trông như "1 ô bị
   tô đen" giữa các ô màu khác — đây chính là "ô đen" trong phản ánh của
   người dùng, và ô này có thể bị "kẹt" ở trạng thái đang mở/focus khi thao
   tác kéo-chọn-vùng bắt đầu bằng chính ô đó (xem thêm chú thích ở hàm
   onMouseUp trong shift_grid_range_select.js).
   Sửa: ép nền + chữ + viền của MỌI <input> bên trong ô ngày về trong suốt/kế
   thừa đúng theo màu + chữ hiện có của <td> cha — không còn mảng đen nào
   xuất hiện nữa dù ô có đang ở trạng thái sửa hay không. Đồng thời đổi màu
   viền của Ô ĐANG SỬA (input đang focus) sang 1 màu dễ phân biệt (cam) thay
   vì đen/không có gì, để người dùng vẫn biết rõ đâu là ô "gốc" (nơi bắt đầu
   kéo chọn) khác với vùng chọn màu xanh do ".range-sel-cell" tô (xem mục 12
   cuối file). */
#shift-grid-table td.dash-cell input,
#shift-worktime-grid-table td.dash-cell input {
    background: transparent !important;
    background-color: transparent !important;
    color: inherit !important;
    border: none !important;
    outline: 1.5px solid #f59e0b !important;
    outline-offset: -1.5px;
    box-shadow: none !important;
}

/* 3. Chip look: bo góc nhẹ + hover để vẫn rõ đây là ô bấm chọn được */
#shift-grid-table .dash-cell .Select-control,
#shift-worktime-grid-table .dash-cell .Select-control {
    border-radius: 4px !important;
    cursor: pointer;
    transition: background-color .12s ease-in-out;
}

#shift-grid-table .dash-cell:hover .Select-control,
#shift-worktime-grid-table .dash-cell:hover .Select-control {
    background-color: rgba(13, 110, 253, 0.08) !important;
}

/* 4. Khi đang mở menu chọn mã ca, vẫn cho input full width, không bị mũi
      tên chiếm chỗ (đã ẩn ở trên) */
#shift-grid-table .Select-menu-outer,
#shift-worktime-grid-table .Select-menu-outer {
    z-index: 20;
    font-size: 12px;
    text-align: left;
}

/* 4b. FIX (dropdown bị "nhảy/giật" liên tục khi scroll trong danh sách mã
      ca hoặc khi hover sang ô khác trong lúc dropdown đang mở): xác nhận
      bằng script debug F12 — mỗi khi react-select tự re-render nội bộ (đổi
      option đang highlight lúc cuộn/hover), nó tự ghi đè lại
      "menuEl.style.position = 'absolute'" (khai báo inline THƯỜNG, không
      "!important"). JS (shift_grid_custom_tooltip.js) trước đó chỉ PHẢN
      ỨNG LẠI sau khi phát hiện thay đổi này để ép về "fixed" — nghĩa là có
      1 khoảnh khắc dropdown thực sự bị vẽ ở "position: absolute" (định vị
      theo containing block gần nhất thay vì viewport) trước khi JS kịp sửa
      lại, gây ra hiện tượng nhảy mỗi lần thư viện re-render.
      Giải pháp: ép "position: fixed" bằng "!important" NGAY TẠI ĐÂY (CSS
      ngoài). Theo đúng luật cascade: 1 khai báo "!important" trong
      stylesheet luôn thắng 1 khai báo inline THƯỜNG (không "!important") dù
      inline có specificity cao hơn — nên dù react-select có ghi đè lại
      "position: absolute" bao nhiêu lần đi nữa, trình duyệt vẫn LUÔN áp
      dụng "fixed" liên tục, không còn khoảng trống nào để "nhảy" nữa (JS
      không cần "chạy đua" sửa lại sau khi phát hiện thay đổi). */
#shift-grid-table .Select-menu-outer,
#shift-worktime-grid-table .Select-menu-outer {
    position: fixed !important;
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
    margin: 0 !important;
}

/* 5. Ô trống (chưa có mã ca) không hiện placeholder "Select..." mặc định
      của react-select — để trống cho gọn */
#shift-grid-table .dash-cell .Select-placeholder,
#shift-worktime-grid-table .dash-cell .Select-placeholder {
    color: transparent !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   6. FIX: Bảng lịch ca bị tràn ra khỏi container (khi có nhiều ngày trong
      tháng, ví dụ tháng 31 ngày). Nguyên nhân: dash_table.DataTable với
      fixed_columns tự tính width tuyệt đối cho 2 bảng con (cột "Nhân viên"
      cố định + phần cuộn ngang), và nếu các div cha không bị ép max-width,
      nó sẽ đẩy tràn cả layout trang thay vì chỉ cuộn ngang bên trong bảng.
   Fix: ép toàn bộ chuỗi div cha/con của bảng luôn <= 100% width của
      container ngoài cùng (#shift-grid-container), phần dư sẽ cuộn ngang
      (overflow-x: auto) ngay bên trong bảng, không lộ ra ngoài trang.
   ───────────────────────────────────────────────────────────────────────── */
#shift-grid-container {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

#shift-grid-table,
#shift-worktime-grid-table {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
}

#shift-grid-table .dash-spreadsheet-container,
#shift-worktime-grid-table .dash-spreadsheet-container {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    overflow-x: auto !important;
    box-sizing: border-box !important;
}

/* (Yêu cầu mới, ĐÃ XÁC NHẬN qua debug F12 do người dùng cung cấp log)
   FIX (header row1 rộng hơn/lệch với các row dữ liệu bên dưới):
   Bản fix trước đây ép "scrollbar-gutter:stable" + "overflow-y:scroll"
   nhầm lên ".dash-spreadsheet-container" — nhưng log F12 cho thấy đây
   KHÔNG PHẢI phần tử thực sự cuộn dọc (scrollHeight == clientHeight, tức
   chưa từng tràn nội dung). Phần tử cuộn dọc THẬT SỰ (nơi sinh ra thanh
   cuộn nhìn thấy trên màn hình, đã xác nhận scrollHeight > clientHeight)
   là DIV con sâu hơn có class ".dt-table-container__row-1" (bọc riêng
   hàng dữ liệu — dash_table tự sinh ra, tách biệt với hàng header
   ".dt-table-container__row-0"). Vì bản fix cũ ép "luôn chừa chỗ" ở SAI
   phần tử (container ngoài), nó chỉ tạo thêm 1 dải trống ~16px KHÔNG DÙNG
   ĐẾN nằm bên ngoài, trong khi ".dt-table-container__row-1" vẫn tự chừa
   thêm 15px riêng của chính nó khi tràn thật -> bị chừa chỗ 2 LẦN CHỒNG
   NHAU -> thanh cuộn thật bị đẩy vào "bên trong", để lộ khoảng trống thừa
   phía ngoài nó (đúng hiện tượng trong ảnh chụp màn hình mới). Sửa: bỏ ép
   ở container ngoài (revert lại "auto" bình thường, xem rule ngay trên),
   chuyển sang ép ĐÚNG vào ".dt-table-container__row-1": luôn chừa sẵn 1
   dải chỗ cho thanh cuộn dọc (overflow-y:scroll, không phải "auto") để
   width tính toán cho header (row-0) và dữ liệu (row-1) luôn nhất quán,
   không phụ thuộc thời điểm thanh cuộn tràn/không tràn nữa — và không còn
   dải trống thừa nào khác vì đây là chỗ DUY NHẤT chừa chỗ. */
#shift-grid-table .dt-table-container__row-1,
#shift-worktime-grid-table .dt-table-container__row-1 {
    overflow-y: scroll !important;
    scrollbar-gutter: stable;
}

/* (Yêu cầu mới) Log F12 lần 2 cho thấy: dù ".dt-table-container__row-1"
   (hàng dữ liệu) đã chừa đúng chỗ cho scrollbar (clientWidth=865 <
   offsetWidth=881), ".dt-table-container__row-0" (hàng HEADER, đứng NGOÀI/
   TRÊN row-1, là 1 phần tử ANH EM riêng biệt chứ không phải cha/con) vẫn
   giữ nguyên overflow-y:visible -> không hề chừa chỗ nào cả -> header vẫn
   trải full-width (bằng đúng width của .dash-spreadsheet-inner, KHÔNG trừ
   16px) trong khi hàng dữ liệu bên dưới đã bị trừ 16px cho scrollbar thật
   -> header lại rộng hơn/tràn lên đúng phần thanh cuộn đang hiển thị bên
   dưới nó, y hệt lỗi ban đầu.
   Cách xử lý ĐÚNG (tham khảo lại chính kỹ thuật đã dùng ở bảng "Mã ca"/
   "Thống kê" — ".shift-codes-header-wrap"): cho header row-0 CŨNG có 1
   thanh cuộn dọc NATIVE thật của riêng nó (overflow-y:scroll) để nó TỰ
   chừa đúng cùng 1 số px mà trình duyệt luôn dành cho scrollbar (không
   cần đoán số px, luôn khớp tuyệt đối vì cùng 1 trình duyệt/engine tính),
   rồi ẩn thanh cuộn đó đi bằng cách tô trong suốt — header vẫn hiện đủ
   100% nội dung (chỉ có 1 hàng, không tràn dọc) nên overflow-y:scroll
   không cắt mất chữ nào, chỉ đơn thuần chừa chỗ.
   FIX (gap dọc xuất hiện giữa header và hàng dữ liệu): đặt overflow-y:
   scroll khiến trình duyệt TỰ ĐỘNG ép overflow-x (đang là "visible") thành
   "auto" luôn (theo spec CSS Overflow — 1 trục non-visible thì trục còn
   lại không được phép giữ visible), làm row-0 tự sinh thêm 1 thanh cuộn
   NGANG phụ của riêng nó khi nội dung có bề rộng nhỉnh hơn 1 chút (do
   chính scrollbar-gutter vừa chừa ra) -> thanh cuộn ngang đó chiếm thêm
   chiều cao -> tạo ra khoảng gap ngay dưới header. Khóa cứng overflow-x:
   hidden để chỉ chừa chỗ THEO CHIỀU DỌC (đúng mục đích), không cho row-0
   tự phát sinh cuộn ngang riêng (row-0 vẫn cuộn ngang bình thường theo
   container cha .dash-spreadsheet-container ở ngoài, không cần tự cuộn). */
#shift-grid-table .dt-table-container__row-0,
#shift-worktime-grid-table .dt-table-container__row-0 {
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    scrollbar-gutter: stable;
    scrollbar-color: transparent transparent;
}
#shift-grid-table .dt-table-container__row-0::-webkit-scrollbar,
#shift-worktime-grid-table .dt-table-container__row-0::-webkit-scrollbar {
    background: transparent;
}
#shift-grid-table .dt-table-container__row-0::-webkit-scrollbar-thumb,
#shift-worktime-grid-table .dt-table-container__row-0::-webkit-scrollbar-thumb {
    background: transparent;
}

#shift-grid-table .dash-spreadsheet-inner,
#shift-worktime-grid-table .dash-spreadsheet-inner,

#shift-grid-table .dash-fixed-content,
#shift-worktime-grid-table .dash-fixed-content,
#shift-grid-table .dash-fixed-row,
#shift-worktime-grid-table .dash-fixed-row {
    max-width: 100% !important;
}

/* Các div cha bao ngoài bảng (sub-tab content, tab-content wrapper...) cũng
   cần min-width:0 vì chúng là flex/grid item — mặc định flex item có
   min-width:auto (co giãn theo nội dung), khiến bảng con to hơn container
   sẽ đẩy tràn cả cha thay vì bị ép co lại + cuộn ngang riêng. */
#shift-subtab-content-schedule,
#shift-subtab-content-wrapper {
    min-width: 0 !important;
    max-width: 100% !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   7. FIX (safety net): trước đây header/cột "Nhân viên" bị đè màu chữ bởi
      CSS chế độ tối (14_dark_mode.css áp dụng cho MỌI dash_table trong app)
      khiến chữ trùng màu nền -> vô hình. Bảng shift đã tự khai báo
      style_header/style_data_conditional màu tường minh trong Python, nhưng
      vẫn ép lại ở đây bằng !important, ưu tiên cao hơn rule chung của
      14_dark_mode.css (nạp trước theo thứ tự file), để chắc chắn không bao
      giờ tái diễn lỗi "chữ biến mất" dù theme sáng/tối.
   FIX (Chủ nhật ở HÀNG HEADER không lên màu vàng): rule này trước đây còn
      ép luôn cả "background: #3730a3 !important" cho MỌI ô header — dù
      Python (style_header_conditional, weekend_style) đã tính đúng màu vàng
      riêng cho cột Chủ nhật, !important ở đây (đặc hiệu hơn vì !important
      luôn thắng style thường, bất kể style đó set theo cột nào) vẫn đè lại
      thành màu chàm mặc định cho TẤT CẢ các cột, kể cả Chủ nhật -> đây là
      nguyên nhân "sửa hoài không lên vàng ở header" dù logic Python không
      còn lỗi gì. Mục đích gốc của rule #7 chỉ là đảm bảo MÀU CHỮ luôn hiện
      rõ (không bị chế độ tối đè mất) — không thật sự cần ép cả nền. Bỏ
      "background" ra khỏi rule !important này để header lại nền do
      Python quyết định theo từng cột (chàm mặc định / vàng cho Chủ nhật).
   FIX (chữ header cột Chủ nhật trắng trên nền vàng -> không đọc được): cùng
      nguyên nhân hệt như "background" ở trên — "color: #ffffff !important"
      ép TOÀN BỘ chữ header thành trắng, kể cả cột Chủ nhật vừa lên nền
      vàng, khiến chữ trắng/nền vàng không đọc nổi. Tách "color" ra khỏi
      !important y hệt cách đã làm với "background": Python giờ set màu chữ
      đen (#000000) riêng cho cột Chủ nhật trong weekend_style (áp dụng cho
      cả style_header_conditional lẫn style_data_conditional), còn các cột
      thường vẫn nhận màu trắng mặc định từ rule non-important bên dưới. */
#shift-grid-table .dash-header,
#shift-worktime-grid-table .dash-header,
#shift-grid-table th,
#shift-worktime-grid-table th {
    white-space: pre-line !important;
    line-height: 1.3 !important;
}
/* Màu chữ + nền MẶC ĐỊNH cho header — KHÔNG !important, để style_header_
   conditional / style_data_conditional của Python (vd: weekend_style tô
   vàng + chữ đen cho cột Chủ nhật) vẫn ghi đè được bình thường theo đúng
   cơ chế cascade CSS thông thường. Specificity ở đây tương đương/thấp hơn
   rule do dash_table tự sinh cho conditional style nên vẫn nhường đúng cho
   cột Chủ nhật. */
#shift-grid-table .dash-header,
#shift-worktime-grid-table .dash-header,
#shift-grid-table th,
#shift-worktime-grid-table th {
    background: #3730a3;
    color: #ffffff;
}

/* FIX: đã bỏ fixed_columns ở phía Python (xem ghi chú trong ui_shift.py) vì
   nó tạo ra 1 bảng "cột cố định" riêng biệt, tính width & áp style độc lập
   với bảng chính -> gây lệch width và khiến style_data_conditional không ăn
   -> chữ cột "Nhân viên" bị vô hình. Giờ cột "Nhân viên" chỉ còn là 1 ô
   `td` bình thường trong bảng chính (cột đầu tiên), nên chỉ cần 1 rule đơn
   giản theo nth-child, không cần phân biệt "fixed"/"scrolling" pane nữa. */
#shift-grid-table td:first-child,
#shift-worktime-grid-table td:first-child {
    color: #212529 !important;
    background: #ffffff !important;
}

/* FIX (đồng bộ cột "Nhân viên" giữa 2 bảng): Python đã set fontWeight="700"
   cho cột full_name ở CẢ 2 bảng (style_cell_conditional, giống hệt nhau),
   nhưng để chắc chắn 100% cột "Nhân viên" của bảng Mã ca luôn hiển thị đậm
   giống hệt bảng Thời gian làm việc trong mọi trường hợp (không phụ thuộc
   thứ tự nạp/merge style của dash_table), ép rõ ràng lại ở đây bằng
   !important cho cả 2 bảng. */
#shift-grid-table td:first-child .dash-cell-value,
#shift-worktime-grid-table td:first-child .dash-cell-value,
#shift-grid-table td:first-child .dash-cell-value-container,
#shift-worktime-grid-table td:first-child .dash-cell-value-container {
    font-weight: 700 !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   8. FIX (#5, đã kiểm tra lại): dùng "transparent" ở bản trước chỉ khiến ô
      lộ ra đúng màu NỀN TRANG phía sau — mà nền trang ở chế độ tối vốn là
      màu tối, nên nhìn vẫn y hệt "tối" như cũ (không phải do CSS nào đè,
      mà do bản chất "transparent" = trong suốt, không phải "sáng"). Sửa
      đúng ý muốn "không cần màu nền tối": ép nền Ô LUÔN LUÔN sáng (trắng),
      không phụ thuộc theme sáng/tối của toàn app — giống 1 bảng tính
      (spreadsheet) độc lập, để mã ca luôn rõ, dễ đọc trong mọi theme. Các
      màu tô có chủ đích (Chủ nhật / cyan / 1-15-25 / theo mã ca ưu tiên)
      vẫn là inline style nên luôn hiển thị đè lên trên bình thường. */
#shift-grid-table .dash-spreadsheet-inner tr:nth-child(odd) td,
#shift-worktime-grid-table .dash-spreadsheet-inner tr:nth-child(odd) td,
#shift-grid-table .dash-spreadsheet-inner tr:nth-child(even) td,
#shift-worktime-grid-table .dash-spreadsheet-inner tr:nth-child(even) td,
[data-theme="dark"] #shift-grid-table .dash-spreadsheet-inner tr:nth-child(odd) td,
[data-theme="dark"] #shift-grid-table .dash-spreadsheet-inner tr:nth-child(even) td,
[data-theme="dark"] #shift-grid-table .dash-spreadsheet-inner td {
    background-color: #ffffff;
    color: #212529;
}

/* ─────────────────────────────────────────────────────────────────────────
   12. REVERT (theo yêu cầu mới): đã thử 2 cách chỉnh đường kẻ (separate
   với viền nhạt "mượn" giữa các ô, rồi collapse với viền đủ 4 cạnh) nhưng
   cả 2 đều không đạt — vẫn còn hiện tượng đậm/mờ không đều, và bản collapse
   còn phát sinh thêm 1 viền ngoài không mong muốn quanh cả bảng (khả năng
   do cấu trúc bảng lồng của "fixed_rows" — dash_table tự dựng 1 bảng
   header nhân bản riêng để dán dính khi cuộn, và "border-collapse: collapse"
   khiến viền ngoài của bảng nhân bản này lộ ra rõ hơn, xếp chồng lên viền
   ngoài của bảng chính, tạo cảm giác như có thêm 1 khung viền bao quanh).
   Theo yêu cầu, ĐÃ GỠ BỎ HẲN mọi CSS tùy chỉnh cho border/border-collapse
   của bảng lịch ca — trả lại đúng đường kẻ MẶC ĐỊNH của thư viện dash_table
   (không phải do project chỉnh sửa), là trạng thái trước khi bắt đầu chỉnh
   sửa đường kẻ trong cuộc trò chuyện này.
   ───────────────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────────
   13. FIX (theo yêu cầu mới #2): đồng bộ font-family của TOÀN BỘ bảng lịch
   ca với font đang dùng cho các badge ở khu vực "Ghi chú" phía trên bảng.
   Các badge "Ghi chú" (html.Span trong cb_shift.py) KHÔNG khai báo
   fontFamily riêng nên chúng tự kế thừa font mặc định toàn app khai báo ở
   "body" (xem 02_base.css: 'Inter', -apple-system, BlinkMacSystemFont,
   'Segoe UI', Roboto, sans-serif).
   Trong khi đó, bảng lịch ca tuy có khai báo "fontFamily": "inherit" ở
   style_cell (Python) — nhưng dòng chữ mã ca THẬT SỰ nằm trong
   span.Select-value-label lồng bên trong react-select (thư viện ngoài),
   và react-select tự nạp kèm 1 font-family mặc định riêng của nó (không
   phải do project khai báo) cho các phần tử con này, KHÔNG "inherit" từ
   <td> cha nữa một khi đã vào bên trong cấu trúc react-select — đây là lý
   do dù Python đã set "inherit" ở style_cell, mã ca hiển thị vẫn có vẻ
   khác font với phần chữ thường trong bảng/badge.
   Sửa: ép tường minh cùng 1 font-family (giống hệt font khai báo ở body)
   cho mọi phần tử chữ trong bảng — cả ô header, ô dữ liệu thường (cột
   Nhân viên) lẫn phần tử con của react-select (nơi mã ca thật sự hiển
   thị) — để toàn bảng luôn cùng 1 font với badge "Ghi chú" bất kể cấu trúc
   DOM lồng nhau thế nào. */
#shift-grid-table,
#shift-worktime-grid-table,
#shift-grid-table .dash-cell,
#shift-worktime-grid-table .dash-cell,
#shift-grid-table th.dash-header,
#shift-worktime-grid-table th.dash-header,
#shift-grid-table .dash-cell .Select,
#shift-worktime-grid-table .dash-cell .Select,
#shift-grid-table .dash-cell .Select-control,
#shift-worktime-grid-table .dash-cell .Select-control,
#shift-grid-table .dash-cell .Select-value,
#shift-worktime-grid-table .dash-cell .Select-value,
#shift-grid-table .dash-cell .Select-value-label,
#shift-worktime-grid-table .dash-cell .Select-value-label,
#shift-grid-table .dash-cell .Select-placeholder,
#shift-worktime-grid-table .dash-cell .Select-placeholder,
#shift-grid-table .dash-cell .Select-input,
#shift-worktime-grid-table .dash-cell .Select-input,
#shift-grid-table .dash-cell .Select-input > input,
#shift-worktime-grid-table .dash-cell .Select-input > input,
#shift-grid-table .dash-table-tooltip,
#shift-worktime-grid-table .dash-table-tooltip {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sub-tab "Mã ca": row 1 (header) cho cả 3 bảng — Tech, BPO, "Mã ngày
   nghỉ" — KHÔNG dùng position:sticky nữa. Lý do đổi cách làm: sticky vẫn
   để lộ 1 khe hở khi cuộn nhanh/trên 1 số trình duyệt — các hàng dữ liệu
   (đặc biệt hàng có border/box-shadow riêng do hover) có thể "vượt lên"
   đè lên trên hàng sticky vì cả 2 cùng nằm chung 1 <table>/1 stacking
   context, sticky chỉ ghim vị trí chứ không tạo ra 1 lớp vẽ tách biệt
   đủ mạnh để luôn thắng z-index cục bộ của td/tr khác trong mọi trường
   hợp cuộn. Cách làm MỚI: tách hẳn row 1 ra thành 1 <table> header RIÊNG,
   nằm HOÀN TOÀN NGOÀI vùng overflow-y:auto (xem ui_shift.py —
   _build_team_shift_panel() và render_codes_subtab()). Vì vậy row 1
   không còn là 1 phần tử "cuộn cùng" nữa — nó là 1 khối tĩnh nằm phía
   trên khung cuộn, không có bất kỳ hàng dữ liệu nào có thể đè lên được,
   bất kể browser/tốc độ cuộn ra sao. 2 bảng header/body dùng chung 1 bộ
   <colgroup> (width %) + table-layout:fixed để các cột luôn thẳng hàng
   với nhau dù nội dung dài/ngắn khác nhau. */

/* Cả 2 bảng (header + body) đều fixed-layout để colgroup quyết định độ
   rộng cột (không để nội dung tự co giãn làm 2 bảng lệch cột nhau). */
.shift-codes-header-table,
.shift-codes-body-table {
    table-layout: fixed !important;
    width: 100% !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
    margin-bottom: 0 !important;
}
/* Khối bọc bảng header: đứng yên phía trên, không cuộn, không co giãn
   theo nội dung bảng body bên dưới.
   FIX (độ rộng cột header lệch với body): bảng body nằm trong
   .shift-codes-table-scroll có overflow-y:auto -> khi xuất hiện thanh
   cuộn dọc thật, nó "ăn" mất vài px chiều rộng nội dung, làm bảng body
   hẹp hơn bảng header (bảng header không có thanh cuộn nên không bị mất
   phần đó) => 2 bộ colgroup % tuy giống nhau về tỉ lệ nhưng tính trên 2
   chiều rộng khác nhau, lệch cột. Sửa: cho .shift-codes-header-wrap cũng
   có 1 thanh cuộn dọc NATIVE y hệt (overflow-y:scroll thay vì hidden) để
   "ăn" đúng cùng số px đó, rồi ẩn thanh cuộn đó đi (trong suốt) — nhờ
   dùng chung thanh cuộn mặc định của trình duyệt (không custom-style) ở
   cả 2 bên nên độ rộng luôn khớp nhau tuyệt đối, không cần đoán số px. */
.shift-codes-header-wrap {
    flex-shrink: 0;
    overflow-y: scroll;
    overflow-x: hidden;
    max-height: 200px; /* đủ cao để scrollbar luôn "có mặt" khi cần */
}
.shift-codes-header-wrap::-webkit-scrollbar {
    background: transparent;
}
.shift-codes-header-wrap::-webkit-scrollbar-thumb {
    background: transparent;
}
.shift-codes-header-wrap {
    scrollbar-color: transparent transparent;
}
.shift-codes-header-table th {
    /* (Yêu cầu mới) Cho phép chữ tiêu đề xuống dòng thay vì bị cắt "…" —
       nhiều tiêu đề dài (vd "FMS — Giờ bắt đầu") không đủ chỗ trên 1
       dòng khi cột hẹp. */
    white-space: normal !important;
    word-break: break-word;
    overflow: visible;
    text-overflow: unset;
    text-align: center;
    vertical-align: middle;
    line-height: 1.25;
    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%) !important;
    color: #fff !important;
    box-shadow: 0 2px 4px rgba(0,0,0,0.15);
    /* (FIX) Bảng "Nhân viên" không resize được cột — .col-resize-handle
       (position:absolute, xem 26_incidents_table.css) cần <th> cha có
       position:relative để bám đúng viền phải mỗi cột. Các bảng resize
       được khác dùng class .inc-detail-table đã có sẵn rule này; bảng
       "Mã ca"/"Nhân viên" dùng class .shift-codes-header-table riêng nên
       thiếu, khiến handle bị định vị lệch (theo ancestor xa hơn) và không
       bấm/kéo được. */
    position: relative;
}
[data-theme="dark"] .shift-codes-header-table th {
    background: linear-gradient(135deg, #4f46e5 0%, #3730a3 100%) !important;
    color: #fff !important;
    border-bottom: 1px solid #6366f1 !important;
}
/* Bảng body chỉ có <tbody> — bỏ viền trên (đã có viền dưới của header
   phía trên rồi, tránh viền đôi/dày bất thường ngay chỗ nối 2 bảng). */
.shift-codes-body-table tr:first-child td {
    border-top: none !important;
}
/* FIX (hàng header lệch/hẹp hơn hàng dữ liệu khi danh sách NGẮN, không đủ
   tràn khung 600px): trước đây dùng overflow-y:auto — chỉ thật sự chiếm
   chỗ thanh cuộn khi nội dung TRÀN. Trong khi đó .shift-codes-header-wrap
   ở trên luôn dùng overflow-y:scroll (luôn chừa chỗ thanh cuộn dù cuộn
   hay không) để đồng bộ với body — nhưng nếu body lại KHÔNG chừa chỗ khi
   không tràn thì 2 bên lệch width ngược lại (header hẹp hơn body). Đổi
   sang overflow-y:scroll (luôn chừa chỗ, giống hệt header-wrap) để 2 bảng
   luôn khớp width tuyệt đối trong MỌI trường hợp, không phụ thuộc số
   dòng dữ liệu nhiều hay ít. */
/* (FIX <1> — Sub-tab Nhân viên) Trước đây dùng maxHeight cố định 70vh
   (đặt trực tiếp trong Python) — trên các màn hình thấp (laptop 14")
   70vh nhỏ hơn nhiều so với khoảng trống thật còn lại phía dưới, khiến
   bảng bị "co lại" bỏ trống 1 khoảng lớn phía trên footer dù dữ liệu
   bên trong còn dài (vẫn phải cuộn). Sửa: áp dụng ĐÚNG kỹ thuật đã dùng
   cho bảng chi tiết Sự cố (xem .inc-detail-table-scroll ở
   26_incidents_table.css) — tính max-height bằng calc() dựa trên các
   biến CSS toàn cục --app-height/--navbar-height/--sticky-header-height
   (được cập nhật liên tục bởi STICKY_JS trong utils_js.py, chạy độc lập
   với MutationObserver riêng của Employees nên không bị lệch nhịp khi
   chuyển sub-tab). 150px còn lại = chiều cao thanh sub-tab "Mã ca/Nhân
   viên/Ca làm việc/Thống kê" (.sub-header-wrapper, KHÔNG nằm trong
   --sticky-header-height vì đó chỉ đo thanh tab chính) + nút "Thêm nhân
   viên" + bảng header (thead) riêng phía trên vùng cuộn. Nhờ dùng biến
   CSS toàn cục, rule này tự đúng trên MỌI kích thước màn hình/zoom,
   không cần JS riêng đo lại mỗi khi đổi sub-tab. */
#shift-employees-table-scroll {
    max-height: calc(var(--app-height, 100vh) - var(--navbar-height, 98px) - var(--sticky-header-height, 60px) - 150px) !important;
    min-height: 200px;
}
.shift-codes-table-scroll {
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    /* (Yêu cầu mới) An toàn thêm: buộc trình duyệt luôn chừa hẳn 1 dải
       riêng cho thanh cuộn dọc NẰM NGOÀI content box (không đè lên cột
       cuối/Action) — hỗ trợ tốt trên Chrome/Edge hiện đại. Cùng cơ chế
       overflow-y:scroll ở trên đã tự chừa chỗ, đây chỉ là lớp bảo hiểm
       thứ 2 để chắc chắn 100% không bị đè trên mọi trình duyệt/OS. */
    scrollbar-gutter: stable;
}
.shift-codes-header-wrap {
    scrollbar-gutter: stable;
}
/* (Yêu cầu mới) Cột cuối cùng (Action) trong bảng Nhân viên luôn chừa thêm
   1 khoảng đệm phải nhỏ để icon Ẩn/Sửa/Xóa/Vô hiệu hoá không bao giờ dính
   sát/bị đè bởi thanh cuộn dọc thật của .shift-codes-table-scroll. */
.shift-codes-table th:last-child,
.shift-codes-table td:last-child {
    padding-right: 10px !important;
}
/* 10_tables.css có rule dùng chung cho MỌI bảng Bootstrap:
   ".table { overflow: hidden; }" — ghi đè lại để không cắt mất
   box-shadow/border-radius của 2 bảng header/body mới. */
.shift-codes-header-table,
.shift-codes-body-table {
    overflow: visible !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}
/* Card chứa bảng dùng flex-column để header luôn nằm trên, phần cuộn
   chiếm phần còn lại — .p-0 (đặt trong ui_shift.py) đã bỏ padding mặc
   định của CardBody để 2 bảng con khớp sát viền card. */
.shift-codes-card .card-body {
    display: flex;
    flex-direction: column;
}
.shift-codes-leave-wrap {
    display: flex;
    flex-direction: column;
}

/* ============================================================
   Shift Sub-Header Import Buttons — đồng bộ layout UI
   (Import Shift Info / Import Staff / Import Shift)
   Trước đây 2 nút dùng color="outline-secondary" (chuỗi string,
   Dash Bootstrap không nhận diện ra nút outline chuẩn) trong khi nút
   cuối dùng color="secondary" (nền đặc) → 3 nút lệch màu/độ đậm nhau.
   Nay cả 3 đều dùng outline=True + class .shift-import-btn để coi
   như 1 nhóm nút đồng nhất: cùng màu viền, cùng hover/transition.
   ============================================================ */
.shift-import-btn {
    font-weight: 600;
    letter-spacing: 0.2px;
    border: none !important;
    color: #fff !important;
    background: linear-gradient(135deg, #475569 0%, #64748b 100%) !important;
    box-shadow: 0 2px 6px rgba(15, 23, 42, 0.35);
    transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1),
                box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1),
                filter 0.18s ease;
    /* FIX: "Import Shift Info" / "Upload/Download Schedule" have longer labels
       than "Import Shift" — without nowrap they'd wrap to 2 lines whenever the
       row gets a bit tight (narrower window, sidebar open, language switch),
       while the shorter-label buttons stayed on 1 line. That made the 4
       buttons randomly different heights ("nhảy lung tung"). Force a single
       line + a fixed height so all 4 always match, and let the row scroll
       horizontally instead of wrapping/growing taller. */
    white-space: nowrap !important;
    flex-shrink: 0 !important;
    height: 31px !important;
    display: inline-flex !important;
    align-items: center !important;
}
.shift-import-btn:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(15, 23, 42, 0.45);
    filter: brightness(1.12);
    color: #fff !important;
}
.shift-import-btn:active:not(:disabled) {
    transform: translateY(0) scale(0.97);
    box-shadow: 0 2px 6px rgba(15, 23, 42, 0.3);
    filter: brightness(0.95);
}
.shift-import-btn:focus {
    box-shadow: 0 0 0 3px rgba(100, 116, 139, 0.45) !important;
}
/* ─────────────────────────────────────────────────────────────────────────
   FIX (Yêu cầu mới #2): resize handle (.crh, injected bởi column_resize.js)
   mặc định nằm ở "right: -3px; width: 7px" — tức là nhô ra NGOÀI biên phải
   của <th> mất 3px, chỉ có 4px còn lại nằm BÊN TRONG ô. Rule ở mục 9 phía
   trên (#shift-grid-table th.dash-header { overflow: hidden !important; })
   cắt mất hẳn phần 3px nhô ra ngoài đó — phần handle còn thấy được (và còn
   bắt được hover) chỉ là 1 dải hẹp nằm LỌT VÀO TRONG ô (cách biên phải thật
   khoảng 3px), khiến người dùng hover đúng biên phải (nơi con trỏ đổi thành
   col-resize) nhưng đường line/hiệu ứng sáng lại hiện ra lệch vào phía
   trong — nhìn giống như đang ở "biên trái" của cột kế bên.
   Sửa: cho handle nằm HOÀN TOÀN BÊN TRONG <th> (right: 0, không âm) và chỉ
   cần 6px là đủ rộng để bắt hover — không còn phần nào bị overflow:hidden
   cắt mất nữa, nên đường line luôn hiện ĐÚNG ngay tại biên phải, đúng vị
   trí con trỏ chuột. Chỉ áp dụng riêng cho 2 bảng ca làm việc, không ảnh
   hưởng tới các bảng khác trong app. */
#shift-grid-table .crh,
#shift-worktime-grid-table .crh {
    right: 0 !important;
    width: 6px !important;
}

.shift-import-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none !important;
    box-shadow: none !important;
    filter: none !important;
}
/* Dark theme: gradient sáng hơn 1 chút để vẫn nổi trên nền navy tối */
[data-theme="dark"] .shift-import-btn {
    background: linear-gradient(135deg, #52627a 0%, #7688a3 100%) !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
[data-theme="dark"] .shift-import-btn:hover:not(:disabled) {
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
}

/* ─── FIX #2: Heatmap sub-tab "Thống kê" không lên màu ────────────────────
   Nguyên nhân: ".shift-codes-table td" ở 10_tables.css ép
   "background-color: transparent !important" cho MỌI ô. Python trước đây
   cố thắng rule đó bằng cách nhét thẳng "!important" vào value của
   style["backgroundColor"] — nhưng Dash/React set inline style bằng cách
   gán trực tiếp element.style.backgroundColor = "...", và trình duyệt sẽ
   ÂM THẦM BỎ QUA toàn bộ giá trị khi chuỗi đó chứa "!important" (chỉ
   style.setProperty(prop, value, "important") hoặc cssText mới hiểu được
   priority "important" — gán trực tiếp property thì không). Kết quả:
   backgroundColor không bao giờ thực sự được set, ô luôn trong suốt.

   Cách sửa: Python giờ chỉ set 2 CSS custom property (--heatmap-bg /
   --heatmap-color) qua inline style — set custom property bằng gán trực
   tiếp vẫn hoạt động bình thường (cơ chế khác property thường). Rule dưới
   đây đọc lại 2 biến đó bằng var() và mới là nơi cần "!important" (đặt
   ngay trong file CSS thì không bị giới hạn như trên) để thắng rule
   "transparent !important" ở 10_tables.css. */
.shift-codes-table td.shift-heatmap-cell {
    background-color: var(--heatmap-bg) !important;
}
.shift-codes-table td.shift-heatmap-cell-light {
    color: var(--heatmap-color, #ffffff) !important;
}

/* ─── Cảnh báo vượt giới hạn OT (40h/tháng, 200h/năm) ──────────────────────
   Ô đã vượt ngưỡng có thêm viền đỏ đậm + icon ⚠️ trong nội dung ô, KHÔNG
   chỉ dựa vào màu nền — để không bỏ sót khi in đen trắng hoặc với người
   khó phân biệt màu (xem _ot_threshold_style trong ui_shift.py). */
.shift-codes-table td.shift-ot-exceeded {
    border: 2px solid #d32f2f !important;
    font-weight: 700;
}
.shift-ot-exceeded-icon {
    font-size: 11px;
}
.shift-ot-warning-banner {
    font-size: 13px;
}

/* ─── Fix: title "Thống kê: Tháng .../..." bị trùng màu nền (không đọc
   được) — trước đây không set color nên dùng mặc định (thường là đen/xám
   đậm), trên nền tối gần như vô hình. Set rõ theo biến theme để luôn rõ
   nét ở cả light/dark mode. */
.shift-stats-period-title {
    color: var(--text-primary) !important;
}

/* (Yêu cầu mới) Giảm padding ô cho TẤT CẢ bảng dùng chung style này (Mã
   ca, Nhân viên, Thống kê) — Bootstrap's table-sm mặc định padding 0.3rem
   trên dưới (~5px), thu nhỏ lại còn 2px trên/dưới, 4px trái/phải để hàng
   thấp/gọn hơn, đỡ phải cuộn dọc nhiều. */
.shift-codes-table th,
.shift-codes-table td {
    padding: 2px 4px !important;
    overflow: hidden;   /* FIX <badge-overflow-on-column-resize>: cùng fix
        như .wo-custom-table/.asset-custom-table — badge Đang làm/Ngưng/Đã
        ẩn không còn tràn ra ngoài khi cột Trạng thái bị kéo nhỏ. */
}

/* ─────────────────────────────────────────────────────────────────────────
   FIX (#1 + #2, tooltip mã ca): tooltip mặc định của dash_table.DataTable bị
   ẩn hẳn (display:none) — đã thay bằng tooltip TỰ VẼ bằng JS
   (assets/js/shift_grid_custom_tooltip.js), gắn thẳng vào <body> với
   "position: fixed" nên KHÔNG bị container cha crop (khắc phục #1 — z-index
   thấp bị cắt bởi overflow của container) và luôn định vị đúng theo
   getBoundingClientRect() bất kể màn hình có scale/DPI cao (khắc phục #2 —
   sai vị trí trên laptop 14"). Giữ "tooltip_data" ở Python (không xoá) vì
   dash_table cần prop này tồn tại để không phá cấu trúc nội bộ, nhưng phần
   hiển thị mặc định của nó bị tắt hẳn ở đây để không hiện tooltip 2 lần
   (1 cái bị lỗi vị trí/crop của dash_table + 1 cái tự vẽ đúng vị trí).

   FIX BỔ SUNG (đã xác nhận bằng cách đọc thẳng source code đã minify của
   thư viện dash_table, file async-table.js trong gói pip "dash"): tooltip
   thật của dash_table gồm 2 <div> LỒNG NHAU, không phải 1:
     <div class="dash-tooltip" ...>        <- div NGOÀI: chính div này mới
                                               là cái được dash_table tự set
                                               position:absolute + top/left
                                               (công thức hay lệch trên màn
                                               hình scale/DPI cao) và hiển
                                               thị MŨI TÊN trỏ vào ô
       <div class="dash-table-tooltip">    <- div TRONG: chỉ chứa chữ
     </div>
   Rule cũ chỉ ẩn div TRONG (".dash-table-tooltip") — div NGOÀI
   (".dash-tooltip") vẫn còn nguyên trong DOM và vẫn được dash_table tự
   định vị/hiển thị (chỉ mỗi phần chữ bên trong bị trống vì đã ẩn) -> đây
   chính là "mũi tên vô chủ" hiển thị SAI VỊ TRÍ mà người dùng thấy, dù ô
   tooltip có chữ (tự vẽ bởi JS ở file riêng) đã hiển thị đúng chỗ. Ẩn nốt
   div NGOÀI ở đây để loại bỏ hoàn toàn phần tử gốc bị lỗi định vị. */
#shift-grid-table .dash-table-tooltip,
#shift-worktime-grid-table .dash-table-tooltip,
#shift-grid-table .dash-tooltip,
#shift-worktime-grid-table .dash-tooltip,
.dash-table-container .dash-tooltip {
    display: none !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   12. Highlight cho vùng đang được chọn bởi cơ chế range-select TỰ VIẾT
   (xem app/assets/js/shift_grid_range_select.js) — thay thế hoàn toàn cơ
   chế range-select gốc của dash_table (đã xác nhận qua debug script là
   không hoạt động ở version dash đang dùng). Dùng box-shadow inset thay vì
   background-color để KHÔNG đè mất màu mã ca gốc của ô (giống cách xử lý
   "cell--selected" ở mục 2f phía trên) — chỉ phủ 1 lớp xanh mờ + viền xanh
   lên trên màu nền sẵn có.
   ".range-sel-cell" nên có độ ưu tiên cao hơn ".focused"/"cell--selected"
   (đặt sau trong file) để luôn thấy rõ vùng đang chọn dù dash_table có gắn
   thêm class nào khác lên cùng ô. */
#shift-grid-table td.range-sel-cell {
    box-shadow: inset 0 0 0 9999px rgba(37, 99, 235, 0.28) !important;
    outline: 1.5px solid #2563eb !important;
    outline-offset: -1.5px;
}

/* ─────────────────────────────────────────────────────────────────────────
   13. FIX: khoảng trắng thừa PHÍA TRÊN dòng "Legend" (giữa hàng Chế độ/nút
   bấm và Legend) — nguyên nhân KHÔNG phải margin/padding của chính legend,
   mà là margin-bottom của "manual_send_result_row" (hàng chứa kết quả gửi
   SeaTalk thủ công, className "mb-1" — xem ui_shift.py) nằm NGAY GIỮA hàng
   Chế độ/nút bấm và Legend, dù nội dung thường RỖNG (không có gì để gửi)
   vẫn chiếm khoảng margin. Ép margin/padding của khối này về 0 khi rỗng.
   Khoảng cách PHÍA DƯỚI Legend (trước bảng lịch ca) thì NGƯỢC LẠI — cố
   tình giữ 1 khoảng nhỏ (marginBottom: 12px, set trực tiếp ở Collapse
   trong ui_shift.py) để Legend không dính sát bảng, nên KHÔNG ép về 0
   ở đây nữa. */
#shift-schedule-manual-send-result:empty {
    margin: 0 !important;
    padding: 0 !important;
    min-height: 0 !important;
}
#shift-schedule-manual-send-result:empty + div,
div:has(> #shift-schedule-manual-send-result:empty) {
    margin-bottom: 0 !important;
    padding-bottom: 0 !important;
}

#shift-grid-container,
#shift-grid-container > div {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

#shift-grid-table .dash-spreadsheet-container,
#shift-grid-table .dash-spreadsheet-inner,
#shift-grid-table .dash-spreadsheet-menu {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* (FIX — badge Legend "Ghi chú" không đều nhau dù đã set minWidth qua
   style inline trong Python) Style inline (Dash "style={...}") có thể vẫn
   bị 1 rule "!important" khác trong assets/css/* đè mất (theo cascade,
   "!important" từ 1 stylesheet NGOÀI luôn thắng style inline THƯỜNG —
   không kèm "!important" — bất kể độ ưu tiên "specificity" của inline có
   cao hơn). Ép "!important" trực tiếp ở đây (file này nạp SAU nhiều file
   CSS khác theo thứ tự tên "00_" -> "31_", nên rule "!important" đứng ở
   đây sẽ thắng bất kỳ rule "!important" nào khác đứng TRƯỚC nó) — dùng
   "width" cố định (không chỉ "min-width") + "box-sizing: border-box" để
   đảm bảo mọi badge rộng bằng nhau tuyệt đối, bất kể nội dung ngắn/dài
   khác nhau (vd "S1" so với "S19", "15h-0h" so với "20h-04h"). */
#shift-legend-box .shift-legend-badge-code {
    display: inline-block !important;
    width: 32px !important;
    box-sizing: border-box !important;
    text-align: center !important;
}
#shift-legend-box .shift-legend-badge-hours {
    display: inline-block !important;
    width: 58px !important;
    box-sizing: border-box !important;
    text-align: center !important;
}

/* (FIX — mượt hoá hiệu ứng "làm mờ theo tuần") Nếu vì bất kỳ lý do gì
   (mạng chậm, lần đầu tải cache tháng mới...) bảng vẫn có 1 khoảng trễ
   ngắn giữa lúc hiện dữ liệu và lúc áp opacity mờ cho các ngày ngoài
   tuần đang chọn, thêm transition mượt cho "opacity" để cảm giác là
   mờ dần êm ái thay vì "chớp" đột ngột như trước — không ảnh hưởng gì
   tới logic tô màu, chỉ là hiệu ứng chuyển động thuần CSS. */
#shift-grid-table td.dash-cell,
#shift-grid-table th.dash-header,
#shift-worktime-grid-table td.dash-cell,
#shift-worktime-grid-table th.dash-header {
    transition: opacity 0.25s ease-in-out;
}

/* ── 32_icon_action_buttons.css ──────────────────────── */
/* ============================================================
   32_icon_action_buttons.css — Nút icon trong các bảng danh sách
   (Work Order "Noti", Shift Schedule "Shift/Leave Codes" +
   "Employees", Work Permit "Approve"/"Actions", Documents "Actions")

   (MỚI) Trước đây các nút icon-only (Sửa/Xóa/Xem/Tải xuống/Duyệt/
   Từ chối/PDF/Ẩn/Kích hoạt...) trong các bảng này dùng kiểu Bootstrap
   "outline" (chỉ có viền màu, KHÔNG có nền) — thậm chí 1 số nút (Sửa/
   Xóa ở bảng Shift Codes/Leave Codes) còn dùng kiểu "link" (KHÔNG viền,
   KHÔNG nền, chỉ có icon màu) — nên ở trạng thái bình thường (chưa
   hover), các nút gần như "biến mất" vào nền tối của bảng, trông không
   giống nút bấm, người dùng khó nhận ra đâu là nút có thể bấm.

   Class ".icon-action-btn" (gắn kèm class màu Bootstrap có sẵn của
   dbc.Button, vd "btn-outline-secondary"/"btn-outline-primary"/
   "btn-outline-danger"/"btn-outline-success"/"btn-outline-warning") ->
   thêm NỀN MỜ cùng tông màu + viền rõ hơn NGAY CẢ KHI CHƯA HOVER, cùng
   hiệu ứng hover/active/focus rõ rệt (nền đậm hơn + nhích lên nhẹ), áp
   dụng ĐỒNG NHẤT cho mọi bảng — cùng "ngôn ngữ thị giác" với
   ".wo-icon-btn" (bảng Work Order, xem 16_misc.css) nhưng dùng chung 1
   class cho MỌI bảng thay vì phải lặp lại rule riêng từng nơi.

   Cách dùng: chỉ cần thêm className "icon-action-btn" vào dbc.Button/
   html.A (đã có sẵn class màu Bootstrap outline) là tự động có style
   này — không cần sửa gì thêm ở CSS khi thêm nút mới, miễn dùng đúng
   quy ước color=<màu> + outline=True (hoặc màu "outline-<màu>") của
   dbc.Button ở các file ui_*.py.
   ============================================================ */

.icon-action-btn,
.btn.btn-outline-secondary,
.btn.btn-outline-primary,
.btn.btn-outline-danger,
.btn.btn-outline-success,
.btn.btn-outline-warning,
.btn.btn-outline-info {
    border-width: 1.5px !important;
    font-weight: 500;
    transition: background-color .15s ease, border-color .15s ease,
                box-shadow .15s ease, transform .1s ease, filter .15s ease;
}

.icon-action-btn:active:not(:disabled),
.btn.btn-outline-secondary:active:not(:disabled),
.btn.btn-outline-primary:active:not(:disabled),
.btn.btn-outline-danger:active:not(:disabled),
.btn.btn-outline-success:active:not(:disabled),
.btn.btn-outline-warning:active:not(:disabled),
.btn.btn-outline-info:active:not(:disabled) {
    transform: translateY(1px) scale(0.96);
}

/* ============================================================
   (MỚI) Từ v22 trở đi: các rule màu nền/viền/hover bên dưới áp
   dụng CHUNG cho MỌI nút .btn-outline-* trong toàn app (kể cả
   những nút KHÔNG gắn class "icon-action-btn" — vd nhóm nút
   Tháng trước/Tháng sau, Chế độ xem, Undo/Redo, Month/Week/Day ở
   tab Ca làm việc) — không chỉ riêng những nút có gắn thêm class
   "icon-action-btn" như trước. Nút nào ĐÃ có class "icon-action-btn"
   thì vẫn nhận đúng các trị số này (không đổi hành vi cũ), chỉ
   thêm phạm vi áp dụng rộng hơn để không còn nút nào bị "trong
   suốt"/không có nền ở trạng thái mặc định.
   ============================================================ */

/* ── Secondary (Sửa PDF / Ẩn / Xem chi tiết trung tính) ── */
.icon-action-btn.btn-outline-secondary,
.btn.btn-outline-secondary {
    color: #e2e8f0 !important;
    border-color: rgba(203, 213, 225, 0.6) !important;
    background-color: rgba(203, 213, 225, 0.14) !important;
}
.icon-action-btn.btn-outline-secondary:hover:not(:disabled),
.btn.btn-outline-secondary:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(203, 213, 225, 0.95) !important;
    background-color: rgba(203, 213, 225, 0.32) !important;
    box-shadow: 0 2px 8px rgba(203, 213, 225, 0.2);
}
.icon-action-btn.btn-outline-secondary:focus,
.btn.btn-outline-secondary:focus {
    box-shadow: 0 0 0 0.2rem rgba(203, 213, 225, 0.35) !important;
}

/* ── Primary (Sửa / Gửi / Xuất PDF chính) ── */
.icon-action-btn.btn-outline-primary,
.btn.btn-outline-primary {
    color: #bfdbfe !important;
    border-color: rgba(99, 102, 241, 0.6) !important;
    background-color: rgba(99, 102, 241, 0.18) !important;
}
.icon-action-btn.btn-outline-primary:hover:not(:disabled),
.btn.btn-outline-primary:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(99, 102, 241, 0.95) !important;
    background-color: rgba(99, 102, 241, 0.36) !important;
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
}
.icon-action-btn.btn-outline-primary:focus,
.btn.btn-outline-primary:focus {
    box-shadow: 0 0 0 0.2rem rgba(99, 102, 241, 0.35) !important;
}

/* ── Danger (Xóa / Từ chối / Vô hiệu hóa) — tăng độ sáng theo
   yêu cầu vì đây là nút bị phản ánh khó nhìn nhất (Work Permit) ── */
.icon-action-btn.btn-outline-danger,
.btn.btn-outline-danger {
    color: #fecaca !important;
    border-color: rgba(239, 68, 68, 0.75) !important;
    background-color: rgba(239, 68, 68, 0.22) !important;
}
.icon-action-btn.btn-outline-danger:hover:not(:disabled),
.btn.btn-outline-danger:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(239, 68, 68, 1) !important;
    background-color: rgba(239, 68, 68, 0.42) !important;
    box-shadow: 0 2px 10px rgba(239, 68, 68, 0.35);
}
.icon-action-btn.btn-outline-danger:focus,
.btn.btn-outline-danger:focus {
    box-shadow: 0 0 0 0.2rem rgba(239, 68, 68, 0.4) !important;
}

/* ── Success (Duyệt / Kích hoạt) — tăng độ sáng cùng mức với
   Danger để cặp nút Duyệt/Từ chối ở Work Permit nổi bật đều nhau ── */
.icon-action-btn.btn-outline-success,
.btn.btn-outline-success {
    color: #bbf7d0 !important;
    border-color: rgba(34, 197, 94, 0.75) !important;
    background-color: rgba(34, 197, 94, 0.22) !important;
}
.icon-action-btn.btn-outline-success:hover:not(:disabled),
.btn.btn-outline-success:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(34, 197, 94, 1) !important;
    background-color: rgba(34, 197, 94, 0.42) !important;
    box-shadow: 0 2px 10px rgba(34, 197, 94, 0.35);
}
.icon-action-btn.btn-outline-success:focus,
.btn.btn-outline-success:focus {
    box-shadow: 0 0 0 0.2rem rgba(34, 197, 94, 0.4) !important;
}

/* ── Warning (Cảnh báo / Đóng nhanh) ── */
.icon-action-btn.btn-outline-warning,
.btn.btn-outline-warning {
    color: #fef08a !important;
    border-color: rgba(255, 193, 7, 0.65) !important;
    background-color: rgba(255, 193, 7, 0.16) !important;
}
.icon-action-btn.btn-outline-warning:hover:not(:disabled),
.btn.btn-outline-warning:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(255, 193, 7, 1) !important;
    background-color: rgba(255, 193, 7, 0.36) !important;
    box-shadow: 0 2px 8px rgba(255, 193, 7, 0.3);
}
.icon-action-btn.btn-outline-warning:focus,
.btn.btn-outline-warning:focus {
    box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.35) !important;
}

/* ── Info (Xem) ── */
.icon-action-btn.btn-outline-info,
.btn.btn-outline-info {
    color: #a5f3fc !important;
    border-color: rgba(13, 202, 240, 0.6) !important;
    background-color: rgba(13, 202, 240, 0.16) !important;
}
.icon-action-btn.btn-outline-info:hover:not(:disabled),
.btn.btn-outline-info:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(13, 202, 240, 0.95) !important;
    background-color: rgba(13, 202, 240, 0.36) !important;
    box-shadow: 0 2px 8px rgba(13, 202, 240, 0.3);
}
.icon-action-btn.btn-outline-info:focus,
.btn.btn-outline-info:focus {
    box-shadow: 0 0 0 0.2rem rgba(13, 202, 240, 0.35) !important;
}

/* ── Nút đã disabled — nhạt hẳn đi, không có hover/nền đậm, tránh
   trông giống nút CÒN bấm được (áp dụng cho tất cả màu ở trên) ── */
.icon-action-btn:disabled,
.icon-action-btn.disabled,
.btn.btn-outline-secondary:disabled,
.btn.btn-outline-primary:disabled,
.btn.btn-outline-danger:disabled,
.btn.btn-outline-success:disabled,
.btn.btn-outline-warning:disabled,
.btn.btn-outline-info:disabled,
.btn.btn-outline-secondary.disabled,
.btn.btn-outline-primary.disabled,
.btn.btn-outline-danger.disabled,
.btn.btn-outline-success.disabled,
.btn.btn-outline-warning.disabled,
.btn.btn-outline-info.disabled {
    opacity: 0.4 !important;
    background-color: rgba(148, 163, 184, 0.06) !important;
    border-color: rgba(148, 163, 184, 0.3) !important;
    box-shadow: none !important;
    transform: none !important;
}

/* ── html.A dùng chung class Bootstrap btn (nút Xem/Tải xuống ở tab
   Documents dựng bằng thẻ <a>, không phải <button>) — đảm bảo cùng
   kích thước/căn giữa icon như dbc.Button, không bị lệch dòng ── */
a.icon-action-btn {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    text-decoration: none !important;
}

/* ── (MỚI) Nút dạng "link" dùng làm nút bấm thật sự trong thanh công
   cụ (vd "Ẩn ghi chú"/"Hiện ghi chú" ở tab Ca làm việc) — thêm class
   "toolbar-link-btn" (xem ui_shift.py) để có nền/viền như nút
   outline-secondary thay vì chỉ là chữ có màu không viền, không nền
   như trước (khiến nút gần như biến mất trên nền tối). ── */
.toolbar-link-btn {
    color: #e2e8f0 !important;
    border: 1.5px solid rgba(203, 213, 225, 0.6) !important;
    background-color: rgba(203, 213, 225, 0.14) !important;
    border-radius: 0.375rem;
    padding: 0.25rem 0.6rem !important;
    text-decoration: none !important;
    transition: background-color .15s ease, border-color .15s ease,
                box-shadow .15s ease, transform .1s ease;
}
.toolbar-link-btn:hover:not(:disabled) {
    color: #fff !important;
    border-color: rgba(203, 213, 225, 0.95) !important;
    background-color: rgba(203, 213, 225, 0.32) !important;
    box-shadow: 0 2px 8px rgba(203, 213, 225, 0.2);
    text-decoration: none !important;
}
.toolbar-link-btn:active:not(:disabled) {
    transform: translateY(1px) scale(0.96);
}
.toolbar-link-btn:focus {
    box-shadow: 0 0 0 0.2rem rgba(203, 213, 225, 0.35) !important;
}

/* ── 33_incidents_table.css ──────────────────────────── */
/* ============================================================
   26_incidents_table.css — Chi tiết Sự cố — inline actions
   ============================================================ */

/* ── Scroll container ── */
.inc-detail-table-scroll {
  overflow: auto !important;
  max-height: calc(var(--app-height, 100vh) - var(--navbar-height, 98px) - var(--sticky-header-height, 60px) - 150px);
  min-height: 200px;
}

/* ── Table base ── */
.inc-detail-table {
  font-size: 0.875rem;
  border-collapse: separate !important;
  border-spacing: 0 !important;
  overflow: visible !important;
  width: 100%;
  table-layout: fixed;
}

/* ── Sticky thead ── */
.inc-detail-table-scroll .inc-detail-thead-row th {
  position: sticky !important;
  top: 0 !important;
  z-index: 10 !important;
  white-space: normal;
  word-break: break-word;
}
.inc-detail-table thead th {
  background: #4f46e5;
  color: white;
  font-weight: 600;
  padding: 10px 8px;
  border-bottom: 2px solid #3730a3;
  border-right: 1px solid rgba(255,255,255,0.18);
  white-space: normal;
  word-break: break-word;
  text-align: center;
  font-size: 13px;
  position: relative;
  overflow: visible;
}

/* ── <4> Drag-resize handle on th ── */
.col-resize-handle {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 5px;
  cursor: col-resize;
  z-index: 20;
  background: transparent;
  transition: background 0.15s;
  user-select: none;
}
.col-resize-handle:hover,
.col-resize-handle.resizing {
  background: rgba(255,255,255,0.35);
}

/* ── Filter row — sticky below header ── */
/* top được cập nhật động bởi inc_sticky_filter_top.js đo thead.offsetHeight thực tế.
   Fallback 39px chỉ dùng khi JS chưa chạy (tránh filter row chồng lên header). */
.inc-detail-filter-row td {
  background: var(--bg-secondary, #f1f5f9);
  border-bottom: 1px solid var(--border-color, #e2e8f0);
  padding: 4px 6px;
  position: sticky !important;
  top: var(--inc-filter-top, 39px) !important;
  z-index: 9 !important;
}
/* filter input styling now in .inc-filter-input below */

/* ── Body rows ── */
.inc-detail-table tbody tr {
  border-bottom: 1px solid #b0b8c9;
  transition: background 0.12s;
}
.inc-detail-table tbody tr:nth-child(odd)  td { background: var(--card-bg, #ffffff); }
.inc-detail-table tbody tr:nth-child(even) td { background: var(--bg-secondary, #f8f9fa); }
.inc-detail-table tbody tr:hover td { background: rgba(99,102,241,0.10) !important; }

.inc-detail-table td {
  padding: 7px 8px;
  vertical-align: middle;
  color: var(--text-primary, #1e293b);
  border-bottom: 1px solid #b0b8c9;
  border-right: 1px solid #d0d5de;
  overflow: visible;
  white-space: normal;
  word-break: break-word;
}
.inc-detail-table td.inc-td-desc  { white-space: normal; word-break: break-word; }
.inc-detail-table td.inc-td-actions {
  white-space: nowrap; text-align: center;
  width: 90px; min-width: 90px;
}

/* ── Action buttons ── */
.inc-act-btn {
  padding: 3px 7px !important;
  font-size: 11px !important;
  border-radius: 4px !important;
  line-height: 1.3 !important;
  margin: 0 1px;
}
.inc-act-btn:hover { opacity: 0.80; }

/* Disabled/not-owner: button visible but grayed out, non-interactive */
.inc-act-btn-dimmed,
.inc-act-btn-dimmed:hover {
  opacity: 0.35 !important;
  cursor: not-allowed !important;
  pointer-events: none !important;
  filter: grayscale(60%);
}

/* ── Pagination bar ── */
.inc-detail-pagination {
  padding: 6px 2px 8px 2px;
  border-bottom: 1px solid var(--border-color, #e2e8f0);
  background: var(--card-bg, #ffffff);
  color: var(--text-primary, #1e293b);
}
.inc-detail-pagination .text-muted { color: var(--text-muted, #6c757d) !important; }
.inc-detail-pagination .table-page-btn {
  background: var(--bg-secondary, #f8f9fa) !important;
  border-color: var(--border-color, #dee2e6) !important;
  color: var(--text-primary, #495057) !important;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, opacity 0.15s, transform 0.1s;
  user-select: none;
}
.inc-detail-pagination .table-page-btn:not(:disabled):hover {
  background: rgba(99,102,241,0.12) !important;
  border-color: #6366f1 !important;
  color: #4f46e5 !important;
}
.inc-detail-pagination .table-page-btn:not(:disabled):active {
  background: rgba(99,102,241,0.22) !important;
  border-color: #4338ca !important;
  color: #3730a3 !important;
  transform: scale(0.93);
}
.inc-detail-pagination .table-page-btn:focus-visible {
  outline: 2px solid #6366f1;
  outline-offset: 2px;
}
.inc-detail-pagination .table-page-btn:disabled {
  opacity: 0.35 !important;
  cursor: not-allowed !important;
  pointer-events: none !important;
}
.inc-detail-pagination .table-page-input {
  background: var(--card-bg, #ffffff) !important;
  color: var(--text-primary, #1e293b) !important;
  border-color: var(--border-color, #dee2e6) !important;
}
.inc-detail-pagination .table-page-input:focus {
  border-color: #6366f1 !important;
  box-shadow: 0 0 0 2px rgba(99,102,241,0.15) !important;
  outline: none !important;
}

/* ── Button "Thêm sự cố" ── */
/* padding-right: 14px matches .sticky-header padding-right so right edges align */
.inc-add-btn {
    flex-shrink: 0 !important;
    white-space: nowrap !important;
    min-width: max-content !important;
    margin-right: 0 !important;
}
/* The sub-header-wrapper itself needs right padding to match sticky-header (14px) */
.sub-header-wrapper.d-flex {
    padding-right: 14px !important;
}

/* ── Per-column filter cell (input + Aa button) ── */
.inc-filter-cell-inner {
    display: flex;
    align-items: center;
    gap: 3px;
}
.inc-filter-input {
    flex: 1;
    min-width: 0;
    font-size: 11px;
    padding: 2px 5px;
    height: 24px;
    border: 1px solid var(--border-color, #b0b8c9);
    border-radius: 3px;
    background: var(--card-bg, white);
    color: var(--text-primary, #1e293b);
    box-sizing: border-box;
    outline: none;
}
.inc-filter-input::placeholder { color: #94a3b8; }
.inc-filter-input:focus { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,0.15); }
/* Aa toggle button */
.inc-filter-aa-btn {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid var(--border-color, #b0b8c9);
    border-radius: 3px;
    color: var(--text-muted, #6c757d);
    font-size: 9px;
    font-weight: 700;
    padding: 1px 3px;
    height: 20px;
    line-height: 1.2;
    cursor: pointer;
    transition: background 0.13s, color 0.13s, border-color 0.13s;
    white-space: nowrap;
    user-select: none;
}
.inc-filter-aa-btn:hover {
    background: rgba(99,102,241,0.10);
    color: #4f46e5;
    border-color: #4f46e5;
}
.inc-filter-aa-btn.active {
    background: #4f46e5;
    color: #fff;
    border-color: #3730a3;
}
/* Dark mode filter inputs */
body.dark-mode .inc-filter-input,
[data-theme="dark"] .inc-filter-input {
    background: var(--card-bg, #0f172a);
    color: var(--text-primary, #e2e8f0);
    border-color: rgba(255,255,255,0.20);
}
body.dark-mode .inc-filter-input::placeholder,
[data-theme="dark"] .inc-filter-input::placeholder { color: #64748b; }
body.dark-mode .inc-filter-input:focus,
[data-theme="dark"] .inc-filter-input:focus { border-color: #6366f1; }
body.dark-mode .inc-filter-aa-btn,
[data-theme="dark"] .inc-filter-aa-btn {
    border-color: rgba(255,255,255,0.20);
    color: #94a3b8;
}
body.dark-mode .inc-filter-aa-btn.active,
[data-theme="dark"] .inc-filter-aa-btn.active {
    background: #4f46e5;
    color: #fff;
}

/* ── Modal lock banner ── */
.inc-modal-lock-banner {
  align-items: center;
  gap: 8px;
  background: #fef3c7;
  border: 1px solid #f59e0b;
  border-radius: 6px;
  padding: 5px 12px;
  font-size: 13px;
  color: #92400e;
  font-weight: 500;
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ════════════════════════════════════════
   DARK MODE
   ════════════════════════════════════════ */
body.dark-mode .inc-detail-table thead th,
[data-theme="dark"] .inc-detail-table thead th {
  background: #3730a3;
  border-bottom-color: #4f46e5;
}

body.dark-mode .inc-detail-table tbody tr:nth-child(odd)  td,
[data-theme="dark"] .inc-detail-table tbody tr:nth-child(odd)  td {
  background: var(--card-bg, #1e293b);
  color: var(--text-primary, #e2e8f0);
  border-bottom-color: rgba(255,255,255,0.15);
  border-right-color: rgba(255,255,255,0.10);
}
body.dark-mode .inc-detail-table tbody tr:nth-child(even) td,
[data-theme="dark"] .inc-detail-table tbody tr:nth-child(even) td {
  background: var(--bg-secondary, #162032);
  color: var(--text-primary, #e2e8f0);
  border-bottom-color: rgba(255,255,255,0.15);
  border-right-color: rgba(255,255,255,0.10);
}
body.dark-mode .inc-detail-table tbody tr:hover td,
[data-theme="dark"] .inc-detail-table tbody tr:hover td {
  background: rgba(99,102,241,0.20) !important;
}

body.dark-mode .inc-detail-filter-row td,
[data-theme="dark"] .inc-detail-filter-row td {
  background: var(--bg-secondary, #1e293b);
  border-bottom-color: rgba(255,255,255,0.10);
}
/* dark mode filter inputs handled by .inc-filter-input rules above */

body.dark-mode .inc-detail-pagination,
[data-theme="dark"] .inc-detail-pagination {
  background: var(--card-bg, #1e293b) !important;
  border-bottom-color: rgba(255,255,255,0.10);
}
body.dark-mode .inc-detail-pagination .text-muted,
[data-theme="dark"] .inc-detail-pagination .text-muted { color: #94a3b8 !important; }
body.dark-mode .inc-detail-pagination .table-page-btn,
[data-theme="dark"] .inc-detail-pagination .table-page-btn {
  background: var(--bg-secondary, #2d3748) !important;
  border-color: rgba(255,255,255,0.15) !important;
  color: #e2e8f0 !important;
}
body.dark-mode .inc-detail-pagination .table-page-btn:not(:disabled):hover,
[data-theme="dark"] .inc-detail-pagination .table-page-btn:not(:disabled):hover {
  background: rgba(99,102,241,0.20) !important;
  border-color: #6366f1 !important;
  color: #a5b4fc !important;
}
body.dark-mode .inc-detail-pagination .table-page-btn:not(:disabled):active,
[data-theme="dark"] .inc-detail-pagination .table-page-btn:not(:disabled):active {
  background: rgba(99,102,241,0.35) !important;
  border-color: #818cf8 !important;
  color: #c7d2fe !important;
  transform: scale(0.93);
}
body.dark-mode .inc-detail-pagination .table-page-btn:disabled,
[data-theme="dark"] .inc-detail-pagination .table-page-btn:disabled {
  opacity: 0.25 !important;
  cursor: not-allowed !important;
  pointer-events: none !important;
}
body.dark-mode .inc-detail-pagination .table-page-input,
[data-theme="dark"] .inc-detail-pagination .table-page-input {
  background: var(--bg-secondary, #2d3748) !important;
  color: #e2e8f0 !important;
  border-color: rgba(255,255,255,0.15) !important;
}
body.dark-mode .inc-detail-pagination .table-page-input:focus,
[data-theme="dark"] .inc-detail-pagination .table-page-input:focus {
  border-color: #6366f1 !important;
  box-shadow: 0 0 0 2px rgba(99,102,241,0.25) !important;
  outline: none !important;
}

body.dark-mode .inc-modal-lock-banner,
[data-theme="dark"] .inc-modal-lock-banner {
  background: rgba(245,158,11,0.12);
  color: #fbbf24;
  border-color: rgba(245,158,11,0.40);
}

/* ── Sort header styles ─────────────────────────────────────────────────── */
.inc-th-sortable { cursor: pointer; }
.inc-th-sortable:hover { background: rgba(99,102,241,0.08); }
.inc-sortable-header { display: inline-flex; align-items: center; gap: 2px; }
.inc-sort-icon { font-size: 10px; transition: opacity 0.15s; flex-shrink: 0; }

/* ── Override Bootstrap .btn-light default hover so our custom states take effect ── */
.inc-detail-pagination .btn.table-page-btn:not(:disabled):hover,
.inc-detail-pagination .btn-light.table-page-btn:not(:disabled):hover {
  background-color: rgba(99,102,241,0.12) !important;
  border-color: #6366f1 !important;
  color: #4f46e5 !important;
}
.inc-detail-pagination .btn.table-page-btn:not(:disabled):active,
.inc-detail-pagination .btn-light.table-page-btn:not(:disabled):active,
.inc-detail-pagination .btn.table-page-btn:not(:disabled).active {
  background-color: rgba(99,102,241,0.22) !important;
  border-color: #4338ca !important;
  color: #3730a3 !important;
  transform: scale(0.93);
}
body.dark-mode .inc-detail-pagination .btn.table-page-btn:not(:disabled):hover,
body.dark-mode .inc-detail-pagination .btn-light.table-page-btn:not(:disabled):hover,
[data-theme="dark"] .inc-detail-pagination .btn.table-page-btn:not(:disabled):hover,
[data-theme="dark"] .inc-detail-pagination .btn-light.table-page-btn:not(:disabled):hover {
  background-color: rgba(99,102,241,0.20) !important;
  border-color: #6366f1 !important;
  color: #a5b4fc !important;
}
body.dark-mode .inc-detail-pagination .btn.table-page-btn:not(:disabled):active,
body.dark-mode .inc-detail-pagination .btn-light.table-page-btn:not(:disabled):active,
[data-theme="dark"] .inc-detail-pagination .btn.table-page-btn:not(:disabled):active,
[data-theme="dark"] .inc-detail-pagination .btn-light.table-page-btn:not(:disabled):active {
  background-color: rgba(99,102,241,0.35) !important;
  border-color: #818cf8 !important;
  color: #c7d2fe !important;
  transform: scale(0.93);
}

/* ── Drilldown modal html.Table styling ──────────────────────────────────── */
.drilldown-html-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: auto;
    font-size: 12px;
    font-family: Inter, system-ui, sans-serif;
}
.drilldown-html-table tbody tr:nth-child(odd) {
    background-color: rgba(128, 128, 128, 0.04);
}
.drilldown-html-table tbody tr:hover {
    background-color: rgba(79, 70, 229, 0.12) !important;
    transition: background-color 0.15s ease;
}
.drilldown-html-table td,
.drilldown-html-table th {
    border-bottom: 1px solid var(--border-color, #2d3748);
}
.drilldown-html-table img {
    max-width: 52px;
    max-height: 52px;
    object-fit: contain;
    border-radius: 4px;
    cursor: pointer;
}

/* ── 34_shift_cell_flash.css ─────────────────────────── */
/* (Yêu cầu mới) Nhấp nháy cảnh báo ngay trên ô vừa bị server từ chối/revert
   trong bảng "Ca làm việc" (mã ca không hợp lệ HOẶC không đủ khoảng nghỉ
   >=12h với ca hôm trước) — xem clientside_callback flash ở cb_shift.py
   (Input "shift-grid-reject-cells-store"). Giúp người dùng biết CHÍNH XÁC
   ô nào vừa bị từ chối, không chỉ đọc toast chung chung. */
@keyframes sgCellRejectFlash {
  0%   { background-color: #fecaca; box-shadow: inset 0 0 0 2px #dc2626; }
  50%  { background-color: #fff1f2; box-shadow: inset 0 0 0 2px #dc2626; }
  100% { background-color: transparent; box-shadow: none; }
}

.sg-cell-reject-flash {
  animation: sgCellRejectFlash 1.6s ease-in-out 2;
}

