// SEIS+ Internals — login gate. Persists session to localStorage.

const LOGIN_STORAGE = "seis_login_session";
const TURNSTILE_SITE_KEY = "0x4AAAAAADEgqMHW3UNgpz2f";

function LoginScreen({ onAuth, theme, onToggleTheme, onSwitchMode }) {
  const [handle, setHandle] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [err, setErr] = React.useState("");
  const [shake, setShake] = React.useState(false);
  const [stage, setStage] = React.useState("idle"); // idle | auth | granted
  const [tick, setTick] = React.useState(0);
  const [tsToken, setTsToken] = React.useState("");
  const tsContainerRef = React.useRef(null);
  const tsWidgetIdRef = React.useRef(null);

  React.useEffect(() => {
    const id = setInterval(() => setTick(t => t + 1), 1000);
    return () => clearInterval(id);
  }, []);

  React.useEffect(() => {
    const tryRender = () => {
      if (!tsContainerRef.current) return;
      if (!window.turnstile) { setTimeout(tryRender, 100); return; }
      if (tsWidgetIdRef.current != null) return;
      tsWidgetIdRef.current = window.turnstile.render(tsContainerRef.current, {
        sitekey: TURNSTILE_SITE_KEY,
        callback: (token) => setTsToken(token),
        "expired-callback": () => setTsToken(""),
        "error-callback": () => setTsToken(""),
        theme: "light",
      });
    };
    tryRender();
    return () => {
      if (window.turnstile && tsWidgetIdRef.current != null) {
        window.turnstile.remove(tsWidgetIdRef.current);
        tsWidgetIdRef.current = null;
      }
    };
  }, []);

  const resetTurnstile = () => {
    if (window.turnstile && tsWidgetIdRef.current != null) {
      window.turnstile.reset(tsWidgetIdRef.current);
    }
    setTsToken("");
  };

  const submit = async (e) => {
    e.preventDefault();
    if (!tsToken) { setErr("COMPLETE THE VERIFICATION BELOW"); return; }
    try {
      const r = await fetch("/api/auth/login", {
        method: "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ handle: handle.trim().toLowerCase(), password, cf_turnstile_response: tsToken }),
      });
      if (!r.ok) {
        setErr("ACCESS DENIED · UNKNOWN HANDLE OR PASSWORD");
        setShake(true);
        setTimeout(() => setShake(false), 420);
        resetTurnstile();
        return;
      }
      const member = await r.json();
      setErr("");
      setStage("auth");
      setTimeout(() => setStage("granted"), 1200);
      setTimeout(() => { window.history.replaceState({}, "", "/"); onAuth(member); }, 2100);
    } catch {
      setErr("CONNECTION ERROR · TRY AGAIN");
      setShake(true);
      setTimeout(() => setShake(false), 420);
      resetTurnstile();
    }
  };

  const now = new Date();
  const time = now.toUTCString().slice(17, 25);
  const dateStr = now.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" }).toUpperCase();

  return (
    <div style={{
      position: "fixed", inset: 0,
      background: "var(--bg)",
      color: "var(--ink)",
      zIndex: 1000,
      display: "flex", flexDirection: "column",
      fontFamily: "var(--mono)",
    }}>
      {/* top status strip */}
      <div style={{
        padding: "10px 28px",
        borderBottom: "1px solid var(--ink)",
        fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase",
        display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 24,
        alignItems: "center",
        color: "var(--muted)",
      }}>
        <span style={{ justifySelf: "start" }}>Internal Tools</span>
        <span style={{ textAlign: "center", justifySelf: "center" }}>{dateStr}</span>
        <span className="row gap-12" style={{ alignItems: "center", justifySelf: "end" }}>
          <span>UTC {time}</span>
          {onToggleTheme && (
            <button
              onClick={onToggleTheme}
              title={theme === "dark" ? "switch to day" : "switch to night"}
              aria-label="toggle theme"
              style={{
                cursor: "pointer", color: "var(--ink)", fontSize: 16, lineHeight: 1,
                padding: "2px 6px", border: "1px solid var(--rule-soft)", borderRadius: 999,
              }}
            >{theme === "dark" ? "☼" : "☽"}</button>
          )}
        </span>
      </div>

      {/* center */}
      <div style={{
        flex: 1,
        display: "grid",
        gridTemplateColumns: "1.1fr 1fr",
        gap: 0,
      }}>
        {/* LEFT — masthead */}
        <div style={{ padding: "60px 56px", display: "flex", flexDirection: "column", justifyContent: "space-between", borderRight: "1px solid var(--ink)" }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)" }}>VOL.01 · ISSUE 117 · 2026.04</div>
            <div style={{
              fontFamily: "var(--mono)", fontWeight: 700,
              fontSize: "clamp(56px, 7vw, 110px)",
              lineHeight: 0.92, letterSpacing: "-0.02em",
              marginTop: 28,
            }}>
              INTERNALS<span style={{ color: "var(--accent)" }}>+</span><br/>
              <span style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontWeight: 300 }}>studio access.</span>
            </div>
            <div style={{ marginTop: 32, maxWidth: 460, fontSize: 13, color: "var(--ink-2)", lineHeight: 1.55 }}>
              Restricted terminal for SEIS+ studio operations. Budgets, model intelligence, EC2 spot fleet, internal links — for members only.
            </div>
          </div>

          <div style={{ marginTop: 60, fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--muted)" }}>
            <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: "6px 16px" }}>
              <span>STATUS</span>     <b style={{ color: "var(--accent)" }}>● TERMINAL ARMED</b>
              <span>NODE</span>       <b style={{ color: "var(--ink)" }}>seis-internals-01</b>
              <span>LATITUDE</span>   <b style={{ color: "var(--ink)" }}>00°00'N · PLANET EARTH</b>
              <span>SESSION</span>    <b style={{ color: "var(--ink)" }}>{Math.floor(tick / 1).toString(16).padStart(4,"0").toUpperCase()}-{Math.floor(Date.now()/1e7).toString(16).slice(-4).toUpperCase()}</b>
            </div>
          </div>
        </div>

        {/* RIGHT — login form */}
        <div style={{
          padding: "60px 56px",
          display: "flex", flexDirection: "column", justifyContent: "center",
          background: "var(--paper)",
        }}>
          <div className="micro" style={{ color: "var(--muted)" }}>§ AUTH-001</div>
          <div style={{
            fontFamily: "var(--serif)", fontStyle: "italic", fontWeight: 300,
            fontSize: 38, lineHeight: 1.1, marginTop: 12, marginBottom: 36,
          }}>
            Identify yourself.
          </div>

          {stage === "idle" && (
            <form onSubmit={submit} style={{
              transform: shake ? "translateX(0)" : "none",
              animation: shake ? "shake 420ms" : "none",
            }}>
              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>01 · HANDLE</label>
                <div style={{ position: "relative" }}>
                  <span style={{ position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", fontSize: 20, color: "var(--muted)", pointerEvents: "none", userSelect: "none" }}>@</span>
                  <input
                    type="text"
                    autoFocus
                    spellCheck={false}
                    autoComplete="off"
                    value={handle}
                    onChange={e => setHandle(e.target.value.replace(/^@/, "").toLowerCase())}
                    placeholder="marina"
                    style={{ width: "100%", fontSize: 20, padding: "12px 14px", paddingLeft: 32, letterSpacing: "0.02em" }}
                  />
                </div>
              </div>

              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>02 · PASSWORD</label>
                <input
                  type="password"
                  value={password}
                  onChange={e => setPassword(e.target.value)}
                  placeholder="••••••••"
                  style={{ width: "100%", fontSize: 20, padding: "12px 14px", letterSpacing: "0.12em" }}
                />
              </div>

              {err && (
                <div style={{
                  border: "1px solid var(--accent)",
                  padding: "10px 12px",
                  fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase",
                  color: "var(--accent)",
                  marginBottom: 22,
                }}>
                  ⚠ {err}
                </div>
              )}

              <div ref={tsContainerRef} style={{ marginBottom: 16 }} />

              <button type="submit" className="btn solid" style={{
                width: "100%", justifyContent: "center", padding: "14px 18px", fontSize: 12,
                opacity: tsToken ? 1 : 0.5,
              }}>
                ENTER TERMINAL <span className="arr">→</span>
              </button>

              <div className="micro" style={{ marginTop: 28, color: "var(--muted)", lineHeight: 1.6 }}>
                NEED AN ACCOUNT? ASK A STUDIO MEMBER FOR AN INVITE LINK.
              </div>
            </form>
          )}

          {stage === "auth" && (
            <div className="stack-3">
              <div className="micro" style={{ color: "var(--muted)" }}>HANDSHAKE · TLS · KEY EXCHANGE</div>
              <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-2)", lineHeight: 1.7 }}>
                <div>{">"} verifying handle <b>@{handle}</b>...</div>
                <div>{">"} resolving role from roster...</div>
                <div>{">"} loading studio context (FRACTURED, ARCADE)...</div>
                <div>{">"} booting LiteLLM bridge...</div>
              </div>
              <div className="bar"><span style={{ width: "85%" }} /></div>
            </div>
          )}

          {stage === "granted" && (
            <div className="stack-3">
              <div className="micro" style={{ color: "var(--accent)" }}>● ACCESS GRANTED</div>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 32, lineHeight: 1.1 }}>
                Welcome back, @{handle}.
              </div>
              <div className="tiny" style={{ color: "var(--muted)" }}>OPENING TERMINAL...</div>
              <div className="bar"><span style={{ width: "100%" }} /></div>
            </div>
          )}
        </div>
      </div>

      {/* footer */}
      <div style={{
        padding: "10px 28px",
        borderTop: "1px solid var(--ink)",
        fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase",
        display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 24,
        color: "var(--muted)",
      }}>
        <span>© SEIS PLUS LLC · INTERNAL</span>
        <span style={{ textAlign: "center" }}>UNAUTHORIZED ACCESS LOGGED · IP RECORDED</span>
        <span>BUILD 2026.04.26-1</span>
      </div>

      <style>{`
        @keyframes shake {
          0%, 100% { transform: translateX(0); }
          20% { transform: translateX(-8px); }
          40% { transform: translateX(8px); }
          60% { transform: translateX(-4px); }
          80% { transform: translateX(4px); }
        }
      `}</style>
    </div>
  );
}

function RegisterScreen({ onAuth, theme, onToggleTheme, onSwitchMode, registerToken }) {
  const [handle, setHandle] = React.useState("");
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [err, setErr] = React.useState("");
  const [shake, setShake] = React.useState(false);
  const [stage, setStage] = React.useState("idle");
  const [tick, setTick] = React.useState(0);
  const [tsToken, setTsToken] = React.useState("");
  const tsContainerRef = React.useRef(null);
  const tsWidgetIdRef = React.useRef(null);

  React.useEffect(() => {
    const id = setInterval(() => setTick(t => t + 1), 1000);
    return () => clearInterval(id);
  }, []);

  React.useEffect(() => {
    const tryRender = () => {
      if (!tsContainerRef.current) return;
      if (!window.turnstile) { setTimeout(tryRender, 100); return; }
      if (tsWidgetIdRef.current != null) return;
      tsWidgetIdRef.current = window.turnstile.render(tsContainerRef.current, {
        sitekey: TURNSTILE_SITE_KEY,
        callback: (token) => setTsToken(token),
        "expired-callback": () => setTsToken(""),
        "error-callback": () => setTsToken(""),
        theme: "light",
      });
    };
    tryRender();
    return () => {
      if (window.turnstile && tsWidgetIdRef.current != null) {
        window.turnstile.remove(tsWidgetIdRef.current);
        tsWidgetIdRef.current = null;
      }
    };
  }, []);

  const resetTurnstile = () => {
    if (window.turnstile && tsWidgetIdRef.current != null) {
      window.turnstile.reset(tsWidgetIdRef.current);
    }
    setTsToken("");
  };

  const submit = async (e) => {
    e.preventDefault();
    if (!registerToken) { setErr("INVALID REGISTRATION LINK"); return; }
    if (!tsToken) { setErr("COMPLETE THE VERIFICATION BELOW"); return; }
    if (password.length < 6) { setErr("PASSWORD MUST BE AT LEAST 6 CHARACTERS"); setShake(true); setTimeout(() => setShake(false), 420); return; }
    try {
      const r = await fetch("/api/auth/register", {
        method: "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ handle: handle.trim().toLowerCase(), firstName: firstName.trim(), lastName: lastName.trim(), password, token: registerToken, cf_turnstile_response: tsToken }),
      });
      if (!r.ok) {
        const body = await r.json().catch(() => ({}));
        setErr(body.detail || "REGISTRATION FAILED");
        setShake(true);
        setTimeout(() => setShake(false), 420);
        resetTurnstile();
        return;
      }
      const member = await r.json();
      setErr("");
      setStage("auth");
      setTimeout(() => setStage("granted"), 1200);
      setTimeout(() => { window.history.replaceState({}, "", "/"); onAuth(member); }, 2100);
    } catch {
      setErr("CONNECTION ERROR · TRY AGAIN");
      setShake(true);
      setTimeout(() => setShake(false), 420);
      resetTurnstile();
    }
  };

  const now = new Date();
  const time = now.toUTCString().slice(17, 25);
  const dateStr = now.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" }).toUpperCase();

  return (
    <div style={{
      position: "fixed", inset: 0,
      background: "var(--bg)",
      color: "var(--ink)",
      zIndex: 1000,
      display: "flex", flexDirection: "column",
      fontFamily: "var(--mono)",
    }}>
      {/* top status strip */}
      <div style={{
        padding: "10px 28px",
        borderBottom: "1px solid var(--ink)",
        fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase",
        display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 24,
        alignItems: "center",
        color: "var(--muted)",
      }}>
        <span style={{ justifySelf: "start" }}>Internal Tools</span>
        <span style={{ textAlign: "center", justifySelf: "center" }}>{dateStr}</span>
        <span className="row gap-12" style={{ alignItems: "center", justifySelf: "end" }}>
          <span>UTC {time}</span>
          {onToggleTheme && (
            <button
              onClick={onToggleTheme}
              title={theme === "dark" ? "switch to day" : "switch to night"}
              aria-label="toggle theme"
              style={{
                cursor: "pointer", color: "var(--ink)", fontSize: 16, lineHeight: 1,
                padding: "2px 6px", border: "1px solid var(--rule-soft)", borderRadius: 999,
              }}
            >{theme === "dark" ? "☼" : "☽"}</button>
          )}
        </span>
      </div>

      {/* center */}
      <div style={{
        flex: 1,
        display: "grid",
        gridTemplateColumns: "1.1fr 1fr",
        gap: 0,
      }}>
        {/* LEFT — masthead */}
        <div style={{ padding: "60px 56px", display: "flex", flexDirection: "column", justifyContent: "space-between", borderRight: "1px solid var(--ink)" }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)" }}>VOL.01 · ISSUE 117 · 2026.04</div>
            <div style={{
              fontFamily: "var(--mono)", fontWeight: 700,
              fontSize: "clamp(56px, 7vw, 110px)",
              lineHeight: 0.92, letterSpacing: "-0.02em",
              marginTop: 28,
            }}>
              INTERNALS<span style={{ color: "var(--accent)" }}>+</span><br/>
              <span style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontWeight: 300 }}>studio access.</span>
            </div>
            <div style={{ marginTop: 32, maxWidth: 460, fontSize: 13, color: "var(--ink-2)", lineHeight: 1.55 }}>
              Restricted terminal for SEIS+ studio operations. Budgets, model intelligence, EC2 spot fleet, internal links — for members only.
            </div>
          </div>

          <div style={{ marginTop: 60, fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--muted)" }}>
            <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: "6px 16px" }}>
              <span>STATUS</span>     <b style={{ color: "var(--accent)" }}>● TERMINAL ARMED</b>
              <span>NODE</span>       <b style={{ color: "var(--ink)" }}>seis-internals-01</b>
              <span>LATITUDE</span>   <b style={{ color: "var(--ink)" }}>00°00'N · PLANET EARTH</b>
              <span>SESSION</span>    <b style={{ color: "var(--ink)" }}>{Math.floor(tick / 1).toString(16).padStart(4,"0").toUpperCase()}-{Math.floor(Date.now()/1e7).toString(16).slice(-4).toUpperCase()}</b>
            </div>
          </div>
        </div>

        {/* RIGHT — register form */}
        <div style={{
          padding: "60px 56px",
          display: "flex", flexDirection: "column", justifyContent: "center",
          background: "var(--paper)",
        }}>
          <div className="micro" style={{ color: "var(--muted)" }}>§ AUTH-002</div>
          <div style={{
            fontFamily: "var(--serif)", fontStyle: "italic", fontWeight: 300,
            fontSize: 38, lineHeight: 1.1, marginTop: 12, marginBottom: 36,
          }}>
            Join the studio.
          </div>

          {stage === "idle" && (
            <form onSubmit={submit} style={{
              transform: shake ? "translateX(0)" : "none",
              animation: shake ? "shake 420ms" : "none",
            }}>
              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>01 · HANDLE</label>
                <div style={{ position: "relative" }}>
                  <span style={{ position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", fontSize: 20, color: "var(--muted)", pointerEvents: "none", userSelect: "none" }}>@</span>
                  <input
                    type="text"
                    autoFocus
                    spellCheck={false}
                    autoComplete="off"
                    value={handle}
                    onChange={e => setHandle(e.target.value.replace(/^@/, "").toLowerCase())}
                    placeholder="marina"
                    style={{ width: "100%", fontSize: 20, padding: "12px 14px", paddingLeft: 32, letterSpacing: "0.02em" }}
                  />
                </div>
              </div>

              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>02 · FIRST NAME</label>
                <input
                  type="text"
                  spellCheck={false}
                  autoComplete="given-name"
                  value={firstName}
                  onChange={e => setFirstName(e.target.value.charAt(0).toUpperCase() + e.target.value.slice(1))}
                  placeholder="Marina"
                  style={{ width: "100%", fontSize: 20, padding: "12px 14px", letterSpacing: "0.02em" }}
                />
              </div>

              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>03 · LAST NAME</label>
                <input
                  type="text"
                  spellCheck={false}
                  autoComplete="family-name"
                  value={lastName}
                  onChange={e => setLastName(e.target.value.charAt(0).toUpperCase() + e.target.value.slice(1))}
                  placeholder="García"
                  style={{ width: "100%", fontSize: 20, padding: "12px 14px", letterSpacing: "0.02em" }}
                />
              </div>

              <div style={{ marginBottom: 22 }}>
                <label className="micro" style={{ display: "block", marginBottom: 8, color: "var(--muted)" }}>04 · PASSWORD</label>
                <input
                  type="password"
                  value={password}
                  onChange={e => setPassword(e.target.value)}
                  placeholder="••••••••"
                  style={{ width: "100%", fontSize: 20, padding: "12px 14px", letterSpacing: "0.12em" }}
                />
              </div>

              {err && (
                <div style={{
                  border: "1px solid var(--accent)",
                  padding: "10px 12px",
                  fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase",
                  color: "var(--accent)",
                  marginBottom: 22,
                }}>
                  ⚠ {err}
                </div>
              )}

              <div ref={tsContainerRef} style={{ marginBottom: 16 }} />

              <button type="submit" className="btn solid" style={{
                width: "100%", justifyContent: "center", padding: "14px 18px", fontSize: 12,
                opacity: tsToken ? 1 : 0.5,
              }}>
                CREATE ACCOUNT <span className="arr">→</span>
              </button>

              <div className="micro" style={{ marginTop: 24, color: "var(--muted)", lineHeight: 1.6 }}>
                ALREADY HAVE ACCESS?{" "}
                <a href="/login" onClick={(e) => { e.preventDefault(); if (onSwitchMode) onSwitchMode("login"); }} style={{ color: "var(--accent)", textDecoration: "underline", cursor: "pointer" }}>
                  SIGN IN →
                </a>
              </div>
            </form>
          )}

          {stage === "auth" && (
            <div className="stack-3">
              <div className="micro" style={{ color: "var(--muted)" }}>HANDSHAKE · TLS · KEY EXCHANGE</div>
              <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-2)", lineHeight: 1.7 }}>
                <div>{">"} creating account <b>@{handle}</b>...</div>
                <div>{">"} hashing credentials...</div>
                <div>{">"} loading studio context (FRACTURED, ARCADE)...</div>
                <div>{">"} booting LiteLLM bridge...</div>
              </div>
              <div className="bar"><span style={{ width: "85%" }} /></div>
            </div>
          )}

          {stage === "granted" && (
            <div className="stack-3">
              <div className="micro" style={{ color: "var(--accent)" }}>● ACCESS GRANTED</div>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 32, lineHeight: 1.1 }}>
                Welcome, @{handle}.
              </div>
              <div className="tiny" style={{ color: "var(--muted)" }}>OPENING TERMINAL...</div>
              <div className="bar"><span style={{ width: "100%" }} /></div>
            </div>
          )}
        </div>
      </div>

      {/* footer */}
      <div style={{
        padding: "10px 28px",
        borderTop: "1px solid var(--ink)",
        fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase",
        display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 24,
        color: "var(--muted)",
      }}>
        <span>© SEIS PLUS LLC · INTERNAL</span>
        <span style={{ textAlign: "center" }}>UNAUTHORIZED ACCESS LOGGED · IP RECORDED</span>
        <span>BUILD 2026.04.26-1</span>
      </div>

      <style>{`
        @keyframes shake {
          0%, 100% { transform: translateX(0); }
          20% { transform: translateX(-8px); }
          40% { transform: translateX(8px); }
          60% { transform: translateX(-4px); }
          80% { transform: translateX(4px); }
        }
      `}</style>
    </div>
  );
}

function loadSession() {
  try {
    const raw = localStorage.getItem(LOGIN_STORAGE);
    if (!raw) return null;
    const s = JSON.parse(raw);
    if (Date.now() - s.t > 1000 * 60 * 60 * 8) return null; // 8h session
    return s.member;
  } catch { return null; }
}
function saveSession(member) {
  try { localStorage.setItem(LOGIN_STORAGE, JSON.stringify({ t: Date.now(), member })); } catch {}
}
function clearSession() {
  try { localStorage.removeItem(LOGIN_STORAGE); } catch {}
}

window.SEIS_LOGIN = { LoginScreen, RegisterScreen, loadSession, saveSession, clearSession };
