refactor(css): 인라인 style → Tailwind className 일괄 변환 (229건)

안전한 패턴 매칭으로 단독 color/background/fontWeight/fontSize/flex 스타일을
Tailwind 유틸리티 클래스로 변환. 혼합 style에서 개별 속성 추출은 제외하여
시각적 회귀 방지.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
htlee 2026-03-01 11:38:59 +09:00
부모 1dacb22487
커밋 628c07f4fb
19개의 변경된 파일256개의 추가작업 그리고 256개의 파일을 삭제

파일 보기

@ -390,7 +390,7 @@ export function MapView({
latitude: incidentCoord.lat,
content: (
<div className="text-xs">
<strong style={{ color: 'var(--orange)' }}>{d.level}</strong>
<strong className="text-status-orange">{d.level}</strong>
<br />
: {dispersionResult.substance}
<br />

파일 보기

@ -327,7 +327,7 @@ export function CctvView() {
))}
<div className="flex items-center justify-between px-2 py-1 bg-bg-3 rounded-[5px]" style={{ border: '1px solid rgba(59,130,246,.2)' }}>
<span className="text-[9px] text-text-2 font-korean"> </span>
<span className="text-[9px] font-bold font-mono" style={{ color: 'var(--blue)' }}>1 fps</span>
<span className="text-[9px] font-bold font-mono text-primary-blue">1 fps</span>
</div>
<div className="text-[9px] text-text-3 font-mono text-right mt-0.5">: {new Date().toLocaleTimeString('ko-KR')}</div>
</div>

파일 보기

@ -301,7 +301,7 @@ function ShipInsurance() {
<><span className="text-status-red font-bold"> {expiredList.length}:</span> {expiredList.map(r => r.shipName).join(', ')}<br /></>
)}
{soonList.length > 0 && (
<><span className="font-bold" style={{ color: 'var(--yellow)' }}> (30) {soonList.length}:</span> {soonList.map(r => r.shipName).join(', ')}</>
<><span className="font-bold text-status-yellow"> (30) {soonList.length}:</span> {soonList.map(r => r.shipName).join(', ')}</>
)}
</div>
)}

파일 보기

@ -204,14 +204,14 @@ export function BoardView() {
return (
<div className="flex flex-1 overflow-hidden">
<div className="flex-1 relative overflow-hidden">
<div className="flex flex-col h-full" style={{ background: 'var(--bg0)' }}>
<div className="flex flex-col h-full bg-bg-0">
{/* 헤더 */}
<div className="flex items-center justify-between px-8 py-4 border-b" style={{ borderColor: 'var(--bd)', background: 'var(--bg1)' }}>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<span style={{ fontSize: 18 }}>📘</span>
<span className="text-lg">📘</span>
<span className="text-[15px] font-bold"></span>
<span className="text-[10px] ml-1" style={{ color: 'var(--t3)' }}> {filteredManuals.length}</span>
<span className="text-[10px] ml-1 text-text-3"> {filteredManuals.length}</span>
</div>
<div className="flex gap-1 ml-4">
{manualCategories.map(cat => (
@ -242,7 +242,7 @@ export function BoardView() {
<div className="flex-1 overflow-auto px-8 py-6">
{manualLoading ? (
<div className="text-center py-20">
<p className="text-sm" style={{ color: 'var(--t3)' }}> ...</p>
<p className="text-sm text-text-3"> ...</p>
</div>
) : (
<div className="grid gap-3" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))' }}>
@ -310,7 +310,7 @@ export function BoardView() {
</button>
</div>
<div className="flex items-center justify-between pt-3" style={{ borderTop: '1px solid var(--bd)' }}>
<div className="flex items-center gap-3 text-[10px]" style={{ color: 'var(--t3)' }}>
<div className="flex items-center gap-3 text-[10px] text-text-3">
<span>{file.authorNm}</span>
<span>{new Date(file.regDtm).toLocaleDateString('ko-KR')}</span>
</div>
@ -367,7 +367,7 @@ export function BoardView() {
{!manualLoading && filteredManuals.length === 0 && (
<div className="text-center py-20">
<div style={{ fontSize: 32, opacity: 0.3, marginBottom: 8 }}>📘</div>
<p className="text-sm" style={{ color: 'var(--t3)' }}> .</p>
<p className="text-sm text-text-3"> .</p>
</div>
)}
</div>

파일 보기

@ -242,7 +242,7 @@ function FG({ label, children }: { label: string; children: React.ReactNode }) {
function InfoRow({ label, value }: { label: string; value: string }) {
return (
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '2px 0' }}>
<span style={{ color: 'var(--t3)' }}>{label}</span>
<span className="text-text-3">{label}</span>
<span style={{ fontWeight: 600, fontFamily: 'var(--fM)' }}>{value}</span>
</div>
)

파일 보기

@ -130,7 +130,7 @@ export function HNSScenarioView() {
}
return (
<div className="flex flex-col flex-1 w-full h-full overflow-hidden" style={{ background: 'var(--bg0)' }}>
<div className="flex flex-col flex-1 w-full h-full overflow-hidden bg-bg-0">
{/* Header */}
<div className="flex items-center justify-between shrink-0 border-b border-border" style={{ padding: '14px 20px', background: 'var(--bg1)' }}>
<div className="flex items-center gap-2.5">
@ -285,7 +285,7 @@ export function HNSScenarioView() {
{/* ── Right: Detail Views ── */}
<div className="flex-1 min-w-0 flex flex-col overflow-hidden">
{/* View Tabs */}
<div className="flex border-b border-border shrink-0 px-4" style={{ background: 'var(--bg1)' }}>
<div className="flex border-b border-border shrink-0 px-4 bg-bg-1">
{['📋 시나리오 상세', '📊 비교 차트', '🗺 확산범위 오버레이'].map((label, i) => (
<button
key={i}
@ -425,7 +425,7 @@ function ScenarioDetail({ scenario }: { scenario: HnsScenario }) {
{ label: '습도', value: scenario.weather.humidity, icon: '💧' },
{ label: '혼합층', value: scenario.weather.mixHeight, icon: '📏' },
].map((w, i) => (
<div key={i} className="text-center p-2 rounded-sm" style={{ background: 'var(--bg0)' }}>
<div key={i} className="text-center p-2 rounded-sm bg-bg-0">
<div className="text-sm mb-0.5">{w.icon}</div>
<div className="text-[12px] font-bold font-mono">{w.value}</div>
<div className="text-text-3 mt-0.5" style={{ fontSize: '8px' }}>{w.label}</div>
@ -577,7 +577,7 @@ function ScenarioComparison() {
</div>
<table className="w-full text-[10px]" style={{ borderCollapse: 'collapse' }}>
<thead>
<tr style={{ background: 'var(--bg0)' }}>
<tr className="bg-bg-0">
{['지표', ...D.map(d => `${d.id} (${d.label})`)].map((h, i) => (
<th key={i} className="text-text-3 border-b border-border" style={{
padding: '8px 10px', textAlign: i === 0 ? 'left' : 'center',

파일 보기

@ -796,11 +796,11 @@ function HmsDetailPanel({ substance: s, activeTab, onTabChange }: { substance: H
<div className="p-3 flex flex-col gap-2">
<div className="rounded-sm" style={{ padding: 10, background: 'rgba(249,115,22,.04)', border: '1px solid rgba(249,115,22,.12)' }}>
<div className="text-[10px] font-bold text-status-orange mb-1">🔥 </div>
<div className="text-[9px] text-text-2" style={{ lineHeight: 1.6 }}>: <b style={{ color: 'var(--red)' }}>{s.responseDistanceFire}</b> </div>
<div className="text-[9px] text-text-2" style={{ lineHeight: 1.6 }}>: <b className="text-status-red">{s.responseDistanceFire}</b> </div>
</div>
<div className="rounded-sm" style={{ padding: 10, background: 'rgba(168,85,247,.04)', border: '1px solid rgba(168,85,247,.12)' }}>
<div className="text-[10px] font-bold text-primary-purple mb-1">💨 ()</div>
<div className="text-[9px] text-text-2" style={{ lineHeight: 1.6 }}> : <b style={{ color: 'var(--purple)' }}>{s.responseDistanceSpillDay}</b><br /> : <b style={{ color: 'var(--red)' }}>{s.responseDistanceSpillNight}</b></div>
<div className="text-[9px] text-text-2" style={{ lineHeight: 1.6 }}> : <b className="text-primary-purple">{s.responseDistanceSpillDay}</b><br /> : <b className="text-status-red">{s.responseDistanceSpillNight}</b></div>
</div>
<div className="rounded-sm" style={{ padding: 10, background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.12)' }}>
<div className="text-[10px] font-bold text-primary-cyan mb-1">🌊 </div>

파일 보기

@ -49,7 +49,7 @@ function HNSManualViewer() {
{/* SEBC 거동 분류 */}
<div className={card} style={{ background: 'var(--bg3)', border: '1px solid var(--bd)' }}>
<div className="text-[13px] font-bold mb-2.5">SEBC (Standard European Behaviour Classification)</div>
<div className="text-[9px] text-text-3 mb-2.5" style={{ lineHeight: '1.5' }}> · (, , , ) 5 + 7 </div>
<div className="text-[9px] text-text-3 mb-2.5" className="leading-normal"> · (, , , ) 5 + 7 </div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(5,1fr)', gap: '8px' }}>
{[
{ icon: '💨', label: 'G — 가스', desc: '대기 중 확산\n증기압 > 101.3kPa\n예: 암모니아, 염소', color: 'rgba(139,92,246' },

파일 보기

@ -141,7 +141,7 @@ export function IncidentsRightPanel({
🔬
</div>
<div className="text-[9px] text-text-3">
: <b style={{ color: 'var(--cyan)' }}>{incident.name}</b>
: <b className="text-primary-cyan">{incident.name}</b>
</div>
</div>

파일 보기

@ -455,7 +455,7 @@ export function IncidentsView() {
</div>
<div className="flex gap-2.5 text-[9px] font-mono">
<div className="text-text-2">
<b style={{ color: 'var(--cyan)' }}>20</b>
<b className="text-primary-cyan">20</b>
</div>
<div className="text-text-2">
<b style={{ color: '#f87171' }}>6</b>
@ -494,7 +494,7 @@ export function IncidentsView() {
<div className="text-[9px] font-bold text-text-2 mt-0.5">
AIS
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px 12px' }}>
<div className="flex flex-wrap gap-[6px_12px]">
{VESSEL_LEGEND.map(vl => (
<div key={vl.type} className="flex items-center gap-1">
<div
@ -535,7 +535,7 @@ export function IncidentsView() {
{/* ── 2분할 View ─────────────────────────────── */}
{analysisActive && viewMode === 'split2' && (
<div style={{ display: 'flex', height: '100%' }}>
<div className="flex h-full">
<div
style={{
flex: 1,
@ -576,7 +576,7 @@ export function IncidentsView() {
<SplitPanelContent tag={analysisTags[0]} incident={selectedIncident} />
</div>
</div>
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<div className="flex-1 flex flex-col overflow-hidden">
<div
style={{
height: 28,
@ -613,7 +613,7 @@ export function IncidentsView() {
{/* ── 3분할 View ─────────────────────────────── */}
{analysisActive && viewMode === 'split3' && (
<div style={{ display: 'flex', height: '100%' }}>
<div className="flex h-full">
<div
style={{
flex: 1,
@ -696,7 +696,7 @@ export function IncidentsView() {
/>
</div>
</div>
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<div className="flex-1 flex flex-col overflow-hidden">
<div
style={{
height: 28,
@ -749,7 +749,7 @@ export function IncidentsView() {
<div style={{ fontSize: 9, color: 'var(--t3)' }}>
📊 {selectedIncident?.name} · {analysisTags.map(t => t.label).join(' + ')}
</div>
<div style={{ display: 'flex', gap: 6 }}>
<div className="flex gap-[6px]">
<button
style={{
padding: '4px 12px',
@ -1258,8 +1258,8 @@ function VesselDetailModal({ vessel: v, onClose }: { vessel: Vessel; onClose: ()
borderBottom: '1px solid #30363d',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontSize: 18 }}>{v.flag}</span>
<div className="flex items-center gap-[10px]">
<span className="text-lg">{v.flag}</span>
<div>
<div style={{ fontSize: 14, fontWeight: 800, color: '#f0f6fc' }}>{v.name}</div>
<div style={{ fontSize: 10, color: '#8b949e', fontFamily: 'var(--fM)' }}>
@ -1538,7 +1538,7 @@ function TabNav(_props: { v: Vessel }) {
</div>
</Sec>
<div style={{ display: 'flex', gap: 8 }}>
<div className="flex gap-[8px]">
<ActionBtn icon="🔍" label="전체 항적 조회" bg="rgba(168,85,247,0.1)" bd="rgba(168,85,247,0.25)" fg="#a78bfa" />
<ActionBtn icon="📐" label="항로 예측" bg="rgba(6,182,212,0.1)" bd="rgba(6,182,212,0.25)" fg="#22d3ee" />
</div>

파일 보기

@ -93,8 +93,8 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
borderBottom: '1px solid #30363d',
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontSize: 18 }}>📋</span>
<div className="flex items-center gap-[10px]">
<span className="text-lg">📋</span>
<div>
<div style={{ fontSize: 14, fontWeight: 800, color: '#f0f6fc' }}>
{incident.name}
@ -104,9 +104,9 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
</div>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div className="flex items-center gap-[8px]">
{/* Tabs */}
<div style={{ display: 'flex', gap: 2 }}>
<div className="flex gap-[2px]">
{MEDIA_TABS.map(t => (
<button key={t.id} onClick={() => setActiveTab(t.id)} style={{
padding: '5px 12px', borderRadius: 6, fontSize: 11, fontWeight: activeTab === t.id ? 700 : 400,
@ -171,13 +171,13 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
flexShrink: 0, padding: '8px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
borderBottom: '1px solid #21262d',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<div className="flex items-center gap-[6px]">
<span style={{ fontSize: 12 }}>📷</span>
<span style={{ fontSize: 12, fontWeight: 700, color: '#f0f6fc' }}>
{str(media.photoMeta, 'title', '현장 사진')}
</span>
</div>
<div style={{ display: 'flex', gap: 4 }}>
<div className="flex gap-[4px]">
<NavBtn label="◀" /> <NavBtn label="▶" /> <NavBtn label="↗" />
</div>
</div>
@ -221,7 +221,7 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
flexShrink: 0, padding: '8px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
borderBottom: '1px solid #21262d',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<div className="flex items-center gap-[6px]">
<span style={{ fontSize: 12 }}>🎬</span>
<span style={{ fontSize: 12, fontWeight: 700, color: '#f0f6fc' }}>
{str(media.droneMeta, 'title', '드론 영상')}
@ -258,7 +258,7 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
<span style={{ fontSize: 8, color: '#8b949e' }}>
🎬 {num(media.droneMeta, 'videoCount')} · {str(media.droneMeta, 'stage')}
</span>
<div style={{ display: 'flex', gap: 8 }}>
<div className="flex gap-[8px]">
<span style={{ fontSize: 8, color: '#58a6ff', cursor: 'pointer' }}>📂 </span>
<span style={{ fontSize: 8, color: '#a78bfa', cursor: 'pointer' }}>🔗 R&D </span>
</div>
@ -274,13 +274,13 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
flexShrink: 0, padding: '8px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
borderBottom: '1px solid #21262d',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<div className="flex items-center gap-[6px]">
<span style={{ fontSize: 12 }}>🛰</span>
<span style={{ fontSize: 12, fontWeight: 700, color: '#f0f6fc' }}>
{str(media.satMeta, 'title', '위성영상')}
</span>
</div>
<div style={{ display: 'flex', gap: 4 }}>
<div className="flex gap-[4px]">
<NavBtn label="◀" /> <NavBtn label="▶" /> <NavBtn label="↗" />
</div>
</div>
@ -341,13 +341,13 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
flexShrink: 0, padding: '8px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
borderBottom: '1px solid #21262d',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<div className="flex items-center gap-[6px]">
<span style={{ fontSize: 12 }}>📹</span>
<span style={{ fontSize: 12, fontWeight: 700, color: '#f0f6fc' }}>
CCTV {str(media.cctvMeta, 'title', 'CCTV')}
</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<div className="flex items-center gap-[6px]">
{bool(media.cctvMeta, 'live') && (
<span style={{
padding: '2px 8px', borderRadius: 4, fontSize: 9, fontWeight: 700,
@ -373,7 +373,7 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
</div>
{/* CAM buttons */}
<div style={{ flexShrink: 0, padding: '10px 16px', borderTop: '1px solid #21262d', display: 'flex', flexDirection: 'column', gap: 8 }}>
<div style={{ display: 'flex', gap: 6 }}>
<div className="flex gap-[6px]">
{Array.from({ length: num(media.cctvMeta, 'camCount') }).map((_, i) => (
<button key={i} onClick={() => setSelectedCam(i)} style={{
padding: '6px 16px', borderRadius: 4, fontSize: 10, fontWeight: 600,
@ -388,7 +388,7 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
<span style={{ fontSize: 8, color: '#8b949e' }}>
📹 CCTV {num(media.cctvMeta, 'camCount')} · {str(media.cctvMeta, 'location')}
</span>
<div style={{ display: 'flex', gap: 8 }}>
<div className="flex gap-[8px]">
<span style={{ fontSize: 8, color: '#ef4444', cursor: 'pointer' }}>🔴 </span>
<span style={{ fontSize: 8, color: '#58a6ff', cursor: 'pointer' }}>🎥 PTZ</span>
</div>
@ -411,7 +411,7 @@ export function MediaModal({ incident, onClose }: { incident: Incident; onClose:
<span>📹 CCTV <b style={{ color: '#f0f6fc' }}>{media.cctvCnt}</b></span>
<span>📎 <b style={{ color: '#c084fc' }}>{total}</b></span>
</div>
<div style={{ display: 'flex', gap: 8 }}>
<div className="flex gap-[8px]">
<BottomBtn icon="📥" label="다운로드" bg="rgba(100,116,139,0.1)" bd="rgba(100,116,139,0.2)" fg="#8b949e" />
<BottomBtn icon="📝" label="보고서" bg="rgba(59,130,246,0.1)" bd="rgba(59,130,246,0.2)" fg="#58a6ff" />
<BottomBtn icon="🔗" label="R&D 분석 연계" bg="rgba(168,85,247,0.1)" bd="rgba(168,85,247,0.25)" fg="#c084fc" />

파일 보기

@ -84,7 +84,7 @@ function OverviewPanel() {
<div>
<div className="text-[13px] font-bold mb-2">🛡 ?</div>
<div className="text-[11px] leading-[1.8] text-text-2">
<b style={{ color: 'var(--orange)' }}> </b> (··) , ( · ) <b style={{ color: 'var(--cyan)' }}> </b> ·· .
<b className="text-status-orange"> </b> (··) , ( · ) <b className="text-primary-cyan"> </b> ·· .
</div>
</div>
<div>
@ -197,7 +197,7 @@ function DeploymentTheoryPanel() {
<div>
<div className="text-[11px] font-bold mb-2 text-primary-cyan"> θ* </div>
<div className="text-[10px] leading-[1.8] mb-2 text-text-2">
. <b></b> , <b style={{ color: 'var(--cyan)' }}>30°~45° </b> .
. <b></b> , <b className="text-primary-cyan">30°~45° </b> .
</div>
<div className="rounded-md p-2.5 text-[10px] leading-[2.1] bg-bg-0 font-mono" style={{ border: '1px solid rgba(6,182,212,.2)' }}>
θ* = arcsin(U<sub>c</sub> / U) <span className="text-[9px] text-text-3">()</span><br />
@ -319,7 +319,7 @@ function OptimizationPanel() {
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--purple),var(--blue))' }} />
<div className="text-[13px] font-bold mb-2"> (Multi-Objective Optimization)</div>
<div className="text-[11px] leading-[1.8] text-text-2">
<b style={{ color: 'var(--purple)' }}> </b> . , <b style={{ color: 'var(--cyan)' }}> (Pareto Optimal) </b> .
<b className="text-primary-purple"> </b> . , <b className="text-primary-cyan"> (Pareto Optimal) </b> .
</div>
</div>
@ -352,7 +352,7 @@ function OptimizationPanel() {
{/* ESI 가중치 */}
<div className="rounded-lg p-3 bg-bg-0" style={{ border: '1px solid rgba(234,179,8,.2)' }}>
<div className="text-[10px] font-bold mb-2" style={{ color: 'var(--yellow)' }}>🏖 ESI w<sub>ESI</sub> </div>
<div className="text-[10px] font-bold mb-2 text-status-yellow">🏖 ESI w<sub>ESI</sub> </div>
<div className="grid grid-cols-5 gap-[5px] text-[9px] text-text-2">
{[
{ grade: 'ESI 1~2', desc: '노출암반', w: 'w = 0.2', color: 'var(--green)', bg: 'rgba(34,197,94,.06)' },
@ -377,7 +377,7 @@ function OptimizationPanel() {
<div className="grid grid-cols-2 gap-3">
<div>
<div className="text-[10px] leading-[1.8] mb-2 text-text-2">
WING의 <b style={{ color: 'var(--purple)' }}>NSGA-II</b>(Deb et al., 2002) . (Pareto Front) .
WING의 <b className="text-primary-purple">NSGA-II</b>(Deb et al., 2002) . (Pareto Front) .
</div>
<div className="flex flex-col gap-1 text-[9px] text-text-2">
{[
@ -388,7 +388,7 @@ function OptimizationPanel() {
'선택 방식 : 비지배 정렬 + 혼잡도 거리(Crowding Distance)',
].map((item, i) => (
<div key={i} className="px-2 py-[5px] rounded text-text-2" style={{ background: 'rgba(168,85,247,.05)', border: '1px solid rgba(168,85,247,.12)' }}>
<b style={{ color: 'var(--purple)' }}>{item.split(' : ')[0]}</b> : {item.split(' : ')[1]}
<b className="text-primary-purple">{item.split(' : ')[0]}</b> : {item.split(' : ')[1]}
</div>
))}
</div>
@ -404,7 +404,7 @@ function OptimizationPanel() {
{ step: '⑤', title: '엘리트 선택', desc: '부모+자식 2N 집단에서 비지배 정렬+혼잡도 기준으로 N개 선택 → 수렴까지 반복' },
].map((item, i) => (
<div key={i} className="flex gap-2 px-[9px] py-1.5 rounded-[5px]" style={{ background: i === 4 ? 'rgba(168,85,247,.05)' : 'rgba(168,85,247,.04)', border: i === 4 ? '1px solid rgba(168,85,247,.12)' : undefined }}>
<span className="min-w-[20px] font-extrabold" style={{ color: 'var(--purple)' }}>{item.step}</span>
<span className="min-w-[20px] font-extrabold text-primary-purple">{item.step}</span>
<div className="leading-[1.6] text-text-2"><b>{item.title}</b> : {item.desc}</div>
</div>
))}

파일 보기

@ -149,7 +149,7 @@ const OilBoomSection = ({
</h4>
<p style={{ lineHeight: '1.5' }} className="text-[9px] text-text-3 mb-2.5">
<p className="leading-normal" className="text-[9px] text-text-3 mb-2.5">
{oilTrajectory.length > 0
? '확산 궤적을 분석하여 해류 직교 방향 1차 방어선, U형 포위 2차 방어선, 연안 보호 3차 방어선을 자동 생성합니다.'
: '상단에서 확산 예측을 실행한 뒤 AI 배치를 적용할 수 있습니다.'

파일 보기

@ -62,7 +62,7 @@ ${styles}
}
return (
<div className="flex flex-col h-full overflow-hidden" style={{ background: 'var(--bg0)' }}>
<div className="flex flex-col h-full overflow-hidden bg-bg-0">
<div className="flex-1 overflow-y-auto scrollbar-thin p-5" ref={contentRef}>
{/* 헤더 */}
@ -150,7 +150,7 @@ function SystemOverviewPanel() {
<span className="text-sm font-bold"> ?</span>
</div>
<div style={{ ...bodyText, fontSize: '12px', lineHeight: '1.8' }}>
<b style={{ color: 'var(--orange)' }}> </b> ·· · . <b style={{ color: 'var(--cyan)' }}> </b> ·· .
<b className="text-status-orange"> </b> ·· · . <b className="text-primary-cyan"> </b> ·· .
</div>
</div>
<div>
@ -163,7 +163,7 @@ function SystemOverviewPanel() {
<span style={{ color: 'var(--red)', fontWeight: 700 }}></span> <b> </b>
</div>
<div className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(249,115,22,.04)', border: '1px solid rgba(249,115,22,.12)' }}>
<span style={{ color: 'var(--orange)', fontWeight: 700 }}></span> <b> </b>
<span className="text-status-orange font-bold"></span> <b> </b>
</div>
<div className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(34,197,94,.04)', border: '1px solid rgba(34,197,94,.12)' }}>
<span style={{ color: 'var(--green)', fontWeight: 700 }}></span> <b> </b>
@ -180,7 +180,7 @@ function SystemOverviewPanel() {
<div className="absolute top-2.5 right-3 w-7 h-7 rounded-full flex items-center justify-center text-xs font-extrabold"
style={{ background: 'rgba(249,115,22,.15)', color: 'var(--orange)', fontFamily: 'var(--fM)' }}>1</div>
<div style={labelStyle('var(--orange)')}>🛢 </div>
<div className="text-[11px] mb-2.5" style={{ color: 'var(--t2)', lineHeight: '1.7' }}> <b>· </b> .</div>
<div className="text-[11px] mb-2.5 text-text-2 leading-[1.7]"> <b>· </b> .</div>
<div className="flex flex-wrap gap-1">
{[
{ label: '비중(API)', color: 'var(--orange)' }, { label: '점도', color: 'var(--red)' },
@ -194,8 +194,8 @@ function SystemOverviewPanel() {
<div className="absolute top-2.5 right-3 w-7 h-7 rounded-full flex items-center justify-center text-xs font-extrabold"
style={{ background: 'rgba(6,182,212,.15)', color: 'var(--cyan)', fontFamily: 'var(--fM)' }}>2</div>
<div style={labelStyle('var(--cyan)')}>🌊 </div>
<div className="text-[11px] mb-2.5" style={{ color: 'var(--t2)', lineHeight: '1.7' }}><b> · </b> .</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] mb-2.5 text-text-2 leading-[1.7]"><b> · </b> .</div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
<div style={{ padding: '4px 8px', background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.12)', borderRadius: '4px' }}>🌬 (KMA·ECMWF)</div>
<div style={{ padding: '4px 8px', background: 'rgba(59,130,246,.05)', border: '1px solid rgba(59,130,246,.12)', borderRadius: '4px' }}>🌊 · (KHOA )</div>
<div style={{ padding: '4px 8px', background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', borderRadius: '4px' }}>🌡 · (NIFS )</div>
@ -206,8 +206,8 @@ function SystemOverviewPanel() {
<div className="absolute top-2.5 right-3 w-7 h-7 rounded-full flex items-center justify-center text-xs font-extrabold"
style={{ background: 'rgba(34,197,94,.15)', color: 'var(--green)', fontFamily: 'var(--fM)' }}>3</div>
<div style={labelStyle('var(--green)')}>🧮 </div>
<div className="text-[11px] mb-2.5" style={{ color: 'var(--t2)', lineHeight: '1.7' }}><b> </b> ·· .</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] mb-2.5 text-text-2 leading-[1.7]"><b> </b> ·· .</div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
<div style={{ padding: '4px 8px', background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', borderRadius: '4px' }}>📍 ~ </div>
<div style={{ padding: '4px 8px', background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', borderRadius: '4px' }}> 1 </div>
<div style={{ padding: '4px 8px', background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', borderRadius: '4px' }}>🗺 · </div>
@ -235,8 +235,8 @@ function SystemOverviewPanel() {
<div className="text-[10px] text-text-3">{m.sub}</div>
</div>
</div>
<div className="text-[10px] mb-2" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>{m.desc}</div>
<div className="flex flex-col gap-0.5 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[10px] mb-2 text-text-2 leading-[1.7]">{m.desc}</div>
<div className="flex flex-col gap-0.5 text-[10px] text-text-2">
<div className="px-1.5 py-0.5 rounded" style={{ background: `${m.color}0F`, color: 'var(--t2)' }}>📍 : {m.org}</div>
<div className="px-1.5 py-0.5 rounded" style={{ background: `${m.color}0F`, color: 'var(--t2)' }}>🗓 {m.year}</div>
<div className="px-1.5 py-0.5 rounded" style={{ background: `${m.color}0F`, color: 'var(--t2)' }}>🎯 : {m.strength}</div>
@ -291,8 +291,8 @@ function SystemOverviewPanel() {
<div className="mt-3.5 px-3.5 py-3 rounded-lg flex items-start gap-2.5"
style={{ background: 'rgba(168,85,247,.04)', border: '1px solid rgba(168,85,247,.15)' }}>
<span className="text-lg flex-shrink-0"></span>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<b style={{ color: 'var(--purple)' }}>3 </b> : WING KOSPS·POSEIDON·OpenDrift를 ·. 3 <b> </b>, <b style={{ color: 'var(--orange)' }}> </b> .
<div className="text-[10px] text-text-2 leading-[1.7]">
<b className="text-primary-purple">3 </b> : WING KOSPS·POSEIDON·OpenDrift를 ·. 3 <b> </b>, <b className="text-status-orange"> </b> .
</div>
</div>
</div>
@ -313,12 +313,12 @@ function KospsPanel() {
<div className="flex items-center gap-3 mb-3">
<div className="w-[38px] h-[38px] rounded-[10px] flex items-center justify-center text-xl" style={{ background: 'rgba(6,182,212,.15)', border: '1px solid rgba(6,182,212,.3)' }}>🔷</div>
<div>
<div className="text-[15px] font-bold" style={{ color: 'var(--cyan)' }}>KOSPS (Korea Oil Spill Prediction System)</div>
<div className="text-[15px] font-bold text-primary-cyan">KOSPS (Korea Oil Spill Prediction System)</div>
<div className="text-[11px] mt-0.5 text-text-3">(KORDI) · </div>
</div>
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
···(2011) KOSPS는 <b style={{ color: 'var(--cyan)' }}> </b> . (·) (KMA ·HYCOM ·KORDI ) FTP <b style={{ color: 'var(--green)' }}> </b> .
<div className="text-[11px] text-text-2 leading-[1.8]">
···(2011) KOSPS는 <b className="text-primary-cyan"> </b> . (·) (KMA ·HYCOM ·KORDI ) FTP <b className="text-status-green"> </b> .
</div>
<div className="mt-2.5 px-3 py-2 rounded-md text-[10px]" style={{ background: 'rgba(6,182,212,.06)', border: '1px solid rgba(6,182,212,.15)', color: 'var(--t3)' }}>
📚 참고문헌: 김혜진···, &quot; &quot;, 17 4, pp.375-382, 2011.
@ -339,20 +339,20 @@ function KospsPanel() {
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(6,182,212,.2)', display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '12px' }}>
<div className="px-2.5 py-1.5 rounded-md text-center whitespace-nowrap" style={{ background: 'rgba(6,182,212,.12)', border: '1px solid rgba(6,182,212,.25)', fontFamily: 'var(--fM)' }}>
<div className="text-[10px] text-text-3"></div>
<div className="text-[11px] font-bold" style={{ color: 'var(--cyan)' }}>10-1567431</div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}>2015.11.03</div>
<div className="text-[11px] font-bold text-primary-cyan">10-1567431</div>
<div className="text-[10px] mt-0.5 text-text-3">2015.11.03</div>
</div>
<div>
<div className="text-[11px] font-bold mb-1"> </div>
<div className="text-[10px]" style={{ color: 'var(--t2)' }}>
<span style={{ color: 'var(--cyan)' }}></span> : · · · | <span style={{ color: 'var(--cyan)' }}></span> :
<div className="text-[10px] text-text-2">
<span className="text-primary-cyan"></span> : · · · | <span className="text-primary-cyan"></span> :
</div>
<div className="flex flex-wrap gap-1 mt-1.5">
{['ESI 방제정보지도', 'CHARRY 실시간 조류모델', '취송류 경험식', 'Monte Carlo 입자추적', '풍화 5단계'].map(t =>
<span key={t} style={tag('var(--cyan)')}>{t}</span>
)}
</div>
<div className="text-[10px] mt-1.5" style={{ color: 'var(--t3)' }}>
<div className="text-[10px] mt-1.5 text-text-3">
R&amp;D: 3 ( 65%) HNS ( 35%) |
</div>
</div>
@ -365,23 +365,23 @@ function KospsPanel() {
{/* CHARRY 모델 */}
<div className={card} style={{ background: 'var(--bg0)', border: '1px solid rgba(6,182,212,.2)' }}>
<div style={labelStyle('var(--cyan)')}>🌀 CHARRY ( )</div>
<div className="text-[11px] mb-2.5" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
<div className="text-[11px] mb-2.5 text-text-2 leading-[1.8]">
<b>CHARRY</b> (Modulated Tide) , .
</div>
<div className="grid grid-cols-2 gap-2.5">
<div className={codeBox}>
<span style={{ color: 'var(--t3)', fontSize: '10px' }}>/* 변조조석 수식 */</span><br />
<span className="text-text-3 text-[10px]">/* 변조조석 수식 */</span><br />
ζ(t) = A(t) cos[σt θ(t)]<br />
A²(t) = Σ Yᵢ² + 2Σ YᵢYⱼ cos[(σσ)t(φφ)]
</div>
<div className="flex flex-col gap-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[10px] text-text-2">
<div className="px-2 py-1.5 rounded" style={{ background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.12)' }}>
<span style={{ color: 'var(--cyan)', fontWeight: 700 }}> </span><br />
<span style={{ color: 'var(--t2)' }}> f배 f배 </span>
<span className="text-primary-cyan font-bold"> </span><br />
<span className="text-text-2"> f배 f배 </span>
</div>
<div className="px-2 py-1.5 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)' }}>
<span style={{ color: 'var(--orange)', fontWeight: 700 }}> </span><br />
<span style={{ color: 'var(--t2)' }}>- </span>
<span className="text-status-orange font-bold"> </span><br />
<span className="text-text-2">- </span>
</div>
</div>
</div>
@ -391,7 +391,7 @@ function KospsPanel() {
<div className="grid grid-cols-2 gap-3 mb-4">
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--cyan)', margin: 0 }}>
<div style={labelStyle('var(--cyan)')}>📊 </div>
<div className="flex flex-col gap-1.5 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[11px] text-text-2">
{[
{ icon: '🌬️', label: '바람·기온', detail: 'KMA UM · ~12km · 2회/일', bg: 'rgba(6,182,212,.04)', bd: 'rgba(6,182,212,.12)' },
{ icon: '🌊', label: '해류(표층)', detail: 'HYCOM · ~9km · 1회/일', bg: 'rgba(59,130,246,.04)', bd: 'rgba(59,130,246,.12)' },
@ -408,14 +408,14 @@ function KospsPanel() {
</div>
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--green)', margin: 0 }}>
<div style={labelStyle('var(--green)')}>🗂 </div>
<div className="flex flex-col gap-1.5 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[11px] text-text-2">
<div className="px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(34,197,94,.04)', border: '1px solid rgba(34,197,94,.12)' }}>
<div className="font-semibold mb-0.5">📍 ·</div>
<div style={{ color: 'var(--t3)' }}>(ENC) 500m </div>
<div className="text-text-3">(ENC) 500m </div>
</div>
<div className="px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(34,197,94,.04)', border: '1px solid rgba(34,197,94,.12)' }}>
<div className="font-semibold mb-0.5">🗺 </div>
<div style={{ color: 'var(--t3)' }}> </div>
<div className="text-text-3"> </div>
</div>
</div>
</div>
@ -427,23 +427,23 @@ function KospsPanel() {
<div className="grid grid-cols-2 gap-3">
<div>
<div className={`${codeBox} mb-2`}>
<span style={{ color: 'var(--t3)', fontSize: '10px' }}>/* 취송류 유속 (이·강, 2000) */</span><br />
V_WDC = <span style={{ color: 'var(--orange)' }}>0.029</span> × V_wind
<span className="text-text-3 text-[10px]">/* 취송류 유속 (이·강, 2000) */</span><br />
V_WDC = <span className="text-status-orange">0.029</span> × V_wind
</div>
<div className={codeBox}>
<span style={{ color: 'var(--t3)', fontSize: '10px' }}>/* 취송류 유향 */</span><br />
θ_WDC = θ_wind + <span style={{ color: 'var(--cyan)' }}>18.6°</span>
<span className="text-text-3 text-[10px]">/* 취송류 유향 */</span><br />
θ_WDC = θ_wind + <span className="text-primary-cyan">18.6°</span>
</div>
</div>
<div className="flex flex-col gap-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[10px] text-text-2">
<div className="px-2 py-1.5 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.15)' }}>
<span style={{ color: 'var(--orange)', fontWeight: 700 }}>V_WDC</span> : (m/s) 2.9%
<span className="text-status-orange font-bold">V_WDC</span> : (m/s) 2.9%
</div>
<div className="px-2 py-1.5 rounded" style={{ background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.15)' }}>
<span style={{ color: 'var(--cyan)', fontWeight: 700 }}>18.6°</span> : Ekman
<span className="text-primary-cyan font-bold">18.6°</span> : Ekman
</div>
<div className="px-2 py-1.5 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.15)' }}>
<b style={{ color: 'var(--green)' }}></b> : ·(2000),
<b className="text-status-green"></b> : ·(2000),
</div>
</div>
</div>
@ -472,16 +472,16 @@ function KospsPanel() {
</div>
))}
</div>
<div className="text-[10px] text-center mt-1" style={{ color: 'var(--t3)' }}>
<div className="text-[10px] text-center mt-1 text-text-3">
FTP DB
</div>
<div className="mt-2.5 p-2 rounded-md" style={{ background: 'rgba(234,179,8,.05)', border: '1px solid rgba(234,179,8,.15)' }}>
<div className="text-[10px] font-bold mb-1" style={{ color: 'var(--yellow)' }}> </div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.6' }}>
<div className="text-[10px] font-bold mb-1 text-status-yellow"> </div>
<div className="text-[10px] text-text-2 leading-[1.6]">
조류: 무한 <br />
(HYCOM): <b>5</b> <br />
·: <b style={{ color: 'var(--orange)' }}>3</b> <br />
<b style={{ color: 'var(--red)' }}>72h </b>
·: <b className="text-status-orange">3</b> <br />
<b className="text-status-red">72h </b>
</div>
</div>
</div>
@ -494,22 +494,22 @@ function KospsPanel() {
<div className="flex items-center gap-2.5 mb-3.5">
<div className="w-[34px] h-[34px] rounded-lg flex items-center justify-center text-[17px]" style={{ background: 'rgba(6,182,212,.15)', border: '1px solid rgba(6,182,212,.3)' }}>📜</div>
<div>
<div className="text-[13px] font-bold" style={{ color: 'var(--cyan)' }}> ( 10-1567431)</div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}> · · 2015 </div>
<div className="text-[13px] font-bold text-primary-cyan"> ( 10-1567431)</div>
<div className="text-[10px] mt-0.5 text-text-3"> · · 2015 </div>
</div>
</div>
{/* 특허 개요 */}
<div className="rounded-lg p-3 mb-3.5 text-[11px]" style={{ background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.12)', color: 'var(--t2)', lineHeight: '1.8' }}>
<b style={{ color: 'var(--cyan)' }}>(ESI, Environmental Sensitivity Index Map)</b> ·· , . ·· ·· , <b style={{ color: 'var(--orange)' }}>CHARRY </b> .
<b className="text-primary-cyan">(ESI, Environmental Sensitivity Index Map)</b> ·· , . ·· ·· , <b className="text-status-orange">CHARRY </b> .
</div>
{/* 3단계 처리 프로세스 */}
<div className="text-[11px] font-bold mb-2.5"> 3 </div>
<div className="grid grid-cols-3 gap-2 mb-3.5">
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(249,115,22,.2)', borderTop: '3px solid var(--orange)' }}>
<div className="text-[11px] font-bold mb-1.5" style={{ color: 'var(--orange)' }}> (S10)</div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] font-bold mb-1.5 text-status-orange"> (S10)</div>
<div className="text-[10px] text-text-2 leading-[1.7]">
<b></b> : ·· <br />
<b></b> : NGSST ( , 5km )<br />
<b></b> :
@ -517,9 +517,9 @@ function KospsPanel() {
<div className="mt-1 p-1 rounded text-[10px]" style={{ background: 'rgba(249,115,22,.06)', color: 'var(--t3)' }}>FTP ···DB구축까지 </div>
</div>
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(6,182,212,.2)', borderTop: '3px solid var(--cyan)' }}>
<div className="text-[11px] font-bold mb-1.5" style={{ color: 'var(--cyan)' }}> · (S20)</div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<b style={{ color: 'var(--cyan)' }}>CHARRY </b> <br />
<div className="text-[11px] font-bold mb-1.5 text-primary-cyan"> · (S20)</div>
<div className="text-[10px] text-text-2 leading-[1.7]">
<b className="text-primary-cyan">CHARRY </b> <br />
2D DB <br />
경험식 : V_WDC=0.029×V_wind, θ_WDC=θ_wind+18.6°<br />
M2·S2·K1·O1 4
@ -527,8 +527,8 @@ function KospsPanel() {
<div className="mt-1 p-1 rounded text-[10px]" style={{ background: 'rgba(6,182,212,.06)', color: 'var(--t3)' }}>계산격자 : 15초( 463m) · 3,225,600</div>
</div>
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(34,197,94,.2)', borderTop: '3px solid var(--green)' }}>
<div className="text-[11px] font-bold mb-1.5" style={{ color: 'var(--green)' }}> (S30)</div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] font-bold mb-1.5 text-status-green"> (S30)</div>
<div className="text-[10px] text-text-2 leading-[1.7]">
<b>·</b> <br />
(Monte Carlo) <br />
fBm 난류확산 : σ²=Atᵐ (m2H)<br />
@ -541,9 +541,9 @@ function KospsPanel() {
{/* 해수유동 방정식 & 풍화 5단계 */}
<div className="grid grid-cols-2 gap-2.5 mb-3">
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(59,130,246,.2)' }}>
<div className="text-[11px] font-bold mb-2" style={{ color: 'var(--blue)' }}>📐 2 </div>
<div className="text-[10px] mb-2" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>(Polar Coordinate) · </div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] font-bold mb-2 text-primary-blue">📐 2 </div>
<div className="text-[10px] mb-2 text-text-2 leading-[1.7]">(Polar Coordinate) · </div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
{[
{ label: '기조력', desc: '제1(Love Number 0.69) + 제2(α=0.9) 포함' },
{ label: '4대 분조', desc: 'M2(1.405×10⁻⁴/s) · S2 · K1 · O1' },
@ -551,28 +551,28 @@ function KospsPanel() {
{ label: '조간대', desc: 'Flather & Heaps(1975) 처리기법' },
].map(r => (
<div key={r.label} className="px-2 py-1 rounded" style={{ background: 'rgba(59,130,246,.05)' }}>
<span className="font-bold" style={{ color: 'var(--blue)' }}>{r.label}</span> : {r.desc}
<span className="font-bold text-primary-blue">{r.label}</span> : {r.desc}
</div>
))}
</div>
</div>
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(249,115,22,.2)' }}>
<div className="text-[11px] font-bold mb-2" style={{ color: 'var(--orange)' }}>🔁 (Weathering) 5</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] font-bold mb-2 text-status-orange">🔁 (Weathering) 5</div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.1)' }}>
<span className="font-bold" style={{ color: 'var(--orange)' }}> </span> : Fay(1969) + Mackay et al.(1980) · 3
<span className="font-bold text-status-orange"> </span> : Fay(1969) + Mackay et al.(1980) · 3
</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(239,68,68,.05)', border: '1px solid rgba(239,68,68,.1)' }}>
<span className="font-bold" style={{ color: 'var(--red)' }}> </span> : Stiver &amp; Mackay(1984) · (1~10, 25%)
<span className="font-bold text-status-red"> </span> : Stiver &amp; Mackay(1984) · (1~10, 25%)
</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(168,85,247,.05)', border: '1px solid rgba(168,85,247,.1)' }}>
<span className="font-bold" style={{ color: 'var(--purple)' }}> </span> : · · (15%)
<span className="font-bold text-primary-purple"> </span> : · · (15%)
</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(234,179,8,.05)', border: '1px solid rgba(234,179,8,.1)' }}>
<span className="font-bold" style={{ color: 'var(--yellow)' }}> </span> : Mackay et al.(1980) + Mooney(1951) · water-in-oil
<span className="font-bold text-status-yellow"> </span> : Mackay et al.(1980) + Mooney(1951) · water-in-oil
</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.1)' }}>
<span className="font-bold" style={{ color: 'var(--green)' }}> </span> : · ·
<span className="font-bold text-status-green"> </span> : · ·
</div>
</div>
</div>
@ -581,38 +581,38 @@ function KospsPanel() {
{/* Akima 수심 보간 & NGSST 수온 */}
<div className="grid grid-cols-2 gap-2.5 mb-3">
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(34,197,94,.2)' }}>
<div className="text-[11px] font-bold mb-2" style={{ color: 'var(--green)' }}>🗺 Akima </div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
(ENC) <b style={{ color: 'var(--green)' }}>Akima(1978) 2 5</b>(Bivariate Quintic Polynomial) . (TIN) 21 .
<div className="text-[11px] font-bold mb-2 text-status-green">🗺 Akima </div>
<div className="text-[10px] text-text-2 leading-[1.7]">
(ENC) <b className="text-status-green">Akima(1978) 2 5</b>(Bivariate Quintic Polynomial) . (TIN) 21 .
</div>
<div className="mt-1.5 p-1.5 rounded" style={{ ...codeBox, padding: '6px' }}>
z(x,y) = Σ Σ qᵢⱼ xⁱ <span className="text-[10px] text-text-3">(i5, i+j5)</span>
</div>
</div>
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(6,182,212,.2)' }}>
<div className="text-[11px] font-bold mb-2" style={{ color: 'var(--cyan)' }}>🌡 NGSST </div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
Kawamura <b style={{ color: 'var(--cyan)' }}>New Generation SST(NGSST)</b> FTP . (AVHRR·MODIS) + (AMSR-E) .
<div className="text-[11px] font-bold mb-2 text-primary-cyan">🌡 NGSST </div>
<div className="text-[10px] text-text-2 leading-[1.7]">
Kawamura <b className="text-primary-cyan">New Generation SST(NGSST)</b> FTP . (AVHRR·MODIS) + (AMSR-E) .
</div>
<div className="flex flex-col gap-1 mt-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold" style={{ color: 'var(--cyan)' }}></span> : 116~166°E, 13~63°N ()</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold" style={{ color: 'var(--cyan)' }}></span> : 3( 5km) · 1 </div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold" style={{ color: 'var(--cyan)' }}></span> : SST() = 0.15 × DN 3.0</div>
<div className="flex flex-col gap-1 mt-1.5 text-[10px] text-text-2">
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold text-primary-cyan"></span> : 116~166°E, 13~63°N ()</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold text-primary-cyan"></span> : 3( 5km) · 1 </div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)' }}><span className="font-bold text-primary-cyan"></span> : SST() = 0.15 × DN 3.0</div>
</div>
</div>
</div>
{/* 특허 기여율 */}
<div className="rounded-lg p-3" style={{ background: 'rgba(234,179,8,.04)', border: '1px solid rgba(234,179,8,.2)' }}>
<div className="text-[11px] font-bold mb-2" style={{ color: 'var(--yellow)' }}>📋 </div>
<div className="grid grid-cols-2 gap-2 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] font-bold mb-2 text-status-yellow">📋 </div>
<div className="grid grid-cols-2 gap-2 text-[10px] text-text-2">
<div className="p-2 rounded-md" style={{ background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.12)' }}>
<div className="font-bold mb-1" style={{ color: 'var(--cyan)' }}>🔷 ( 65%)</div>
<div style={{ color: 'var(--t2)', lineHeight: '1.6' }}>3 <br /><span style={{ color: 'var(--t3)' }}> | 2013.01~2013.12</span></div>
<div className="font-bold mb-1 text-primary-cyan">🔷 ( 65%)</div>
<div className="text-text-2 leading-[1.6]">3 <br /><span className="text-text-3"> | 2013.01~2013.12</span></div>
</div>
<div className="p-2 rounded-md" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)' }}>
<div className="font-bold mb-1" style={{ color: 'var(--orange)' }}>🔶 ( 35%)</div>
<div style={{ color: 'var(--t2)', lineHeight: '1.6' }}> (HNS) <br /><span style={{ color: 'var(--t3)' }}> | 2013.01~2013.12</span></div>
<div className="font-bold mb-1 text-status-orange">🔶 ( 35%)</div>
<div className="text-text-2 leading-[1.6]"> (HNS) <br /><span className="text-text-3"> | 2013.01~2013.12</span></div>
</div>
</div>
<div className="mt-2 p-1.5 rounded text-[10px]" style={{ background: 'rgba(255,255,255,.02)', border: '1px solid var(--bd)', color: 'var(--t3)' }}>
@ -628,7 +628,7 @@ function KospsPanel() {
<div className="w-[30px] h-[30px] rounded-[7px] flex items-center justify-center text-sm shrink-0" style={{ background: 'rgba(6,182,212,.12)', border: '1px solid rgba(6,182,212,.25)' }}>📄</div>
<div className="flex-1">
<div className="text-xs font-bold">KOSPS관련 <span className="text-[11px] ml-1" style={{ color: 'var(--t3)', transition: 'transform .2s', display: 'inline-block', transform: kospsPapersOpen ? 'rotate(180deg)' : 'rotate(0)' }}></span></div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}>KOSPS · · 3D · ·</div>
<div className="text-[10px] mt-0.5 text-text-3">KOSPS · · 3D · ·</div>
</div>
</div>
{kospsPapersOpen && <div className="flex flex-col gap-2 mt-3.5">
@ -646,8 +646,8 @@ function KospsPanel() {
<span className="text-[10px] text-text-3">{paper.year}</span>
</div>
<div className="text-[11px] font-bold mb-1">{paper.title}</div>
<div className="text-[11px] mb-1.5" style={{ color: 'var(--t3)' }}>{paper.authors}</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>{paper.desc}</div>
<div className="text-[11px] mb-1.5 text-text-3">{paper.authors}</div>
<div className="text-[11px] text-text-2 leading-[1.7]">{paper.desc}</div>
</div>
))}
</div>}
@ -659,7 +659,7 @@ function KospsPanel() {
<span style={{ ...tag('var(--cyan)'), fontWeight: 700, fontSize: '12px' }}>📄 </span>
<span className="text-[11px] ml-1" style={{ color: 'var(--t3)', transition: 'transform .2s', display: 'inline-block', transform: papersOpen ? 'rotate(180deg)' : 'rotate(0)' }}></span>
</div>
{papersOpen && <div className="flex flex-col gap-1.5 mb-3.5 text-[10px]" style={{ color: 'var(--t2)' }}>
{papersOpen && <div className="flex flex-col gap-1.5 mb-3.5 text-[10px] text-text-2">
{[
{ num: '①', title: '유출유 확산 예측 모델의 상시 운용 체계 개발에 관한 연구', authors: '김혜진 · 이문진 · 오세웅 · 강준묵', journal: '해양환경안전학회지', detail: '제17권 4호, pp.375-382 | 2011', desc: 'KOSPS 상시 운용 체계 구축 · 정적/동적 자료 FTP 자동 연계 · 서해·남해 시범 운용 성능 평가', color: 'var(--cyan)' },
{ num: '②', title: '해양오염 방제지원시스템 구축을 위한 실시간 조류 예측 기술 개발', authors: '이문진 · 강용균 외', journal: '해양환경안전학회 춘계학술발표회', detail: '| 2008', desc: 'CHARRY 모델 인천·서해 적용 검증 · 창조/낙조 실시간 조류 재현 결과', color: 'var(--cyan)' },
@ -676,8 +676,8 @@ function KospsPanel() {
<div className="w-6 h-6 rounded-[5px] flex items-center justify-center text-[11px] shrink-0" style={{ background: `${paper.color}1F` }}>{paper.num}</div>
<div>
<div className="font-bold mb-0.5">{paper.title}</div>
<div style={{ color: 'var(--t3)', lineHeight: '1.6' }}>{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1" style={{ color: 'var(--t2)' }}>{paper.desc}</div>
<div className="text-text-3 leading-[1.6]">{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1 text-text-2">{paper.desc}</div>
{paper.tags && (
<div className="flex flex-wrap gap-1 mt-1">
{paper.tags.map(t => <span key={t} style={tag(paper.color)}>{t}</span>)}
@ -695,7 +695,7 @@ function KospsPanel() {
<span style={{ ...tag('var(--green)'), fontWeight: 700, fontSize: '12px' }}>🌐 </span>
<span className="text-[11px] ml-1" style={{ color: 'var(--t3)', transition: 'transform .2s', display: 'inline-block', transform: intlPapersOpen ? 'rotate(180deg)' : 'rotate(0)' }}></span>
</div>
{intlPapersOpen && <div className="flex flex-col gap-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
{intlPapersOpen && <div className="flex flex-col gap-1.5 text-[10px] text-text-2">
{[
{ num: '①', title: 'OpenDrift v1.0: a generic framework for trajectory modelling', authors: 'Dagestad et al.', journal: 'Geoscientific Model Development', detail: 'Vol.11, pp.1405-1420 | 2018', desc: 'OpenDrift 프레임워크 전체 설계·구현·검증 · Python 모듈화 구조 · OpenOil 유출유 모듈 포함', color: 'var(--green)' },
{ num: '②', title: 'Observation-based evaluation of surface wave effects on oil spill trajectories', authors: 'Röhrs et al.', journal: 'J. Geophys. Res. Oceans', detail: '| 2013', desc: 'Stokes drift 파랑 기여 효과 · OpenOil 유출유 확산 현장 검증', color: 'var(--green)' },
@ -709,8 +709,8 @@ function KospsPanel() {
<div className="w-6 h-6 rounded-[5px] flex items-center justify-center text-[11px] shrink-0" style={{ background: `${paper.color}1F` }}>{paper.num}</div>
<div>
<div className="font-bold mb-0.5">{paper.title}</div>
<div style={{ color: 'var(--t3)', lineHeight: '1.6' }}>{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1" style={{ color: 'var(--t2)' }}>{paper.desc}</div>
<div className="text-text-3 leading-[1.6]">{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1 text-text-2">{paper.desc}</div>
</div>
</div>
))}
@ -731,12 +731,12 @@ function PoseidonPanel() {
<div className="flex items-center gap-3 mb-3">
<div className="w-[38px] h-[38px] rounded-[10px] flex items-center justify-center text-xl" style={{ background: 'rgba(59,130,246,.15)', border: '1px solid rgba(59,130,246,.3)' }}>🔵</div>
<div>
<div className="text-[15px] font-bold" style={{ color: 'var(--blue)' }}>POSEIDON ( )</div>
<div className="text-[15px] font-bold text-primary-blue">POSEIDON ( )</div>
<div className="text-[11px] mt-0.5 text-text-3"> · () · · MOHID · </div>
</div>
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
· ( 10-1868791, 2018) POSEIDON은 <b style={{ color: 'var(--blue)' }}>(Drifter) </b> , <b style={{ color: 'var(--purple)' }}>GA·DE·HS·PSO </b> . IST/MARETEC이 <b style={{ color: 'var(--cyan)' }}>MOHID 3D </b> .
<div className="text-[11px] text-text-2 leading-[1.8]">
· ( 10-1868791, 2018) POSEIDON은 <b className="text-primary-blue">(Drifter) </b> , <b className="text-primary-purple">GA·DE·HS·PSO </b> . IST/MARETEC이 <b className="text-primary-cyan">MOHID 3D </b> .
</div>
<div className="mt-2.5 px-3 py-2 rounded-md text-[10px]" style={{ background: 'rgba(59,130,246,.06)', border: '1px solid rgba(59,130,246,.15)', color: 'var(--t3)' }}>
📚 : ·, &quot; &quot;, 10-1868791, 2018.<br />
@ -752,13 +752,13 @@ function PoseidonPanel() {
<div className="rounded-lg p-3" style={{ background: 'var(--bg0)', border: '1px solid rgba(59,130,246,.2)', display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '12px' }}>
<div className="px-2.5 py-1.5 rounded-md text-center whitespace-nowrap" style={{ background: 'rgba(59,130,246,.12)', border: '1px solid rgba(59,130,246,.25)', fontFamily: 'var(--fM)' }}>
<div className="text-[10px] text-text-3"></div>
<div className="text-[11px] font-bold" style={{ color: 'var(--blue)' }}>10-1868791</div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}>2018 </div>
<div className="text-[11px] font-bold text-primary-blue">10-1868791</div>
<div className="text-[10px] mt-0.5 text-text-3">2018 </div>
</div>
<div>
<div className="text-[11px] font-bold mb-1"> (POSEIDON)</div>
<div className="text-[10px]" style={{ color: 'var(--t2)' }}>
<span style={{ color: 'var(--blue)' }}></span> : · · | <span style={{ color: 'var(--blue)' }}></span> : ()
<div className="text-[10px] text-text-2">
<span className="text-primary-blue"></span> : · · | <span className="text-primary-blue"></span> : ()
</div>
<div className="flex flex-wrap gap-1 mt-1.5">
{['GA(유전알고리즘)', 'DE(차분진화)', 'HS(화음탐색)', 'PSO(입자군집최적화)', '뜰개 자동 동화'].map(t =>
@ -773,21 +773,21 @@ function PoseidonPanel() {
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--cyan)', margin: 0 }}>
<div style={labelStyle('var(--cyan)')}>🌊 MOHID ( )</div>
<div className={`${bodyText} mb-2.5`}> IST/MARETEC에서 1985 3D . 60 ····· .</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
{[
{ label: '격자 구성', desc: '동아시아 9km + 한반도 3km (Nesting)' },
{ label: '수직 좌표', desc: 'σ + Z-level 혼합 (GVC)' },
{ label: '검증 결과', desc: 'SST RMSE 0.42~0.78°C, SLA RMSE 0.11~0.17m' },
{ label: '경계조건', desc: 'HYCOM 재분석 (MYOCEAN 대비 우수)' },
].map(t =>
<div key={t.label} className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.12)', color: 'var(--t2)' }}><span style={{ color: 'var(--cyan)', fontWeight: 700 }}>{t.label}</span> : {t.desc}</div>
<div key={t.label} className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.12)', color: 'var(--t2)' }}><span className="text-primary-cyan font-bold">{t.label}</span> : {t.desc}</div>
)}
</div>
</div>
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--purple)', margin: 0 }}>
<div style={labelStyle('var(--purple)')}> </div>
<div className={`${bodyText} mb-2.5`}> 1 2 .</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
{[
{ label: '최적화 알고리즘', desc: 'GA · DE · HS · PSO 중 선택' },
{ label: '입력 데이터', desc: '유속·풍속 벡터 + 제1모델 변화량' },
@ -805,21 +805,21 @@ function PoseidonPanel() {
<div style={labelStyle('var(--blue)')}>📐 POSEIDON </div>
<div className="grid grid-cols-2 gap-3">
<div>
<div className="text-[11px] font-semibold mb-1.5" style={{ color: 'var(--t3)' }}>1 ()</div>
<div className="text-[11px] font-semibold mb-1.5 text-text-3">1 ()</div>
<div className={codeBox}>
Model_x = Δt × current_u + Δt × c × wind_u<br />
Model_y = Δt × current_v + Δt × c × wind_v
</div>
<div className="text-[10px] mt-1.5" style={{ color: 'var(--t3)' }}>c : 풍속 (: c=0.3 30% )</div>
<div className="text-[10px] mt-1.5 text-text-3">c : 풍속 (: c=0.3 30% )</div>
</div>
<div>
<div className="text-[11px] font-semibold mb-1.5" style={{ color: 'var(--t3)' }}>2 ( )</div>
<div className="text-[11px] font-semibold mb-1.5 text-text-3">2 ( )</div>
<div className={codeBox}>
Revised_x = a1·current_u + a2·current_v<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ a3·wind_u + a4·wind_v<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ a5·Model_x + a6·Model_y + a7
</div>
<div className="text-[10px] mt-1.5" style={{ color: 'var(--t3)' }}>a1~a7 : GA·DE·PSO로 </div>
<div className="text-[10px] mt-1.5 text-text-3">a1~a7 : GA·DE·PSO로 </div>
</div>
</div>
</div>
@ -828,7 +828,7 @@ function PoseidonPanel() {
<div style={labelStyle('var(--t1)')}>🔄 POSEIDON_V2 </div>
{/* 외부 입력 자료 */}
<div className="text-[10px] font-bold mb-1.5 mt-1" style={{ color: 'var(--t3)' }}> </div>
<div className="text-[10px] font-bold mb-1.5 mt-1 text-text-3"> </div>
<div className="flex items-center justify-center gap-0 mb-3">
{[
{ label: 'HYCOM', sub: '해류·수온·염분', detail: 'YYYYMMDD.nc', color: 'var(--blue)' },
@ -841,7 +841,7 @@ function PoseidonPanel() {
background: `${node.color}14`, border: `1px solid ${node.color}33`
}}>
<div className="font-bold text-[11px]" style={{ color: node.color }}>{node.label}</div>
<div style={{ color: 'var(--t2)' }}>{node.sub}</div>
<div className="text-text-2">{node.sub}</div>
<div className="mt-0.5" style={{ color: 'var(--t3)', fontSize: '9px' }}>{node.detail}</div>
</div>
{i < 3 && <div className="w-[20px] h-px" style={{ background: 'var(--bdL)' }} />}
@ -850,10 +850,10 @@ function PoseidonPanel() {
</div>
{/* 중앙 화살표 */}
<div className="text-center text-[10px] mb-2" style={{ color: 'var(--t3)' }}> DATA PREP / </div>
<div className="text-center text-[10px] mb-2 text-text-3"> DATA PREP / </div>
{/* 4대 도메인 실행 모듈 */}
<div className="text-[10px] font-bold mb-1.5" style={{ color: 'var(--t3)' }}>POSEIDON 4 (EA012 KO108 )</div>
<div className="text-[10px] font-bold mb-1.5 text-text-3">POSEIDON 4 (EA012 KO108 )</div>
<div className="grid grid-cols-4 gap-2 mb-3">
{[
{ label: 'HYDR', script: 'RUN-HYDR.sh', engine: 'MOHID 3D', desc: '해류·수온·염분·수위', color: 'var(--cyan)', icon: '🌊' },
@ -867,15 +867,15 @@ function PoseidonPanel() {
}}>
<div className="text-base mb-1">{m.icon}</div>
<div className="text-[12px] font-bold" style={{ color: m.color }}>{m.label}</div>
<div className="text-[9px] mt-0.5" style={{ color: 'var(--t2)' }}>{m.engine}</div>
<div className="text-[9px] mt-0.5 text-text-2">{m.engine}</div>
<div className="text-[9px] mt-0.5 px-1 py-0.5 rounded" style={{ background: `${m.color}14`, color: 'var(--t3)' }}>{m.script}</div>
<div className="text-[9px] mt-1" style={{ color: 'var(--t2)' }}>{m.desc}</div>
<div className="text-[9px] mt-1 text-text-2">{m.desc}</div>
</div>
))}
</div>
{/* 화살표 + 최적화 */}
<div className="text-center text-[10px] mb-2" style={{ color: 'var(--t3)' }}> HYDR + WAVE + TIDE OILS GA/DE/PSO </div>
<div className="text-center text-[10px] mb-2 text-text-3"> HYDR + WAVE + TIDE OILS GA/DE/PSO </div>
{/* 출력·활용 */}
<div className="flex items-center justify-center gap-0">
@ -901,12 +901,12 @@ function PoseidonPanel() {
HYCOM(.nc) + GDAPS(.grib2) (EA012/KO108) MOHID() + SWAN() + OILS HDF5
</div>
<div className="mt-2.5 p-2 rounded-md" style={{ background: 'rgba(234,179,8,.05)', border: '1px solid rgba(234,179,8,.15)' }}>
<div className="text-[10px] font-bold mb-1" style={{ color: 'var(--yellow)' }}> </div>
<div className="text-[10px]" style={{ color: 'var(--t2)', lineHeight: '1.6' }}>
<div className="text-[10px] font-bold mb-1 text-status-yellow"> </div>
<div className="text-[10px] text-text-2 leading-[1.6]">
조류: 무한 <br />
(HYCOM): <b>5</b> <br />
·: <b style={{ color: 'var(--orange)' }}>3</b> <br />
<b style={{ color: 'var(--red)' }}>72h </b>
·: <b className="text-status-orange">3</b> <br />
<b className="text-status-red">72h </b>
</div>
</div>
</div>
@ -918,7 +918,7 @@ function PoseidonPanel() {
<div className="w-[30px] h-[30px] rounded-[7px] flex items-center justify-center text-sm shrink-0" style={{ background: 'rgba(59,130,246,.12)', border: '1px solid rgba(59,130,246,.25)' }}>📄</div>
<div>
<div className="text-xs font-bold">POSEIDON관련 </div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}> · · · · MOHID · </div>
<div className="text-[10px] mt-0.5 text-text-3"> · · · · MOHID · </div>
</div>
</div>
<div className="flex flex-col gap-2">
@ -936,8 +936,8 @@ function PoseidonPanel() {
<span className="text-[10px] text-text-3">{paper.year}</span>
</div>
<div className="text-[11px] font-bold mb-1">{paper.title}</div>
<div className="text-[11px] mb-1.5" style={{ color: 'var(--t3)' }}>{paper.authors}</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>{paper.desc}</div>
<div className="text-[11px] mb-1.5 text-text-3">{paper.authors}</div>
<div className="text-[11px] text-text-2 leading-[1.7]">{paper.desc}</div>
</div>
))}
</div>
@ -956,12 +956,12 @@ function OpenDriftPanel() {
<div className="flex items-center gap-3 mb-3">
<div className="w-[38px] h-[38px] rounded-[10px] flex items-center justify-center text-xl" style={{ background: 'rgba(34,197,94,.15)', border: '1px solid rgba(34,197,94,.3)' }}>🟢</div>
<div>
<div className="text-[15px] font-bold" style={{ color: 'var(--blue)' }}>OpenDrift ( )</div>
<div className="text-[15px] font-bold text-primary-blue">OpenDrift ( )</div>
<div className="text-[11px] mt-0.5 text-text-3"> MET Norway · OpenOil · Python · IMO/IPIECA </div>
</div>
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
Dagestad et al.(2018) OpenDrift는 ·SAR·· <b style={{ color: 'var(--blue)' }}>Python </b>. NEMO·ROMS·HYCOM , <b style={{ color: 'var(--cyan)' }}>OpenOil </b> .
<div className="text-[11px] text-text-2 leading-[1.8]">
Dagestad et al.(2018) OpenDrift는 ·SAR·· <b className="text-primary-blue">Python </b>. NEMO·ROMS·HYCOM , <b className="text-primary-cyan">OpenOil </b> .
</div>
<div className="flex gap-2 flex-wrap mt-2.5">
<span className="px-3.5 py-1.5 rounded-md text-[11px] font-semibold" style={{ border: '1px solid rgba(34,197,94,.3)', background: 'rgba(34,197,94,.08)', color: 'var(--green)' }}>🔗 (opendrift.github.io)</span>
@ -988,7 +988,7 @@ function OpenDriftPanel() {
].map(s => (
<div key={s.title} className={`${card} ${cardBg}`} style={{ borderTop: `3px solid ${s.color}`, margin: 0 }}>
<div style={labelStyle(s.color)}>{s.title}</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
{s.items.map((item, idx) => (
'html' in item
? <div key={idx} className="px-2 py-1 rounded" style={{ background: `${s.color}0A`, border: `1px solid ${s.color}1F`, color: 'var(--t2)' }} dangerouslySetInnerHTML={{ __html: sanitizeHtml(item.html) }} />
@ -1042,7 +1042,7 @@ function OpenDriftPanel() {
</div>
))}
</div>
<div className="text-[10px] text-center mt-1" style={{ color: 'var(--t3)' }}>
<div className="text-[10px] text-center mt-1 text-text-3">
(NEMO·ROMS·HYCOM) + (ECMWF·GFS) NOAA Oil Library OpenDrift/OpenOil NetCDF ·
</div>
</div>
@ -1054,7 +1054,7 @@ function OpenDriftPanel() {
<div className="w-8 h-8 rounded-lg flex items-center justify-center text-base shrink-0" style={{ background: 'rgba(59,130,246,.12)', border: '1px solid rgba(59,130,246,.25)' }}>📄</div>
<div>
<div className="text-xs font-bold">OpenDrift / OpenOil </div>
<div className="text-[10px] mt-0.5" style={{ color: 'var(--t3)' }}> 3 WING </div>
<div className="text-[10px] mt-0.5 text-text-3"> 3 WING </div>
</div>
</div>
<div className="flex flex-col gap-2.5">
@ -1067,26 +1067,26 @@ function OpenDriftPanel() {
<span key={t.label} className="whitespace-nowrap" style={{ padding: '2px 8px', background: `${t.color}1F`, border: `1px solid ${t.color}40`, borderRadius: '4px', fontSize: '10px', fontWeight: 700, color: t.color }}>{t.label}</span>
)}
</div>
<span className="text-[10px] whitespace-nowrap" style={{ color: 'var(--t3)' }}>2024</span>
<span className="text-[10px] whitespace-nowrap text-text-3">2024</span>
</div>
<div className="text-[11px] font-bold mb-1" style={{ lineHeight: '1.5' }}>Numerical Model Test of Spilled Oil Transport Near the Korean Coasts Using Various Input Parametric Models</div>
<div className="text-[11px] mb-2" style={{ color: 'var(--t3)' }}>Hai Van Dang, Suchan Joo, Junhyeok Lim, Jinhwan Hur, Sungwon Shin | Hanyang University ERICA | Journal of Ocean Engineering and Technology, 2024</div>
<div className="text-[11px] font-bold mb-1" className="leading-normal">Numerical Model Test of Spilled Oil Transport Near the Korean Coasts Using Various Input Parametric Models</div>
<div className="text-[11px] mb-2 text-text-3">Hai Van Dang, Suchan Joo, Junhyeok Lim, Jinhwan Hur, Sungwon Shin | Hanyang University ERICA | Journal of Ocean Engineering and Technology, 2024</div>
<div className="grid grid-cols-2 gap-2 mb-2">
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
OpenOil - (Met-Ocean) . (2007) 6 .
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
CMEMS + ECMWF . ( &lt;60m ) . Envisat ASAR .
</div>
</div>
<div className="mb-2">
<div className="text-[11px] mb-1" style={{ color: 'var(--t2)' }}><b> 6 </b></div>
<div className="grid grid-cols-3 gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="text-[11px] mb-1 text-text-2"><b> 6 </b></div>
<div className="grid grid-cols-3 gap-1 text-[10px] text-text-2">
<div className="px-2 py-1 rounded" style={{ background: 'rgba(59,130,246,.05)', border: '1px solid rgba(59,130,246,.12)', color: 'var(--t2)' }}><b style={{ color: '#3b82f6' }}></b> HYCOM / CMEMS</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--green)' }}></b> CMEMS / ECMWF-ERA5</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--orange)' }}></b> NCEP-GFS / ECMWF</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', color: 'var(--t2)' }}><b className="text-status-green"></b> CMEMS / ECMWF-ERA5</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b className="text-status-orange"></b> NCEP-GFS / ECMWF</div>
</div>
</div>
<div className="p-2 rounded-md text-[10px]" style={{ background: 'rgba(59,130,246,.04)', border: '1px solid rgba(59,130,246,.1)', color: 'var(--t2)', lineHeight: '1.7' }}>
@ -1102,24 +1102,24 @@ function OpenDriftPanel() {
<span key={t.label} className="whitespace-nowrap" style={{ padding: '2px 8px', background: `${t.color}1F`, border: `1px solid ${t.color}40`, borderRadius: '4px', fontSize: '10px', fontWeight: 700, color: t.color }}>{t.label}</span>
)}
</div>
<span className="text-[10px] whitespace-nowrap" style={{ color: 'var(--t3)' }}>1998</span>
<span className="text-[10px] whitespace-nowrap text-text-3">1998</span>
</div>
<div className="text-[11px] font-bold mb-1" style={{ lineHeight: '1.5' }}> (Oil Spill Behavior Forecasting Model in South-eastern Coastal Area of Korea)</div>
<div className="text-[11px] mb-2" style={{ color: 'var(--t3)' }}>, , , | | Vol.1 No.2, pp.5259, 1998</div>
<div className="text-[11px] font-bold mb-1" className="leading-normal"> (Oil Spill Behavior Forecasting Model in South-eastern Coastal Area of Korea)</div>
<div className="text-[11px] mb-2 text-text-3">, , , | | Vol.1 No.2, pp.5259, 1998</div>
<div className="grid grid-cols-2 gap-2 mb-2">
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
(-) OILSPILLFM . (1995) .
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
+ 2D (ADI법). Vw = 0.03×V10. Random Walk. 1 .
</div>
</div>
<div className="grid grid-cols-3 gap-1 text-[10px] mb-2" style={{ color: 'var(--t2)' }}>
<div className="grid grid-cols-3 gap-1 text-[10px] mb-2 text-text-2">
<div className="px-2 py-1 rounded" style={{ background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.12)', color: 'var(--t2)' }}><b style={{ color: '#06b6d4' }}></b> Navier-Stokes 2D ·</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(168,85,247,.05)', border: '1px solid rgba(168,85,247,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--purple)' }}></b> DB </div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--orange)' }}></b> ··· 5</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(168,85,247,.05)', border: '1px solid rgba(168,85,247,.12)', color: 'var(--t2)' }}><b className="text-primary-purple"></b> DB </div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b className="text-status-orange"></b> ··· 5</div>
</div>
<div className="p-2 rounded-md text-[10px]" style={{ background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.1)', color: 'var(--t2)', lineHeight: '1.7' }}>
<b style={{ color: '#06b6d4' }}>WING </b> : OpenDrift·KOSPS의 . · OpenDrift .
@ -1134,37 +1134,37 @@ function OpenDriftPanel() {
<span key={t.label} className="whitespace-nowrap" style={{ padding: '2px 8px', background: `${t.color}1F`, border: `1px solid ${t.color}40`, borderRadius: '4px', fontSize: '10px', fontWeight: 700, color: t.color }}>{t.label}</span>
)}
</div>
<span className="text-[10px] whitespace-nowrap" style={{ color: 'var(--t3)' }}>2008</span>
<span className="text-[10px] whitespace-nowrap text-text-3">2008</span>
</div>
<div className="text-[11px] font-bold mb-1" style={{ lineHeight: '1.5' }}> (Analysis of Oil Spill Dispersion in Taean Coastal Zone)</div>
<div className="text-[11px] mb-2" style={{ color: 'var(--t3)' }}>, | | · 17 pp.6063, 2008</div>
<div className="text-[11px] font-bold mb-1" className="leading-normal"> (Analysis of Oil Spill Dispersion in Taean Coastal Zone)</div>
<div className="text-[11px] mb-2 text-text-3">, | | · 17 pp.6063, 2008</div>
<div className="grid grid-cols-2 gap-2 mb-2">
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
2007 12 15 · 2D . · .
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.7' }}>
<div className="text-[11px] text-text-2 leading-[1.7]">
<b> </b><br />
α = 2% (3% , 2.5% ). θ = 20° . , .
</div>
</div>
<div className="grid grid-cols-3 gap-1 text-[10px] mb-2" style={{ color: 'var(--t2)' }}>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--orange)' }}></b> ~( )</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(239,68,68,.05)', border: '1px solid rgba(239,68,68,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--red)' }}></b> , 150m</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', color: 'var(--t2)' }}><b style={{ color: 'var(--green)' }}></b> 50/9 · 5 </div>
<div className="grid grid-cols-3 gap-1 text-[10px] mb-2 text-text-2">
<div className="px-2 py-1 rounded" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.12)', color: 'var(--t2)' }}><b className="text-status-orange"></b> ~( )</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(239,68,68,.05)', border: '1px solid rgba(239,68,68,.12)', color: 'var(--t2)' }}><b className="text-status-red"></b> , 150m</div>
<div className="px-2 py-1 rounded" style={{ background: 'rgba(34,197,94,.05)', border: '1px solid rgba(34,197,94,.12)', color: 'var(--t2)' }}><b className="text-status-green"></b> 50/9 · 5 </div>
</div>
{/* 취송류 파라미터 비교 */}
<div className="p-2.5 rounded-[7px] mb-2" style={{ background: 'var(--bg0)', border: '1px solid var(--bd)' }}>
<div className="text-[10px] font-bold mb-1.5" style={{ color: 'var(--t2)' }}> ( )</div>
<div className="grid grid-cols-4 gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(239,68,68,.06)', border: '1px solid rgba(239,68,68,.12)' }}><div className="font-bold" style={{ color: 'var(--red)' }}>α = 3%</div><div style={{ color: 'var(--t3)' }}> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(234,179,8,.06)', border: '1px solid rgba(234,179,8,.12)' }}><div className="font-bold" style={{ color: 'var(--yellow)' }}>α = 2.5%</div><div style={{ color: 'var(--t3)' }}> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(34,197,94,.08)', border: '1px solid rgba(34,197,94,.2)' }}><div className="font-bold" style={{ color: 'var(--green)' }}>α = 2% </div><div style={{ color: 'var(--t3)' }}> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(6,182,212,.06)', border: '1px solid rgba(6,182,212,.12)' }}><div className="font-bold" style={{ color: '#06b6d4' }}>θ = 20° </div><div style={{ color: 'var(--t3)' }}> </div></div>
<div className="text-[10px] font-bold mb-1.5 text-text-2"> ( )</div>
<div className="grid grid-cols-4 gap-1 text-[10px] text-text-2">
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(239,68,68,.06)', border: '1px solid rgba(239,68,68,.12)' }}><div className="font-bold text-status-red">α = 3%</div><div className="text-text-3"> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(234,179,8,.06)', border: '1px solid rgba(234,179,8,.12)' }}><div className="font-bold text-status-yellow">α = 2.5%</div><div className="text-text-3"> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(34,197,94,.08)', border: '1px solid rgba(34,197,94,.2)' }}><div className="font-bold text-status-green">α = 2% </div><div className="text-text-3"> </div></div>
<div className="px-2 py-1 rounded text-center" style={{ background: 'rgba(6,182,212,.06)', border: '1px solid rgba(6,182,212,.12)' }}><div className="font-bold" style={{ color: '#06b6d4' }}>θ = 20° </div><div className="text-text-3"> </div></div>
</div>
</div>
<div className="p-2 rounded-md text-[10px]" style={{ background: 'rgba(249,115,22,.04)', border: '1px solid rgba(249,115,22,.1)', color: 'var(--t2)', lineHeight: '1.7' }}>
<b style={{ color: 'var(--orange)' }}>WING </b> : ( ) α = 2%·θ = 20° OpenDrift wind drift factor . POSEIDON( 10-1868791) .
<b className="text-status-orange">WING </b> : ( ) α = 2%·θ = 20° OpenDrift wind drift factor . POSEIDON( 10-1868791) .
</div>
</div>
</div>
@ -1181,8 +1181,8 @@ function LagrangianPanel() {
style={{ background: 'linear-gradient(135deg,rgba(6,182,212,.05),rgba(59,130,246,.04))', border: '1px solid rgba(6,182,212,.2)' }}>
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--cyan),var(--blue))' }} />
<div style={labelStyle('var(--t1)')}>🧭 (Lagrangian Particle Tracking)</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
<b style={{ color: 'var(--cyan)' }}> (Virtual Particle)</b> , . KOSPS·POSEIDON·OpenDrift 3 .
<div className="text-[11px] text-text-2 leading-[1.8]">
<b className="text-primary-cyan"> (Virtual Particle)</b> , . KOSPS·POSEIDON·OpenDrift 3 .
</div>
</div>
@ -1193,11 +1193,11 @@ function LagrangianPanel() {
dx/dt = U_c + α·U_w + U_stokes + U&apos;<br />
dy/dt = V_c + α·V_w + V_stokes + V&apos;
</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex gap-2"><span style={{ color: 'var(--orange)', fontWeight: 700, width: '60px' }}>U_c, V_c</span><span style={{ color: 'var(--t2)' }}> · (m/s)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--blue)', fontWeight: 700, width: '60px' }}>α·U_w</span><span style={{ color: 'var(--t2)' }}> (α 0.03)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--green)', fontWeight: 700, width: '60px' }}>U_stokes</span><span style={{ color: 'var(--t2)' }}> ( )</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--purple)', fontWeight: 700, width: '60px' }}>U&apos;</span><span style={{ color: 'var(--t2)' }}> ()</span></div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
<div className="flex gap-2"><span style={{ color: 'var(--orange)', fontWeight: 700, width: '60px' }}>U_c, V_c</span><span className="text-text-2"> · (m/s)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--blue)', fontWeight: 700, width: '60px' }}>α·U_w</span><span className="text-text-2"> (α 0.03)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--green)', fontWeight: 700, width: '60px' }}>U_stokes</span><span className="text-text-2"> ( )</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--purple)', fontWeight: 700, width: '60px' }}>U&apos;</span><span className="text-text-2"> ()</span></div>
</div>
</div>
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--blue)', margin: 0 }}>
@ -1206,10 +1206,10 @@ function LagrangianPanel() {
U&apos; = R · (2K_h / Δt)<br />
V&apos; = R · (2K_h / Δt)
</div>
<div className="flex flex-col gap-1 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex gap-2"><span style={{ color: 'var(--purple)', fontWeight: 700, width: '60px' }}>R</span><span style={{ color: 'var(--t2)' }}>[-1, 1] </span></div>
<div className="flex gap-2"><span style={{ color: 'var(--blue)', fontWeight: 700, width: '60px' }}>K_h</span><span style={{ color: 'var(--t2)' }}> (m²/s)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--t2)', fontWeight: 700, width: '60px' }}>Δt</span><span style={{ color: 'var(--t2)' }}> ( 1)</span></div>
<div className="flex flex-col gap-1 text-[10px] text-text-2">
<div className="flex gap-2"><span style={{ color: 'var(--purple)', fontWeight: 700, width: '60px' }}>R</span><span className="text-text-2">[-1, 1] </span></div>
<div className="flex gap-2"><span style={{ color: 'var(--blue)', fontWeight: 700, width: '60px' }}>K_h</span><span className="text-text-2"> (m²/s)</span></div>
<div className="flex gap-2"><span style={{ color: 'var(--t2)', fontWeight: 700, width: '60px' }}>Δt</span><span className="text-text-2"> ( 1)</span></div>
</div>
</div>
</div>
@ -1220,20 +1220,20 @@ function LagrangianPanel() {
<div className="grid grid-cols-2 gap-3">
<div>
<div className={`${codeBox} mb-2`}>
<span style={{ color: 'var(--t3)', fontSize: '10px' }}>/* 중력-관성 체제 (초기) */</span><br />
R(t) = <span style={{ color: 'var(--orange)' }}>K</span> · (<span style={{ color: 'var(--cyan)' }}>ΔρgV²</span> / <span style={{ color: 'var(--blue)' }}>ρw</span>)<sup>¼</sup> · t<sup>½</sup>
<span className="text-text-3 text-[10px]">/* 중력-관성 체제 (초기) */</span><br />
R(t) = <span className="text-status-orange">K</span> · (<span className="text-primary-cyan">ΔρgV²</span> / <span className="text-primary-blue">ρw</span>)<sup>¼</sup> · t<sup>½</sup>
</div>
<div className={codeBox}>
<span style={{ color: 'var(--t3)', fontSize: '10px' }}>/* 중력-점성 체제 (후기) */</span><br />
R(t) = <span style={{ color: 'var(--orange)' }}>K</span> · (<span style={{ color: 'var(--cyan)' }}>ΔρgV²</span> / <span style={{ color: 'var(--purple)' }}>νw</span>)<sup></sup> · t<sup>¾</sup>
<span className="text-text-3 text-[10px]">/* 중력-점성 체제 (후기) */</span><br />
R(t) = <span className="text-status-orange">K</span> · (<span className="text-primary-cyan">ΔρgV²</span> / <span className="text-primary-purple">νw</span>)<sup></sup> · t<sup>¾</sup>
</div>
</div>
<div className="flex flex-col gap-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[10px] text-text-2">
<div className="px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(249,115,22,.05)', border: '1px solid rgba(249,115,22,.15)' }}>
<span style={{ color: 'var(--orange)', fontWeight: 700 }}>Δρ</span> : - (kg/m³)
<span className="text-status-orange font-bold">Δρ</span> : - (kg/m³)
</div>
<div className="px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(6,182,212,.05)', border: '1px solid rgba(6,182,212,.15)' }}>
<span style={{ color: 'var(--cyan)', fontWeight: 700 }}>g</span> : 9.81 m/s²
<span className="text-primary-cyan font-bold">g</span> : 9.81 m/s²
</div>
<div className="px-2.5 py-1.5 rounded-md" style={{ background: 'rgba(59,130,246,.05)', border: '1px solid rgba(59,130,246,.15)' }}>
<span style={{ color: 'var(--blue)', fontWeight: 700 }}>V</span> : (m³)
@ -1256,8 +1256,8 @@ function WeatheringPanel() {
style={{ background: 'linear-gradient(135deg,rgba(249,115,22,.05),rgba(239,68,68,.04))', border: '1px solid rgba(249,115,22,.2)' }}>
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--orange),var(--red),var(--yellow))' }} />
<div style={labelStyle('var(--t1)')}>🔁 (Weathering) </div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
<b style={{ color: 'var(--orange)' }}>·· </b> . WING .
<div className="text-[11px] text-text-2 leading-[1.8]">
<b className="text-status-orange">·· </b> . WING .
</div>
</div>
@ -1271,7 +1271,7 @@ function WeatheringPanel() {
<div style={labelStyle(w.color)}>{w.title}</div>
<div className={`${bodyText} mb-2`}>{w.desc}</div>
<div className={codeBox}>{w.formula}</div>
<div className="mt-2 text-[10px]" style={{ color: 'var(--t3)' }}>{w.note}</div>
<div className="mt-2 text-[10px] text-text-3">{w.note}</div>
</div>
))}
</div>
@ -1309,14 +1309,14 @@ function OceanInputPanel() {
style={{ background: 'linear-gradient(135deg,rgba(34,197,94,.05),rgba(6,182,212,.04))', border: '1px solid rgba(34,197,94,.2)' }}>
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--green),var(--cyan))' }} />
<div style={labelStyle('var(--t1)')}>🌊 </div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
<b style={{ color: 'var(--cyan)' }}> · </b> . WING .
<div className="text-[11px] text-text-2 leading-[1.8]">
<b className="text-primary-cyan"> · </b> . WING .
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--green)', margin: 0 }}>
<div style={labelStyle('var(--green)')}>🌬 </div>
<div className="flex flex-col gap-1.5 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[11px] text-text-2">
{[
{ label: 'KMA RDAPS', desc: '동아시아 12km 해상도 · 24h 예보' },
{ label: 'ECMWF ERA5', desc: '전지구 0.25° 재분석 데이터' },
@ -1324,14 +1324,14 @@ function OceanInputPanel() {
].map(t =>
<div key={t.label} className="rounded-md" style={{ padding: '7px 10px', background: 'rgba(34,197,94,.04)', border: '1px solid rgba(34,197,94,.12)' }}>
<div className="font-semibold mb-0.5">{t.label}</div>
<div style={{ color: 'var(--t3)' }}>{t.desc}</div>
<div className="text-text-3">{t.desc}</div>
</div>
)}
</div>
</div>
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--cyan)', margin: 0 }}>
<div style={labelStyle('var(--cyan)')}>🌊 </div>
<div className="flex flex-col gap-1.5 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-1.5 text-[11px] text-text-2">
{[
{ label: 'NIFS ROMS', desc: '한국 근해 1km 해류·수온 예보' },
{ label: 'HYCOM', desc: '전지구 1/12° 해양 순환 모델' },
@ -1339,7 +1339,7 @@ function OceanInputPanel() {
].map(t =>
<div key={t.label} className="rounded-md" style={{ padding: '7px 10px', background: 'rgba(6,182,212,.04)', border: '1px solid rgba(6,182,212,.12)' }}>
<div className="font-semibold mb-0.5">{t.label}</div>
<div style={{ color: 'var(--t3)' }}>{t.desc}</div>
<div className="text-text-3">{t.desc}</div>
</div>
)}
</div>
@ -1358,8 +1358,8 @@ function VerificationPanel() {
style={{ background: 'linear-gradient(135deg,rgba(59,130,246,.05),rgba(34,197,94,.04))', border: '1px solid rgba(59,130,246,.2)' }}>
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--blue),var(--green))' }} />
<div style={labelStyle('var(--t1)')}> </div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
WING <b style={{ color: 'var(--blue)' }}> </b> .
<div className="text-[11px] text-text-2 leading-[1.8]">
WING <b className="text-primary-blue"> </b> .
</div>
</div>
@ -1375,7 +1375,7 @@ function VerificationPanel() {
{ value: '±8h', label: '해안 도달 시간 오차', color: 'var(--orange)' },
{ value: '3종', label: '비교 검증 모델 수', color: 'var(--purple)' },
].map(s => (
<div key={s.label} className="text-center p-2 rounded-md" style={{ background: 'var(--bg0)' }}>
<div key={s.label} className="text-center p-2 rounded-md bg-bg-0">
<div className="font-bold" style={{ fontSize: '14px', color: s.color, fontFamily: 'var(--fM)' }}>{s.value}</div>
<div className="text-[10px] text-text-3">{s.label}</div>
</div>
@ -1388,8 +1388,8 @@ function VerificationPanel() {
<div style={labelStyle('var(--t1)')}>2014 </div>
<span className="text-[10px] px-2 py-0.5 rounded" style={{ background: 'rgba(6,182,212,.12)', color: 'var(--cyan)', fontWeight: 600 }}></span>
</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.6' }}>
KOSPS , SAR <b style={{ color: 'var(--cyan)' }}> 82.1%</b> . .
<div className="text-[11px] text-text-2 leading-[1.6]">
KOSPS , SAR <b className="text-primary-cyan"> 82.1%</b> . .
</div>
</div>
@ -1399,7 +1399,7 @@ function VerificationPanel() {
<span style={{ ...tag('var(--blue)'), fontWeight: 700, fontSize: '12px' }}>📄 </span>
<span className="text-[11px] ml-1" style={{ color: 'var(--t3)', transition: 'transform .2s', display: 'inline-block', transform: papersOpen ? 'rotate(180deg)' : 'rotate(0)' }}></span>
</div>
{papersOpen && <div className="flex flex-col gap-1.5 text-[10px]" style={{ color: 'var(--t2)' }}>
{papersOpen && <div className="flex flex-col gap-1.5 text-[10px] text-text-2">
{[
{ num: '①', title: '허베이스피리트호 유출유 확산예측 검증 분석', authors: '이문진 · 김선동 · 김혜진 · 오세웅', journal: '한국해양과학기술협의회 공동학술대회', detail: 'pp.3154 | 2010', desc: 'Radarsat 인공위성영상 비교 분석 · NOAA GNOME과 동일 입력조건 하 비교 검증', color: 'var(--red)', system: 'KOSPS' },
{ num: '②', title: '3차원 유출유 확산예측 시스템 연구', authors: '이문진 · 김혜진 · 강관근', journal: '한국해양과학기술협의회 공동학술대회', detail: 'pp.17-18 | 2013', desc: 'Monte Carlo Simulation 기반 3D 확산모델 · 허베이 스피리트호 720시간 적용 검증', color: 'var(--purple)', system: 'KOSPS' },
@ -1419,8 +1419,8 @@ function VerificationPanel() {
<div className="font-bold">{paper.title}</div>
<span style={{ ...tag(paper.color), fontSize: '9px', padding: '1px 5px' }}>{paper.system}</span>
</div>
<div style={{ color: 'var(--t3)', lineHeight: '1.6' }}>{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1" style={{ color: 'var(--t2)' }}>{paper.desc}</div>
<div className="text-text-3 leading-[1.6]">{paper.authors} | <b style={{ color: paper.color }}>{paper.journal}</b> {paper.detail}</div>
<div className="mt-1 text-text-2">{paper.desc}</div>
</div>
</div>
))}
@ -1438,8 +1438,8 @@ function EnsemblePanel() {
style={{ background: 'linear-gradient(135deg,rgba(168,85,247,.05),rgba(6,182,212,.04))', border: '1px solid rgba(168,85,247,.2)' }}>
<div className="absolute top-0 left-0 right-0 h-[3px]" style={{ background: 'linear-gradient(90deg,var(--purple),var(--cyan))' }} />
<div style={labelStyle('var(--t1)')}> (Ensemble Prediction)</div>
<div className="text-[11px]" style={{ color: 'var(--t2)', lineHeight: '1.8' }}>
WING 3 (KOSPS·POSEIDON·OpenDrift) <b style={{ color: 'var(--purple)' }}> </b> . .
<div className="text-[11px] text-text-2 leading-[1.8]">
WING 3 (KOSPS·POSEIDON·OpenDrift) <b className="text-primary-purple"> </b> . .
</div>
</div>
<div className="grid grid-cols-2 gap-3">
@ -1452,7 +1452,7 @@ function EnsemblePanel() {
</div>
<div className={`${card} ${cardBg}`} style={{ borderLeft: '3px solid var(--orange)', margin: 0 }}>
<div style={labelStyle('var(--orange)')}>🎯 (Worst Case)</div>
<div className={bodyText}> 3 <b style={{ color: 'var(--orange)' }}> </b> . .</div>
<div className={bodyText}> 3 <b className="text-status-orange"> </b> . .</div>
</div>
</div>
</div>
@ -1466,7 +1466,7 @@ function RoadmapPanel() {
<div className="grid grid-cols-2 gap-3 mb-4">
<div className={`${card} ${cardBg}`} style={{ borderTop: '3px solid var(--red)', margin: 0 }}>
<div style={labelStyle('var(--red)')}> </div>
<div className="flex flex-col gap-2 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-2 text-[11px] text-text-2">
<div className="rounded-md" style={{ padding: '8px 10px', background: 'rgba(239,68,68,.04)', border: '1px solid rgba(239,68,68,.12)', color: 'var(--t2)' }}>2D <b>3D </b></div>
<div className="rounded-md" style={{ padding: '8px 10px', background: 'rgba(239,68,68,.04)', border: '1px solid rgba(239,68,68,.12)', color: 'var(--t2)' }}>· <b> </b></div>
<div className="rounded-md" style={{ padding: '8px 10px', background: 'rgba(239,68,68,.04)', border: '1px solid rgba(239,68,68,.12)', color: 'var(--t2)' }}> <b>· </b></div>
@ -1474,7 +1474,7 @@ function RoadmapPanel() {
</div>
<div className={`${card} ${cardBg}`} style={{ borderTop: '3px solid var(--green)', margin: 0 }}>
<div style={labelStyle('var(--green)')}>🚀 </div>
<div className="flex flex-col gap-2 text-[11px]" style={{ color: 'var(--t2)' }}>
<div className="flex flex-col gap-2 text-[11px] text-text-2">
{[
{ title: 'ROMS 3D 해양모델 결합', desc: '광역→상세역 Nesting 200m급 고해상도 구현' },
{ title: 'AI/ML 서로게이트 모델', desc: '수치모델 학습 기반 수초 내 근사 예측' },

파일 보기

@ -607,7 +607,7 @@ export function OilSpillView() {
{ label: '차단율', value: boomLines.length > 0 ? `${Math.min(95, 70 + Math.round(timelinePosition * 0.2))}%` : '—', color: 'var(--boom)' },
].map((s, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: '5px', fontSize: '11px' }}>
<span style={{ color: 'var(--t3)' }}>{s.label}</span>
<span className="text-text-3">{s.label}</span>
<span style={{ color: s.color, fontWeight: 600, fontFamily: 'var(--fM)' }}>{s.value}</span>
</div>
))}

파일 보기

@ -189,7 +189,7 @@ const PredictionInputSection = ({
fontSize: '10px',
fontFamily: 'var(--fM)'
}}>
<span style={{ color: 'var(--t2)' }}>📄 {uploadedFileName || 'example_plot_0.gif'}</span>
<span className="text-text-2">📄 {uploadedFileName || 'example_plot_0.gif'}</span>
<button
onClick={removeUploadedImage}
style={{

파일 보기

@ -211,7 +211,7 @@ function ReportGenerator({ onSave }: ReportGeneratorProps) {
{/* Preview Content */}
<div className="flex-1 overflow-y-auto px-6 py-5">
{/* Report Header */}
<div className="rounded-lg border border-border p-8 mb-6" style={{ background: 'var(--bg2)' }}>
<div className="rounded-lg border border-border p-8 mb-6 bg-bg-2">
<div className="text-center">
<p className="text-[10px] text-text-3 font-korean mb-2"> </p>
<h2 className="text-[20px] font-bold text-text-1 font-korean mb-2">{cat.reportName}</h2>
@ -221,7 +221,7 @@ function ReportGenerator({ onSave }: ReportGeneratorProps) {
{/* Dynamic Sections */}
{activeSections.map(sec => (
<div key={sec.id} className="rounded-lg border border-border mb-4 overflow-hidden" style={{ background: 'var(--bg2)' }}>
<div key={sec.id} className="rounded-lg border border-border mb-4 overflow-hidden bg-bg-2">
<div className="px-5 py-3 border-b border-border">
<h4 className="text-[13px] font-bold text-text-1 font-korean flex items-center gap-2">
{sec.icon} {sec.title}

파일 보기

@ -320,8 +320,8 @@ function ScatMap({ segments, selectedSeg, onSelectSeg, onOpenPopup }: ScatMapPro
<div className="h-full transition-all duration-500" style={{ width: `${notPct}%`, background: 'var(--bd)' }} />
</div>
<div className="flex justify-between mt-1">
<span className="text-[9px] font-mono" style={{ color: 'var(--green)' }}> {donePct}%</span>
<span className="text-[9px] font-mono" style={{ color: 'var(--orange)' }}> {progPct}%</span>
<span className="text-[9px] font-mono text-status-green"> {donePct}%</span>
<span className="text-[9px] font-mono text-status-orange"> {progPct}%</span>
<span className="text-[9px] font-mono text-text-3"> {notPct}%</span>
</div>
<div className="mt-2.5">

파일 보기

@ -125,11 +125,11 @@ function ScatTimeline({
<div className="flex gap-3.5">
<span className="flex items-center gap-1.5 text-[11px]">
<span className="text-text-2 font-korean"></span>
<span className="text-text-1 font-semibold font-mono" style={{ color: 'var(--green)' }}>{doneCount}/{segments.length}</span>
<span className="text-text-1 font-semibold font-mono text-status-green">{doneCount}/{segments.length}</span>
</span>
<span className="flex items-center gap-1.5 text-[11px]">
<span className="text-text-2 font-korean"></span>
<span className="text-text-1 font-semibold font-mono" style={{ color: 'var(--orange)' }}>{progCount}/{segments.length}</span>
<span className="text-text-1 font-semibold font-mono text-status-orange">{progCount}/{segments.length}</span>
</span>
<span className="flex items-center gap-1.5 text-[11px]">
<span className="text-text-2 font-korean"> </span>