<!--燃气隐患一张图-->
<template>
  <div class="hazard-gis-dashboard">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <el-icon><Warning /></el-icon>
        <span class="title">隐患点GIS一张图</span>
        <div class="stats-badge">
          <span class="stat-item critical"><i class="dot critical-dot"></i>重大隐患 {{ criticalCount }}</span>
          <span class="stat-item major"><i class="dot major-dot"></i>较大隐患 {{ majorCount }}</span>
          <span class="stat-item general"><i class="dot general-dot"></i>一般隐患 {{ generalCount }}</span>
        </div>
      </div>
      <div class="header-right">
        <el-input
            v-model="searchKeyword"
            placeholder="搜索隐患点名称/地址"
            clearable
            :prefix-icon="Search"
            style="width: 240px"
            size="default"
        />
        <el-select v-model="levelFilter" placeholder="隐患级别" clearable style="width: 120px" size="default">
          <el-option label="重大隐患" value="critical" />
          <el-option label="较大隐患" value="major" />
          <el-option label="一般隐患" value="general" />
        </el-select>
        <el-button type="primary" :icon="Refresh" @click="refreshMap">刷新</el-button>
        <el-button :icon="FullScreen" @click="fitBounds">全图</el-button>
      </div>
    </div>

    <!-- 主内容区：左侧隐患列表 + 右侧GIS地图 -->
    <div class="main-layout">
      <!-- 左侧隐患列表 -->
      <div class="hazard-list-panel">
        <div class="list-header">
          <span><el-icon><List /></el-icon> 隐患点列表</span>
          <el-radio-group v-model="listFilter" size="small">
            <el-radio-button label="all">全部</el-radio-button>
            <el-radio-button label="unresolved">未整改</el-radio-button>
            <el-radio-button label="resolved">已整改</el-radio-button>
          </el-radio-group>
        </div>
        <div class="hazard-list">
          <div
              v-for="hazard in paginatedHazards"
              :key="hazard.id"
              class="hazard-item"
              :class="{
              selected: selectedHazard?.id === hazard.id,
              critical: hazard.level === 'critical',
              major: hazard.level === 'major'
            }"
              @click="selectHazard(hazard)"
          >
            <div class="hazard-header">
              <span class="hazard-name">{{ hazard.name }}</span>
              <el-tag :type="getLevelType(hazard.level)" size="small">{{ getLevelText(hazard.level) }}</el-tag>
            </div>
            <div class="hazard-location">
              <el-icon><Location /></el-icon> {{ hazard.locationShort }}
            </div>
            <div class="hazard-desc">{{ hazard.description }}</div>
            <div class="hazard-status">
              <el-tag :type="hazard.status === 'unresolved' ? 'danger' : 'success'" size="small">
                {{ hazard.status === 'unresolved' ? '未整改' : '已整改' }}
              </el-tag>
            </div>
          </div>
        </div>
        <div class="pagination-area">
          <el-pagination
              small
              layout="prev, pager, next"
              :total="filteredHazards.length"
              :page-size="pageSize"
              v-model:current-page="currentPage"
          />
        </div>
      </div>

      <!-- 右侧GIS地图区域 -->
      <div class="gis-container">
        <div class="map-toolbar">
          <el-button-group>
            <el-button size="small" :icon="ZoomIn" @click="zoomIn">放大</el-button>
            <el-button size="small" :icon="ZoomOut" @click="zoomOut">缩小</el-button>
            <el-button size="small" :icon="Location" @click="fitBounds">重置视图</el-button>
          </el-button-group>
          <div class="coordinate-info">
            <span>隐患点总数: {{ filteredHazards.length }}</span>
            <span class="coords">当前坐标: {{ currentLng.toFixed(4) }}, {{ currentLat.toFixed(4) }}</span>
          </div>
        </div>
        <div class="map-wrapper" ref="mapContainer">
          <canvas id="hazardMapCanvas" ref="canvasRef" @click="onMapClick" @mousemove="updateCoordinates"></canvas>
          <!-- 悬浮信息卡 -->
          <div v-if="hoverHazard" class="hover-card" :style="{ top: hoverY + 'px', left: hoverX + 'px' }">
            <div class="hover-title">{{ hoverHazard.name }}</div>
            <div>级别: {{ getLevelText(hoverHazard.level) }}</div>
            <div>类型: {{ hoverHazard.type }}</div>
            <div>状态: {{ hoverHazard.status === 'unresolved' ? '未整改' : '已整改' }}</div>
          </div>
        </div>

        <!-- 隐患详情侧边栏 -->
        <el-drawer v-model="detailDrawerVisible" :title="`隐患详情 - ${currentHazard?.name}`" size="480px" direction="rtl">
          <div v-if="currentHazard" class="hazard-detail">
            <!-- 基本信息 -->
            <el-descriptions :column="1" border>
              <el-descriptions-item label="隐患名称">{{ currentHazard.name }}</el-descriptions-item>
              <el-descriptions-item label="隐患编号">{{ currentHazard.code }}</el-descriptions-item>
              <el-descriptions-item label="隐患级别">
                <el-tag :type="getLevelType(currentHazard.level)">{{ getLevelText(currentHazard.level) }}</el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="隐患类型">{{ currentHazard.type }}</el-descriptions-item>
              <el-descriptions-item label="隐患描述">{{ currentHazard.description }}</el-descriptions-item>
              <el-descriptions-item label="详细地址">{{ currentHazard.address }}</el-descriptions-item>
              <el-descriptions-item label="经纬度">{{ currentHazard.lng }}, {{ currentHazard.lat }}</el-descriptions-item>
              <el-descriptions-item label="发现时间">{{ currentHazard.discoverTime }}</el-descriptions-item>
              <el-descriptions-item label="责任单位">{{ currentHazard.responsibleUnit }}</el-descriptions-item>
              <el-descriptions-item label="整改状态">
                <el-tag :type="currentHazard.status === 'unresolved' ? 'danger' : 'success'">
                  {{ currentHazard.status === 'unresolved' ? '未整改' : '已整改' }}
                </el-tag>
              </el-descriptions-item>
              <el-descriptions-item v-if="currentHazard.status === 'resolved'" label="整改时间">{{ currentHazard.resolveTime }}</el-descriptions-item>
            </el-descriptions>

            <!-- 周边环境分布 -->
            <div class="surrounding-section">
              <div class="section-title">
                <span><el-icon><OfficeBuilding /></el-icon> 周边环境分布</span>
                <el-button size="small" link @click="viewSurroundingMap">查看地图分布</el-button>
              </div>
              <div class="surrounding-stats">
                <div class="stat-item"><span class="label">居民区:</span> {{ currentHazard.surrounding?.residential || 0 }}个</div>
                <div class="stat-item"><span class="label">商业区:</span> {{ currentHazard.surrounding?.commercial || 0 }}个</div>
                <div class="stat-item"><span class="label">学校/医院:</span> {{ currentHazard.surrounding?.public || 0 }}个</div>
                <div class="stat-item"><span class="label">交通干道:</span> {{ currentHazard.surrounding?.road || 0 }}条</div>
              </div>
              <div class="nearby-hazards" v-if="currentHazard.nearbyHazards?.length">
                <div class="sub-title">周边隐患点 (500m内)</div>
                <div class="nearby-list">
                  <div v-for="nearby in currentHazard.nearbyHazards" :key="nearby.id" class="nearby-item">
                    <span class="nearby-name">{{ nearby.name }}</span>
                    <el-tag :type="getLevelType(nearby.level)" size="small">{{ getLevelText(nearby.level) }}</el-tag>
                    <span class="nearby-dist">约{{ nearby.distance }}m</span>
                  </div>
                </div>
              </div>
            </div>

            <!-- 处置记录 -->
            <div class="history-section" v-if="currentHazard.records?.length">
              <div class="section-title"><el-icon><Document /></el-icon> 处置记录</div>
              <el-timeline>
                <el-timeline-item v-for="record in currentHazard.records" :key="record.id" :timestamp="record.time" :type="record.type">
                  {{ record.content }}
                </el-timeline-item>
              </el-timeline>
            </div>
          </div>
        </el-drawer>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
import { Warning, Search, Refresh, FullScreen, List, Location, ZoomIn, ZoomOut, OfficeBuilding, Document } from '@element-plus/icons-vue'

// 模拟隐患点数据
const hazardPoints = ref([
  {
    id: 1, code: 'HZ-001', name: '人民路井盖沉降隐患', level: 'critical', type: '井盖下沉',
    description: '井盖沉降约8cm，周边路面开裂，存在塌陷风险', address: '人民路与解放路口东50m', locationShort: '人民路口',
    lng: 121.487, lat: 31.249, discoverTime: '2025-03-15', responsibleUnit: '市政工程管理处', status: 'unresolved',
    surrounding: { residential: 2, commercial: 1, public: 0, road: 1 },
    nearbyHazards: [{ id: 2, name: '解放路口管线老化', level: 'major', distance: 120 }],
    records: [{ id: 1, time: '2025-03-16', type: 'warning', content: '已派发维修工单，待处理' }]
  },
  {
    id: 2, code: 'HZ-002', name: '滨江路燃气泄漏隐患', level: 'critical', type: '燃气泄漏',
    description: '井下检测到H₂S浓度28ppm，有燃气异味，需紧急处置', address: '滨江路化工园区南门', locationShort: '滨江园区',
    lng: 121.502, lat: 31.235, discoverTime: '2025-04-01', responsibleUnit: '燃气集团', status: 'unresolved',
    surrounding: { residential: 0, commercial: 2, public: 1, road: 2 },
    nearbyHazards: [{ id: 3, name: '滨江路排水管破损', level: 'general', distance: 80 }],
    records: [{ id: 1, time: '2025-04-01', type: 'danger', content: '紧急派单，抢修队已出发' }]
  },
  {
    id: 3, code: 'HZ-003', name: '古城街井盖破损', level: 'major', type: '井盖破损',
    description: '井盖边缘破损严重，存在行人跌落风险', address: '古城街北段树下', locationShort: '古城街',
    lng: 121.478, lat: 31.258, discoverTime: '2025-03-28', responsibleUnit: '市政设施管理处', status: 'unresolved',
    surrounding: { residential: 3, commercial: 0, public: 1, road: 1 },
    nearbyHazards: [],
    records: [{ id: 1, time: '2025-03-29', type: 'primary', content: '已安排更换，备货中' }]
  },
  {
    id: 4, code: 'HZ-004', name: '高新区排水管道堵塞', level: 'general', type: '管道堵塞',
    description: '排水不畅，雨季易积水', address: '高新大道云计算中心旁', locationShort: '高新区',
    lng: 121.512, lat: 31.242, discoverTime: '2025-03-20', responsibleUnit: '水务集团', status: 'resolved',
    surrounding: { residential: 1, commercial: 2, public: 0, road: 1 },
    nearbyHazards: [],
    records: [{ id: 1, time: '2025-03-22', type: 'success', content: '已完成疏通，排水正常' }],
    resolveTime: '2025-03-22'
  },
  {
    id: 5, code: 'HZ-005', name: '南港路窨井盖缺失', level: 'critical', type: '井盖缺失',
    description: '井盖缺失，井口裸露，存在重大安全隐患', address: '南港路旧车站段', locationShort: '南港路',
    lng: 121.495, lat: 31.228, discoverTime: '2025-04-02', responsibleUnit: '市政工程管理处', status: 'unresolved',
    surrounding: { residential: 2, commercial: 1, public: 0, road: 2 },
    nearbyHazards: [{ id: 4, name: '高新区排水堵塞', level: 'general', distance: 350 }],
    records: [{ id: 1, time: '2025-04-02', type: 'danger', content: '已设置警示标志，紧急采购井盖' }]
  },
  {
    id: 6, code: 'HZ-006', name: '石化区管道腐蚀', level: 'major', type: '管道腐蚀',
    description: '管道外壁腐蚀严重，有泄漏风险', address: '石化大道南侧', locationShort: '石化大道',
    lng: 121.524, lat: 31.239, discoverTime: '2025-03-25', responsibleUnit: '生态环境局', status: 'resolved',
    surrounding: { residential: 0, commercial: 0, public: 0, road: 1 },
    nearbyHazards: [],
    records: [{ id: 1, time: '2025-03-28', type: 'success', content: '已完成防腐处理' }],
    resolveTime: '2025-03-28'
  },
  {
    id: 7, code: 'HZ-007', name: '中山路井盖异响', level: 'general', type: '井盖松动',
    description: '车辆经过时井盖跳动异响，存在移位风险', address: '中山路与人民路口', locationShort: '中山路口',
    lng: 121.488, lat: 31.252, discoverTime: '2025-03-30', responsibleUnit: '市政工程管理处', status: 'unresolved',
    surrounding: { residential: 2, commercial: 3, public: 1, road: 2 },
    nearbyHazards: [{ id: 1, name: '人民路井盖沉降', level: 'critical', distance: 200 }],
    records: []
  }
])

// 筛选条件
const searchKeyword = ref('')
const levelFilter = ref('')
const listFilter = ref('all')
const currentPage = ref(1)
const pageSize = 6

// GIS画布相关
const canvasRef = ref(null)
const mapContainer = ref(null)
let ctx = null
let mapWidth = 0, mapHeight = 0
let mapZoom = 1
let offsetX = 0, offsetY = 0
let dragStart = null
let isDragging = false
const bounds = { minLng: 121.45, maxLng: 121.56, minLat: 31.20, maxLat: 31.27 }

// 交互状态
const selectedHazard = ref(null)
const currentHazard = ref(null)
const detailDrawerVisible = ref(false)
const hoverHazard = ref(null)
const hoverX = ref(0), hoverY = ref(0)
const currentLng = ref(121.505)
const currentLat = ref(31.235)

// 计算属性
const filteredHazards = computed(() => {
  let list = hazardPoints.value
  if (searchKeyword.value) {
    const kw = searchKeyword.value.toLowerCase()
    list = list.filter(h => h.name.toLowerCase().includes(kw) || h.address.toLowerCase().includes(kw))
  }
  if (levelFilter.value) {
    list = list.filter(h => h.level === levelFilter.value)
  }
  if (listFilter.value === 'unresolved') {
    list = list.filter(h => h.status === 'unresolved')
  } else if (listFilter.value === 'resolved') {
    list = list.filter(h => h.status === 'resolved')
  }
  return list
})

const paginatedHazards = computed(() => {
  const start = (currentPage.value - 1) * pageSize
  return filteredHazards.value.slice(start, start + pageSize)
})

const criticalCount = computed(() => hazardPoints.value.filter(h => h.level === 'critical' && h.status === 'unresolved').length)
const majorCount = computed(() => hazardPoints.value.filter(h => h.level === 'major' && h.status === 'unresolved').length)
const generalCount = computed(() => hazardPoints.value.filter(h => h.level === 'general' && h.status === 'unresolved').length)

// 辅助函数
const getLevelType = (level) => {
  const map = { critical: 'danger', major: 'warning', general: 'info' }
  return map[level]
}
const getLevelText = (level) => {
  const map = { critical: '重大隐患', major: '较大隐患', general: '一般隐患' }
  return map[level]
}

// 选择隐患点
const selectHazard = (hazard) => {
  selectedHazard.value = hazard
  currentHazard.value = hazard
  detailDrawerVisible.value = true
  // 地图居中到该点
  const { x, y } = worldToCanvas(hazard.lng, hazard.lat)
  offsetX = mapWidth/2 - x
  offsetY = mapHeight/2 - y
  renderMap()
}

// GIS地图绘制
function worldToCanvas(lng, lat) {
  const px = (lng - bounds.minLng) / (bounds.maxLng - bounds.minLng) * mapWidth
  const py = (1 - (lat - bounds.minLat) / (bounds.maxLat - bounds.minLat)) * mapHeight
  const cx = mapWidth / 2, cy = mapHeight / 2
  return { x: (px - cx) * mapZoom + cx + offsetX, y: (py - cy) * mapZoom + cy + offsetY }
}

function canvasToWorld(x, y) {
  const cx = mapWidth / 2, cy = mapHeight / 2
  const px = (x - cx - offsetX) / mapZoom + cx
  const py = (y - cy - offsetY) / mapZoom + cy
  const lng = bounds.minLng + (px / mapWidth) * (bounds.maxLng - bounds.minLng)
  const lat = bounds.maxLat - (py / mapHeight) * (bounds.maxLat - bounds.minLat)
  return { lng, lat }
}

function drawBaseMap() {
  if (!ctx) return
  ctx.fillStyle = '#eaf5e9'
  ctx.fillRect(0, 0, mapWidth, mapHeight)

  ctx.strokeStyle = '#c8ddc4'
  ctx.lineWidth = 1
  for (let i = 0; i <= 10; i++) {
    const x = (i / 10) * mapWidth
    ctx.beginPath()
    ctx.moveTo(x, 0)
    ctx.lineTo(x, mapHeight)
    ctx.stroke()
    const y = (i / 10) * mapHeight
    ctx.beginPath()
    ctx.moveTo(0, y)
    ctx.lineTo(mapWidth, y)
    ctx.stroke()
  }

  ctx.fillStyle = '#a8d0a6'
  ctx.font = '12px "Microsoft YaHei"'
  ctx.fillText('世纪大道', 350, 120)
  ctx.fillText('人民路', 200, 300)
  ctx.fillText('张杨路', 450, 280)
  ctx.fillText('龙阳路', 180, 370)
}

function drawHazards() {
  filteredHazards.value.forEach(hazard => {
    const { x, y } = worldToCanvas(hazard.lng, hazard.lat)
    if (x < -30 || x > mapWidth + 30 || y < -30 || y > mapHeight + 30) return

    let color = '#67c23a'
    let size = 12
    if (hazard.level === 'critical') {
      color = '#f56c6c'
      size = 16
    } else if (hazard.level === 'major') {
      color = '#e6a23c'
      size = 14
    } else {
      color = '#409eff'
      size = 12
    }

    // 未整改的加外圈
    ctx.beginPath()
    ctx.arc(x, y, size, 0, 2 * Math.PI)
    ctx.fillStyle = color
    ctx.fill()
    ctx.strokeStyle = '#fff'
    ctx.lineWidth = 2
    ctx.stroke()

    if (hazard.status === 'unresolved') {
      ctx.beginPath()
      ctx.arc(x, y, size + 4, 0, 2 * Math.PI)
      ctx.fillStyle = 'rgba(245,108,108,0.2)'
      ctx.fill()
    }

    // 绘制感叹号
    ctx.fillStyle = '#fff'
    ctx.font = 'bold 14px sans-serif'
    ctx.fillText('!', x - 4, y + 5)

    // 标签
    ctx.fillStyle = '#333'
    ctx.font = '10px sans-serif'
    ctx.fillText(hazard.name.slice(0, 6), x - 15, y - 10)
  })
}

function renderMap() {
  if (!canvasRef.value || !mapContainer.value) return
  const canvas = canvasRef.value
  mapWidth = mapContainer.value.clientWidth
  mapHeight = mapContainer.value.clientHeight
  canvas.width = mapWidth
  canvas.height = mapHeight
  ctx = canvas.getContext('2d')

  drawBaseMap()
  drawHazards()
}

// 地图操作
function zoomIn() { mapZoom = Math.min(mapZoom + 0.15, 2.5); renderMap() }
function zoomOut() { mapZoom = Math.max(mapZoom - 0.15, 0.6); renderMap() }
function fitBounds() { mapZoom = 1; offsetX = 0; offsetY = 0; renderMap() }
function refreshMap() { renderMap() }

function updateCoordinates(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const mouseX = (e.clientX - rect.left) * (mapWidth / rect.width)
  const mouseY = (e.clientY - rect.top) * (mapHeight / rect.height)
  const { lng, lat } = canvasToWorld(mouseX, mouseY)
  currentLng.value = lng
  currentLat.value = lat
}

function onMapClick(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const mouseX = (e.clientX - rect.left) * (mapWidth / rect.width)
  const mouseY = (e.clientY - rect.top) * (mapHeight / rect.height)

  let minDist = 25
  let hit = null

  filteredHazards.value.forEach(hazard => {
    const { x, y } = worldToCanvas(hazard.lng, hazard.lat)
    const dist = Math.hypot(mouseX - x, mouseY - y)
    if (dist < minDist) {
      minDist = dist
      hit = hazard
    }
  })

  if (hit) {
    selectedHazard.value = hit
    currentHazard.value = hit
    detailDrawerVisible.value = true
  }
}

function onCanvasMouseMove(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const mouseX = (e.clientX - rect.left) * (mapWidth / rect.width)
  const mouseY = (e.clientY - rect.top) * (mapHeight / rect.height)

  let minDist = 20
  let hit = null

  filteredHazards.value.forEach(hazard => {
    const { x, y } = worldToCanvas(hazard.lng, hazard.lat)
    const dist = Math.hypot(mouseX - x, mouseY - y)
    if (dist < minDist) {
      minDist = dist
      hit = hazard
    }
  })

  if (hit) {
    hoverHazard.value = hit
    hoverX.value = e.clientX + 12
    hoverY.value = e.clientY - 40
  } else {
    hoverHazard.value = null
  }
}

function viewSurroundingMap() {
  ElMessage.info('查看周边环境GIS分布图（演示功能）')
}

// 拖动地图
function initDragEvents() {
  const canvas = canvasRef.value
  if (!canvas) return

  canvas.addEventListener('mousedown', (e) => {
    dragStart = { x: e.clientX, y: e.clientY, offsetX: offsetX, offsetY: offsetY }
    isDragging = true
    canvas.style.cursor = 'grabbing'
  })

  window.addEventListener('mousemove', (e) => {
    if (!isDragging) return
    const dx = e.clientX - dragStart.x
    const dy = e.clientY - dragStart.y
    offsetX = dragStart.offsetX + dx
    offsetY = dragStart.offsetY + dy
    renderMap()
  })

  window.addEventListener('mouseup', () => {
    isDragging = false
    if (canvasRef.value) canvasRef.value.style.cursor = 'crosshair'
  })
}

// 监听筛选变化重绘地图
watch([searchKeyword, levelFilter, listFilter], () => {
  currentPage.value = 1
  renderMap()
})

import { ElMessage } from 'element-plus'

onMounted(() => {
  nextTick(() => {
    renderMap()
    initDragEvents()
    window.addEventListener('resize', renderMap)
  })
})
onUnmounted(() => window.removeEventListener('resize', renderMap))
</script>

<style scoped>
.hazard-gis-dashboard {
  background: #f0f2f6;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.page-header {
  background: white;
  padding: 12px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #e9ecef;
  flex-shrink: 0;
}
.header-left { display: flex; align-items: center; gap: 20px; }
.header-left .title { font-size: 1.3rem; font-weight: 600; color: #1f2d3d; }
.stats-badge { display: flex; gap: 16px; }
.stat-item { font-size: 13px; display: flex; align-items: center; gap: 6px; }
.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.critical-dot { background: #f56c6c; }
.major-dot { background: #e6a23c; }
.general-dot { background: #409eff; }
.header-right { display: flex; gap: 12px; }

.main-layout {
  display: flex;
  flex: 1;
  overflow: hidden;
  padding: 12px;
  gap: 12px;
}
.hazard-list-panel {
  width: 360px;
  background: white;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.list-header {
  padding: 16px;
  border-bottom: 1px solid #e9ecef;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}
.hazard-list {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
}
.hazard-item {
  padding: 12px;
  margin-bottom: 10px;
  border-radius: 12px;
  background: #fafbfc;
  border: 1px solid #e9ecef;
  cursor: pointer;
  transition: all 0.2s;
}
.hazard-item.selected { background: #ecf5ff; border-color: #409eff; }
.hazard-item.critical { border-left: 3px solid #f56c6c; }
.hazard-item.major { border-left: 3px solid #e6a23c; }
.hazard-header { display: flex; justify-content: space-between; margin-bottom: 6px; }
.hazard-name { font-weight: 600; }
.hazard-location { font-size: 12px; color: #6c757d; display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.hazard-desc { font-size: 12px; color: #606266; margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pagination-area { padding: 12px; text-align: center; border-top: 1px solid #eee; }

.gis-container {
  flex: 1;
  background: white;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.map-toolbar {
  padding: 10px 16px;
  border-bottom: 1px solid #e9ecef;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.coordinate-info { display: flex; gap: 16px; font-size: 12px; color: #909399; }
.map-wrapper {
  flex: 1;
  position: relative;
  cursor: crosshair;
}
canvas { width: 100%; height: 100%; display: block; cursor: crosshair; }
.hover-card {
  position: fixed;
  background: rgba(0,0,0,0.8);
  color: white;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 12px;
  pointer-events: none;
  z-index: 200;
  backdrop-filter: blur(4px);
}
.hover-title { font-weight: 600; margin-bottom: 4px; }

.hazard-detail { padding: 8px; }
.section-title { font-weight: 600; margin: 20px 0 12px 0; display: flex; justify-content: space-between; align-items: center; }
.surrounding-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; background: #f5f7fa; padding: 12px; border-radius: 8px; }
.surrounding-stats .stat-item .label { color: #606266; }
.nearby-list { max-height: 200px; overflow-y: auto; }
.nearby-item { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px solid #eee; }
.nearby-name { flex: 1; }
.nearby-dist { font-size: 11px; color: #909399; }
.sub-title { font-weight: 500; margin: 12px 0 8px 0; font-size: 13px; }
</style>