1544 lines
45 KiB
HTML
1544 lines
45 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
||
<title>Maps App</title>
|
||
|
||
|
||
|
||
<style>
|
||
/* ========================================
|
||
Apple-Style Glassmorphism Design System
|
||
======================================== */
|
||
|
||
:root {
|
||
/* Glass backgrounds */
|
||
--glass-bg-light: rgba(255, 255, 255, 0.72);
|
||
--glass-bg-medium: rgba(255, 255, 255, 0.55);
|
||
--glass-bg-dark: rgba(28, 28, 30, 0.75);
|
||
|
||
/* Borders */
|
||
--glass-border: rgba(255, 255, 255, 0.18);
|
||
--glass-border-strong: rgba(255, 255, 255, 0.25);
|
||
|
||
/* Shadows */
|
||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.16);
|
||
--shadow-glow: 0 0 20px rgba(255, 255, 255, 0.1);
|
||
|
||
/* Accent colors */
|
||
--accent-blue: #007AFF;
|
||
--accent-blue-hover: #0A84FF;
|
||
--accent-red: #FF3B30;
|
||
--accent-green: #34C759;
|
||
|
||
/* Text */
|
||
--text-primary: rgba(0, 0, 0, 0.85);
|
||
--text-secondary: rgba(0, 0, 0, 0.55);
|
||
--text-light: rgba(255, 255, 255, 0.95);
|
||
--text-light-secondary: rgba(255, 255, 255, 0.7);
|
||
|
||
/* Spacing */
|
||
--radius-sm: 8px;
|
||
--radius-md: 12px;
|
||
--radius-lg: 16px;
|
||
--radius-xl: 20px;
|
||
--radius-full: 9999px;
|
||
|
||
/* Animation */
|
||
--transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
||
--transition-smooth: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||
--transition-bounce: 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
}
|
||
|
||
/* Dark Theme Overrides */
|
||
[data-theme="dark"] {
|
||
--glass-bg-light: rgba(40, 40, 42, 0.85);
|
||
--glass-bg-medium: rgba(50, 50, 52, 0.75);
|
||
--glass-bg-dark: rgba(28, 28, 30, 0.9);
|
||
|
||
--glass-border: rgba(255, 255, 255, 0.1);
|
||
--glass-border-strong: rgba(255, 255, 255, 0.18);
|
||
|
||
--text-primary: rgba(255, 255, 255, 0.95);
|
||
--text-secondary: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
[data-theme="dark"] body {
|
||
background-color: #0a0a0a;
|
||
}
|
||
|
||
/* Legacy label overrides removed to use new system */
|
||
|
||
[data-theme="dark"] .beta-tag {
|
||
background: rgba(255, 255, 255, 0.15);
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
[data-theme="dark"] .search-box {
|
||
background: rgba(255, 255, 255, 0.08);
|
||
border-color: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] .search-box:focus-within {
|
||
background: rgba(255, 255, 255, 0.12);
|
||
}
|
||
|
||
[data-theme="dark"] .search-box input {
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
[data-theme="dark"] .search-box input::placeholder {
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
[data-theme="dark"] .hamburger-line {
|
||
background: var(--text-primary);
|
||
}
|
||
|
||
[data-theme="dark"] .menu-divider {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] .recent-tile {
|
||
background: rgba(60, 60, 62, 0.8);
|
||
border-color: rgba(255, 255, 255, 0.08);
|
||
}
|
||
|
||
[data-theme="dark"] .icon-btn:hover {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] .icon-btn:active {
|
||
background: rgba(255, 255, 255, 0.15);
|
||
}
|
||
|
||
[data-theme="dark"] .zoom-stack .zoom-divider {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
body {
|
||
margin: 0;
|
||
overflow: hidden;
|
||
background-color: #1a1a1a;
|
||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
}
|
||
|
||
canvas {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
/* Prevent browser default drag behavior */
|
||
-webkit-user-select: none;
|
||
-moz-user-select: none;
|
||
-ms-user-select: none;
|
||
user-select: none;
|
||
-webkit-touch-callout: none;
|
||
-webkit-tap-highlight-color: transparent;
|
||
touch-action: none;
|
||
cursor: grab;
|
||
}
|
||
|
||
canvas:active {
|
||
cursor: grabbing;
|
||
}
|
||
|
||
/* ========================================
|
||
UI Container - Main Control Panel
|
||
======================================== */
|
||
#ui-container {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
background: var(--glass-bg-light);
|
||
padding: 12px;
|
||
border-radius: var(--radius-lg);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border: 1px solid var(--glass-border);
|
||
box-shadow:
|
||
var(--shadow-lg),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.5),
|
||
var(--shadow-glow);
|
||
color: var(--text-primary);
|
||
min-width: 48px;
|
||
transition: transform var(--transition-smooth), box-shadow var(--transition-smooth);
|
||
}
|
||
|
||
#ui-container:hover {
|
||
box-shadow:
|
||
0 12px 40px rgba(0, 0, 0, 0.2),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.6),
|
||
0 0 30px rgba(255, 255, 255, 0.15);
|
||
}
|
||
|
||
.control-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
}
|
||
|
||
/* ========================================
|
||
Buttons - Glassmorphism Style
|
||
======================================== */
|
||
button {
|
||
background: var(--glass-bg-medium);
|
||
color: var(--text-primary);
|
||
border: 1px solid var(--glass-border);
|
||
padding: 10px 14px;
|
||
border-radius: var(--radius-md);
|
||
cursor: pointer;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
font-family: inherit;
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
box-shadow:
|
||
var(--shadow-sm),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.4);
|
||
transition:
|
||
transform var(--transition-fast),
|
||
background var(--transition-fast),
|
||
box-shadow var(--transition-fast),
|
||
border-color var(--transition-fast);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
button::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(135deg,
|
||
rgba(255, 255, 255, 0.1) 0%,
|
||
rgba(255, 255, 255, 0) 50%,
|
||
rgba(0, 0, 0, 0.05) 100%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
button:hover {
|
||
background: var(--glass-bg-light);
|
||
border-color: var(--glass-border-strong);
|
||
box-shadow:
|
||
var(--shadow-md),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.6);
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
button:active {
|
||
background: rgba(200, 200, 200, 0.5);
|
||
transform: scale(0.97);
|
||
box-shadow:
|
||
var(--shadow-sm),
|
||
inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
/* Zoom Buttons - Compact pill style */
|
||
#btn-zoom-in,
|
||
#btn-zoom-out {
|
||
width: 32px;
|
||
height: 32px;
|
||
padding: 0;
|
||
font-size: 16px;
|
||
font-weight: 400;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 0;
|
||
}
|
||
|
||
/* Location Button - Neutral by default, blue on hover */
|
||
#btn-location {
|
||
background: transparent;
|
||
color: var(--text-primary);
|
||
border: none;
|
||
font-weight: 600;
|
||
box-shadow: none;
|
||
}
|
||
|
||
#btn-location:hover {
|
||
background: linear-gradient(135deg, var(--accent-blue) 0%, #0A84FF 100%);
|
||
color: white;
|
||
box-shadow:
|
||
0 4px 12px rgba(0, 122, 255, 0.35),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.25);
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
#btn-location:active {
|
||
background: linear-gradient(135deg, #006AE0 0%, var(--accent-blue) 100%);
|
||
color: white;
|
||
transform: scale(0.97);
|
||
}
|
||
|
||
/* Theme Toggle Button */
|
||
#btn-theme {
|
||
background: transparent;
|
||
color: var(--text-primary);
|
||
border: none;
|
||
font-weight: 600;
|
||
box-shadow: none;
|
||
}
|
||
|
||
#btn-theme:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
transform: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
#btn-theme:active {
|
||
background: rgba(0, 0, 0, 0.1);
|
||
transform: none;
|
||
}
|
||
|
||
/* Slider styling */
|
||
input[type="range"] {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
width: 100%;
|
||
height: 6px;
|
||
background: rgba(0, 0, 0, 0.1);
|
||
border-radius: var(--radius-full);
|
||
outline: none;
|
||
margin: 8px 0;
|
||
}
|
||
|
||
input[type="range"]::-webkit-slider-thumb {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
width: 20px;
|
||
height: 20px;
|
||
background: white;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
box-shadow:
|
||
0 2px 6px rgba(0, 0, 0, 0.2),
|
||
0 0 0 1px rgba(0, 0, 0, 0.05);
|
||
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
|
||
}
|
||
|
||
input[type="range"]::-webkit-slider-thumb:hover {
|
||
transform: scale(1.1);
|
||
box-shadow:
|
||
0 3px 10px rgba(0, 0, 0, 0.25),
|
||
0 0 0 1px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
input[type="range"]::-moz-range-thumb {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: white;
|
||
border: none;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
/* ========================================
|
||
Debug Info - Minimal Pill Design
|
||
======================================== */
|
||
#debug-info {
|
||
position: absolute;
|
||
bottom: 24px;
|
||
left: 24px;
|
||
color: var(--text-light-secondary);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.2px;
|
||
pointer-events: none;
|
||
background: var(--glass-bg-dark);
|
||
padding: 8px 14px;
|
||
border-radius: var(--radius-full);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
box-shadow:
|
||
var(--shadow-md),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
/* ========================================
|
||
Compass - Premium Glass Design
|
||
======================================== */
|
||
#compass {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
width: 52px;
|
||
height: 52px;
|
||
background: var(--glass-bg-light);
|
||
border-radius: 50%;
|
||
border: 1px solid var(--glass-border);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--text-primary);
|
||
font-weight: 600;
|
||
pointer-events: none;
|
||
box-shadow:
|
||
var(--shadow-lg),
|
||
inset 0 0.5px 0 rgba(255, 255, 255, 0.5),
|
||
0 0 0 4px rgba(255, 255, 255, 0.08);
|
||
z-index: 100;
|
||
transition: transform var(--transition-smooth);
|
||
}
|
||
|
||
.direction {
|
||
position: absolute;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.n {
|
||
top: 6px;
|
||
color: var(--accent-red);
|
||
}
|
||
|
||
.s {
|
||
bottom: 6px;
|
||
color: var(--text-secondary);
|
||
font-size: 9px;
|
||
}
|
||
|
||
.e {
|
||
right: 8px;
|
||
color: var(--text-secondary);
|
||
font-size: 9px;
|
||
}
|
||
|
||
.w {
|
||
left: 8px;
|
||
color: var(--text-secondary);
|
||
font-size: 9px;
|
||
}
|
||
|
||
.compass-center {
|
||
width: 6px;
|
||
height: 6px;
|
||
background: linear-gradient(135deg, #666 0%, #333 100%);
|
||
border-radius: 50%;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||
z-index: 2;
|
||
}
|
||
|
||
.compass-arrow {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 0;
|
||
height: 0;
|
||
border-left: 4px solid transparent;
|
||
border-right: 4px solid transparent;
|
||
border-bottom: 16px solid var(--accent-red);
|
||
transform: translate(-50%, -100%);
|
||
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
|
||
}
|
||
|
||
/* South arrow (optional visual balance) */
|
||
.compass-arrow::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 16px;
|
||
left: -4px;
|
||
width: 0;
|
||
height: 0;
|
||
border-left: 4px solid transparent;
|
||
border-right: 4px solid transparent;
|
||
border-top: 14px solid rgba(0, 0, 0, 0.2);
|
||
}
|
||
</style>
|
||
<style>
|
||
/* Pulse Animation */
|
||
@keyframes pulse {
|
||
0% {
|
||
box-shadow: 0 0 0 0 rgba(66, 133, 244, 0.6);
|
||
}
|
||
|
||
70% {
|
||
box-shadow: 0 0 0 15px rgba(66, 133, 244, 0);
|
||
}
|
||
|
||
100% {
|
||
box-shadow: 0 0 0 0 rgba(66, 133, 244, 0);
|
||
}
|
||
}
|
||
|
||
#user-location {
|
||
position: absolute;
|
||
width: 16px;
|
||
height: 16px;
|
||
background: #4285F4;
|
||
border: 2px solid white;
|
||
border-radius: 50%;
|
||
display: none;
|
||
/* Hidden by default */
|
||
z-index: 1000;
|
||
/* High z-index to stay on top */
|
||
pointer-events: none;
|
||
box-shadow: 0 0 10px rgba(66, 133, 244, 0.6);
|
||
animation: pulse 2s infinite;
|
||
top: 0;
|
||
left: 0;
|
||
backdrop-filter: blur(2px);
|
||
}
|
||
|
||
/* Dark Theme adjustment for location marker */
|
||
[data-theme="dark"] #user-location {
|
||
background: #5c97f5;
|
||
box-shadow: 0 0 12px rgba(92, 151, 245, 0.7);
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<div id="loading-screen">
|
||
<div class="spinner"></div>
|
||
<div class="loading-text">Loading Maps...</div>
|
||
</div>
|
||
<style>
|
||
#loading-screen {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: #1a1a1a;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 9999;
|
||
transition: opacity 0.5s ease-out;
|
||
}
|
||
|
||
#loading-screen.fade-out {
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.spinner {
|
||
width: 40px;
|
||
height: 40px;
|
||
border: 3px solid rgba(255, 255, 255, 0.1);
|
||
border-radius: 50%;
|
||
border-top-color: #007AFF;
|
||
animation: spin 1s ease-in-out infinite;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.loading-text {
|
||
color: rgba(255, 255, 255, 0.8);
|
||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
@keyframes spin {
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
[data-theme="light"] #loading-screen {
|
||
background-color: #f5f5f7;
|
||
}
|
||
|
||
[data-theme="light"] .loading-text {
|
||
color: rgba(0, 0, 0, 0.6);
|
||
}
|
||
|
||
[data-theme="light"] .spinner {
|
||
border-color: rgba(0, 0, 0, 0.1);
|
||
border-top-color: #007AFF;
|
||
}
|
||
</style>
|
||
<div id="user-location"></div>
|
||
<div id="compass">
|
||
<div class="direction n">N</div>
|
||
<div class="direction e">E</div>
|
||
<div class="direction s">S</div>
|
||
<div class="direction w">W</div>
|
||
<div class="compass-arrow"></div>
|
||
<div class="compass-center"></div>
|
||
</div>
|
||
|
||
<!-- Canvas for GPU-based label rendering (Apple Maps approach) -->
|
||
<canvas id="label-canvas" style="
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
pointer-events: none;
|
||
z-index: 10;
|
||
background: transparent;
|
||
"></canvas>
|
||
|
||
<div id="labels"></div>
|
||
|
||
<style>
|
||
#labels {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
pointer-events: none;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.label {
|
||
position: absolute;
|
||
transform: translate(-50%, -50%);
|
||
color: #333;
|
||
/* Lighter, cleaner shadow */
|
||
text-shadow: 0 0 2px white, 0 0 4px white;
|
||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
|
||
white-space: nowrap;
|
||
pointer-events: none;
|
||
font-weight: 500;
|
||
z-index: 10;
|
||
}
|
||
|
||
.label-country {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
color: #555;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.label-city {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
/* Apple Maps-style street labels - Very Clean */
|
||
.label-street {
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
color: #6e6e73;
|
||
/* Apple Gray */
|
||
letter-spacing: 0.2px;
|
||
text-shadow:
|
||
0 0 2px rgba(255, 255, 255, 0.95),
|
||
0 0 4px rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
/* Road type based sizing - larger roads get larger fonts */
|
||
.label-street-motorway {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: #444;
|
||
}
|
||
|
||
.label-street-primary {
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: #555;
|
||
}
|
||
|
||
.label-street-secondary {
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: #5e5e63;
|
||
}
|
||
|
||
.label-street-tertiary {
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.label-street-residential {
|
||
font-size: 9px;
|
||
font-weight: 400;
|
||
color: #7e7e83;
|
||
}
|
||
|
||
/* One-way direction arrows */
|
||
.oneway-arrow {
|
||
position: absolute;
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
color: rgba(100, 100, 100, 0.5);
|
||
pointer-events: none;
|
||
text-shadow: none;
|
||
z-index: 5;
|
||
}
|
||
|
||
[data-theme="dark"] .oneway-arrow {
|
||
color: rgba(180, 180, 180, 0.5);
|
||
}
|
||
|
||
/* Apple Maps-style POI labels */
|
||
.label-poi {
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: #666;
|
||
letter-spacing: 0.1px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
/* Icon above text */
|
||
gap: 2px;
|
||
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
/* The Icon Circle */
|
||
.label-poi::before {
|
||
content: '';
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background-color: #999;
|
||
/* Default Gray */
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||
border: 1px solid white;
|
||
display: block;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
/* Specific POI Categories */
|
||
|
||
/* Parks - Green */
|
||
.label-poi-park {
|
||
color: #357a38;
|
||
}
|
||
|
||
.label-poi-park::before {
|
||
background-color: #4caf50;
|
||
}
|
||
|
||
.label-poi-garden::before {
|
||
background-color: #4caf50;
|
||
}
|
||
|
||
/* Restaurants/Food - Orange */
|
||
.label-poi-restaurant {
|
||
color: #d86800;
|
||
}
|
||
|
||
.label-poi-restaurant::before {
|
||
background-color: #ff9800;
|
||
}
|
||
|
||
.label-poi-cafe::before {
|
||
background-color: #ff9800;
|
||
}
|
||
|
||
/* Health - Red */
|
||
.label-poi-hospital {
|
||
color: #c62828;
|
||
}
|
||
|
||
.label-poi-hospital::before {
|
||
background-color: #f44336;
|
||
}
|
||
|
||
.label-poi-pharmacy::before {
|
||
background-color: #f44336;
|
||
}
|
||
|
||
/* Education - Gray/Purple */
|
||
.label-poi-university {
|
||
color: #555;
|
||
}
|
||
|
||
.label-poi-university::before {
|
||
background-color: #9e9e9e;
|
||
}
|
||
|
||
.label-poi-school::before {
|
||
background-color: #9e9e9e;
|
||
}
|
||
|
||
/* Stores - Purple */
|
||
.label-poi-shop {
|
||
color: #6a1b9a;
|
||
}
|
||
|
||
.label-poi-shop::before {
|
||
background-color: #9c27b0;
|
||
}
|
||
|
||
/* Transport - Blue */
|
||
.label-poi-fuel {
|
||
color: #0277bd;
|
||
}
|
||
|
||
.label-poi-fuel::before {
|
||
background-color: #03a9f4;
|
||
}
|
||
|
||
.label-poi-parking::before {
|
||
background-color: #03a9f4;
|
||
}
|
||
|
||
/* Tourism - Pink/Brown */
|
||
.label-poi-museum {
|
||
color: #ad1457;
|
||
}
|
||
|
||
.label-poi-museum::before {
|
||
background-color: #e91e63;
|
||
}
|
||
|
||
.label-poi-hotel {
|
||
color: #8d6e63;
|
||
}
|
||
|
||
.label-poi-hotel::before {
|
||
background-color: #795548;
|
||
}
|
||
|
||
/* Dark Theme Adjustments for Labels */
|
||
[data-theme="dark"] .label {
|
||
color: #ddd;
|
||
text-shadow: 0 0 3px rgba(0, 0, 0, 0.8);
|
||
}
|
||
|
||
[data-theme="dark"] .label-street {
|
||
color: #a1a1a6;
|
||
text-shadow: 0 0 3px rgba(0, 0, 0, 0.9);
|
||
}
|
||
|
||
[data-theme="dark"] .label-poi {
|
||
color: #ccc;
|
||
}
|
||
|
||
[data-theme="dark"] .label-poi::before {
|
||
border-color: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
/* ========================================
|
||
TRANSIT LINE LABELS (S-Bahn, U-Bahn)
|
||
Munich-style badges
|
||
======================================== */
|
||
.label-transit {
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.3px;
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
background: white;
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
|
||
border: 2px solid currentColor;
|
||
text-shadow: none;
|
||
}
|
||
|
||
/* S-Bahn - Green circle badge style */
|
||
.label-transit-sbahn {
|
||
background: #408335;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 50%;
|
||
width: 24px;
|
||
height: 24px;
|
||
padding: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 10px;
|
||
font-weight: 800;
|
||
}
|
||
|
||
/* U-Bahn - Blue square badge style */
|
||
.label-transit-ubahn {
|
||
background: #0065AE;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
padding: 3px 6px;
|
||
font-size: 10px;
|
||
font-weight: 800;
|
||
}
|
||
|
||
/* Generic rail - Gray */
|
||
.label-transit-rail {
|
||
background: #666;
|
||
color: white;
|
||
border: none;
|
||
}
|
||
|
||
/* Dark theme adjustments */
|
||
[data-theme="dark"] .label-transit {
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
[data-theme="dark"] .label-transit-sbahn {
|
||
background: #4a9c3d;
|
||
}
|
||
|
||
[data-theme="dark"] .label-transit-ubahn {
|
||
background: #1a7bcb;
|
||
}
|
||
</style>
|
||
|
||
<!-- ========================================
|
||
LEFT SIDEBAR - Google Style Hamburger Menu
|
||
======================================== -->
|
||
<div id="left-sidebar">
|
||
<!-- Google-style Hamburger/Saved Menu -->
|
||
<div id="hamburger-menu">
|
||
<button class="hamburger-btn" id="hamburger-toggle" title="Menu">
|
||
<span class="hamburger-line"></span>
|
||
<span class="hamburger-line"></span>
|
||
<span class="hamburger-line"></span>
|
||
</button>
|
||
<div class="menu-divider"></div>
|
||
<a href="#" class="menu-item">
|
||
<span class="menu-icon">🔖</span>
|
||
<span class="menu-label">Saved</span>
|
||
</a>
|
||
<a href="#" class="menu-item">
|
||
<span class="menu-icon">🕐</span>
|
||
<span class="menu-label">Recents</span>
|
||
</a>
|
||
<div class="menu-divider"></div>
|
||
<!-- Transportation Toggle -->
|
||
<button type="button" class="menu-item" id="btn-transport" title="Toggle Public Transport"
|
||
style="background:none; border:none; width:100%; font-family:inherit;">
|
||
<span class="menu-icon">🚇</span>
|
||
<span class="menu-label">Transit</span>
|
||
</button>
|
||
<div class="menu-divider"></div>
|
||
<!-- Recent locations (placeholder tiles) -->
|
||
<div class="recent-tiles">
|
||
<div class="recent-tile" title="Recent Location">
|
||
<div class="tile-placeholder">📍</div>
|
||
</div>
|
||
<div class="recent-tile" title="Recent Location">
|
||
<div class="tile-placeholder">🏛️</div>
|
||
</div>
|
||
<div class="recent-tile" title="Recent Location">
|
||
<div class="tile-placeholder">⛰️</div>
|
||
</div>
|
||
</div>
|
||
<!-- Get App at bottom -->
|
||
|
||
</div>
|
||
|
||
<!-- Slide-out Search Panel (hidden by default) -->
|
||
<div id="search-panel" class="hidden">
|
||
<div class="panel-header">
|
||
<div class="app-logo">
|
||
<span class="logo-icon">🗺️</span>
|
||
<span class="logo-text">Maps</span>
|
||
<span class="beta-tag">BETA</span>
|
||
</div>
|
||
</div>
|
||
<div class="search-box">
|
||
<span class="search-icon">🔍</span>
|
||
<input type="text" id="search-input" placeholder="Search maps">
|
||
</div>
|
||
<nav class="nav-menu">
|
||
<a href="#" class="nav-item">
|
||
<span class="nav-icon">📍</span>
|
||
<span>Guides</span>
|
||
</a>
|
||
<a href="#" class="nav-item">
|
||
<span class="nav-icon">↗️</span>
|
||
<span>Routes</span>
|
||
</a>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========================================
|
||
RIGHT CONTROLS - Apple Maps Style
|
||
======================================== -->
|
||
<div id="right-controls">
|
||
<!-- Theme toggle button -->
|
||
<div class="control-stack">
|
||
<button class="icon-btn" id="btn-theme" title="Toggle Theme">
|
||
<svg id="theme-icon-light" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
<svg id="theme-icon-dark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2" style="display: none;">
|
||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Location button -->
|
||
<div class="control-stack">
|
||
<button class="icon-btn" id="btn-location" title="My Location">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polygon points="3,11 22,2 13,21 11,13 3,11"></polygon>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Compass -->
|
||
<div id="compass-new">
|
||
<div class="compass-inner">
|
||
<div class="compass-needle"></div>
|
||
<span class="compass-n">N</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Zoom controls -->
|
||
<div class="control-stack zoom-stack">
|
||
<button class="icon-btn" id="btn-zoom-in" title="Zoom In">+</button>
|
||
<div class="zoom-divider"></div>
|
||
<button class="icon-btn" id="btn-zoom-out" title="Zoom Out">−</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Hidden slider for compatibility -->
|
||
<input type="range" id="zoom-slider" min="0" max="100" value="50" style="display:none;">
|
||
|
||
<!-- Debug info removed for cleaner UI -->
|
||
|
||
<style>
|
||
/* ========================================
|
||
LEFT SIDEBAR STYLES
|
||
======================================== */
|
||
#left-sidebar {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
height: 100%;
|
||
display: flex;
|
||
z-index: 100;
|
||
}
|
||
|
||
/* Apple Maps-style Search Panel */
|
||
#search-panel {
|
||
width: 280px;
|
||
background: var(--glass-bg-light);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border-right: 1px solid var(--glass-border);
|
||
padding: 16px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
box-shadow: var(--shadow-lg);
|
||
/* Liquid animation properties */
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
visibility: visible;
|
||
transition:
|
||
transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
|
||
opacity 0.35s cubic-bezier(0.16, 1, 0.3, 1),
|
||
visibility 0.4s,
|
||
box-shadow 0.3s ease;
|
||
will-change: transform, opacity;
|
||
}
|
||
|
||
#search-panel.hidden {
|
||
transform: translateX(-100%);
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
box-shadow: none;
|
||
}
|
||
|
||
/* Staggered content animation inside panel */
|
||
#search-panel>* {
|
||
opacity: 1;
|
||
transform: translateX(0);
|
||
transition:
|
||
opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1),
|
||
transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
|
||
}
|
||
|
||
#search-panel.hidden>* {
|
||
opacity: 0;
|
||
transform: translateX(-20px);
|
||
}
|
||
|
||
/* Staggered delays for children */
|
||
#search-panel>*:nth-child(1) {
|
||
transition-delay: 0.02s;
|
||
}
|
||
|
||
#search-panel>*:nth-child(2) {
|
||
transition-delay: 0.04s;
|
||
}
|
||
|
||
#search-panel>*:nth-child(3) {
|
||
transition-delay: 0.06s;
|
||
}
|
||
|
||
#search-panel>*:nth-child(4) {
|
||
transition-delay: 0.08s;
|
||
}
|
||
|
||
#search-panel>*:nth-child(5) {
|
||
transition-delay: 0.10s;
|
||
}
|
||
|
||
#search-panel.hidden>*:nth-child(1) {
|
||
transition-delay: 0s;
|
||
}
|
||
|
||
#search-panel.hidden>*:nth-child(2) {
|
||
transition-delay: 0s;
|
||
}
|
||
|
||
#search-panel.hidden>*:nth-child(3) {
|
||
transition-delay: 0s;
|
||
}
|
||
|
||
#search-panel.hidden>*:nth-child(4) {
|
||
transition-delay: 0s;
|
||
}
|
||
|
||
#search-panel.hidden>*:nth-child(5) {
|
||
transition-delay: 0s;
|
||
}
|
||
|
||
.menu-bottom {
|
||
margin-top: auto;
|
||
}
|
||
|
||
.hamburger-btn.active .hamburger-line:nth-child(1) {
|
||
transform: translateY(7px) rotate(45deg);
|
||
transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
|
||
}
|
||
|
||
.hamburger-btn.active .hamburger-line:nth-child(2) {
|
||
opacity: 0;
|
||
transform: scaleX(0);
|
||
transition:
|
||
opacity 0.2s ease,
|
||
transform 0.25s ease;
|
||
}
|
||
|
||
.hamburger-btn.active .hamburger-line:nth-child(3) {
|
||
transform: translateY(-7px) rotate(-45deg);
|
||
transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
|
||
}
|
||
|
||
.app-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 4px 0;
|
||
}
|
||
|
||
.logo-icon {
|
||
font-size: 20px;
|
||
}
|
||
|
||
.logo-text {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.beta-tag {
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
background: rgba(0, 0, 0, 0.08);
|
||
color: var(--text-secondary);
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.search-box {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
background: rgba(0, 0, 0, 0.04);
|
||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||
border-radius: var(--radius-md);
|
||
padding: 10px 12px;
|
||
transition: all var(--transition-fast);
|
||
}
|
||
|
||
.search-box:focus-within {
|
||
background: white;
|
||
border-color: var(--accent-blue);
|
||
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.15);
|
||
}
|
||
|
||
.search-icon {
|
||
font-size: 14px;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.search-box input {
|
||
flex: 1;
|
||
border: none;
|
||
background: transparent;
|
||
font-size: 15px;
|
||
font-family: inherit;
|
||
color: var(--text-primary);
|
||
outline: none;
|
||
}
|
||
|
||
.search-box input::placeholder {
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.nav-menu {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.nav-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 10px 12px;
|
||
border-radius: var(--radius-md);
|
||
color: var(--text-primary);
|
||
text-decoration: none;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
transition: background var(--transition-fast);
|
||
}
|
||
|
||
.nav-item:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.nav-icon {
|
||
font-size: 16px;
|
||
}
|
||
|
||
/* Google-style Hamburger Menu */
|
||
#hamburger-menu {
|
||
width: 64px;
|
||
background: var(--glass-bg-light);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border-right: 1px solid var(--glass-border);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 16px 0;
|
||
gap: 8px;
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
.hamburger-btn {
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: var(--radius-md);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 5px;
|
||
cursor: pointer;
|
||
background: transparent;
|
||
border: none;
|
||
padding: 0;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.hamburger-btn:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
transform: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.hamburger-line {
|
||
width: 20px;
|
||
height: 2px;
|
||
background: var(--text-primary);
|
||
border-radius: 2px;
|
||
transform-origin: center;
|
||
transition:
|
||
transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
|
||
opacity 0.25s ease,
|
||
background 0.2s ease;
|
||
}
|
||
|
||
.menu-divider {
|
||
width: 32px;
|
||
height: 1px;
|
||
background: rgba(0, 0, 0, 0.1);
|
||
margin: 8px 0;
|
||
}
|
||
|
||
.menu-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 10px 8px;
|
||
border-radius: var(--radius-md);
|
||
color: var(--text-secondary);
|
||
text-decoration: none;
|
||
transition: all var(--transition-fast);
|
||
width: 48px;
|
||
}
|
||
|
||
.menu-item:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.menu-icon {
|
||
font-size: 18px;
|
||
}
|
||
|
||
.menu-item.active {
|
||
background: rgba(0, 122, 255, 0.1);
|
||
color: var(--accent-blue);
|
||
}
|
||
|
||
.menu-item.active .menu-icon {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.menu-label {
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
text-align: center;
|
||
}
|
||
|
||
.recent-tiles {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
margin-top: auto;
|
||
padding-bottom: 16px;
|
||
}
|
||
|
||
.recent-tile {
|
||
width: 48px;
|
||
height: 48px;
|
||
background: white;
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid rgba(0, 0, 0, 0.08);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
transition: all var(--transition-fast);
|
||
box-shadow: var(--shadow-sm);
|
||
}
|
||
|
||
.recent-tile:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
.tile-placeholder {
|
||
font-size: 20px;
|
||
}
|
||
|
||
/* ========================================
|
||
RIGHT CONTROLS STYLES
|
||
======================================== */
|
||
#right-controls {
|
||
position: absolute;
|
||
top: 16px;
|
||
right: 16px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
z-index: 100;
|
||
}
|
||
|
||
.control-stack {
|
||
background: var(--glass-bg-light);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border-radius: var(--radius-sm);
|
||
border: 1px solid var(--glass-border);
|
||
box-shadow: var(--shadow-md);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 32px;
|
||
height: 32px;
|
||
fill: #333;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: transparent;
|
||
border: none;
|
||
color: var(--text-primary);
|
||
cursor: pointer;
|
||
padding: 6px;
|
||
font-size: 14px;
|
||
font-weight: 300;
|
||
transition: background var(--transition-fast);
|
||
box-shadow: none;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.icon-btn::before {
|
||
display: none;
|
||
}
|
||
|
||
.icon-btn:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
transform: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.icon-btn:active {
|
||
background: rgba(0, 0, 0, 0.1);
|
||
transform: none;
|
||
}
|
||
|
||
.icon-btn svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
.zoom-stack .zoom-divider {
|
||
height: 1px;
|
||
background: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
/* New Compass Style */
|
||
#compass-new {
|
||
width: 32px;
|
||
height: 32px;
|
||
background: var(--glass-bg-light);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
border-radius: 50%;
|
||
border: 1px solid var(--glass-border);
|
||
box-shadow: var(--shadow-md);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.compass-inner {
|
||
position: relative;
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
.compass-needle {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 2px;
|
||
height: 14px;
|
||
transform: translate(-50%, -50%);
|
||
background: linear-gradient(to bottom,
|
||
var(--accent-red) 0%,
|
||
var(--accent-red) 50%,
|
||
#666 50%,
|
||
#666 100%);
|
||
border-radius: 1px;
|
||
}
|
||
|
||
.compass-n {
|
||
position: absolute;
|
||
top: -1px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-size: 7px;
|
||
font-weight: 700;
|
||
color: var(--accent-red);
|
||
}
|
||
|
||
/* Hide old compass */
|
||
#compass {
|
||
display: none;
|
||
}
|
||
</style>
|
||
|
||
<script type="module">
|
||
import init, { run } from './wasm.js?v=transit_hover_v1';
|
||
|
||
async function main() {
|
||
try {
|
||
await init();
|
||
// run() is auto-called via #[wasm_bindgen(start)] in lib.rs
|
||
} catch (e) {
|
||
console.error("Wasm failed:", e);
|
||
}
|
||
}
|
||
main();
|
||
|
||
// Hamburger menu toggle
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const hamburgerBtn = document.getElementById('hamburger-toggle');
|
||
const searchPanel = document.getElementById('search-panel');
|
||
|
||
if (hamburgerBtn && searchPanel) {
|
||
hamburgerBtn.addEventListener('click', () => {
|
||
searchPanel.classList.toggle('hidden');
|
||
hamburgerBtn.classList.toggle('active');
|
||
});
|
||
}
|
||
|
||
// Theme toggle functionality
|
||
const themeBtn = document.getElementById('btn-theme');
|
||
const lightIcon = document.getElementById('theme-icon-light');
|
||
const darkIcon = document.getElementById('theme-icon-dark');
|
||
|
||
// Check for saved theme preference or default to light
|
||
const savedTheme = localStorage.getItem('theme') || 'light';
|
||
document.documentElement.setAttribute('data-theme', savedTheme);
|
||
updateThemeIcon(savedTheme);
|
||
|
||
if (themeBtn) {
|
||
themeBtn.addEventListener('click', () => {
|
||
const currentTheme = document.documentElement.getAttribute('data-theme');
|
||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||
|
||
document.documentElement.setAttribute('data-theme', newTheme);
|
||
localStorage.setItem('theme', newTheme);
|
||
updateThemeIcon(newTheme);
|
||
|
||
// Trigger a resize event to force WASM to redraw with new theme
|
||
window.dispatchEvent(new Event('resize'));
|
||
});
|
||
}
|
||
|
||
function updateThemeIcon(theme) {
|
||
if (lightIcon && darkIcon) {
|
||
if (theme === 'dark') {
|
||
lightIcon.style.display = 'none';
|
||
darkIcon.style.display = 'block';
|
||
} else {
|
||
lightIcon.style.display = 'block';
|
||
darkIcon.style.display = 'none';
|
||
}
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html> |