<template>
  <div class="lifeline-home" v-loading="loading">
    <header class="home-header">
      <div class="header-copy">
        <span class="header-kicker">城市生命线运行态势</span>
        <h1>预警联动管理首页</h1>
        <p>汇集供水、排水、燃气与窨井预警，集中掌握风险和处置进度。</p>
      </div>
      <div class="header-tools">
        <div class="date-block">
          <strong>{{ currentDateLabel }}</strong>
          <span>{{ currentTimeLabel }} · 数据更新 {{ lastUpdated || '未更新' }}</span>
        </div>
        <el-tooltip content="刷新首页数据" placement="bottom">
          <el-button circle type="primary" :loading="loading" aria-label="刷新首页数据" @click="loadData">
            <el-icon v-if="!loading"><Refresh /></el-icon>
          </el-button>
        </el-tooltip>
      </div>
    </header>

    <el-alert
      v-if="errorMessage"
      :title="errorMessage"
      :type="allRequestsFailed ? 'error' : 'warning'"
      show-icon
      closable
      class="data-alert"
      @close="errorMessage = ''"
    >
      <template #default>
        <el-button link type="primary" @click="loadData">重新加载</el-button>
      </template>
    </el-alert>

    <section class="metric-grid" aria-label="今日预警核心指标">
      <button
        v-for="metric in metricCards"
        :key="metric.key"
        type="button"
        class="metric-card"
        :style="{ '--tone': metric.color, '--tone-soft': metric.softColor }"
        @click="navigate(metric.routeName)"
      >
        <span class="metric-icon"><el-icon><component :is="metric.icon" /></el-icon></span>
        <span class="metric-content">
          <span class="metric-label">{{ metric.label }}</span>
          <strong>{{ formatCount(metric.value) }}</strong>
          <small>{{ metric.note }}</small>
        </span>
        <el-icon class="metric-arrow"><ArrowRight /></el-icon>
      </button>
    </section>

    <div class="analysis-grid">
      <section class="panel trend-panel">
        <div class="panel-header">
          <div>
            <h2>近 7 日预警趋势</h2>
            <p>四类设施非草稿预警的每日变化</p>
          </div>
          <el-button link type="primary" @click="navigate('WarningTrend')">
            趋势分析<el-icon><ArrowRight /></el-icon>
          </el-button>
        </div>
        <div ref="trendChartRef" class="chart-box" />
        <el-empty v-if="!trendRows.length && !loading" description="近 7 日暂无预警数据" :image-size="74" />
      </section>

      <section class="panel status-panel">
        <div class="panel-header">
          <div>
            <h2>近 30 日处置状态</h2>
            <p>各处置阶段预警数量分布</p>
          </div>
          <el-button link type="primary" @click="navigate('WarningDisposeStatus')">
            查看分析<el-icon><ArrowRight /></el-icon>
          </el-button>
        </div>
        <div ref="statusChartRef" class="chart-box" />
        <el-empty v-if="!statusRows.length && !loading" description="当前周期暂无状态数据" :image-size="74" />
      </section>
    </div>

    <section class="panel facility-panel">
      <div class="panel-header">
        <div>
          <h2>设施预警分布</h2>
          <p>历史非草稿预警累计 {{ formatCount(facilityTotal) }} 条</p>
        </div>
        <el-button link type="primary" @click="navigate('WarningHistoryOverview')">
          历史预警概况<el-icon><ArrowRight /></el-icon>
        </el-button>
      </div>
      <div class="facility-grid">
        <article
          v-for="facility in facilityStats"
          :key="facility.value"
          class="facility-card"
          :style="{ '--facility-color': facility.color, '--facility-soft': facility.softColor }"
        >
          <div class="facility-title">
            <span class="facility-mark">{{ facility.shortLabel }}</span>
            <div><strong>{{ facility.label }}</strong><small>历史预警</small></div>
          </div>
          <div class="facility-value">
            <strong>{{ formatCount(facility.count) }}</strong>
            <span>{{ formatPercent(facility.percentage) }}</span>
          </div>
          <div class="facility-progress"><i :style="{ width: `${facility.percentage}%` }" /></div>
        </article>
      </div>
    </section>

    <div class="operations-grid">
      <section class="panel warning-panel">
        <div class="panel-header">
          <div>
            <h2>重点未处置预警</h2>
            <p>按预警级别和等待时长优先展示，共 {{ formatCount(unprocessedTotal) }} 条</p>
          </div>
          <el-button link type="primary" @click="navigate('WarningTodayUnprocessed')">
            查看全部<el-icon><ArrowRight /></el-icon>
          </el-button>
        </div>
        <el-table
          :data="unprocessedRows"
          row-key="warningId"
          class="warning-table"
          empty-text="当前暂无未处置预警"
          @row-click="openDetail"
        >
          <el-table-column label="级别" width="122">
            <template #default="{ row }">
              <el-tag :type="warningLevelTag(row)" effect="light" size="small">
                {{ warningLevelText(row) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="预警事项" min-width="190" show-overflow-tooltip>
            <template #default="{ row }">
              <div class="warning-name">
                <i :class="`level-${warningLevelCode(row)}`" />
                <span>{{ listValue(row, 'warningName', 'warning_name') || '未命名预警' }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="设施类型" width="110">
            <template #default="{ row }">{{ warningTypeText(row) }}</template>
          </el-table-column>
          <el-table-column label="权属单位" min-width="150" show-overflow-tooltip>
            <template #default="{ row }">{{ listValue(row, 'ownershipUnit', 'ownership_unit') || '未设置' }}</template>
          </el-table-column>
          <el-table-column label="等待时长" width="105">
            <template #default="{ row }"><span class="waiting-time">{{ waitingText(row) }}</span></template>
          </el-table-column>
          <el-table-column label="状态" width="94" align="center">
            <template #default="{ row }">
              <el-tag :type="warningStatusTag(row)" effect="plain" size="small">
                {{ warningStatusText(row) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="84" fixed="right" align="center">
            <template #default="{ row }">
              <el-button link type="primary" @click.stop="openDetail(row)">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
      </section>

      <aside class="panel quick-panel">
        <div class="panel-header">
          <div>
            <h2>常用功能</h2>
            <p>快速进入预警查询与处置工作</p>
          </div>
        </div>
        <div class="quick-list">
          <button
            v-for="action in quickActions"
            :key="action.routeName"
            type="button"
            class="quick-action"
            @click="navigate(action.routeName)"
          >
            <span class="quick-icon" :style="{ color: action.color, background: action.softColor }">
              <el-icon><component :is="action.icon" /></el-icon>
            </span>
            <span><strong>{{ action.label }}</strong><small>{{ action.note }}</small></span>
            <el-icon class="quick-arrow"><ArrowRight /></el-icon>
          </button>
        </div>
      </aside>
    </div>

    <WarningDetailDrawer v-model="detailVisible" :row="selectedRow" />
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
  ArrowRight,
  Bell,
  CircleCheck,
  Clock,
  DataAnalysis,
  Refresh,
  Setting,
  TrendCharts,
  Warning
} from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import {
  getWarningTodayOverview,
  pageWarningHistory,
  pageWarningTodayUnprocessed
} from '@/api/warning/dashboard'
import { getDisposeStatusStat, getWarningTrendByDay } from '@/api/warning/statistics'
import WarningDetailDrawer from '../lOverviewWarning/WarningDetailDrawer.vue'
import {
  dashboardData,
  listValue,
  pageRecords,
  pageTotal,
  warningLevelCode,
  warningLevelTag,
  warningLevelText,
  warningStatusTag,
  warningStatusText,
  warningTypeText
} from '../lOverviewWarning/dashboardShared'
import { labelOf, responseData, statusLabels } from '../lstatistics/statisticsShared'

const router = useRouter()
const loading = ref(false)
const errorMessage = ref('')
const allRequestsFailed = ref(false)
const lastUpdated = ref('')
const now = ref(new Date())
const todayOverview = ref({})
const unprocessedRows = ref([])
const unprocessedTotal = ref(null)
const trendRows = ref([])
const statusRows = ref([])
const detailVisible = ref(false)
const selectedRow = ref(null)
const trendChartRef = ref()
const statusChartRef = ref()
let trendChart
let statusChart
let clockTimer
let resizeObserver

const facilityDefinitions = [
  { value: 'WATER_PIPE', label: '供水管网', shortLabel: '供', color: '#2563eb', softColor: '#eff6ff' },
  { value: 'SEWER_PIPE', label: '排水管网', shortLabel: '排', color: '#0f766e', softColor: '#ecfdf5' },
  { value: 'GAS_PIPE', label: '燃气管网', shortLabel: '燃', color: '#d97706', softColor: '#fffbeb' },
  { value: 'MANHOLE', label: '窨井', shortLabel: '井', color: '#64748b', softColor: '#f1f5f9' }
]

const facilityCounts = ref(Object.fromEntries(facilityDefinitions.map(item => [item.value, null])))

const facilityTotal = computed(() => {
  const values = Object.values(facilityCounts.value).filter(value => Number.isFinite(value))
  return values.length ? values.reduce((total, value) => total + value, 0) : null
})

const facilityStats = computed(() => facilityDefinitions.map(item => {
  const count = facilityCounts.value[item.value]
  const percentage = Number.isFinite(count) && facilityTotal.value > 0
    ? Number(((count / facilityTotal.value) * 100).toFixed(1))
    : 0
  return { ...item, count, percentage }
}))

const metricCards = computed(() => [
  {
    key: 'today', label: '今日预警', value: numericValue(todayOverview.value.todayTotal),
    note: '今日非草稿预警', routeName: 'WarningTodayOverview', icon: Bell,
    color: '#2563eb', softColor: '#eff6ff'
  },
  {
    key: 'unresolved', label: '当前未解除', value: numericValue(todayOverview.value.unresolvedCount),
    note: '截至当前仍在跟进', routeName: 'WarningTodayOverview', icon: Warning,
    color: '#dc2626', softColor: '#fef2f2'
  },
  {
    key: 'resolved', label: '今日已解除', value: numericValue(todayOverview.value.resolvedCount),
    note: '今日完成风险解除', routeName: 'WarningTodayOverview', icon: CircleCheck,
    color: '#059669', softColor: '#ecfdf5'
  },
  {
    key: 'unprocessed', label: '未处置预警', value: unprocessedTotal.value,
    note: '需要重点督办', routeName: 'WarningTodayUnprocessed', icon: Clock,
    color: '#d97706', softColor: '#fffbeb'
  }
])

const quickActions = [
  { label: '今日预警概况', note: '查看今日警情明细', routeName: 'WarningTodayOverview', icon: Bell, color: '#2563eb', softColor: '#eff6ff' },
  { label: '今日未处置预警', note: '跟进待处理警情', routeName: 'WarningTodayUnprocessed', icon: Warning, color: '#dc2626', softColor: '#fef2f2' },
  { label: '历史预警概况', note: '查看设施预警分布', routeName: 'WarningHistoryOverview', icon: DataAnalysis, color: '#0f766e', softColor: '#ecfdf5' },
  { label: '处置状态分析', note: '分析处置进度', routeName: 'WarningDisposeStatus', icon: TrendCharts, color: '#7c3aed', softColor: '#f5f3ff' },
  { label: '预警事项管理', note: '维护预警清单配置', routeName: 'WarningItemManage', icon: Setting, color: '#475569', softColor: '#f1f5f9' }
]

const currentDateLabel = computed(() => new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric', month: 'long', day: 'numeric', weekday: 'long'
}).format(now.value))

const currentTimeLabel = computed(() => new Intl.DateTimeFormat('zh-CN', {
  hour: '2-digit', minute: '2-digit', hour12: false
}).format(now.value))

function numericValue(value) {
  if (value === null || value === undefined || value === '') return null
  const number = Number(value)
  return Number.isFinite(number) ? number : null
}

function formatCount(value) {
  return Number.isFinite(value) ? new Intl.NumberFormat('zh-CN').format(value) : '-'
}

function formatPercent(value) {
  return facilityTotal.value > 0 ? `${Number(value || 0).toFixed(1)}%` : '-'
}

function pad(value) {
  return String(value).padStart(2, '0')
}

function formatApiDate(date) {
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
}

function rangeForDays(days) {
  const end = new Date()
  const start = new Date(end)
  start.setHours(0, 0, 0, 0)
  start.setDate(start.getDate() - days + 1)
  return { startTime: formatApiDate(start), endTime: formatApiDate(end) }
}

function recentDateKeys(days = 7) {
  const result = []
  const cursor = new Date()
  cursor.setHours(0, 0, 0, 0)
  cursor.setDate(cursor.getDate() - days + 1)
  for (let index = 0; index < days; index += 1) {
    result.push(`${cursor.getFullYear()}-${pad(cursor.getMonth() + 1)}-${pad(cursor.getDate())}`)
    cursor.setDate(cursor.getDate() + 1)
  }
  return result
}

function warningCount(row) {
  return Number(row.warning_count ?? row.warningCount ?? row.status_count ?? row.statusCount ?? 0)
}

function renderTrendChart() {
  if (!trendChartRef.value) return
  trendChart ||= echarts.init(trendChartRef.value)
  if (!trendRows.value.length) {
    trendChart.clear()
    return
  }
  const dates = recentDateKeys()
  const totals = Object.fromEntries(dates.map(date => [date, 0]))
  trendRows.value.forEach(row => {
    const date = String(row.stat_date ?? row.statDate ?? '').slice(0, 10)
    if (date in totals) totals[date] += warningCount(row)
  })
  trendChart.setOption({
    animationDuration: 450,
    color: ['#2563eb'],
    tooltip: { trigger: 'axis', valueFormatter: value => `${value} 条` },
    grid: { left: 48, right: 22, top: 24, bottom: 38 },
    xAxis: {
      type: 'category', boundaryGap: false, data: dates.map(date => date.slice(5)),
      axisLine: { lineStyle: { color: '#d9e1ea' } }, axisLabel: { color: '#64748b' }
    },
    yAxis: {
      type: 'value', minInterval: 1, axisLabel: { color: '#64748b' },
      splitLine: { lineStyle: { color: '#edf1f5' } }
    },
    series: [{
      name: '预警数量', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7,
      lineStyle: { width: 3 }, itemStyle: { borderColor: '#ffffff', borderWidth: 2 },
      areaStyle: { color: 'rgba(37, 99, 235, 0.10)' }, data: dates.map(date => totals[date])
    }]
  }, true)
}

function renderStatusChart() {
  if (!statusChartRef.value) return
  statusChart ||= echarts.init(statusChartRef.value)
  const data = statusRows.value.map(row => ({
    name: labelOf(statusLabels, row.status), value: warningCount(row), status: String(row.status || '').toUpperCase()
  })).filter(item => item.value > 0)
  if (!data.length) {
    statusChart.clear()
    return
  }
  const colorByStatus = {
    PENDING: '#dc2626', PROCESSING: '#d97706', RELEASED: '#2563eb',
    HANDLED: '#0f766e', CLOSED: '#059669', RESOLVED: '#059669'
  }
  statusChart.setOption({
    tooltip: { trigger: 'item', formatter: '{b}<br/>{c} 条（{d}%）' },
    legend: { type: 'scroll', bottom: 0, left: 'center', textStyle: { color: '#64748b' } },
    series: [{
      type: 'pie', radius: ['46%', '68%'], center: ['50%', '43%'], avoidLabelOverlap: true,
      itemStyle: { borderColor: '#ffffff', borderWidth: 3 }, label: { show: false },
      emphasis: { label: { show: true, fontSize: 14, fontWeight: 600 } },
      data: data.map(item => ({
        name: item.name, value: item.value,
        itemStyle: { color: colorByStatus[item.status] || '#64748b' }
      }))
    }]
  }, true)
}

function waitingText(row) {
  const hours = numericValue(listValue(row, 'waitingHours', 'waiting_hours'))
  if (hours === null) return '-'
  if (hours < 1) return '< 1 小时'
  if (hours < 24) return `${hours.toFixed(hours >= 10 ? 0 : 1)} 小时`
  return `${Math.floor(hours / 24)} 天 ${Math.round(hours % 24)} 小时`
}

function openDetail(row) {
  selectedRow.value = row
  detailVisible.value = true
}

function navigate(routeName) {
  const routeCandidates = router.getRoutes().filter(route => route.name === routeName)
  if (!routeCandidates.length) {
    ElMessage.warning('当前账号暂无该功能菜单权限')
    return
  }
  // Legacy databases can temporarily expose the same route name at root level
  // and under the subsystem. Prefer the scoped route when both are available.
  const preferredRoute = routeCandidates.sort((left, right) => {
    const leftScoped = left.path.startsWith('/subSystem/') ? 1 : 0
    const rightScoped = right.path.startsWith('/subSystem/') ? 1 : 0
    return rightScoped - leftScoped || right.path.length - left.path.length
  })[0]
  router.push(preferredRoute.path).catch(() => {})
}

async function loadData() {
  if (loading.value) return
  loading.value = true
  errorMessage.value = ''
  const requests = [
    { key: 'today', label: '今日概况', promise: getWarningTodayOverview() },
    { key: 'unprocessed', label: '未处置清单', promise: pageWarningTodayUnprocessed({ pageNum: 1, pageSize: 6 }) },
    { key: 'trend', label: '预警趋势', promise: getWarningTrendByDay(rangeForDays(7)) },
    { key: 'status', label: '处置状态', promise: getDisposeStatusStat(rangeForDays(30)) },
    ...facilityDefinitions.map(item => ({
      key: item.value, label: item.label,
      promise: pageWarningHistory({ pageNum: 1, pageSize: 1, warningType: item.value })
    }))
  ]

  try {
    const results = await Promise.allSettled(requests.map(item => item.promise))
    const failedLabels = []
    let successCount = 0
    let generatedAt = ''

    results.forEach((result, index) => {
      const request = requests[index]
      if (result.status === 'rejected') {
        failedLabels.push(request.label)
        return
      }
      successCount += 1
      if (request.key === 'today') {
        todayOverview.value = dashboardData(result.value, {})
        generatedAt = todayOverview.value.generatedAt || generatedAt
      } else if (request.key === 'unprocessed') {
        const data = dashboardData(result.value, {})
        unprocessedRows.value = pageRecords(result.value)
        unprocessedTotal.value = pageTotal(result.value)
        generatedAt = data.generatedAt || generatedAt
      } else if (request.key === 'trend') {
        trendRows.value = responseData(result.value, [])
      } else if (request.key === 'status') {
        statusRows.value = responseData(result.value, [])
      } else {
        facilityCounts.value = { ...facilityCounts.value, [request.key]: pageTotal(result.value) }
      }
    })

    allRequestsFailed.value = successCount === 0
    if (successCount > 0) lastUpdated.value = generatedAt || formatApiDate(new Date())
    if (failedLabels.length) errorMessage.value = `${failedLabels.join('、')}加载失败，其他可用数据已正常展示。`
    await nextTick()
    renderTrendChart()
    renderStatusChart()
  } finally {
    loading.value = false
  }
}

function resizeCharts() {
  trendChart?.resize()
  statusChart?.resize()
}

onMounted(() => {
  clockTimer = window.setInterval(() => { now.value = new Date() }, 30000)
  resizeObserver = new ResizeObserver(resizeCharts)
  if (trendChartRef.value) resizeObserver.observe(trendChartRef.value)
  if (statusChartRef.value) resizeObserver.observe(statusChartRef.value)
  loadData()
})

onUnmounted(() => {
  window.clearInterval(clockTimer)
  resizeObserver?.disconnect()
  trendChart?.dispose()
  statusChart?.dispose()
})
</script>

<style scoped lang="scss">
.lifeline-home {
  min-height: calc(100vh - 84px);
  padding: 20px 22px 28px;
  background: #f3f6fa;
  color: #1f2937;
}

.home-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding: 2px 2px 18px;
  border-bottom: 1px solid #dfe6ee;
}

.header-kicker { color: #2563eb; font-size: 12px; font-weight: 700; }
.header-copy h1 { margin: 6px 0 5px; font-size: 26px; line-height: 1.25; }
.header-copy p, .panel-header p { margin: 0; color: #718096; }
.header-tools { display: flex; align-items: center; gap: 14px; }

.date-block {
  display: flex;
  min-width: 245px;
  flex-direction: column;
  align-items: flex-end;
  gap: 5px;
}

.date-block strong { font-size: 14px; }
.date-block span { color: #8492a6; font-size: 12px; }
.data-alert { margin-top: 16px; }

.metric-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin: 18px 0 16px;
}

.metric-card {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 122px;
  align-items: center;
  gap: 15px;
  padding: 20px;
  border: 1px solid #e1e7ef;
  border-top: 3px solid var(--tone);
  border-radius: 8px;
  background: #ffffff;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s;
}

.metric-card:hover {
  border-color: var(--tone);
  box-shadow: 0 8px 20px rgba(31, 41, 55, 0.08);
  transform: translateY(-1px);
}

.metric-icon, .quick-icon {
  display: inline-flex;
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
}

.metric-icon { background: var(--tone-soft); color: var(--tone); font-size: 21px; }
.metric-content { display: flex; min-width: 0; flex: 1; flex-direction: column; }
.metric-label { color: #64748b; font-size: 13px; }
.metric-content strong { margin: 4px 0 2px; color: #172033; font-size: 34px; line-height: 1.05; }

.metric-content small {
  overflow: hidden;
  color: #94a3b8;
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.metric-arrow { color: #b6c0cd; }

.analysis-grid, .operations-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(320px, 0.8fr);
  gap: 16px;
  margin-bottom: 16px;
}

.panel {
  min-width: 0;
  border: 1px solid #e1e7ef;
  border-radius: 8px;
  background: #ffffff;
  box-shadow: 0 2px 8px rgba(31, 41, 55, 0.035);
}

.panel-header {
  display: flex;
  min-height: 72px;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 17px 20px 14px;
  border-bottom: 1px solid #edf1f5;
}

.panel-header h2 { margin: 0 0 5px; font-size: 17px; line-height: 1.25; }
.panel-header p { font-size: 12px; }
.panel-header .el-button { flex: 0 0 auto; }
.chart-box { width: 100%; height: 292px; }
.trend-panel, .status-panel { position: relative; min-height: 365px; }
.trend-panel .el-empty, .status-panel .el-empty { position: absolute; inset: 84px 0 8px; }
.facility-panel { margin-bottom: 16px; }

.facility-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  padding: 16px 20px 20px;
}

.facility-card {
  min-width: 0;
  padding: 16px;
  border: 1px solid #e7ebf1;
  border-radius: 7px;
  background: #ffffff;
}

.facility-title, .facility-value {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.facility-title { justify-content: flex-start; }
.facility-title > div { display: flex; min-width: 0; flex-direction: column; gap: 3px; }
.facility-title strong { overflow: hidden; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.facility-title small, .facility-value span { color: #94a3b8; font-size: 12px; }

.facility-mark {
  display: inline-flex;
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  background: var(--facility-soft);
  color: var(--facility-color);
  font-size: 14px;
  font-weight: 700;
}

.facility-value { margin: 14px 0 10px; align-items: flex-end; }
.facility-value strong { font-size: 27px; line-height: 1; }
.facility-progress { height: 5px; overflow: hidden; border-radius: 3px; background: #eef2f6; }

.facility-progress i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--facility-color);
  transition: width 0.35s ease;
}

.warning-table { width: calc(100% - 32px); margin: 0 16px 16px; cursor: pointer; }
.warning-name { display: flex; min-width: 0; align-items: center; gap: 8px; }

.warning-name i {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: #94a3b8;
}

.warning-name i.level-1 { background: #2563eb; }
.warning-name i.level-2 { background: #eab308; }
.warning-name i.level-3 { background: #f97316; }
.warning-name i.level-4 { background: #dc2626; }
.warning-name span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.waiting-time { color: #b45309; font-weight: 600; }
.quick-panel { align-self: stretch; }
.quick-list { display: flex; flex-direction: column; padding: 8px 14px 14px; }

.quick-action {
  display: flex;
  width: 100%;
  min-height: 64px;
  align-items: center;
  gap: 12px;
  padding: 10px 8px;
  border: 0;
  border-bottom: 1px solid #edf1f5;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.quick-action:last-child { border-bottom: 0; }
.quick-action:hover { background: #f8fafc; }

.quick-action > span:nth-child(2) {
  display: flex;
  min-width: 0;
  flex: 1;
  flex-direction: column;
  gap: 4px;
}

.quick-action strong, .quick-action small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.quick-action strong { font-size: 14px; }
.quick-action small { color: #94a3b8; font-size: 12px; }
.quick-icon { width: 38px; height: 38px; flex-basis: 38px; font-size: 18px; }
.quick-arrow { flex: 0 0 auto; color: #b6c0cd; }

@media (max-width: 1180px) {
  .metric-grid, .facility-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .analysis-grid, .operations-grid { grid-template-columns: 1fr; }
  .quick-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
}

@media (max-width: 680px) {
  .lifeline-home { padding: 14px 12px 22px; }
  .home-header { align-items: flex-start; flex-direction: column; }
  .header-tools { width: 100%; justify-content: space-between; }
  .date-block { min-width: 0; align-items: flex-start; }
  .metric-grid, .facility-grid, .quick-list { grid-template-columns: 1fr; }
  .metric-card { min-height: 110px; }
  .panel-header { align-items: flex-start; }
  .chart-box { height: 260px; }
  .trend-panel, .status-panel { min-height: 335px; }
  .facility-grid { padding: 14px; }
}
</style>
