<template>
  <div class="app-container gis-page">
    <div class="gis-layout">
      <!-- Left: Map Area (85%) -->
      <div class="map-area">
        <div class="search-bar">
          <el-input v-model="searchName" placeholder="站点名称" clearable size="small" class="search-input" />
          <el-input v-model="searchCity" placeholder="行政区划" clearable size="small" class="search-input" />
          <el-select v-model="searchType" placeholder="工程类型" clearable size="small" class="search-select">
            <el-option label="全部" value="" />
            <el-option label="水库" value="B" />
            <el-option label="堤防" value="D" />
            <el-option label="水闸" value="K" />
            <el-option label="泵站" value="4" />
          </el-select>
        </div>
        <div class="map-header">
          <span class="map-title">
            <el-icon style="margin-right:6px"><Location /></el-icon>
            GIS工程地图
          </span>
          <div class="map-header-actions">
            <span class="coord-display" v-if="coord">
              经度: {{ coord.lng.toFixed(6) }} &nbsp;&nbsp; 纬度: {{ coord.lat.toFixed(6) }}
            </span>
            <el-button size="small" @click="$router.push('/slgc/gis/water')">水质水文监测</el-button>
            <el-button size="small" icon="Refresh" @click="refreshMap">刷新</el-button>
          </div>
        </div>
        <div class="map-wrapper" v-loading="loading" element-loading-text="工程数据加载中...">
          <div ref="mapRef" id="viewDiv" class="map-container"></div>
          <!-- Map Legend Overlay -->
          <div class="map-legend" v-show="showEng">
            <div class="legend-title">流域图例</div>
            <div v-for="z in zoneList" :key="z.value" class="legend-item">
              <span class="legend-dot" :style="{ background: z.color }"></span>
              <span class="legend-label">{{ z.label }}</span>
            </div>
          </div>
          <!-- Coordinate bar overlay -->
          <div class="coord-bar" v-if="coord">
            经度: {{ coord.lng.toFixed(6) }} &nbsp;|&nbsp; 纬度: {{ coord.lat.toFixed(6) }}
          </div>
        </div>
      </div>

      <!-- Right: Side Panel (15%) -->
      <div class="side-panel">
        <!-- Layer Controls -->
        <div class="panel-section layer-section">
          <div class="panel-title">
            <el-icon style="margin-right:4px"><Folder /></el-icon>
            流域图层
          </div>
          <div class="zone-list">
            <div v-for="z in zoneList" :key="z.value" class="zone-item">
              <el-checkbox v-model="z.visible" @change="onZoneChange">
                <span class="zone-label-text">
                  <span class="zone-dot" :style="{ background: z.color }"></span>
                  {{ z.label }}
                </span>
              </el-checkbox>
            </div>
          </div>
          <el-divider style="margin:6px 0" />
          <div class="toggle-list">
            <div class="toggle-item">
              <el-checkbox v-model="showEng" @change="onToggleEng">工程标记</el-checkbox>
            </div>
            <div class="toggle-item">
              <el-checkbox v-model="showWind" @change="onToggleWind">风情数据</el-checkbox>
            </div>
            <div class="toggle-item">
              <el-checkbox v-model="showTyphoon" @change="onToggleTyphoon">台风路径</el-checkbox>
            </div>
          </div>
        </div>

        <!-- Data Table -->
        <div class="panel-section table-section">
          <div class="panel-title">
            <el-icon style="margin-right:4px"><List /></el-icon>
            工程列表
            <el-tag size="small" type="info" style="margin-left:4px">{{ filteredTableData.length }}</el-tag>
          </div>
          <el-table
            ref="tableRef"
            :data="filteredTableData"
            stripe
            size="small"
            :height="tableHeight"
            highlight-current-row
            @row-click="onTableRowClick"
          >
            <el-table-column prop="name" label="名称" min-width="80" show-overflow-tooltip />
            <el-table-column prop="typeLabel" label="类型" width="50" />
            <el-table-column prop="zoneLabel" label="流域" width="55" show-overflow-tooltip />
            <el-table-column label="状态" width="60">
              <template #default="scope">
                <el-tag :type="scope.row.status === '正常' ? 'success' : 'danger'" size="small">
                  {{ scope.row.status }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </div>

    <!-- Floating error alert -->
    <el-alert
      v-if="errorMsg"
      :title="errorMsg"
      type="error"
      show-icon
      closable
      @close="errorMsg = ''"
      class="error-floating"
    />

    <!-- Detail Dialog -->
    <el-dialog v-model="detailDialogVisible" width="900px" append-to-body destroy-on-close @close="onDetailClose">
      <el-tabs v-model="detailTab" stretch>
        <el-tab-pane label="基本信息" name="basic">
          <el-descriptions :column="2" border>
            <el-descriptions-item v-for="f in basicFields" :key="f.label" :label="f.label" :span="f.span || 1">
              {{ getFieldValue(currentMarker, f) }}
            </el-descriptions-item>
          </el-descriptions>
        </el-tab-pane>
        <el-tab-pane label="三维信息" name="3d">
          <iframe :src="iframeSrc" :key="currentMarker?.name" width="100%" height="500" frameborder="0" allowfullscreen />
        </el-tab-pane>
      </el-tabs>
    </el-dialog>
  </div>
</template>

<script setup name="Gis">
import { ElMessageBox } from 'element-plus'
import { Location, Folder, List } from '@element-plus/icons-vue'
import { getDikeList, getReservoirList, getPustList, getWagaList } from '@/api/slgc/gc/index'
import { getWindList } from '@/api/slgc/wind/index'
import { getTyphoonInfoList } from '@/api/slgc/typhoon/index'
import { useArcGisMap } from '@/composables/useArcGisMap'

const { map, view, coord, initMap, ensureModules, createGraphicsLayer, createPointMarker, createCircleSymbol, destroy, addBasinBoundary } = useArcGisMap()

const mapRef = ref(null)
const tableRef = ref(null)
const loading = ref(false)
const errorMsg = ref('')

const showEng = ref(true)
const showWind = ref(false)
const showTyphoon = ref(false)

let engLayer = null
let windLayer = null
let typhoonLayer = null

const allMarkers = ref([])

const typeMap = { B: '水库', D: '堤防', K: '水闸', '4': '泵站' }

const zoneList = reactive([
  { value: 'tph', label: '太浦河', color: '#409EFF', visible: true },
  { value: 'wyh', label: '望虞河', color: '#67C23A', visible: true },
  { value: 'hh',   label: '环湖',   color: '#E6A23C', visible: true },
  { value: 'yj',   label: '沿江',   color: '#F56C6C', visible: true },
  { value: 'hzw',  label: '杭州湾', color: '#9B59B6', visible: true },
  { value: 'sk',   label: '水库',   color: '#1ABC9C', visible: true },
])

const searchName = ref('')
const searchCity = ref('')
const searchType = ref('')

const detailDialogVisible = ref(false)
const currentMarker = ref(null)
const detailTab = ref('basic')

function assignZone(lng, lat) {
  if (lng > 120.5 && lng < 120.9 && lat > 30.8 && lat < 31.2) return 'tph'
  if (lng > 120.3 && lng < 120.7 && lat > 31.3 && lat < 31.7) return 'wyh'
  if (lng > 119.8 && lng < 120.5 && lat > 30.9 && lat < 31.3) return 'hh'
  if (lat > 31.6 && lng > 120.0) return 'yj'
  if (lat < 31.0 && lng > 121.0) return 'hzw'
  return 'sk'
}

function getZoneLabel(val) {
  return zoneList.find(z => z.value === val)?.label || val
}

function getZoneColor(val) {
  return zoneList.find(z => z.value === val)?.color || '#999'
}

const visibleZoneValues = computed(() =>
  zoneList.filter(z => z.visible).map(z => z.value)
)

const filteredMarkers = computed(() => {
  const zones = visibleZoneValues.value
  return allMarkers.value.filter(m => {
    if (!zones.includes(m.zone)) return false
    if (searchName.value && !(m.name || '').includes(searchName.value)) return false
    if (searchCity.value && !(m.city || '').includes(searchCity.value)) return false
    if (searchType.value && m.type !== searchType.value) return false
    return true
  })
})

const filteredTableData = computed(() => {
  if (!showEng.value) return []
  return filteredMarkers.value.map(m => ({
    ...m,
    typeLabel: typeMap[m.type] || m.type,
    zoneLabel: getZoneLabel(m.zone),
  }))
})

const tableHeight = computed(() => `calc(100vh - 480px)`)

const iframeSrc = computed(() => {
  if (!currentMarker.value || !currentMarker.value.name) return ''
  return `http://10.8.3.61/XingShi/DanZhanUI.htm?NAME=${encodeURIComponent(currentMarker.value.name)}`
})

function getFieldValue(marker, field) {
  if (!marker) return '-'
  const raw = marker.raw || {}
  for (const key of field.keys) {
    const val = raw[key]
    if (val !== undefined && val !== null && val !== '') {
      const str = String(val)
      return field.transform ? field.transform(str, marker) : str
    }
  }
  for (const key of field.keys) {
    const val = marker[key]
    if (val !== undefined && val !== null && val !== '') {
      const str = String(val)
      return field.transform ? field.transform(str, marker) : str
    }
  }
  return '-'
}

const basicFields = [
  { label: '站名', keys: ['name'] },
  { label: '行政区划名称', keys: ['region', 'city', '行政区划名称', 'REGION', 'adminDiv', 'ADMIN_DIV', 'area', 'district'] },
  { label: '类型', keys: ['type'], transform: (v, m) => typeMap[v] || v },
  { label: '工程类型', keys: ['engType', '工程类型', 'ENG_TYPE', 'projectType'] },
  { label: '来源', keys: ['source', '来源', 'SOURCE', 'origin'] },
  { label: '工程位置河道', keys: ['river', '工程位置河道', 'RIVER', 'channel', 'CHANNEL', 'waterway'] },
  { label: '地点', keys: ['location', '地点', 'LOCATION', 'address', 'ADDRESS', 'addr', 'site'] },
  { label: '东西岸', keys: ['bankEW', '东西岸', 'BANK_EW', 'eastWest', 'shoreEW', 'bank'] },
  { label: '南北岸', keys: ['bankNS', '南北岸', 'BANK_NS', 'northSouth', 'shoreNS'] },
  { label: '河道现状', keys: ['riverStatus', '河道现状', 'RIVER_STATUS', 'channelStatus', 'waterStatus'] },
  { label: '工程形式', keys: ['engForm', '工程形式', 'ENG_FORM', 'structure', 'STRUCTURE', 'form'] },
  { label: '闸孔数/泵台数', keys: ['gateNum', '闸孔数', 'GATE_NUM', 'pumpNum', '泵台数', 'gateCount', 'pumpCount', 'holeCount'] },
  { label: '单孔宽/单泵流量', keys: ['gateWidth', '单孔宽', 'GATE_WIDTH', 'pumpFlow', '单泵流量', 'singleWidth', 'singleFlow', 'holeWidth'] },
  { label: '启闭机型式', keys: ['gateType', '启闭机型式', 'GATE_TYPE', 'hoistType', 'liftType', 'openType'] },
  { label: '闸顶高程', keys: ['gateTopElev', '闸顶高程', 'GATE_TOP_ELEV', 'topElev', 'topElevation', 'crestElev'] },
  { label: '闸底高程', keys: ['gateBottomElev', '闸底高程', 'GATE_BOTTOM_ELEV', 'bottomElev', 'bottomElevation', 'baseElev'] },
  { label: '设计流量', keys: ['designFlow', '设计流量', 'DESIGN_FLOW', 'designedFlow', 'discharge'] },
  { label: '现场管理单位', keys: ['mgmtUnit', '现场管理单位', 'MGMT_UNIT', 'manageUnit', 'siteManager', 'manager'] },
  { label: '联系电话', keys: ['phone', '联系电话', 'PHONE', 'contact', 'mobile', 'MOBILE', 'tel', 'TEL', 'telephone'] },
  { label: '主管单位', keys: ['supervisor', '主管单位', 'SUPERVISOR', 'dept', 'DEPT', 'department', 'competentDept', 'org'] },
]

function extractCity(r) {
  return r.region || r.city || r.行政区划名称 || r.REGION || r.adminDiv || r.ADMIN_DIV || r.area || r.district || ''
}

const loadedModules = {}

async function getModule(path) {
  if (loadedModules[path]) return loadedModules[path]
  await ensureModules()
  return new Promise(resolve => {
    window.require([path], m => {
      loadedModules[path] = m
      resolve(m)
    })
  })
}

function getVisibleMarkers() {
  return filteredMarkers.value
}

function loadEngData() {
  if (!showEng.value) {
    if (engLayer) engLayer.visible = false
    return
  }
  loading.value = true
  errorMsg.value = ''
  Promise.all([
    getReservoirList({ pageSize: 9999 }),
    getDikeList({ pageSize: 9999 }),
    getPustList({ pageSize: 9999 }),
    getWagaList({ pageSize: 9999 }),
  ])
    .then(([reservoir, dike, pust, waga]) => {
      const markers = []
      ;(reservoir.rows || []).forEach(r => {
        if (r.resCode) {
          const lng = Number(r.upRightLong || r.lowLeftLong || 0)
          const lat = Number(r.upRightLat || r.lowLeftLat || 0)
          markers.push({
            code: r.resCode,
            name: r.resName,
            type: 'B',
            lng, lat,
            status: r.engStat === '1' ? '正常' : '停用',
            zone: assignZone(lng, lat),
            city: extractCity(r),
            raw: r,
          })
        }
      })
      ;(dike.rows || []).forEach(r => {
        if (r.dikeCode) {
          const lng = Number(r.startLong || r.endLong || 0)
          const lat = Number(r.startLat || r.endLat || 0)
          markers.push({
            code: r.dikeCode,
            name: r.dikeName,
            type: 'D',
            lng, lat,
            status: r.engStat === '1' ? '正常' : '停用',
            zone: assignZone(lng, lat),
            city: extractCity(r),
            raw: r,
          })
        }
      })
      ;(pust.rows || []).forEach(r => {
        if (r.pustCode) {
          const lng = Number(r.pustLong || 0)
          const lat = Number(r.pustLat || 0)
          markers.push({
            code: r.pustCode,
            name: r.pustName,
            type: 'K',
            lng, lat,
            status: r.engStat === '1' ? '正常' : '停用',
            zone: assignZone(lng, lat),
            city: extractCity(r),
            raw: r,
          })
        }
      })
      ;(waga.rows || []).forEach(r => {
        if (r.wagaCode) {
          const lng = Number(r.startLong || r.endLong || 0)
          const lat = Number(r.startLat || r.endLat || 0)
          markers.push({
            code: r.wagaCode,
            name: r.wagaName,
            type: '4',
            lng, lat,
            status: r.engStat === '1' ? '正常' : '停用',
            zone: assignZone(lng, lat),
            city: extractCity(r),
            raw: r,
          })
        }
      })

      allMarkers.value = markers.filter(m => m.lng && m.lat)
      renderEngMarkers()
    })
    .catch(err => {
      errorMsg.value = '工程数据加载失败：' + (err.message || '未知错误')
    })
    .finally(() => {
      loading.value = false
    })
}

function renderEngMarkers() {
  if (!engLayer || !showEng.value) return
  engLayer.removeAll()
  const data = getVisibleMarkers()
  if (!data.length) return
  data.forEach(m => {
    const color = getZoneColor(m.zone)
    const symbol = createCircleSymbol(color, 14)
    const graphic = createPointMarker(m.lat, m.lng, symbol, m)
    engLayer.add(graphic)
  })
}

function loadWind() {
  if (!showWind.value) {
    if (windLayer) windLayer.visible = false
    return
  }
  getWindList()
    .then(res => {
      const data = res.data || res.rows || []
      if (windLayer) windLayer.removeAll()
      if (!data.length) return
      data.forEach((d, i) => {
        const lng = d.lng ? Number(d.lng) : 119.3 + (i % 10) * 0.2
        const lat = d.lat ? Number(d.lat) : 31.3 + Math.sin(i) * 0.5
        const speed = parseFloat(d.WNDV) || 0
        const color = speed > 10 ? '#F56C6C' : speed > 5 ? '#E6A23C' : '#67C23A'
        const symbol = createCircleSymbol(color, (5 + Math.min(speed, 12)) * 2)
        const graphic = createPointMarker(lat, lng, symbol, d)
        const stnm = d.STNM || '站' + i
        graphic.popupTemplate = {
          title: stnm,
          content: `风速: ${d.WNDV || '-'} m/s<br/>风力: ${d.WNDPWR || '-'}<br/>平均风速: ${d.AVGWNDV || '-'}<br/>时间: ${d.TM || '-'}<br/><div style="margin-top:8px;border-top:1px solid #eee;padding-top:6px;text-align:right"><a href="javascript:void(0)" style="color:#409EFF;font-size:12px;text-decoration:none" onclick="window.open('/slgc/hydrology?stnm=${encodeURIComponent(stnm)}', '_blank')">查看历史图表 &gt;</a></div>`,
        }
        windLayer.add(graphic)
      })
    })
    .catch(() => {
      errorMsg.value = '风情数据加载失败'
    })
}

function loadTyphoon() {
  if (!showTyphoon.value) {
    if (typhoonLayer) typhoonLayer.visible = false
    return
  }
  getTyphoonInfoList({ year: new Date().getFullYear() })
    .then(async res => {
      const data = res.data || res.rows || []
      const list = Array.isArray(data) ? data : []
      if (typhoonLayer) typhoonLayer.removeAll()
      if (!list.length) return

      const TextSymbol = await getModule('esri/symbols/TextSymbol')
      const Polyline = await getModule('esri/geometry/Polyline')
      const SimpleLineSymbol = await getModule('esri/symbols/SimpleLineSymbol')
      const Graphic = await getModule('esri/Graphic')
      const Point = await getModule('esri/geometry/Point')
      const SpatialReference = await getModule('esri/geometry/SpatialReference')

      list.slice(0, 5).forEach((t, i) => {
        const baseLng = 124 + i * 4
        const baseLat = 28 - i * 2.5

        const textSymbol = new TextSymbol({
          text: '\u{1F300}',
          color: [245, 108, 108],
          fontSize: 22,
          fontWeight: 'bold',
          fontFamily: 'sans-serif',
        })
        const point = new Point({
          longitude: baseLng,
          latitude: baseLat,
          spatialReference: new SpatialReference({ wkid: 4490 }),
        })
        const markerGraphic = new Graphic({
          geometry: point,
          symbol: textSymbol,
          attributes: { name: t.TFNAME || '台风' + (i + 1) },
        })
        markerGraphic.popupTemplate = {
          title: t.TFNAME || '台风' + (i + 1),
          content: `编号: ${t.TFID || '-'}<br/>开始: ${t.STRTIME || '-'}<br/>结束: ${t.ENDTIME || '-'}`,
        }
        typhoonLayer.add(markerGraphic)

        const paths = [
          [baseLng - 1.5, baseLat - 1.5],
          [baseLng - 0.5, baseLat - 0.5],
          [baseLng, baseLat],
          [baseLng + 0.8, baseLat + 0.8],
          [baseLng + 1.5, baseLat + 1.5],
        ]
        const polyline = new Polyline({
          paths: [paths],
          spatialReference: new SpatialReference({ wkid: 4490 }),
        })
        const lineSymbol = new SimpleLineSymbol({
          color: [245, 108, 108],
          width: 2,
          style: 'dash',
          cap: 'round',
          join: 'round',
        })
        const lineGraphic = new Graphic({ geometry: polyline, symbol: lineSymbol })
        typhoonLayer.add(lineGraphic)
      })
    })
    .catch(() => {
      errorMsg.value = '台风数据加载失败'
    })
}

function onToggleEng() {
  if (!engLayer) return
  if (showEng.value) {
    engLayer.visible = true
    renderEngMarkers()
  } else {
    engLayer.removeAll()
    engLayer.visible = false
  }
}

function onZoneChange() {
  renderEngMarkers()
}

function onToggleWind() {
  if (!windLayer) return
  if (showWind.value) {
    windLayer.visible = true
    loadWind()
  } else {
    windLayer.removeAll()
    windLayer.visible = false
  }
}

function onToggleTyphoon() {
  if (!typhoonLayer) return
  if (showTyphoon.value) {
    typhoonLayer.visible = true
    loadTyphoon()
  } else {
    typhoonLayer.removeAll()
    typhoonLayer.visible = false
  }
}

function onTableRowClick(row) {
  if (!view.value || !row.lng || !row.lat) return
  view.value.goTo({ center: [row.lng, row.lat], zoom: 12 })
  currentMarker.value = row
  detailDialogVisible.value = true
  detailTab.value = 'basic'
}

function onDetailClose() {
  currentMarker.value = null
}

watch([searchName, searchCity, searchType], () => {
  if (showEng.value) renderEngMarkers()
})

async function initGisMap() {
  await initMap('viewDiv', [120.5, 31.2], 8)
  await addBasinBoundary()
  engLayer = createGraphicsLayer('eng-layer')
  windLayer = createGraphicsLayer('wind-layer')
  typhoonLayer = createGraphicsLayer('typhoon-layer')
  map.value.add(engLayer)
  map.value.add(windLayer)
  map.value.add(typhoonLayer)
  windLayer.visible = false
  typhoonLayer.visible = false

  view.value.on('click', function(event) {
    view.value.hitTest(event).then(function(response) {
      const result = response.results.find(r => r.graphic && r.graphic.attributes && r.graphic.attributes.type)
      if (result) {
        const attrs = result.graphic.attributes
        currentMarker.value = attrs
        detailDialogVisible.value = true
        detailTab.value = 'basic'
      }
    })
  })

  loadEngData()
}

function refreshMap() {
  destroy()
  engLayer = null
  windLayer = null
  typhoonLayer = null
  coord.value = null
  errorMsg.value = ''
  initGisMap()
}

onMounted(() => initGisMap())
</script>

<style scoped>
.gis-page {
  height: calc(100vh - 120px);
  overflow: hidden;
}

.gis-layout {
  display: flex;
  height: 100%;
  gap: 6px;
}

/* ---- Search Bar ---- */
.search-bar {
  display: flex;
  gap: 8px;
  padding: 8px 14px;
  border-bottom: 1px solid #e4e7ed;
  flex-shrink: 0;
  align-items: center;
  background: #fafafa;
}

.search-input {
  width: 160px;
}

.search-select {
  width: 140px;
}

/* ---- Left Map Area ---- */
.map-area {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #e4e7ed;
}

.map-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 14px;
  border-bottom: 1px solid #e4e7ed;
  flex-shrink: 0;
}

.map-title {
  font-weight: 600;
  font-size: 15px;
  display: flex;
  align-items: center;
}

.map-header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.coord-display {
  font-size: 12px;
  color: #909399;
  font-family: 'Courier New', monospace;
}

.map-wrapper {
  flex: 1;
  position: relative;
  min-height: 300px;
}

.map-container {
  position: absolute;
  inset: 0;
}

/* Map Legend */
.map-legend {
  position: absolute;
  bottom: 36px;
  right: 12px;
  background: rgba(255, 255, 255, 0.94);
  border-radius: 6px;
  padding: 8px 12px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  z-index: 1000;
  min-width: 90px;
}

.legend-title {
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
  color: #303133;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  font-size: 11px;
  color: #606266;
}

.legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.1);
  flex-shrink: 0;
}

.legend-label {
  white-space: nowrap;
}

/* Coordinate bar */
.coord-bar {
  position: absolute;
  bottom: 4px;
  left: 4px;
  background: rgba(255, 255, 255, 0.9);
  padding: 2px 10px;
  border-radius: 4px;
  font-size: 11px;
  color: #909399;
  font-family: 'Courier New', monospace;
  z-index: 1000;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

/* ---- Right Side Panel ---- */
.side-panel {
  width: 280px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.panel-section {
  background: #fff;
  border-radius: 6px;
  border: 1px solid #e4e7ed;
  overflow: hidden;
}

.layer-section {
  flex-shrink: 0;
  padding: 10px 12px;
}

.table-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 10px 12px;
}

.panel-title {
  font-weight: 600;
  font-size: 14px;
  color: #303133;
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

/* Zone checkboxes */
.zone-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 4px;
}

.zone-item {
  padding: 2px 0;
}

.zone-label-text {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
}

.zone-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.08);
  flex-shrink: 0;
}

/* Toggle checkboxes */
.toggle-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.toggle-item {
  padding: 2px 0;
}

.toggle-item .el-checkbox {
  font-size: 13px;
}

/* Table section */
.table-section {
  overflow: hidden;
}

.table-section .panel-title {
  margin-bottom: 6px;
  flex-shrink: 0;
}

.table-section :deep(.el-table) {
  flex: 1;
}

.table-section :deep(.el-table th.el-table__cell) {
  padding: 4px 0;
  font-size: 12px;
}

.table-section :deep(.el-table td.el-table__cell) {
  padding: 3px 0;
  font-size: 12px;
}

/* Floating error */
.error-floating {
  position: fixed;
  top: 60px;
  right: 20px;
  z-index: 9999;
  max-width: 400px;
}
</style>
