﻿body {
    background-color: #f4f6f9;
}

/* ===== Trang đăng nhập ===== */
.login-body {
    background: linear-gradient(135deg, #0d6efd 0%, #0a3d91 100%);
    min-height: 100vh;
}

.login-wrapper {
    min-height: 100vh;
}

.login-card {
    width: 100%;
    max-width: 420px;
    border-radius: 1rem;
}

/* ===== Thẻ thống kê Dashboard ===== */
.stat-card {
    border-radius: 1rem;
}

.stat-card-link {
    transition: transform .15s ease, box-shadow .15s ease;
    cursor: pointer;
}

.stat-card-link:hover {
    transform: translateY(-3px);
    box-shadow: 0 .5rem 1rem rgba(0,0,0,.12) !important;
}

.stat-icon {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    margin-bottom: .5rem;
}

.stat-value {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.2;
}

.stat-label {
    color: #6c757d;
    font-size: .8rem;
}

/* =========================================================================
   Trang vừa đúng một màn hình
   -------------------------------------------------------------------------
   Trang bản đồ không được có thanh cuộn dọc. Cách làm: biến thân trang thành
   một cột co giãn cao đúng bằng màn hình, rồi để một phần tử duy nhất
   (.md-co-gian) nuốt hết chỗ còn thừa.

   Vì sao không đặt chiều cao bản đồ bằng vh: thanh điều hướng, thanh công cụ
   và hai hàng chú giải cao bao nhiêu là do cỡ chữ và bề rộng cửa sổ quyết định,
   không phải hằng số. Mọi con số vh đoán trước đều sai ở một cỡ màn hình nào đó
   — hoặc thừa ra thanh cuộn, hoặc chừa một dải trống dưới đáy.

   dvh (dynamic viewport height) là để trên điện thoại: thanh địa chỉ của trình
   duyệt trượt ra/vào làm 100vh lớn hơn phần thực sự nhìn thấy.
   ========================================================================= */
body.trang-mot-man-hinh {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* min-height:0 là bắt buộc. Mặc định một flex item không co nhỏ hơn nội dung của nó,
   nên thiếu dòng này thì bản đồ vẫn đẩy trang dài ra đúng như cũ. */
body.trang-mot-man-hinh > main {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Chân trang chỉ có dòng bản quyền, không đáng đổi lấy một thanh cuộn. */
body.trang-mot-man-hinh > footer {
    display: none;
}

/* Mọi khối trong <main> giữ nguyên chiều cao tự nhiên của nó... */
body.trang-mot-man-hinh > main > * {
    flex: 0 0 auto;
}

/* ...trừ đúng một khối được đánh dấu .md-co-gian: nó nuốt hết chỗ còn thừa,
   và cũng là khối duy nhất chịu co lại khi khung chi tiết mở ra. */
body.trang-mot-man-hinh .md-co-gian {
    flex: 1 1 auto;
    min-height: 180px;   /* cửa sổ quá thấp thì thà cắt bớt chú giải còn hơn để bản đồ biến mất */
    display: flex;
}

/* ===== Bản đồ ===== */
.map-container {
    flex: 1 1 auto;
    height: 100%;
    width: 100%;
    border-radius: .5rem;
    overflow: hidden;
}

.legend-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

/* ===== Nhãn tên tủ hiện thường trực trên bản đồ (map.js: bindTooltip) ===== */
.leaflet-tooltip.nhan-tu {
    background: rgba(255, 255, 255, .92);
    border: 1px solid rgba(0, 0, 0, .18);
    border-radius: 4px;
    padding: 1px 5px;
    font-size: .7rem;
    font-weight: 600;
    color: #1f2933;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    white-space: nowrap;
    pointer-events: none;   /* bấm xuyên qua nhãn để vẫn chọn được marker bên dưới */
}
/* Bỏ mũi nhọn mặc định của tooltip Leaflet cho nhãn gọn. */
.leaflet-tooltip.nhan-tu::before {
    display: none;
}
/* Thu nhỏ xa -> ẩn nhãn (map.js gắn lớp này lên khung bản đồ theo mức phóng). */
.an-nhan-tu .leaflet-tooltip.nhan-tu {
    display: none;
}

/* Mẫu đường cáp trong chú giải: nét liền (cáp treo) / nét đứt (cáp ngầm). */
.legend-line {
    display: inline-block;
    width: 22px;
    height: 0;
    border-top: 3px solid #e67e22;   /* cùng màu đường cáp trên bản đồ */
    vertical-align: middle;
}
.legend-line-dash {
    border-top-style: dashed;
}

/* ===== Thanh nhắc "Cài app ra màn hình chính" (pwa-install.js) ===== */
.pwa-nhac {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: 12px;
    z-index: 2000;
    display: none;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 12px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
    transform: translateY(120%);
    transition: transform .25s ease;
}
.pwa-nhac.hien {
    display: flex;
    transform: translateY(0);
}
.pwa-nhac-icon {
    width: 40px;
    height: 40px;
    border-radius: 9px;
    flex: 0 0 auto;
}
.pwa-nhac-chu {
    flex: 1 1 auto;
    min-width: 0;
}
.pwa-nhac-tieude {
    font-weight: 600;
    font-size: .92rem;
}
.pwa-nhac-phu {
    font-size: .78rem;
    color: #6c757d;
}
.pwa-nhac-nut {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
}
@media (min-width: 768px) {
    .pwa-nhac {
        left: auto;
        right: 16px;
        bottom: 16px;
        max-width: 440px;
    }
}
@media print {
    .pwa-nhac { display: none !important; }
}

/* Biểu tượng bóng đèn (chỉ dùng ở chế độ "Chỉnh vị trí"). Bình thường đèn vẽ thành chấm
   tròn nhỏ trên canvas — xem nodeChamStyle() trong map.js. */
.marker-offline i,
.marker-on100 i,
.marker-dimmed i,
.marker-fault i,
.marker-off i {
    font-size: 1.05rem;
    text-shadow: 0 0 3px #fff, 0 0 3px #fff;
}

/* Mất kết nối - xám */
.marker-offline i {
    color: #6c757d;
}

/* Bật 100% - xanh dương */
.marker-on100 i {
    color: #0d6efd;
}

/* Đang tiết giảm năng lượng - xanh dương nhạt hơn */
.marker-dimmed i {
    color: #74b9ff;
}

/* Có kết nối, đang bật nhưng mất dòng (đèn không sáng) - vàng */
.marker-fault i {
    color: #f1c40f;
}

/* Có kết nối nhưng đã tắt (Cắt) - bình thường, màu tối để phân biệt với "mất kết nối" */
.marker-off i {
    color: #2c3e50;
}

/* Điểm Tủ điều khiển trên bản đồ - SVG tủ điện vẽ tay.
   Màu thân tủ do JavaScript quyết định theo trạng thái đóng/cắt (xem map.js). */
.marker-cabinet svg {
    filter: drop-shadow(0 2px 2px rgba(0,0,0,.25));
}

/* Tủ vừa nhận lệnh nhưng thiết bị CHƯA báo trạng thái mới về.
   Marker đã đổi sang màu của lệnh vừa gửi, nhấp nháy để nói rõ: đây là điều mong đợi,
   chưa phải điều đã xác nhận. Hết nhấp nháy khi thiết bị báo về đúng chế độ đó. */
.marker-cabinet-pending svg {
    animation: cho-xac-nhan 1s ease-in-out infinite;
}

@keyframes cho-xac-nhan {
    0%, 100% { filter: drop-shadow(0 2px 2px rgba(0,0,0,.25)); opacity: 1; }
    50%      { filter: drop-shadow(0 0 6px #f1c40f); opacity: .65; }
}


/* Người dùng bật "giảm chuyển động" trong hệ điều hành thì không nhấp nháy nữa. */
@media (prefers-reduced-motion: reduce) {
    .marker-cabinet-pending svg {
        animation: none;
        filter: drop-shadow(0 0 5px #f1c40f);
    }
}

/* ===== Menu chuột phải dùng chung (Tủ / Đèn) ===== */
.scada-context-menu {
    position: fixed;
    /* Thấp hơn z-index của modal Bootstrap (1050-1055) để hộp thoại xác nhận / chi tiết
       luôn hiện TRÊN menu chuột phải, không bị menu che mất hoặc hiện ra phía sau. */
    z-index: 1040;
    background: #fff;
    border-radius: .5rem;
    box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.25);
    min-width: 220px;
    padding: .35rem 0;
    max-height: 70vh;
    overflow-y: auto;
}

.scada-context-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    padding: .5rem .9rem;
    font-size: .9rem;
    color: #212529;
    cursor: pointer;
}

.scada-context-menu-item:hover:not(.disabled) {
    background-color: #f0f4ff;
}

.scada-context-menu-item.disabled {
    color: #adb5bd;
    cursor: default;
}

.scada-context-menu-sep {
    height: 1px;
    background: #e9ecef;
    margin: .3rem 0;
}

.cabinet-node-list {
    max-height: 220px;
    overflow-y: auto;
}

.cabinet-node-row {
    border-radius: .35rem;
    cursor: context-menu;
}

.cabinet-node-row:hover {
    background-color: #f8f9fa;
}

/* ===== Toast thông báo góc màn hình ===== */
.scada-toast {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 3000;
    min-width: 240px;
    max-width: 360px;
    padding: .75rem 1rem;
    border-radius: .5rem;
    color: #fff;
    font-size: .9rem;
    box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.25);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity .2s ease, transform .2s ease;
    pointer-events: none;
}

.scada-toast.show {
    opacity: 1;
    transform: translateY(0);
}

.scada-toast-success { background-color: #198754; }
.scada-toast-error { background-color: #dc3545; }

/* ===== Modal Chi tiết Tủ (4 khối theo đặc tả) ===== */
.cabinet-card-header {
    cursor: pointer;
}

.cabinet-section-title {
    font-weight: 700;
    border-bottom: 2px solid #e9ecef;
    padding-bottom: .35rem;
    margin-top: 1.25rem;
    margin-bottom: .75rem;
    color: #0d6efd;
}

.cabinet-section-title:first-of-type {
    margin-top: 0;
}

.cabinet-info-box {
    background: #f8f9fa;
    border-radius: .5rem;
    padding: .5rem .75rem;
    height: 100%;
}

.cabinet-info-box .label {
    font-size: .75rem;
    color: #6c757d;
}

.cabinet-info-box .value {
    font-weight: 600;
}

/* ===== Khối "Lịch biểu hiện tại" trong hộp thoại đặt lịch =====
   Mỗi mốc là một viên: giờ in đậm, mũi tên, rồi việc sẽ xảy ra. Xếp ngang và tự xuống dòng,
   nên 5 mốc của tủ hay 9 mốc của đèn đều gọn trong vài dòng, không đẩy bảng nhập xuống dưới. */
.lich-khung {
    background: #f2f7fd;
    border: 1px solid rgba(42,120,214,.20);
    border-radius: .5rem;
    padding: .6rem .75rem;
}

.lich-tieu-de {
    font-size: .8rem;
    font-weight: 600;
    color: #1c5cab;
    margin-bottom: .5rem;
}

.lich-danh-sach {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

.lich-moc {
    display: inline-flex;
    align-items: center;
    background: #fff;
    border: 1px solid rgba(11,11,11,.10);
    border-radius: 999px;
    padding: .18rem .6rem;
    font-size: .82rem;
    white-space: nowrap;
}

.lich-gio {
    font-weight: 700;
    color: #0b0b0b;
    /* Chữ số đều bề ngang thì cột giờ thẳng hàng dù là 1 hay 11. */
    font-variant-numeric: tabular-nums;
}

.lich-mo-ta { color: #52514e; }

.lich-chu-thich {
    font-size: .72rem;
    color: #6c757d;
    margin-top: .5rem;
}

/* =====================================================================
   BẢNG (dùng chung mọi trang): kẻ vạch dọc phân tách từng ô + căn giữa.

   Ô nào cần căn khác thì dùng lớp tiện ích của Bootstrap (.text-start /
   .text-end / .text-center) — các lớp đó có !important nên luôn thắng
   quy tắc ở đây (ví dụ cột nút thao tác đang dùng .text-end vẫn dạt phải).
   ===================================================================== */
.table > :not(caption) > * > th,
.table > :not(caption) > * > td {
    border-right: 1px solid #dee2e6;
    text-align: center;
    vertical-align: middle;
}
.table > :not(caption) > * > th:last-child,
.table > :not(caption) > * > td:last-child {
    border-right: 0;   /* mép phải bảng đã có viền, không kẻ thêm cho thừa */
}

/* Liên kết trong bảng: bỏ gạch chân cho bảng đỡ rối; vẫn giữ màu xanh để biết bấm được,
   và chỉ gạch chân khi rê chuột vào. */
.table a {
    text-decoration: none;
}
.table a:hover {
    text-decoration: underline;
}

@media print {
    /* In ra giấy: vạch dọc đậm hơn cho rõ. */
    .table > :not(caption) > * > th,
    .table > :not(caption) > * > td {
        border-right: 1px solid #999 !important;
    }
    .table > :not(caption) > * > th:last-child,
    .table > :not(caption) > * > td:last-child {
        border-right: 0 !important;
    }
}

/* ===== Mũi tên sắp xếp cột (table-sort.js) ===== */
.js-sort thead th .th-arrow {
    font-size: .75rem;
    color: #adb5bd;
    user-select: none;
}
.js-sort thead th[data-dir] .th-arrow {
    color: #0d6efd;   /* cột đang sắp: mũi tên đậm màu */
}
.js-sort thead th:hover {
    background-color: #eef2ff;
}

/* ===== Modal xác nhận gửi lệnh ===== */
.result-box {
    min-height: 1.2em;
}

/* ===== Phân tầng z-index cho các hộp thoại lồng nhau =====
   cabinetDetailModal (mặc định Bootstrap ~1055) là tầng gốc.
   nodeListModal mở TỪ TRONG cabinetDetailModal -> phải hiện TRÊN.
   confirmSendModal mở TỪ TRONG cả 2 cái trên (tầng xác nhận cuối) -> phải hiện TRÊN CÙNG.
   Bootstrap gán z-index giống nhau cho mọi modal theo mặc định nên cần ép riêng như dưới đây,
   không phụ thuộc modal nào được thêm vào HTML trước/sau. */
#nodeListModal {
    z-index: 1075;
}

#nodeScheduleModal, #nodesScheduleBulkModal {
    z-index: 1080;
}

#quickAddModal, #quickAddGroupModal {
    z-index: 1085;
}

#confirmSendModal {
    z-index: 1095;
}

/* Lớp phủ mờ (backdrop) của các modal mở sau cũng phải ăn theo, không thì vẫn bị modal gốc che dấu.
   Thứ tự lồng nhau tối đa: cabinetDetailModal(1055) -> nodeListModal(1075) ->
   nodeScheduleModal(1080) -> confirmSendModal(1095) */
.modal-backdrop ~ .modal-backdrop {
    z-index: 1070;
}

.modal-backdrop ~ .modal-backdrop ~ .modal-backdrop {
    z-index: 1078;
}

.modal-backdrop ~ .modal-backdrop ~ .modal-backdrop ~ .modal-backdrop {
    z-index: 1090;
}

/* =========================================================================
   Khung chi tiết dưới bản đồ
   -------------------------------------------------------------------------
   Mắt đọc từ trái sang phải theo đúng thứ tự người dùng cần:
   "cái gì" (định danh) -> "đang thế nào" (số liệu) -> "làm gì" (điều khiển).
   Không lồng bảng trong bảng. Số liệu quan trọng hiện dạng thẻ, đọc được từ xa
   khi đang giới thiệu cho khách.
   ========================================================================= */
.md-panel {
    position: relative;
    margin-top: .5rem;
    background: #fff;
    border: 1px solid rgba(11,11,11,.08);
    border-radius: .75rem;
    box-shadow: 0 2px 10px rgba(11,11,11,.06);
    overflow: hidden;
}

/* Vạch màu trạng thái ở mép trái, JS đổi background theo tủ. */
.md-stripe {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: #c3c2b7;
}

/* ---------- Đầu khung ---------- */
.md-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .35rem .6rem .35rem .8rem;
    border-bottom: 1px solid rgba(11,11,11,.07);
    background: #fbfbfa;
}

.md-head-left { display: flex; align-items: center; gap: .6rem; min-width: 0; }

.md-avatar {
    flex: 0 0 auto;
    width: 24px; height: 24px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: #eef1f4;
    color: #52514e;
    font-size: .72rem;
}

.md-titles { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }

.md-name {
    font-weight: 650;
    font-size: .86rem;
    color: #0b0b0b;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.md-sub {
    font-size: .72rem;
    color: #898781;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Nhãn trạng thái: viền + chữ cùng màu, KHÔNG tô nền đặc. Nền đặc ở cỡ chữ này
   khiến chữ trắng trên xanh nhạt gần như không đọc được. */
.md-state {
    flex: 0 0 auto;
    font-size: .72rem;
    font-weight: 600;
    padding: .12rem .5rem;
    border-radius: 999px;
    border: 1px solid currentColor;
    white-space: nowrap;
}

.md-head-right { display: flex; gap: .25rem; flex: 0 0 auto; }

.md-icon-btn {
    width: 24px; height: 24px;
    display: grid; place-items: center;
    border: 1px solid rgba(11,11,11,.12);
    border-radius: .4rem;
    background: #fff;
    color: #52514e;
    font-size: .75rem;
    cursor: pointer;
}
.md-icon-btn:hover { background: #f2f2f0; }

/* ---------- Thân khung: 3 cột ---------- */
.md-body {
    display: grid;
    grid-template-columns: minmax(200px, 1fr) minmax(230px, 1.05fr) minmax(240px, 1.05fr);

    /* Khung chi tiết nằm DƯỚI bản đồ và đẩy bản đồ co lại -> mỗi centimet của khung là một
       centimet bản đồ bị mất. Nhưng nếu chặn theo tỉ lệ màn hình (32vh như trước) thì màn hình
       thấp lại bị cuộn trong khung, còn màn hình cao thì khung phình ra vô ích.
       Chặn theo KHOẢNG: không bao giờ thấp hơn 170px (đủ chứa hết nội dung, khỏi cuộn) và
       không bao giờ cao quá 210px (khỏi ăn hết bản đồ). */
    max-height: clamp(170px, 22vh, 210px);
    overflow-y: auto;
}

.md-col { padding: .45rem .6rem; min-width: 0; }
.md-col + .md-col { border-left: 1px solid rgba(11,11,11,.07); }
.md-col-info { padding-left: .8rem; }

@media (max-width: 1199.98px) {
    .md-body { grid-template-columns: 1fr 1fr; }
    .md-col-actions { grid-column: 1 / -1; border-left: 0; border-top: 1px solid rgba(11,11,11,.07); }
}
@media (max-width: 767.98px) {
    .md-body { grid-template-columns: 1fr; }
    .md-col + .md-col { border-left: 0; border-top: 1px solid rgba(11,11,11,.07); }
}

.md-section {
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #898781;
    margin-bottom: .25rem;
}
.md-block + .md-block { margin-top: .5rem; }

/* ---------- Cột 1: danh sách nhãn / giá trị ---------- */
.md-list { display: flex; flex-direction: column; }

.md-row {
    display: flex;
    justify-content: space-between;
    gap: .75rem;
    padding: .12rem 0;
    font-size: .74rem;
    border-bottom: 1px solid rgba(11,11,11,.05);
}
.md-row:last-child { border-bottom: 0; }

.md-key { color: #898781; white-space: nowrap; }
.md-val {
    font-weight: 600; color: #0b0b0b; text-align: right;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- Cột 2: thẻ số liệu ---------- */
.md-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: .3rem; }
.md-tiles-2 { grid-template-columns: repeat(2, 1fr); }

.md-tile {
    background: #f7f8f9;
    border: 1px solid rgba(11,11,11,.06);
    border-radius: .45rem;
    padding: .25rem .3rem;
    text-align: center;
    min-width: 0;
}
.md-tile-name  { font-size: .6rem; color: #898781; text-transform: uppercase; letter-spacing: .03em; }
.md-tile-big   { font-size: .9rem; font-weight: 650; color: #0b0b0b; line-height: 1.25; }
/* Dòng dưới (dòng điện) đọc ngang hàng với dòng trên (điện áp): cùng cỡ chữ, cùng độ đậm.
   Cả hai đều là số đo người vận hành cần, không cái nào là chú thích của cái nào. */
.md-tile-small { font-size: .9rem; font-weight: 650; color: #0b0b0b; line-height: 1.25; }
.md-tile-unit  { font-size: .68rem; color: #898781; font-weight: 400; }

/* Thẻ mức tiết giảm của đèn: cùng cỡ mọi thẻ khác, chỉ tô xanh cho nổi. */
.md-tile-dim {
    background: #eaf2fd;
    border-color: rgba(42,120,214,.28);
}
.md-tile-dim .md-tile-big { color: #1c5cab; }

/* Con số quan trọng gói trong MỘT DÒNG (trước là khối lớn + thanh tiến trình, cao ~70px). */
.md-strong {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-top: .3rem;
    padding: .25rem .4rem;
    background: #eaf2fd;
    border: 1px solid rgba(42,120,214,.22);
    border-radius: .45rem;
}
.md-strong-name  { font-size: .66rem; color: #52514e; }
.md-strong-value { font-size: .9rem; font-weight: 650; color: #1c5cab; white-space: nowrap; }

.md-seg { display: grid; grid-template-columns: repeat(4, 1fr); gap: .25rem; }
.md-seg .md-act {
    font-size: .72rem;
    padding: .28rem .2rem;
    border-radius: .4rem;
    border: 1px solid rgba(11,11,11,.14);
    background: #fff;
    color: #0b0b0b;
    cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.md-seg .md-act:hover { background: #f2f2f0; }

/* Chế độ tủ đang chạy: tô nền màu tương ứng để biết ngay đang ở đâu. */
.md-seg .md-act.dang-chay { color: #fff; border-color: transparent; font-weight: 600; }

.md-btns { display: flex; flex-wrap: wrap; gap: .25rem; }
.md-btns .md-act {
    font-size: .72rem;
    padding: .25rem .5rem;
    border-radius: .4rem;
    border: 1px solid rgba(11,11,11,.14);
    background: #fff;
    color: #0b0b0b;
    cursor: pointer;
}
.md-btns .md-act:hover { background: #f2f2f0; }
.md-act[disabled] { opacity: .55; cursor: default; }

/* Nút "Chỉ đường" là thẻ <a> (mở Google Maps) nhưng phải trông y hệt các nút tác vụ khác. */
.md-btns a.md-act {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

.md-inline { display: flex; gap: .3rem; align-items: center; }
.md-inline select,
.md-rename input {
    font-size: .78rem; padding: .2rem .45rem;
    border: 1px solid rgba(11,11,11,.14); border-radius: .4rem;
    background: #fff; color: #0b0b0b;
}
.md-rename { display: flex; gap: .3rem; }
.md-rename input { flex: 1 1 auto; min-width: 0; }

.md-foot { font-size: .72rem; }
.md-foot:not(:empty) { padding: .4rem .85rem .5rem 1.1rem; }

/* ---------- Chế độ tối ---------- */
@media (prefers-color-scheme: dark) {
    .md-panel { background: #1a1a19; border-color: rgba(255,255,255,.1); }
    .md-head  { background: #202020; border-bottom-color: rgba(255,255,255,.08); }
    .md-name, .md-val, .md-tile-big, .md-tile-small { color: #fff; }
    .md-avatar { background: #2c2c2a; color: #c3c2b7; }
    .md-col + .md-col { border-left-color: rgba(255,255,255,.08); }
    .md-row { border-bottom-color: rgba(255,255,255,.06); }
    .md-tile { background: #202020; border-color: rgba(255,255,255,.07); }
    .md-icon-btn, .md-seg .md-act, .md-btns .md-act, .md-rename input, .md-inline select {
        background: #202020; color: #e8e8e6; border-color: rgba(255,255,255,.14);
    }
    .md-strong    { background: #14273c; border-color: rgba(57,135,229,.35); }
    .md-strong-value { color: #86b6ef; }
    .md-tile-dim  { background: #14273c; border-color: rgba(57,135,229,.35); }
    .md-tile-dim .md-tile-big { color: #86b6ef; }
}

/* ===== Thẻ tủ điều khiển (trang Điều khiển) =====
   Thu gọn để mỗi hàng chứa được nhiều tủ hơn. Vẫn giữ vùng bấm đủ lớn cho ngón tay. */
.cabinet-card {
    border-radius: .6rem;
}

.cabinet-card-title {
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.2;
}

.cabinet-card .badge {
    font-size: .68rem;
    padding: .25em .45em;
}

.cabinet-phase-table {
    font-size: .78rem;
}

.cabinet-phase-table th,
.cabinet-phase-table td {
    padding: .15rem .3rem;
}

/* Trên điện thoại, 2 tủ mỗi hàng nên chữ phải nhỏ thêm một nấc để không vỡ. */
@media (max-width: 575.98px) {
    .cabinet-card-title { font-size: .85rem; }
    .cabinet-phase-table { font-size: .72rem; }
}

/* ===== Thanh điều hướng =====
   Có tới 9 mục menu cộng thương hiệu và khu vực tài khoản. Với cỡ chữ mặc định của Bootstrap
   (1rem) và khoảng đệm rộng, tổng chiều rộng vượt quá màn hình nên chữ bị ngắt xuống dòng
   giữa chừng ("Tổng / quan", "Điều / khiển"). Thu nhỏ chữ, thu hẹp khoảng đệm và cấm ngắt dòng. */
.navbar-brand.fw-bold {
    font-size: 1.05rem;
}

.navbar .nav-link {
    font-size: .875rem;
    padding-left: .55rem;
    padding-right: .55rem;
    white-space: nowrap;   /* thà tràn ngang còn hơn vỡ chữ làm hai dòng */
}

.navbar .nav-link i {
    font-size: .85em;      /* biểu tượng theo cỡ chữ, không lấn át nhãn */
}

/* Khu vực tài khoản (tên đăng nhập + nút Đăng xuất) cũng phải gọn tương ứng. */
.navbar .navbar-account,
.navbar .btn {
    font-size: .875rem;
    white-space: nowrap;
}

/* Vẫn ở dạng thanh ngang nhưng màn hình hẹp (1200px-1499px): siết thêm một nấc.
   Dưới 1200px thanh đã thu về nút menu (navbar-expand-xl) nên không cần xử lý. */
@media (min-width: 1200px) and (max-width: 1499px) {
    .navbar .nav-link {
        font-size: .8rem;
        padding-left: .4rem;
        padding-right: .4rem;
    }

    .navbar-brand.fw-bold {
        font-size: .95rem;
    }
}

/* ===== Responsive tinh chỉnh cho điện thoại ===== */
@media (max-width: 576px) {
    .stat-value {
        font-size: 1.3rem;
    }

    .navbar-brand {
        font-size: 1rem;
    }

    .table-responsive {
        font-size: .85rem;
    }
}


/* ==========================================================================
   Căn LỀ TRÁI cho các ô chứa văn bản dài (tên thiết bị, địa chỉ).
   Quy tắc chung của bảng là căn giữa — hợp với số liệu, nhưng tên và địa chỉ
   căn giữa thì nhìn nhấp nhô, khó dò mắt theo cột. Thêm class .td-trai vào
   đúng những ô đó để ghi đè.
   ========================================================================== */
.table > :not(caption) > * > th.td-trai,
.table > :not(caption) > * > td.td-trai {
    text-align: left;
}


/* ==========================================================================
   IN DANH SÁCH (Danh sách tủ / Danh sách điểm sáng)
   Khi in, chỉ giữ lại tiêu đề và bảng dữ liệu. Ẩn menu, ô tìm kiếm, các nút
   thao tác và cột chứa nút — in ra giấy không ai bấm được nút, để lại chỉ
   tốn giấy và làm bảng vỡ cột.
   ========================================================================== */
@media print {
    /* ----------------------------------------------------------------------
       LỖI ĐÃ SỬA — IN RA BỊ "NHẢY Ô":

       Bản cũ có dòng   th[data-nosort] { display: none }
       Nó ẩn TIÊU ĐỀ của mọi cột không sắp xếp được (cột "#", cột nút...) NHƯNG
       KHÔNG ẩn các Ô DỮ LIỆU của cột đó. Tiêu đề mất một ô, thân bảng vẫn đủ ô
       -> toàn bảng TRƯỢT một cột: số thứ tự rơi vào cột "Loại", tên rơi vào cột
       "Mã"... Mọi báo cáo đều sai.

       NGUYÊN TẮC: ẩn một cột thì phải ẩn CẢ tiêu đề LẪN ô dữ liệu của nó. Cách
       duy nhất an toàn là đánh dấu bằng class .no-print / .khong-in đặt trên CẢ
       <th> lẫn <td>. TUYỆT ĐỐI không ẩn cột dựa theo thuộc tính chỉ có ở <th>.
       ---------------------------------------------------------------------- */
    .khong-in,
    .no-print,
    nav.navbar,
    footer,
    .btn {
        display: none !important;
    }

    /* Ô tích chọn: ẩn phần tử bên trong, KHÔNG ẩn ô -> bảng giữ nguyên số cột. */
    .xh-check,
    #xhCheckAll,
    .ahl-check,
    .bh-check,
    .bt-check,
    .tc-check,
    .form-check-input {
        visibility: hidden !important;
    }

    .card { border: none !important; box-shadow: none !important; }
    .table { font-size: 11pt; }

    /* Mũi tên sắp xếp ⇅ in ra vô nghĩa, nhưng chỉ ẩn CHỮ, không ẩn cả ô. */
    .th-arrow { display: none !important; }

    /* Tiêu đề in: tên bảng + ngày in (thẻ .tieu-de-in trong trang). */
    .tieu-de-in { display: block !important; }
}

/* Bình thường không hiện dòng tiêu đề dành riêng cho bản in. */
.tieu-de-in { display: none; }


/* ==========================================================================
   THANH MENU: LÀM CHỮ VÀ BIỂU TƯỢNG NÉT HẲN

   Hai nguyên nhân khiến thanh menu nhìn mờ như vỡ ảnh:

   1. Bootstrap "navbar-dark" để chữ ở độ đục CHỈ 0.55 (--bs-navbar-color:
      rgba(255,255,255,.55)). Chữ trắng mờ hơn nửa trên nền xanh -> xám xịt,
      đọc mỏi mắt. Kéo lên gần trắng hẳn.

   2. Trình duyệt mặc định khử răng cưa kiểu subpixel. Kiểu đó tốt cho chữ ĐEN
      trên nền TRẮNG, nhưng với chữ SÁNG trên nền TỐI thì nó làm nét chữ dày
      bệt ra, trông nhoè. Chuyển sang antialiased (khử răng cưa theo mức xám)
      cho riêng thanh menu -> nét đanh lại.
   ========================================================================== */
.navbar.bg-primary {
    --bs-navbar-color: rgba(255, 255, 255, .92);
    --bs-navbar-hover-color: #fff;
    --bs-navbar-active-color: #fff;
    --bs-navbar-brand-color: #fff;
    --bs-navbar-brand-hover-color: #fff;

    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

.navbar.bg-primary .nav-link,
.navbar.bg-primary .navbar-brand,
.navbar.bg-primary .navbar-account,
.navbar.bg-primary .btn {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Chữ menu hơi đậm lên một nấc: ở cỡ nhỏ (.875rem) nét mảnh dễ bị "loãng". */
.navbar.bg-primary .nav-link {
    font-weight: 500;
}

/* Biểu tượng Font Awesome cũng phải khử răng cưa, nếu không rìa icon lởm chởm. */
.navbar.bg-primary .nav-link i,
.navbar.bg-primary .navbar-brand i,
.navbar.bg-primary .btn i {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    opacity: 1;          /* không để icon mờ hơn chữ */
}

/* Đang ở trang nào thì mục đó nổi hẳn lên, khỏi phải dò. */
.navbar.bg-primary .nav-link:hover,
.navbar.bg-primary .nav-link:focus {
    color: #fff;
}


/* ==========================================================================
   BẢN ĐỒ: DẤU HIỆU "ĐANG CHỌN"

   Bấm vào một tủ (hoặc một chấm đèn) giữa hàng trăm cái giống hệt nhau mà không
   có dấu gì thì không biết mình đang xem cái nào — phải dò theo tên ở khung chi
   tiết. Đánh dấu rõ ràng ngay trên bản đồ.

   Chấm ĐÈN đang chọn được phóng to + viền đỏ (làm trong map.js, vì chấm vẽ trên
   canvas nên CSS không với tới). Còn TỦ là biểu tượng HTML nên đánh dấu bằng CSS.
   ========================================================================== */
.leaflet-marker-icon.dang-chon {
    filter: drop-shadow(0 0 6px #ff1744) drop-shadow(0 0 2px #ff1744);
    z-index: 1000 !important;
}

.leaflet-marker-icon.dang-chon::after {
    content: '';
    position: absolute;
    inset: -6px;
    border: 2px solid #ff1744;
    border-radius: 50%;
    animation: chon-nhay 1.2s ease-out infinite;
    pointer-events: none;
}

@keyframes chon-nhay {
    0%   { transform: scale(.85); opacity: 1; }
    100% { transform: scale(1.35); opacity: 0; }
}


/* ==========================================================================
   BẢN ĐỒ: TRẠM BIẾN ÁP
   Trạm là NGUỒN CẤP cho các tủ, nên vẽ khác hẳn tủ và đèn: biểu tượng tia sét
   trong khung vuông vàng — nhìn phát biết ngay đâu là điểm cấp nguồn.
   ========================================================================== */
.marker-tram {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    background: #ffc107;
    color: #1a1a1a;
    border: 2px solid #fff;
    border-radius: .35rem;
    box-shadow: 0 2px 6px rgba(0,0,0,.35);
    font-size: 15px;
}

/* Popup thông tin trạm */
.md-pop { min-width: 210px; }
.md-pop-head {
    border-bottom: 1px solid #dee2e6;
    padding-bottom: .3rem;
    margin-bottom: .35rem;
}
.md-pop-row {
    display: flex;
    justify-content: space-between;
    gap: .75rem;
    font-size: .82rem;
    padding: .1rem 0;
}
.md-pop-row span { color: #6c757d; }


/* ==========================================================================
   POPUP THIẾT BỊ TRÊN BẢN ĐỒ

   LỖI ĐÃ SỬA: trước đây để "width: auto" cho popup, Leaflet co nó lại theo nội
   dung hẹp nhất -> popup teo còn hơn trăm pixel, chữ vỡ từng từ ("Trạm / biến /
   áp 01"), các ô số liệu tụt xuống hai dòng. Nay ẤN ĐỊNH chiều rộng cố định.
   ========================================================================== */
.mp-popup .leaflet-popup-content-wrapper {
    border-radius: .5rem;
    padding: 0;
    overflow: hidden;
    box-shadow: 0 4px 16px rgba(0,0,0,.16);
}
/* Chiều rộng CỐ ĐỊNH — đây là mấu chốt, thiếu nó là popup tự bóp lại. */
.mp-popup .leaflet-popup-content {
    margin: 0;
    width: 268px !important;
}

.mp {
    font-size: .78rem;
    /* Không bao giờ cắt chữ giữa từ. */
    word-break: normal;
    overflow-wrap: break-word;
}

/* ----- Đầu ----- */
.mp-dau {
    border-left: 3px solid #6c757d;
    background: #f8f9fa;
    padding: .4rem .55rem .35rem;
}
.mp-ten { font-weight: 650; font-size: .86rem; line-height: 1.25; }
.mp-phu { color: #9aa0a6; font-size: .68rem; line-height: 1.3; margin-top: .05rem; }
.mp-tt {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    margin-top: .25rem;
    font-size: .7rem;
    font-weight: 600;
}
.mp-tt i { width: .42rem; height: .42rem; border-radius: 50%; flex: 0 0 auto; }

.mp-than { padding: .45rem .55rem .55rem; }

/* ----- Ô số liệu ----- */
.mp-o { display: grid; gap: .28rem; margin-bottom: .35rem; }
.mp-o-item {
    background: #f8f9fa;
    border: 1px solid #eceef1;
    border-radius: .3rem;
    padding: .2rem .1rem;
    text-align: center;
    min-width: 0;                /* cho phép ô co, nhưng nội dung một dòng */
}
.mp-o-nhan { font-size: .62rem; color: #9aa0a6; line-height: 1.1; }
.mp-o-so {
    font-size: .8rem;
    font-weight: 650;
    line-height: 1.3;
    white-space: nowrap;         /* "0 V" KHÔNG được tách hai dòng */
}
.mp-o-so span { font-size: .6rem; font-weight: 500; color: #9aa0a6; margin-left: .1rem; }

.mp-tong { font-size: .74rem; color: #6c757d; text-align: center; padding: .1rem 0 .2rem; }

/* ----- Cáp nối tới ----- */
.mp-cap { display: grid; gap: .3rem; margin-top: .2rem; }
.mp-cap-dong {
    border-left: 2px solid #e9ecef;
    padding-left: .4rem;
}
.mp-cap-dau {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .4rem;
}
.mp-cap-ten {
    font-size: .76rem;
    font-weight: 600;
    line-height: 1.3;
    min-width: 0;                /* tên dài thì xuống dòng, KHÔNG đẩy vỡ số mét */
}
.mp-cap-m {
    color: #9aa0a6;
    font-size: .68rem;
    white-space: nowrap;         /* "183 m" luôn nằm một dòng */
    flex: 0 0 auto;
}
.mp-cap-nhan { font-size: .66rem; color: #868e96; line-height: 1.35; margin-top: .05rem; }

/* ----- Nút ----- */
.mp-nut {
    display: block;
    margin-top: .5rem;
    text-align: center;
    background: #0d6efd;
    color: #fff !important;
    border-radius: .3rem;
    padding: .28rem .4rem;
    font-size: .74rem;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none !important;
}
.mp-nut:hover { background: #0b5ed7; }
.mp-mo { color: #adb5bd; font-size: .72rem; }
