// Auth screens — login, signup, forgot, reset, MFA, magic-link, verify // Sits between marketing and admin: own shell, no marketing nav const Auth = ({ screen = 'login', setPage, setAuthScreen }) => { const goto = (s) => { setAuthScreen ? setAuthScreen(s) : null; window.scrollTo({top:0}); }; return (
{/* Left brand panel */} {/* Right form panel */}
{screen === 'login' && } {screen === 'signup' && } {screen === 'forgot' && } {screen === 'sent' && } {screen === 'reset' && } {screen === 'mfa' && } {screen === 'verify' && } {screen === 'magic' && }
); }; // ───────────────────────────────────────────────────────────────── // LEFT BRAND PANEL const AuthBrandPanel = ({ screen }) => { const copy = { login: {kicker:'Welcome back', headline:'Pick up where you left off.', sub:'Your dashboards, files, conversations — exactly as you left them.'}, signup: {kicker:'New here?', headline:'A place for the work to live.', sub:'One workspace for the studio, your team, every file, every revision.'}, forgot: {kicker:'Forgot it?', headline:'Happens to all of us.', sub:'Enter your email. We\'ll send a one-time link in under a minute.'}, sent: {kicker:'Sent', headline:'Check your inbox.', sub:'If we recognise that email, a reset link is on its way.'}, reset: {kicker:'Reset password', headline:'A fresh password, one last time.', sub:'Long, weird, and ideally generated by a manager.'}, mfa: {kicker:'One more thing', headline:'Two-factor verification.', sub:'Enter the 6-digit code from your authenticator app.'}, verify: {kicker:'Almost there', headline:'Confirm your email.', sub:'We sent a link to verify the address you signed up with.'}, magic: {kicker:'Magic link sent', headline:'Skip the password.', sub:'Click the link in your inbox. The session opens automatically.'}, }; const c = copy[screen] || copy.login; return (
{/* Ambient glow */}
{/* Decorative pattern */}
{c.kicker}

{c.headline.split(' ').slice(0,-1).join(' ')} {c.headline.split(' ').slice(-1)}

{c.sub}

JC
Jane Cooper
CTO · LEDGERLINE
"The shipped product was exactly what we'd discussed in week one — not what scope creep turned it into at week eighteen. That alone made it worth it."
); }; // ───────────────────────────────────────────────────────────────── // LOGIN const AuthLogin = ({ goto, setPage }) => (

Sign in

Don't have an account?

{/* SSO row */}
{e.preventDefault();setPage('portal');}} style={{display:'flex',flexDirection:'column',gap:14}}> goto('forgot')} style={{fontSize:11,color:'var(--accent)'}}>Forgot?}/>
); // ───────────────────────────────────────────────────────────────── // SIGNUP const AuthSignup = ({ goto, setPage }) => { const [pwd, setPwd] = React.useState(''); return (

Create your account

Already have one?

{e.preventDefault();goto('verify');}} style={{display:'flex',flexDirection:'column',gap:14}}>
I agree to the Terms and Privacy Policy}/>
); }; // ───────────────────────────────────────────────────────────────── // FORGOT PASSWORD const AuthForgot = ({ goto }) => (

Forgot password?

Enter your email and we'll send a one-time reset link.

{e.preventDefault();goto('sent');}} style={{display:'flex',flexDirection:'column',gap:14}}>
); // ───────────────────────────────────────────────────────────────── // SENT (post-forgot) const AuthSent = ({ goto }) => (

Check your inbox

If jane@ledgerline.com matches an account, a reset link is on its way. The link expires in 15 minutes.

NOT SEEING IT?
  • · Check your spam folder
  • · Allow up to 60 seconds
  • · Triple-check the address
); // ───────────────────────────────────────────────────────────────── // RESET (from email link) const AuthReset = ({ goto }) => { const [pwd, setPwd] = React.useState(''); return (

Set a new password

Resetting password for jane@ledgerline.com

{e.preventDefault();goto('login');}} style={{display:'flex',flexDirection:'column',gap:14}}>
PASSWORD MUST
{[ ['12+ characters', pwd.length >= 12], ['One uppercase', /[A-Z]/.test(pwd)], ['One number', /\d/.test(pwd)], ['One symbol', /[^a-zA-Z0-9]/.test(pwd)], ].map(([l,ok]) => (
{ok ? Icon.check() : '○'}{l}
))}
); }; // ───────────────────────────────────────────────────────────────── // MFA const AuthMFA = ({ goto, setPage }) => { const [code, setCode] = React.useState(['','','','','','']); const refs = React.useRef([]); const handleChange = (i, v) => { if (!/^\d?$/.test(v)) return; const next = [...code]; next[i] = v; setCode(next); if (v && refs.current[i+1]) refs.current[i+1].focus(); }; return (

Two-factor code

Open your authenticator app and enter the 6-digit code for SolidAtoms.

{code.map((v,i) => ( refs.current[i] = el} value={v} maxLength={1} inputMode="numeric" onChange={(e)=>handleChange(i, e.target.value)} style={{ width:54,height:64,textAlign:'center', fontFamily:'var(--mono)',fontSize:24,fontWeight:500, background:'var(--bg-3)',border:'1px solid', borderColor: v ? 'var(--accent)' : 'var(--line-2)', borderRadius:10,color:'var(--ink)',outline:'none', transition:'border-color .15s ease' }} onFocus={(e)=>e.target.style.borderColor='var(--accent)'} onBlur={(e)=>e.target.style.borderColor= v ? 'var(--accent)' : 'var(--line-2)'} /> ))}
Code refreshes in 22s
); }; // ───────────────────────────────────────────────────────────────── // VERIFY EMAIL const AuthVerify = ({ goto }) => (

Verify your email

We sent a verification link to jane@ledgerline.com. Click it to activate your account.

Wrong address?
); // ───────────────────────────────────────────────────────────────── // MAGIC LINK const AuthMagicLink = ({ goto }) => (

Magic link sent

Click the link in your inbox. It expires in 10 minutes. You can close this tab — the session will open in a new one.

G
Open Gmail
jane@ledgerline.com
{Icon.arrow()}
); // ───────────────────────────────────────────────────────────────── // HELPERS const AuthField = ({ label, type='text', placeholder, rightAction, value, onChange, autoFocus, compact }) => { const [v, setV] = React.useState(''); const val = value != null ? value : v; const set = onChange || setV; return (
{label} {rightAction}
set(e.target.value)} autoFocus={autoFocus} style={{ width:'100%', padding:'12px 14px', borderRadius:8, background:'var(--bg-3)', border:'1px solid var(--line-2)', color:'var(--ink)', fontSize:14, fontFamily: type==='password' ? 'var(--mono)' : 'var(--sans)', letterSpacing: type==='password' ? '0.08em' : 'normal', outline:'none', transition:'border-color .15s ease' }} onFocus={e=>e.target.style.borderColor='var(--accent)'} onBlur={e=>e.target.style.borderColor='var(--line-2)'} />
); }; const SSOButton = ({ label, icon }) => ( ); const Divider = () => (
OR
); const Checkbox = ({ label }) => { const [on, setOn] = React.useState(false); return ( ); }; const PasswordStrength = ({ value }) => { const score = Math.min(4, Math.floor(( (value.length >= 12 ? 1 : 0) + (/[A-Z]/.test(value) ? 1 : 0) + (/\d/.test(value) ? 1 : 0) + (/[^a-zA-Z0-9]/.test(value) ? 1 : 0) ))); const labels = ['','Weak','Okay','Strong','Excellent']; const colors = ['var(--line)','var(--accent-2)','var(--warn)','#7ee787','var(--accent)']; return (
{[1,2,3,4].map(i => (
))}
Password strength {labels[score] || '—'}
); }; window.Auth = Auth;