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; }
.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;
}
.btn-xs {
    padding: 1px 6px;
    font-size: 11px;
    line-height: 1.4;
    border-radius: 3px;
}
