149 lines
5.7 KiB
HTML
149 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="theme-color" content="#0f0f1a" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
<title>Lagomare Gates</title>
|
|
<link rel="manifest" href="/manifest.json" />
|
|
<link rel="icon" type="image/svg+xml" href="/static/logo.svg" />
|
|
<link rel="apple-touch-icon" href="/static/logo.svg" />
|
|
<link rel="stylesheet" href="/static/style.css" />
|
|
|
|
<style>
|
|
/* ── Login view ──────────────────────────────────────────────────────── */
|
|
#login-view {
|
|
min-height: 100dvh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 1.5rem;
|
|
}
|
|
#login-view h1 {
|
|
font-size: 1.6rem;
|
|
font-weight: 800;
|
|
margin-bottom: .25rem;
|
|
letter-spacing: -.5px;
|
|
}
|
|
#login-view .subtitle {
|
|
color: var(--text-muted);
|
|
font-size: .9rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
#login-view .card { width: 100%; max-width: 380px; }
|
|
#keypass-input {
|
|
font-size: 1.4rem;
|
|
font-family: monospace;
|
|
letter-spacing: .15em;
|
|
text-align: center;
|
|
text-transform: uppercase;
|
|
}
|
|
#keypass-input::placeholder { text-transform: none; letter-spacing: normal; font-size: 1rem; font-family: inherit; }
|
|
|
|
/* ── Gates view ──────────────────────────────────────────────────────── */
|
|
#gates-view {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100dvh;
|
|
}
|
|
.app-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 1rem 1.25rem;
|
|
background: var(--surface);
|
|
border-bottom: 1px solid var(--border);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
}
|
|
.app-header h2 { font-size: 1.1rem; font-weight: 800; }
|
|
.app-header .sub { color: var(--text-muted); font-size: .8rem; }
|
|
|
|
#gates-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
gap: 1rem;
|
|
padding: 1.25rem;
|
|
flex: 1;
|
|
}
|
|
/* ── Loading state ───────────────────────────────────────────────────── */
|
|
#loading-gates {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-muted);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ── Login view ──────────────────────────────────────────────────────── -->
|
|
<div id="login-view">
|
|
<img src="/static/logo.svg" alt="Lagomare" style="width:72px;height:72px;object-fit:contain;margin-bottom:.5rem" />
|
|
<h1>Lagomare Gates</h1>
|
|
<p class="subtitle">Enter your keypass to continue</p>
|
|
<div class="card">
|
|
<form id="login-form">
|
|
<div class="field">
|
|
<label for="keypass-input">Keypass</label>
|
|
<input
|
|
id="keypass-input"
|
|
type="text"
|
|
autocomplete="off"
|
|
autocorrect="off"
|
|
autocapitalize="characters"
|
|
spellcheck="false"
|
|
placeholder="Enter keypass…"
|
|
maxlength="20"
|
|
/>
|
|
</div>
|
|
<p id="login-error" class="error-msg hidden"></p>
|
|
<button id="login-btn" type="submit" class="btn btn-primary btn-full" style="margin-top:.25rem">
|
|
Access
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Gates view ──────────────────────────────────────────────────────── -->
|
|
<div id="gates-view" class="hidden">
|
|
<header class="app-header">
|
|
<div style="display:flex;align-items:center;gap:.6rem">
|
|
<img src="/static/logo.svg" alt="" style="width:32px;height:32px;object-fit:contain" />
|
|
<div>
|
|
<div class="app-header h2">Lagomare Gates</div>
|
|
<div class="sub">Select a gate to open</div>
|
|
</div>
|
|
</div>
|
|
<button id="logout-btn" class="btn btn-ghost" style="font-size:.85rem;padding:.5rem 1rem">
|
|
Logout
|
|
</button>
|
|
</header>
|
|
<div id="loading-gates">Loading gates…</div>
|
|
<div id="gates-grid" class="hidden"></div>
|
|
</div>
|
|
|
|
<!-- ── Toast ───────────────────────────────────────────────────────────── -->
|
|
<div id="toast" class="toast hidden" aria-live="assertive"></div>
|
|
|
|
<!-- ── Confirm open modal ─────────────────────────────────────────────── -->
|
|
<div id="confirm-modal" class="modal-backdrop hidden">
|
|
<div class="modal" style="max-width:320px;text-align:center">
|
|
<p style="font-size:1.1rem;font-weight:700;margin-bottom:.25rem" id="confirm-gate-name"></p>
|
|
<p style="color:var(--text-muted);font-size:.9rem;margin-bottom:1.5rem">Open this gate?</p>
|
|
<div style="display:flex;gap:.75rem;justify-content:center">
|
|
<button id="confirm-cancel" class="btn btn-ghost" style="flex:1">Cancel</button>
|
|
<button id="confirm-ok" class="btn btn-primary" style="flex:1">Open</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/app.js"></script>
|
|
</body>
|
|
</html>
|