// Login.jsx — terminal-style login with Turnstile captcha, TOTP MFA,
// redacted/scramble reveal + ACCESS GRANTED flash.
// SECURITY: error messages are deliberately generic. No enumeration of valid emails.

const Login = ({ onLoggedIn, onSwitchToRegister }) => {
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [phase, setPhase] = React.useState('idle'); // idle | submitting | mfa | revealing | granted | denied
  const [err, setErr] = React.useState(null);
  const [scrambled, setScrambled] = React.useState({ handle: '', email: '', tier: '' });
  const [deniedInfo, setDeniedInfo] = React.useState({ lockout: 5, attempt: 1 });
  const [turnstileToken, setTurnstileToken] = React.useState(null);
  const [mfaCode, setMfaCode] = React.useState('');
  const [mfaMode, setMfaMode] = React.useState('totp'); // totp | recovery
  const [mfaErr, setMfaErr] = React.useState(null);
  const [mfaSubmitting, setMfaSubmitting] = React.useState(false);
  const [resolvedUser, setResolvedUser] = React.useState(null);
  const turnstileWidgetId = React.useRef(null);
  const demo = window.OBC_DEMO_USER || { handle:'op1337', email:'operator@brew-co', tier:'ADVANCED' };

  // Caps & rate-limit cosmetics — purely client-side, no real protection
  const [attempts, setAttempts] = React.useState(0);

  // DEMO ONLY — magic trigger words that simulate a failed login.
  // NOT a security check. In production, never branch on user input like this.
  const isIntruder = (val) => {
    const v = (val || '').toLowerCase().trim();
    return v === 'intruder' || v === 'denied' || v.startsWith('intruder@') || v.startsWith('denied@');
  };

  // Render Turnstile widget when in idle phase
  React.useEffect(() => {
    if (phase === 'idle' && window.turnstile) {
      // Clean up previous widget if it exists
      if (turnstileWidgetId.current != null) {
        try { window.turnstile.remove(turnstileWidgetId.current); } catch (e) { /* noop */ }
        turnstileWidgetId.current = null;
      }
      const el = document.getElementById('login-turnstile');
      if (!el) return;
      turnstileWidgetId.current = window.turnstile.render('#login-turnstile', {
        sitekey: '0x4AAAAAADT5ebjsA6gd7yaa',
        theme: 'dark',
        callback: (token) => setTurnstileToken(token),
        'expired-callback': () => setTurnstileToken(null),
        'error-callback': () => setTurnstileToken(null),
      });
    }
    return () => {
      if (turnstileWidgetId.current != null) {
        try { window.turnstile.remove(turnstileWidgetId.current); } catch (e) { /* noop */ }
        turnstileWidgetId.current = null;
      }
    };
  }, [phase]);

  const beginReveal = (user) => {
    setResolvedUser(user);
    setPhase('revealing');
    scrambleTo('handle', user.handle || user.email, 1300);
    scrambleTo('email', user.email, 1500);
    scrambleTo('tier', user.tier || 'OPERATOR', 1100);

    setTimeout(() => setPhase('granted'), 1700);
    setTimeout(() => onLoggedIn(user), 2700);
  };

  const triggerDenied = () => {
    setDeniedInfo((d) => ({ lockout: 5, attempt: attempts + 1 }));
    setPhase('denied');
    // Countdown lockout, then unlock
    let n = 5;
    const tick = setInterval(() => {
      n -= 1;
      setDeniedInfo((d) => ({ ...d, lockout: n }));
      if (n <= 0) {
        clearInterval(tick);
        setTimeout(() => { setPhase('idle'); setPassword(''); setTurnstileToken(null); }, 400);
      }
    }, 1000);
  };

  const submit = async (e) => {
    e.preventDefault();
    if (phase !== 'idle') return;
    setErr(null);

    // Cheap client-side validation — generic messaging, no enumeration
    if (!email.trim() || !password) {
      setErr('// missing input. supply both fields.');
      return;
    }
    if (email.length > 320 || password.length > 1000) {
      setErr('// payload too large.');
      return;
    }

    // Intruder easter egg — purely client-side demo, checked before API call
    if (isIntruder(email) || isIntruder(password)) {
      setPhase('submitting');
      setAttempts((a) => a + 1);
      setTimeout(() => triggerDenied(), 1100);
      return;
    }

    // Require Turnstile token (skip check in mock mode for demo convenience)
    if (!turnstileToken && window.OBC_API.mode !== 'mock') {
      setErr('// captcha verification required.');
      return;
    }

    setPhase('submitting');
    setAttempts((a) => a + 1);

    try {
      const result = await window.OBC_API.login(email, password, turnstileToken);

      // MFA required — transition to MFA phase
      if (result && result.mfa_required) {
        setPhase('mfa');
        return;
      }

      // Success — begin reveal with real customer data
      beginReveal(result);
    } catch (error) {
      triggerDenied();
    }
  };

  const submitMfa = async (e) => {
    e.preventDefault();
    if (mfaSubmitting) return;
    setMfaErr(null);

    const code = mfaCode.trim();
    const isRecovery = mfaMode === 'recovery';

    if (!code) {
      setMfaErr('// enter a code.');
      return;
    }
    if (!isRecovery && (code.length !== 6 || !/^\d{6}$/.test(code))) {
      setMfaErr('// TOTP code must be 6 digits.');
      return;
    }

    setMfaSubmitting(true);
    try {
      const result = await window.OBC_API.verifyMfa(code, isRecovery);
      if (result.ok && result.customer) {
        beginReveal(result.customer);
      } else if (result.customer) {
        beginReveal(result.customer);
      } else {
        setMfaErr('// verification failed. try again.');
      }
    } catch (error) {
      setMfaErr('// verification failed. try again.');
    } finally {
      setMfaSubmitting(false);
    }
  };

  const scrambleTo = (key, target, dur) => {
    const chars = '!@#$%^&*()_+-={}[]|:;<>,.?/~`ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    const start = Date.now();
    const tick = () => {
      const elapsed = Date.now() - start;
      const t = Math.min(elapsed / dur, 1);
      // Number of chars locked from left to right
      const locked = Math.floor(t * target.length);
      let out = '';
      for (let i = 0; i < target.length; i++) {
        if (i < locked) out += target[i];
        else if (target[i] === ' ') out += ' ';
        else if (target[i] === '@' || target[i] === '-' || target[i] === '.') out += target[i];
        else out += chars[Math.floor(Math.random() * chars.length)];
      }
      setScrambled((s) => ({ ...s, [key]: out }));
      if (t < 1) requestAnimationFrame(tick);
    };
    tick();
  };

  // While submitting, show fake authentication log
  return (
    <section style={{ padding: '60px 24px 80px', maxWidth: 720, margin: '0 auto' }}>
      {/* terminal window header */}
      <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 16px', borderBottom:'1px solid rgba(255,255,255,0.22)', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.22)' }}>
        <span style={{ width: 10, height: 10, borderRadius: '50%', background:'#FF3344' }}></span>
        <span style={{ width: 10, height: 10, borderRadius: '50%', background:'#FFD23F' }}></span>
        <span style={{ width: 10, height: 10, borderRadius: '50%', background:'#00FF41' }}></span>
        <span style={{ marginLeft: 14, fontSize: 12, color:'#BFBFBF', letterSpacing:'0.12em' }}>operator@brew-co — /bin/auth</span>
        <span style={{ marginLeft:'auto', fontSize: 11, color:'#9A9A9A', letterSpacing:'0.18em' }}>SESSION: NEW · TLS 1.3</span>
      </div>

      <div style={{ border:'1px solid rgba(255,255,255,0.22)', borderTop:'none', padding:'36px 32px', background:'#000' }}>
        {/* IDLE — login form */}
        {phase === 'idle' && (
          <form onSubmit={submit}>
            <div style={{ fontSize: 11, color:'#00FF41', letterSpacing:'0.22em', marginBottom: 10 }}>$ ./auth --login</div>
            <h2 style={{ fontSize: 32, fontWeight: 800, color:'#FFF', letterSpacing:'0.04em', margin: '0 0 8px' }}>AUTHENTICATE</h2>
            <p style={{ fontSize: 13, color:'#BFBFBF', lineHeight: 1.6, letterSpacing:'0.04em', margin: '0 0 28px' }}>
              // identify yourself to access /account.
            </p>

            <Field label="HANDLE OR EMAIL" value={email} onChange={setEmail} placeholder="op1337 — or — operator@brew-co" autoFocus />
            <Field label="PASSWORD" value={password} onChange={setPassword} type="password" placeholder="••••••••••••" />

            {/* Turnstile captcha */}
            <div style={{ margin: '18px 0', padding: '14px', border: '1px dashed rgba(255,255,255,0.22)', background: '#0A0A0A' }}>
              <div style={{ fontSize: 10, letterSpacing: '0.2em', color: '#9A9A9A', marginBottom: 8 }}>// CAPTCHA VERIFICATION — cf-turnstile</div>
              <div id="login-turnstile"></div>
            </div>

            {err && (
              <div role="alert" style={{ marginTop: 18, padding: '10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 12, letterSpacing:'0.06em' }}>
                {err}
              </div>
            )}

            <div style={{ display:'flex', alignItems:'center', gap: 12, marginTop: 24 }}>
              <button type="submit" disabled={!turnstileToken && window.OBC_API.mode !== 'mock'} style={{
                background: (!turnstileToken && window.OBC_API.mode !== 'mock') ? '#3A3A3A' : '#00FF41',
                color:'#000', border: '1px solid ' + ((!turnstileToken && window.OBC_API.mode !== 'mock') ? '#3A3A3A' : '#00FF41'),
                padding:'14px 22px', fontFamily:'inherit', fontWeight: 800, fontSize: 13,
                letterSpacing:'0.22em', cursor: (!turnstileToken && window.OBC_API.mode !== 'mock') ? 'not-allowed' : 'pointer', borderRadius: 2,
                opacity: (!turnstileToken && window.OBC_API.mode !== 'mock') ? 0.5 : 1,
              }}>{'>'} ./execute</button>
              <a style={{ marginLeft: 'auto', fontSize: 12, color:'#BFBFBF', letterSpacing:'0.15em', cursor:'pointer' }} onClick={(e) => { e.preventDefault(); setErr('// recovery link sent — if the account exists.'); }}>
                ./forgot →
              </a>
            </div>

            <div style={{ marginTop: 28, paddingTop: 18, borderTop:'1px dashed rgba(255,255,255,0.32)', fontSize: 12, color:'#BFBFBF', lineHeight: 1.7, letterSpacing:'0.03em' }}>
              <div>// no account?</div>
              <div style={{ marginTop: 4 }}>
                $ <span onClick={onSwitchToRegister} style={{ color:'#00FF41', cursor:'pointer', textDecoration:'underline' }}>./register</span> — or — checkout once to auto-create.
              </div>
            </div>

            <p style={{ marginTop: 22, fontSize: 10, color:'#7A7A7A', letterSpacing:'0.15em', lineHeight: 1.6 }}>
              // failed attempts are rate-limited. tls everywhere. we never store passwords in plaintext.<br/>
              // <span style={{ color:'#FF3344' }}>demo:</span> use handle "<span style={{ color:'#FF3344' }}>intruder</span>" or "<span style={{ color:'#FF3344' }}>denied</span>" to simulate a failed login.
            </p>
          </form>
        )}

        {/* DENIED — big red flashing access denied */}
        {phase === 'denied' && (
          <div className="denied-shake" style={{ color:'#FF3344', fontSize: 14, lineHeight: 1.9, letterSpacing:'0.04em' }}>
            <div style={{ color:'#FF3344', fontWeight: 700 }}>$ ./auth --execute</div>
            <div>&nbsp;&nbsp;resolving identity provider ........... <span style={{ color:'#00FF41' }}>[ OK ]</span></div>
            <div>&nbsp;&nbsp;establishing TLS session .............. <span style={{ color:'#00FF41' }}>[ OK ]</span></div>
            <div>&nbsp;&nbsp;hashing credentials (argon2id) ........ <span style={{ color:'#00FF41' }}>[ OK ]</span></div>
            <div>&nbsp;&nbsp;verifying credentials ................. <span style={{ color:'#FF3344', fontWeight: 800 }}>[ FAIL ]</span></div>
            <div>&nbsp;&nbsp;triggering intrusion detection ........ <span style={{ color:'#FF3344', fontWeight: 800 }}>[ ALERT ]</span></div>

            <div style={{ marginTop: 24, padding: '24px', border:'2px solid #FF3344', background:'rgba(255,51,68,0.06)', textAlign:'center' }}>
              <span className="denied-flash">[ ACCESS DENIED ]</span>
              <div style={{ marginTop: 14, color:'#FF3344', fontSize: 13, letterSpacing:'0.18em', fontWeight: 700 }}>
                // INTRUDER DETECTED · CREDENTIALS REJECTED
              </div>
            </div>

            <div style={{ marginTop: 22, display:'grid', gridTemplateColumns:'1fr 1fr', gap: 12, fontSize: 12, color:'#BFBFBF', letterSpacing:'0.06em' }}>
              <div>// attempt #{deniedInfo.attempt} this session</div>
              <div style={{ textAlign:'right' }}>// IP: redacted</div>
              <div>// event logged to /var/log/auth.log</div>
              <div style={{ textAlign:'right' }}>// ts: {new Date().toISOString().slice(0,19)}Z</div>
            </div>

            <div style={{ marginTop: 22, padding: 14, border:'1px solid #FF3344', background:'#000', fontSize: 12, color:'#FFFFFF', letterSpacing:'0.06em', lineHeight: 1.7 }}>
              {/* generic non-enumerating message — same regardless of whether user exists */}
              // authentication failed. invalid credentials.<br/>
              // your account is not at risk if this was not you.<br/>
              // <span style={{ color:'#FFD23F' }}>cooldown: {String(Math.max(0, deniedInfo.lockout)).padStart(2,'0')}s</span> before next attempt allowed.
            </div>
          </div>
        )}

        {/* SUBMITTING — auth log animation */}
        {phase === 'submitting' && (
          <div style={{ color:'#00FF41', fontSize: 14, lineHeight: 1.9, letterSpacing:'0.04em' }}>
            <div>$ ./auth --execute</div>
            <Log>resolving identity provider ........... <Ok/></Log>
            <Log>establishing TLS session .............. <Ok/></Log>
            <Log>hashing credentials (argon2id) ........ <Ok/></Log>
            <Log>checking 2FA token .................... <Pending/></Log>
            <Log>verifying session signature ........... <Ok/></Log>
            <div style={{ marginTop: 10, color:'#BFBFBF' }}>// stand by<Cursor/></div>
          </div>
        )}

        {/* MFA — TOTP / recovery code input */}
        {phase === 'mfa' && (
          <form onSubmit={submitMfa}>
            <div style={{ fontSize: 11, color:'#FFD23F', letterSpacing: '0.22em', marginBottom: 18 }}>$ ./auth --mfa-verify</div>
            <div style={{ fontSize: 13, color:'#BFBFBF', lineHeight: 1.7, marginBottom: 20 }}>
              {'>'} session requires second factor<br/>
              {'>'} {mfaMode === 'totp'
                ? 'enter 6-digit TOTP code from authenticator app'
                : 'enter 8-character recovery code'}
            </div>

            {mfaMode === 'totp' ? (
              <div style={{ marginBottom: 18 }}>
                <div style={{ fontSize: 11, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP CODE</div>
                <input
                  value={mfaCode}
                  onChange={(e) => { setMfaCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setMfaErr(null); }}
                  maxLength={6}
                  pattern="[0-9]*"
                  inputMode="numeric"
                  autoComplete="one-time-code"
                  autoFocus
                  placeholder="000000"
                  style={{
                    width: '100%', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.28)',
                    color:'#FFF', fontFamily:'inherit', fontSize: 22, padding:'14px 14px', borderRadius: 2,
                    letterSpacing: '0.3em', textAlign: 'center',
                  }}
                  onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
                  onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
                />
              </div>
            ) : (
              <div style={{ marginBottom: 18 }}>
                <div style={{ fontSize: 11, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} RECOVERY CODE</div>
                <input
                  value={mfaCode}
                  onChange={(e) => { setMfaCode(e.target.value.toUpperCase().slice(0, 8)); setMfaErr(null); }}
                  maxLength={8}
                  autoComplete="off"
                  autoFocus
                  placeholder="ABCD1234"
                  style={{
                    width: '100%', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.28)',
                    color:'#FFF', fontFamily:'inherit', fontSize: 22, padding:'14px 14px', borderRadius: 2,
                    letterSpacing: '0.3em', textAlign: 'center',
                  }}
                  onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
                  onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
                />
              </div>
            )}

            {mfaErr && (
              <div role="alert" style={{ marginTop: 0, marginBottom: 14, padding: '10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 12, letterSpacing:'0.06em' }}>
                {mfaErr}
              </div>
            )}

            <button type="submit" disabled={mfaSubmitting} style={{
              background: mfaSubmitting ? '#3A3A3A' : '#00FF41', color:'#000', border:'1px solid ' + (mfaSubmitting ? '#3A3A3A' : '#00FF41'),
              padding:'14px 22px', fontFamily:'inherit', fontWeight: 800, fontSize: 13,
              letterSpacing:'0.22em', cursor: mfaSubmitting ? 'not-allowed' : 'pointer', borderRadius: 2,
              opacity: mfaSubmitting ? 0.5 : 1,
            }}>{mfaSubmitting ? '// verifying...' : '> ./verify'}</button>

            <div style={{ marginTop: 14 }}>
              {mfaMode === 'totp' ? (
                <a onClick={() => { setMfaMode('recovery'); setMfaCode(''); setMfaErr(null); }}
                   style={{ fontSize: 12, color:'#BFBFBF', letterSpacing:'0.08em', cursor:'pointer' }}>
                  // use recovery code instead
                </a>
              ) : (
                <a onClick={() => { setMfaMode('totp'); setMfaCode(''); setMfaErr(null); }}
                   style={{ fontSize: 12, color:'#BFBFBF', letterSpacing:'0.08em', cursor:'pointer' }}>
                  // use TOTP code instead
                </a>
              )}
            </div>
          </form>
        )}

        {/* REVEALING — scrambled identity that locks in left-to-right */}
        {(phase === 'revealing' || phase === 'granted') && (
          <div>
            <div style={{ fontSize: 11, color:'#00FF41', letterSpacing:'0.22em', marginBottom: 18 }}>$ whoami</div>
            <IdentityRow label="HANDLE" value={scrambled.handle || '████████'} accent="#00FF41" />
            <IdentityRow label="EMAIL"  value={scrambled.email  || '████████████████████'} accent="#00E5FF" />
            <IdentityRow label="TIER"   value={scrambled.tier   || '████████'} accent="#FFD23F" />
            <div style={{ marginTop: 24, fontSize: 11, color:'#BFBFBF', letterSpacing:'0.18em' }}>// session id: {Math.random().toString(36).slice(2, 14).toUpperCase()}</div>

            {phase === 'granted' && (
              <div style={{ marginTop: 28, display:'flex', alignItems:'center', gap: 12 }}>
                <span className="login-granted">[ ACCESS GRANTED ]</span>
                <span style={{ color:'#BFBFBF', fontSize: 12, letterSpacing:'0.15em' }}>→ redirecting<Cursor/></span>
              </div>
            )}
          </div>
        )}
      </div>

      {/* legal-ish strip */}
      <div style={{ marginTop: 18, fontSize: 10, color:'#7A7A7A', letterSpacing:'0.2em', textAlign:'center' }}>
        // by authenticating you agree to brew responsibly. pwn responsibly. ·
        attempts (this session): {attempts.toString().padStart(2,'0')}
      </div>

      <style>{`
        .login-granted {
          display: inline-block;
          background: #00FF41; color: #000;
          padding: 8px 16px;
          font-size: 18px; font-weight: 800; letter-spacing: 0.25em;
          box-shadow: 0 0 24px rgba(0,255,65,0.6);
          animation: grantedFlash 160ms steps(2) 5;
        }
        @keyframes grantedFlash {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.15; }
        }

        /* DENIED — big red flashing block + screen shake */
        .denied-flash {
          display: inline-block;
          background: #FF3344; color: #000;
          padding: 14px 24px;
          font-size: 28px; font-weight: 800; letter-spacing: 0.3em;
          box-shadow: 0 0 32px rgba(255,51,68,0.8), inset 0 0 0 2px rgba(255,255,255,0.2);
          animation: deniedFlash 220ms steps(2) infinite;
          text-shadow: 0 0 8px rgba(255,255,255,0.3);
        }
        @keyframes deniedFlash {
          0%, 100% { opacity: 1; background: #FF3344; color: #000; }
          50%      { opacity: 1; background: #000; color: #FF3344; box-shadow: 0 0 32px rgba(255,51,68,0.4), inset 0 0 0 2px #FF3344; }
        }

        .denied-shake { animation: deniedShake 120ms ease-out 6, deniedFadeBG 5s linear 1; }
        @keyframes deniedShake {
          0%, 100% { transform: translate(0,0); }
          25%      { transform: translate(-4px, 1px); }
          50%      { transform: translate(4px, -1px); }
          75%      { transform: translate(-3px, -2px); }
        }
        @keyframes deniedFadeBG {
          0%   { background: rgba(255,51,68,0.18); }
          12%  { background: rgba(255,51,68,0.05); }
          24%  { background: rgba(255,51,68,0.18); }
          36%  { background: rgba(255,51,68,0.05); }
          100% { background: transparent; }
        }
      `}</style>
    </section>
  );
};

const Field = ({ label, value, onChange, type='text', placeholder, autoFocus }) => (
  <div style={{ marginTop: 18 }}>
    <div style={{ fontSize: 11, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} {label}</div>
    <input
      type={type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      autoFocus={autoFocus}
      autoComplete={type === 'password' ? 'current-password' : 'username'}
      maxLength={type === 'password' ? 256 : 320}
      style={{
        width: '100%', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.28)',
        color:'#FFF', fontFamily:'inherit', fontSize: 14, padding:'12px 14px', borderRadius: 2,
      }}
      onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
      onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
    />
  </div>
);

const IdentityRow = ({ label, value, accent }) => (
  <div style={{ display:'grid', gridTemplateColumns:'120px 1fr', gap: 16, padding:'12px 0', borderBottom:'1px dashed rgba(255,255,255,0.18)' }}>
    <span style={{ fontSize: 11, color:'#BFBFBF', letterSpacing:'0.22em', fontWeight: 700 }}>{label}</span>
    <span style={{ fontSize: 16, color: accent, letterSpacing:'0.06em', fontFamily:'inherit', fontWeight: 700 }}>{value}</span>
  </div>
);

const Log = ({ children }) => <div style={{ marginTop: 4 }}>&nbsp;&nbsp;{children}</div>;
const Ok = () => <span style={{ color:'#00FF41' }}>[ OK ]</span>;
const Pending = () => <span style={{ color:'#FFD23F' }}>[OK]</span>;
const Cursor = () => <span style={{ background:'#00FF41', color:'#000', marginLeft: 4, padding:'0 4px' }}>_</span>;

window.Login = Login;
