/* --- src/shell.jsx --- */
// Shell: TopBar, Sidebar, common UI atoms
const { useState, useMemo, useEffect, useRef } = React;

const NAV_ICONS = {
  home:'home', dashboard:'grid', upper:'pulse', compare:'compare',
  lower:'layers', forms:'doc', report:'megaphone', analysis:'brain',
  insight:'chart', agencies:'building'
};

function TopBar({ current, setCurrent }){
  const [mode, setMode] = useState('전체');
  const [searchOpen, setSearchOpen] = useState(false);
  const [notifOpen, setNotifOpen] = useState(false);
  const [profileOpen, setProfileOpen] = useState(false);
  const [loggedIn, setLoggedIn] = useState(()=>{
    try { return sessionStorage.getItem('synclaw-login') !== 'false'; } catch(e) { return true; }
  });
  useEffect(()=>{
    try { sessionStorage.setItem('synclaw-login', loggedIn ? 'true' : 'false'); } catch(e) {}
  }, [loggedIn]);

  const user = loggedIn
    ? { name:'홍길동 사무관', org:'법제처 · 규제정비과', role:'정비 검토자', mark:'법제처' }
    : { name:'로그인', org:'계정이 필요합니다', role:'방문자', mark:'LOGIN' };

  const menuItemStyle = {
    width:'100%', display:'flex', alignItems:'flex-start', gap:10,
    padding:'10px 12px', border:'none', background:'transparent', color:'var(--ink)',
    borderRadius:8, fontSize:13, fontWeight:600, cursor:'pointer', textAlign:'left'
  };
  const menuSubStyle = {fontSize:11, color:'var(--ink-3)', fontWeight:500, marginTop:1};
  const iconBox = (txt, bg='#EEF2F7', fg='var(--navy)') => (
    <span style={{width:24, height:24, borderRadius:7, background:bg, color:fg, display:'inline-flex', alignItems:'center', justifyContent:'center', fontSize:13, flexShrink:0}}>{txt}</span>
  );

  const openLoginModal = () => {
    setProfileOpen(false);
    window.openModal && window.openModal({
      eyebrow:'Account Login',
      title:'Sync·Law 업무계정 로그인',
      headerBg:'#E6EEFB', headerFg:'#0B2E5C',
      body:(
        <div style={{display:'grid', gap:14}}>
          <div style={{padding:'14px 16px', background:'#F8FAFC', border:'1px solid var(--line)', borderRadius:10, color:'var(--ink-2)', lineHeight:1.7}}>
            시연용 화면에서는 아래 기본 계정으로 바로 로그인됩니다. 실제 서비스에서는 기관 SSO·공무원 업무망 인증·권한그룹을 연동하는 구조입니다.
          </div>
          <label style={{display:'grid', gap:6, fontSize:12, fontWeight:700, color:'var(--ink-2)'}}>
            기관 이메일
            <input defaultValue="hong@law.go.kr" style={{padding:'10px 12px', border:'1px solid var(--line-2)', borderRadius:8, fontSize:13}} />
          </label>
          <label style={{display:'grid', gap:6, fontSize:12, fontWeight:700, color:'var(--ink-2)'}}>
            비밀번호
            <input type="password" defaultValue="synclaw-demo" style={{padding:'10px 12px', border:'1px solid var(--line-2)', borderRadius:8, fontSize:13}} />
          </label>
          <div style={{display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:8}}>
            <div style={{padding:'10px 12px', background:'#F8FAFC', borderRadius:8}}><b style={{fontSize:12}}>권한</b><div style={{fontSize:11, color:'var(--ink-3)', marginTop:4}}>정비 검토자</div></div>
            <div style={{padding:'10px 12px', background:'#F8FAFC', borderRadius:8}}><b style={{fontSize:12}}>소속</b><div style={{fontSize:11, color:'var(--ink-3)', marginTop:4}}>법제처</div></div>
            <div style={{padding:'10px 12px', background:'#F8FAFC', borderRadius:8}}><b style={{fontSize:12}}>보안</b><div style={{fontSize:11, color:'var(--ink-3)', marginTop:4}}>2단계 인증</div></div>
          </div>
        </div>
      ),
      actions:[
        {label:'취소'},
        {label:'로그인', primary:true, onClick:()=>{ setLoggedIn(true); window.toast && window.toast('홍길동 사무관으로 로그인되었습니다', {tone:'success', sub:'마이페이지와 검토자 기능을 사용할 수 있습니다'}); }}
      ]
    });
  };

  const openMyPageModal = () => {
    setProfileOpen(false);
    if(!loggedIn){ openLoginModal(); return; }
    window.openModal && window.openModal({
      eyebrow:'My Page',
      title:'홍길동 사무관 마이페이지',
      headerBg:'#E6EEFB', headerFg:'#0B2E5C',
      body:(
        <div style={{display:'grid', gap:14}}>
          <div style={{display:'flex', gap:14, alignItems:'center', padding:'14px 16px', background:'#F8FAFC', border:'1px solid var(--line)', borderRadius:10}}>
            <div style={{width:46, height:46, borderRadius:'50%', background:'linear-gradient(135deg, #4A78C4, #2E5FB0)', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', fontSize:12, fontWeight:700}}>법제처</div>
            <div>
              <div style={{fontSize:16, fontWeight:700, color:'var(--ink)'}}>홍길동 사무관</div>
              <div style={{fontSize:12, color:'var(--ink-3)', marginTop:2}}>법제처 · 규제정비과 · 권한: 정비 검토자</div>
            </div>
          </div>
          <div style={{display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:10}}>
            <div style={{padding:'13px 14px', border:'1px solid var(--line)', borderRadius:10}}><div style={{fontSize:11, color:'var(--ink-3)'}}>내 검토 대기</div><div className="mono" style={{fontSize:22, fontWeight:700, color:'var(--navy)', marginTop:4}}>12</div></div>
            <div style={{padding:'13px 14px', border:'1px solid var(--line)', borderRadius:10}}><div style={{fontSize:11, color:'var(--ink-3)'}}>관심 법령</div><div className="mono" style={{fontSize:22, fontWeight:700, color:'var(--navy)', marginTop:4}}>8</div></div>
            <div style={{padding:'13px 14px', border:'1px solid var(--line)', borderRadius:10}}><div style={{fontSize:11, color:'var(--ink-3)'}}>알림 규칙</div><div className="mono" style={{fontSize:22, fontWeight:700, color:'var(--navy)', marginTop:4}}>5</div></div>
          </div>
          <div style={{display:'grid', gap:8}}>
            {[
              ['최근 열람', '대기환경보전법 제16조 · 하위규정 대조 화면'],
              ['내 즐겨찾기', '개인정보 보호법 · 건축법 · 식품위생법'],
              ['결재/검토', 'A부처 건축법 시행령 정비 검토 요청 1건'],
              ['알림 설정', '영향 큼 · 중앙부처 · 민원서식 변동 알림 수신']
            ].map((r,i)=>(
              <div key={i} style={{display:'grid', gridTemplateColumns:'90px 1fr', gap:10, padding:'10px 12px', background:'#FBFCFE', border:'1px solid var(--line)', borderRadius:8}}>
                <b style={{fontSize:12, color:'var(--ink)'}}>{r[0]}</b>
                <span style={{fontSize:12, color:'var(--ink-2)'}}>{r[1]}</span>
              </div>
            ))}
          </div>
        </div>
      ),
      actions:[
        {label:'닫기'},
        {label:'내 검토 대시보드로 이동', primary:true, onClick:()=>setCurrent('dashboard')}
      ]
    });
  };

  const handleLogout = () => {
    setProfileOpen(false);
    setLoggedIn(false);
    window.toast && window.toast('로그아웃되었습니다', {tone:'info', sub:'개인화 메뉴가 숨겨졌습니다'});
  };

  return (
    <div id="rs-topbar" data-screen-label="topbar" style={{
      height:64, background:'linear-gradient(180deg, #0B2E5C 0%, #0E3568 100%)',
      color:'#fff', display:'flex', alignItems:'center',
      padding:'0 28px', borderBottom:'1px solid #08234A',
      position:'sticky', top:0, zIndex:50,
    }}>
      <div data-action="open-home" data-brand="sync-law" style={{display:'flex', alignItems:'center', gap:12, cursor:'pointer'}} onClick={()=>setCurrent('home')}>
        <Logo />
        <div>
          <div style={{fontSize:16, fontWeight:700, letterSpacing:'-0.02em', fontFamily:'"Inter", "Pretendard", sans-serif'}}>
            Sync<span style={{color:'#5EE6B5', marginLeft:1}}>·</span>Law
          </div>
          <div style={{fontSize:10.5, opacity:.65, marginTop:-1, letterSpacing:'0.02em'}}>범정부 규제 동기화 플랫폼</div>
        </div>
        <span style={{
          marginLeft:14, padding:'3px 9px', borderRadius:4, fontSize:10, fontWeight:700,
          letterSpacing:'0.06em', background:'rgba(242,181,68,0.18)', color:'#FBEFD9',
          border:'1px solid rgba(242,181,68,0.4)'
        }}>DEMO · 시연용</span>
      </div>

      <div style={{flex:1}} />

      <div data-action="switch-mode" style={{display:'flex', alignItems:'center', gap:6, marginRight:20}}>
        {['전체','중앙','지방','전문가'].map((t)=>{
          const active = mode === t;
          return (
            <button key={t} data-mode={t} onClick={()=>{ setMode(t); window.toast && window.toast(`${t} 모드로 전환되었습니다`, {tone:'info'}); }} style={{
              background: active ? 'rgba(94,230,181,0.18)' : 'transparent',
              color:'#fff', border:'1px solid '+(active ? 'rgba(94,230,181,0.36)' : 'rgba(255,255,255,0.12)'),
              padding:'6px 12px', borderRadius:6, fontSize:12, opacity: active?1:.8,
              fontWeight: active?700:500, cursor:'pointer'
            }}>{t} 모드</button>
          );
        })}
      </div>

      <div style={{
        display:'flex', alignItems:'center', gap:8, padding:'6px 12px',
        background:'rgba(255,255,255,0.08)', borderRadius:6, fontSize:12, marginRight:14
      }}>
        <span style={{
          width:6, height:6, borderRadius:'50%', background:'#5EE6B5',
          boxShadow:'0 0 0 3px rgba(94,230,181,0.18)'
        }}/>
        <span>AI 모니터링 정상</span>
      </div>

      <div style={{display:'flex', alignItems:'center', gap:14}}>
        <button data-action="open-search" onClick={()=>setSearchOpen(true)} style={iconBtn} title="검색 (⌘K)"><Icon name="search" size={18}/></button>
        <button data-action="open-notifications" onClick={()=>setNotifOpen(o=>!o)} style={iconBtn} title="알림">
          <Icon name="bell" size={18}/>
          <span style={{
            position:'absolute', top:4, right:4, width:7, height:7, borderRadius:'50%',
            background:'#F2B544', border:'1.5px solid #0B2E5C'
          }}/>
        </button>
        <div style={{height:24, width:1, background:'rgba(255,255,255,0.18)'}}/>
        <div style={{position:'relative'}}>
          <button data-action="open-profile-menu" onClick={()=>setProfileOpen(o=>!o)} style={{display:'flex', alignItems:'center', gap:10, background:profileOpen?'rgba(255,255,255,0.10)':'transparent', border:'1px solid '+(profileOpen?'rgba(255,255,255,0.18)':'transparent'), color:'#fff', cursor:'pointer', padding:'4px 8px 4px 6px', borderRadius:8}}>
            <div style={{
              width:30, height:30, borderRadius:'50%',
              background: loggedIn ? 'linear-gradient(135deg, #4A78C4, #2E5FB0)' : 'rgba(255,255,255,0.14)',
              border: loggedIn ? 'none' : '1px solid rgba(255,255,255,0.22)',
              display:'flex', alignItems:'center', justifyContent:'center',
              fontSize: loggedIn ? 11 : 10, fontWeight:700
            }}>{user.mark}</div>
            <div style={{lineHeight:1.2, textAlign:'left'}}>
              <div style={{fontSize:13, fontWeight:600}}>{user.name}</div>
              <div style={{fontSize:11, opacity:.65}}>{user.org}</div>
            </div>
            <span style={{fontSize:11, opacity:.65, transform:profileOpen?'rotate(180deg)':'none', transition:'transform .15s'}}>▾</span>
          </button>
          {profileOpen && (
            <div style={{position:'absolute', right:0, top:44, width:286, background:'#fff', color:'var(--ink)', border:'1px solid var(--line)', borderRadius:12, boxShadow:'0 18px 48px rgba(15,23,42,0.22)', padding:8, zIndex:200}}>
              <div style={{display:'flex', gap:10, alignItems:'center', padding:'10px 10px 12px', borderBottom:'1px solid var(--line)', marginBottom:6}}>
                <div style={{width:38, height:38, borderRadius:'50%', background:loggedIn?'linear-gradient(135deg, #4A78C4, #2E5FB0)':'#EEF2F7', color:loggedIn?'#fff':'var(--navy)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:11, fontWeight:700}}>{user.mark}</div>
                <div>
                  <div style={{fontSize:14, fontWeight:700}}>{loggedIn ? '홍길동 사무관' : '로그인이 필요합니다'}</div>
                  <div style={{fontSize:11, color:'var(--ink-3)', marginTop:2}}>{loggedIn ? '법제처 · 규제정비과' : '업무계정으로 로그인하세요'}</div>
                </div>
              </div>
              {loggedIn ? (
                <>
                  <button style={menuItemStyle} onClick={openMyPageModal}>{iconBox('👤')}<span><b>마이페이지</b><div style={menuSubStyle}>내 검토함 · 관심 법령 · 최근 열람</div></span></button>
                  <button style={menuItemStyle} onClick={()=>{ setProfileOpen(false); setCurrent('upper'); window.toast && window.toast('관심 법령 목록을 불러왔습니다', {tone:'info'}); }}>{iconBox('★')}<span><b>관심 법령</b><div style={menuSubStyle}>즐겨찾기한 법령·조례 확인</div></span></button>
                  <button style={menuItemStyle} onClick={()=>{ setProfileOpen(false); window.toast && window.toast('계정 설정 화면 준비 중', {tone:'info', sub:'알림·권한·관심 법령 설정'}); }}>{iconBox('⚙')}<span><b>계정·알림 설정</b><div style={menuSubStyle}>기관별 알림, 권한, 표시 설정</div></span></button>
                  <div style={{height:1, background:'var(--line)', margin:'6px 4px'}}/>
                  <button style={{...menuItemStyle, color:'var(--rose)'}} onClick={handleLogout}>{iconBox('↗', '#F5E1E3', 'var(--rose)')}<span><b>로그아웃</b><div style={{...menuSubStyle, color:'var(--ink-4)'}}>개인화 메뉴 닫기</div></span></button>
                </>
              ) : (
                <>
                  <button style={menuItemStyle} onClick={openLoginModal}>{iconBox('↗')}<span><b>로그인</b><div style={menuSubStyle}>법제처 업무계정으로 접속</div></span></button>
                  <button style={menuItemStyle} onClick={()=>{ setLoggedIn(true); setProfileOpen(false); window.toast && window.toast('시연용 계정으로 로그인되었습니다', {tone:'success'}); }}>{iconBox('✓', '#DBEEEA', 'var(--teal)')}<span><b>시연 계정으로 계속</b><div style={menuSubStyle}>홍길동 사무관 권한 적용</div></span></button>
                </>
              )}
            </div>
          )}
        </div>
      </div>
      {window.SearchPalette && <SearchPalette open={searchOpen} onClose={()=>setSearchOpen(false)} go={setCurrent}/>}
      {window.NotificationsPanel && <NotificationsPanel open={notifOpen} onClose={()=>setNotifOpen(false)} go={setCurrent}/>}
    </div>
  );
}

function Logo(){
  return (
    <svg width="34" height="34" viewBox="0 0 40 40" fill="none">
      <rect x="2" y="2" width="36" height="36" rx="8" fill="#143A73" stroke="#2E5FB0" strokeWidth="1"/>
      <path d="M11 14L20 9l9 5v8c0 5-4 8-9 9-5-1-9-4-9-9v-8z" stroke="#7DA9E6" strokeWidth="1.6" fill="rgba(125,169,230,0.10)"/>
      <path d="M16 20l3 3 6-6" stroke="#5EE6B5" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

const iconBtn = {
  position:'relative', width:34, height:34, display:'flex', alignItems:'center',
  justifyContent:'center', borderRadius:6, background:'rgba(255,255,255,0.06)',
  border:'1px solid rgba(255,255,255,0.10)', color:'#fff'
};

function Sidebar({ current, setCurrent }){
  const groups = ['메인','법령 변경 추적','국민 참여','사례·통계 분석'];
  return (
    <aside style={{
      width:240, background:'#fff', borderRight:'1px solid var(--line)',
      padding:'20px 12px', position:'sticky', top:64, alignSelf:'flex-start',
      height:'calc(100vh - 64px)', overflowY:'auto'
    }}>
      {groups.map(g => (
        <div key={g} style={{marginBottom:18}}>
          <div style={{
            fontSize:10, fontWeight:600, color:'var(--ink-4)', letterSpacing:'0.08em',
            padding:'4px 10px 8px', textTransform:'uppercase'
          }}>{g}</div>
          {RSData.NAV.filter(n => n.group===g).map(n => {
            const active = current === n.id;
            const isAiMeasuredMenu = n.id === 'dashboard' || n.id === 'analysis';
            return (
              <button key={n.id} data-action={`open-${n.id}`} data-nav-id={n.id} onClick={()=>setCurrent(n.id)} style={{
                display:'flex', alignItems:'center', gap:10, width:'100%',
                padding:'9px 10px', borderRadius:7, marginBottom:2,
                background: active ? 'var(--blue-soft)' : 'transparent',
                color: active ? 'var(--navy)' : 'var(--ink-2)',
                border:'none', textAlign:'left',
                fontSize:13, fontWeight: active? 600 : 500,
                position:'relative'
              }}
              onMouseEnter={e=>{ if(!active) e.currentTarget.style.background='var(--steel-soft)'; }}
              onMouseLeave={e=>{ if(!active) e.currentTarget.style.background='transparent'; }}>
                {active && <span style={{position:'absolute', left:0, top:8, bottom:8, width:3, borderRadius:2, background:'var(--navy)'}}/>}
                <Icon name={NAV_ICONS[n.id]} size={16} color={active ? 'var(--navy)' : 'var(--ink-3)'}/>
                <span style={{flex:1, minWidth:0, display:'flex', alignItems:'center', gap:6}}>
                  <span style={{whiteSpace:'nowrap'}}>{n.label}</span>
                  {isAiMeasuredMenu && (
                    <span style={{
                      display:'inline-flex', alignItems:'center', justifyContent:'center',
                      padding:'2px 6px', borderRadius:5, border:'1px solid #D4A24A88',
                      background:'#FFF7E6', color:'#8B5410', fontSize:9.5, fontWeight:800,
                      lineHeight:1.2, whiteSpace:'nowrap'
                    }}>AI 활용 실측 사례</span>
                  )}
                </span>
              </button>
            );
          })}
        </div>
      ))}

      <div style={{
        marginTop:20, padding:14, background:'#F8FAFC', borderRadius:8,
        border:'1px solid var(--line)'
      }}>
        <div style={{fontSize:11, color:'var(--ink-3)', marginBottom:6}}>금주 모니터링</div>
        <div style={{fontSize:22, fontWeight:700, color:'var(--navy)', letterSpacing:'-0.02em'}} className="mono">12,847</div>
        <div style={{fontSize:11, color:'var(--ink-3)', marginTop:2}}>탐지 건수 (전주 대비 <span style={{color:'var(--teal)'}}>+312</span>)</div>
      </div>
    </aside>
  );
}

// ──────────────── Atoms ────────────────
function Card({ children, style, padding=20 }){
  return (
    <div style={{
      background:'var(--surface)', border:'1px solid var(--line)',
      borderRadius:'var(--radius-lg)', padding, boxShadow:'var(--shadow-sm)', ...style
    }}>{children}</div>
  );
}

function SectionHeader({ eyebrow, title, desc, right }){
  return (
    <div style={{display:'flex', alignItems:'flex-end', justifyContent:'space-between', marginBottom:14, gap:24}}>
      <div>
        {eyebrow && <div style={{fontSize:11, color:'var(--ink-3)', letterSpacing:'0.08em', textTransform:'uppercase', marginBottom:6, fontWeight:600}}>{eyebrow}</div>}
        <div style={{fontSize:18, fontWeight:700, color:'var(--ink)', letterSpacing:'-0.01em'}}>{title}</div>
        {desc && <div style={{fontSize:13, color:'var(--ink-3)', marginTop:4}}>{desc}</div>}
      </div>
      {right}
    </div>
  );
}

function Badge({ tone='steel', children, soft=true, size='md' }){
  const tones = {
    navy:   {bg:'#0B2E5C', fg:'#fff',          softBg:'#E6EEFB', softFg:'#0B2E5C'},
    blue:   {bg:'#2E5FB0', fg:'#fff',          softBg:'#E6EEFB', softFg:'#1E4D8C'},
    steel:  {bg:'#5B7C99', fg:'#fff',          softBg:'#EEF2F7', softFg:'#3F5A75'},
    amber:  {bg:'#C77A1B', fg:'#fff',          softBg:'#FBEFD9', softFg:'#8B5410'},
    teal:   {bg:'#1F7A6B', fg:'#fff',          softBg:'#DBEEEA', softFg:'#155F53'},
    rose:   {bg:'#A8434A', fg:'#fff',          softBg:'#F5E1E3', softFg:'#7C2F35'},
    ghost:  {bg:'#F1F5F9', fg:'#475569',       softBg:'#F1F5F9', softFg:'#475569'},
  };
  const t = tones[tone] || tones.steel;
  const pad = size==='sm' ? '2px 8px' : '4px 10px';
  const fs = size==='sm' ? 11 : 12;
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:6,
      background: soft? t.softBg : t.bg, color: soft ? t.softFg : t.fg,
      padding:pad, borderRadius:999, fontSize:fs, fontWeight:600, lineHeight:1.4,
      whiteSpace:'nowrap'
    }}>{children}</span>
  );
}

function Btn({ children, kind='primary', size='md', onClick, icon, style, ...rest }){
  const styles = {
    primary: { background:'var(--navy)', color:'#fff', border:'1px solid var(--navy)' },
    secondary: { background:'#fff', color:'var(--navy)', border:'1px solid var(--line-2)' },
    ghost: { background:'transparent', color:'var(--ink-2)', border:'1px solid transparent' },
    accent: { background:'var(--blue)', color:'#fff', border:'1px solid var(--blue)' },
  };
  const s = styles[kind] || styles.primary;
  const pad = size==='sm' ? '6px 12px' : size==='lg' ? '12px 20px' : '9px 16px';
  const fs  = size==='sm' ? 12 : size==='lg' ? 14 : 13;
  return (
    <button onClick={onClick} {...rest} style={{
      ...s, padding:pad, fontSize:fs, fontWeight:600, borderRadius:7,
      display:'inline-flex', alignItems:'center', gap:8, letterSpacing:'-0.005em',
      ...style
    }}>{icon && <Icon name={icon} size={fs+3}/>} {children}</button>
  );
}

function Chip({ active, children, onClick }){
  return (
    <button onClick={onClick} style={{
      padding:'6px 12px', borderRadius:6, fontSize:12, fontWeight: active? 600:500,
      background: active ? 'var(--navy)' : '#fff',
      color: active ? '#fff' : 'var(--ink-2)',
      border: '1px solid ' + (active? 'var(--navy)':'var(--line-2)'),
    }}>{children}</button>
  );
}

function Stat({ label, value, delta, tone='navy', icon }){
  const toneMap = {
    navy:  { strip:'#0B2E5C', tag:'navy' },
    amber: { strip:'#C77A1B', tag:'amber' },
    steel: { strip:'#5B7C99', tag:'steel' },
    teal:  { strip:'#1F7A6B', tag:'teal' },
  };
  const t = toneMap[tone];
  return (
    <div style={{
      background:'#fff', border:'1px solid var(--line)', borderRadius:'var(--radius-lg)',
      padding:'18px 18px 16px', position:'relative', overflow:'hidden'
    }}>
      <div style={{position:'absolute', left:0, top:0, bottom:0, width:3, background:t.strip}}/>
      <div style={{display:'flex', alignItems:'center', justifyContent:'space-between'}}>
        <div style={{fontSize:12, color:'var(--ink-3)', fontWeight:500}}>{label}</div>
        {icon && <Icon name={icon} size={14} color="var(--ink-4)"/>}
      </div>
      <div style={{display:'flex', alignItems:'baseline', gap:10, marginTop:8}}>
        <div className="mono" style={{fontSize:28, fontWeight:700, color:'var(--ink)', letterSpacing:'-0.02em'}}>{value.toLocaleString()}</div>
        <div style={{fontSize:11, color:'var(--ink-4)'}}>건</div>
      </div>
      <div style={{display:'flex', alignItems:'center', gap:6, marginTop:4}}>
        <Icon name="arrow-up" size={11} color="var(--teal)"/>
        <span className="mono" style={{fontSize:11, color:'var(--teal)', fontWeight:600}}>{delta}</span>
        <span style={{fontSize:11, color:'var(--ink-4)'}}>전주 대비</span>
      </div>
    </div>
  );
}

// Risk gauge dot row
function RiskBar({ value, tone }){
  const num = Number(value) || 0;
  const safe = Math.max(0, Math.min(100, num));
  const label = num.toFixed(1);
  const color = safe >= 90 ? '#C77A1B' : safe >= 75 ? '#D4A24A' : safe >= 60 ? '#5B7C99' : '#94A3B8';
  return (
    <div style={{display:'flex', alignItems:'center', gap:8}}>
      <div style={{flex:1, height:5, background:'#EEF2F7', borderRadius:99, overflow:'hidden'}}>
        <div style={{width:`${safe}%`, height:'100%', background:color, borderRadius:99}}/>
      </div>
      <span className="mono" style={{fontSize:11, fontWeight:600, color:'var(--ink-2)', minWidth:38, textAlign:'right'}}>{label}</span>
    </div>
  );
}

// Page wrapper
function Page({ children, eyebrow, title, desc, actions }){
  return (
    <div style={{padding:'28px 32px 60px', maxWidth:1440}}>
      <div style={{display:'flex', alignItems:'flex-end', justifyContent:'space-between', marginBottom:24, gap:24}}>
        <div>
          {eyebrow && <div style={{fontSize:11, color:'var(--blue)', letterSpacing:'0.1em', textTransform:'uppercase', marginBottom:8, fontWeight:700}}>{eyebrow}</div>}
          <h1 style={{fontSize:26, fontWeight:700, color:'var(--ink)', letterSpacing:'-0.02em', margin:0}}>{title}</h1>
          {desc && <div style={{fontSize:14, color:'var(--ink-3)', marginTop:6, maxWidth:760}}>{desc}</div>}
        </div>
        <div style={{display:'flex', gap:8}}>{actions}</div>
      </div>
      {children}
    </div>
  );
}

Object.assign(window, { TopBar, Sidebar, Card, SectionHeader, Badge, Btn, Chip, Stat, RiskBar, Page });
