1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1.0"> 6<title>Smart Gate, Sign in</title> 7<style> 8 :root{--bg:#f3f2ef;--card:#fff;--ink:#111;--muted:#6b7280;--purple:#6f1fd4;--purple-dark:#5a18b0;--line:#e6e6e3;--cold:#dc2626} 9 *{box-sizing:border-box} 10 body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:var(--bg); 11 color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif} 12 .card{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:34px 34px 30px;width:360px;box-shadow:0 8px 30px rgba(0,0,0,.06)} 13 .brand{display:flex;align-items:center;gap:9px;margin-bottom:20px} 14 .logo{width:30px;height:30px;border-radius:8px;background:var(--purple);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800} 15 .brand b{font-size:17px} 16 h1{font-size:20px;margin:0 0 4px}.sub{color:var(--muted);font-size:13.5px;margin-bottom:20px} 17 label{display:block;font-weight:600;font-size:13px;margin:12px 0 6px} 18 input{width:100%;padding:12px 13px;border:1px solid var(--line);border-radius:10px;font-size:15px;background:#fbfbfa} 19 input:focus{outline:none;border-color:var(--purple);background:#fff;box-shadow:0 0 0 3px rgba(111,31,212,.1)} 20 .btn{width:100%;margin-top:18px;background:var(--purple);color:#fff;border:none;border-radius:10px;padding:13px;font-weight:700;font-size:15px;cursor:pointer} 21 .btn:hover{background:var(--purple-dark)} 22 .err{color:var(--cold);font-size:13px;margin-top:12px;display:none} 23</style> 24</head> 25<body> 26<form class="card" id="form" onsubmit="return login(event)"> 27 <div class="brand"><div class="logo">â¡</div><b>Smart Gate</b></div> 28 <h1>Sign in</h1> 29 <div class="sub">Use your team account.</div> 30 <label>Email</label><input type="email" id="email" autocomplete="username" required> 31 <label>Password</label><input type="password" id="password" autocomplete="current-password" required> 32 <button class="btn" type="submit">Sign in</button> 33 <div class="err" id="err"></div> 34</form>
35<script> 36async function login(e){ 37 e.preventDefault(); 38 const err=document.getElementById('err'); err.style.display='none'; 39 const r=await fetch('/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'}, 40 body:JSON.stringify({email:document.getElementById('email').value,password:document.getElementById('password').value})}); 41 if(r.ok){ location.href='/admin'; } 42 else{ const d=await r.json().catch(()=>({})); err.textContent=d.error||'Sign in failed'; err.style.display='block'; } 43 return false; 44} 45// if already signed in, go straight to admin 46fetch('/api/auth/me').then(r=>{ if(r.ok) location.href='/admin'; }); 47</script>
47 48</body> 49</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.