/* global React, Icon, Origin, SyncChip, Meter, CB, RoleChip, JobChip, Portrait, Tag, Empty, Seg, Input, useRoute */
// ============================================================
// Screens 8-9: Free Company overview + Settings / sync status
// ============================================================
const { useState: useS89, useMemo: useM89 } = React;

// Fake-but-plausible FC roster builder
function buildFCRoster() {
  const FIRST = ['Aerith','Korr','Liliane','Yumi','Veska','Olric','Thalia','Imre','Mira','Brennan','Soren','Kael','Nyx','Riven','Zara','Tobin','Marin','Cinder','Vex','Halen','Pia','Jorah','Sable','Ravi','Bram','Lys','Orin','Sage','Tess','Quinn','Hale','Mara','Ennis','Roe','Sienna','Calla','Drake','Petra','Lior','Nova','Faye','Aldric','Bree','Caelan','Demi','Eira','Finn','Gretta','Hilde','Iva'];
  const LAST = ['Nightsong','Brassbottom','d\'Aubreville','Shiroyama','Voidsong','Stonebreak','Greycloak','Kalvain','Sundwalker','Holt','Caelduin','Vesper','Brightmoor','Kestrel','Wynter','Halewind','Frostbloom','Rookward','Stardrift','Embergale','Aldermoor','Thornwell','Pellgrove','Maris','Crowmere','Silverkin','Faewright','Driftwood','Halcyon','Mosswood','Lockewood','Holloway','Brenholme','Caradine','Mirewood','Penbrook','Lyonette','Vossfeld','Quill','Riverford','Sablewood','Thrushe','Vellichor','Whitlock','Yseult','Zantor','Abernathy','Beauchamp','Cervantes','Dunmoor'];
  const JOBS = ['PLD','WAR','DRK','GNB','WHM','SCH','AST','SGE','MNK','DRG','NIN','SAM','RPR','VPR','BRD','MCH','DNC','BLM','SMN','RDM','PCT'];
  const ranks = ['Member','Member','Member','Member','Member','Member','Sergeant','Sergeant','Lieutenant','Master'];
  const out = [];
  let seed = 7;
  const rand = () => { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; };
  for (let i = 0; i < 72; i++) {
    const f = FIRST[Math.floor(rand() * FIRST.length)];
    const l = LAST[Math.floor(rand() * LAST.length)];
    const mainJob = JOBS[Math.floor(rand() * JOBS.length)];
    const capCount = Math.floor(rand() * 14) + 1;
    const ilvl = Math.floor(680 + rand() * 60);
    const mounts = Math.floor(40 + rand() * 270);
    const linked = rand() > 0.42;
    const priv = !linked && rand() > 0.55;
    const lastOn = Math.floor(rand() * 14);
    const rank = ranks[Math.floor(rand() * ranks.length)];
    out.push({
      name: `${f} ${l}`,
      mainJob, capCount, ilvl, mounts, linked, priv, lastOn, rank,
    });
  }
  return out;
}

const FC_ROSTER = buildFCRoster();

function ScreenFC() {
  const [sortKey, setSortKey] = useS89('lastOn');
  const [filter, setFilter] = useS89('all');
  const [q, setQ] = useS89('');

  const filtered = useM89(() => {
    let r = FC_ROSTER.filter(m => {
      if (filter === 'linked' && !m.linked) return false;
      if (filter === 'unlinked' && m.linked) return false;
      if (q && !m.name.toLowerCase().includes(q.toLowerCase())) return false;
      return true;
    });
    if (sortKey === 'name') r = [...r].sort((a, b) => a.name.localeCompare(b.name));
    else if (sortKey === 'ilvl') r = [...r].sort((a, b) => b.ilvl - a.ilvl);
    else if (sortKey === 'mounts') r = [...r].sort((a, b) => b.mounts - a.mounts);
    else if (sortKey === 'capCount') r = [...r].sort((a, b) => b.capCount - a.capCount);
    else r = [...r].sort((a, b) => a.lastOn - b.lastOn);
    return r;
  }, [sortKey, filter, q]);

  const linkedCount = FC_ROSTER.filter(m => m.linked).length;
  const avgIlvl = Math.round(FC_ROSTER.reduce((a, m) => a + m.ilvl, 0) / FC_ROSTER.length);
  const totalMounts = FC_ROSTER.reduce((a, m) => a + (m.linked ? m.mounts : 0), 0);

  return (
    <div className="fc-page">
      <section className="fc-head card">
        <div className="fc-head-l">
          <div className="row gap-8" style={{ marginBottom: 8 }}>
            <Tag dot kind="primary">«WoH»</Tag>
            <Tag>Aether · Sargatanas</Tag>
            <Origin kind="auto" />
          </div>
          <h1 style={{ margin: 0, fontSize: 26, fontWeight: 600, color: 'var(--text-strong)', letterSpacing: '-0.018em' }}>
            Whispers of Hydaelyn
          </h1>
          <div className="muted" style={{ marginTop: 4, fontSize: 13 }}>
            Founded Eorzea time 8/12 · Rank 30 · Master <strong style={{ color: 'var(--text)' }}>Aerith Nightsong</strong>
          </div>
          <div className="row gap-8" style={{ marginTop: 14 }}>
            <button className="btn small"><Icon.Discord /> Discord</button>
            <button className="btn small"><Icon.External /> Lodestone</button>
            <button className="btn small"><Icon.Refresh /> Resync FC page</button>
          </div>
        </div>
        <div className="fc-head-r">
          <div className="fc-stat">
            <div className="fc-stat-l">Members</div>
            <div className="fc-stat-v num">{FC_ROSTER.length}<span className="muted" style={{ fontSize: 14 }}>/100</span></div>
            <div className="muted" style={{ fontSize: 11.5 }}>{linkedCount} bound · <Origin kind="auto" /></div>
          </div>
          <div className="fc-stat">
            <div className="fc-stat-l">Avg item level</div>
            <div className="fc-stat-v num">{avgIlvl}</div>
            <Meter value={avgIlvl - 660} total={80} tone="status" showPct={false} />
          </div>
          <div className="fc-stat">
            <div className="fc-stat-l">Mounts collected</div>
            <div className="fc-stat-v num">{totalMounts.toLocaleString()}</div>
            <div className="muted" style={{ fontSize: 11.5 }}>across linked members · <Origin kind="diffed" /></div>
          </div>
          <div className="fc-stat">
            <div className="fc-stat-l">Avg weekly logins</div>
            <div className="fc-stat-v num">52<span className="muted" style={{ fontSize: 14 }}>%</span></div>
            <div className="muted" style={{ fontSize: 11.5 }}>last 4 weeks · <Origin kind="auto" /></div>
          </div>
        </div>
      </section>

      <div className="fc-toolbar">
        <div className="row gap-10" style={{ flex: 1 }}>
          <div style={{ width: 280 }}>
            <Input icon={<Icon.Search />} placeholder="Search by name…" value={q} onChange={e => setQ(e.target.value)} />
          </div>
          <Seg
            value={filter}
            onChange={setFilter}
            options={[
              { value: 'all', label: `All · ${FC_ROSTER.length}` },
              { value: 'linked', label: `Linked · ${linkedCount}` },
              { value: 'unlinked', label: `Unlinked · ${FC_ROSTER.length - linkedCount}` },
            ]}
          />
        </div>
        <div className="row gap-8">
          <button className="btn ghost small"><Icon.Filter /> Filter</button>
          <button className="btn ghost small"><Icon.External /> Export</button>
          <button className="btn primary small"><Icon.Plus /> Invite</button>
        </div>
      </div>

      <section className="card" style={{ padding: 0 }}>
        <div style={{ maxHeight: '60vh', overflowY: 'auto' }}>
          <table className="tbl fc-tbl">
            <thead>
              <tr>
                <th style={{ width: 32 }}></th>
                <SortableTh k="name" k2={sortKey} onSort={setSortKey}>Name</SortableTh>
                <th style={{ width: 100 }}>Rank</th>
                <th style={{ width: 90 }}>Main</th>
                <SortableTh k="capCount" k2={sortKey} onSort={setSortKey} cls="num-cell">Cap</SortableTh>
                <SortableTh k="ilvl" k2={sortKey} onSort={setSortKey} cls="num-cell">iLvl</SortableTh>
                <SortableTh k="mounts" k2={sortKey} onSort={setSortKey} cls="num-cell">Mounts</SortableTh>
                <SortableTh k="lastOn" k2={sortKey} onSort={setSortKey} cls="num-cell">Last on</SortableTh>
                <th style={{ width: 110 }}>Source</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map((m, i) => (
                <tr key={m.name + i} className={!m.linked ? 'unlinked' : ''}>
                  <td><Portrait size={22} label="" /></td>
                  <td>
                    <div className="strong" style={{ fontSize: 12.5 }}>{m.name}</div>
                    {!m.linked && (
                      <div className="muted" style={{ fontSize: 10.5 }}>
                        {m.priv ? 'Private profile · limited data' : 'Not on Aether Hub yet'}
                      </div>
                    )}
                  </td>
                  <td><span className={`fc-rank rank-${m.rank.toLowerCase()}`}>{m.rank}</span></td>
                  <td><RoleChip job={m.mainJob} /></td>
                  <td className="num-cell">
                    {m.linked ? `${m.capCount}/22` : <span className="faint">—</span>}
                  </td>
                  <td className="num-cell">
                    {m.linked ? m.ilvl : <span className="faint">—</span>}
                  </td>
                  <td className="num-cell">
                    {m.linked
                      ? <span><strong style={{ color: 'var(--text)' }}>{m.mounts}</strong> <span className="muted">/312</span></span>
                      : m.priv ? <Tag><Icon.Lock />private</Tag> : <button className="btn ghost small" style={{ height: 22 }}>Invite</button>}
                  </td>
                  <td className="num-cell muted">{m.lastOn === 0 ? 'today' : `${m.lastOn}d ago`}</td>
                  <td>
                    {m.linked
                      ? <Origin kind="auto" />
                      : m.priv ? <Origin kind="auto" label="auto · partial" /> : <span className="muted" style={{ fontSize: 11 }}>roster only</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </section>

      <div className="fc-foot-note">
        <Icon.Info />
        <div>
          Roster is auto-imported from the Lodestone FC page every 24h. Collection detail only fills in for members who've bound their character — invite them so this table fills out.
        </div>
      </div>

      <style>{`
        .fc-head { display: flex; padding: 22px 24px; gap: 24px; align-items: center; margin-bottom: 16px; }
        .fc-head-l { flex: 1; min-width: 0; }
        .fc-head-r {
          display: grid; grid-template-columns: repeat(4, minmax(120px, 1fr));
          gap: 18px;
          padding-left: 24px; border-left: 1px solid var(--border-soft);
        }
        .fc-stat-l { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
        .fc-stat-v { font-size: 22px; font-weight: 600; color: var(--text-strong); letter-spacing: -0.01em; margin-bottom: 6px; }

        .fc-toolbar {
          display: flex; align-items: center; justify-content: space-between;
          margin-bottom: 10px;
          padding: 10px 12px;
          background: var(--bg-elev);
          border: 1px solid var(--border-soft);
          border-radius: 10px;
        }
        .fc-tbl thead th { white-space: nowrap; }
        .fc-tbl .tight td { padding: 8px 14px; }
        .fc-tbl tbody tr.unlinked td { background: oklch(from var(--bg) l c h / 1); }
        .fc-tbl tbody tr.unlinked .strong { color: var(--text-muted); font-weight: 500; }

        .fc-rank {
          font-size: 11px;
          padding: 2px 7px;
          border-radius: 4px;
          background: var(--surface-hi);
          color: var(--text-muted);
          border: 1px solid var(--border-soft);
        }
        .fc-rank.rank-master { color: var(--primary-hi); background: var(--primary-bg-2); border-color: oklch(0.50 0.13 275 / 0.35); }
        .fc-rank.rank-lieutenant { color: var(--info); background: var(--auto-bg); border-color: oklch(0.50 0.10 220 / 0.35); }
        .fc-rank.rank-sergeant { color: var(--warning); background: var(--warning-bg); border-color: oklch(0.50 0.10 75 / 0.35); }

        .fc-foot-note {
          display: flex; gap: 10px;
          padding: 12px 14px;
          color: var(--text-muted);
          font-size: 12.5px;
          margin-top: 14px;
        }
        .fc-foot-note svg { color: var(--text-faint); flex: 0 0 14px; margin-top: 2px; }

        @media (max-width: 1100px) {
          .fc-head { flex-direction: column; align-items: stretch; }
          .fc-head-r { grid-template-columns: 1fr 1fr; border-left: none; padding-left: 0; border-top: 1px solid var(--border-soft); padding-top: 16px; }
        }
      `}</style>
    </div>
  );
}

function SortableTh({ k, k2, onSort, children, cls }) {
  const active = k === k2;
  return (
    <th className={cls}>
      <button
        onClick={() => onSort?.(k)}
        style={{
          background: 'none', border: 0, padding: 0, color: active ? 'var(--text)' : 'inherit',
          font: 'inherit', textTransform: 'uppercase', letterSpacing: '0.04em', fontSize: 11, cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', gap: 5,
        }}
      >
        {children}
        <span style={{ opacity: active ? 1 : 0.35, display: 'inline-flex' }}>
          <Icon.ChevUD />
        </span>
      </button>
    </th>
  );
}

// -------------------- 9. Settings / Sync --------------------
function ScreenSettings() {
  const sections = [
    { id: 'account', label: 'Account' },
    { id: 'chars',   label: 'Characters' },
    { id: 'privacy', label: 'Privacy & data' },
    { id: 'discord', label: 'Discord' },
    { id: 'danger',  label: 'Danger zone' },
  ];
  const [active, setActive] = useS89('chars');

  return (
    <div className="settings">
      <div className="page-h">
        <div>
          <h1 className="page-h-title">Settings</h1>
          <div className="page-h-sub">Manage your account, bound characters, and what data we sync.</div>
        </div>
      </div>

      <div className="settings-layout">
        <aside className="settings-side">
          <ul className="settings-nav">
            {sections.map(s => (
              <li key={s.id}>
                <a href={`#${s.id}`} className={active === s.id ? 'on' : ''} onClick={(e) => { e.preventDefault(); setActive(s.id); }}>
                  {s.label}
                </a>
              </li>
            ))}
          </ul>
        </aside>

        <div className="settings-main">
          {/* Account */}
          {active === 'account' && (
            <section id="account">
              <h2 className="settings-h">Account</h2>
              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="row gap-12">
                    <div className="sb-account-avatar" style={{ width: 38, height: 38, fontSize: 14 }}>JK</div>
                    <div>
                      <div className="strong" style={{ fontSize: 14 }}>jakob.kohl</div>
                      <div className="muted" style={{ fontSize: 12 }}>Signed in with Discord · jakob#4382</div>
                    </div>
                  </div>
                </div>
                <button className="btn small">Sign out</button>
              </div>
              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Email notifications</div>
                  <div className="muted" style={{ fontSize: 12 }}>Raid night reminders, prog summaries, FC weekly digest.</div>
                </div>
                <Seg value="opt-in" options={[{value:'off',label:'Off'},{value:'opt-in',label:'Opt-in'},{value:'all',label:'All'}]} onChange={() => {}} />
              </div>
            </section>
          )}

          {/* Characters & sync */}
          {active === 'chars' && (
            <section id="chars">
              <div className="row" style={{ justifyContent: 'space-between', marginBottom: 14 }}>
                <h2 className="settings-h" style={{ margin: 0 }}>Bound characters</h2>
                <button className="btn small primary"><Icon.Plus /> Bind another character</button>
              </div>

              <CharSyncCard
                name="Aerith Nightsong" world="Sargatanas · Aether"
                state="ok" last="2h ago" next="in 2h 14m"
                main
              />
              <CharSyncCard
                name="Aerith Lightwhisper" world="Faerie · Aether"
                state="syncing" last="now"
              />
              <CharSyncCard
                name="Brennan Stormblade" world="Excalibur · Primal"
                state="warn" last="6h ago" next="in 18h"
                warn="Lodestone profile is private — mounts, minions, and achievements can't be synced. Make your character search results public to enable full sync."
              />
              <CharSyncCard
                name="Sable Highrook" world="Lich · Light"
                state="failed" last="3d ago" next="retrying in 1h"
                err="Lodestone is rate-limiting us right now. We'll retry automatically — no action needed."
              />
            </section>
          )}

          {/* Privacy & data */}
          {active === 'privacy' && (
            <section id="privacy">
              <h2 className="settings-h">Privacy & data</h2>
              <div className="card priv-card">
                <div className="priv-ic"><Icon.Lock /></div>
                <div>
                  <div className="strong" style={{ fontSize: 14, marginBottom: 4 }}>What we read and don't read</div>
                  <p className="muted" style={{ margin: 0, fontSize: 13, lineHeight: 1.6 }}>
                    Aether Hub only reads <strong style={{ color: 'var(--text)' }}>public</strong> data — your Lodestone character page,
                    FFLogs reports you've made public, and a community-maintained item catalog. We <strong style={{ color: 'var(--text)' }}>never</strong> read
                    your game client, never use addons, and never ask for your Square Enix password. We can't see anything that isn't already public.
                  </p>
                </div>
              </div>

              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Sync sources</div>
                  <div className="muted" style={{ fontSize: 12 }}>Toggle which public sources we read from.</div>
                </div>
              </div>
              <div className="card sources">
                {[
                  { name: 'Lodestone', sub: 'Character page, FC roster', on: true },
                  { name: 'FFLogs', sub: 'Public reports for raid nights', on: true },
                  { name: 'Community item API', sub: 'Catalog of items & icons', on: true },
                  { name: 'Discord activity', sub: 'Only your linked server', on: false },
                ].map(s => (
                  <div key={s.name} className="source-row">
                    <div>
                      <div className="strong" style={{ fontSize: 13 }}>{s.name}</div>
                      <div className="muted" style={{ fontSize: 11.5 }}>{s.sub}</div>
                    </div>
                    <Toggle on={s.on} />
                  </div>
                ))}
              </div>

              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Export your data</div>
                  <div className="muted" style={{ fontSize: 12 }}>Download everything we've stored about you, as JSON.</div>
                </div>
                <button className="btn small">Request export</button>
              </div>
            </section>
          )}

          {/* Discord */}
          {active === 'discord' && (
            <section id="discord">
              <h2 className="settings-h">Discord</h2>
              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="row gap-10">
                    <div className="dc-server-ic">WoH</div>
                    <div>
                      <div className="strong" style={{ fontSize: 13.5 }}>Whispers of Hydaelyn</div>
                      <div className="muted" style={{ fontSize: 12 }}>148 members · Aether Hub bot active <Tag dot kind="primary">online</Tag></div>
                    </div>
                  </div>
                </div>
                <button className="btn small">Manage in Discord <Icon.External /></button>
              </div>
              <div className="card setting-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Bot commands</div>
                  <div className="muted" style={{ fontSize: 12 }}>What members can run in your server.</div>
                </div>
              </div>
              <div className="card cmd-list">
                {[
                  { cmd: '/loot <item> <member> <rule>', what: 'Log a loot drop into the static loot table.' },
                  { cmd: '/raid log <fflogs-url>',        what: 'Import an FFLogs report into the current raid night.' },
                  { cmd: '/static',                       what: 'Post the next raid night and pull RSVPs.' },
                  { cmd: '/relic <job>',                  what: 'DM your current relic progress.' },
                  { cmd: '/fc weekly',                    what: 'Post the FC weekly digest in this channel.' },
                ].map(c => (
                  <div key={c.cmd} className="cmd-row">
                    <code className="cmd-code mono">{c.cmd}</code>
                    <div className="muted" style={{ fontSize: 12.5 }}>{c.what}</div>
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* Danger zone */}
          {active === 'danger' && (
            <section id="danger">
              <h2 className="settings-h">Danger zone</h2>
              <div className="card danger-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Unbind a character</div>
                  <div className="muted" style={{ fontSize: 12 }}>Removes the character from your account and stops all syncing.</div>
                </div>
                <button className="btn danger small">Unbind…</button>
              </div>
              <div className="card danger-row">
                <div className="setting-row-l">
                  <div className="strong" style={{ fontSize: 13.5 }}>Delete account</div>
                  <div className="muted" style={{ fontSize: 12 }}>Permanently delete your account and all associated data. This can't be undone.</div>
                </div>
                <button className="btn danger small">Delete account</button>
              </div>
            </section>
          )}
        </div>
      </div>

      <style>{`
        .settings-layout { display: grid; grid-template-columns: 200px 1fr; gap: 28px; }
        .settings-side { position: sticky; top: 0; align-self: start; }
        .settings-nav { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 1px; }
        .settings-nav a {
          display: block;
          padding: 8px 12px;
          border-radius: 7px;
          color: var(--text-muted);
          text-decoration: none;
          font-size: 13px;
          font-weight: 500;
        }
        .settings-nav a:hover { color: var(--text); background: var(--surface); }
        .settings-nav a.on { color: var(--text-strong); background: var(--primary-bg); }

        .settings-main { max-width: 760px; }
        .settings-h { font-size: 17px; font-weight: 600; color: var(--text-strong); letter-spacing: -0.01em; margin: 0 0 14px; }
        .setting-row {
          display: flex; align-items: center; justify-content: space-between;
          padding: 16px 18px;
          gap: 18px;
          margin-bottom: 10px;
        }
        .setting-row-l { min-width: 0; }
        .danger-row { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px; gap: 18px; margin-bottom: 10px; border-color: oklch(0.50 0.13 27 / 0.3); }

        .priv-card { display: flex; gap: 14px; padding: 18px; margin-bottom: 14px; }
        .priv-ic {
          width: 36px; height: 36px;
          flex: 0 0 36px;
          border-radius: 8px;
          background: var(--primary-bg);
          color: var(--primary-hi);
          display: grid; place-items: center;
        }

        .sources { padding: 0; margin-bottom: 14px; }
        .source-row {
          display: flex; align-items: center; justify-content: space-between;
          padding: 12px 18px;
          border-top: 1px solid var(--border-soft);
        }
        .source-row:first-child { border-top: none; }

        .cmd-list { padding: 0; }
        .cmd-row {
          display: grid; grid-template-columns: 280px 1fr; gap: 16px; align-items: center;
          padding: 10px 18px;
          border-top: 1px solid var(--border-soft);
        }
        .cmd-row:first-child { border-top: none; }
        .cmd-code {
          font-size: 12px;
          color: var(--primary-hi);
          background: var(--primary-bg-2);
          padding: 4px 8px;
          border-radius: 5px;
          border: 1px solid oklch(0.50 0.13 275 / 0.3);
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }

        .dc-server-ic {
          width: 36px; height: 36px;
          flex: 0 0 36px;
          border-radius: 8px;
          background: linear-gradient(135deg, #5865F2 0%, #4752c4 100%);
          display: grid; place-items: center;
          font-family: 'Geist Mono', monospace;
          font-size: 11px;
          font-weight: 700;
          color: white;
        }

        @media (max-width: 900px) {
          .settings-layout { grid-template-columns: 1fr; }
          .settings-side { position: static; }
          .settings-nav { flex-direction: row; flex-wrap: wrap; }
        }
      `}</style>
    </div>
  );
}

function CharSyncCard({ name, world, state, last, next, main, warn, err }) {
  return (
    <div className="char-sync-card">
      <div className="row gap-12" style={{ alignItems: 'flex-start' }}>
        <Portrait size={44} label="" />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="row gap-8" style={{ marginBottom: 2 }}>
            <span className="strong" style={{ fontSize: 14 }}>{name}</span>
            {main && <Tag kind="primary" dot>Main</Tag>}
          </div>
          <div className="muted" style={{ fontSize: 12 }}>{world}</div>
          <div className="row gap-10" style={{ marginTop: 10 }}>
            <SyncChip state={state === 'ok' ? 'ok' : state === 'syncing' ? 'syncing' : state === 'failed' ? 'failed' : 'ok'}
              label={state === 'ok' ? `Synced ${last}` : state === 'syncing' ? 'Syncing now' : state === 'failed' ? 'Sync failed' : `Synced ${last}`}
            />
            {next && <span className="muted" style={{ fontSize: 11.5 }}>Next sync {next}</span>}
            <button className="btn ghost small" style={{ marginLeft: 'auto' }}><Icon.Refresh /> Refresh now</button>
          </div>
          {warn && (
            <div className="char-warn">
              <Icon.Lock />
              <div className="muted" style={{ fontSize: 12, lineHeight: 1.5 }}>{warn}</div>
            </div>
          )}
          {err && (
            <div className="char-warn err">
              <Icon.Warning />
              <div className="muted" style={{ fontSize: 12, lineHeight: 1.5 }}>{err}</div>
            </div>
          )}
        </div>
        <button className="btn ghost small" style={{ width: 28, padding: 0 }}><Icon.More /></button>
      </div>
      <style>{`
        .char-sync-card {
          background: var(--surface);
          border: 1px solid var(--border-soft);
          border-radius: 12px;
          padding: 16px;
          margin-bottom: 10px;
        }
        .char-warn {
          display: flex; gap: 8px;
          margin-top: 10px;
          padding: 10px 12px;
          background: var(--warning-bg);
          border: 1px solid oklch(0.50 0.10 75 / 0.3);
          border-radius: 8px;
        }
        .char-warn svg { color: var(--warning); flex: 0 0 14px; margin-top: 1px; width: 14px; height: 14px; }
        .char-warn.err { background: var(--danger-bg); border-color: oklch(0.50 0.13 27 / 0.3); }
        .char-warn.err svg { color: var(--danger); }
      `}</style>
    </div>
  );
}

function Toggle({ on: defaultOn }) {
  const [on, setOn] = useS89(defaultOn);
  return (
    <button
      className="toggle"
      onClick={() => setOn(o => !o)}
      style={{
        width: 36, height: 20,
        borderRadius: 999,
        border: '1px solid var(--border)',
        background: on ? 'var(--primary)' : 'var(--surface-hi)',
        position: 'relative',
        cursor: 'pointer',
        transition: 'background 120ms',
      }}>
      <span style={{
        position: 'absolute',
        top: 1, left: on ? 17 : 1,
        width: 16, height: 16,
        borderRadius: '50%',
        background: 'white',
        transition: 'left 140ms',
        boxShadow: '0 1px 3px rgba(0,0,0,.3)',
      }}></span>
    </button>
  );
}

Object.assign(window, { ScreenFC, ScreenSettings });
