<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sign in — sfpermits.ai</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="obsidian-tokens.css">
<style>
body {
min-height: 100vh; min-height: 100dvh;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
padding: var(--space-6);
}
.auth-container {
width: 100%; max-width: 380px;
opacity: 0; animation: fadeUp 1.2s 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.auth-wordmark {
font-family: var(--mono); font-size: var(--text-xs); font-weight: 300;
letter-spacing: 0.35em; text-transform: uppercase; color: var(--text-tertiary);
text-align: center; margin-bottom: var(--space-10);
}
.auth-card {
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
padding: var(--space-8);
}
.auth-title {
font-family: var(--sans); font-size: var(--text-xl); font-weight: 300;
color: var(--text-primary); text-align: center;
margin-bottom: var(--space-2);
}
.auth-subtitle {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); text-align: center;
margin-bottom: var(--space-8);
line-height: 1.5;
}
/* Form */
.auth-label {
font-family: var(--mono); font-size: var(--text-xs); font-weight: 400;
letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-tertiary);
display: block; margin-bottom: var(--space-2);
}
.auth-input {
width: 100%; padding: 12px 16px;
font-family: var(--mono); font-size: var(--text-sm); font-weight: 300;
color: var(--text-primary); background: var(--glass);
border: 1px solid var(--glass-border); border-radius: var(--radius-sm);
outline: none; transition: border-color 0.3s, box-shadow 0.3s;
}
.auth-input::placeholder { color: var(--text-tertiary); }
.auth-input:focus {
border-color: var(--accent-ring);
box-shadow: 0 0 24px var(--accent-glow);
}
.auth-submit {
width: 100%; margin-top: var(--space-6);
padding: 12px;
font-family: var(--mono); font-size: var(--text-sm); font-weight: 300;
color: var(--text-tertiary); letter-spacing: 0.04em;
background: none;
border: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
cursor: pointer;
transition: border-color 0.3s, color 0.3s, background 0.2s;
}
.auth-submit:hover {
border-color: var(--accent-ring); color: var(--accent);
background: var(--accent-glow);
}
.auth-note {
font-family: var(--sans); font-size: var(--text-xs); color: var(--text-tertiary);
text-align: center; margin-top: var(--space-4);
line-height: 1.5;
}
/* Sent state */
.auth-sent { display: none; text-align: center; }
.auth-sent.visible { display: block; }
.auth-form.hidden { display: none; }
.auth-sent__icon {
width: 40px; height: 40px; border-radius: var(--radius-full);
background: rgba(52, 211, 153, 0.1); border: 1px solid rgba(52, 211, 153, 0.25);
display: flex; align-items: center; justify-content: center;
margin: 0 auto var(--space-4);
}
.auth-sent__title {
font-family: var(--sans); font-size: var(--text-lg); font-weight: 300;
color: var(--text-primary); margin-bottom: var(--space-2);
}
.auth-sent__email {
font-family: var(--mono); font-size: var(--text-sm); color: var(--accent);
margin-bottom: var(--space-4);
}
.auth-sent__text {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); line-height: 1.55;
}
.auth-sent__resend {
margin-top: var(--space-6);
}
/* Footer */
.auth-footer {
margin-top: var(--space-10);
text-align: center;
}
.auth-footer a {
font-family: var(--mono); font-size: var(--text-xs); font-weight: 300;
color: var(--text-tertiary); text-decoration: none;
transition: color 0.3s;
}
.auth-footer a:hover { color: var(--accent); }
.auth-footer .sep { margin: 0 var(--space-3); color: var(--glass-border); }
</style>
</head>
<body>
<div class="auth-container">
<div class="auth-wordmark">sfpermits.ai</div>
<div class="auth-card">
<!-- FORM STATE -->
<div class="auth-form" id="auth-form">
<h1 class="auth-title">Sign in</h1>
<p class="auth-subtitle">No password needed. We'll send a magic link to your email.</p>
<label class="auth-label" for="email">Email</label>
<input type="email" id="email" class="auth-input" placeholder="you@example.com" autocomplete="email">
<button class="auth-submit" onclick="showSent()">Send magic link →</button>
<p class="auth-note">
Don't have an account? The link will create one automatically.
</p>
</div>
<!-- SENT STATE -->
<div class="auth-sent" id="auth-sent">
<div class="auth-sent__icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
</div>
<div class="auth-sent__title">Check your email</div>
<div class="auth-sent__email" id="sent-email">you@example.com</div>
<div class="auth-sent__text">
We sent a sign-in link. Click it and you're in.<br>
Check spam if you don't see it within a minute.
</div>
<div class="auth-sent__resend">
<a href="#" class="ghost-cta" onclick="showForm()">Use a different email →</a>
</div>
</div>
</div>
<div class="auth-footer">
<a href="#">About</a>
<span class="sep">·</span>
<a href="#">Methodology</a>
<span class="sep">·</span>
<a href="#">Privacy</a>
</div>
</div>
<script>
function showSent() {
const email = document.getElementById('email').value || 'you@example.com';
document.getElementById('sent-email').textContent = email;
document.getElementById('auth-form').classList.add('hidden');
document.getElementById('auth-sent').classList.add('visible');
}
function showForm() {
document.getElementById('auth-form').classList.remove('hidden');
document.getElementById('auth-sent').classList.remove('visible');
}
</script>
</body>
</html>