<template>
  <div class="review-page">
    <!-- 顶部 -->
    <div class="review-header">
      <div class="header-left">
        <el-button text @click="$router.push('/maps')">← 返回战略地图</el-button>
        <el-button text type="primary" @click="goCanvas" v-if="selectedMap">🗺️ 打开画布</el-button>
        <h3>{{ mapTitle }} · 战略回顾</h3>
      </div>
      <div class="header-right">
        <el-select v-model="selectedMap" placeholder="选择地图" style="width:200px;margin-right:8px;" @change="loadReview">
          <el-option v-for="m in maps" :key="m.id" :label="m.title" :value="m.id" />
        </el-select>
        <el-radio-group v-model="period" size="small">
          <el-radio-button value="month">本月</el-radio-button>
          <el-radio-button value="quarter">本季</el-radio-button>
          <el-radio-button value="year">本年</el-radio-button>
        </el-radio-group>
      </div>
    </div>

    <!-- 会议类型选择 -->
    <div class="meeting-type-bar">
      <el-radio-group v-model="meetingType" size="default" @change="onMeetingTypeChange">
        <el-radio-button value="strategic">
          <span style="font-weight:600;">🔵 战略回顾会（季度）</span>
        </el-radio-button>
        <el-radio-button value="operational">
          <span style="font-weight:600;">🟢 运营复盘会（月度）</span>
        </el-radio-button>
      </el-radio-group>
      <el-tag v-if="meetingType === 'strategic'" type="primary" size="small" style="margin-left:12px;">
        议程：①战略地图O检查 ②因果链验证 ③O调整 ④下季度优先级
      </el-tag>
      <el-tag v-else type="success" size="small" style="margin-left:12px;">
        议程：①OKR进度检查 ②KPI达标情况 ③偏差分析 ④改善行动确认
      </el-tag>
    </div>

    <!-- 复盘结论持久化工具条（大PDCA Act闭环 2026-08-27） -->
    <div class="review-toolbar">
      <el-button type="primary" :disabled="!selectedMap || !summary" @click="openSaveDialog">
        📝 保存本次复盘结论
      </el-button>
      <el-button :disabled="!selectedMap" @click="showHistoryDialog = true">
        📚 历史复盘记录
        <el-badge v-if="reviewRecords.length > 0" :value="reviewRecords.length" type="primary" style="margin-left:6px;" />
      </el-button>
    </div>

    <!-- 运营复盘会特殊内容 -->
    <template v-if="meetingType === 'operational' && !loading && summary">
      <div class="op-agenda-cards">
        <div class="agenda-card">
          <div class="agenda-card-title">① OKR进度检查</div>
          <div class="agenda-card-body">
            <div v-for="dim in dimensions" :key="dim.key" class="agenda-dim-row">
              <span class="agenda-dim-icon">{{ dim.icon }}</span>
              <span class="agenda-dim-name">{{ dim.name }}</span>
              <span class="agenda-dim-count">{{ dim.objectives?.length || 0 }} 个O</span>
            </div>
          </div>
        </div>
        <div class="agenda-card">
          <div class="agenda-card-title">② KPI达标情况</div>
          <div class="agenda-card-body">
            <div class="kpi-summary-row"><span class="green-dot">🟢</span> 达成: {{ summary.green || 0 }} 项</div>
            <div class="kpi-summary-row"><span class="yellow-dot">🟡</span> 预警: {{ summary.yellow || 0 }} 项</div>
            <div class="kpi-summary-row"><span class="red-dot">🔴</span> 异常: {{ summary.red || 0 }} 项</div>
          </div>
        </div>
        <div class="agenda-card">
          <div class="agenda-card-title">③ 偏差分析</div>
          <div class="agenda-card-body">
            <div v-if="deviations.length > 0">
              <div v-for="d in deviations.slice(0,5)" :key="d.id" class="deviation-row">
                <span class="deviation-badge" :class="'badge-' + (d.alert_level || 'yellow')">{{ d.alert_level === 'red' ? '🔴' : '🟡' }}</span>
                <span class="deviation-kpi">{{ d.kpi_name || d.kpi_code }}</span>
                <span class="deviation-rate">{{ d.deviation_rate != null ? d.deviation_rate.toFixed(1) + '%' : '-' }}</span>
              </div>
              <el-empty v-if="deviations.length === 0" description="本期无偏差" :image-size="60" />
            </div>
            <div v-else class="no-data">加载中...</div>
          </div>
        </div>
        <div class="agenda-card">
          <div class="agenda-card-title">④ 改善行动确认</div>
          <div class="agenda-card-body">
            <div class="kpi-summary-row">✅ 已完成: {{ doneCount() }} 项</div>
            <div class="kpi-summary-row">🔄 进行中: {{ inProgressCount() }} 项</div>
            <div class="kpi-summary-row">⏳ 待处理: {{ pendingCount() }} 项</div>
            <div class="kpi-summary-row" v-if="overdueCount() > 0">🔴 逾期: {{ overdueCount() }} 项</div>
            <el-button size="small" type="primary" style="margin-top:10px;" @click="$router.push('/action-plans')">查看改善行动 →</el-button>
          </div>
        </div>
      </div>
    </template>

    <!-- 战略回顾会数据联动卡片 -->
    <template v-if="meetingType === 'strategic' && !loading && summary">
      <div class="linkage-cards">
        <div class="linkage-card">
          <div class="linkage-card-title">📊 各层O完成情况</div>
          <div class="linkage-card-body">
            <div v-for="dim in dimensions" :key="dim.key" class="linkage-dim-row">
              <span class="linkage-dim-icon">{{ dim.icon }}</span>
              <div class="linkage-dim-info">
                <span class="linkage-dim-name">{{ dim.name }}</span>
                <span class="linkage-dim-ratio">
                  {{ dim.objectives?.filter((o:any) => o.level === 'green').length || 0 }}/{{ dim.objectives?.length || 0 }} 达成
                </span>
              </div>
            </div>
            <el-empty v-if="dimensions.length === 0" description="暂无O数据" :image-size="60" />
          </div>
        </div>
        <div class="linkage-card">
          <div class="linkage-card-title">📈 KR进度</div>
          <div class="linkage-card-body">
            <div v-if="krs.length > 0">
              <div v-for="kr in krs.slice(0,8)" :key="kr.id" class="kr-row">
                <span class="kr-name">{{ kr.name || kr.title }}</span>
                <el-progress :percentage="kr.progress || 0" :stroke-width="10" style="width:100px;" />
              </div>
            </div>
            <div v-else class="no-data">从OKR模块同步中...</div>
          </div>
        </div>
        <div class="linkage-card">
          <div class="linkage-card-title">🚨 偏差项</div>
          <div class="linkage-card-body">
            <div v-if="deviations.length > 0">
              <div v-for="d in deviations.slice(0,8)" :key="d.id" class="deviation-row">
                <span class="deviation-badge" :class="'badge-' + (d.alert_level || 'yellow')">{{ d.alert_level === 'red' ? '🔴' : '🟡' }}</span>
                <span class="deviation-kpi">{{ d.kpi_name || d.kpi_code }}</span>
                <span class="deviation-rate">{{ d.deviation_rate != null ? d.deviation_rate.toFixed(1) + '%' : '-' }}</span>
              </div>
              <el-button size="small" style="margin-top:8px;" @click="$router.push('/deviations')">查看全部偏差 →</el-button>
            </div>
            <el-empty v-else-if="!loadingDeviations" description="本期无偏差" :image-size="60" />
            <div v-else class="no-data">加载中...</div>
          </div>
        </div>
        <div class="linkage-card">
          <div class="linkage-card-title">📋 上期改善行动完成情况</div>
          <div class="linkage-card-body">
            <div class="kpi-summary-row">✅ 已完成: {{ doneCount() }} 项</div>
            <div class="kpi-summary-row">🔄 进行中: {{ inProgressCount() }} 项</div>
            <div class="kpi-summary-row">⏳ 待处理: {{ pendingCount() }} 项</div>
            <div class="kpi-summary-row" v-if="overdueCount() > 0">🔴 逾期: {{ overdueCount() }} 项</div>
            <div v-if="actionPlans.length > 0" class="action-plan-preview">
              <div v-for="p in actionPlans.slice(0,4)" :key="p.id" class="ap-row">
                <span class="ap-status">{{ planIcon(p) }}</span>
                <span class="ap-title">{{ p.title }}</span>
              </div>
            </div>
            <el-empty v-else-if="actionPlans.length === 0 && !loading" description="无上期改善行动" :image-size="60" />
          </div>
        </div>
      </div>
    </template>

    <!-- 加载中 -->
    <div v-if="loading" class="loading-wrap">
      <el-skeleton :rows="6" animated />
    </div>

    <template v-if="!loading && summary">
      <!-- 总体得分卡片 -->
      <div class="summary-cards">
        <div class="s-card overall">
          <div class="s-card-top">
            <span class="score">{{ summary.health_score }}%</span>
            <span class="score-label">整体健康度</span>
          </div>
          <div class="s-card-btm">
            <span class="stat-item green">🟢 {{ summary.green }}个达成</span>
            <span class="stat-item yellow">🟡 {{ summary.yellow }}个预警</span>
            <span class="stat-item red">🔴 {{ summary.red }}个异常</span>
          </div>
        </div>
      </div>

      <!-- 四维度矩阵 -->
      <div class="dim-matrix">
        <div v-for="dim in dimensions" :key="dim.key" class="dim-col" :style="{ borderLeft: '4px solid ' + dim.color }">
          <div class="dim-head">
            <span class="dim-icon">{{ dim.icon }}</span>
            <span class="dim-name">{{ dim.name }}</span>
          </div>
          <div class="dim-body">
            <div v-for="obj in dim.objectives" :key="obj.name"
              class="obj-row"
              :class="'obj-' + obj.level"
              @click="showObjKpis(obj)">
              <span class="obj-badge">{{ badgeIcon(obj.level) }}</span>
              <div class="obj-info">
                <span class="obj-name">{{ obj.name }}</span>
                <span v-if="obj.has_data" class="obj-ratio">
                  <template v-for="k in obj.kpis.slice(0,2)" :key="k.kpi_code">
                    {{ fmtValue(k.actual_value, k.kpi_code) }}/{{ k.target_value ?? '-' }}
                  </template>
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 🔴 需重点关注 -->
      <div v-if="focusItems.length > 0" class="focus-section">
        <h4 class="focus-title">🔴 需重点关注</h4>
        <div v-for="item in focusItems" :key="item.name" class="focus-card" :class="'focus-' + item.level" @click="showObjKpis(item)">
          <div class="focus-head">
            <span class="focus-level">{{ item.level === 'red' ? '紧急' : '预警' }}</span>
            <span class="focus-name">{{ item.name }}</span>
          </div>
          <div class="focus-kpis">
            <div v-for="k in item.kpis" :key="k.kpi_code" class="fkpi-row">
              <span class="fkpi-name">{{ k.kpi_name }}</span>
              <span class="fkpi-val" :style="{ color: k.level === 'red' ? '#f56c6c' : '#e6a23c' }">
                {{ fmtValue(k.actual_value, k.kpi_code) }} / {{ k.target_value ?? '-' }}
              </span>
            </div>
          </div>
          <!-- 关联的改善行动 -->
          <div v-if="getPlansByKpi(item.kpis)" class="focus-plans">
            <div v-for="p in getPlansByKpi(item.kpis)" :key="p.id" class="fplan-row" :class="'plan-' + planStatus(p)">
              <span class="fplan-status">{{ planIcon(p) }}</span>
              <span class="fplan-title">{{ p.title }}</span>
              <span class="fplan-assignee">{{ p.assignee }}</span>
              <span v-if="p.due_date && p.status !== 'completed'" class="fplan-due">{{ dueText(p) }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 📋 改善行动进度 -->
      <div v-if="actionPlans.length > 0" class="plans-section">
        <h4 class="plans-title">📋 改善行动进度</h4>
        <div class="plans-stats">
          <el-tag>{{ pendingCount() }} 待处理</el-tag>
          <el-tag type="warning">{{ inProgressCount() }} 进行中</el-tag>
          <el-tag type="success">{{ doneCount() }} 已完成</el-tag>
          <el-tag type="danger">{{ overdueCount() }} 逾期</el-tag>
        </div>
        <el-table :data="actionPlans" size="small" style="width:100%" @row-click="(r:any)=>$router.push('/action-plans?kpi='+r.kpi_id)">
          <el-table-column prop="title" label="行动标题" min-width="200" />
          <el-table-column prop="assignee" label="负责人" width="120" />
          <el-table-column label="状态" width="100">
            <template #default="{ row }">
              <el-tag :type="planTagType(row)" size="small">{{ planLabel(row) }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="进度" width="120">
            <template #default="{ row }">
              <el-progress :percentage="row.progress || 0" :status="row.status==='completed'?'success':undefined" :stroke-width="12" />
            </template>
          </el-table-column>
          <el-table-column label="截止" width="120">
            <template #default="{ row }">
              <span :style="{ color: isOverdue(row) ? '#f56c6c' : '#666' }">{{ row.due_date ? row.due_date.slice(0,10) : '-' }}</span>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </template>

    <el-empty v-if="!loading && !summary && selectedMap" description="暂无战略回顾数据" />

    <!-- KPI详情弹出 -->
    <el-dialog v-model="showKpiDialog" :title="selectedObjName" width="600">
      <div v-for="k in selectedKpis" :key="k.kpi_code" class="kpi-detail-row" :class="'kpi-' + k.level">
        <div class="kpi-detail-head">
          <span class="kpi-detail-badge">{{ badgeIcon(k.level) }}</span>
          <span class="kpi-detail-name">{{ k.kpi_name }} ({{ k.kpi_code }})</span>
        </div>
        <div class="kpi-detail-body">
          <div class="kpi-detail-item">
            <span class="label">实际值</span>
            <span class="val">{{ fmtValue(k.actual_value, k.kpi_code) }}</span>
          </div>
          <div class="kpi-detail-item">
            <span class="label">目标值</span>
            <span class="val">{{ k.target_value ?? '-' }} {{ k.unit }}</span>
          </div>
          <div class="kpi-detail-item" v-if="k.actual_value != null && k.target_value">
            <span class="label">达成率</span>
            <span class="val" :style="{ color: k.level === 'red' ? '#f56c6c' : 'inherit' }">
              {{ (k.actual_value / k.target_value * 100).toFixed(1) }}%
            </span>
          </div>
          <el-button size="small" @click="$router.push('/kpis/'+k.kpi_id)" style="margin-top:8px;">查看KPI详情 →</el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 保存复盘结论弹窗（大PDCA Act闭环 2026-08-27） -->
    <el-dialog v-model="saveDialogVisible" title="📝 保存复盘结论" width="560">
      <el-form label-width="110px">
        <el-form-item label="复盘类型">
          <el-select v-model="reviewForm.review_type" style="width: 200px;">
            <el-option label="月度运营复盘" value="monthly" />
            <el-option label="季度战略回顾" value="quarterly" />
          </el-select>
        </el-form-item>
        <el-form-item label="复盘日期">
          <el-date-picker v-model="reviewForm.review_date" type="date" value-format="YYYY-MM-DD" style="width: 200px;" />
        </el-form-item>
        <el-form-item label="复盘结论">
          <el-input v-model="reviewForm.summary" type="textarea" :rows="3"
            placeholder="为什么没达成 / 关键偏差原因 / 需要怎么调整" />
        </el-form-item>
        <el-form-item label="调整项(JSON)">
          <el-input v-model="reviewForm.adjustments_text" type="textarea" :rows="2"
            placeholder='[{"type":"kpi","target":"F_REVENUE","action":"调高目标"}]' />
        </el-form-item>
        <el-form-item label="下期优先级">
          <el-input v-model="reviewForm.next_priorities_text" type="textarea" :rows="2"
            placeholder='["聚焦营收增长", "改善现金流"]' />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="saveDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="saveReview">保存</el-button>
      </template>
    </el-dialog>

    <!-- 历史复盘记录弹窗 -->
    <el-dialog v-model="showHistoryDialog" title="📚 历史复盘记录" width="600">
      <div v-if="reviewRecords.length === 0" style="color:#909399;padding:20px;text-align:center;">暂无历史复盘记录</div>
      <el-timeline v-else>
        <el-timeline-item v-for="rec in reviewRecords" :key="rec.id" :timestamp="rec.review_date + ' · ' + (rec.review_type === 'quarterly' ? '季度战略回顾' : '月度运营复盘')" placement="top">
          <el-card shadow="never" style="border:1px solid #e2e8f0;">
            <div style="font-size:13px;color:#334155;white-space:pre-wrap;">{{ rec.summary }}</div>
            <div v-if="rec.next_priorities?.length" style="margin-top:8px;font-size:12px;color:#64748b;">
              下期优先级：{{ rec.next_priorities.join(' / ') }}
            </div>
          </el-card>
        </el-timeline-item>
      </el-timeline>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from "vue"
import { useRoute, useRouter } from "vue-router"
import { ElMessage } from "element-plus"
import api from "../api/index"

const route = useRoute()
const $router = useRouter()

// ── 状态 ──
const maps = ref<any[]>([])
const selectedMap = ref<number | null>(null)
const mapTitle = ref("")
const loading = ref(false)
const period = ref("month")
const summary = ref<any>(null)
const dimensions = ref<any[]>([])
const focusItems = ref<any[]>([])
const actionPlans = ref<any[]>([])
const showKpiDialog = ref(false)
// ── 复盘持久化（大PDCA Act闭环 2026-08-27） ──
const reviewRecords = ref<any[]>([])
const saveDialogVisible = ref(false)
const showHistoryDialog = ref(false)
const saving = ref(false)
const reviewForm = reactive({
  review_type: "quarterly",
  review_date: "",
  summary: "",
  adjustments_text: "",
  next_priorities_text: "",
})
const selectedObjName = ref("")
const selectedKpis = ref<any[]>([])

// ── 双会议模板状态 ──
const meetingType = ref("strategic")
const deviations = ref<any[]>([])
const krs = ref<any[]>([])
const loadingDeviations = ref(false)

// ── 计算属性 ──
const pendingCount = () => actionPlans.value.filter((p:any) => p.status === 'pending').length
const inProgressCount = () => actionPlans.value.filter((p:any) => p.status === 'in_progress').length
const doneCount = () => actionPlans.value.filter((p:any) => p.status === 'completed').length
const overdueCount = () => actionPlans.value.filter((p:any) => p.status !== 'completed' && isOverdue(p)).length

// ── 加载 ──
async function loadReview() {
  if (!selectedMap.value) return
  loading.value = true
  try {
    const r: any = await api.get(`/maps/${selectedMap.value}/review`)
    mapTitle.value = r.title
    summary.value = r.summary
    dimensions.value = r.dimensions || []
    focusItems.value = r.focus_items || []
    actionPlans.value = r.action_plans || []
    // 联动加载偏差数据
    await loadDeviations()
    await loadKrs()
    await loadReviewRecords()
  } catch (e: any) {
    ElMessage.error("加载战略回顾数据失败")
  } finally {
    loading.value = false
  }
}

// ── 加载偏差数据（从差异分析模块联动） ──
async function loadDeviations() {
  loadingDeviations.value = true
  try {
    const r: any = await api.get('/deviations', { params: { hierarchical: true, page_size: 20 } })
    const data = r.data || r.items || r || []
    deviations.value = Array.isArray(data) ? data : []
  } catch (_) {
    deviations.value = []
  } finally {
    loadingDeviations.value = false
  }
}

// ── 加载KR进度数据 ──
async function loadKrs() {
  try {
    const r: any = await api.get('/maps/' + selectedMap.value + '/krs')
    krs.value = r.data || r || []
  } catch (_) {
    krs.value = []
  }
}

// ── 复盘记录加载/保存（大PDCA Act闭环 2026-08-27） ──
async function loadReviewRecords() {
  if (!selectedMap.value) return
  try {
    const r: any = await api.get(`/maps/${selectedMap.value}/review-records`)
    reviewRecords.value = r.data || []
  } catch (_) {
    reviewRecords.value = []
  }
}

function openSaveDialog() {
  reviewForm.review_type = "quarterly"
  reviewForm.review_date = new Date().toISOString().slice(0, 10)
  reviewForm.summary = ""
  reviewForm.adjustments_text = ""
  reviewForm.next_priorities_text = ""
  saveDialogVisible.value = true
}

async function saveReview() {
  if (!selectedMap.value || !reviewForm.summary.trim()) {
    ElMessage.warning("请填写复盘结论")
    return
  }
  saving.value = true
  try {
    let adjustments: any[] = []
    let nextPriorities: string[] = []
    try { adjustments = reviewForm.adjustments_text ? JSON.parse(reviewForm.adjustments_text) : [] } catch { ElMessage.warning("调整项JSON格式错误"); return }
    try { nextPriorities = reviewForm.next_priorities_text ? JSON.parse(reviewForm.next_priorities_text) : [] } catch { ElMessage.warning("优先级JSON格式错误"); return }
    await api.post(`/maps/${selectedMap.value}/review-records`, {
      review_type: reviewForm.review_type,
      review_date: reviewForm.review_date || new Date().toISOString().slice(0, 10),
      summary: reviewForm.summary,
      adjustments,
      next_priorities: nextPriorities,
    })
    ElMessage.success("复盘结论已保存")
    saveDialogVisible.value = false
    await loadReviewRecords()
  } catch (e: any) {
    ElMessage.error("保存失败: " + (e?.message || ""))
  } finally {
    saving.value = false
  }
}

// ── 会议类型切换 ──
function onMeetingTypeChange() {
  if (selectedMap.value) {
    loadReview()
  }
}

// ── 工具函数 ──
function badgeIcon(level: string) {
  return level === 'green' ? '🟢' : level === 'yellow' ? '🟡' : level === 'red' ? '🔴' : '⚪'
}

function fmtValue(val: any, code: string) {
  if (val == null) return '-'
  if (typeof val === 'number') {
    if (Math.abs(val) >= 10000) return (val / 10000).toFixed(1) + '万'
    return val.toLocaleString()
  }
  return val
}

function showObjKpis(obj: any) {
  selectedObjName.value = obj.name
  selectedKpis.value = obj.kpis || []
  showKpiDialog.value = true
}

function getPlansByKpi(kpis: any[]) {
  if (!kpis || !actionPlans.value.length) return null
  const kpiIds = kpis.map((k:any) => k.kpi_id)
  return actionPlans.value.filter((p:any) => kpiIds.includes(p.kpi_id))
}

function planStatus(p: any) {
  if (p.status === 'completed') return 'done'
  if (isOverdue(p)) return 'overdue'
  if (p.status === 'in_progress') return 'active'
  return 'pending'
}

function planIcon(p: any) {
  if (p.status === 'completed') return '✅'
  if (isOverdue(p)) return '🔴'
  if (p.status === 'in_progress') return '🔄'
  return '⏳'
}

function planLabel(p: any) {
  const labels: Record<string, string> = { pending: '待处理', in_progress: '进行中', completed: '已完成', cancelled: '已取消' }
  return labels[p.status] || p.status
}

function planTagType(p: any) {
  if (p.status === 'completed') return 'success'
  if (isOverdue(p)) return 'danger'
  if (p.status === 'in_progress') return 'warning'
  return 'info'
}

function isOverdue(p: any) {
  if (p.status === 'completed' || !p.due_date) return false
  return new Date(p.due_date) < new Date()
}

function dueText(p: any) {
  if (!p.due_date) return ''
  const due = new Date(p.due_date)
  const now = new Date()
  const diff = Math.ceil((due.getTime() - now.getTime()) / 86400000)
  if (diff < 0) return `逾期${Math.abs(diff)}天`
  if (diff === 0) return '今日截止'
  return `剩余${diff}天`
}

function goCanvas() {
  if (selectedMap.value) {
    $router.push('/maps/canvas/' + selectedMap.value)
  }
}

onMounted(async () => {
  const r: any = await api.get('/maps')
  maps.value = r.data || []
  const id = route.params.id ? Number(route.params.id) : (maps.value[0]?.id || null)
  if (id) {
    selectedMap.value = id
    await loadReview()
  }
})
</script>

<style scoped>
.review-page { padding: 20px; height: calc(100vh - 60px); overflow-y: auto; }
.review-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-shrink: 0; }
.review-header .header-left { display: flex; align-items: center; gap: 12px; }
.review-header h3 { margin: 0; font-size: 18px; }
.review-header .header-right { display: flex; align-items: center; }
.loading-wrap { padding: 40px; }
.summary-cards { display: flex; gap: 16px; margin-bottom: 20px; }
.s-card { padding: 20px; border-radius: 12px; flex: 1; }
.s-card.overall { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; }
.s-card-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; }
.score { font-size: 36px; font-weight: 700; }
.score-label { font-size: 14px; opacity: 0.8; }
.s-card-btm { display: flex; gap: 16px; font-size: 13px; }
.stat-item { opacity: 0.9; }
.dim-matrix { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
.dim-col { background: #fff; border-radius: 8px; padding: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.dim-head { font-size: 14px; font-weight: 600; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.dim-body { display: flex; flex-direction: column; gap: 6px; }
.obj-row { display: flex; align-items: center; gap: 6px; padding: 8px; border-radius: 6px; cursor: pointer; transition: background 0.2s; font-size: 13px; }
.obj-row:hover { background: #f5f7fa; }
.obj-red { background: #fef0f0; }
.obj-yellow { background: #fdf6ec; }
.obj-green { background: #f0f9eb; }
.obj-gray { background: #fafafa; }
.obj-badge { font-size: 12px; }
.obj-info { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.obj-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.obj-ratio { font-size: 11px; color: #999; }
.focus-section { margin-bottom: 24px; }
.focus-title { font-size: 16px; margin: 0 0 12px 0; }
.focus-card { background: #fff; border-radius: 8px; padding: 12px; margin-bottom: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); cursor: pointer; }
.focus-red { border-left: 4px solid #f56c6c; }
.focus-yellow { border-left: 4px solid #e6a23c; }
.focus-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.focus-level { font-size: 11px; padding: 2px 6px; border-radius: 4px; font-weight: 600; }
.focus-red .focus-level { background: #fef0f0; color: #f56c6c; }
.focus-yellow .focus-level { background: #fdf6ec; color: #e6a23c; }
.focus-name { font-weight: 600; font-size: 14px; }
.focus-kpis { padding-left: 20px; margin-bottom: 6px; }
.fkpi-row { display: flex; justify-content: space-between; font-size: 13px; padding: 4px 0; }
.fkpi-name { color: #666; }
.fkpi-val { font-weight: 500; }
.focus-plans { padding-left: 20px; margin-top: 4px; border-top: 1px solid #f0f0f0; padding-top: 6px; }
.fplan-row { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 4px 0; }
.fplan-status { flex-shrink: 0; }
.fplan-title { flex: 1; }
.fplan-assignee { color: #999; }
.fplan-due { color: #f56c6c; font-size: 11px; }
.plans-section { margin-bottom: 24px; }
.plans-title { font-size: 16px; margin: 0 0 12px 0; }
.plans-stats { display: flex; gap: 8px; margin-bottom: 12px; }
.kpi-detail-row { border: 1px solid #eee; border-radius: 8px; padding: 12px; margin-bottom: 8px; }
.kpi-red { border-left: 4px solid #f56c6c; }
.kpi-yellow { border-left: 4px solid #e6a23c; }
.kpi-green { border-left: 4px solid #67c23a; }
.kpi-gray { border-left: 4px solid #ccc; }
.kpi-detail-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.kpi-detail-name { font-weight: 600; font-size: 14px; }
.kpi-detail-body { padding-left: 24px; }
.kpi-detail-item { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 13px; }
.kpi-detail-item .label { color: #999; width: 60px; }
.kpi-detail-item .val { font-weight: 500; }

/* ── 双会议模板 ── */
.meeting-type-bar { display: flex; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 8px; }
.op-agenda-cards,
.linkage-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 24px; }
.agenda-card,
.linkage-card { background: #fff; border-radius: 12px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); border: 1px solid #f0f0f0; }
.agenda-card-title,
.linkage-card-title { font-size: 15px; font-weight: 600; margin-bottom: 12px; color: #333; padding-bottom: 8px; border-bottom: 2px solid #f0f2f5; }
.agenda-card-body,
.linkage-card-body { font-size: 13px; }
.agenda-dim-row,
.linkage-dim-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid #f5f5f5; }
.agenda-dim-row:last-child,
.linkage-dim-row:last-child { border-bottom: none; }
.agenda-dim-icon,
.linkage-dim-icon { font-size: 16px; }
.agenda-dim-name,
.linkage-dim-name { flex: 1; }
.agenda-dim-count { color: #999; font-size: 12px; }
.linkage-dim-info { flex: 1; display: flex; justify-content: space-between; align-items: center; }
.linkage-dim-ratio { color: #409EFF; font-size: 12px; font-weight: 500; }
.kpi-summary-row { padding: 4px 0; font-size: 13px; display: flex; align-items: center; gap: 6px; }
.deviation-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid #f5f5f5; font-size: 13px; }
.deviation-row:last-child { border-bottom: none; }
.deviation-badge { font-size: 12px; flex-shrink: 0; }
.deviation-kpi { flex: 1; color: #333; }
.deviation-rate { font-weight: 500; color: #e6a23c; }
.badge-red .deviation-rate { color: #f56c6c; }
.kr-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid #f5f5f5; }
.kr-row:last-child { border-bottom: none; }
.kr-name { flex: 1; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.action-plan-preview { margin-top: 8px; border-top: 1px solid #f0f0f0; padding-top: 8px; }
.ap-row { display: flex; align-items: center; gap: 6px; padding: 4px 0; font-size: 12px; }
.ap-status { flex-shrink: 0; }
.ap-title { flex: 1; color: #666; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.no-data { color: #999; padding: 12px; text-align: center; font-size: 13px; }
@media screen and (max-width: 768px) {
  .op-agenda-cards,
  .linkage-cards { grid-template-columns: 1fr; }
}
</style>
