472 lines
19 KiB
Plaintext
472 lines
19 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>PokeMaps </title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<link rel="icon" href="/css/yt-ukraine.svg" />
|
|
<meta name="color-scheme" content="dark light" />
|
|
<style>
|
|
/* === PokeMaps Base CSS (no JS) === */
|
|
|
|
/* Root tokens */
|
|
:root{
|
|
--bg:#0b0b0b; --fg:#f5f5f5; --muted:#b4b4b4;
|
|
--panel:#121212; --border:#1f1f1f; --accent:#0ea5e9;
|
|
--pad:12px; --r:12px; --bar-h:56px; --sidebar-w:320px;
|
|
}
|
|
|
|
/* Reset-ish */
|
|
*{box-sizing:border-box} html,body{height:100%;margin:0}
|
|
body{background:var(--bg);color:var(--fg);font:14px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Noto Sans",Arial}
|
|
|
|
/* App shell */
|
|
#app-shell{min-height:100%;display:grid;grid-template-rows:auto 1fr auto}
|
|
|
|
/* Top bar */
|
|
#topbar{
|
|
position:sticky;top:0;display:grid;grid-template-columns:1fr auto auto;gap:8px;
|
|
align-items:center;padding:8px var(--pad);background:rgba(0,0,0,.55);
|
|
backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);z-index:10;border-bottom:1px solid var(--border)
|
|
}
|
|
#brand{font-weight:700;letter-spacing:.2px}
|
|
#search-form{display:flex}
|
|
#search-input{
|
|
width:100%;padding:10px 12px;border:1px solid var(--border);border-radius:10px;
|
|
background:#0e0e0e;color:var(--fg);outline:none
|
|
}
|
|
#search-input:focus{border-color:#2a2a2a;box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 24%, transparent)}
|
|
#topbar-actions{display:flex;gap:8px}
|
|
#topbar-actions button{
|
|
border:1px solid var(--border);background:#111;color:var(--fg);border-radius:10px;
|
|
padding:10px 12px;cursor:pointer
|
|
}
|
|
|
|
/* Autosuggest */
|
|
#autosuggest{
|
|
position:absolute;left:var(--pad);right:var(--pad);top:calc(var(--bar-h) - 8px);
|
|
max-height:48vh;overflow:auto;margin:0;padding:0;list-style:none;display:none;
|
|
background:#0f0f0f;border:1px solid var(--border);border-radius:10px;z-index:12
|
|
}
|
|
#autosuggest[data-open="1"]{display:block}
|
|
#autosuggest li{padding:10px 12px;border-top:1px solid #151515;cursor:pointer}
|
|
#autosuggest li:first-child{border-top:0}
|
|
#autosuggest li[aria-selected="true"]{background:#161616}
|
|
|
|
/* Workspace */
|
|
#workspace{position:relative;display:grid;grid-template-columns:1fr;grid-template-rows:1fr}
|
|
|
|
/* Map area */
|
|
#map-area{position:relative;min-height:calc(100vh - var(--bar-h))}
|
|
#map-frame{position:absolute;inset:0;border:0;width:100%;height:100%}
|
|
#map-marker{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none}
|
|
#map-marker-dot{display:block;width:12px;height:12px;border-radius:50%;background:#e53935;box-shadow:0 0 0 3px rgba(229,57,53,.35)}
|
|
#brand-badge{
|
|
position:absolute;left:10px;bottom:10px;padding:6px 10px;border:1px solid var(--border);
|
|
background:rgba(0,0,0,.5);backdrop-filter:blur(8px);border-radius:10px;font-weight:600
|
|
}
|
|
|
|
/* Floating actions (mobile) */
|
|
#float-actions{
|
|
position:absolute;left:10px;bottom:60px;display:flex;flex-direction:column;gap:8px;z-index:5
|
|
}
|
|
#float-actions button{
|
|
border:1px solid var(--border);background:#0f0f0f;color:var(--fg);border-radius:10px;padding:8px 10px
|
|
}
|
|
|
|
/* Coords */
|
|
#coords-panel{
|
|
position:absolute;right:10px;bottom:10px;min-width:220px;text-align:right;
|
|
padding:6px 10px;border:1px solid var(--border);border-radius:10px;
|
|
background:rgba(0,0,0,.5);backdrop-filter:blur(8px);font-family:ui-monospace,monospace
|
|
}
|
|
|
|
/* Panels (dialog-like) */
|
|
[id^="panel-"]{
|
|
position:fixed;right:10px;left:10px;bottom:10px;top:auto;max-height:60vh;overflow:auto;
|
|
background:var(--panel);border:1px solid var(--border);border-radius:12px;z-index:20;padding-bottom:8px
|
|
}
|
|
[id^="panel-"][hidden]{display:none}
|
|
[id^="panel-"] header{
|
|
position:sticky;top:0;display:flex;justify-content:space-between;align-items:center;
|
|
gap:8px;padding:10px 12px;border-bottom:1px solid var(--border);background:#0f0f0f
|
|
}
|
|
[id^="panel-"] h2{margin:0;font-size:16px}
|
|
[id^="panel-"] footer, [id^="panel-"] div, [id^="panel-"] section{padding:10px 12px}
|
|
#pin-list{list-style:none;margin:0;padding:0}
|
|
#pin-list li{padding:10px 12px;border-top:1px solid #151515}
|
|
#pin-list li:first-child{border-top:0}
|
|
|
|
/* Desktop sidebar */
|
|
#desk-sidebar{
|
|
display:none; /* hidden on mobile */
|
|
position:relative;padding:12px;background:var(--panel);border-right:1px solid var(--border)
|
|
}
|
|
#desk-sidebar section{border:1px solid var(--border);border-radius:12px;overflow:hidden;margin-bottom:12px}
|
|
#desk-sidebar section header,
|
|
#desk-sidebar h2{margin:0;padding:10px 12px;border-bottom:1px solid var(--border);font-size:15px}
|
|
#desk-sidebar section > div,
|
|
#desk-sidebar textarea{padding:8px 12px}
|
|
#desk-sidebar input[type="text"],
|
|
#desk-sidebar select,
|
|
#desk-sidebar input[type="color"]{
|
|
width:100%;padding:10px 12px;border:1px solid var(--border);border-radius:10px;background:#0f0f0f;color:var(--fg)
|
|
}
|
|
#desk-sidebar input[type="range"]{width:100%}
|
|
#desk-sidebar button{
|
|
border:1px solid var(--border);background:#111;color:var(--fg);border-radius:10px;padding:8px 10px;cursor:pointer
|
|
}
|
|
#desk-user-css{width:100%;min-height:110px;border:1px solid var(--border);border-radius:10px;background:#0f0f0f;color:var(--fg);resize:vertical}
|
|
|
|
/* Footer */
|
|
#app-footer{padding:10px var(--pad);border-top:1px solid var(--border);color:var(--muted);text-align:center}
|
|
|
|
/* Utility */
|
|
.visually-hidden{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}
|
|
|
|
/* Desktop layout */
|
|
@media (min-width: 1024px){
|
|
#workspace{
|
|
grid-template-columns: var(--sidebar-w) 1fr;
|
|
grid-template-rows: 1fr;
|
|
}
|
|
#desk-sidebar{display:block}
|
|
#float-actions{display:none}
|
|
/* Panels prefer right column on desktop */
|
|
[id^="panel-"]{left:auto;top:72px;right:16px;bottom:auto;max-height:70vh;width:min(460px,40vw)}
|
|
}
|
|
|
|
/* Buttons + links subtle hover */
|
|
button,a{transition:background .15s,border-color .15s,opacity .15s,color .15s}
|
|
button:hover{background:#161616}
|
|
a{color:var(--accent);text-decoration:none}
|
|
a:hover{text-decoration:underline}
|
|
|
|
/* Color-scheme support */
|
|
@media (prefers-color-scheme: light){
|
|
:root{--bg:#fafafa;--fg:#111;--panel:#fff;--border:#e5e5e5;--muted:#555}
|
|
#topbar,#brand-badge,#coords-panel{background:rgba(255,255,255,.6)}
|
|
#search-input{background:#fff}
|
|
#autosuggest{background:#fff}
|
|
}
|
|
|
|
/* Scrollbars (webkit) */
|
|
*::-webkit-scrollbar{height:10px;width:10px}
|
|
*::-webkit-scrollbar-thumb{background:#2a2a2a;border-radius:10px}
|
|
*::-webkit-scrollbar-track{background:transparent}
|
|
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- App Shell -->
|
|
<div id="app-shell" data-app="pokemaps">
|
|
|
|
<!-- Top Bar -->
|
|
<header id="topbar" role="banner">
|
|
<div id="brand" aria-label="App name">PokeMaps</div>
|
|
|
|
<!-- Search -->
|
|
<form id="search-form" role="search" aria-label="Place search" autocomplete="off">
|
|
<label for="search-input" class="visually-hidden">Search places or paste lat,lon</label>
|
|
<input id="search-input" name="q" type="search" placeholder="Search places or paste lat,lon" />
|
|
</form>
|
|
|
|
<!-- Quick actions -->
|
|
<div id="topbar-actions" role="group" aria-label="Quick actions">
|
|
<button id="action-locate" type="button" aria-label="Locate">📍</button>
|
|
<button id="action-menu" type="button" aria-haspopup="true" aria-expanded="false" aria-controls="panel-menu">⋯</button>
|
|
</div>
|
|
|
|
<!-- Suggestions (hidden by default) -->
|
|
<ul id="autosuggest" role="listbox" aria-label="Suggestions" aria-live="polite">
|
|
<!-- <li role="option" id="sug-0" data-type="place">…</li> -->
|
|
</ul>
|
|
</header>
|
|
|
|
<!-- Main Area -->
|
|
<main id="workspace" role="main" aria-label="Map workspace">
|
|
|
|
<!-- Desktop Sidebar (hidden on mobile until styled) -->
|
|
<aside id="desk-sidebar" aria-label="Controls">
|
|
<!-- Overview -->
|
|
<section id="desk-overview" aria-labelledby="desk-overview-title">
|
|
<h2 id="desk-overview-title">Overview</h2>
|
|
<div>
|
|
<input id="desk-search" type="text" placeholder="Search or lat,lon" />
|
|
</div>
|
|
<div>
|
|
<label for="desk-layer">Layer</label>
|
|
<select id="desk-layer" name="layer">
|
|
<option value="mapnik">Standard</option>
|
|
<option value="cyclemap">Cycle</option>
|
|
<option value="transportmap">Transport</option>
|
|
<option value="hot">Humanitarian</option>
|
|
</select>
|
|
</div>
|
|
<div role="group" aria-label="Navigation">
|
|
<button id="desk-locate" type="button">Locate</button>
|
|
<button id="desk-follow" type="button" aria-pressed="false">Follow</button>
|
|
<button id="desk-reset" type="button">Reset</button>
|
|
</div>
|
|
<div role="group" aria-label="Sharing">
|
|
<button id="desk-copy-link" type="button">Copy Link</button>
|
|
<button id="desk-copy-coord" type="button">Copy Coords</button>
|
|
<button id="desk-open-osm" type="button">Open OSM</button>
|
|
<button id="desk-open-gmaps" type="button">Google Maps</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Marker Controls -->
|
|
<section id="desk-marker" aria-labelledby="desk-marker-title">
|
|
<h2 id="desk-marker-title">Marker</h2>
|
|
<div>
|
|
<label><input id="desk-marker-visible" type="checkbox" checked /> Visible</label>
|
|
</div>
|
|
<div>
|
|
<label for="desk-marker-style">Style</label>
|
|
<select id="desk-marker-style">
|
|
<option value="dot">Dot</option>
|
|
<option value="crosshair">Crosshair</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="desk-marker-size">Size</label>
|
|
<input id="desk-marker-size" type="range" min="8" max="64" value="20" />
|
|
</div>
|
|
<div>
|
|
<label for="desk-marker-color">Color</label>
|
|
<input id="desk-marker-color" type="color" value="#e53935" />
|
|
</div>
|
|
<div>
|
|
<label><input id="desk-marker-ring" type="checkbox" checked /> Ring glow</label>
|
|
</div>
|
|
<div>
|
|
<label for="desk-ring-width">Ring width</label>
|
|
<input id="desk-ring-width" type="range" min="0" max="16" value="3" />
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Pins -->
|
|
<section id="desk-pins" aria-labelledby="desk-pins-title">
|
|
<h2 id="desk-pins-title">Pins</h2>
|
|
<div role="group" aria-label="Pins actions">
|
|
<button id="desk-pin-save" type="button">Save current</button>
|
|
<button id="desk-pin-manage" type="button" aria-controls="panel-pins" aria-expanded="false">Manage</button>
|
|
</div>
|
|
<div id="desk-pins-recent" aria-live="polite" aria-label="Recent pins">
|
|
<!-- recent pins preview -->
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Display -->
|
|
<section id="desk-display" aria-labelledby="desk-display-title">
|
|
<h2 id="desk-display-title">Display</h2>
|
|
<div>
|
|
<label><input id="desk-show-coords" type="checkbox" /> Always show coords</label>
|
|
</div>
|
|
<div>
|
|
<label for="desk-coord-fmt">Coordinates</label>
|
|
<select id="desk-coord-fmt">
|
|
<option value="dec">DD (Decimal)</option>
|
|
<option value="dms">DMS</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="desk-precision">Precision</label>
|
|
<input id="desk-precision" type="range" min="0" max="8" value="6" />
|
|
</div>
|
|
<div>
|
|
<label for="desk-accent">Accent</label>
|
|
<input id="desk-accent" type="color" value="#0ea5e9" />
|
|
<button id="desk-accent-reset" type="button">Reset</button>
|
|
</div>
|
|
<div>
|
|
<label for="desk-theme">Theme</label>
|
|
<select id="desk-theme">
|
|
<option value="auto">Auto</option>
|
|
<option value="dark">Dark</option>
|
|
<option value="light">Light</option>
|
|
</select>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Custom CSS -->
|
|
<section id="desk-custom-css" aria-labelledby="desk-custom-css-title">
|
|
<h2 id="desk-custom-css-title">Custom CSS</h2>
|
|
<textarea id="desk-user-css" placeholder="/* Your CSS here */"></textarea>
|
|
<div role="group" aria-label="Custom CSS actions">
|
|
<button id="desk-apply-css" type="button">Apply</button>
|
|
<button id="desk-clear-css" type="button">Clear</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- About -->
|
|
<section id="desk-about" aria-labelledby="desk-about-title">
|
|
<h2 id="desk-about-title">About</h2>
|
|
<p>Data © OpenStreetMap contributors • Viewer: PokeMaps Public Beta</p>
|
|
</section>
|
|
</aside>
|
|
|
|
<!-- Map Area -->
|
|
<section id="map-area" aria-label="Map">
|
|
<iframe id="map-frame" title="OSM map"></iframe>
|
|
|
|
<!-- Marker placeholder -->
|
|
<div id="map-marker" aria-hidden="true">
|
|
<span id="map-marker-dot"></span>
|
|
</div>
|
|
|
|
<!-- Brand -->
|
|
<div id="brand-badge" aria-hidden="true">PokeMaps Public Beta</div>
|
|
|
|
<!-- Floating actions (mobile/tablet) -->
|
|
<nav id="float-actions" aria-label="Floating actions">
|
|
<button id="fa-pin-save" type="button">⭐ Save Pin</button>
|
|
<button id="fa-pins-open" type="button" aria-controls="panel-pins" aria-expanded="false">📒 Pins</button>
|
|
<button id="fa-settings" type="button" aria-controls="panel-settings" aria-expanded="false">⚙ Settings</button>
|
|
</nav>
|
|
|
|
<!-- Coordinates panel -->
|
|
<output id="coords-panel" aria-live="polite" aria-atomic="true"></output>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- Mobile/Tablet Panels (hidden by default; no styling here) -->
|
|
|
|
<!-- Menu Panel -->
|
|
<section id="panel-menu" role="dialog" aria-modal="false" aria-labelledby="panel-menu-title" hidden>
|
|
<header>
|
|
<h2 id="panel-menu-title">Menu</h2>
|
|
<button id="panel-menu-close" type="button" aria-label="Close">✕</button>
|
|
</header>
|
|
<div>
|
|
<label for="menu-layer">Layer</label>
|
|
<select id="menu-layer" name="layer">
|
|
<option value="mapnik">Standard</option>
|
|
<option value="cyclemap">Cycle</option>
|
|
<option value="transportmap">Transport</option>
|
|
<option value="hot">Humanitarian</option>
|
|
</select>
|
|
</div>
|
|
<div role="group" aria-label="View">
|
|
<button id="menu-follow" type="button" aria-pressed="false">🛰️ Follow</button>
|
|
<button id="menu-reset" type="button">🔁 Reset</button>
|
|
</div>
|
|
<div role="group" aria-label="Shortcuts">
|
|
<button id="menu-near" type="button">📍 Near me</button>
|
|
<button id="menu-clear" type="button">🧹 Clear search</button>
|
|
</div>
|
|
<div role="group" aria-label="Share">
|
|
<button id="menu-copy" type="button">📋 Copy Link</button>
|
|
<button id="menu-copycoord" type="button">📐 Coords</button>
|
|
<button id="menu-share" type="button">🔗 Share</button>
|
|
</div>
|
|
<div role="group" aria-label="External">
|
|
<button id="menu-open-osm" type="button">🌐 Open OSM</button>
|
|
<button id="menu-open-gmaps" type="button">🛰️ Google Maps</button>
|
|
</div>
|
|
<footer>
|
|
<a id="menu-osm-terms" href="https://wiki.osmfoundation.org/wiki/Terms_of_Use" target="_blank" rel="noopener">OSM Terms</a>
|
|
<a id="menu-osm-copyright" href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener">Copyright</a>
|
|
<a id="menu-osm-nominatim" href="https://operations.osmfoundation.org/policies/nominatim/" target="_blank" rel="noopener">Nominatim Policy</a>
|
|
</footer>
|
|
</section>
|
|
|
|
<!-- Pins Panel -->
|
|
<section id="panel-pins" role="dialog" aria-modal="false" aria-labelledby="panel-pins-title" hidden>
|
|
<header>
|
|
<h2 id="panel-pins-title">Saved Pins</h2>
|
|
<button id="panel-pins-close" type="button" aria-label="Close">✕</button>
|
|
</header>
|
|
<ul id="pin-list" aria-label="Pins list">
|
|
<!-- <li data-lat="" data-lon=""><strong>Name</strong><span>lat, lon · layer</span><div role="group">...</div></li> -->
|
|
</ul>
|
|
</section>
|
|
|
|
<!-- Settings Panel -->
|
|
<section id="panel-settings" role="dialog" aria-modal="false" aria-labelledby="panel-settings-title" hidden>
|
|
<header>
|
|
<h2 id="panel-settings-title">Settings</h2>
|
|
<button id="panel-settings-close" type="button" aria-label="Close">✕</button>
|
|
</header>
|
|
|
|
<section aria-labelledby="set-general-title">
|
|
<h3 id="set-general-title">General</h3>
|
|
<label><input id="set-autofollow" type="checkbox" /> Auto-follow on load</label>
|
|
<label><input id="set-show-coords" type="checkbox" /> Always show coordinates</label>
|
|
<div>
|
|
<label for="set-coord-fmt">Coordinates format</label>
|
|
<select id="set-coord-fmt">
|
|
<option value="dec">DD (Decimal)</option>
|
|
<option value="dms">DMS</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="set-precision">Coordinate precision</label>
|
|
<input id="set-precision" type="range" min="0" max="8" step="1" value="6" />
|
|
</div>
|
|
<div>
|
|
<label for="set-theme">Theme</label>
|
|
<select id="set-theme">
|
|
<option value="auto">Auto</option>
|
|
<option value="dark">Dark</option>
|
|
<option value="light">Light</option>
|
|
</select>
|
|
</div>
|
|
</section>
|
|
|
|
<section aria-labelledby="set-marker-title">
|
|
<h3 id="set-marker-title">Marker</h3>
|
|
<label><input id="set-marker-visible" type="checkbox" checked /> Marker visible</label>
|
|
<div>
|
|
<label for="set-marker-style">Marker style</label>
|
|
<select id="set-marker-style">
|
|
<option value="dot">Dot</option>
|
|
<option value="crosshair">Crosshair</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="set-marker-size">Marker size</label>
|
|
<input id="set-marker-size" type="range" min="8" max="64" step="1" value="20" />
|
|
</div>
|
|
<div>
|
|
<label for="set-marker-color">Marker color</label>
|
|
<input id="set-marker-color" type="color" value="#e53935" />
|
|
</div>
|
|
<label><input id="set-marker-ring" type="checkbox" checked /> Ring glow</label>
|
|
<div>
|
|
<label for="set-ring-width">Ring width</label>
|
|
<input id="set-ring-width" type="range" min="0" max="16" step="1" value="3" />
|
|
</div>
|
|
</section>
|
|
|
|
<section aria-labelledby="set-links-title">
|
|
<h3 id="set-links-title">View & Links</h3>
|
|
<label><input id="set-share-delta" type="checkbox" checked /> Include Δ in shared links</label>
|
|
<label><input id="set-confirm-delete" type="checkbox" checked /> Confirm before deleting pins</label>
|
|
<div>
|
|
<label for="set-accent">Accent color</label>
|
|
<input id="set-accent" type="color" value="#0ea5e9" />
|
|
<button id="set-accent-reset" type="button">Reset</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section aria-labelledby="set-css-title">
|
|
<h3 id="set-css-title">Custom CSS</h3>
|
|
<textarea id="set-user-css" placeholder="/* Write CSS to inject */"></textarea>
|
|
<div role="group" aria-label="Custom CSS controls">
|
|
<button id="set-apply-css" type="button">Apply</button>
|
|
<button id="set-clear-css" type="button">Clear</button>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
|
|
<!-- Footer (optional) -->
|
|
<footer id="app-footer" role="contentinfo">
|
|
<small>Map tiles/data © OpenStreetMap contributors.</small>
|
|
</footer>
|
|
</div>
|
|
</body>
|
|
</html>
|