import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { Map, Marker, Popup } from '@vis.gl/react-maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
import { useBaseMapStyle } from '@common/hooks/useBaseMapStyle';
import { fetchRescueOps, fetchRescueScenarios } from '../services/rescueApi';
import type { RescueOpsItem, RescueScenarioItem } from '../services/rescueApi';

/* ─── Types ─── */
type Severity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'RESOLVED';
type DetailView = 0 | 1 | 2;

interface RescueScenario {
  id: string;
  name: string;
  severity: Severity;
  timeStep: string;
  datetime: string;
  gm: string;
  list: string;
  trim: string;
  buoyancy: number;
  oilRate: string;
  bmRatio: string;
  description: string;
  compartments: { name: string; status: string; color: string }[];
  assessment: { label: string; value: string; color: string }[];
  actions: { time: string; text: string; color: string }[];
}

const SEV_STYLE: Record<Severity, { bg: string; color: string; label: string }> = {
  CRITICAL: { bg: 'rgba(239,68,68,0.15)', color: 'var(--color-danger)', label: 'CRITICAL' },
  HIGH: { bg: 'rgba(249,115,22,0.15)', color: 'var(--color-warning)', label: 'HIGH' },
  MEDIUM: { bg: 'rgba(234,179,8,0.15)', color: 'var(--color-caution)', label: 'MEDIUM' },
  RESOLVED: { bg: 'rgba(34,197,94,0.15)', color: 'var(--color-success)', label: 'RESOLVED' },
};

const SEV_COLOR: Record<Severity, string> = {
  CRITICAL: 'var(--color-danger)',
  HIGH: 'var(--color-warning)',
  MEDIUM: 'var(--color-caution)',
  RESOLVED: 'var(--color-success)',
};

/* ─── Color helpers ─── */
function gmColor(v: number) {
  return v < 1.0
    ? 'var(--color-danger)'
    : v < 1.5
      ? 'var(--color-caution)'
      : 'var(--color-success)';
}
function listColor(v: number) {
  return v > 20 ? 'var(--color-danger)' : v > 10 ? 'var(--color-caution)' : 'var(--color-success)';
}
function buoyColor(v: number) {
  return v < 30 ? 'var(--color-danger)' : v < 50 ? 'var(--color-caution)' : 'var(--color-success)';
}
function oilColor(v: number) {
  return v > 100
    ? 'var(--color-danger)'
    : v > 30
      ? 'var(--color-warning)'
      : v > 0
        ? 'var(--color-caution)'
        : 'var(--color-success)';
}

/* ─── API 시나리오 → 로컬 타입 변환 ─── */
function toRescueScenario(s: RescueScenarioItem, i: number): RescueScenario {
  return {
    id: `S-${String(i + 1).padStart(2, '0')}`,
    name: s.description?.split('.')[0] ?? s.timeStep,
    severity: s.svrtCd as Severity,
    timeStep: s.timeStep,
    datetime: s.scenarioDtm
      ? new Date(s.scenarioDtm).toLocaleString('ko-KR', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
        }) + ' KST'
      : '—',
    gm: String(s.gmM ?? 0),
    list: String(s.listDeg ?? 0),
    trim: String(s.trimM ?? 0),
    buoyancy: s.buoyancyPct ?? 0,
    oilRate: s.oilRateLpm != null ? `${s.oilRateLpm} L/min` : '— L/min',
    bmRatio: s.bmRatioPct != null ? `${s.bmRatioPct}%` : '—%',
    description: s.description ?? '',
    compartments: s.compartments ?? [],
    assessment: s.assessment ?? [],
    actions: s.actions ?? [],
  };
}

/* ─── ChartData 타입 ─── */
interface ChartDataItem {
  id: string;
  label: string;
  gm: number;
  list: number;
  buoy: number;
  oil: number;
  bm: number;
  severity: Severity;
}

/* ─── 시나리오 관리 요건 ─── */
const SCENARIO_MGMT_GUIDELINES = [
  '긴급구난 R&D 분석 결과는 시간 단계별 시나리오의 형태로 관리되어야 함',
  '각 시나리오는 사고 발생 시점부터 구난 진행 단계별 상태 변화를 포함하여야 함',
  '시나리오별 분석 결과는 사고 단위로 기존 사고 정보와 연계되어 관리되어야 함',
  '동일 사고에 대해 복수 시나리오(시간대, 조건별)가 존재할 경우, 상호 비교·검토가 되어야 함',
  '시나리오별 분석결과는 긴급구난 대응 판단을 지원할 수 있도록 요약 정보 형태로 제공되어야 함',
  '시나리오 관리 기능은 기존 통합지원시스템의 흐름과 연계되어 실질적인 구난 대응 업무에 활용 가능하도록 반영되어야 함',
  '긴급구난 시나리오 관리 기능 구현 시 1차 구축 완료된 GIS기능을 활용하여 구축하여 재개발하거나 중복구현하지 않도록 함',
];

/* ─── Mock 시나리오 (API 미연결 시 폴백) — 긴급구난 모델 이론 기반 10개 ─── */
const MOCK_SCENARIOS: RescueScenarioItem[] = [
  {
    scenarioSn: 1,
    rescueOpsSn: 1,
    timeStep: 'T+0h',
    scenarioDtm: '2024-10-27T01:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.8,
    listDeg: 15.0,
    trimM: 2.5,
    buoyancyPct: 30.0,
    oilRateLpm: 100.0,
    bmRatioPct: 92.0,
    description:
      '좌현 35° 충돌로 No.1P 화물탱크 파공. 벙커C유 유출 개시. 손상복원성 분석: 초기 GM 0.8m으로 IMO 기준(1.0m) 미달, 복원력 위험 판정.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'BREACHED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'RISK', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '위험 (GM 0.8m < IMO 1.0m)', color: 'var(--red)' },
      { label: '유출 위험', value: '활발 유출중 (100 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 92% (경계)', color: 'var(--orange)' },
      { label: '승선인원', value: '15/20 확인, 5명 수색중', color: 'var(--red)' },
    ],
    actions: [
      { time: '10:30', text: '충돌 발생, VHF Ch.16 조난 통보', color: 'var(--red)' },
      { time: '10:32', text: 'EPIRB 자동 발신 확인', color: 'var(--red)' },
      { time: '10:35', text: '해경 3009함 출동 지시', color: 'var(--orange)' },
      { time: '10:42', text: '인근 선박 구조 활동 개시', color: 'var(--cyan)' },
    ],
    sortOrd: 1,
  },
  {
    scenarioSn: 2,
    rescueOpsSn: 1,
    timeStep: 'T+30m',
    scenarioDtm: '2024-10-27T02:00:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.7,
    listDeg: 17.0,
    trimM: 2.8,
    buoyancyPct: 28.0,
    oilRateLpm: 120.0,
    bmRatioPct: 90.0,
    description:
      '잠수사 수중 조사 결과 좌현 No.1P 파공 크기 1.2m×0.8m 확인. Bernoulli 유입률 모델 적용: 수두차 4.5m 기준 유입률 약 2.1㎥/min.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'BREACHED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'RISK', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '악화 (GM 0.7m, GZ 커브 감소)', color: 'var(--red)' },
      { label: '유출 위험', value: '증가 (120 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 90% — 종강도 모니터링 개시', color: 'var(--orange)' },
      { label: '승선인원', value: '15명 퇴선, 5명 수색중', color: 'var(--red)' },
    ],
    actions: [
      { time: '10:50', text: '잠수사 투입, 수중 손상 조사 개시', color: 'var(--cyan)' },
      { time: '10:55', text: '파공 규모 확인: 1.2m×0.8m', color: 'var(--red)' },
      { time: '11:00', text: '손상복원성 재계산 — IMO 기준 위험', color: 'var(--red)' },
      { time: '11:00', text: '유출유 방제선 배치 요청', color: 'var(--orange)' },
    ],
    sortOrd: 2,
  },
  {
    scenarioSn: 3,
    rescueOpsSn: 1,
    timeStep: 'T+1h',
    scenarioDtm: '2024-10-27T02:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.65,
    listDeg: 18.5,
    trimM: 3.0,
    buoyancyPct: 26.0,
    oilRateLpm: 135.0,
    bmRatioPct: 89.0,
    description:
      '해경 3009함 현장 도착, SAR 작전 개시. Leeway 표류 예측 모델: 풍속 8m/s, 해류 2.5kn NE — 실종자 표류 반경 1.2nm. GZ 최대 복원력 각도 25°로 감소.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODING', color: 'var(--red)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '한계 접근 (GM 0.65m)', color: 'var(--red)' },
      { label: '유출 위험', value: '파공 확대 우려 (135 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 89% — Hogging 증가', color: 'var(--orange)' },
      { label: '인명구조', value: '실종 5명 수색중, 표류 1.2nm', color: 'var(--red)' },
    ],
    actions: [
      { time: '11:10', text: '해경 3009함 현장 도착, SAR 구역 설정', color: 'var(--cyan)' },
      { time: '11:15', text: 'Leeway 표류 예측 모델 적용', color: 'var(--cyan)' },
      { time: '11:20', text: '회전익 항공기 수색 개시', color: 'var(--cyan)' },
      { time: '11:30', text: '#2 Port Tank 2차 침수 징후', color: 'var(--red)' },
    ],
    sortOrd: 3,
  },
  {
    scenarioSn: 4,
    rescueOpsSn: 1,
    timeStep: 'T+2h',
    scenarioDtm: '2024-10-27T03:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.5,
    listDeg: 20.0,
    trimM: 3.5,
    buoyancyPct: 22.0,
    oilRateLpm: 160.0,
    bmRatioPct: 86.0,
    description:
      '격벽 관통으로 #2 Port Tank 침수 확대. 자유표면효과(FSE) 보정: GM_fluid = 0.5m. 종강도: Sagging 모멘트 86%. 침몰 위험 단계 진입.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'RISK', color: 'var(--orange)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '위기 (GM 0.5m, FSE 보정)', color: 'var(--red)' },
      { label: '유출 위험', value: '최대치 접근 (160 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 86% — Sagging 경고', color: 'var(--red)' },
      { label: '승선인원', value: '실종 3명 발견, 2명 수색', color: 'var(--orange)' },
    ],
    actions: [
      { time: '12:00', text: '#2 Port Tank 격벽 관통 침수', color: 'var(--red)' },
      { time: '12:10', text: '자유표면효과(FSE) 보정 재계산', color: 'var(--red)' },
      { time: '12:15', text: '긴급 Counter-Flooding 검토', color: 'var(--orange)' },
      { time: '12:30', text: '실종자 3명 추가 발견 구조', color: 'var(--green)' },
    ],
    sortOrd: 4,
  },
  {
    scenarioSn: 5,
    rescueOpsSn: 1,
    timeStep: 'T+3h',
    scenarioDtm: '2024-10-27T04:30:00.000Z',
    svrtCd: 'HIGH',
    gmM: 0.55,
    listDeg: 16.0,
    trimM: 3.2,
    buoyancyPct: 25.0,
    oilRateLpm: 140.0,
    bmRatioPct: 87.0,
    description:
      'Counter-Flooding 실시: #3 Stbd Tank에 평형수 280톤 주입, 횡경사 20°→16° 교정. 종강도: 중량 재배분으로 BM 87% 유지.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'RISK', color: 'var(--orange)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '개선 중 (GM 0.55m, 경사 16°)', color: 'var(--orange)' },
      { label: '유출 위험', value: '감소 추세 (140 L/min)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 87% — Counter-Flooding 평가', color: 'var(--orange)' },
      { label: '구조 상황', value: '실종 2명 수색 지속', color: 'var(--orange)' },
    ],
    actions: [
      { time: '12:45', text: 'Counter-Flooding — #3 Stbd 주입 개시', color: 'var(--orange)' },
      { time: '13:00', text: '평형수 280톤 주입, 경사 교정 진행', color: 'var(--cyan)' },
      { time: '13:15', text: '종강도 재계산 — 허용 범위 내', color: 'var(--cyan)' },
      { time: '13:30', text: '횡경사 16° 안정화 확인', color: 'var(--green)' },
    ],
    sortOrd: 5,
  },
  {
    scenarioSn: 6,
    rescueOpsSn: 1,
    timeStep: 'T+6h',
    scenarioDtm: '2024-10-27T07:30:00.000Z',
    svrtCd: 'HIGH',
    gmM: 0.7,
    listDeg: 12.0,
    trimM: 2.5,
    buoyancyPct: 32.0,
    oilRateLpm: 80.0,
    bmRatioPct: 90.0,
    description:
      '수중패치 설치, 유입률 감소. GM 0.7m 회복. Trim/Stability Booklet 기준 예인 가능 최소 조건(GM≥0.5m, List≤15°) 충족.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '개선 (GM 0.7m, 예인 가능)', color: 'var(--orange)' },
      { label: '유출 위험', value: '수중패치 효과 (80 L/min)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 90% — 안정 범위', color: 'var(--green)' },
      { label: '구조 상황', value: '전원 구조 완료', color: 'var(--green)' },
    ],
    actions: [
      { time: '14:00', text: '수중패치 설치 작업 개시', color: 'var(--cyan)' },
      { time: '14:30', text: '수중패치 설치 완료', color: 'var(--green)' },
      { time: '15:00', text: '해상크레인 도착, 잔류유 이적 준비', color: 'var(--cyan)' },
      { time: '16:30', text: '잔류유 1차 이적 완료 (45kL)', color: 'var(--green)' },
    ],
    sortOrd: 6,
  },
  {
    scenarioSn: 7,
    rescueOpsSn: 1,
    timeStep: 'T+8h',
    scenarioDtm: '2024-10-27T09:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 0.8,
    listDeg: 10.0,
    trimM: 2.0,
    buoyancyPct: 38.0,
    oilRateLpm: 55.0,
    bmRatioPct: 91.0,
    description:
      '오일붐 2중 전개, 유회수기 3대 가동. GNOME 확산 모델: 12시간 후 확산 면적 2.3km² 예측. 기계적 회수율 35%.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '안정 (GM 0.8m)', color: 'var(--orange)' },
      { label: '유출 위험', value: '방제 진행 (55 L/min, 회수 35%)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 91%', color: 'var(--green)' },
      { label: '방제 현황', value: '오일붐 2중, 유회수기 3대', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '17:00', text: '오일붐 1차 전개 (500m)', color: 'var(--cyan)' },
      { time: '17:30', text: '오일붐 2차 전개 (이중 방어선)', color: 'var(--cyan)' },
      { time: '17:45', text: '유회수기 3대 배치·가동', color: 'var(--cyan)' },
      { time: '18:30', text: 'GNOME 확산 예측 갱신', color: 'var(--orange)' },
    ],
    sortOrd: 7,
  },
  {
    scenarioSn: 8,
    rescueOpsSn: 1,
    timeStep: 'T+12h',
    scenarioDtm: '2024-10-27T13:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 0.9,
    listDeg: 8.0,
    trimM: 1.5,
    buoyancyPct: 45.0,
    oilRateLpm: 30.0,
    bmRatioPct: 94.0,
    description:
      '예인 개시. 예인 저항 Rt=1/2·ρ·Cd·A·V²  기반 4,000HP급 배정. 목포항 42nm, 예인 속도 3kn, ETA 14h.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '안정 (GM 0.9m)', color: 'var(--orange)' },
      { label: '유출 위험', value: '억제 중 (30 L/min)', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 94%', color: 'var(--green)' },
      { label: '예인 상태', value: '목포항, ETA 14h, 3kn', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '18:00', text: '예인 접속, 예인삭 250m 전개', color: 'var(--cyan)' },
      { time: '18:30', text: '예인 개시 (목포항 방향)', color: 'var(--cyan)' },
      { time: '20:00', text: '야간 감시 체제 전환', color: 'var(--orange)' },
      { time: '22:30', text: '예인 진행률 30%, 선체 안정', color: 'var(--green)' },
    ],
    sortOrd: 8,
  },
  {
    scenarioSn: 9,
    rescueOpsSn: 1,
    timeStep: 'T+18h',
    scenarioDtm: '2024-10-27T19:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 1.0,
    listDeg: 5.0,
    trimM: 1.0,
    buoyancyPct: 55.0,
    oilRateLpm: 15.0,
    bmRatioPct: 96.0,
    description:
      '예인 진행률 65%. 파랑 응답 분석(RAO): 유의파고 1.2m, 주기 6s — 횡동요 ±3° 안전 범위. 잔류 유출률 15 L/min.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'STABLE', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '양호 (GM 1.0m, IMO 충족)', color: 'var(--green)' },
      { label: '유출 위험', value: '미량 유출 (15 L/min)', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 96% 정상', color: 'var(--green)' },
      { label: '예인 상태', value: '진행률 65%, ETA 5.5h', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '00:00', text: '야간 예인 정상 진행', color: 'var(--green)' },
      { time: '02:00', text: '파랑 응답 분석 — 안전 확인', color: 'var(--green)' },
      { time: '03:00', text: '잔류유 유출률 15 L/min', color: 'var(--green)' },
      { time: '04:30', text: '목포항 VTS 통보, 입항 협의', color: 'var(--cyan)' },
    ],
    sortOrd: 9,
  },
  {
    scenarioSn: 10,
    rescueOpsSn: 1,
    timeStep: 'T+24h',
    scenarioDtm: '2024-10-28T01:30:00.000Z',
    svrtCd: 'RESOLVED',
    gmM: 1.2,
    listDeg: 3.0,
    trimM: 0.5,
    buoyancyPct: 75.0,
    oilRateLpm: 5.0,
    bmRatioPct: 98.0,
    description:
      '목포항 접안 완료. 잔류유 전량 이적(120kL). 최종 GM 1.2m IMO 충족, BM 98% 정상. 방제 총 회수량 85kL (회수율 71%). 상황 종료.',
    compartments: [
      { name: '#1 FP Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: '#1 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'STABLE', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '안전 (GM 1.2m)', color: 'var(--green)' },
      { label: '유출 위험', value: '차단 완료', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 98% 정상', color: 'var(--green)' },
      { label: '최종 상태', value: '접안 완료, 상황 종료', color: 'var(--green)' },
    ],
    actions: [
      { time: '06:00', text: '목포항 접근, 도선사 대기', color: 'var(--cyan)' },
      { time: '08:00', text: '도선사 승선, 접안 개시', color: 'var(--cyan)' },
      { time: '09:30', text: '접안 완료, 잔류유 이적선 접현', color: 'var(--green)' },
      { time: '10:30', text: '잔류유 전량 이적, 상황 종료', color: 'var(--green)' },
    ],
    sortOrd: 10,
  },
];

const MOCK_OPS: RescueOpsItem[] = [
  {
    rescueOpsSn: 1,
    acdntSn: 1,
    opsCd: 'RSC-2026-001',
    acdntTpCd: 'collision',
    vesselNm: 'M/V SEA GUARDIAN',
    commanderNm: null,
    lon: 126.25,
    lat: 37.467,
    locDc: "37°28'N, 126°15'E",
    depthM: 25.0,
    currentDc: '2.5kn NE',
    gmM: 0.8,
    listDeg: 15.0,
    trimM: 2.5,
    buoyancyPct: 30.0,
    oilRateLpm: 100.0,
    bmRatioPct: 92.0,
    totalCrew: 20,
    survivors: 15,
    missing: 5,
    hydroData: null,
    gmdssData: null,
    sttsCd: 'ACTIVE',
    regDtm: '2024-10-27T01:30:00.000Z',
  },
];

/* ═══════════════════════════════════════════════════════════════════
   RescueScenarioView
   ═══════════════════════════════════════════════════════════════════ */
export function RescueScenarioView() {
  const [ops, setOps] = useState<RescueOpsItem[]>([]);
  const [apiScenarios, setApiScenarios] = useState<RescueScenarioItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [selectedIncident, setSelectedIncident] = useState(0);
  const [checked, setChecked] = useState<Set<string>>(new Set());
  const [selectedId, setSelectedId] = useState('');
  const [sortBy, setSortBy] = useState<'time' | 'risk'>('time');
  const [detailView, setDetailView] = useState<DetailView>(0);
  const [newScnModalOpen, setNewScnModalOpen] = useState(false);
  const [guideOpen, setGuideOpen] = useState(false);

  const loadScenarios = useCallback(async (opsSn: number) => {
    setLoading(true);
    try {
      const items = await fetchRescueScenarios(opsSn);
      setApiScenarios(items.length > 0 ? items : MOCK_SCENARIOS);
    } catch {
      setApiScenarios(MOCK_SCENARIOS);
    } finally {
      setLoading(false);
    }
  }, []);

  const loadOps = useCallback(async () => {
    try {
      const items = await fetchRescueOps();
      if (items.length > 0) {
        setOps(items);
        loadScenarios(items[0].rescueOpsSn);
      } else {
        setOps(MOCK_OPS);
        setApiScenarios(MOCK_SCENARIOS);
        setLoading(false);
      }
    } catch {
      setOps(MOCK_OPS);
      setApiScenarios(MOCK_SCENARIOS);
      setLoading(false);
    }
  }, [loadScenarios]);

  useEffect(() => {
    loadOps();
  }, [loadOps]);

  useEffect(() => {
    if (ops.length > 0 && ops[selectedIncident]) {
      loadScenarios(ops[selectedIncident].rescueOpsSn);
    }
  }, [selectedIncident, ops, loadScenarios]);

  /* API 시나리오 → 로컬 타입 변환 */
  const scenarios: RescueScenario[] = apiScenarios.map(toRescueScenario);

  /* checked / selectedId: apiScenarios 변경 시 초기화 */
  useEffect(() => {
    setChecked(new Set(scenarios.map((s) => s.id)));
    if (scenarios.length > 0) setSelectedId(scenarios[0].id);
  }, [apiScenarios]); // eslint-disable-line react-hooks/exhaustive-deps

  /* chartData: scenarios에서 파생 */
  const chartData: ChartDataItem[] = scenarios.map((s) => ({
    id: s.id,
    label: s.timeStep,
    gm: parseFloat(s.gm),
    list: parseFloat(s.list),
    buoy: s.buoyancy,
    oil: parseFloat(s.oilRate),
    bm: parseFloat(s.bmRatio),
    severity: s.severity,
  }));

  const selected = scenarios.find((s) => s.id === selectedId);

  const sorted = [...scenarios].sort((a, b) => {
    if (sortBy === 'risk') {
      const order: Record<Severity, number> = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, RESOLVED: 3 };
      return order[a.severity] - order[b.severity];
    }
    return 0;
  });

  const toggleCheck = (id: string) => {
    setChecked((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  return (
    <div className="flex flex-col flex-1 w-full h-full overflow-hidden bg-bg-base">
      {/* ── Header ── */}
      <div className="px-5 py-3.5 border-b border-stroke flex items-center justify-between shrink-0">
        <div className="flex items-center gap-2.5">
          <span className="text-base">📊</span>
          <div>
            <div className="text-title-4 font-bold">긴급구난 시나리오 관리</div>
            <div className="text-label-2 text-fg-disabled">
              시간 단계별 시나리오 비교·검토 및 구난 의사결정 지원 (SFR-009)
            </div>
          </div>
        </div>
        <div className="flex gap-2 items-center">
          <select
            value={selectedIncident}
            onChange={(e) => setSelectedIncident(Number(e.target.value))}
            className="prd-i w-[280px] text-label-2"
          >
            {ops.map((op, i) => (
              <option key={op.rescueOpsSn} value={i}>
                {op.opsCd} · {op.vesselNm}
              </option>
            ))}
          </select>
          <button
            onClick={() => setNewScnModalOpen(true)}
            className="cursor-pointer whitespace-nowrap font-semibold text-color-accent text-label-2 px-[14px] py-1.5 rounded-sm"
            style={{
              border: '1px solid rgba(6,182,212,.3)',
              background: 'rgba(6,182,212,.08)',
            }}
          >
            + 신규 시나리오
          </button>
          <button
            onClick={() => setGuideOpen((v) => !v)}
            className="cursor-pointer whitespace-nowrap font-semibold text-label-2 px-[14px] py-1.5 rounded-sm"
            style={{
              border: '1px solid rgba(6,182,212,.15)',
              background: guideOpen ? 'rgba(6,182,212,.12)' : 'transparent',
              color: guideOpen ? 'var(--color-accent)' : 'var(--fg-disabled)',
            }}
          >
            {guideOpen ? '▴ 관리 요건' : '▾ 관리 요건'}
          </button>
        </div>
      </div>

      {/* ── 시나리오 관리 요건 가이드라인 ── */}
      {guideOpen && (
        <div className="border-b border-stroke px-5 py-3 bg-bg-surface shrink-0">
          <p className="text-label-1 font-bold mb-2">시나리오 관리 요건</p>
          <ul className="flex flex-col gap-1">
            {SCENARIO_MGMT_GUIDELINES.map((g, i) => (
              <li key={i} className="text-caption text-fg-sub leading-relaxed flex gap-1.5">
                <span className="text-color-accent shrink-0">{i + 1}.</span>
                <span>{g}</span>
              </li>
            ))}
          </ul>
        </div>
      )}

      {/* ── Content: Left List + Right Detail ── */}
      <div className="flex flex-1 overflow-hidden">
        {/* ═══ LEFT: 시나리오 목록 ═══ */}
        <div
          className="flex flex-col overflow-hidden shrink-0 border-r border-stroke bg-bg-surface"
          style={{ width: '370px', minWidth: '370px' }}
        >
          {/* Sort bar */}
          <div className="flex items-center justify-between border-b border-stroke px-[14px] py-2.5">
            <span className="text-label-2 font-bold text-fg-disabled">
              시나리오 목록 ({scenarios.length}개)
            </span>
            <div className="flex gap-1">
              {(['time', 'risk'] as const).map((s) => (
                <button
                  key={s}
                  onClick={() => setSortBy(s)}
                  className={`cursor-pointer px-2 py-[3px] text-caption font-semibold rounded-sm border border-stroke ${
                    sortBy === s
                      ? 'bg-[rgba(6,182,212,0.08)] text-color-accent'
                      : 'bg-bg-card text-fg-disabled'
                  }`}
                >
                  {s === 'time' ? '시간순' : '위험도순'}
                </button>
              ))}
            </div>
          </div>

          {/* Card list */}
          <div
            className="flex-1 overflow-y-auto flex flex-col gap-1.5 p-2"
            style={{ scrollbarWidth: 'thin', scrollbarColor: 'var(--stroke-light) transparent' }}
          >
            {loading && scenarios.length === 0 && (
              <div className="text-center py-10 text-label-2 text-fg-disabled">
                시나리오 로딩 중...
              </div>
            )}
            {sorted.map((sc) => {
              const isSel = selectedId === sc.id;
              const sev = SEV_STYLE[sc.severity];
              return (
                <div
                  key={sc.id}
                  onClick={() => setSelectedId(sc.id)}
                  className={`hns-scn-card${isSel ? ' sel' : ''}`}
                >
                  {/* Top: checkbox + ID + severity */}
                  <div className="flex items-center justify-between mb-1.5">
                    <div className="flex items-center gap-1.5">
                      <input
                        type="checkbox"
                        checked={checked.has(sc.id)}
                        onChange={(e) => {
                          e.stopPropagation();
                          toggleCheck(sc.id);
                        }}
                        style={{ accentColor: 'var(--color-accent)' }}
                      />
                      <span className="text-label-1 font-bold">
                        {sc.id} {sc.name}
                      </span>
                    </div>
                    <span
                      className="font-bold px-2 py-[2px] rounded-lg text-caption"
                      style={{ background: sev.bg, color: sev.color }}
                    >
                      {sev.label}
                    </span>
                  </div>
                  {/* Time row */}
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <span
                      className="font-bold font-mono text-color-accent text-caption px-1.5 py-[2px] rounded-[3px]"
                      style={{ background: 'rgba(6,182,212,0.1)' }}
                    >
                      {sc.timeStep}
                    </span>
                    <span className="text-caption text-fg-disabled font-mono">{sc.datetime}</span>
                  </div>
                  {/* KPI grid */}
                  <div className="grid grid-cols-4 gap-1 font-mono text-caption">
                    {[
                      { label: 'GM', value: `${sc.gm}m`, color: gmColor(parseFloat(sc.gm)) },
                      {
                        label: '횡경사',
                        value: `${sc.list}°`,
                        color: listColor(parseFloat(sc.list)),
                      },
                      { label: '부력', value: `${sc.buoyancy}%`, color: buoyColor(sc.buoyancy) },
                      {
                        label: '유출',
                        value: sc.oilRate.split(' ')[0],
                        color: oilColor(parseFloat(sc.oilRate)),
                      },
                    ].map((m, i) => (
                      <div key={i} className="text-center p-[3px] bg-bg-base rounded-[3px]">
                        <div className="text-fg-disabled text-caption">{m.label}</div>
                        <div className="font-bold" style={{ color: m.color }}>
                          {m.value}
                        </div>
                      </div>
                    ))}
                  </div>
                  {/* Description */}
                  <div className="text-fg-sub mt-1.5 text-caption leading-[1.4]">
                    {sc.description}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Bottom actions */}
          <div className="flex gap-2 border-t border-stroke px-[14px] py-2.5">
            <button
              onClick={() => setDetailView(1)}
              className="flex-1 cursor-pointer font-bold text-static-white text-label-2 p-2 rounded-sm bg-color-navy hover:bg-color-navy-hover"
            >
              📊 선택 시나리오 비교
            </button>
            <button className="cursor-pointer font-semibold text-fg-sub text-label-2 px-[14px] py-2 rounded-sm bg-bg-card border border-stroke">
              📄 보고서
            </button>
          </div>
        </div>

        {/* ═══ RIGHT: 상세/비교 ═══ */}
        <div className="flex-1 min-w-0 flex flex-col overflow-hidden">
          {/* Detail tabs */}
          <div className="flex border-b border-stroke shrink-0 px-4 bg-bg-surface">
            {(['📋 시나리오 상세', '📊 비교 차트', '🗺 지도 오버레이'] as const).map((label, i) => (
              <button
                key={i}
                onClick={() => setDetailView(i as DetailView)}
                className={`rsc-atab ${detailView === i ? 'on' : ''}`}
              >
                {label}
              </button>
            ))}
          </div>

          {/* View content */}
          <div
            className={`flex-1 ${detailView === 2 ? 'flex flex-col overflow-hidden' : 'overflow-y-auto scrollbar-thin'}`}
          >
            {/* ─── VIEW 0: 시나리오 상세 ─── */}
            {detailView === 0 && selected && (
              <div className="p-5">
                {/* Header card */}
                <div className="px-5 py-4 rounded-[10px] bg-bg-card border border-stroke mb-4">
                  <div className="flex items-center gap-2.5 mb-2.5">
                    <span className="text-base font-extrabold font-mono text-color-accent">
                      {selected.id}
                    </span>
                    <span className="text-label-1 font-bold">{selected.name}</span>
                    <span
                      className="px-2 py-[2px] rounded-lg text-caption font-bold font-mono"
                      style={{
                        background: SEV_STYLE[selected.severity].bg,
                        color: SEV_STYLE[selected.severity].color,
                      }}
                    >
                      {selected.severity}
                    </span>
                    <span className="ml-auto text-label-2 text-fg-disabled font-mono">
                      {selected.datetime}
                    </span>
                  </div>
                  {/* 6 KPI cards */}
                  <div
                    className="grid gap-2 text-caption text-center"
                    style={{ gridTemplateColumns: 'repeat(6,1fr)' }}
                  >
                    {[
                      {
                        label: 'GM (복원심)',
                        value: `${selected.gm}m`,
                        color: gmColor(parseFloat(selected.gm)),
                      },
                      {
                        label: '횡경사 (List)',
                        value: `${selected.list}°`,
                        color: listColor(parseFloat(selected.list)),
                      },
                      {
                        label: '종경사 (Trim)',
                        value: `${selected.trim}m`,
                        color:
                          parseFloat(selected.trim) > 3
                            ? 'var(--color-danger)'
                            : 'var(--fg-default)',
                      },
                      {
                        label: '잔존부력',
                        value: `${selected.buoyancy}%`,
                        color: buoyColor(selected.buoyancy),
                      },
                      {
                        label: '유출률',
                        value: selected.oilRate,
                        color: oilColor(parseFloat(selected.oilRate)),
                      },
                      {
                        label: 'BM 비율',
                        value: selected.bmRatio,
                        color:
                          parseFloat(selected.bmRatio) > 100
                            ? 'var(--color-danger)'
                            : parseFloat(selected.bmRatio) > 85
                              ? 'var(--color-warning)'
                              : 'var(--color-success)',
                      },
                    ].map((kpi) => (
                      <div
                        key={kpi.label}
                        className="px-1 py-2 bg-bg-card rounded-md border border-stroke"
                      >
                        <div className="text-fg-disabled mb-1">{kpi.label}</div>
                        <div
                          className="text-lg font-extrabold font-mono"
                          style={{ color: kpi.color }}
                        >
                          {kpi.value}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>

                {/* 2-column: 침수구획 + 구난판단 */}
                <div className="grid grid-cols-2 gap-4 mb-4">
                  {/* 침수 구획 */}
                  <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                    <div className="text-label-2 font-bold mb-2.5">🚢 침수 구획 상태</div>
                    <div className="flex flex-col gap-1.5">
                      {selected.compartments.map((c, i) => (
                        <div
                          key={i}
                          className="flex items-center justify-between px-2.5 py-1.5 bg-bg-base rounded"
                          style={{ borderLeft: `3px solid ${c.color}` }}
                        >
                          <span className="text-caption">{c.name}</span>
                          <span
                            className="text-caption font-semibold font-mono"
                            style={{ color: c.color }}
                          >
                            {c.status}
                          </span>
                        </div>
                      ))}
                    </div>
                  </div>
                  {/* 구난 판단 */}
                  <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                    <div className="text-label-2 font-bold mb-2.5">⚠️ 구난 판단 요약</div>
                    <div className="flex flex-col gap-1.5">
                      {selected.assessment.map((a, i) => (
                        <div
                          key={i}
                          className="px-2.5 py-2 bg-bg-base rounded"
                          style={{ borderLeft: `3px solid ${a.color}` }}
                        >
                          <div className="text-caption font-bold" style={{ color: a.color }}>
                            {a.label}
                          </div>
                          <div className="text-caption text-fg-sub mt-0.5">{a.value}</div>
                        </div>
                      ))}
                    </div>
                  </div>
                </div>

                {/* 대응 조치 이력 */}
                <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                  <div className="text-label-2 font-bold mb-2.5">📋 대응 조치 이력</div>
                  <div className="flex flex-col gap-1.5">
                    {selected.actions.map((a, i) => (
                      <div
                        key={i}
                        className="flex items-center gap-2.5 px-2.5 py-1.5 bg-bg-base rounded"
                      >
                        <span
                          className="text-label-2 font-bold font-mono min-w-[40px]"
                          style={{ color: a.color }}
                        >
                          {a.time}
                        </span>
                        <div
                          className="w-1.5 h-1.5 rounded-full shrink-0"
                          style={{ background: a.color }}
                        />
                        <span className="text-caption">{a.text}</span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            )}

            {/* ─── VIEW 1: 비교 차트 ─── */}
            {detailView === 1 && <ScenarioComparison chartData={chartData} />}

            {/* ─── VIEW 2: 지도 오버레이 ─── */}
            {detailView === 2 && (
              <ScenarioMapOverlay
                ops={ops}
                selectedIncident={selectedIncident}
                scenarios={scenarios}
                selectedId={selectedId}
                checked={checked}
                onSelectScenario={setSelectedId}
              />
            )}
          </div>
        </div>
      </div>

      {/* ═══ 신규 시나리오 모달 ═══ */}
      {newScnModalOpen && <NewScenarioModal ops={ops} onClose={() => setNewScnModalOpen(false)} />}
    </div>
  );
}

/* ═══ 지도 오버레이 ═══ */
interface ScenarioMapOverlayProps {
  ops: RescueOpsItem[];
  selectedIncident: number;
  scenarios: RescueScenario[];
  selectedId: string;
  checked: Set<string>;
  onSelectScenario: (id: string) => void;
}

function ScenarioMapOverlay({
  ops,
  selectedIncident,
  scenarios,
  selectedId,
  checked,
  onSelectScenario,
}: ScenarioMapOverlayProps) {
  const [popupId, setPopupId] = useState<string | null>(null);
  const baseMapStyle = useBaseMapStyle();

  const currentOp = ops[selectedIncident] ?? null;
  const center = useMemo<[number, number]>(
    () =>
      currentOp?.lon != null && currentOp?.lat != null
        ? [currentOp.lon, currentOp.lat]
        : [126.25, 37.467],
    [currentOp],
  );

  const visibleScenarios = useMemo(
    () => scenarios.filter((s) => checked.has(s.id)),
    [scenarios, checked],
  );

  const selected = scenarios.find((s) => s.id === selectedId);

  return (
    <div className="flex flex-col flex-1 overflow-hidden">
      {/* 시나리오 선택 바 */}
      <div className="flex items-center gap-1.5 px-4 py-2 border-b border-stroke bg-bg-surface shrink-0 overflow-x-auto">
        <span className="text-caption text-fg-disabled shrink-0">시나리오:</span>
        {visibleScenarios.map((sc) => {
          const sev = SEV_STYLE[sc.severity];
          const isActive = selectedId === sc.id;
          return (
            <button
              key={sc.id}
              onClick={() => onSelectScenario(sc.id)}
              className="cursor-pointer shrink-0 px-2 py-1 rounded text-caption font-semibold transition-all"
              style={{
                border: `1.5px solid ${isActive ? sev.color : sev.color + '40'}`,
                background: isActive ? sev.bg : 'transparent',
                color: isActive ? sev.color : 'var(--fg-disabled)',
              }}
            >
              {sc.id} {sc.timeStep}
            </button>
          );
        })}
      </div>

      {/* 지도 영역 */}
      <div className="flex-1 relative">
        <Map
          initialViewState={{ longitude: center[0], latitude: center[1], zoom: 11 }}
          mapStyle={baseMapStyle}
          style={{ width: '100%', height: '100%' }}
          attributionControl={false}
        >
          {/* 사고 위치 마커 */}
          {currentOp && currentOp.lon != null && currentOp.lat != null && (
            <Marker longitude={currentOp.lon} latitude={currentOp.lat} anchor="center">
              <div
                className="flex items-center justify-center"
                style={{
                  width: 28,
                  height: 28,
                  borderRadius: '50%',
                  background: 'rgba(239,68,68,0.25)',
                  border: '2px solid var(--color-danger)',
                }}
              >
                <div
                  style={{
                    width: 10,
                    height: 10,
                    borderRadius: '50%',
                    background: 'var(--color-danger)',
                  }}
                />
              </div>
            </Marker>
          )}

          {/* 시나리오별 마커 — 사고 지점 주변에 시간 순서대로 배치 */}
          {visibleScenarios.map((sc, idx) => {
            const angle = (idx / visibleScenarios.length) * Math.PI * 2 - Math.PI / 2;
            const radius = 0.015 + idx * 0.003;
            const lng = center[0] + Math.cos(angle) * radius;
            const lat = center[1] + Math.sin(angle) * radius * 0.8;
            const sev = SEV_STYLE[sc.severity];
            const isActive = selectedId === sc.id;

            return (
              <Marker
                key={sc.id}
                longitude={lng}
                latitude={lat}
                anchor="center"
                onClick={(e) => {
                  e.originalEvent.stopPropagation();
                  onSelectScenario(sc.id);
                  setPopupId(popupId === sc.id ? null : sc.id);
                }}
              >
                <div
                  className="cursor-pointer flex items-center justify-center transition-transform"
                  style={{
                    width: isActive ? 36 : 28,
                    height: isActive ? 36 : 28,
                    borderRadius: '50%',
                    background: sev.bg,
                    border: `2px solid ${sev.color}`,
                    transform: isActive ? 'scale(1.15)' : 'scale(1)',
                    boxShadow: isActive ? `0 0 12px ${sev.color}60` : 'none',
                    zIndex: isActive ? 10 : 1,
                  }}
                >
                  <span
                    className="font-bold font-mono"
                    style={{ fontSize: isActive ? 11 : 9, color: sev.color }}
                  >
                    {sc.timeStep.replace('T+', '')}
                  </span>
                </div>
              </Marker>
            );
          })}

          {/* 팝업 — 클릭한 시나리오 정보 표출 */}
          {popupId &&
            (() => {
              const sc = visibleScenarios.find((s) => s.id === popupId);
              if (!sc) return null;
              const idx = visibleScenarios.indexOf(sc);
              const angle = (idx / visibleScenarios.length) * Math.PI * 2 - Math.PI / 2;
              const radius = 0.015 + idx * 0.003;
              const lng = center[0] + Math.cos(angle) * radius;
              const lat = center[1] + Math.sin(angle) * radius * 0.8;
              const sev = SEV_STYLE[sc.severity];

              return (
                <Popup
                  longitude={lng}
                  latitude={lat}
                  anchor="bottom"
                  closeOnClick={false}
                  onClose={() => setPopupId(null)}
                  maxWidth="320px"
                  className="rescue-map-popup"
                >
                  <div
                    style={{
                      padding: '8px 4px',
                      minWidth: 260,
                      background: 'var(--bg-card)',
                      color: 'var(--fg)',
                    }}
                  >
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
                      <span
                        style={{
                          fontWeight: 800,
                          fontFamily: 'monospace',
                          color: sev.color,
                          fontSize: 13,
                        }}
                      >
                        {sc.id}
                      </span>
                      <span style={{ fontWeight: 700, fontSize: 12 }}>{sc.timeStep}</span>
                      <span
                        style={{
                          marginLeft: 'auto',
                          padding: '1px 6px',
                          borderRadius: 8,
                          fontSize: 10,
                          fontWeight: 700,
                          background: sev.bg,
                          color: sev.color,
                        }}
                      >
                        {sev.label}
                      </span>
                    </div>
                    <div
                      style={{
                        fontSize: 11,
                        color: 'var(--fg-sub)',
                        lineHeight: 1.5,
                        marginBottom: 6,
                      }}
                    >
                      {sc.description}
                    </div>
                    {/* KPI */}
                    <div
                      style={{
                        display: 'grid',
                        gridTemplateColumns: '1fr 1fr 1fr 1fr',
                        gap: 4,
                        marginBottom: 6,
                      }}
                    >
                      {[
                        { label: 'GM', value: `${sc.gm}m`, color: gmColor(parseFloat(sc.gm)) },
                        {
                          label: '횡경사',
                          value: `${sc.list}°`,
                          color: listColor(parseFloat(sc.list)),
                        },
                        { label: '부력', value: `${sc.buoyancy}%`, color: buoyColor(sc.buoyancy) },
                        {
                          label: '유출',
                          value: sc.oilRate.split(' ')[0],
                          color: oilColor(parseFloat(sc.oilRate)),
                        },
                      ].map((m) => (
                        <div
                          key={m.label}
                          style={{
                            textAlign: 'center',
                            padding: '3px 2px',
                            borderRadius: 3,
                            background: 'var(--bg-base)',
                            fontSize: 10,
                          }}
                        >
                          <div style={{ color: 'var(--fg-disabled)' }}>{m.label}</div>
                          <div style={{ fontWeight: 700, fontFamily: 'monospace', color: m.color }}>
                            {m.value}
                          </div>
                        </div>
                      ))}
                    </div>
                    {/* 구획 상태 */}
                    {sc.compartments.length > 0 && (
                      <div style={{ marginBottom: 4 }}>
                        <div
                          style={{
                            fontSize: 10,
                            fontWeight: 600,
                            color: 'var(--fg-disabled)',
                            marginBottom: 3,
                          }}
                        >
                          구획 상태
                        </div>
                        <div style={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
                          {sc.compartments.map((c) => (
                            <span
                              key={c.name}
                              style={{
                                fontSize: 9,
                                padding: '1px 5px',
                                borderRadius: 3,
                                border: `1px solid ${c.color}40`,
                                color: c.color,
                              }}
                            >
                              {c.name}: {c.status}
                            </span>
                          ))}
                        </div>
                      </div>
                    )}
                  </div>
                </Popup>
              );
            })()}
        </Map>

        {/* 좌측 하단 — 선택된 시나리오 요약 오버레이 */}
        {selected && (
          <div
            className="absolute bottom-3 left-3 z-10 rounded-lg border border-stroke overflow-hidden"
            style={{ background: 'rgba(15,23,42,0.92)', width: 280, backdropFilter: 'blur(8px)' }}
          >
            <div className="px-3 py-2 border-b border-stroke flex items-center gap-2">
              <span className="font-bold font-mono text-color-accent text-label-2">
                {selected.id}
              </span>
              <span className="text-caption font-bold">{selected.timeStep}</span>
              <span
                className="ml-auto px-1.5 py-0.5 rounded-md text-caption font-bold"
                style={{
                  background: SEV_STYLE[selected.severity].bg,
                  color: SEV_STYLE[selected.severity].color,
                }}
              >
                {SEV_STYLE[selected.severity].label}
              </span>
            </div>
            <div className="px-3 py-2">
              <div className="grid grid-cols-4 gap-1 font-mono text-caption mb-2">
                {[
                  {
                    label: 'GM',
                    value: `${selected.gm}m`,
                    color: gmColor(parseFloat(selected.gm)),
                  },
                  {
                    label: '횡경사',
                    value: `${selected.list}°`,
                    color: listColor(parseFloat(selected.list)),
                  },
                  {
                    label: '부력',
                    value: `${selected.buoyancy}%`,
                    color: buoyColor(selected.buoyancy),
                  },
                  {
                    label: '유출',
                    value: selected.oilRate.split(' ')[0],
                    color: oilColor(parseFloat(selected.oilRate)),
                  },
                ].map((m) => (
                  <div key={m.label} className="text-center p-1 bg-bg-base rounded">
                    <div className="text-fg-disabled" style={{ fontSize: 9 }}>
                      {m.label}
                    </div>
                    <div className="font-bold" style={{ color: m.color, fontSize: 11 }}>
                      {m.value}
                    </div>
                  </div>
                ))}
              </div>
              <div className="text-caption text-fg-sub leading-relaxed" style={{ fontSize: 10 }}>
                {selected.description.slice(0, 120)}
                {selected.description.length > 120 ? '...' : ''}
              </div>
            </div>
          </div>
        )}

        {/* 우측 상단 — 범례 */}
        <div
          className="absolute top-3 right-3 z-10 rounded-lg border border-stroke px-3 py-2"
          style={{ background: 'rgba(15,23,42,0.88)', backdropFilter: 'blur(8px)' }}
        >
          <div className="text-caption font-bold text-fg-disabled mb-1.5">시나리오 범례</div>
          {(['CRITICAL', 'HIGH', 'MEDIUM', 'RESOLVED'] as Severity[]).map((sev) => (
            <div key={sev} className="flex items-center gap-1.5 mb-0.5">
              <span
                className="inline-block rounded-full"
                style={{ width: 8, height: 8, background: SEV_COLOR[sev] }}
              />
              <span className="text-caption text-fg-sub">{SEV_STYLE[sev].label}</span>
            </div>
          ))}
          <div className="flex items-center gap-1.5 mt-1 pt-1 border-t border-stroke">
            <span
              className="inline-block rounded-full"
              style={{
                width: 8,
                height: 8,
                background: 'var(--color-danger)',
                border: '1px solid var(--color-danger)',
              }}
            />
            <span className="text-caption text-fg-sub">사고 위치</span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ═══ 신규 시나리오 생성 모달 ═══ */
function NewScenarioModal({ ops, onClose }: { ops: RescueOpsItem[]; onClose: () => void }) {
  const overlayRef = useRef<HTMLDivElement>(null);
  const [submitting, setSubmitting] = useState(false);
  const [done, setDone] = useState(false);

  const handleSubmit = () => {
    setSubmitting(true);
    setTimeout(() => {
      setSubmitting(false);
      setDone(true);
    }, 2000);
  };

  /* ── shared className helpers ── */
  const labelCls = 'text-caption text-fg-disabled block mb-1';
  const inputCls =
    'w-full px-3 py-2 rounded-md border border-stroke bg-bg-base text-label-2 outline-none';
  const numCls = `${inputCls} font-mono`;
  const sectionIcon = (n: number) => (
    <div
      className="w-[18px] h-[18px] rounded-[5px] flex items-center justify-center text-caption font-bold text-color-accent"
      style={{ background: 'rgba(6,182,212,.12)' }}
    >
      {n}
    </div>
  );
  const sectionTitleCls = 'text-label-2 font-bold mb-2.5 flex items-center gap-1.5';

  return (
    <div
      ref={overlayRef}
      onClick={(e) => {
        if (e.target === overlayRef.current) onClose();
      }}
      className="fixed inset-0 z-[9999] flex items-center justify-center"
      style={{ background: 'rgba(0,0,0,.65)', backdropFilter: 'blur(6px)' }}
    >
      <div
        className="bg-bg-surface border border-stroke rounded-[14px] w-[700px] max-h-[88vh] flex flex-col overflow-hidden"
        style={{ boxShadow: '0 24px 80px rgba(0,0,0,.6)' }}
      >
        {/* ── 헤더 ── */}
        <div className="px-6 pt-5 pb-4 border-b border-stroke shrink-0">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2.5">
              <span className="text-lg">🚨</span>
              <div>
                <div className="text-title-4 font-bold">신규 긴급구난 시나리오 생성</div>
                <div className="text-label-2 text-fg-disabled mt-0.5">
                  선박 사고 조건 및 구난 분석 파라미터를 설정합니다 (SFR-009)
                </div>
              </div>
            </div>
            <span onClick={onClose} className="text-lg cursor-pointer text-fg-disabled p-1">
              ✕
            </span>
          </div>
        </div>

        {/* ── 본문 스크롤 ── */}
        <div className="flex-1 overflow-y-auto px-6 py-5 flex flex-col gap-[18px] scrollbar-thin">
          {/* ① 기본 정보 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(1)} 기본 정보</div>
            <div className="grid grid-cols-2 gap-2.5">
              <div>
                <label className={labelCls}>
                  시나리오명 <span className="text-color-danger">*</span>
                </label>
                <input type="text" placeholder="예: T+3h 기관실 침수 확대" className={inputCls} />
              </div>
              <div>
                <label className={labelCls}>
                  연계 사고 <span className="text-color-danger">*</span>
                </label>
                <select defaultValue="0" className={inputCls}>
                  {ops.map((op, i) => (
                    <option key={op.rescueOpsSn} value={i}>
                      {op.opsCd} · {op.vesselNm}
                    </option>
                  ))}
                  <option value="new">+ 신규 사고 등록...</option>
                </select>
              </div>
              <div>
                <label className={labelCls}>
                  시간 단계 (Time Step) <span className="text-color-danger">*</span>
                </label>
                <select defaultValue="T+3h" className={inputCls}>
                  {[
                    'T+0h (사고 발생 직후)',
                    'T+1h',
                    'T+2h',
                    'T+3h',
                    'T+6h',
                    'T+12h',
                    'T+24h',
                    'T+48h',
                  ].map((t) => (
                    <option key={t} value={t}>
                      {t}
                    </option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>기준 시각</label>
                <input type="datetime-local" defaultValue="2024-10-27T13:30" className={inputCls} />
              </div>
            </div>
          </div>

          {/* ② 선박 정보 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(2)} 선박 정보</div>
            <div className="grid grid-cols-3 gap-2.5">
              <div>
                <label className={labelCls}>
                  선박명 <span className="text-color-danger">*</span>
                </label>
                <input type="text" defaultValue="M/V SEA GUARDIAN" className={inputCls} />
              </div>
              <div>
                <label className={labelCls}>
                  선종 <span className="text-color-danger">*</span>
                </label>
                <select defaultValue="화물선 (Cargo)" className={inputCls}>
                  {[
                    '유조선 (Tanker)',
                    '화물선 (Cargo)',
                    '컨테이너선 (Container)',
                    '여객선 (Passenger)',
                    '어선 (Fishing)',
                    'LNG선',
                    '케미컬선 (Chemical)',
                    '기타',
                  ].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>총톤수 (GT)</label>
                <input type="number" defaultValue={45000} step={100} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>선체 길이 (m)</label>
                <input type="number" defaultValue={189} step={1} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>흘수 (m)</label>
                <input type="number" defaultValue={8.5} step={0.1} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>승선 인원</label>
                <input type="number" defaultValue={22} step={1} min={0} className={numCls} />
              </div>
            </div>
            <div className="mt-2 grid grid-cols-2 gap-2.5">
              <div>
                <label className={labelCls}>적재 화물</label>
                <input type="text" placeholder="예: 일반화물, 벙커C 450kL" className={inputCls} />
              </div>
              <div>
                <label className={labelCls}>연료유 종류 · 탑재량</label>
                <input type="text" defaultValue="벙커C 450kL / MGO 80kL" className={inputCls} />
              </div>
            </div>
          </div>

          {/* ③ 사고 조건 · 선체 상태 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(3)} 사고 조건 · 선체 상태</div>
            <div className="grid grid-cols-3 gap-2.5">
              <div>
                <label className={labelCls}>
                  사고 유형 <span className="text-color-danger">*</span>
                </label>
                <select defaultValue="충돌 (Collision)" className={inputCls}>
                  {[
                    '충돌 (Collision)',
                    '좌초 (Grounding)',
                    '침수 (Flooding)',
                    '기관고장 (Engine Failure)',
                    '화재 (Fire)',
                    '전복 (Capsizing)',
                    '구조손상 (Structural)',
                  ].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>손상 구역</label>
                <select defaultValue="우현 중앙 (Starboard Mid)" className={inputCls}>
                  {[
                    '선수부 (Bow)',
                    '우현 중앙 (Starboard Mid)',
                    '좌현 중앙 (Port Mid)',
                    '선미부 (Stern)',
                    '기관실 (Engine Room)',
                    '선저 (Bottom)',
                    '복수 구역',
                  ].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>파공 크기 (㎡)</label>
                <input type="number" defaultValue={2.8} step={0.1} min={0} className={numCls} />
              </div>
            </div>
            <div className="mt-2 grid grid-cols-4 gap-2.5">
              <div>
                <label className={labelCls}>횡경사 (°)</label>
                <input type="number" defaultValue={8.5} step={0.5} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>종경사 (°)</label>
                <input type="number" defaultValue={2.1} step={0.1} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>건현 (m)</label>
                <input type="number" defaultValue={3.2} step={0.1} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>GM (m)</label>
                <input type="number" defaultValue={1.8} step={0.1} className={numCls} />
              </div>
            </div>
            {/* 침수 상태 */}
            <div className="mt-2.5 px-3.5 py-2.5 rounded-md border border-stroke bg-bg-card">
              <div className="text-caption font-bold mb-2">💧 침수 상태</div>
              <div className="grid grid-cols-4 gap-2">
                <div>
                  <label className="text-caption text-fg-disabled block mb-px">침수 구역 수</label>
                  <select
                    defaultValue="2개"
                    className="w-full px-2 py-1.5 rounded border border-stroke bg-bg-base text-label-2 outline-none"
                  >
                    {['1개', '2개', '3개', '4개 이상'].map((v) => (
                      <option key={v}>{v}</option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className="text-caption text-fg-disabled block mb-px">침수량 (톤)</label>
                  <input
                    type="number"
                    defaultValue={850}
                    step={50}
                    min={0}
                    className="w-full px-2 py-1.5 rounded border border-stroke bg-bg-base text-label-2 font-mono outline-none"
                  />
                </div>
                <div>
                  <label className="text-caption text-fg-disabled block mb-px">
                    침수 진행률 (t/h)
                  </label>
                  <input
                    type="number"
                    defaultValue={120}
                    step={10}
                    min={0}
                    className="w-full px-2 py-1.5 rounded border border-stroke bg-bg-base text-label-2 font-mono outline-none"
                  />
                </div>
                <div>
                  <label className="text-caption text-fg-disabled block mb-px">
                    배수 능력 (t/h)
                  </label>
                  <input
                    type="number"
                    defaultValue={80}
                    step={10}
                    min={0}
                    className="w-full px-2 py-1.5 rounded border border-stroke bg-bg-base text-label-2 font-mono outline-none"
                  />
                </div>
              </div>
            </div>
          </div>

          {/* ④ 사고 위치 · 해상 조건 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(4)} 사고 위치 · 해상 조건</div>
            <div className="grid gap-2.5 items-end" style={{ gridTemplateColumns: '1fr 1fr auto' }}>
              <div>
                <label className={labelCls}>위도 (Lat)</label>
                <input type="text" defaultValue="34.5832" className={`${inputCls} font-mono`} />
              </div>
              <div>
                <label className={labelCls}>경도 (Lon)</label>
                <input type="text" defaultValue="128.4217" className={`${inputCls} font-mono`} />
              </div>
              <button
                className="px-3.5 py-2 rounded-md border border-[rgba(6,182,212,.3)] text-color-accent text-label-2 font-semibold cursor-pointer whitespace-nowrap"
                style={{ background: 'rgba(6,182,212,.08)' }}
              >
                📍 지도에서 선택
              </button>
            </div>
            <div className="mt-2 grid grid-cols-4 gap-2.5">
              <div>
                <label className={labelCls}>
                  풍향 / 풍속 <span className="text-color-danger">*</span>
                </label>
                <div className="flex gap-1">
                  <select
                    defaultValue="SW"
                    className="flex-1 p-2 rounded-md border border-stroke bg-bg-base text-label-2 outline-none"
                  >
                    {['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'].map((d) => (
                      <option key={d}>{d}</option>
                    ))}
                  </select>
                  <input
                    type="number"
                    defaultValue={12.5}
                    step={0.5}
                    min={0}
                    className="w-[60px] p-2 rounded-md border border-stroke bg-bg-base text-label-2 font-mono outline-none text-center"
                  />
                </div>
              </div>
              <div>
                <label className={labelCls}>
                  파고 (m) <span className="text-color-danger">*</span>
                </label>
                <input type="number" defaultValue={2.5} step={0.1} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>조류 방향 / 유속</label>
                <div className="flex gap-1">
                  <select
                    defaultValue="NE"
                    className="flex-1 p-2 rounded-md border border-stroke bg-bg-base text-label-2 outline-none"
                  >
                    {['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'].map((d) => (
                      <option key={d}>{d}</option>
                    ))}
                  </select>
                  <input
                    type="number"
                    defaultValue={1.2}
                    step={0.1}
                    min={0}
                    className="w-[60px] p-2 rounded-md border border-stroke bg-bg-base text-label-2 font-mono outline-none text-center"
                  />
                </div>
              </div>
              <div>
                <label className={labelCls}>수심 (m)</label>
                <input type="number" defaultValue={25} step={1} min={0} className={numCls} />
              </div>
            </div>
            <div className="mt-1.5 grid grid-cols-3 gap-2.5">
              <div>
                <label className={labelCls}>시정 (km)</label>
                <input type="number" defaultValue={8} step={1} min={0} className={numCls} />
              </div>
              <div>
                <label className={labelCls}>해상 상태 (Douglas)</label>
                <select defaultValue="3 — 거침 (Moderate)" className={inputCls}>
                  {[
                    '0 — 평온 (Calm)',
                    '1 — 잔잔 (Smooth)',
                    '2 — 약간 거침 (Slight)',
                    '3 — 거침 (Moderate)',
                    '4 — 다소 높음 (Rough)',
                    '5 — 높음 (Very rough)',
                    '6 — 매우 높음 (High)',
                  ].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>수온 (°C)</label>
                <input type="number" defaultValue={17.2} step={0.5} className={numCls} />
              </div>
            </div>
          </div>

          {/* ⑤ 구난 분석 설정 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(5)} 구난 분석 설정</div>
            <div className="grid grid-cols-3 gap-2.5">
              <div>
                <label className={labelCls}>
                  분석 모델 <span className="text-color-danger">*</span>
                </label>
                <select defaultValue="R&D 긴급구난 종합분석" className={inputCls}>
                  {[
                    'R&D 긴급구난 종합분석',
                    'HECSALV (Salvage)',
                    'NAPA Emergency',
                    '수동 입력 (직접 판단)',
                  ].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>예측 시간</label>
                <select defaultValue="12시간" className={inputCls}>
                  {['6시간', '12시간', '24시간', '48시간', '72시간'].map((v) => (
                    <option key={v}>{v}</option>
                  ))}
                </select>
              </div>
              <div>
                <label className={labelCls}>분석 항목</label>
                <div className="flex flex-wrap gap-1 mt-0.5">
                  {['복원성', '예인력', '인양력', '유출 위험'].map((item) => (
                    <label
                      key={item}
                      className="flex items-center gap-px text-caption text-fg-sub cursor-pointer"
                    >
                      <input
                        type="checkbox"
                        defaultChecked
                        style={{ accentColor: 'var(--color-accent)', transform: 'scale(.85)' }}
                      />
                      {item}
                    </label>
                  ))}
                </div>
              </div>
            </div>
            {/* R&D 연계 분석 */}
            <div className="mt-2.5 px-3.5 py-2.5 flex flex-col gap-1.5 rounded-md border border-stroke bg-bg-card">
              <div className="text-caption font-bold">🔗 R&D 연계 분석</div>
              <div className="flex gap-3">
                <label className="flex items-center gap-1 text-caption text-fg-sub cursor-pointer">
                  <input type="checkbox" style={{ accentColor: 'var(--color-accent)' }} /> 유출유
                  확산예측 동시 실행
                </label>
                <label className="flex items-center gap-1 text-caption text-fg-sub cursor-pointer">
                  <input type="checkbox" style={{ accentColor: 'var(--color-accent)' }} /> HNS
                  대기확산 연계 분석
                </label>
              </div>
              <div className="text-caption text-fg-disabled leading-[1.5]">
                화물 유출 가능성이 있는 경우, 긴급구난 분석 결과와 확산예측을 동시에 수행하여 종합
                대응 판단을 지원합니다
              </div>
            </div>
          </div>

          {/* ⑥ 비고 */}
          <div>
            <div className={sectionTitleCls}>{sectionIcon(6)} 비고</div>
            <textarea
              placeholder="시나리오 설명, 가정 조건, 현장 상황 특이사항 등을 기록합니다..."
              className="w-full h-[60px] px-3 py-2.5 rounded-md border border-stroke bg-bg-base text-label-2 outline-none resize-y leading-relaxed scrollbar-thin"
            />
          </div>
        </div>

        {/* ── 하단 버튼 ── */}
        <div className="px-6 py-4 border-t border-stroke shrink-0 flex gap-2 items-center">
          <div className="flex-1 text-caption text-fg-disabled leading-[1.5]">
            <span className="text-color-danger">*</span> 필수 입력 항목 · 해상 조건은 기상청/조사원
            API 연계 시 자동 갱신
          </div>
          <button
            onClick={onClose}
            className="px-5 py-2.5 rounded-md border border-stroke bg-bg-card text-fg-sub text-caption font-semibold cursor-pointer"
          >
            취소
          </button>
          {done ? (
            <button
              onClick={onClose}
              className="px-7 py-2.5 rounded-md border-none text-static-white text-caption font-bold cursor-pointer bg-color-success"
            >
              ✅ 생성 완료 — 닫기
            </button>
          ) : (
            <button
              onClick={handleSubmit}
              disabled={submitting}
              className={`px-7 py-2.5 rounded-md border-none text-caption font-bold ${
                submitting
                  ? 'bg-bg-card text-fg-disabled cursor-wait'
                  : 'bg-color-navy text-static-white cursor-pointer hover:bg-color-navy-hover'
              }`}
            >
              {submitting ? '⏳ 분석 중...' : '🚨 시나리오 생성 · 분석 실행'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

/* ═══ 비교 차트 컴포넌트 ═══ */
function ScenarioComparison({ chartData }: { chartData: ChartDataItem[] }) {
  const W = 480,
    H = 180,
    PX = 50,
    PY = 20;
  const pw = W - PX * 2,
    ph = H - PY * 2;
  const xStep = chartData.length > 1 ? pw / (chartData.length - 1) : pw;

  if (chartData.length === 0) {
    return (
      <div className="p-10 text-center text-label-2 text-fg-disabled">
        비교할 시나리오 데이터가 없습니다.
      </div>
    );
  }

  return (
    <div className="p-5">
      {/* Chart 1: GM 추이 */}
      <div className="bg-bg-card border border-stroke rounded-[10px] p-4 mb-4">
        <div className="text-label-2 font-bold mb-2.5">📈 GM (복원심) 변화 추이 (m)</div>
        <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ maxHeight: 180 }}>
          {/* Grid */}
          {[0, 0.5, 1.0, 1.5, 2.0].map((v) => {
            const y = PY + ph - (v / 2.0) * ph;
            return (
              <g key={v}>
                <line x1={PX} x2={W - PX} y1={y} y2={y} stroke="var(--stroke-light)" />
                <text
                  x={PX - 6}
                  y={y + 3}
                  textAnchor="end"
                  fill="var(--fg-disabled)"
                  fontSize={8}
                  fontFamily="var(--font-mono)"
                >
                  {v}
                </text>
              </g>
            );
          })}
          {/* GM=1.0 threshold */}
          <line
            x1={PX}
            x2={W - PX}
            y1={PY + ph - (1.0 / 2.0) * ph}
            y2={PY + ph - (1.0 / 2.0) * ph}
            stroke="rgba(239,68,68,.4)"
            strokeDasharray="4"
          />
          <text
            x={W - PX + 4}
            y={PY + ph - (1.0 / 2.0) * ph + 3}
            fill="var(--color-danger)"
            fontSize={7}
          >
            GM=1.0 위험
          </text>
          {/* Area */}
          <polygon
            points={`${PX},${PY + ph} ${chartData.map((d, i) => `${PX + i * xStep},${PY + ph - (d.gm / 2.0) * ph}`).join(' ')} ${PX + (chartData.length - 1) * xStep},${PY + ph}`}
            fill="rgba(6,182,212,.08)"
          />
          {/* Line + dots */}
          <polyline
            points={chartData
              .map((d, i) => `${PX + i * xStep},${PY + ph - (d.gm / 2.0) * ph}`)
              .join(' ')}
            fill="none"
            stroke="var(--color-accent)"
            strokeWidth={2}
          />
          {chartData.map((d, i) => (
            <g key={d.id}>
              <circle
                cx={PX + i * xStep}
                cy={PY + ph - (d.gm / 2.0) * ph}
                r={4}
                fill={SEV_COLOR[d.severity]}
                stroke="#0d1117"
                strokeWidth={1.5}
              />
              <text
                x={PX + i * xStep}
                y={PY + ph + 14}
                textAnchor="middle"
                fill="var(--fg-disabled)"
                fontSize={8}
                fontFamily="var(--font-korean)"
              >
                {d.label}
              </text>
              <text
                x={PX + i * xStep}
                y={PY + ph - (d.gm / 2.0) * ph - 8}
                textAnchor="middle"
                fill="var(--fg-default)"
                fontSize={8}
                fontFamily="var(--font-mono)"
                fontWeight={700}
              >
                {d.gm}
              </text>
            </g>
          ))}
        </svg>
      </div>

      {/* Charts 2 & 3: 2-column */}
      <div className="grid grid-cols-2 gap-4 mb-4">
        {/* Chart 2: 횡경사 변화 */}
        <div className="bg-bg-card border border-stroke rounded-[10px] p-4">
          <div className="text-label-2 font-bold mb-2.5">📉 횡경사 (List) 변화 (°)</div>
          <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ maxHeight: 160 }}>
            {[0, 5, 10, 15, 20, 25].map((v) => {
              const y = PY + ph - (v / 25) * ph;
              return (
                <g key={v}>
                  <line x1={PX} x2={W - PX} y1={y} y2={y} stroke="var(--stroke-light)" />
                  <text
                    x={PX - 6}
                    y={y + 3}
                    textAnchor="end"
                    fill="var(--fg-disabled)"
                    fontSize={7}
                    fontFamily="var(--font-mono)"
                  >
                    {v}
                  </text>
                </g>
              );
            })}
            <line
              x1={PX}
              x2={W - PX}
              y1={PY + ph - (15 / 25) * ph}
              y2={PY + ph - (15 / 25) * ph}
              stroke="rgba(239,68,68,.3)"
              strokeDasharray="4"
            />
            <polyline
              points={chartData
                .map((d, i) => `${PX + i * xStep},${PY + ph - (d.list / 25) * ph}`)
                .join(' ')}
              fill="none"
              stroke="var(--color-warning)"
              strokeWidth={2}
            />
            {chartData.map((d, i) => (
              <g key={d.id}>
                <circle
                  cx={PX + i * xStep}
                  cy={PY + ph - (d.list / 25) * ph}
                  r={3.5}
                  fill={SEV_COLOR[d.severity]}
                  stroke="#0d1117"
                  strokeWidth={1.5}
                />
                <text
                  x={PX + i * xStep}
                  y={PY + ph + 14}
                  textAnchor="middle"
                  fill="var(--fg-disabled)"
                  fontSize={7}
                  fontFamily="var(--font-korean)"
                >
                  {d.label}
                </text>
              </g>
            ))}
          </svg>
        </div>

        {/* Chart 3: 유출률 변화 (bar) */}
        <div className="bg-bg-card border border-stroke rounded-[10px] p-4">
          <div className="text-label-2 font-bold mb-2.5">📊 유출률 변화 (L/min)</div>
          <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ maxHeight: 160 }}>
            {[0, 50, 100, 150, 200].map((v) => {
              const y = PY + ph - (v / 200) * ph;
              return (
                <g key={v}>
                  <line x1={PX} x2={W - PX} y1={y} y2={y} stroke="var(--stroke-light)" />
                  <text
                    x={PX - 6}
                    y={y + 3}
                    textAnchor="end"
                    fill="var(--fg-disabled)"
                    fontSize={7}
                    fontFamily="var(--font-mono)"
                  >
                    {v}
                  </text>
                </g>
              );
            })}
            {chartData.map((d, i) => {
              const barW = xStep * 0.5;
              const barH = (d.oil / 200) * ph;
              return (
                <g key={d.id}>
                  <rect
                    x={PX + i * xStep - barW / 2}
                    y={PY + ph - barH}
                    width={barW}
                    height={barH}
                    rx={3}
                    fill={SEV_COLOR[d.severity]}
                    opacity={0.7}
                  />
                  <text
                    x={PX + i * xStep}
                    y={PY + ph - barH - 4}
                    textAnchor="middle"
                    fill="var(--fg-default)"
                    fontSize={8}
                    fontFamily="var(--font-mono)"
                    fontWeight={700}
                  >
                    {d.oil}
                  </text>
                  <text
                    x={PX + i * xStep}
                    y={PY + ph + 14}
                    textAnchor="middle"
                    fill="var(--fg-disabled)"
                    fontSize={7}
                    fontFamily="var(--font-korean)"
                  >
                    {d.label}
                  </text>
                </g>
              );
            })}
          </svg>
        </div>
      </div>

      {/* Chart 4: 비교 테이블 */}
      <div className="bg-bg-card border border-stroke rounded-[10px] p-4">
        <div className="text-label-2 font-bold mb-2.5">📋 시나리오 종합 비교표</div>
        <table className="w-full border-collapse text-caption">
          <thead>
            <tr className="bg-bg-base">
              <th className="py-[7px] px-2 text-left border-b-2 border-[var(--stroke-light)] text-fg-sub">
                지표
              </th>
              {chartData.map((d) => (
                <th
                  key={d.id}
                  className="py-[7px] px-2 text-center border-b-2 border-[var(--stroke-light)]"
                  style={{ color: SEV_COLOR[d.severity] }}
                >
                  {d.id}
                  <br />
                  <span className="font-normal text-caption text-fg-disabled">{d.label}</span>
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {[
              {
                label: 'GM (m)',
                key: 'gm',
                fmt: (d: ChartDataItem) => d.gm.toFixed(1),
                clr: (d: ChartDataItem) => gmColor(d.gm),
              },
              {
                label: '횡경사 (°)',
                key: 'list',
                fmt: (d: ChartDataItem) => `${d.list}°`,
                clr: (d: ChartDataItem) => listColor(d.list),
              },
              {
                label: '잔존부력 (%)',
                key: 'buoy',
                fmt: (d: ChartDataItem) => `${d.buoy}%`,
                clr: (d: ChartDataItem) => buoyColor(d.buoy),
              },
              {
                label: '유출률 (L/min)',
                key: 'oil',
                fmt: (d: ChartDataItem) => `${d.oil}`,
                clr: (d: ChartDataItem) => oilColor(d.oil),
              },
              {
                label: 'BM 비율 (%)',
                key: 'bm',
                fmt: (d: ChartDataItem) => `${d.bm}%`,
                clr: (d: ChartDataItem) =>
                  d.bm > 100
                    ? 'var(--color-danger)'
                    : d.bm > 85
                      ? 'var(--color-warning)'
                      : 'var(--color-success)',
              },
              {
                label: '위험 등급',
                key: 'sev',
                fmt: (d: ChartDataItem) => d.severity,
                clr: (d: ChartDataItem) => SEV_COLOR[d.severity],
              },
            ].map((row) => (
              <tr key={row.label} style={{ borderBottom: '1px solid rgba(255,255,255,.04)' }}>
                <td className="py-1.5 px-2 font-semibold text-fg-sub">{row.label}</td>
                {chartData.map((d) => (
                  <td
                    key={d.id}
                    className="py-1.5 px-2 text-center font-mono font-bold"
                    style={{ color: row.clr(d) }}
                  >
                    {row.fmt(d)}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
