211 lines
8.9 KiB
HTML
211 lines
8.9 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="#018133ff" />
|
|
<meta name="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/images/logo.svg" />
|
|
<link rel="apple-touch-icon" href="/static/images/mobile_icon.png" />
|
|
<link rel="stylesheet" href="/static/style.css" />
|
|
<link rel="stylesheet" href="/static/leaflet.css" />
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pwa-add-to-homescreen@4/dist/add-to-homescreen.min.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);
|
|
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: flex;
|
|
flex-direction: column;
|
|
gap: 1.5rem;
|
|
padding: 1.25rem;
|
|
flex: 1;
|
|
}
|
|
.gate-group-title {
|
|
font-size: .8rem;
|
|
font-weight: 700;
|
|
color: var(--text-muted);
|
|
text-transform: uppercase;
|
|
letter-spacing: .08em;
|
|
margin-bottom: .6rem;
|
|
}
|
|
.gate-group-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
gap: 1rem;
|
|
}
|
|
/* ── Loading state ───────────────────────────────────────────────────── */
|
|
#loading-gates {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* ── Map modal ─────────────────────────────────────────────────────── */
|
|
#map-modal .modal {
|
|
width: min(96vw, 700px);
|
|
padding: 0;
|
|
overflow: hidden;
|
|
}
|
|
#map-modal-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: .85rem 1.1rem;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
#map-modal-header h3 { font-size: 1rem; font-weight: 700; }
|
|
#map { height: min(60vh, 480px); }
|
|
/* Fix Leaflet default icon paths */
|
|
.leaflet-default-icon-path { background-image: url(/static/images/marker-icon.png); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ── Login view ──────────────────────────────────────────────────────── -->
|
|
<div id="login-view">
|
|
<img src="/static/images/logo.svg" alt="Lagomare" style="width:72px;height:72px;object-fit:contain;margin-bottom:.5rem" />
|
|
<h1>Lagomare Gates</h1>
|
|
<div class="card" style="margin-top:2rem">
|
|
<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="40"
|
|
/>
|
|
</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:.75rem">
|
|
<img src="/static/images/logo.svg" alt="" style="width:50px;height:50px;object-fit:contain;flex-shrink:0" />
|
|
<div class="app-header h2">Lagomare Gates</div>
|
|
</div>
|
|
<div style="display:flex;align-items:center;gap:.5rem">
|
|
<button id="install-app-btn" class="btn btn-primary" style="padding:.4rem .6rem;line-height:0" aria-label="Add to Home Screen" title="Add to Home Screen">
|
|
<img src="/static/images/add_to_home_screen.svg" alt="" style="width:22px;height:22px;display:block;filter:invert(1)" />
|
|
</button>
|
|
<button id="map-btn" class="btn btn-ghost hidden" style="padding:.4rem .6rem;line-height:0" aria-label="Show map">
|
|
<img src="/static/images/map.svg" alt="Map" style="width:22px;height:22px;filter:invert(1)" />
|
|
</button>
|
|
<button id="logout-btn" class="btn btn-ghost" style="font-size:.85rem;padding:.5rem 1rem">Logout</button>
|
|
</div>
|
|
</header>
|
|
<div id="loading-gates">Loading gates…</div>
|
|
<div id="gates-grid" class="hidden"></div>
|
|
</div>
|
|
|
|
<!-- ── Map modal ──────────────────────────────────────────────────────── -->
|
|
<div id="map-modal" class="modal-backdrop hidden">
|
|
<div class="modal">
|
|
<div id="map-modal-header">
|
|
<h3>Map</h3>
|
|
<button id="map-close" class="btn btn-ghost" style="padding:.35rem .8rem;font-size:.85rem">✕</button>
|
|
</div>
|
|
<div id="map"></div>
|
|
</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>
|
|
|
|
<!-- ── PWA install banner ─────────────────────────────────────────────────────── -->
|
|
<div id="install-banner" class="install-banner hidden" role="banner" aria-label="Install app">
|
|
<div class="install-banner-body">
|
|
<img src="/static/images/logo.svg" alt="" class="install-banner-icon" />
|
|
<div class="install-banner-text">
|
|
<strong>Add to Home Screen</strong>
|
|
<span>Install Lagomare Gates for quick access</span>
|
|
</div>
|
|
</div>
|
|
<div class="install-banner-actions">
|
|
<button id="install-dismiss" class="btn btn-ghost" style="font-size:.8rem;padding:.45rem .9rem">Later</button>
|
|
<button id="install-btn" class="btn btn-primary" style="font-size:.8rem;padding:.45rem .9rem">Install</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/leaflet.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/pwa-add-to-homescreen@4/dist/add-to-homescreen.min.js"></script>
|
|
<script src="/static/app.js"></script>
|
|
</body>
|
|
</html>
|