<template>
  <div class="vehicle-monitor" :class="{ 'is-compact': compact, 'is-table': table, 'is-lite': lite }">
    <div v-if="!compact && !table" class="overview-row">
      <div class="overview-item">
        <div class="overview-num">{{ cars.length }}</div>
        <div class="overview-label">总数</div>
      </div>
      <div class="overview-item">
        <div class="overview-num online">{{ onlineCount }}</div>
        <div class="overview-label">在线</div>
      </div>
      <div class="overview-item">
        <div class="overview-num running">{{ runningCount }}</div>
        <div class="overview-label">运行</div>
      </div>
      <div class="overview-item">
        <div class="overview-num charging">{{ chargingCount }}</div>
        <div class="overview-label">充电</div>
      </div>
      <div class="overview-item">
        <div class="overview-num fault">{{ faultCount }}</div>
        <div class="overview-label">故障</div>
      </div>
    </div>

    <div class="toolbar">
      <el-input
        v-model="search"
        size="small"
        clearable
        :placeholder="tablePlaceholder"
        class="search"
      />
      <el-select
        v-if="!table"
        v-model="filterState"
        size="small"
        placeholder="状态"
        clearable
        class="filter"
      >
        <el-option
          v-for="opt in stateOptions"
          :key="opt.value"
          :label="opt.label"
          :value="opt.value"
        />
      </el-select>
    </div>

    <div v-if="table" class="chip-row" role="tablist" aria-label="状态筛选">
      <button
        v-for="chip in filterChips"
        :key="chip.key"
        type="button"
        role="tab"
        class="chip"
        :class="{ 'is-active': quickFilter === chip.key }"
        :aria-selected="quickFilter === chip.key"
        @click="quickFilter = chip.key"
      >
        {{ chip.label }}
        <span class="chip-n">{{ chip.count }}</span>
      </button>
    </div>

    <div v-if="table" class="table-wrap">
      <div class="dense-scroll">
        <table class="dense-table" aria-label="车辆列表">
          <thead>
            <tr>
              <th class="col-vehicle">车辆</th>
              <th class="col-state">状态</th>
              <th class="col-bat">电量</th>
              <th class="col-mission">任务</th>
              <th v-if="!lite" class="col-alarm">报警</th>
              <th class="col-tc">交管</th>
              <th v-if="!lite" class="col-lock">锁点</th>
              <th v-if="!lite" class="col-ops">操作</th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="car in filteredCars"
              :key="car.id"
              class="dense-row"
              :class="{
                'is-selected': car.id === selectedId,
                'has-alarm': !lite && hasAlarm(car),
                'is-busy': !lite && !!actingId && actingId === carKey(car)
              }"
              tabindex="0"
              @click="onSelect(car)"
              @keydown.enter.prevent="onSelect(car)"
            >
              <td class="col-vehicle">
                <div class="veh-cell">
                  <span class="veh-id">{{ shortId(car) }}</span>
                  <span class="veh-name" :title="car.name">{{ car.name || `车辆 ${shortId(car)}` }}</span>
                </div>
                <div class="veh-meta" :title="positionMeta(car)">{{ positionMeta(car) }}</div>
              </td>
              <td class="col-state">
                <span class="state-pill" :class="`pill-${car.state}`">
                  <i class="state-dot" :class="`dot-${car.state}`" />
                  {{ stateLabel(car.state) }}
                </span>
              </td>
              <td class="col-bat" :class="batteryLevel(batteryPct(car))">{{ batteryText(car) }}</td>
              <td class="col-mission" :class="{ muted: !missionForCar(car) }" :title="missionTitle(car)">
                {{ missionCell(car) }}
              </td>
              <td v-if="!lite" class="col-alarm" :class="{ warn: hasAlarm(car) }" :title="alarmText(car)">
                {{ alarmCell(car) }}
              </td>
              <td class="col-tc" :class="{ warn: isTrafficBlocked(car) }" :title="trafficText(car)">
                {{ trafficCell(car) }}
              </td>
              <td v-if="!lite" class="col-lock mono" :title="lockText(car)">{{ lockCell(car) }}</td>
              <td v-if="!lite" class="col-ops" @click.stop>
                <el-dropdown
                  trigger="click"
                  placement="bottom-end"
                  :disabled="!!actingId"
                  @command="(cmd: VehicleQuickAction) => onQuickAction(car, cmd)"
                >
                  <button
                    type="button"
                    class="ops-btn"
                    :disabled="!!actingId"
                    title="车辆操作"
                  >
                    操作
                    <el-icon class="ops-caret"><ArrowDown /></el-icon>
                  </button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item
                        v-for="op in quickActions"
                        :key="op.value"
                        :command="op.value"
                        :divided="op.value === 'disable'"
                        :class="{ 'is-danger-item': op.danger }"
                      >
                        {{ op.label }}
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </td>
            </tr>
          </tbody>
        </table>
        <div v-if="!filteredCars.length" class="empty muted">无匹配车辆</div>
      </div>
    </div>

    <div v-else class="vehicle-list">
      <div
        v-for="car in filteredCars"
        :key="car.id"
        class="vehicle-row"
        :class="{ 'is-selected': car.id === selectedId }"
        @click="onSelect(car)"
      >
        <div class="vehicle-head">
          <span class="vid">{{ car.id }}</span>
          <span class="vname" :title="car.name">{{ car.name }}</span>
          <el-tag
            size="small"
            :type="stateTagType(car.state)"
            class="state-tag"
            effect="dark"
          >
            <span class="dot" :class="`dot-${car.state}`" />
            {{ stateLabel(car.state) }}
          </el-tag>
        </div>

        <div class="vehicle-sub">
          <div class="battery-mini" :title="`电量 ${batteryPct(car)}%`">
            <el-progress
              :percentage="batteryPct(car)"
              :stroke-width="6"
              :show-text="false"
              :color="batteryColor(batteryPct(car))"
              class="battery-bar"
            />
            <span class="battery-text" :class="batteryLevel(batteryPct(car))">
              {{ batteryPct(car) }}%
            </span>
          </div>
          <div class="mission-mini">
            <template v-if="missionForCar(car)">
              <el-tag
                size="small"
                :type="missionStatusTagType(missionForCar(car)!.status)"
                effect="plain"
                class="mission-tag"
              >
                {{ missionStatusLabel(missionForCar(car)!.status) }}
              </el-tag>
              <span class="mission-name" :title="missionForCar(car)!.name">
                {{ missionForCar(car)!.name }}
              </span>
            </template>
            <template v-else>
              <span class="mission-name muted">空闲</span>
            </template>
          </div>
        </div>
      </div>

      <div v-if="!filteredCars.length" class="empty muted">
        无匹配车辆
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { ArrowDown } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { Car, CarState } from '@/types/car'
import type { Mission, MissionStatus } from '@/types/mission'
import type { SelectedObjectRef } from '@/types/workbench'
import {
  VEHICLE_QUICK_ACTIONS,
  executeVehicleQuickAction,
  type VehicleQuickAction
} from '@/api/vehicleOps'
import { isTrafficCongested } from '@/utils/carRuntime'

const props = defineProps<{
  cars: Car[]
  missions: Mission[]
  selectedId?: string | null
  /** 紧凑模式：隐藏顶部概览条 */
  compact?: boolean
  /** 表格模式：筛选芯片 + 紧凑数据表（地图监控） */
  table?: boolean
  /** 双栏精简：隐藏报警 / 锁点 / 操作列 */
  lite?: boolean
}>()

const emit = defineEmits<{
  select: [ref: SelectedObjectRef]
  'action-done': []
}>()

const quickActions = VEHICLE_QUICK_ACTIONS
const actingId = ref<string | null>(null)

const tablePlaceholder = computed(() => {
  if (!props.table) return '搜索 ID / 名称 / 任务'
  return props.lite
    ? '搜索编号 / 名称 / 交管 / 任务'
    : '搜索编号 / 名称 / 报警 / 交管 / 任务'
})

const search = ref('')
const filterState = ref<CarState | ''>('')
type QuickFilter = 'all' | 'running' | 'idle' | 'offline' | 'fault'
const quickFilter = ref<QuickFilter>('all')

const stateOptions: { value: CarState; label: string }[] = [
  { value: 'idle', label: '空闲' },
  { value: 'running', label: '运行中' },
  { value: 'charging', label: '充电中' },
  { value: 'paused', label: '已暂停' },
  { value: 'fault', label: '故障' },
  { value: 'offline', label: '离线' }
]

const stateLabels = stateOptions.reduce<Record<string, string>>((acc, o) => {
  acc[o.value] = o.label
  return acc
}, {})

function stateLabel(s: CarState): string {
  return stateLabels[s] ?? s
}

type TagType = 'success' | 'warning' | 'danger' | 'info' | 'primary'

function stateTagType(s: CarState): TagType {
  switch (s) {
    case 'running':
      return 'success'
    case 'charging':
      return 'primary'
    case 'paused':
      return 'warning'
    case 'fault':
      return 'danger'
    case 'offline':
      return 'info'
    case 'idle':
    default:
      return 'info'
  }
}

const missionStatusLabels: Record<MissionStatus, string> = {
  queued: '排队',
  assigned: '已分配',
  running: '执行中',
  paused: '暂停',
  completed: '已完成',
  cancelled: '已取消',
  failed: '失败'
}

function missionStatusLabel(s: MissionStatus): string {
  return missionStatusLabels[s] ?? s
}

function missionStatusTagType(s: MissionStatus): TagType {
  switch (s) {
    case 'running':
      return 'success'
    case 'assigned':
      return 'primary'
    case 'queued':
      return 'info'
    case 'paused':
      return 'warning'
    case 'completed':
      return 'success'
    case 'cancelled':
      return 'info'
    case 'failed':
      return 'danger'
    default:
      return 'info'
  }
}

const onlineCount = computed(() => props.cars.filter((c) => c.state !== 'offline').length)
const runningCount = computed(() => props.cars.filter((c) => c.state === 'running').length)
const chargingCount = computed(() => props.cars.filter((c) => c.state === 'charging').length)
const faultCount = computed(() => props.cars.filter((c) => c.state === 'fault').length)
const idleCount = computed(() => props.cars.filter((c) => c.state === 'idle').length)
const offlineCount = computed(() => props.cars.filter((c) => c.state === 'offline').length)

const filterChips = computed(() => [
  { key: 'all' as const, label: '全部', count: props.cars.length },
  { key: 'running' as const, label: '运行中', count: runningCount.value },
  { key: 'idle' as const, label: '空闲', count: idleCount.value },
  { key: 'offline' as const, label: '离线', count: offlineCount.value },
  { key: 'fault' as const, label: '异常', count: faultCount.value }
])

const missionByCarId = computed(() => {
  const order = (s: MissionStatus) =>
    s === 'running' ? 0 : s === 'paused' ? 1 : s === 'assigned' ? 2 : 3
  const map = new Map<string, Mission>()
  for (const m of props.missions) {
    if (!m.carId) continue
    if (m.status !== 'running' && m.status !== 'paused' && m.status !== 'assigned') continue
    const prev = map.get(m.carId)
    if (!prev || order(m.status) < order(prev.status)) {
      map.set(m.carId, m)
    }
  }
  return map
})

function missionForCar(car: Car): Mission | undefined {
  if (car.missionId) {
    const found = props.missions.find((m) => m.id === car.missionId)
    if (found) return found
  }
  return missionByCarId.value.get(car.id)
}

function batteryPct(car: Car): number {
  const raw = car.batterySoc ?? 0
  if (!raw) return 0
  const pct = raw > 1 ? raw : raw * 100
  return Math.max(0, Math.min(100, Math.round(pct)))
}

function batteryText(car: Car): string {
  const pct = batteryPct(car)
  return pct > 0 ? `${pct}%` : '—'
}

function batteryColor(p: number): string {
  if (p < 20) return '#f56c6c'
  if (p < 50) return '#e6a23c'
  return '#67c23a'
}

function batteryLevel(p: number): 'low' | 'mid' | 'high' {
  if (p < 20) return 'low'
  if (p < 50) return 'mid'
  return 'high'
}

function shortId(car: Car): string {
  if (car.rawId != null) return String(car.rawId).padStart(3, '0').slice(-3)
  const digits = car.id.replace(/\D/g, '')
  return digits ? digits.slice(-3) : car.id
}

function positionText(car: Car): string {
  if (!Number.isFinite(car.x) || !Number.isFinite(car.y)) return '-'
  return `${Math.round(car.x)}, ${Math.round(car.y)}`
}

function positionMeta(car: Car): string {
  const parts = [positionText(car)]
  if (car.siteId != null) parts.push(`站点 #${car.siteId}`)
  if (car.lstatus) parts.push(car.lstatus)
  return parts.filter((p) => p && p !== '-').join(' · ') || '—'
}

function hasAlarm(car: Car): boolean {
  return (car.alarmLevel != null && car.alarmLevel > 0) || !!car.alarmInfo || car.state === 'fault'
}

function alarmText(car: Car): string {
  if (car.alarmInfo) return car.alarmInfo
  if (car.state === 'fault') return car.lstatus || '故障'
  return '无'
}

function alarmCell(car: Car): string {
  const t = alarmText(car)
  if (t === '无') return '—'
  return t.length > 10 ? `${t.slice(0, 10)}…` : t
}

function trafficText(car: Car): string {
  return (car.trafficStatus || '—').trim() || '—'
}

function isTrafficBlocked(car: Car): boolean {
  return isTrafficCongested(trafficText(car))
}

function trafficCell(car: Car): string {
  const t = trafficText(car)
  return t.length > 14 ? `${t.slice(0, 14)}…` : t
}

function lockText(car: Car): string {
  return (car.lockPoint || '—').trim() || '—'
}

function lockCell(car: Car): string {
  const t = lockText(car)
  return t.length > 10 ? `${t.slice(0, 10)}…` : t
}

function missionCell(car: Car): string {
  const m = missionForCar(car)
  if (!m) return car.missionId ? '有任务' : '空闲'
  return missionStatusLabel(m.status)
}

function missionTitle(car: Car): string {
  const m = missionForCar(car)
  if (!m) return car.missionId ? `任务 ${car.missionId}` : '空闲'
  return `${missionStatusLabel(m.status)} · ${m.name}`
}

const filteredCars = computed(() => {
  const q = search.value.trim().toLowerCase()
  const tokens = q ? q.split(/\s+/).filter(Boolean) : []
  return props.cars.filter((c) => {
    if (props.table) {
      if (quickFilter.value === 'running' && c.state !== 'running') return false
      if (quickFilter.value === 'idle' && c.state !== 'idle') return false
      if (quickFilter.value === 'offline' && c.state !== 'offline') return false
      if (quickFilter.value === 'fault' && c.state !== 'fault') return false
    } else if (filterState.value && c.state !== filterState.value) {
      return false
    }
    if (!tokens.length) return true
    const mission = missionForCar(c)
    const hay = [
      c.id,
      c.name,
      c.typeName ?? '',
      c.group ?? '',
      c.ip ?? '',
      c.lstatus ?? '',
      c.alarmInfo ?? '',
      c.trafficStatus ?? '',
      c.lockPoint ?? '',
      c.siteId != null ? String(c.siteId) : '',
      stateLabel(c.state),
      mission?.name ?? '',
      mission ? missionStatusLabel(mission.status) : '',
      positionText(c)
    ]
      .join(' ')
      .toLowerCase()
    return tokens.every((t) => hay.includes(t))
  })
})

function onSelect(car: Car) {
  emit('select', { kind: 'vehicle', id: detailIdForCar(car), name: car.name })
}

function detailIdForCar(car: Car): string {
  if (car.rawId != null) return String(car.rawId)
  return car.id.replace(/^C/i, '').replace(/^0+/, '') || car.id
}

function carKey(car: Car): string {
  return String(car.rawId ?? car.id)
}

function rawIdOf(car: Car): number | null {
  if (car.rawId != null && Number.isFinite(car.rawId)) return car.rawId
  const n = Number(detailIdForCar(car))
  return Number.isFinite(n) && n > 0 ? n : null
}

async function onQuickAction(car: Car, action: VehicleQuickAction) {
  const rawId = rawIdOf(car)
  if (rawId == null) {
    ElMessage.warning('无法解析车辆 ID')
    return
  }
  const op = quickActions.find((x) => x.value === action)
  if (!op) return
  try {
    await ElMessageBox.confirm(
      `${op.confirm}\n目标：${car.name || shortId(car)}（#${rawId}）`,
      op.label,
      {
        type: op.danger ? 'warning' : 'info',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        distinguishCancelAndClose: true
      }
    )
  } catch {
    return
  }

  actingId.value = carKey(car)
  try {
    await executeVehicleQuickAction(rawId, action)
    ElMessage.success(`已执行「${op.label}」`)
    emit('action-done')
  } catch (err) {
    ElMessage.error(`「${op.label}」失败：${(err as Error).message}`)
  } finally {
    actingId.value = null
  }
}
</script>

<style scoped>
.vehicle-monitor {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}
.vehicle-monitor.is-compact { gap: 8px; }
.vehicle-monitor.is-table { gap: 6px; }
.vehicle-monitor.is-lite .col-vehicle { width: 36%; }
.vehicle-monitor.is-lite .col-state { width: 86px; }
.vehicle-monitor.is-lite .col-bat { width: 48px; }
.vehicle-monitor.is-lite .col-mission { width: 72px; }
.vehicle-monitor.is-lite .col-tc { width: auto; }

.vehicle-monitor.is-compact .vehicle-row {
  border-radius: 8px;
  border-color: transparent;
  background: transparent;
  padding: 8px 10px;
}
.vehicle-monitor.is-compact .vehicle-row:hover {
  background: var(--mg-veil-2);
  border-color: transparent;
}
.vehicle-monitor.is-compact .vehicle-row.is-selected {
  background: rgba(var(--mg-primary-rgb), 0.1);
  border-color: transparent;
  box-shadow: inset 3px 0 0 var(--mg-primary);
}

.overview-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  flex: none;
}
.overview-item {
  background: var(--mg-veil-1);
  border: 1px solid var(--mg-veil-border);
  border-radius: 6px;
  padding: 4px 2px;
  text-align: center;
  transition: var(--mg-transition, all 0.2s ease);
}
.overview-item:hover {
  background: rgba(var(--mg-accent-rgb, 142, 200, 252), 0.14);
  border-color: rgba(var(--mg-accent-rgb, 142, 200, 252), 0.4);
}
.overview-num {
  font-size: 15px;
  font-weight: 600;
  color: var(--mg-text-light);
  line-height: 1.2;
}
.overview-num.online { color: var(--mg-accent); }
.overview-num.running { color: var(--mg-status-success); }
.overview-num.charging { color: var(--mg-primary-hover); }
.overview-num.fault { color: var(--mg-status-danger); }
.overview-label {
  font-size: 11px;
  color: var(--mg-text-muted);
  margin-top: 2px;
}

.toolbar {
  display: flex;
  gap: 6px;
  flex: none;
}
.toolbar .search { flex: 1; min-width: 0; }
.toolbar .filter { width: 100px; flex: none; }

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: none;
}
.chip {
  appearance: none;
  border: 1px solid var(--mg-veil-border);
  background: transparent;
  color: var(--mg-text-muted);
  font-size: 11px;
  font-weight: 550;
  height: 24px;
  padding: 0 8px;
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.chip:hover {
  color: var(--mg-text-light);
  border-color: var(--mg-veil-border-hi);
}
.chip.is-active {
  background: rgba(var(--mg-primary-rgb), 0.12);
  border-color: rgba(var(--mg-primary-rgb), 0.45);
  color: var(--mg-primary);
}
.chip-n {
  font-family: var(--mg-font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.table-wrap {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--mg-veil-border);
  border-radius: 8px;
  background: #fff;
}
.dense-scroll {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
}
.dense-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  font-size: 12px;
}
.dense-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 30px;
  padding: 0 8px;
  text-align: left;
  font-size: 11px;
  font-weight: 650;
  color: var(--mg-text-muted);
  background: var(--mg-veil-1, #f6f3fb);
  border-bottom: 1px solid var(--mg-veil-border);
  white-space: nowrap;
}
.dense-row {
  cursor: pointer;
  transition: background 0.12s ease;
}
.dense-row td {
  height: 40px;
  padding: 4px 8px;
  vertical-align: middle;
  border-bottom: 1px solid rgba(40, 33, 58, 0.06);
  color: var(--mg-text-light);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dense-row:hover td {
  background: rgba(var(--mg-primary-rgb), 0.04);
}
.dense-row.is-selected td {
  background: rgba(var(--mg-primary-rgb), 0.08);
}
.dense-row.is-selected td:first-child {
  box-shadow: inset 3px 0 0 var(--mg-primary);
}
.dense-row.has-alarm td.col-alarm {
  font-weight: 650;
}
.dense-row.is-busy {
  opacity: 0.65;
  pointer-events: none;
}

.col-vehicle { width: 22%; }
.col-state { width: 88px; }
.col-bat { width: 52px; }
.col-mission { width: 72px; }
.col-alarm { width: 14%; }
.col-tc { width: 14%; }
.col-lock { width: 72px; }
.col-ops { width: 64px; text-align: right; }

.veh-cell {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.veh-id {
  font-family: var(--mg-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 750;
  color: var(--mg-text-light);
  flex: none;
}
.veh-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 550;
  color: var(--mg-text-light);
}
.veh-meta {
  margin-top: 1px;
  font-size: 10.5px;
  color: var(--mg-text-faint);
  font-family: var(--mg-font-mono);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.state-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding: 0 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 650;
  background: var(--mg-veil-1);
  color: var(--mg-text-muted);
  border: 1px solid var(--mg-veil-border);
}
.state-pill.pill-running {
  color: var(--mg-status-success);
  background: color-mix(in srgb, var(--mg-status-success) 12%, #fff);
  border-color: color-mix(in srgb, var(--mg-status-success) 28%, transparent);
}
.state-pill.pill-fault {
  color: var(--mg-status-danger);
  background: color-mix(in srgb, var(--mg-status-danger) 10%, #fff);
  border-color: color-mix(in srgb, var(--mg-status-danger) 28%, transparent);
}
.state-pill.pill-offline {
  color: var(--mg-text-faint);
}
.state-pill.pill-charging {
  color: var(--mg-primary);
  background: rgba(var(--mg-primary-rgb), 0.08);
  border-color: rgba(var(--mg-primary-rgb), 0.28);
}
.state-pill.pill-paused {
  color: var(--mg-status-warning);
  background: color-mix(in srgb, var(--mg-status-warning) 12%, #fff);
}

.ops-btn {
  appearance: none;
  height: 24px;
  padding: 0 8px;
  border-radius: 6px;
  border: 1px solid rgba(var(--mg-primary-rgb), 0.35);
  background: rgba(var(--mg-primary-rgb), 0.08);
  color: var(--mg-primary);
  font-size: 11px;
  font-weight: 650;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 1px;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.ops-btn:hover:not(:disabled) {
  background: rgba(var(--mg-primary-rgb), 0.14);
  border-color: rgba(var(--mg-primary-rgb), 0.55);
}
.ops-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.ops-caret { font-size: 11px; margin-left: 1px; }

.col-bat,
.col-mission,
.col-alarm,
.col-tc,
.col-lock {
  font-variant-numeric: tabular-nums;
}
.col-bat.low,
.col-alarm.warn,
.col-tc.warn { color: var(--mg-status-danger); font-weight: 650; }
.col-bat.mid { color: var(--mg-status-warning); font-weight: 650; }
.col-bat.high { color: var(--mg-status-success); font-weight: 650; }
.col-mission.muted { color: var(--mg-text-faint); }
.mono {
  font-family: var(--mg-font-mono);
  font-variant-numeric: tabular-nums;
}

:deep(.is-danger-item) {
  color: var(--mg-status-danger) !important;
}
.state-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex: none;
  background: currentColor;
}
.state-dot.dot-running,
.dot.dot-running { color: var(--mg-status-success); background: var(--mg-status-success); }
.state-dot.dot-idle,
.dot.dot-idle { color: var(--mg-status-info); background: var(--mg-status-info); }
.state-dot.dot-offline,
.dot.dot-offline { color: var(--mg-text-faint); background: var(--mg-text-faint); }
.state-dot.dot-fault,
.dot.dot-fault { color: var(--mg-status-danger); background: var(--mg-status-danger); }
.state-dot.dot-charging,
.dot.dot-charging { color: var(--mg-primary); background: var(--mg-primary); }
.state-dot.dot-paused,
.dot.dot-paused { color: var(--mg-status-warning); background: var(--mg-status-warning); }

.vehicle-list {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-right: 2px;
}

.vehicle-row {
  background: var(--mg-veil-1);
  border: 1px solid var(--mg-veil-border);
  border-radius: 4px;
  padding: 4px 6px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: none;
  transition: all 0.18s ease;
}
.vehicle-row:hover {
  background: rgba(var(--mg-accent-rgb, 142, 200, 252), 0.12);
  border-color: rgba(var(--mg-accent-rgb, 142, 200, 252), 0.35);
}
.vehicle-row.is-selected {
  background: rgba(109, 40, 217, 0.32);
  border-color: rgba(167, 139, 250, 0.75);
  box-shadow: inset 3px 0 0 rgba(196, 181, 253, 0.95);
}

.vehicle-head {
  display: flex;
  align-items: center;
  gap: 6px;
}
.vid {
  font-size: 10.5px;
  color: var(--mg-text-muted);
  font-family: ui-monospace, 'SFMono-Regular', 'Menlo', monospace;
  flex: none;
}
.vname {
  flex: 1;
  min-width: 0;
  color: var(--mg-text-light);
  font-weight: 600;
  font-size: 11.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.state-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
}
.dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.dot-running { color: #6fcd45; }
.dot-charging { color: var(--mg-primary-hover); }
.dot-paused { color: #e6a23c; }
.dot-fault { color: #ff7396; }
.dot-offline { color: var(--mg-text-faint); }
.dot-idle { color: var(--mg-accent); }

.vehicle-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
}
.battery-mini {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 44%;
  min-width: 0;
}
.mission-mini {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.battery-bar {
  flex: 1;
  min-width: 0;
}
.battery-bar :deep(.el-progress-bar__outer) {
  background: var(--mg-veil-3);
}
.battery-text {
  width: 34px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 11.5px;
  flex: none;
}
.battery-text.low { color: var(--mg-status-danger); }
.battery-text.mid { color: var(--mg-status-warning); }
.battery-text.high { color: var(--mg-status-success); }

.mission-name {
  flex: 1;
  min-width: 0;
  color: var(--mg-text-light);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mission-name.muted { color: var(--mg-text-dim); }
.mission-tag { flex: none; }

.empty {
  text-align: center;
  padding: 24px 0;
  font-size: 12px;
}
.muted { color: var(--mg-text-muted); }
</style>
