/* dapp.jsx — 穿山甲 VPN desktop · window + views (i18n) */
const { useState, useEffect, useRef } = React;

function DToggle({ on, onChange }) {
  return <div onClick={onChange} style={{ width:42, height:25, borderRadius:999, position:'relative', cursor:'pointer', flexShrink:0, background: on?'var(--accent)':'var(--border-strong)', transition:'background 220ms var(--ease-out)' }}>
    <div style={{ position:'absolute', top:3, left:on?20:3, width:19, height:19, borderRadius:'50%', background:'#fff', boxShadow:'var(--shadow-sm)', transition:'left 220ms var(--ease-out)' }} /></div>;
}
function DLangSwitch({ lang, setLang }) {
  return <div style={{ display:'flex', background:'var(--bg-subtle)', borderRadius:999, padding:3, gap:2 }}>
    {[['zh','中文'],['en','EN']].map(([v,l])=>(
      <button key={v} onClick={()=>setLang(v)} style={{ border:'none', cursor:'pointer', borderRadius:999, padding:'4px 12px', fontFamily:'var(--font-sans)', fontSize:12, fontWeight:700, background: lang===v?'var(--accent)':'transparent', color: lang===v?'var(--fg-on-accent)':'var(--fg3)', transition:'all 140ms var(--ease-out)' }}>{l}</button>
    ))}</div>;
}
function NavItem({ icon, label, active, onClick }) {
  return (
    <button onClick={onClick} style={{ display:'flex', alignItems:'center', gap:11, width:'100%', textAlign:'left', border:'none', cursor:'pointer',
      background: active?'var(--accent-subtle)':'transparent', color: active?'var(--accent)':'var(--fg2)',
      padding:'9px 12px', borderRadius:'var(--radius-md)', fontFamily:'var(--font-sans)', fontSize:13.5, fontWeight: active?600:500, transition:'background-color 140ms var(--ease-out), color 140ms var(--ease-out)' }}>
      <DIcon name={icon} size={18} stroke={active?2.3:2} color={active?'var(--accent)':'var(--fg3)'} />{label}
    </button>
  );
}

function DConnect({ t, lang, status, onToggle, server, smart, free, mins, adDone, onAd, elapsed }) {
  const map = {
    off:{ fill:'var(--sand-100)', fg:'var(--clay-500)', icon:'power', cap:t('capOff'), sub:t('subOff'), ring:'track' },
    connecting:{ fill:'var(--accent)', fg:'#fff', icon:'loader-circle', cap:t('capConnecting'), sub:t('subConnecting'), ring:'spin' },
    on:{ fill:'var(--success)', fg:'#fff', icon:'shield-check', cap:t('capOn'), sub:t('subOn'), ring:'full' },
  }[status];
  const fmt = s => `${String(Math.floor(s/3600)).padStart(2,'0')}:${String(Math.floor(s%3600/60)).padStart(2,'0')}:${String(s%60).padStart(2,'0')}`;
  const shadow = status==='off' ? 'inset 0 0 0 1px var(--sand-200), var(--shadow-md)' : `0 0 0 8px ${status==='on'?'var(--success-subtle)':'var(--accent-subtle)'}, var(--shadow-lg)`;
  return (
    <div style={{ display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', height:'100%', gap:24, padding:'10px 40px' }}>
      <button onClick={onToggle} style={{ position:'relative', width:176, height:176, borderRadius:'50%', border:'none', cursor:'pointer', background:map.fill, color:map.fg,
        boxShadow:shadow, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:7, transition:'box-shadow 300ms var(--ease-out), background-color 300ms var(--ease-out)' }}>
        <svg viewBox="0 0 176 176" style={{ position:'absolute', inset:0, width:'100%', height:'100%', transformOrigin:'center', animation: map.ring==='spin'?'pg-spin 1.4s linear infinite':'none' }}>
          {map.ring==='track' && <circle cx="88" cy="88" r="81" fill="none" stroke="var(--sand-200)" strokeWidth="3" strokeDasharray="2 8" strokeLinecap="round"/>}
          {map.ring==='spin' && <><circle cx="88" cy="88" r="81" fill="none" stroke="rgba(255,255,255,.3)" strokeWidth="4"/><circle cx="88" cy="88" r="81" fill="none" stroke="#fff" strokeWidth="4" strokeLinecap="round" strokeDasharray="130 380"/></>}
          {map.ring==='full' && <circle cx="88" cy="88" r="81" fill="none" stroke="rgba(255,255,255,.85)" strokeWidth="4" strokeLinecap="round"/>}
        </svg>
        <DIcon name={map.icon} size={46} stroke={1.7} style={status==='connecting'?{animation:'pg-spin 1s linear infinite'}:{}} />
        {status==='off' && <span style={{ fontFamily:'var(--font-sans)', fontWeight:700, fontSize:13 }}>{t('connectNow')}</span>}
        {status==='connecting' && <span style={{ fontFamily:'var(--font-mono)', fontWeight:700, fontSize:13, letterSpacing:'0.08em' }}>···</span>}
        {status==='on' && <span style={{ fontFamily:'var(--font-mono)', fontWeight:600, fontSize:15 }}>{fmt(elapsed)}</span>}
      </button>
      <div style={{ textAlign:'center' }}>
        <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:22, color:'var(--fg1)' }}>{map.cap}</div>
        <div style={{ fontSize:13, color:'var(--fg3)', marginTop:4 }}>{map.sub}</div>
        <div style={{ display:'inline-flex', alignItems:'center', gap:7, marginTop:10, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-full)', padding:'6px 14px', fontSize:12.5, fontWeight:600, color:'var(--fg2)' }}>
          {smart && <DIcon name="zap" size={13} stroke={2.4} color="var(--accent)" />}
          <span style={{ whiteSpace:'nowrap' }}>{smart ? `${t('smartSelect')} · ` : ''}{dName(server,lang)} · {server.ping}ms</span>
        </div>
      </div>
      {free && (
        <div style={{ width:340, background:'var(--surface)', borderRadius:'var(--radius-lg)', padding:'12px 14px', boxShadow:'var(--shadow-sm)', border:'1px solid var(--border)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:7, marginBottom:8 }}>
            <DIcon name="clock" size={14} stroke={2.2} color="var(--accent)" />
            <span style={{ fontSize:12, fontWeight:600, color:'var(--fg2)' }}>{t('quotaToday')}</span>
            <span style={{ fontFamily:'var(--font-mono)', fontSize:13.5, fontWeight:600, color:'var(--fg1)', whiteSpace:'nowrap' }}>{mins} {t('minutes')}</span>
            <span style={{ marginLeft:'auto', fontSize:10.5, fontWeight:600, color:'var(--fg3)', background:'var(--bg-subtle)', padding:'3px 9px', borderRadius:'var(--radius-full)', whiteSpace:'nowrap' }}>{t('quotaFree')}</span>
          </div>
          <div style={{ height:6, background:'var(--bg-subtle)', borderRadius:3, overflow:'hidden', marginBottom:10 }}>
            <div style={{ width:`${Math.min(100, mins/10*100)}%`, height:'100%', background:mins<=3?'var(--warning)':'var(--accent)', borderRadius:3 }}></div>
          </div>
          {adDone ? (
            <div style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:7, color:'var(--success)', fontWeight:700, fontSize:13, padding:'8px' }}>
              <DIcon name="check-circle" size={15} stroke={2.2} color="var(--success)" />{t('adUnlocked')}
            </div>
          ) : (
            <button onClick={onAd} style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:7, width:'100%', border:'1.5px solid var(--accent-border)', background:'var(--accent-subtle)', color:'var(--accent)', fontFamily:'var(--font-sans)', fontWeight:700, fontSize:13, padding:'8px', borderRadius:'var(--radius-full)', cursor:'pointer' }}>
              <DIcon name="play-circle" size={15} stroke={2.2} />{t('watchAd')}
            </button>
          )}
        </div>
      )}
      {status==='on' &&
        <div style={{ display:'flex', gap:10 }}>
          {[['arrow-down','86.4','Mb/s'],['arrow-up','12.1','Mb/s'],['zap',String(server.ping),'ms']].map(([ic,v,u])=>(
            <div key={ic} style={{ display:'flex', alignItems:'center', gap:7, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-md)', padding:'8px 14px', boxShadow:'var(--shadow-sm)' }}>
              <DIcon name={ic} size={15} stroke={2.2} color="var(--accent)" /><span style={{ fontFamily:'var(--font-mono)', fontSize:14, color:'var(--fg1)' }}>{v}<span style={{ fontSize:10, color:'var(--fg3)' }}> {u}</span></span>
            </div>
          ))}
        </div>}
    </div>
  );
}

function DServers({ t, lang, current, onPick }) {
  const [q,setQ]=useState('');
  const list = DSERVERS.filter(s=>(s.name+s.en).toLowerCase().includes(q.toLowerCase()));
  const smartActive = current==='AUTO';
  return (
    <div style={{ padding:'4px 28px 24px' }}>
      <div style={{ display:'flex', alignItems:'center', gap:9, background:'var(--bg-subtle)', borderRadius:'var(--radius-md)', padding:'9px 13px', marginBottom:16, maxWidth:340 }}>
        <DIcon name="search" size={17} color="var(--fg3)" /><input value={q} onChange={e=>setQ(e.target.value)} placeholder={t('search')} style={{ border:'none', background:'transparent', outline:'none', flex:1, fontFamily:'var(--font-sans)', fontSize:13.5, color:'var(--fg1)' }} />
      </div>
      {/* smart select — recommended card */}
      <button onClick={()=>onPick('AUTO')} style={{ display:'flex', alignItems:'center', gap:12, width:'100%', textAlign:'left', cursor:'pointer',
        background:'var(--accent-subtle)', border:`1.5px solid ${smartActive?'var(--accent)':'var(--accent-border)'}`,
        borderRadius:'var(--radius-xl)', padding:'14px', boxShadow:smartActive?'var(--shadow-md)':'var(--shadow-sm)', marginBottom:10 }}>
        <div style={{ width:38, height:38, borderRadius:'var(--radius-md)', background:'linear-gradient(150deg,var(--clay-500),var(--clay-700))', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}><DIcon name="zap" size={18} stroke={2.2} color="#fff" /></div>
        <div style={{ flex:1 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <span style={{ fontFamily:'var(--font-sans)', fontSize:14.5, fontWeight:700, color:'var(--fg1)' }}>{t('smartSelect')}</span>
            <span style={{ fontSize:10, fontWeight:700, color:'#fff', background:'var(--accent)', padding:'2px 8px', borderRadius:999, letterSpacing:'0.04em' }}>{t('recommended')}</span>
          </div>
          <div style={{ fontSize:11.5, color:'var(--fg2)', marginTop:3 }}>{t('smartSub')}</div>
        </div>
        {smartActive && <DIcon name="check" size={18} color="var(--accent)" stroke={2.6} />}
      </button>
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
        {list.map(s=>{
          const active = s.code===current;
          return (
            <button key={s.code} onClick={()=>onPick(s.code)} style={{ display:'flex', alignItems:'center', gap:12, textAlign:'left', cursor:'pointer',
              background: active?'var(--accent-subtle)':'var(--surface)', border:`1.5px solid ${active?'var(--accent-border)':'var(--border)'}`,
              borderRadius:'var(--radius-lg)', padding:'12px 14px', boxShadow:'var(--shadow-sm)' }}>
              <DCC code={s.code} active={active} />
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontFamily:'var(--font-sans)', fontSize:14, fontWeight:600, color:'var(--fg1)' }}>{dName(s,lang)}</div>
                <div style={{ fontSize:11.5, color:'var(--fg3)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{dSub(s,lang)}</div>
              </div>
              <div style={{ display:'flex', flexDirection:'column', alignItems:'flex-end', gap:5 }}>
                <span style={{ fontFamily:'var(--font-mono)', fontSize:11.5, color:'var(--fg2)' }}>{s.ping}ms</span>
                <DSignal ping={s.ping} />
              </div>
              {active && <DIcon name="check" size={17} color="var(--accent)" />}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function DStats({ t, lang }) {
  const vals=[2.1,3.4,1.8,4.6,5.2,6.1,3.0]; const labels=t('days'); const max=6.1;
  return (
    <div style={{ padding:'8px 32px 24px' }}>
      <div style={{ display:'flex', gap:14, marginBottom:22 }}>
        {[[t('trafficMonth'),'42.6 GB'],[t('avgPing'),'29 ms'],[t('durMonth'),'86.4 h']].map(([l,v])=>(
          <div key={l} style={{ flex:1, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-lg)', padding:'16px 18px', boxShadow:'var(--shadow-sm)' }}>
            <div style={{ fontSize:12, color:'var(--fg3)', fontWeight:600 }}>{l}</div>
            <div style={{ fontFamily:'var(--font-mono)', fontSize:24, fontWeight:500, color:'var(--fg1)', marginTop:6 }}>{v}</div>
          </div>
        ))}
      </div>
      <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-lg)', padding:'18px 20px', boxShadow:'var(--shadow-sm)' }}>
        <div style={{ fontSize:13, fontWeight:600, color:'var(--fg1)', marginBottom:18 }}>{t('weekTraffic')}</div>
        <div style={{ display:'flex', alignItems:'flex-end', gap:18, height:120 }}>
          {vals.map((v,i)=>(
            <div key={i} style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', gap:8 }}>
              <div style={{ fontFamily:'var(--font-mono)', fontSize:10, color:'var(--fg3)' }}>{v}</div>
              <div style={{ width:'100%', maxWidth:34, height:`${v/max*86}px`, background:'var(--accent)', borderRadius:'6px 6px 0 0', opacity:0.85 }} />
              <div style={{ fontSize:11, color:'var(--fg3)' }}>{labels[i]}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function DSettings({ t, lang, setLang, dark, setDark, free, setFree, onReplayAuth, onReplayOnboarding, onRedeem }) {
  const [auto,setAuto]=useState(true); const [kill,setKill]=useState(true); const [boot,setBoot]=useState(true);
  const card={ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-lg)', boxShadow:'var(--shadow-sm)', overflow:'hidden', marginBottom:16 };
  const Row=({title,sub,right,last,onClick})=>(
    <div onClick={onClick} style={{ display:'flex', alignItems:'center', gap:12, padding:'14px 18px', borderBottom:last?'none':'1px solid var(--border)', cursor:onClick?'pointer':'default' }}>
      <div style={{ flex:1 }}><div style={{ fontSize:14, fontWeight:500, color:'var(--fg1)' }}>{title}</div>{sub&&<div style={{ fontSize:12, color:'var(--fg3)', marginTop:2 }}>{sub}</div>}</div>{right}
    </div>
  );
  return (
    <div style={{ padding:'8px 32px 24px', maxWidth:560 }}>
      <div style={card}>
        <Row title={t('redeemEntry')} sub={t('proMember')} right={<DIcon name="chevron-right" size={18} color="var(--fg3)" />} last onClick={onRedeem} />
      </div>
      <div style={card}>
        <Row title={t('autostart')} sub={t('autostartSub')} right={<DToggle on={boot} onChange={()=>setBoot(!boot)} />} />
        <Row title={t('smartRoute')} sub={t('smartRouteSub')} right={<DToggle on={auto} onChange={()=>setAuto(!auto)} />} />
        <Row title={t('killSwitch')} sub={t('killSwitchSub')} right={<DToggle on={kill} onChange={()=>setKill(!kill)} />} last />
      </div>
      <div style={card}>
        <Row title={t('language')} right={<DLangSwitch lang={lang} setLang={setLang} />} />
        <Row title={t('darkAppearance')} sub={dark?t('stateOn'):t('followLight')} right={<DToggle on={dark} onChange={()=>setDark(!dark)} />} />
        <Row title={t('protocol')} right={<span style={{ fontFamily:'var(--font-mono)', fontSize:13, color:'var(--fg3)' }}>WireGuard</span>} />
        <Row title={t('checkUpdate')} right={<DIcon name="chevron-right" size={18} color="var(--fg3)" />} />
        <Row title={t('version')} right={<span style={{ fontFamily:'var(--font-mono)', fontSize:13, color:'var(--fg3)' }}>v2.4.0 (macOS)</span>} last />
      </div>
      <div style={card}>
        <Row title={t('replayAuth')} sub={t('replayAuthSub')} right={<DIcon name="chevron-right" size={18} color="var(--fg3)" />} onClick={onReplayAuth} />
        <Row title={t('replayOnboarding')} sub={t('replayOnboardingSub')} right={<DIcon name="chevron-right" size={18} color="var(--fg3)" />} onClick={onReplayOnboarding} />
        <Row title={t('freeDemo')} sub={t('freeDemoSub')} right={<DToggle on={free} onChange={()=>setFree(!free)} />} last />
      </div>
    </div>
  );
}

function DesktopApp() {
  const [stage,setStage]=useState('app');   // app | auth | onboarding — UI kit opens on the main app
  const [view,setView]=useState('connect');
  const [status,setStatus]=useState('off');
  const [code,setCode]=useState('AUTO');   // 'AUTO' = 智能选择(默认)
  const [dark,setDark]=useState(false);
  const [lang,setLang]=useState('zh');
  const [free,setFree]=useState(true);     // 演示:免费版视角(与移动端一致)
  const [mins,setMins]=useState(6);
  const [adDone,setAdDone]=useState(false);
  const [elapsed,setElapsed]=useState(0);
  const timer=useRef(null);
  const t=dT(lang);
  const smart=code==='AUTO';
  const server=smart ? DSERVERS.reduce((a,b)=>a.ping<b.ping?a:b) : DSERVERS.find(s=>s.code===code);
  const titles={connect:t('connect'),servers:t('servers'),stats:t('stats'),account:t('navAccount'),plans:t('choosePlan'),redeem:t('redeemTitle'),contact:t('navContact'),settings:t('settings')};

  function toggle(){ if(status==='off'){ setStatus('connecting'); setTimeout(()=>{setStatus('on');setElapsed(0);},1500); } else setStatus('off'); }
  function pick(c){ setCode(c); setView('connect'); if(status==='on'){ setStatus('connecting'); setTimeout(()=>{setStatus('on');setElapsed(0);},1200); } }
  useEffect(()=>{ if(status==='on') timer.current=setInterval(()=>setElapsed(e=>e+1),1000); return ()=>clearInterval(timer.current); },[status]);

  if(stage==='auth') return (
    <div style={{ display:'flex', alignItems:'center', justifyContent:'center', minHeight:'100vh', padding:28, boxSizing:'border-box' }}>
      <DAuthFlow t={t} lang={lang} dark={dark} onDone={()=>setStage('onboarding')} />
    </div>
  );
  if(stage==='onboarding') return (
    <div style={{ display:'flex', alignItems:'center', justifyContent:'center', minHeight:'100vh', padding:28, boxSizing:'border-box' }}>
      <DOnboarding t={t} lang={lang} dark={dark} onDone={()=>setStage('app')} />
    </div>
  );

  let main;
  if(view==='connect') main=<DConnect t={t} lang={lang} status={status} onToggle={toggle} server={server} smart={smart} free={free} mins={mins} adDone={adDone} onAd={()=>setAdDone(true)} elapsed={elapsed} />;
  else if(view==='servers') main=<DServers t={t} lang={lang} current={code} onPick={pick} />;
  else if(view==='stats') main=<DStats t={t} lang={lang} />;
  else if(view==='account') main=<DAccountView t={t} lang={lang} free={free} onUpgrade={()=>setView('plans')} onSignOut={()=>setStage('auth')} />;
  else if(view==='plans') main=<DPlansView t={t} lang={lang} onChoose={()=>setView('redeem')} />;
  else if(view==='redeem') main=<DRedeemView t={t} lang={lang} />;
  else if(view==='contact') main=<DContactView t={t} lang={lang} />;
  else main=<DSettings t={t} lang={lang} setLang={setLang} dark={dark} setDark={setDark} free={free} setFree={setFree} onReplayAuth={()=>setStage('auth')} onReplayOnboarding={()=>setStage('onboarding')} onRedeem={()=>setView('redeem')} />;

  return (
    <div data-theme={dark?'dark':'light'} style={{ width:920, height:600, borderRadius:16, overflow:'hidden', display:'flex',
      background:'var(--bg)', boxShadow:'0 0 0 1px rgba(0,0,0,0.12), 0 28px 70px rgba(0,0,0,0.4)', fontFamily:'var(--font-sans)' }}>
      <div style={{ width:204, flexShrink:0, background:'var(--bg-subtle)', borderRight:'1px solid var(--border)', display:'flex', flexDirection:'column', padding:'14px 12px' }}>
        <div style={{ padding:'2px 4px 16px' }}><MacTrafficLights /></div>
        <div style={{ display:'flex', alignItems:'center', gap:9, padding:'0 6px 16px' }}>
          <DMark size={28} /><div><div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:16, color:'var(--fg1)', lineHeight:1 }}>{lang==='zh'?'穿山甲':'Pangolin'}</div><div style={{ fontSize:9, fontWeight:600, letterSpacing:'0.18em', color:'var(--accent)', marginTop:3 }}>PANGOLIN</div></div>
        </div>
        <div style={{ display:'flex', flexDirection:'column', gap:3 }}>
          <NavItem icon="power" label={t('navConnect')} active={view==='connect'} onClick={()=>setView('connect')} />
          <NavItem icon="globe" label={t('navServers')} active={view==='servers'} onClick={()=>setView('servers')} />
          <NavItem icon="chart-no-axes-column" label={t('navStats')} active={view==='stats'} onClick={()=>setView('stats')} />
          <NavItem icon="user" label={t('navAccount')} active={view==='account'||view==='plans'||view==='redeem'} onClick={()=>setView('account')} />
          <NavItem icon="message-circle" label={t('navContact')} active={view==='contact'} onClick={()=>setView('contact')} />
          <NavItem icon="settings" label={t('navSettings')} active={view==='settings'} onClick={()=>setView('settings')} />
        </div>
        <div style={{ flex:1 }} />
        <div style={{ display:'flex', alignItems:'center', gap:10, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--radius-md)', padding:'9px 11px' }}>
          <div style={{ width:30, height:30, borderRadius:'50%', background:'linear-gradient(150deg,var(--clay-500),var(--clay-700))', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}><DIcon name="crown" size={15} color="#fff" /></div>
          <div style={{ minWidth:0 }}><div style={{ fontSize:12, fontWeight:600, color:'var(--fg1)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{free?t('freePlanName'):t('proMember')}</div><div style={{ fontSize:10.5, color:'var(--fg3)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{free?t('quotaFree'):t('until')}</div></div>
        </div>
      </div>
      <div style={{ flex:1, display:'flex', flexDirection:'column', minWidth:0 }}>
        <div style={{ height:52, flexShrink:0, display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 24px', borderBottom:'1px solid var(--border)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            {(view==='redeem'||view==='plans') && <button onClick={()=>setView('account')} style={{ border:'none', background:'transparent', cursor:'pointer', padding:4, display:'flex' }}><DIcon name="arrow-left" size={20} color="var(--fg1)" /></button>}
            <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:17, color:'var(--fg1)' }}>{titles[view]}</div>
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:12 }}>
            <span style={{ fontFamily:'var(--font-mono)', fontSize:12, fontWeight:600, whiteSpace:'nowrap', color:status==='on'?'var(--success)':'var(--fg3)' }}>{status==='on'?'● '+t('connected')+' '+server.code:'○ '+t('notConnected')}</span>
            <button onClick={()=>setDark(!dark)} style={{ border:'none', background:'transparent', cursor:'pointer', padding:6, borderRadius:'var(--radius-sm)', display:'flex' }}><DIcon name={dark?'sun':'moon'} size={18} color="var(--fg2)" /></button>
          </div>
        </div>
        <div style={{ flex:1, overflow:'auto', minHeight:0 }}>{main}</div>
      </div>
    </div>
  );
}
Object.assign(window, { DesktopApp });
