/* ============================================================ main.js — 오케스트레이터 (데이터 로드 · 탭 네비 · 지연 초기화) ============================================================ */ (function () { 'use strict'; // Chart.js 전역 폰트를 Pretendard로 (모든 차트 생성 전에 즉시 적용) if (window.Chart) { Chart.defaults.font.family = "'Pretendard Variable', Pretendard, system-ui, 'Malgun Gothic', sans-serif"; Chart.defaults.font.size = 13; Chart.defaults.color = '#4a463d'; } const inited = {}; function el(id) { return document.getElementById(id); } function setHeader() { const cat = Store.catalog || { proteins: [] }; el('stat-proteins').textContent = cat.n_proteins || cat.proteins.length; el('stat-structures').textContent = (cat.proteins || []).filter(p => p.structure && p.structure.accession).length; const gs = cat.grounding_stats; if (gs) el('stat-grounding').textContent = `${gs.in_model_grounded}/${gs.in_model_total} 트윈·${gs.catalog_grounded}/${gs.catalog_total} 전체`; el('last-updated').textContent = (cat.last_updated || '').replace('T', ' ').slice(0, 16) || '—'; const pa = (Store.extras && Store.extras.prior_art) || []; const fw = (Store.extras && Store.extras.frameworks) || []; el('prior-art-note').textContent = `선행연구 ${pa.length}건 · 권장 프레임워크 ${fw.length}종 · 에이전트 14기 마이닝`; } function initTab(name) { if (inited[name]) { if (name === 'graph') window.GraphTab.init(); if (name === 'atlas') window.AtlasTab.resize(); return; } inited[name] = true; try { if (name === 'twin') window.TwinTab.init(); else if (name === 'timeline') window.TimelineTab.init(); else if (name === 'network') window.NetworkTab.init(); else if (name === 'atlas') window.AtlasTab.init(); else if (name === 'graph') window.GraphTab.init(); else if (name === 'calibrate') window.CalibrateTab.init(); else if (name === 'validation') window.ValidationTab.init(); else if (name === 'stats') window.StatsTab.render(); else if (name === 'papers') window.LibraryTab.init(); } catch (e) { console.error('탭 초기화 오류', name, e); } } function bindTabs() { document.querySelectorAll('.tab-btn').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); btn.classList.add('active'); el('tab-' + btn.dataset.tab).classList.add('active'); initTab(btn.dataset.tab); }); }); } async function boot() { await Store.loadAll(); setHeader(); bindTabs(); initTab('twin'); // 기본 탭 } document.addEventListener('DOMContentLoaded', boot); })();