/* tabapp.jsx — 穿山甲 iPad 客户端 · 分栏布局
   复用 ../mobile/parts.jsx 的 Icon/Mark/CC/Signal/SERVERS/makeT/srvName/srvSub。
   仅 iPad 专属字串定义在本文件 TSTR。 */

const { useState, useEffect, useRef } = React;

/* iPad 专属字串(双语单显) */
const TSTR = {
  navConnect: { zh: '连接', en: 'Connect' },
  navNodes:   { zh: '节点', en: 'Nodes' },
  navStats:   { zh: '统计', en: 'Stats' },
  navAccount: { zh: '账户', en: 'Account' },
  capOff:     { zh: '未连接 · 轻点连接', en: 'Not connected · tap to start' },
  capConnecting:{ zh: '连接中 Connecting…', en: 'Connecting…' },
  capOn:      { zh: '已连接 · 网络已加密', en: 'Connected · traffic encrypted' },
  download:   { zh: '下载', en: 'Down' },
  upload:     { zh: '上传', en: 'Up' },
  latency:    { zh: '延迟', en: 'Ping' },
  curNode:    { zh: '当前节点', en: 'Current node' },
  searchPh:   { zh: '搜索国家 / 城市', en: 'Search country / city' },
  statTraffic:{ zh: '本月流量', en: 'Data this month' },
  statPing:   { zh: '平均延迟', en: 'Avg latency' },
  statTime:   { zh: '本月时长', en: 'Time this month' },
  weekTraffic:{ zh: '本周流量 (GB)', en: 'This week (GB)' },
  days:       { zh: ['周一','周二','周三','周四','周五','周六','周日'], en: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'] },
  acctEmail:  { zh: '邮箱', en: 'Email' },
  language:   { zh: '语言', en: 'Language' },
  darkMode:   { zh: '深色外观', en: 'Dark appearance' },
  smartRoute: { zh: '智能分流', en: 'Smart routing' },
  smartRouteSub:{ zh: '海外应用走加速,国内直连', en: 'Accelerate abroad, direct at home' },
  killSwitch: { zh: 'Kill Switch', en: 'Kill Switch' },
  killSub:    { zh: '断线时阻断网络,防止泄露', en: 'Block traffic if the link drops' },
  freeBanner: { zh: '免费版', en: 'Free plan' },
  trialNote:  { zh: '升级 PRO:不限时长 · 80+ 加速线路 · 5 台设备', en: 'Go PRO: unlimited time · 80+ routes · 5 devices' },
  version:    { zh: '穿山甲 · iPadOS · v2.4.0', en: 'Pangolin · iPadOS · v2.4.0' },
};
function makeTT(lang) { return (k) => (TSTR[k] && TSTR[k][lang]) !== undefined ? TSTR[k][lang] : k; }

function fmtHMS(s) { return `${String(Math.floor(s/3600)).padStart(2,'0')}:${String(Math.floor(s%3600/60)).padStart(2,'0')}:${String(s%60).padStart(2,'0')}`; }

/* ── 左侧栏 ── */
function TabRail({ tt, view, setView, free, t }) {
  const items = [['connect','power','navConnect'],['nodes','globe','navNodes'],['stats','chart','navStats'],['account','user','navAccount']];
  return (
    <div style={{ width: 232, flexShrink: 0, background: 'var(--bg-subtle)', borderRight: '1px solid var(--border)', display: 'flex', flexDirection: 'column', padding: '18px 14px 16px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '0 8px 20px' }}>
        <Mark size={30} />
        <div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 17, color: 'var(--fg1)', lineHeight: 1 }}>穿山甲</div>
          <div style={{ fontSize: 9, fontWeight: 600, letterSpacing: '0.2em', color: 'var(--accent)', marginTop: 3 }}>PANGOLIN</div>
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
        {items.map(([id, ic, lk]) => {
          const a = view === id;
          return (
            <button key={id} onClick={() => setView(id)} style={{
              display: 'flex', alignItems: 'center', gap: 12, width: '100%', textAlign: 'left', border: 'none', cursor: 'pointer',
              background: a ? 'var(--accent-subtle)' : 'transparent', color: a ? 'var(--accent)' : 'var(--fg2)',
              padding: '13px 14px', borderRadius: 'var(--radius-md)', fontFamily: 'var(--font-sans)', fontSize: 15, fontWeight: a ? 700 : 500,
              transition: 'background-color 140ms var(--ease-out), color 140ms var(--ease-out)', minHeight: 48,
            }}>
              <Icon name={ic} size={20} stroke={a ? 2.4 : 2} color={a ? 'var(--accent)' : 'var(--fg3)'} />{tt(lk)}
            </button>
          );
        })}
      </div>
      <div style={{ flex: 1 }}></div>
      <div style={{ background: free ? 'var(--surface)' : 'linear-gradient(150deg,var(--clay-600),var(--clay-800))', border: free ? '1px solid var(--border)' : 'none', borderRadius: 'var(--radius-lg)', padding: '12px 13px', color: free ? 'var(--fg1)' : '#fff' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
          <div style={{ width: 32, height: 32, borderRadius: '50%', background: free ? 'var(--bg-subtle)' : 'rgba(255,255,255,0.18)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <Icon name={free ? 'user' : 'crown'} size={16} color={free ? 'var(--fg2)' : '#fff'} />
          </div>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 12.5, fontWeight: 700, whiteSpace: 'nowrap' }}>{free ? tt('freeBanner') : t('proMember')}</div>
            <div style={{ fontSize: 10.5, opacity: 0.65, whiteSpace: 'nowrap' }}>me@pangolin.vpn</div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── 连接视图:左大按钮 + 右信息列 ── */
function TabConnect({ t, tt, lang, status, onToggle, server, smart, free, mins, adDone, onAd, elapsed, goNodes }) {
  const map = {
    off:        { ring: 'var(--border)', fill: 'var(--surface)', fg: 'var(--fg2)', icon: 'power', label: 'TAP', cap: tt('capOff') },
    connecting: { ring: 'var(--accent-subtle)', fill: 'var(--accent)', fg: '#fff', icon: 'loader-circle', label: '···', cap: tt('capConnecting') },
    on:         { ring: 'var(--success-subtle)', fill: 'var(--success)', fg: '#fff', icon: 'shield-check', label: 'SAFE', cap: tt('capOn') },
  }[status];
  const card = { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-sm)' };
  return (
    <div style={{ display: 'flex', height: '100%', alignItems: 'stretch' }}>
      <div style={{ flex: 1.25, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 26 }}>
        <button onClick={onToggle} style={{
          width: 216, height: 216, borderRadius: '50%', border: 'none', cursor: 'pointer',
          background: map.fill, color: map.fg, boxShadow: `0 0 0 11px ${map.ring}, var(--shadow-lg)`,
          display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 12,
          transition: 'box-shadow 300ms var(--ease-out), background-color 300ms var(--ease-out)',
        }}>
          <Icon name={map.icon} size={60} stroke={1.6} style={status === 'connecting' ? { animation: 'pg-spin 1s linear infinite' } : {}} />
          <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: 14, letterSpacing: '0.08em' }}>{map.label}</span>
        </button>
        <div style={{ textAlign: 'center' }}>
          <div style={{ fontFamily: 'var(--font-sans)', fontSize: 16, fontWeight: 600, color: 'var(--fg2)', whiteSpace: 'nowrap' }}>{map.cap}</div>
          {status === 'on' && <div style={{ fontFamily: 'var(--font-mono)', fontSize: 28, fontWeight: 500, color: 'var(--fg1)', marginTop: 8, letterSpacing: '-0.01em' }}>{fmtHMS(elapsed)}</div>}
        </div>
      </div>

      <div style={{ width: 332, flexShrink: 0, display: 'flex', flexDirection: 'column', gap: 14, justifyContent: 'center', paddingRight: 28 }}>
        {free && (
          <div style={{ ...card, padding: '14px 16px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 9 }}>
              <Icon name="clock" size={15} stroke={2.2} color="var(--accent)" />
              <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--fg2)' }}>{t('quotaToday')}</span>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, 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: 11 }}>
              <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' }}>
                <Icon name="check-circle" size={16} 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.5, padding: '10px', borderRadius: 'var(--radius-full)', cursor: 'pointer', minHeight: 44 }}>
                <Icon name="play-circle" size={16} stroke={2.2} />{t('watchAd')}
              </button>
            )}
          </div>
        )}

        <button onClick={goNodes} style={{ ...card, display: 'flex', alignItems: 'center', gap: 13, textAlign: 'left', padding: '13px 15px', cursor: 'pointer', minHeight: 48 }}>
          <CC code={server.code} active />
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--fg3)', marginBottom: 2 }}>{tt('curNode')}</div>
            <div style={{ fontFamily: 'var(--font-sans)', fontSize: 15, fontWeight: 600, color: 'var(--fg1)', display: 'flex', alignItems: 'center', gap: 7 }}>
              {smart ? t('smartSelect') : srvName(server, lang)}
              {smart && <Icon name="zap" size={13} stroke={2.4} color="var(--accent)" />}
            </div>
            <div style={{ fontSize: 12, color: 'var(--fg3)' }}>{smart ? `${srvName(server, lang)} · ${server.ping}ms` : `${srvSub(server, lang)} · ${server.ping}ms`}</div>
          </div>
          <Icon name="chevron-right" size={20} color="var(--fg3)" />
        </button>

        {status === 'on' && (
          <div style={{ display: 'flex', gap: 10 }}>
            {[['arrow-down', tt('download'), '86.4', 'Mb/s'], ['arrow-up', tt('upload'), '12.1', 'Mb/s'], ['zap', tt('latency'), String(server.ping), 'ms']].map(([ic, l, v, u]) => (
              <div key={ic} style={{ ...card, flex: 1, padding: '11px 13px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 5, color: 'var(--fg3)', fontSize: 11, fontWeight: 600, marginBottom: 4 }}><Icon name={ic} size={13} stroke={2.2} color="var(--accent)" />{l}</div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 16, fontWeight: 500, color: 'var(--fg1)' }}>{v}<span style={{ fontSize: 10.5, color: 'var(--fg3)' }}> {u}</span></div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

/* ── 节点视图 ── */
function TabNodes({ t, tt, lang, current, onPick }) {
  const [q, setQ] = useState('');
  const list = SERVERS.filter(s => (s.name + s.en).toLowerCase().includes(q.toLowerCase()));
  const smartActive = current === 'AUTO';
  return (
    <div style={{ padding: '6px 28px 24px', overflow: 'auto', height: '100%', boxSizing: 'border-box' }}>
      <button onClick={() => onPick('AUTO')} style={{
        display: 'flex', alignItems: 'center', gap: 13, 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: '15px 16px', boxShadow: smartActive ? 'var(--shadow-md)' : 'var(--shadow-sm)', marginBottom: 14, minHeight: 56,
      }}>
        <div style={{ width: 42, height: 42, borderRadius: 'var(--radius-md)', background: 'linear-gradient(150deg,var(--clay-500),var(--clay-700))', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name="zap" size={21} 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: 15.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: 12, color: 'var(--fg2)', marginTop: 3 }}>{t('smartSub')}</div>
        </div>
        {smartActive && <Icon name="check" size={19} color="var(--accent)" stroke={2.6} />}
      </button>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, background: 'var(--bg-subtle)', borderRadius: 'var(--radius-md)', padding: '11px 14px', marginBottom: 14, maxWidth: 380 }}>
        <Icon name="search" size={18} color="var(--fg3)" />
        <input value={q} onChange={e => setQ(e.target.value)} placeholder={tt('searchPh')} style={{ border: 'none', background: 'transparent', outline: 'none', flex: 1, fontFamily: 'var(--font-sans)', fontSize: 14.5, color: 'var(--fg1)' }} />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 11 }}>
        {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: '13px 15px', boxShadow: 'var(--shadow-sm)', minHeight: 56,
            }}>
              <CC code={s.code} active={active} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14.5, fontWeight: 600, color: 'var(--fg1)' }}>{srvName(s, lang)}</div>
                <div style={{ fontSize: 12, color: 'var(--fg3)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{srvSub(s, lang)}</div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 5 }}>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg2)' }}>{s.ping}ms</span>
                <Signal ping={s.ping} />
              </div>
              {active && <Icon name="check" size={18} color="var(--accent)" />}
            </button>
          );
        })}
      </div>
    </div>
  );
}

/* ── 统计视图 ── */
function TabStats({ tt, lang }) {
  const vals = [2.1, 3.4, 1.8, 4.6, 5.2, 6.1, 3.0];
  const days = TSTR.days[lang];
  const max = Math.max(...vals);
  const card = { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-sm)' };
  return (
    <div style={{ padding: '6px 28px 24px', overflow: 'auto', height: '100%', boxSizing: 'border-box' }}>
      <div style={{ display: 'flex', gap: 14, marginBottom: 20 }}>
        {[[tt('statTraffic'), '42.6 GB'], [tt('statPing'), '29 ms'], [tt('statTime'), '86.4 h']].map(([l, v]) => (
          <div key={l} style={{ ...card, flex: 1, padding: '18px 20px' }}>
            <div style={{ fontSize: 12.5, color: 'var(--fg3)', fontWeight: 600 }}>{l}</div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 26, fontWeight: 500, color: 'var(--fg1)', marginTop: 7 }}>{v}</div>
          </div>
        ))}
      </div>
      <div style={{ ...card, padding: '20px 22px' }}>
        <div style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--fg1)', marginBottom: 20 }}>{tt('weekTraffic')}</div>
        <div style={{ display: 'flex', alignItems: 'flex-end', gap: 22, height: 150 }}>
          {vals.map((v, i) => (
            <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 9 }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--fg3)' }}>{v}</div>
              <div style={{ width: '100%', maxWidth: 40, height: `${v / max * 104}px`, background: 'var(--accent)', borderRadius: '6px 6px 0 0', opacity: 0.85 }}></div>
              <div style={{ fontSize: 11.5, color: 'var(--fg3)' }}>{days[i]}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ── 账户视图 ── */
function TabToggle({ on, onChange }) {
  return (
    <div onClick={onChange} style={{ width: 48, height: 29, 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 ? 22 : 3, width: 23, height: 23, borderRadius: '50%', background: '#fff', boxShadow: 'var(--shadow-sm)', transition: 'left 220ms var(--ease-out)' }}></div>
    </div>
  );
}
function TabAccount({ t, tt, lang, setLang, dark, setDark, free, setFree }) {
  const [smartRoute, setSmartRoute] = useState(true);
  const [kill, setKill] = 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 = ({ icon, title, sub, right, last }) => (
    <div style={{ display: 'flex', alignItems: 'center', gap: 13, padding: '15px 18px', borderBottom: last ? 'none' : '1px solid var(--border)', minHeight: 48, boxSizing: 'border-box' }}>
      {icon && <div style={{ width: 34, height: 34, borderRadius: 'var(--radius-sm)', background: 'var(--accent-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name={icon} size={17} color="var(--accent)" stroke={2.2} /></div>}
      <div style={{ flex: 1 }}>
        <div style={{ fontSize: 15, fontWeight: 500, color: 'var(--fg1)' }}>{title}</div>
        {sub && <div style={{ fontSize: 12, color: 'var(--fg3)', marginTop: 2 }}>{sub}</div>}
      </div>
      {right}
    </div>
  );
  const seg = (val) => ({
    border: 'none', cursor: 'pointer', padding: '7px 16px', borderRadius: 'var(--radius-full)', fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, minHeight: 32,
    background: lang === val ? 'var(--surface)' : 'transparent', color: lang === val ? 'var(--fg1)' : 'var(--fg3)',
    boxShadow: lang === val ? 'var(--shadow-sm)' : 'none',
  });
  return (
    <div style={{ padding: '6px 28px 24px', overflow: 'auto', height: '100%', boxSizing: 'border-box', maxWidth: 640 }}>
      <div style={{ background: free ? 'var(--surface)' : 'linear-gradient(155deg,var(--clay-600),var(--clay-800))', border: free ? '1px solid var(--border)' : 'none', borderRadius: 'var(--radius-xl)', padding: 20, color: free ? 'var(--fg1)' : '#fff', marginBottom: 18, boxShadow: 'var(--shadow-md)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{ width: 46, height: 46, borderRadius: '50%', background: free ? 'var(--bg-subtle)' : 'rgba(255,255,255,0.18)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name={free ? 'user' : 'crown'} size={22} color={free ? 'var(--fg2)' : '#fff'} /></div>
          <div>
            <div style={{ fontWeight: 700, fontSize: 16.5 }}>me@pangolin.vpn</div>
            <div style={{ display: 'inline-block', fontSize: 11, fontWeight: 600, background: free ? 'var(--bg-subtle)' : 'rgba(255,255,255,0.2)', color: free ? 'var(--fg2)' : '#fff', padding: '2px 9px', borderRadius: 999, marginTop: 5 }}>{free ? tt('freeBanner') : t('proMember')}</div>
          </div>
        </div>
        <div style={{ marginTop: 14, paddingTop: 13, borderTop: `1px solid ${free ? 'var(--border)' : 'rgba(255,255,255,0.18)'}`, fontSize: 12.5, opacity: free ? 1 : 0.92, color: free ? 'var(--fg2)' : '#fff' }}>
          {free ? tt('trialNote') : '2026-12-31 · 42.6 GB'}
        </div>
      </div>

      <div style={card}>
        <Row icon="zap" title={tt('smartRoute')} sub={tt('smartRouteSub')} right={<TabToggle on={smartRoute} onChange={() => setSmartRoute(!smartRoute)} />} />
        <Row icon="shield" title={tt('killSwitch')} sub={tt('killSub')} right={<TabToggle on={kill} onChange={() => setKill(!kill)} />} last />
      </div>
      <div style={card}>
        <Row icon="globe" title={tt('language')} right={
          <div style={{ display: 'flex', gap: 4, background: 'var(--bg-subtle)', borderRadius: 'var(--radius-full)', padding: 3 }}>
            <button style={seg('zh')} onClick={() => setLang('zh')}>中文</button>
            <button style={seg('en')} onClick={() => setLang('en')}>EN</button>
          </div>
        } />
        <Row icon={dark ? 'moon' : 'sun'} title={tt('darkMode')} right={<TabToggle on={dark} onChange={() => setDark(!dark)} />} />
        <Row icon="clock" title={t('freeDemo')} sub={t('freeDemoSub')} right={<TabToggle on={free} onChange={() => setFree(!free)} />} last />
      </div>
      <div style={{ textAlign: 'center', fontSize: 12, color: 'var(--fg3)', fontFamily: 'var(--font-mono)' }}>{tt('version')}</div>
    </div>
  );
}

/* ── iPad 外壳 + 应用 ── */
function TabletApp() {
  const [view, setView] = useState('connect');
  const [status, setStatus] = useState('off');
  const [code, setCode] = useState('AUTO');
  const [lang, setLang] = useState('zh');
  const [dark, setDark] = useState(false);
  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 = makeT(lang), tt = makeTT(lang);

  const smart = code === 'AUTO';
  const server = smart ? SERVERS.reduce((a, b) => (a.ping < b.ping ? a : b)) : SERVERS.find(s => s.code === code);
  const titles = { connect: tt('navConnect'), nodes: tt('navNodes'), stats: tt('navStats'), account: tt('navAccount') };

  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]);

  let main;
  if (view === 'connect') main = <TabConnect t={t} tt={tt} lang={lang} status={status} onToggle={toggle} server={server} smart={smart} free={free} mins={mins} adDone={adDone} onAd={() => setAdDone(true)} elapsed={elapsed} goNodes={() => setView('nodes')} />;
  else if (view === 'nodes') main = <TabNodes t={t} tt={tt} lang={lang} current={code} onPick={pick} />;
  else if (view === 'stats') main = <TabStats tt={tt} lang={lang} />;
  else main = <TabAccount t={t} tt={tt} lang={lang} setLang={setLang} dark={dark} setDark={setDark} free={free} setFree={setFree} />;

  return (
    <div style={{ background: '#1a1714', borderRadius: 34, padding: 16, boxShadow: '0 0 0 1px rgba(0,0,0,0.3), 0 30px 80px rgba(0,0,0,0.45)' }}>
      <div data-theme={dark ? 'dark' : 'light'} style={{ width: 1180, height: 820, borderRadius: 20, overflow: 'hidden', background: 'var(--bg)', display: 'flex', flexDirection: 'column', fontFamily: 'var(--font-sans)', position: 'relative' }}>
        {/* status bar */}
        <div style={{ height: 30, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 22px', fontFamily: 'var(--font-sans)', fontSize: 12.5, fontWeight: 600, color: 'var(--fg1)' }}>
          <span>9:41</span>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <Icon name="wifi" size={15} stroke={2.2} color="var(--fg1)" />
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5 }}>87%</span>
            <div style={{ width: 24, height: 12, border: '1.5px solid var(--fg2)', borderRadius: 3.5, padding: 1.5, boxSizing: 'border-box' }}><div style={{ width: '80%', height: '100%', background: 'var(--fg1)', borderRadius: 1.5 }}></div></div>
          </div>
        </div>
        <div style={{ flex: 1, minHeight: 0, display: 'flex' }}>
          <TabRail tt={tt} view={view} setView={setView} free={free} t={t} />
          <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
            <div style={{ height: 56, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 28px' }}>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 19, color: 'var(--fg1)' }}>{titles[view]}</div>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5, fontWeight: 600, color: status === 'on' ? 'var(--success)' : 'var(--fg3)', whiteSpace: 'nowrap' }}>{status === 'on' ? '● ' + server.code : '○'}</span>
            </div>
            <div style={{ flex: 1, minHeight: 0 }}>{main}</div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { TabletApp });
