// Full-screen login gate. Rendered by app.jsx whenever // GET /api/auth/me returns 401 (fresh page load or session expired). // // Rules-of-Hooks: every useState / useEffect is declared BEFORE any // early return so hook order can never change between renders. This // pattern has bit us three times in other admin views — keep it strict. function Login({ onAuthed }) { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [busy, setBusy] = React.useState(false); const [err, setErr] = React.useState(null); async function submit(e) { e.preventDefault(); setErr(null); setBusy(true); try { const user = await window.login(username.trim(), password); if (typeof onAuthed === 'function') onAuthed(user); } catch (e2) { setErr(e2.message || 'sign in failed'); } finally { setBusy(false); } } const INPUT = { width: '100%', padding: '8px 11px', background: 'var(--surface)', border: '1px solid var(--border-2)', borderRadius: 3, color: 'var(--text)', fontFamily: 'var(--mono)', fontSize: 13, outline: 'none', }; return (