body {
    background: #f5f6fa;
    font-size: 14px;
}

.sidebar {
    background: #2c3e50;
    padding: 20px 0;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}
/* Slimmer scrollbar so it doesn't dominate the dark sidebar (Webkit). */
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: #4a5d72; border-radius: 3px; }
.sidebar::-webkit-scrollbar-thumb:hover { background: #5d7088; }

.sidebar-title {
    color: #ecf0f1;
    text-align: center;
    padding: 0 15px 15px;
    border-bottom: 1px solid #34495e;
    margin-bottom: 10px;
}

.sidebar .nav-link {
    color: #bdc3c7;
    padding: 10px 20px;
    border-left: 3px solid transparent;
}

.sidebar .nav-link:hover {
    color: #ecf0f1;
    background: #34495e;
}

.sidebar .nav-link.active {
    color: #fff;
    background: #34495e;
    border-left-color: #3498db;
}

.main-content {
    padding: 30px;
}

.tab-panel {
    display: none;
}

.tab-panel.active {
    display: block;
}

.tab-panel h4 {
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 2px solid #3498db;
}

.table th {
    background: #ecf0f1;
    font-weight: 600;
}

.btn-xs {
    font-size: 12px;
    padding: 2px 8px;
}

.route-card {
    border: 1px solid #dee2e6;
    border-radius: 4px;
    padding: 15px;
    margin-bottom: 15px;
    background: #fff;
}

.route-card h6 {
    margin-bottom: 10px;
}

.route-wp-item {
    background: #f8f9fa;
    border: 1px solid #e9ecef;
    border-radius: 4px;
    padding: 8px 12px;
    margin-bottom: 6px;
}

.route-wp-item .badge {
    margin-left: 6px;
}

#alert-container .alert {
    margin-bottom: 10px;
}

/* Map */
#map-container {
    min-height: 200px;
}

#map-wrapper {
    text-align: center;
}

#wp-map-canvas {
    /* No max-width: zoomMap() resizes the canvas bitmap up to _MAP_ZOOM_MAX
       ×; the parent #wp-map-container handles overflow with scrollbars.
       A CSS clamp here would re-shrink the displayed canvas and make
       only the markers (drawn at bitmap pixel coords) appear to change
       size — see drawMap() in app.js. */
    border: 1px solid #dee2e6;
    border-radius: 4px;
    background: #1a1a2e;
}

/* Cursor feedback for click-and-drag pan (see _initMapPan in app.js).
   `grab` invites the gesture; `grabbing` confirms it while the user
   holds the mouse down. */
#wp-map-container { cursor: grab; }
#wp-map-container.grabbing,
#wp-map-container.grabbing * { cursor: grabbing; user-select: none; }

/* 机器管理：每台机器一张卡片。 */
.robot-card {
    border: 2px solid #dee2e6;
    border-radius: 6px;
    padding: 12px;
    background: #fff;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
    height: 100%;
}
.robot-card:hover { border-color: #adb5bd; }
.robot-card.is-selected { border-color: #007bff; box-shadow: 0 0 0 2px #cfe2ff; }
.robot-card .rc-id { font-family: monospace; font-weight: bold; font-size: 1rem; }
.robot-card .rc-name { color: #495057; font-size: 0.85rem; }
.robot-card .rc-row { display: flex; justify-content: space-between;
                      align-items: center; margin-top: 6px; font-size: 0.85rem; }
/* 电量进度条用浏览器原生 progress，但调小高度并改色阶 */
.robot-card progress { width: 80px; height: 8px; margin-right: 4px; }
.robot-card .battery-low { color: #dc3545; font-weight: 600; }
.robot-card .battery-mid { color: #fd7e14; }
.robot-card .battery-ok  { color: #28a745; }

/* 摄像头 / 餐盘配置：4 个 cam 卡片网格。两个 tab 复用同一份样式，
   通过 data-state 切配色（none/photo/tray/conflict）。 */
.cam-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
}
.cam-card {
    cursor: pointer;
    padding: 14px 8px;
    text-align: center;
    border: 2px solid #dee2e6;
    border-radius: 6px;
    background: #fff;
    transition: border-color 0.15s, background 0.15s;
    user-select: none;
}
.cam-card:hover { background: #f8f9fa; }
.cam-card[data-state="photo"] { border-color: #007bff; background: #e7f1ff; }
.cam-card[data-state="tray"]  { border-color: #28a745; background: #e8f5ec; }
.cam-card[data-state="conflict"] { border-color: #dc3545; background: #fdecee; }
.cam-card .cam-num { font-weight: bold; font-size: 1.1rem; }
.cam-card .cam-role { font-size: 0.75rem; margin-top: 4px; color: #6c757d; }
.cam-card[data-state="photo"] .cam-role { color: #007bff; font-weight: 500; }
.cam-card[data-state="tray"] .cam-role { color: #28a745; font-weight: 500; }
.cam-card[data-state="conflict"] .cam-role { color: #dc3545; font-weight: 600; }

/* 副屏配置：每组 collapsible section。隐藏浏览器默认 marker（Webkit/Firefox
   样式不一），用自己渲染的 ▶ 在 [open] 时旋转 90°。 */
.sdi-group-section > summary { list-style: none; }
.sdi-group-section > summary::-webkit-details-marker { display: none; }
.sdi-group-section > summary::marker { content: ''; }
.sdi-group-tri {
    display: inline-block;
    color: #6c757d;
    transition: transform 0.15s ease;
    font-size: 0.7rem;
}
.sdi-group-section[open] > summary .sdi-group-tri {
    transform: rotate(90deg);
}

#venue-wp-list {
    font-size: 13px;
}

#venue-wp-list code {
    font-size: 12px;
    color: #6c757d;
}

/* ── Voice ── */

.voice-btn {
    padding: 12px 48px;
    font-size: 18px;
    border-radius: 50px;
    transition: all 0.2s;
}

.voice-status-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    vertical-align: middle;
}

.status-idle { background: #95a5a6; }
.status-offline { background: #e74c3c; }
.status-connecting { background: #f39c12; animation: pulse 1s infinite; }
.status-active { background: #2ecc71; animation: pulse 1s infinite; }
.status-recording { background: #e74c3c; animation: pulse 1s infinite; }
.status-processing { background: #3498db; animation: pulse 1s infinite; }
.status-error { background: #e67e22; }

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

.voice-transcript {
    min-height: 120px;
    max-height: 300px;
    overflow-y: auto;
    font-size: 14px;
}

.transcript-item {
    padding: 6px 10px;
    margin-bottom: 4px;
    border-radius: 6px;
}

.transcript-user {
    background: #ebf5fb;
}

.transcript-assistant {
    background: #eafaf1;
}

.voice-log {
    min-height: 60px;
    max-height: 160px;
    overflow-y: auto;
    font-family: monospace;
    font-size: 12px;
    color: #7f8c8d;
}

.voice-log-line {
    padding: 1px 0;
}

.voice-turn {
    padding: 8px 10px;
    margin-bottom: 8px;
    border-left: 3px solid #3498db;
    background: #f8f9fa;
    border-radius: 4px;
}
.voice-turn .voice-q { color: #2c3e50; margin-bottom: 4px; }
.voice-turn .voice-a { color: #16a085; }
.voice-turn .voice-meta { font-size: 11px; margin-top: 4px; }

/* ── Sidebar section headers ── */
.nav-section {
    color: #7f8c8d;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1px;
    padding: 16px 20px 4px;
    margin-top: 6px;
    border-top: 1px solid #34495e;
}

/* ── Robot picker bar ── */
.robot-picker-bar {
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    padding: 8px 14px;
}

/* ── Dashboard ── */
.dash-stat {
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 16px 18px;
    text-align: center;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    transition: box-shadow 120ms ease, transform 120ms ease;
}
.dash-stat:hover { box-shadow: 0 3px 10px rgba(0,0,0,0.08); transform: translateY(-1px); }
.dash-stat.active {
    /* 「正在巡视 N」格在 N>0 时高亮，提醒运营当前有任务在跑 */
    border-color: #17a2b8;
    background: #f0fbfd;
}
.dash-stat .num {
    font-size: 28px;
    font-weight: 700;
    color: #2c3e50;
    line-height: 1.1;
}
.dash-stat .num.small { font-size: 14px; }
.dash-stat .num .dash-stat-sub {
    font-size: 15px;
    color: #95a5a6;
    font-weight: 500;
    margin-left: 2px;
}
.dash-stat .lbl {
    font-size: 12px;
    color: #7f8c8d;
    margin-top: 4px;
}
.dash-robot {
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 12px 14px;
    border-left: 4px solid #95a5a6;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    transition: box-shadow 120ms ease;
}
.dash-robot:hover { box-shadow: 0 3px 10px rgba(0,0,0,0.08); }
.dash-robot.online { border-left-color: #2ecc71; }
.dash-robot.offline { border-left-color: #95a5a6; opacity: 0.75; }
.dash-robot-time { font-size: 11px; margin-top: 2px; }
.dash-robot-actions { display: flex; gap: 6px; }
.dash-store-badge { font-weight: normal; color: #495057; }
.dash-row {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    padding: 2px 0;
}
.dash-row span:first-child { color: #7f8c8d; }
/* 电量条：底色 + 进度填充 + 居中文字 */
.dash-batt {
    position: relative;
    height: 22px;
    background: #ecf0f1;
    border-radius: 4px;
    overflow: hidden;
}
.dash-batt-bar {
    position: absolute;
    inset: 0 auto 0 0;
    background: #2ecc71;
    transition: width 200ms ease;
}
.dash-batt-bar.low  { background: #e74c3c; }
.dash-batt-bar.mid  { background: #f39c12; }
.dash-batt-bar.ok   { background: #2ecc71; }
.dash-batt-bar.unknown { background: #bdc3c7; width: 100%; opacity: 0.3; }
.dash-batt-label {
    position: relative;
    z-index: 1;
    display: block;
    text-align: center;
    line-height: 22px;
    font-size: 12px;
    font-weight: 600;
    color: #2c3e50;
    text-shadow: 0 0 2px rgba(255,255,255,0.6);
}
.dash-patrol-card { border-left: 4px solid #17a2b8; }

/* ── Event stream (机器管理) ── */
.event-stream {
    min-height: 100px;
    max-height: 280px;
    overflow-y: auto;
    font-family: monospace;
    font-size: 12px;
}
.event-line {
    padding: 2px 6px;
    border-bottom: 1px solid #f1f3f5;
}
.event-line .t { color: #95a5a6; margin-right: 6px; }
.evt-event { color: #2980b9; }
.evt-telemetry { color: #27ae60; }
.evt-ack { color: #8e44ad; }
.evt-error { color: #c0392b; }
.evt-warn { color: #d35400; }

/* ── Control console ── */
/* 控制目标状态条：颜色随机器在线源（ws/http/offline）变化，
   同时承担「下一条指令会发给谁」的视觉锚点。 */
.ctrl-target-bar {
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    padding: 10px 14px;
    border-left: 4px solid #adb5bd;
    transition: border-left-color 0.2s, background 0.2s;
}
.ctrl-target-bar.online-ws    { border-left-color: #28a745; background: #f4fbf6; }
.ctrl-target-bar.online-http  { border-left-color: #ffc107; background: #fffbf0; }
.ctrl-target-bar.offline      { border-left-color: #dc3545; background: #fdf2f3; }
.ctrl-target-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.ctrl-target-label {
    font-size: 12px;
    color: #6c757d;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.ctrl-target-id {
    font-family: monospace;
    font-weight: 600;
    font-size: 15px;
    color: #2c3e50;
}
.ctrl-target-hint {
    margin-top: 4px;
}
/* 离线提示时把 hint 染红（覆盖默认 text-muted）。 */
.ctrl-target-bar.offline .ctrl-target-hint { color: #c0392b !important; }

/* 4 个快捷按钮的 2×2 网格；每个按钮独占一格，图标大字标小、纵向排列。 */
.quick-cmd-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}
.quick-cmd-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 10px 6px;
    min-height: 64px;
    line-height: 1.2;
}
.quick-cmd-btn .qc-icon { font-size: 20px; line-height: 1; margin-bottom: 4px; }
.quick-cmd-btn .qc-label { font-size: 13px; }
/* 离线/无 WS 时按钮失去交互能力，但仍可见配色（让用户能看见会下发什么）。 */
.quick-cmd-btn:disabled,
.quick-cmd-trigger:disabled { opacity: 0.45; cursor: not-allowed; }

/* 响应区状态码徽章 */
#ctrl-result-badge .badge { font-family: monospace; }

/* 高层导航折叠面板：隐藏默认 disclosure 三角；
 * 单独的 .ctrl-disc 三角旋转 90° 表达 open（不要旋转文字）。 */
#panel-control details > summary { list-style: none; }
#panel-control details > summary::-webkit-details-marker { display: none; }
#panel-control details > summary::marker { content: ''; }
#panel-control .ctrl-disc {
    display: inline-block;
    color: #6c757d;
    margin-right: 4px;
    transition: transform 0.15s ease;
}
#panel-control details[open] .ctrl-disc {
    transform: rotate(90deg);
}

.control-result {
    font-family: monospace;
    font-size: 12px;
    background: #f8f9fa;
    padding: 8px;
    border-radius: 4px;
    max-height: 320px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-all;
}

/* ── KB hits ── */
.kb-hit {
    background: #fff;
    border: 1px solid #e9ecef;
    border-radius: 4px;
    padding: 8px 12px;
    margin-bottom: 8px;
}
.kb-hit-content {
    font-size: 13px;
    color: #2c3e50;
    margin-top: 4px;
    white-space: pre-wrap;
}

.kb-chat-bubble {
    padding: 10px 14px;
    border-radius: 8px;
    margin-bottom: 8px;
    white-space: pre-wrap;
    line-height: 1.5;
}
.kb-chat-bubble.user {
    background: #ebf5fb;
    border-left: 3px solid #3498db;
}
.kb-chat-bubble.bot {
    background: #eafaf1;
    border-left: 3px solid #2ecc71;
}

/* ── Login page ── */
.login-body {
    background: linear-gradient(135deg, #2c3e50 0%, #4ca1af 100%);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
}
.login-card {
    background: #fff;
    width: 360px;
    padding: 32px 28px;
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.login-title {
    text-align: center;
    color: #2c3e50;
    margin-bottom: 4px;
}

/* ── User menu (top right) ── */
.user-menu {
    border-left: 1px solid #dee2e6;
    padding-left: 12px;
}
.user-menu i {
    font-style: normal;
    margin-right: 2px;
}

/* ── Modal ── */
.modal-backdrop-custom {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
}
.modal-card {
    background: #fff;
    width: 400px;
    max-width: 90vw;
    padding: 24px;
    border-radius: 6px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

/* ── Map-archive table ── */
/* Header on one line; both header and body cells left-aligned horizontally
 * and vertically centered (badges, btn-group, and plain text have different
 * intrinsic heights — without align-middle the row looks ragged).
 * `:not([colspan])` keeps full-row empty-state placeholders (那行 "加载中…"
 * / "暂无归档…") still horizontally centered as Bootstrap text-center wants. */
#maps-archive-table th,
#maps-archive-table td {
    vertical-align: middle;
}
#maps-archive-table th,
#maps-archive-table td:not([colspan]) {
    text-align: left;
}
#maps-archive-table th {
    white-space: nowrap;
}

/* ── 巡视 tab 顶「正在巡视」状态条 ── */
/* 每行一台正在巡视的机器，border-left 颜色按 onlineSource：
 * ws=绿（可即时下发 patrol_skip / patrol_stop）/ http=黄（按钮变灰）。
 * 空状态退化成一行灰色 hint，避免占太大版面。 */
.patrol-status-bar {
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    padding: 10px 14px;
    border-left: 4px solid #28a745;
    margin-bottom: 8px;
}
.patrol-status-bar.psb-http {
    border-left-color: #ffc107;
    background: #fffbf0;
}
.patrol-status-bar.psb-empty {
    border-left-color: #adb5bd;
    background: #f8f9fa;
    color: #6c757d;
    padding: 6px 14px;
    font-size: 13px;
}
.patrol-status-bar .psb-icon { font-size: 18px; margin-right: 4px; }
.patrol-status-bar .psb-route {
    font-weight: 600;
    color: #2c3e50;
}
.patrol-status-bar .psb-progress {
    font-family: monospace;
    color: #6c757d;
}

/* ── 审计日志 ── */
/* action chips：未激活描边，激活时填色（Bootstrap 没 .active 等价做法所以自己写） */
.audit-chip.active {
    color: #fff;
    background: #495057;
    border-color: #495057;
}
.audit-chip.btn-outline-primary.active   { background: #007bff; border-color: #007bff; }
.audit-chip.btn-outline-info.active      { background: #17a2b8; border-color: #17a2b8; }
.audit-chip.btn-outline-success.active   { background: #28a745; border-color: #28a745; }
.audit-chip.btn-outline-warning.active   { background: #fd7e14; border-color: #fd7e14; color: #fff; }
.audit-chip.btn-outline-dark.active      { background: #343a40; border-color: #343a40; }

/* action badge：按业务前缀着色，跟 chip 颜色映射一致 */
.audit-table .audit-action-cmd     { background: #007bff; color: #fff; }
.audit-table .audit-action-route   { background: #17a2b8; color: #fff; }
.audit-table .audit-action-sdi     { background: #28a745; color: #fff; }
.audit-table .audit-action-monitor { background: #fd7e14; color: #fff; }
.audit-table .audit-action-user    { background: #6f42c1; color: #fff; }
.audit-table .audit-action-config  { background: #343a40; color: #fff; }
.audit-table .audit-action-map     { background: #20c997; color: #fff; }
.audit-table .audit-action-robot   { background: #e83e8c; color: #fff; }
.audit-table .audit-action-oss     { background: #6c757d; color: #fff; }
.audit-table td .badge {
    font-family: monospace;
    font-size: 11px;
}
.audit-table th { font-size: 12px; }

/* ── 「分配门店」modal 表格行 ── */
.user-stores-table .usm-org-row td {
    border-top: 1px solid #dee2e6;
    border-bottom: 1px solid #dee2e6;
    font-weight: 600;
    padding: 6px 10px;
}
.user-stores-table tbody tr:not(.usm-org-row):hover { background: #f8f9fa; }

/* ── KB 编辑表单：选择器候选值多选 chip ── */
.kb-options-multi {
    border: 1px solid #ced4da;
    border-radius: 6px;
    padding: 6px 8px;
    background: #fff;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    min-height: 38px;
}
.kb-options-chip {
    background: #f1f3f5;
    border: 1px solid #dee2e6;
    border-radius: 14px;
    padding: 3px 10px;
    font-size: 12px;
    cursor: pointer;
    user-select: none;
    margin: 0;
    transition: background 100ms ease;
}
.kb-options-chip:hover { background: #e9ecef; }
.kb-options-chip input[type="checkbox"] {
    vertical-align: middle;
    margin-right: 4px;
}
.kb-options-chip:has(input:checked) {
    background: #3498db;
    border-color: #2e8bcd;
    color: #fff;
}
.kb-options-chip.chip-extra:has(input:checked) {
    background: #f39c12;
    border-color: #e08a0a;
}
.kb-options-chip small { opacity: 0.85; }

/* ── 导览编辑器：waypoint KB 测试结果气泡 ── */
.route-wp-test-result:empty { display: none; }
.route-wp-test-bubble {
    background: #f0f7fb;
    border-left: 3px solid #17a2b8;
    border-radius: 4px;
    padding: 6px 10px;
    font-size: 13px;
}
.route-wp-test-answer {
    color: #2c3e50;
    margin-top: 2px;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── 语音助手用量柱图 hover tooltip ──
 * #voice-usage-chart 是 Bootstrap card-body，position 默认 static；这里强制
 * relative 让绝对定位的 tooltip 以它为坐标原点。 */
#voice-usage-chart { position: relative; }
.vu-bar { cursor: default; transition: opacity 80ms ease; fill: var(--brand, #4263eb); }
.vu-bar.vu-bar-zero { fill: #e9ecef; }
html[data-theme="dark"] .vu-bar.vu-bar-zero { fill: #2c3650; }
.vu-bar:hover { stroke: #2c3e50; stroke-width: 1.5; opacity: 0.85; }
.vu-tooltip {
    position: absolute;
    display: none;
    background: rgba(33, 37, 41, 0.92);
    color: #fff;
    padding: 5px 9px;
    border-radius: 4px;
    font-size: 12px;
    line-height: 1.3;
    pointer-events: none;
    /* 锚点在 bar 顶部正中：translate 把元素本身往左移一半、往上移 100%
     * 让箭头自然落在正中正上方。 */
    transform: translate(-50%, -100%);
    white-space: nowrap;
    z-index: 100;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
/* 朝下的小三角，连成"气泡 + 指针" */
.vu-tooltip::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: -5px;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: rgba(33, 37, 41, 0.92);
    border-bottom: 0;
}

/* ═════════════════════════════════════════════════════════════
 * 全局 UI polish 层（追加在最底部，高优先级覆盖 Bootstrap 默认）
 * 目标：所有 tab 看起来一套设计，不重写每个面板的 markup。
 * ═════════════════════════════════════════════════════════════ */

/* 背景：略带渐变的灰，把 Bootstrap 默认平铺色变得不那么"硬" */
body {
    background: linear-gradient(180deg, #f5f6fa 0%, #eef0f5 100%);
    min-height: 100vh;
}

/* 侧栏 nav：圆角 + 平滑过渡 + 激活态强对比 */
.sidebar .nav-link {
    border-radius: 0 6px 6px 0;
    margin: 1px 8px 1px 0;
    transition: background 120ms ease, color 120ms ease, padding-left 120ms ease;
}
.sidebar .nav-link:hover { padding-left: 22px; }
.sidebar .nav-link.active {
    box-shadow: inset 4px 0 0 #3498db;
    border-left-color: transparent;
    font-weight: 500;
}

/* 页面主标题 h4：渐变下划线代替单色，icon-friendly */
.tab-panel h4 {
    border-bottom: none;
    padding-bottom: 6px;
    margin-bottom: 16px;
    position: relative;
    font-weight: 600;
    color: #2c3e50;
}
.tab-panel h4::after {
    content: '';
    position: absolute;
    left: 0; bottom: 0;
    width: 48px; height: 3px;
    background: linear-gradient(90deg, #3498db, #1abc9c);
    border-radius: 2px;
}
.tab-panel h6 { color: #34495e; font-weight: 600; }

/* Bootstrap 卡片：统一阴影 + hover 微浮起。会盖到 .route-card / .dash-stat /
 * .dash-robot 等自定义类，但那些已经有自己的 box-shadow，不冲突。 */
.card {
    border: 1px solid #e6e9ed;
    border-radius: 8px;
    box-shadow: 0 1px 2px rgba(44, 62, 80, 0.04);
    transition: box-shadow 140ms ease, transform 140ms ease;
}
.card:hover { box-shadow: 0 3px 12px rgba(44, 62, 80, 0.08); }
.card-header {
    background: #fafbfc;
    border-bottom: 1px solid #e6e9ed;
    border-radius: 8px 8px 0 0 !important;
    font-weight: 500;
}

/* 表格：thead 浅蓝灰 + 行 hover + 紧凑 padding（替 Bootstrap 默认） */
.table thead th {
    background: #f1f3f5;
    color: #495057;
    border-top: none;
    border-bottom: 2px solid #dee2e6;
    font-weight: 600;
    font-size: 13px;
    text-transform: none;
    letter-spacing: 0;
}
.table tbody tr { transition: background 80ms ease; }
.table tbody tr:hover { background: #f8f9fa; }
.table-sm td, .table-sm th { padding: 6px 8px; }

/* 表单控件：focus 圈柔和 */
.form-control, .form-control:focus {
    border-radius: 6px;
}
.form-control:focus {
    border-color: #5dade2;
    box-shadow: 0 0 0 0.15rem rgba(52, 152, 219, 0.18);
}
.form-control-sm { font-size: 13px; }
label { color: #495057; font-weight: 500; }

/* 按钮：圆角 + hover 微抬 + 主色调对齐侧栏激活蓝 */
.btn {
    border-radius: 6px;
    font-weight: 500;
    transition: transform 100ms ease, box-shadow 120ms ease, filter 120ms ease;
}
.btn:hover:not(:disabled):not(.disabled) {
    transform: translateY(-1px);
    filter: brightness(1.05);
}
.btn:active { transform: translateY(0); }
.btn-primary { background: #3498db; border-color: #3498db; }
.btn-primary:hover { background: #2e8bcd; border-color: #2e8bcd; }
.btn-success { background: #27ae60; border-color: #27ae60; }
.btn-success:hover { background: #229a55; border-color: #229a55; }
.btn-danger  { background: #e74c3c; border-color: #e74c3c; }
.btn-warning { background: #f39c12; border-color: #f39c12; color: #fff; }
.btn-warning:hover { color: #fff; }
.btn-info    { background: #17a2b8; border-color: #17a2b8; }
.btn-group-sm > .btn, .btn-sm { font-size: 12.5px; padding: 4px 10px; }
.btn-xs { font-size: 11.5px; padding: 2px 8px; border-radius: 4px; }

/* badge：稍微圆 + 微 padding，颜色饱和度统一调降一点 */
.badge {
    border-radius: 4px;
    padding: 3px 6px;
    font-weight: 500;
    letter-spacing: 0.3px;
}
.badge-primary    { background: #3498db; }
.badge-success    { background: #27ae60; }
.badge-warning    { background: #f39c12; color: #fff; }
.badge-danger     { background: #e74c3c; }
.badge-info       { background: #17a2b8; }
.badge-secondary  { background: #95a5a6; }
.badge-light      { background: #ecf0f1; color: #34495e; }
.badge-dark       { background: #34495e; }

/* alert：圆角微调，让弹出消息不那么"突兀" */
.alert { border-radius: 6px; border: 1px solid transparent; }
.alert-info    { background: #ebf5fb; border-color: #d6eaf8; color: #21618c; }
.alert-warning { background: #fef5e7; border-color: #fae5b8; color: #7d6608; }
.alert-success { background: #eafaf1; border-color: #cce8d3; color: #196f3d; }
.alert-danger  { background: #fdedec; border-color: #f8d7da; color: #922b21; }

/* progress bar：圆角 + 平滑过渡 */
.progress { border-radius: 4px; background: #ecf0f1; }
.progress-bar { transition: width 240ms ease; }

/* code 标签：浅紫底色让 inline 引用更显眼 */
code {
    background: #f8f0fc;
    color: #843c8c;
    padding: 1px 5px;
    border-radius: 3px;
    font-size: 0.9em;
}

/* modal 通用（.modal-backdrop-custom 居中样式保留，只加背景与动画） */
.modal-backdrop-custom {
    background: rgba(44, 62, 80, 0.55);
    backdrop-filter: blur(2px);
}
.modal-card {
    animation: modal-pop 160ms cubic-bezier(.2,.7,.4,1.2);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
}
@keyframes modal-pop {
    from { transform: translateY(-6px) scale(0.98); opacity: 0; }
    to   { transform: translateY(0)    scale(1);    opacity: 1; }
}

/* 空状态 / text-muted：色温稍暖，不像系统报错 */
.text-muted { color: #7f8c8d !important; }

/* 提示文 small / hint 行的间距收紧 */
.form-text, small { line-height: 1.5; }

/* 让分割线轻一点 */
hr { border-top-color: #e6e9ed; opacity: 0.8; }

/* 顶部 robot-picker-bar 在新背景下更显眼 */
.robot-picker-bar {
    background: #fff;
    border: 1px solid #e6e9ed;
    border-radius: 8px;
    padding: 10px 14px;
    box-shadow: 0 1px 2px rgba(44, 62, 80, 0.04);
}

/* 滚动条整体（除了 sidebar）柔化 */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: #cdd5dc; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #aab4bc; }
::-webkit-scrollbar-track { background: transparent; }

/* ── 地图归档表 ── */
#maps-archive-table tbody tr.maps-row-current {
    background-color: rgba(40, 167, 69, 0.08);
    border-left: 3px solid #28a745;
}
#maps-archive-table tbody tr.maps-row-current:hover {
    background-color: rgba(40, 167, 69, 0.14);
}
#maps-archive-table tbody tr.table-active {
    border-left: 3px solid #6c757d;
}
#maps-archive-table tbody tr {
    border-left: 3px solid transparent;
}
/* ═══════════════════════════════════════════════════════════════════
   Robot-Admin 靛蓝换肤层 (2026-06)
   —— 参考 robotadmin.cn 的现代后台风：靛蓝主色 + 深靛蓝侧栏 + 卡片化。
   做法：后置覆盖。只迁移「品牌蓝」(#3498db / #007bff / #1abc9c 渐变) 到靛蓝，
   绿/红/黄/青等「状态语义色」(online/error/warning…) 一律保持不动。
   设计 token 见 :root，下方各组件引用变量，便于后续整体调色。
   ═══════════════════════════════════════════════════════════════════ */
:root {
    --brand:        #4263eb;   /* 主色 indigo */
    --brand-dark:   #3b51c9;   /* hover / active */
    --brand-darker: #2f40a0;
    --brand-soft:   #edf0ff;   /* 浅靛底 (选中/高亮背景) */
    --brand-ring:   rgba(66, 99, 235, 0.22);  /* focus 光圈 */
    --brand-grad:   linear-gradient(90deg, #4263eb, #738bff);
    --side-grad:    linear-gradient(180deg, #232b4d 0%, #1b2138 100%);
    --radius:       10px;
    --radius-sm:    8px;
    --shadow-sm:    0 1px 3px rgba(33, 43, 80, 0.06);
    --shadow-md:    0 4px 16px rgba(33, 43, 80, 0.08);
}

/* —— 全局排版：现代无衬线栈 + 字形平滑 —— */
body {
    background: #f3f5fb;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
                 "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    color: #2d3450;
}

/* —— 侧边栏：深靛蓝渐变 + 圆角胶囊式激活项 —— */
.sidebar {
    background: var(--side-grad);
    padding: 16px 0;
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.04);
}
.sidebar-title {
    color: #f4f6ff;
    letter-spacing: 1px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.sidebar .nav-link {
    color: #aeb6d6;
    margin: 2px 10px;
    padding: 9px 14px;
    border-left: none;
    border-radius: var(--radius-sm);
    transition: background 0.15s, color 0.15s;
}
.sidebar .nav-link:hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.06);
}
.sidebar .nav-link.active {
    color: #fff;
    background: var(--brand);
    border-left: none;
    box-shadow: 0 4px 12px rgba(66, 99, 235, 0.45);
}
.sidebar::-webkit-scrollbar-thumb { background: #3a4470; }
.sidebar::-webkit-scrollbar-thumb:hover { background: #4a5690; }
.nav-section {
    color: #6f79a8;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}

/* —— 品牌蓝 → 靛蓝（按钮 / 徽章 / 强调）—— */
.btn-primary { background: var(--brand); border-color: var(--brand); }
.btn-primary:hover:not(:disabled):not(.disabled) {
    background: var(--brand-dark); border-color: var(--brand-dark);
}
.btn-outline-primary { color: var(--brand); border-color: var(--brand); }
.btn-outline-primary:hover { background: var(--brand); border-color: var(--brand); }
.badge-primary { background: var(--brand); }
.audit-chip.btn-outline-primary.active { background: var(--brand); border-color: var(--brand); }
.robot-card.is-selected { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft); }

/* —— focus 光圈改靛蓝 —— */
.form-control:focus {
    border-color: #8fa0f2;
    box-shadow: 0 0 0 0.18rem var(--brand-ring);
}

/* —— 主标题渐变下划线改靛蓝 —— */
.tab-panel h4::after { background: var(--brand-grad); }

/* —— 卡片：更大圆角 + 更柔的投影（卡片化内容）—— */
.card {
    border: 1px solid #e7eaf3;
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.card:hover { box-shadow: var(--shadow-md); }
.card-header { background: #f7f8fd; border-bottom: 1px solid #e7eaf3; }
.robot-picker-bar,
.route-card,
.dash-stat,
.dash-robot,
.ctrl-target-bar,
.patrol-status-bar {
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.robot-picker-bar { border-color: #e7eaf3; }
.modal-card { border-radius: 14px; box-shadow: 0 16px 48px rgba(33, 43, 80, 0.22); }

/* —— 表格表头：浅靛灰 —— */
.table thead th { background: #eef1fa; color: #46506f; border-bottom: 2px solid #dfe4f2; }
.table tbody tr:hover { background: #f6f7fd; }

/* —— 登录 / 选择平台 页背景：teal → 靛蓝渐变（与后台主色统一）—— */
.login-body { background: linear-gradient(135deg, #2f3a66 0%, #4263eb 100%); }

.btn-xs {
    padding: 1px 6px;
    font-size: 11px;
    line-height: 1.4;
    border-radius: 3px;
}

/* ═══════════════════════════════════════════════════════════════════
   Robot-Admin 交互增强 (2026-06)
   —— 侧栏图标列 + 折叠 + 品牌区 + 面包屑 + 顶栏控件 + 暗黑模式。
   主题色 / 暗黑由 <html data-theme> + JS 写 :root 变量驱动 (config.html 顶栏控件)。
   ═══════════════════════════════════════════════════════════════════ */

/* —— 侧栏品牌区 (替代纯文字标题) —— */
.sidebar-brand {
    display: flex; align-items: center; gap: 10px;
    padding: 4px 18px 14px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    margin-bottom: 8px;
    white-space: nowrap; overflow: hidden;
}
.sidebar-brand .brand-logo { font-size: 24px; line-height: 1; flex-shrink: 0; }
.sidebar-brand .brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.sidebar-brand .brand-text strong { color: #f4f6ff; font-size: 1.05rem; letter-spacing: 1px; }
.sidebar-brand .brand-text small { color: #6f79a8; font-size: 0.68rem; letter-spacing: 1px; }

/* —— 侧栏图标列：按 data-tab 注入 emoji，展开时图标+文字，折叠时只图标 —— */
.sidebar .nav-link { display: flex; align-items: center; }
.sidebar .nav-link::before {
    font-size: 15px; width: 22px; text-align: center; margin-right: 8px; flex-shrink: 0;
}
.sidebar .nav-link[data-tab="dashboard"]::before         { content: "🏠"; }
.sidebar .nav-link[data-tab="robots"]::before            { content: "🤖"; }
.sidebar .nav-link[data-tab="control"]::before           { content: "🎮"; }
.sidebar .nav-link[data-tab="venue"]::before             { content: "🏢"; }
.sidebar .nav-link[data-tab="maps"]::before              { content: "🗺️"; }
.sidebar .nav-link[data-tab="tour-routes"]::before       { content: "🧭"; }
.sidebar .nav-link[data-tab="patrol-routes"]::before     { content: "🛡️"; }
.sidebar .nav-link[data-tab="table-mappings"]::before    { content: "🏷️"; }
.sidebar .nav-link[data-tab="camera"]::before            { content: "📷"; }
.sidebar .nav-link[data-tab="secondary-display"]::before { content: "🖥️"; }
.sidebar .nav-link[data-tab="monitor"]::before           { content: "📹"; }
.sidebar .nav-link[data-tab="kb"]::before                { content: "📚"; }
.sidebar .nav-link[data-tab="voice"]::before             { content: "🎙️"; }
.sidebar .nav-link[data-tab="system"]::before            { content: "⚙️"; }
.sidebar .nav-link[data-tab="stores"]::before            { content: "🏬"; }
.sidebar .nav-link[data-tab="users"]::before             { content: "👥"; }
.sidebar .nav-link[data-tab="audit-log"]::before         { content: "📋"; }

/* —— 侧栏折叠态 (body.sidebar-collapsed) —— */
.sidebar { transition: flex-basis 0.18s ease, max-width 0.18s ease, width 0.18s ease; }
body.sidebar-collapsed nav.sidebar { flex: 0 0 62px; max-width: 62px; width: 62px; }
body.sidebar-collapsed main.main-content { flex: 0 0 calc(100% - 62px); max-width: calc(100% - 62px); }
body.sidebar-collapsed .sidebar .nav-link {
    /* font-size:0 折叠文字节点，::before 用显式字号留住图标 */
    font-size: 0; justify-content: center; padding: 9px 0; margin: 2px 8px;
}
body.sidebar-collapsed .sidebar .nav-link::before { margin-right: 0; font-size: 16px; }
body.sidebar-collapsed .sidebar .nav-section { font-size: 0; padding: 8px 0; border-top-width: 0; }
body.sidebar-collapsed .sidebar-brand { justify-content: center; padding: 4px 0 14px; }
body.sidebar-collapsed .sidebar-brand .brand-text { display: none; }
/* 折叠态悬停浮出菜单名 */
body.sidebar-collapsed .sidebar .nav-link { position: relative; }
body.sidebar-collapsed .sidebar .nav-link::after {
    content: attr(data-label); position: absolute; left: calc(100% + 6px); top: 50%;
    transform: translateY(-50%); background: #232b4d; color: #fff; font-size: 12px;
    padding: 4px 10px; border-radius: 6px; white-space: nowrap; opacity: 0;
    pointer-events: none; box-shadow: var(--shadow-md); z-index: 50; transition: opacity 0.12s;
}
body.sidebar-collapsed .sidebar .nav-link:hover::after { opacity: 1; }

/* —— 顶栏头部行：折叠钮 + 面包屑 + 主题控件 —— */
.topbar-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.sidebar-toggle {
    border: 1px solid var(--border, #e7eaf3); background: #fff; color: #46506f;
    width: 34px; height: 34px; border-radius: 8px; cursor: pointer; flex-shrink: 0;
    font-size: 16px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
    transition: background 0.12s, border-color 0.12s;
}
.sidebar-toggle:hover { background: var(--brand-soft, #edf0ff); border-color: var(--brand, #4263eb); color: var(--brand, #4263eb); }
.breadcrumb-bar { font-size: 14px; color: #8089a3; display: flex; align-items: center; gap: 7px; }
.breadcrumb-bar .crumb-root { color: #8089a3; }
.breadcrumb-bar .sep { color: #c3cad9; }
.breadcrumb-bar #crumb-current { color: #2d3450; font-weight: 600; }

/* —— 主题控件：暗黑钮 + 色板 —— */
.theme-controls { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.theme-swatches { display: inline-flex; gap: 6px; }
.theme-swatch {
    width: 18px; height: 18px; border-radius: 50%; cursor: pointer; padding: 0;
    border: 2px solid transparent; box-shadow: 0 0 0 1px rgba(0,0,0,0.12);
    transition: transform 0.1s;
}
.theme-swatch:hover { transform: scale(1.15); }
.theme-swatch.active { border-color: #fff; box-shadow: 0 0 0 2px currentColor; }
.dark-toggle {
    border: 1px solid var(--border, #e7eaf3); background: #fff; color: #46506f;
    width: 34px; height: 34px; border-radius: 8px; cursor: pointer; font-size: 15px;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background 0.12s, border-color 0.12s;
}
.dark-toggle:hover { background: var(--brand-soft, #edf0ff); border-color: var(--brand, #4263eb); }

/* ═══════════ 暗黑模式 (html[data-theme="dark"]) ═══════════
   覆盖主要 surface / 文字 / 边框；状态语义色 (绿红黄) 保持不动。 */
html[data-theme="dark"] body { background: #11151f; color: #c7cee0; }
html[data-theme="dark"] .main-content { color: #c7cee0; }
html[data-theme="dark"] .card,
html[data-theme="dark"] .robot-picker-bar,
html[data-theme="dark"] .route-card,
html[data-theme="dark"] .dash-stat,
html[data-theme="dark"] .dash-robot,
html[data-theme="dark"] .ctrl-target-bar,
html[data-theme="dark"] .patrol-status-bar,
html[data-theme="dark"] .robot-card,
html[data-theme="dark"] .cam-card,
html[data-theme="dark"] .modal-card,
html[data-theme="dark"] .login-card {
    background: #1a2030; border-color: #2c3650; color: #c7cee0;
}
html[data-theme="dark"] .card-header { background: #222a3d; border-color: #2c3650; color: #c7cee0; }
html[data-theme="dark"] .table { color: #c7cee0; }
html[data-theme="dark"] .table thead th { background: #222a3d; color: #aab2cc; border-bottom-color: #2c3650; }
html[data-theme="dark"] .table td, html[data-theme="dark"] .table th { border-color: #2c3650; }
html[data-theme="dark"] .table tbody tr:hover { background: #222a3d; }
html[data-theme="dark"] .form-control,
html[data-theme="dark"] select.form-control,
html[data-theme="dark"] textarea.form-control,
html[data-theme="dark"] .custom-select {
    background: #11151f; border-color: #2c3650; color: #dbe0f0;
}
html[data-theme="dark"] .form-control::placeholder { color: #5b667f; }
html[data-theme="dark"] .form-control:focus { background: #11151f; }
html[data-theme="dark"] label { color: #aab2cc; }
html[data-theme="dark"] .text-dark { color: #c7cee0 !important; }
html[data-theme="dark"] .text-muted, html[data-theme="dark"] .muted-note { color: #7b85a3 !important; }
html[data-theme="dark"] code { background: #2a2440; color: #d8b7ff; }
html[data-theme="dark"] hr { border-top-color: #2c3650; }
html[data-theme="dark"] .nav-tabs { border-bottom-color: #2c3650; }
html[data-theme="dark"] .nav-tabs .nav-link.active {
    background: #1a2030; border-color: #2c3650 #2c3650 #1a2030; color: #c7cee0;
}
html[data-theme="dark"] .nav-tabs .nav-link:hover { border-color: #2c3650; }
html[data-theme="dark"] .badge-light { background: #2c3650; color: #c7cee0; }
html[data-theme="dark"] .badge-secondary { background: #4a5470; }
html[data-theme="dark"] .sidebar-toggle,
html[data-theme="dark"] .dark-toggle { background: #1a2030; border-color: #2c3650; color: #c7cee0; }
html[data-theme="dark"] .breadcrumb-bar #crumb-current { color: #e3e8f5; }
html[data-theme="dark"] .breadcrumb-bar .sep { color: #44506e; }
html[data-theme="dark"] .dash-stat .num { color: #e3e8f5; }
html[data-theme="dark"] .ctrl-target-id, html[data-theme="dark"] .dash-batt-label { color: #e3e8f5; }
html[data-theme="dark"] .dash-batt { background: #2c3650; }
/* 医小保暗黑 */
html[data-theme="dark"] .yxb-main { color: #c7cee0; }
html[data-theme="dark"] .card-block { background: #1a2030; border-color: #2c3650; color: #c7cee0; }
html[data-theme="dark"] .kv-table th { color: #8089a3; }
/* 弹层遮罩在暗黑下更深 */
html[data-theme="dark"] .modal-backdrop-custom { background: rgba(0, 0, 0, 0.66); }
