// LOLA Consola Web — Acceso partido persistente: la presentación (con estrellas) queda
// SIEMPRE a la izquierda; a la derecha cambia el paso (Bienvenida, Login, 2FA, Recuperar,
// Cambiar contraseña). La sesión la maneja window.LOLA.api (sessionStorage, NO localStorage).
// Acceso POR INVITACIÓN: no hay registro público (las cuentas se crean en Configuración → Equipo).

const api = () => window.LOLA.api;

// Keyframes (titileo de estrellas + entrada suave del panel derecho). Se inyectan una vez.
(function injectAuthKeyframes() {
  if (typeof document === 'undefined' || document.getElementById('lola-auth-kf')) return;
  const s = document.createElement('style');
  s.id = 'lola-auth-kf';
  s.textContent =
    '@keyframes lolaTwinkle{0%,100%{opacity:.12;transform:scale(.6)}50%{opacity:1;transform:scale(1)}}' +
    '@keyframes lolaFadeUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}';
  document.head.appendChild(s);
})();

// ── Íconos locales (no están en window.WI) ──
function Eye({ size = 18 }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></svg>;
}
function EyeOff({ size = 18 }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><path d="M9.9 4.24A9.1 9.1 0 0 1 12 4c6.5 0 10 7 10 7a13.4 13.4 0 0 1-2.16 2.92M6.7 6.7A13.3 13.3 0 0 0 2 11s3.5 7 10 7a9 9 0 0 0 4.1-.98"/><path d="m1 1 22 22M9.9 9.9a3 3 0 0 0 4.2 4.2"/></svg>;
}
function ArrowR({ size = 17 }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>;
}
function Key({ size = 18 }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><circle cx="8" cy="15" r="4"/><path d="M10.8 12.2 20 3M17 6l2 2M14 9l2 2"/></svg>;
}

// ── Fondo dark centrado (solo para la pantalla de bloqueo) ──
function AuthBackdrop({ children }) {
  const t = window.WC;
  return (
    <div style={{ position: 'relative', minHeight: '100dvh', overflow: 'hidden', background: '#0A1420',
      fontFamily: t.font, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '36px 20px' }}>
      <div style={{ position: 'absolute', inset: 0, backgroundImage: 'radial-gradient(rgba(255,255,255,.05) 1px, transparent 1px)',
        backgroundSize: '30px 30px', maskImage: 'radial-gradient(circle at 50% 38%, #000 52%, transparent 100%)',
        WebkitMaskImage: 'radial-gradient(circle at 50% 38%, #000 52%, transparent 100%)' }}/>
      <div style={{ position: 'absolute', top: '-16%', left: '50%', transform: 'translateX(-50%)', width: 720, height: 720,
        borderRadius: '50%', background: 'radial-gradient(circle, rgba(29,87,169,.45), transparent 62%)', filter: 'blur(16px)', pointerEvents: 'none' }}/>
      <div style={{ position: 'relative', width: '100%', display: 'flex', justifyContent: 'center' }}>{children}</div>
    </div>
  );
}

function Brand() {
  const t = window.WC;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 13, justifyContent: 'center' }}>
      <div style={{ width: 46, height: 46, borderRadius: 15, background: `linear-gradient(158deg, ${t.brandHi}, ${t.brand})`,
        display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff',
        boxShadow: '0 12px 28px -10px rgba(29,87,169,.75), inset 0 1px 0 rgba(255,255,255,.28)' }}>
        <window.WI.Truck size={25} sw={2}/>
      </div>
      <div style={{ textAlign: 'left' }}>
        <div style={{ fontSize: 21, fontWeight: 800, letterSpacing: -.6, color: '#fff', lineHeight: 1 }}>LOLA</div>
        <div style={{ fontSize: 10.5, color: t.accent, fontFamily: t.mono, letterSpacing: 1.6, textTransform: 'uppercase', marginTop: 5 }}>Consola Admin</div>
      </div>
    </div>
  );
}

function Card({ children, style }) {
  return <div style={{ background: '#fff', borderRadius: 20, padding: '30px 30px 26px',
    boxShadow: '0 34px 80px -26px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.18)',
    border: '1px solid rgba(255,255,255,.6)', ...style }}>{children}</div>;
}

// ── Campo con ícono, foco animado y mostrar/ocultar ──
function Field({ t, label, type, value, onChange, autoFocus, onEnter, placeholder, icon, mono }) {
  const [show, setShow] = React.useState(false);
  const [foc, setFoc] = React.useState(false);
  const isPass = type === 'password';
  const Icn = icon ? window.WI[icon] : null;
  return (
    <label style={{ display: 'block', marginBottom: 14 }}>
      <span style={{ display: 'block', fontSize: 11, color: t.sec, fontFamily: t.mono, textTransform: 'uppercase',
        letterSpacing: .8, fontWeight: 700, marginBottom: 7 }}>{label}</span>
      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', borderRadius: 11, background: '#fff',
        border: `1.5px solid ${foc ? t.brand : t.border}`, boxShadow: foc ? '0 0 0 4px rgba(29,87,169,.12)' : 'none',
        transition: 'border-color .15s, box-shadow .15s' }}>
        {Icn && <span style={{ paddingLeft: 13, color: foc ? t.brand : t.ter, display: 'flex' }}><Icn size={18}/></span>}
        <input type={isPass && show ? 'text' : (type || 'text')} value={value} autoFocus={autoFocus} placeholder={placeholder || ''}
          onFocus={() => setFoc(true)} onBlur={() => setFoc(false)}
          onChange={e => onChange(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter' && onEnter) onEnter(); }}
          style={{ flex: 1, minWidth: 0, border: 'none', outline: 'none', background: 'transparent',
            padding: Icn ? '13px 12px' : '13px 14px', fontFamily: (isPass || mono) ? t.mono : t.font, fontSize: 14.5, color: t.text }}/>
        {isPass && (
          <button type="button" tabIndex={-1} onClick={() => setShow(s => !s)}
            style={{ padding: '0 13px', background: 'none', border: 'none', cursor: 'pointer', color: t.ter, display: 'flex', alignItems: 'center' }}>
            {show ? <EyeOff/> : <Eye/>}
          </button>
        )}
      </div>
    </label>
  );
}

function Btn({ t, children, onClick, disabled, kind }) {
  const [h, setH] = React.useState(false);
  const primary = kind !== 'ghost';
  return (
    <button onClick={onClick} disabled={disabled} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{ width: '100%', padding: '14px 0', borderRadius: 12, border: 'none', cursor: disabled ? 'default' : 'pointer',
        background: primary ? (h && !disabled ? t.brandHi : t.brand) : 'transparent', color: primary ? '#fff' : t.brand,
        fontFamily: t.font, fontSize: 14.5, fontWeight: 700, opacity: disabled ? .55 : 1,
        boxShadow: primary ? '0 12px 26px -12px rgba(29,87,169,.85)' : 'none',
        transform: h && !disabled && primary ? 'translateY(-1px)' : 'none', transition: 'background .15s, transform .12s',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>{children}</button>
  );
}

function OutlineBtn({ t, children, onClick }) {
  return (
    <button onClick={onClick} style={{ width: '100%', marginTop: 12, padding: '14px 0', borderRadius: 12, cursor: 'pointer',
      border: `1.5px solid ${t.border}`, background: '#fff', color: t.text, fontFamily: t.font, fontSize: 14.5, fontWeight: 700,
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>{children}</button>
  );
}

function TextLink({ t, children, onClick, color }) {
  return <button onClick={onClick} style={{ background: 'none', border: 'none', color: color || t.brand, fontFamily: t.mono,
    fontSize: 12, fontWeight: 700, letterSpacing: .6, textTransform: 'uppercase', cursor: 'pointer', padding: 4 }}>{children}</button>;
}

function ErrBox({ t, children }) {
  if (!children) return null;
  return <div style={{ background: '#FDF0EF', border: '1px solid #F2C4C0', color: t.danger, fontSize: 13,
    padding: '10px 13px', borderRadius: 10, marginBottom: 14 }}>{children}</div>;
}

function Footer({ t }) {
  return <div style={{ textAlign: 'center', marginTop: 20, fontSize: 11.5, color: 'rgba(255,255,255,.34)', fontFamily: t.mono }}>
    LOLA Logística S.A. · Acceso restringido
  </div>;
}

function Eyebrow({ t, children }) {
  return <div style={{ fontSize: 12, fontFamily: t.mono, fontWeight: 700, letterSpacing: 1, textTransform: 'uppercase', color: t.brand, marginBottom: 12 }}>{children}</div>;
}
function Title({ t, children }) {
  return <div style={{ fontSize: 27, fontWeight: 800, letterSpacing: -.6, color: t.text, lineHeight: 1.1 }}>{children}</div>;
}
function Sub({ t, children }) {
  return <div style={{ fontSize: 14, color: t.ter, marginTop: 8, marginBottom: 26, lineHeight: 1.5 }}>{children}</div>;
}
function BackLink({ t, onClick, children }) {
  return <div style={{ marginTop: 18 }}><TextLink t={t} color={t.ter} onClick={onClick}>{children || '← Volver a la bienvenida'}</TextLink></div>;
}

// ── Marco partido persistente: izquierda fija (presentación con estrellas), derecha cambiante ──
function AuthSplit({ t, screenKey, children }) {
  const isMobile = window.useIsMobile(880);
  const caps = [
    { i: 'Check', l: 'Aprobaciones', d: 'Autoriza contratos de clientes y transportistas' },
    { i: 'Wallet', l: 'Comisiones', d: 'Ingresos de la plataforma por categoría' },
    { i: 'Users', l: 'Usuarios', d: 'Gestión de clientes y proveedores' },
    { i: 'Book', l: 'Bitácora', d: 'Registro de accesos y auditoría' },
  ];
  const stars = React.useMemo(() => {
    const arr = [];
    for (let i = 0; i < 60; i++) {
      const r = Math.random();
      arr.push({
        top: (Math.random() * 100).toFixed(2),
        left: (Math.random() * 100).toFixed(2),
        size: r < 0.12 ? 3 : (r < 0.5 ? 1.4 : 2),
        op: (0.35 + Math.random() * 0.65).toFixed(2),
        dur: (2.4 + Math.random() * 3.4).toFixed(2),
        delay: (Math.random() * 5).toFixed(2),
      });
    }
    return arr;
  }, []);

  return (
    <div style={{ position: 'fixed', inset: 0, display: 'flex', fontFamily: t.font, background: '#0A1420',
      flexDirection: isMobile ? 'column' : 'row', overflowY: isMobile ? 'auto' : 'hidden' }}>

      {/* IZQUIERDA — presentación con estrellas (FIJA) */}
      <div style={{ position: 'relative', overflow: 'hidden', color: '#fff',
        flex: isMobile ? '0 0 auto' : '1.05', display: 'flex', alignItems: 'center',
        padding: isMobile ? '44px 30px 42px' : '64px 6vw',
        background: 'linear-gradient(158deg, #2E6EC4 0%, #1D57A9 48%, #123A6B 100%)' }}>

        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
          {stars.map((s, i) => (
            <span key={i} style={{ position: 'absolute', top: s.top + '%', left: s.left + '%',
              width: s.size, height: s.size, borderRadius: '50%', background: '#fff', opacity: s.op,
              boxShadow: s.size >= 3 ? '0 0 7px 1px rgba(255,255,255,.85)' : 'none',
              animation: 'lolaTwinkle ' + s.dur + 's ease-in-out ' + s.delay + 's infinite' }}/>
          ))}
        </div>
        <div style={{ position: 'absolute', top: -130, right: -90, width: 360, height: 360, borderRadius: '50%',
          background: 'radial-gradient(circle, rgba(244,199,30,.22), transparent 62%)', filter: 'blur(8px)', pointerEvents: 'none' }}/>
        <div style={{ position: 'absolute', bottom: -150, left: -130, width: 400, height: 400, borderRadius: '50%',
          background: 'radial-gradient(circle, rgba(46,110,196,.45), transparent 60%)', filter: 'blur(10px)', pointerEvents: 'none' }}/>
        <svg viewBox="0 0 600 800" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', opacity: .22, pointerEvents: 'none' }}>
          <path d="M-40 640 C 160 540, 240 340, 440 270 S 660 90, 700 30" fill="none" stroke="rgba(255,255,255,.6)" strokeWidth="1.5" strokeDasharray="2 11" strokeLinecap="round"/>
        </svg>

        <div style={{ position: 'relative', width: '100%', maxWidth: 470, margin: isMobile ? '0 auto' : '0 0 0 auto' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 13, marginBottom: isMobile ? 22 : 36 }}>
            <div style={{ width: 50, height: 50, borderRadius: 14, background: 'rgba(255,255,255,.16)', border: '1px solid rgba(255,255,255,.28)',
              display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}><window.WI.Truck size={27} sw={2}/></div>
            <div>
              <div style={{ fontSize: 23, fontWeight: 800, letterSpacing: -.5, lineHeight: 1 }}>LOLA</div>
              <div style={{ fontSize: 11, color: '#F4C71E', fontFamily: t.mono, letterSpacing: 1.7, textTransform: 'uppercase', marginTop: 5 }}>Consola Admin</div>
            </div>
          </div>

          <h1 style={{ fontSize: isMobile ? 28 : 37, lineHeight: 1.1, fontWeight: 800, letterSpacing: -1, margin: '0 0 16px' }}>
            Toda la operación de LOLA, en un <span style={{ color: '#F4C71E' }}>solo lugar</span>
          </h1>
          <p style={{ fontSize: 15, lineHeight: 1.6, color: 'rgba(255,255,255,.76)', margin: '0 0 30px', maxWidth: 410 }}>
            El panel de control para aprobar, medir y administrar la plataforma de carga.
          </p>

          {!isMobile && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 15 }}>
              {caps.map(c => {
                const Icn = window.WI[c.i];
                return (
                  <div key={c.l} style={{ display: 'flex', alignItems: 'flex-start', gap: 13 }}>
                    <div style={{ flexShrink: 0, width: 36, height: 36, borderRadius: 11, background: 'rgba(255,255,255,.12)', border: '1px solid rgba(255,255,255,.18)',
                      display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#F4C71E' }}><Icn size={18}/></div>
                    <div>
                      <div style={{ fontSize: 14.5, fontWeight: 700 }}>{c.l}</div>
                      <div style={{ fontSize: 12.5, color: 'rgba(255,255,255,.64)', lineHeight: 1.4 }}>{c.d}</div>
                    </div>
                  </div>
                );
              })}
            </div>
          )}

          <div style={{ marginTop: isMobile ? 8 : 40, fontSize: 11.5, color: 'rgba(255,255,255,.5)', fontFamily: t.mono, letterSpacing: .4 }}>
            LOLA Logística S.A. · A donde vayas yo voy
          </div>
        </div>
      </div>

      {/* DERECHA — contenido cambiante */}
      <div style={{ position: 'relative', background: '#fff', flex: isMobile ? '1 0 auto' : '0.95',
        display: 'flex', flexDirection: 'column', justifyContent: 'center',
        padding: isMobile ? '38px 28px 46px' : '56px 6vw', overflowY: 'auto' }}>
        <div key={screenKey} style={{ width: '100%', maxWidth: 384, margin: isMobile ? '0 auto' : '0 auto 0 0',
          animation: 'lolaFadeUp .28s ease' }}>
          {children}
        </div>
      </div>
    </div>
  );
}

// ── Derecha: Bienvenida (acciones) ──
function WelcomeRight({ t, onLogin, onChange }) {
  return (
    <React.Fragment>
      <Eyebrow t={t}>Bienvenido</Eyebrow>
      <Title t={t}>Ingresa a la consola</Title>
      <Sub t={t}>Elige cómo quieres continuar.</Sub>
      <Btn t={t} onClick={onLogin}>Iniciar sesión <ArrowR/></Btn>
      <OutlineBtn t={t} onClick={onChange}><span style={{ color: t.brand, display: 'flex' }}><Key size={18}/></span> Cambiar contraseña</OutlineBtn>
      <div style={{ height: 1, background: t.grid, margin: '26px 0 16px' }}/>
      <div style={{ fontSize: 12.5, color: t.sec, lineHeight: 1.55 }}>
        Acceso <b style={{ color: t.text }}>por invitación</b>. Las cuentas se crean en <span style={{ fontFamily: t.mono, color: t.brand }}>Configuración → Equipo</span>.
      </div>
      <div style={{ marginTop: 8, fontFamily: t.mono, fontSize: 11.5, color: t.ter }}>Demo: admin@lola.gt · Admin123*</div>
    </React.Fragment>
  );
}

// ── Derecha: Login (real) ──
function LoginRight({ t, onOk, onRecover, onChange, onNeed2FA, onBack }) {
  // Demo: credenciales del seed precargadas para probar sin escribir nada.
  const [email, setEmail] = React.useState('admin@lola.gt');
  const [pass, setPass] = React.useState('Admin123*');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);

  const entrar = async () => {
    setErr('');
    if (!email.trim() || !pass) { setErr('Escribe tu correo y contraseña.'); return; }
    setBusy(true);
    try {
      const r = await api().login(email.trim().toLowerCase(), pass);
      if (r.need2FA) { onNeed2FA(r.email, r.devCode); return; }
      onOk();
    } catch (e) {
      setErr(e.status === 0 || e.message === 'Failed to fetch'
        ? 'No hay conexión con el servidor. ¿Está corriendo la API?'
        : (e.code === 'BAD_CREDENTIALS' ? 'Credenciales incorrectas.' : (e.message || 'No se pudo iniciar sesión.')));
      setBusy(false);
    }
  };

  return (
    <React.Fragment>
      <Eyebrow t={t}>Bienvenido</Eyebrow>
      <Title t={t}>Inicia sesión</Title>
      <Sub t={t}>Ingresa con tu cuenta de administrador.</Sub>
      <Field t={t} label="Correo" value={email} onChange={setEmail} autoFocus onEnter={entrar} placeholder="tu@lola.gt" icon="Mail"/>
      <Field t={t} label="Contraseña" type="password" value={pass} onChange={setPass} onEnter={entrar} placeholder="••••••••" icon="Shield"/>
      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: -2, marginBottom: 16 }}>
        <TextLink t={t} onClick={onRecover}>¿Olvidaste tu contraseña?</TextLink>
      </div>
      <ErrBox t={t}>{err}</ErrBox>
      <Btn t={t} onClick={entrar} disabled={busy}>{busy ? 'Verificando…' : 'Entrar a la consola'}{!busy && <ArrowR/>}</Btn>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, margin: '18px 0 4px' }}>
        <span style={{ flex: 1, height: 1, background: t.grid }}/>
        <span style={{ fontSize: 11, color: t.ter, fontFamily: t.mono }}>o</span>
        <span style={{ flex: 1, height: 1, background: t.grid }}/>
      </div>
      <OutlineBtn t={t} onClick={onChange}><span style={{ color: t.brand, display: 'flex' }}><Key size={18}/></span> Cambiar contraseña</OutlineBtn>
      <BackLink t={t} onClick={onBack}/>
    </React.Fragment>
  );
}

// ── Derecha: 2FA ──
function TwoFactorRight({ t, email, devCode, onOk, onBack }) {
  const [code, setCode] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);

  const verificar = async () => {
    setErr('');
    if (code.trim().length < 6) { setErr('Ingresa el código de 6 dígitos.'); return; }
    setBusy(true);
    try { await api().verify2FA(email, code.trim()); onOk(); }
    catch (e) { setErr(e.code === 'CODE_EXPIRED' ? 'El código expiró. Vuelve a iniciar sesión.' : 'Código incorrecto.'); setBusy(false); }
  };

  return (
    <React.Fragment>
      <div style={{ width: 50, height: 50, borderRadius: 14, background: 'rgba(29,87,169,.1)', color: t.brand,
        display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16 }}><window.WI.Shield size={24}/></div>
      <Title t={t}>Verificación en dos pasos</Title>
      <Sub t={t}>Enviamos un código de 6 dígitos a <span style={{ fontFamily: t.mono, color: t.text }}>{email}</span>.</Sub>
      <Field t={t} label="Código de verificación" value={code} onChange={(v) => setCode(v.replace(/\D/g, '').slice(0, 6))}
        autoFocus onEnter={verificar} placeholder="000000" mono/>
      {devCode && <div style={{ marginTop: -6, marginBottom: 12, fontSize: 12, color: t.accentDk, fontFamily: t.mono }}>
        Código de desarrollo: <b>{devCode}</b> (solo aparece fuera de producción)
      </div>}
      <ErrBox t={t}>{err}</ErrBox>
      <Btn t={t} onClick={verificar} disabled={busy}>{busy ? 'Verificando…' : 'Verificar y entrar'}</Btn>
      <BackLink t={t} onClick={onBack} children="← Volver al inicio de sesión"/>
    </React.Fragment>
  );
}

// ── Derecha: Recuperar contraseña (real) ──
function RecoverRight({ t, onBack }) {
  const [email, setEmail] = React.useState('');
  const [sent, setSent] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  const enviar = async () => {
    if (!email.trim() || busy) return;
    setErr(''); setBusy(true);
    try { await api().recuperar(email.trim().toLowerCase()); setSent(true); }
    catch (e) {
      // El backend responde igual exista o no la cuenta (no confirma por respuesta); solo
      // mostramos error ante un problema real de conexión/servidor.
      setErr(e.status === 0 || e.message === 'Failed to fetch'
        ? 'No hay conexión con el servidor. ¿Está corriendo la API?' : (e.message || 'No se pudo enviar el enlace.'));
    }
    setBusy(false);
  };

  return (
    <React.Fragment>
      {!sent ? (
        <React.Fragment>
          <div style={{ width: 50, height: 50, borderRadius: 14, background: 'rgba(29,87,169,.1)', color: t.brand,
            display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16 }}><window.WI.Mail size={24}/></div>
          <Title t={t}>Recuperar contraseña</Title>
          <Sub t={t}>Escribe el correo de tu cuenta y te enviaremos un enlace para restablecerla.</Sub>
          <Field t={t} label="Correo" value={email} onChange={setEmail} autoFocus onEnter={enviar} placeholder="tu@lola.gt" icon="Mail"/>
          <ErrBox t={t}>{err}</ErrBox>
          <Btn t={t} onClick={enviar} disabled={!email.trim() || busy}>{busy ? 'Enviando…' : 'Enviar enlace'}</Btn>
        </React.Fragment>
      ) : (
        <div style={{ textAlign: 'center', padding: '4px 0' }}>
          <div style={{ width: 54, height: 54, borderRadius: '50%', background: 'rgba(31,138,91,.1)', color: t.success,
            display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}><window.WI.Check size={26}/></div>
          <div style={{ fontSize: 18, fontWeight: 800, color: t.text }}>Revisa tu correo</div>
          <div style={{ fontSize: 13.5, color: t.ter, marginTop: 6, lineHeight: 1.55 }}>
            Si <span style={{ fontFamily: t.mono, color: t.text }}>{email}</span> tiene una cuenta,
            recibirá un enlace para restablecer la contraseña.
          </div>
        </div>
      )}
      <BackLink t={t} onClick={onBack} children="← Volver al inicio de sesión"/>
    </React.Fragment>
  );
}

// ── Derecha: Restablecer contraseña (desde el enlace del correo, ?reset=token) ──
function ResetPasswordRight({ t, token, onDone }) {
  const [nueva, setNueva] = React.useState('');
  const [conf, setConf] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);

  const guardar = async () => {
    setErr('');
    if (nueva.length < 8) { setErr('La contraseña debe tener al menos 8 caracteres.'); return; }
    if (nueva !== conf) { setErr('Las contraseñas no coinciden.'); return; }
    setBusy(true);
    try { await api().resetPassword(token, nueva); setDone(true); }
    catch (e) {
      setErr(e.code === 'RESET_INVALID' ? 'El enlace es inválido o ya expiró. Solicita uno nuevo.' : (e.message || 'No se pudo restablecer la contraseña.'));
      setBusy(false);
    }
  };

  if (done) {
    return (
      <div style={{ textAlign: 'center', padding: '4px 0' }}>
        <div style={{ width: 54, height: 54, borderRadius: '50%', background: 'rgba(31,138,91,.1)', color: t.success,
          display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}><window.WI.Check size={26}/></div>
        <div style={{ fontSize: 18, fontWeight: 800, color: t.text }}>Contraseña actualizada</div>
        <div style={{ fontSize: 13.5, color: t.ter, marginTop: 6, marginBottom: 20, lineHeight: 1.55 }}>
          Ya puedes iniciar sesión con tu nueva contraseña.
        </div>
        <Btn t={t} onClick={onDone}>Ir al inicio de sesión</Btn>
      </div>
    );
  }

  return (
    <React.Fragment>
      <div style={{ width: 50, height: 50, borderRadius: 14, background: 'rgba(29,87,169,.1)', color: t.brand,
        display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16 }}><Key size={24}/></div>
      <Title t={t}>Elige una nueva contraseña</Title>
      <Sub t={t}>Tu enlace de restablecimiento es válido por 30 minutos.</Sub>
      <Field t={t} label="Nueva contraseña" type="password" value={nueva} onChange={(v) => { setNueva(v); setErr(''); }} autoFocus placeholder="Mínimo 8 caracteres" icon="Key"/>
      <Field t={t} label="Confirmar contraseña" type="password" value={conf} onChange={(v) => { setConf(v); setErr(''); }} onEnter={guardar} placeholder="••••••••" icon="Key"/>
      <ErrBox t={t}>{err}</ErrBox>
      <Btn t={t} onClick={guardar} disabled={busy}>{busy ? 'Guardando…' : 'Restablecer contraseña'}</Btn>
    </React.Fragment>
  );
}

// ── Derecha: Cambiar contraseña ──
function ChangePasswordRight({ t, onBack }) {
  const [email, setEmail] = React.useState('');
  const [actual, setActual] = React.useState('');
  const [nueva, setNueva] = React.useState('');
  const [conf, setConf] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);

  const score = (p) => {
    let s = 0;
    if (p.length >= 8) s++;
    if (/[A-Z]/.test(p) && /[a-z]/.test(p)) s++;
    if (/[0-9]/.test(p)) s++;
    if (/[^A-Za-z0-9]/.test(p)) s++;
    return s;
  };
  const sc = nueva ? score(nueva) : 0;
  const scLabel = ['Muy débil', 'Débil', 'Aceptable', 'Fuerte', 'Excelente'][sc];
  const scColor = [t.danger, t.danger, t.warn, t.success, t.success][sc];

  const guardar = async () => {
    setErr('');
    if (!email.trim() || !actual || !nueva) { setErr('Completa todos los campos.'); return; }
    if (nueva.length < 8) { setErr('La nueva contraseña debe tener al menos 8 caracteres.'); return; }
    if (nueva === actual) { setErr('La nueva contraseña debe ser distinta a la actual.'); return; }
    if (nueva !== conf) { setErr('Las contraseñas no coinciden.'); return; }
    setBusy(true);
    try {
      if (api().changePassword) await api().changePassword(email.trim().toLowerCase(), actual, nueva);
      setDone(true);
    } catch (e) {
      setErr(e.status === 0 || e.message === 'Failed to fetch'
        ? 'No hay conexión con el servidor. ¿Está corriendo la API?'
        : (e.code === 'BAD_CREDENTIALS' ? 'La contraseña actual es incorrecta.' : (e.message || 'No se pudo cambiar la contraseña.')));
      setBusy(false);
    }
  };

  if (done) {
    return (
      <div style={{ textAlign: 'center', padding: '4px 0' }}>
        <div style={{ width: 54, height: 54, borderRadius: '50%', background: 'rgba(31,138,91,.1)', color: t.success,
          display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}><window.WI.Check size={26}/></div>
        <div style={{ fontSize: 18, fontWeight: 800, color: t.text }}>Contraseña actualizada</div>
        <div style={{ fontSize: 13.5, color: t.ter, marginTop: 6, marginBottom: 20, lineHeight: 1.55 }}>
          Ya puedes iniciar sesión con tu nueva contraseña.
        </div>
        <Btn t={t} onClick={onBack}>Ir al inicio de sesión</Btn>
      </div>
    );
  }

  return (
    <React.Fragment>
      <div style={{ width: 50, height: 50, borderRadius: 14, background: 'rgba(29,87,169,.1)', color: t.brand,
        display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16 }}><Key size={24}/></div>
      <Title t={t}>Cambiar contraseña</Title>
      <Sub t={t}>Confirma tu contraseña actual y define una nueva.</Sub>
      <Field t={t} label="Correo" value={email} onChange={setEmail} autoFocus placeholder="tu@lola.gt" icon="Mail"/>
      <Field t={t} label="Contraseña actual" type="password" value={actual} onChange={setActual} placeholder="••••••••" icon="Shield"/>
      <Field t={t} label="Nueva contraseña" type="password" value={nueva} onChange={(v) => { setNueva(v); setErr(''); }} placeholder="Mínimo 8 caracteres" icon="Key"/>
      {nueva && (
        <div style={{ marginTop: -6, marginBottom: 14 }}>
          <div style={{ display: 'flex', gap: 4 }}>
            {[0, 1, 2, 3].map(i => (
              <span key={i} style={{ flex: 1, height: 4, borderRadius: 3, background: i < sc ? scColor : t.grid, transition: 'background .2s' }}/>
            ))}
          </div>
          <div style={{ fontSize: 11.5, color: scColor, fontFamily: t.mono, marginTop: 6, fontWeight: 700 }}>Seguridad: {scLabel}</div>
        </div>
      )}
      <Field t={t} label="Confirmar nueva contraseña" type="password" value={conf} onChange={(v) => { setConf(v); setErr(''); }} onEnter={guardar} placeholder="••••••••" icon="Key"/>
      <ErrBox t={t}>{err}</ErrBox>
      <Btn t={t} onClick={guardar} disabled={busy}>{busy ? 'Guardando…' : 'Actualizar contraseña'}</Btn>
      <BackLink t={t} onClick={onBack} children="← Volver al inicio de sesión"/>
    </React.Fragment>
  );
}

// ── Pantalla de bloqueo (sesión iniciada pero bloqueada) ──
function LockView({ t, session, onUnlock, onLogout }) {
  const [pass, setPass] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const nombre = (session.user && session.user.nombre) || 'Administrador';
  const mail = (session.user && session.user.email) || '';
  const iniciales = window.LOLA.map.iniciales(nombre);

  const desbloquear = async () => {
    if (!pass) return;
    setBusy(true); setErr('');
    try {
      await api().login(mail, pass);
      api().unlock(); onUnlock();
    } catch (e) { setErr('Contraseña incorrecta.'); setBusy(false); }
  };

  return (
    <div style={{ width: '100%', maxWidth: 424 }}>
      <div style={{ marginBottom: 22 }}><Brand/></div>
      <Card style={{ textAlign: 'center' }}>
        <div style={{ width: 64, height: 64, borderRadius: '50%', background: `linear-gradient(158deg, ${t.brandHi}, ${t.brand})`, color: '#fff',
          margin: '0 auto 12px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 800, fontFamily: t.mono, fontSize: 22,
          boxShadow: '0 12px 28px -10px rgba(29,87,169,.75)' }}>{iniciales}</div>
        <div style={{ fontSize: 18, fontWeight: 800, color: t.text }}>{nombre}</div>
        <div style={{ fontSize: 12.5, color: t.ter, fontFamily: t.mono, marginBottom: 6 }}>{mail}</div>
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: t.sec, fontFamily: t.mono,
          textTransform: 'uppercase', letterSpacing: .8, fontWeight: 700, marginBottom: 18 }}>
          <window.WI.Shield size={13}/> Sesión bloqueada
        </div>
        <div style={{ textAlign: 'left' }}>
          <Field t={t} label="Contraseña" type="password" value={pass} onChange={v => { setPass(v); setErr(''); }}
            autoFocus onEnter={desbloquear} placeholder="••••••••" icon="Shield"/>
        </div>
        <ErrBox t={t}>{err}</ErrBox>
        <Btn t={t} onClick={desbloquear} disabled={busy || !pass}>{busy ? 'Verificando…' : 'Desbloquear'}</Btn>
        <div style={{ marginTop: 14 }}><TextLink t={t} color={t.ter} onClick={onLogout}>¿No eres tú? Cambiar de cuenta</TextLink></div>
      </Card>
      <Footer t={t}/>
    </div>
  );
}

// ── Compuerta principal ──
function AuthGate() {
  const t = window.WC;
  const [, force] = React.useReducer((x) => x + 1, 0);
  // Enlace de restablecimiento (?reset=TOKEN) llegado por correo: entra directo a esa pantalla.
  const resetToken = React.useMemo(() => new URLSearchParams(location.search).get('reset'), []);
  const [screen, setScreen] = React.useState(() => resetToken ? 'reset' : 'welcome'); // welcome | login | twofa | recover | reset | change
  const [twoFA, setTwoFA] = React.useState({ email: '', devCode: null });
  const session = api().session();

  React.useEffect(() => {
    window.__lolaLock = () => { api().lock(); force(); };
    window.__lolaLogout = async () => { await api().logout(); setScreen('welcome'); force(); };
    window.__lolaRerender = () => force();
    return () => { delete window.__lolaLock; delete window.__lolaLogout; delete window.__lolaRerender; };
  }, []);

  const salirDeReset = () => {
    try { history.replaceState(null, '', location.pathname + location.hash); } catch (e) {}
    setScreen('login');
  };

  if (!session || !session.accessToken) {
    let right = null;
    if (screen === 'login') right = <LoginRight t={t} onOk={() => force()} onRecover={() => setScreen('recover')}
      onChange={() => setScreen('change')} onBack={() => setScreen('welcome')}
      onNeed2FA={(email, devCode) => { setTwoFA({ email, devCode }); setScreen('twofa'); }}/>;
    else if (screen === 'twofa') right = <TwoFactorRight t={t} email={twoFA.email} devCode={twoFA.devCode}
      onOk={() => { setScreen('login'); force(); }} onBack={() => setScreen('login')}/>;
    else if (screen === 'recover') right = <RecoverRight t={t} onBack={() => setScreen('login')}/>;
    else if (screen === 'reset') right = <ResetPasswordRight t={t} token={resetToken} onDone={salirDeReset}/>;
    else if (screen === 'change') right = <ChangePasswordRight t={t} onBack={() => setScreen('login')}/>;
    else right = <WelcomeRight t={t} onLogin={() => setScreen('login')} onChange={() => setScreen('change')}/>;
    return <AuthSplit t={t} screenKey={screen}>{right}</AuthSplit>;
  }
  if (session.locked) {
    return <AuthBackdrop><LockView t={t} session={session} onUnlock={() => force()} onLogout={() => window.__lolaLogout()}/></AuthBackdrop>;
  }
  return <window.ConsoleApp/>;
}

window.AuthGate = AuthGate;
