Files
JGA-2026/packliste.html
T
Hermes AI Bot c3fbe892cc Hotel-Highlight + Route + Nachbarn + Restaurants + PWA + Theme-Toggle (index.html)
**Hotel präsenter auf Karten:**
- Größerer Hotel-Marker (56px vs 38px)
- Goldener pulsierender Glow (CSS-Animation hotelPulse)
- Permanentes Label 'Hotel Uno · Basis' unter dem Pin
- Auto-Open Popup nach 1.5s mit goldenem Banner
- Filter-Toggle (Hotel immer sichtbar, Action/Fun/Sight ausblendbar)

**Feature 7 - Route zwischen Locations:**
- OSRM Public API für echte Auto-Routen
- Schnell-Routen vom Hotel (3 nächste Locations)
- 'Zurück zum Hotel' Button in jedem Location-Popup
- Fallback auf Haversine-Luftlinie wenn API down

**Feature 8 - Was ist in der Nähe:**
- Nachbarn <3km Luftlinie in jedem Popup

**Feature 14 - Restaurant-Tipps:**
- Geo-Cluster-basierte Restaurant-Empfehlungen pro Location
- 14 handgepflegte Tipps (€€, Cuisine, Beschreibung)

**Feature 20 - PWA:**
- manifest.json + sw.js (cache-first für eigene Files)
- Theme-Color, Apple-Meta, SW-Registrierung in allen 5 HTML-Dateien

**Feature 21 - Dark/Light Mode Toggle:**
- CSS-Variablen-System + 🌙/☀️ Toggle-Button
- localStorage-Persistenz (nur index.html, andere Seiten folgen)

**Bugfixes:**
- Enigma-URL auf User-Sublink korrigiert (alle 3 Map-Dateien)
- tourenplan-mit-tram.html Locations-Sync mit tourenplan.html
  (Endorfin/KartPlanet hatten komplett andere Preise+Koordinaten+URLs)
2026-06-27 08:32:48 +00:00

297 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JGA Prag Packliste</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#3b82f6">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="JGA Prag">
<meta name="mobile-web-app-capable" content="yes"><text y='.9em' font-size='90'>🧭</text></svg>">
<style>
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #1c1c1f;
color: #e8e8ea;
min-height: 100vh;
}
.container { max-width: 900px; margin: 0 auto; padding: 40px 24px; }
h1 {
font-size: 38px;
margin: 0 0 8px 0;
color: #fff;
font-weight: 700;
}
.subtitle { color: #999; margin-bottom: 32px; font-size: 16px; }
.back-link {
display: inline-block;
margin-bottom: 24px;
color: #60a5fa;
text-decoration: none;
font-size: 14px;
}
.back-link:hover { text-decoration: underline; }
.category {
background: #26262a;
border: 1px solid #353539;
border-radius: 12px;
padding: 20px 24px;
margin-bottom: 16px;
}
.category h2 {
margin: 0 0 16px 0;
font-size: 20px;
color: #fff;
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.category h2 .icon {
font-size: 28px;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", emoji;
}
.checklist { list-style: none; padding: 0; margin: 0; }
.checklist li {
padding: 8px 0;
border-bottom: 1px solid #2a2a2d;
display: flex;
align-items: flex-start;
gap: 10px;
font-size: 15px;
}
.checklist li:last-child { border-bottom: none; }
.checklist input[type="checkbox"] {
appearance: none;
width: 18px;
height: 18px;
border: 2px solid #3b82f6;
border-radius: 4px;
flex-shrink: 0;
margin-top: 2px;
cursor: pointer;
position: relative;
background: transparent;
}
.checklist input[type="checkbox"]:checked {
background: #3b82f6;
border-color: #3b82f6;
}
.checklist input[type="checkbox"]:checked::after {
content: "✓";
color: white;
position: absolute;
left: 2px;
top: -3px;
font-size: 14px;
font-weight: bold;
}
.checklist li.checked span {
text-decoration: line-through;
color: #666;
}
.checklist li small {
display: block;
color: #888;
font-size: 12px;
margin-top: 2px;
}
.progress-bar {
background: #2a2a2d;
height: 8px;
border-radius: 4px;
overflow: hidden;
margin: 24px 0;
}
.progress-bar .fill {
height: 100%;
background: #3b82f6;
width: 0%;
transition: width 0.3s ease;
}
.progress-text {
text-align: center;
color: #aaa;
font-size: 13px;
margin-bottom: 24px;
}
@media print {
body { background: white; color: black; }
.category { background: white; border: 1px solid #ccc; }
.checklist input[type="checkbox"] {
border-color: #333;
}
button { display: none !important; }
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back-link">← Zurück zur Übersicht</a>
<h1>🎒 JGA Prag Packliste</h1>
<p class="subtitle">Für 8 Personen · 25.26. Juli 2026 · Wochenende</p>
<div class="progress-text" id="progress-text">0 von 0 erledigt</div>
<div class="progress-bar"><div class="fill" id="progress-fill"></div></div>
<div style="display:flex;gap:12px;justify-content:center;margin-bottom:24px;flex-wrap:wrap;">
<button type="button" onclick="window.print()" style="padding:10px 20px;background:#3b82f6;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;font-size:14px;">🖨️ Als PDF drucken</button>
<button type="button" id="reset-btn" style="padding:10px 20px;background:transparent;color:#aaa;border:1px solid #353539;border-radius:6px;font-weight:500;cursor:pointer;font-size:14px;">↻ Häkchen zurücksetzen</button>
</div>
<div class="category">
<h2><span class="icon">📄</span>Dokumente & Geld</h2>
<ul class="checklist">
<li><input type="checkbox"><span>Personalausweis oder Reisepass<small>(Personalausweis reicht innerhalb EU)</small></span></li>
<li><input type="checkbox"><span>Krankenversicherungskarte</span></li>
<li><input type="checkbox"><span>Bargeld in CZK (~2.000 CZK pro Person für Trinkgeld & kleine Ausgaben)</span></li>
<li><input type="checkbox"><span>EC-Karte / Kreditkarte<small>(Visa/Mastercard fast überall akzeptiert)</small></span></li>
<li><input type="checkbox"><span>Hotel-Buchungsbestätigung (auf dem Handy)</span></li>
<li><input type="checkbox"><span>Bordkarte / Zugticket Hinfahrt + Rückfahrt</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">👕</span>Kleidung</h2>
<ul class="checklist">
<li><input type="checkbox"><span>T-Shirts / Hemden (23 Stück)</span></li>
<li><input type="checkbox"><span>Hose / Shorts</span></li>
<li><input type="checkbox"><span>JGA-Shirt / Outfit<small>(falls ihr eines habt)</small></span></li>
<li><input type="checkbox"><span>Leichte Jacke / Hoodie<small>(Abende, Geister-Tour)</small></span></li>
<li><input type="checkbox"><span>Unterwäsche + Socken (2 Tage)</span></li>
<li><input type="checkbox"><span>Bequeme Schuhe fürs Laufen</span></li>
<li><input type="checkbox"><span>Schickere Schuhe für Clubs/Restaurants</span></li>
<li><input type="checkbox"><span>Schwimmzeug (falls Beer Spa)</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">🧴</span>Pflege & Hygiene</h2>
<ul class="checklist">
<li><input type="checkbox"><span>Zahnbürste + Zahnpasta</span></li>
<li><input type="checkbox"><span>Duschgel / Shampoo</span></li>
<li><input type="checkbox"><span>Deo</span></li>
<li><input type="checkbox"><span>Sonnencreme</span></li>
<li><input type="checkbox"><span>Handtuch (klein, für unterwegs)</span></li>
<li><input type="checkbox"><span>Kopfschmerztabletten</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">📱</span>Technik</h2>
<ul class="checklist">
<li><input type="checkbox"><span>Handy + Ladekabel</span></li>
<li><input type="checkbox"><span>Powerbank<small>(Tag wird lang!)</small></span></li>
<li><input type="checkbox"><span>Kopfhörer</span></li>
<li><input type="checkbox"><span>EU-Ladeadapter<small>(Prag nutzt Typ E, wie in DE/AT)</small></span></li>
<li><input type="checkbox"><span>Kamera (optional)</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">🚇</span>Prag-spezifisch</h2>
<ul class="checklist">
<li><input type="checkbox"><span>Google Translate (Offline-Pack Tschechisch installieren!)</span></li>
<li><input type="checkbox"><span>Bolt-App installieren<small>(Uber gibt's nicht mehr in Prag!)</small></span></li>
<li><input type="checkbox"><span>Google Maps Offline-Karte Prag laden</span></li>
<li><input type="checkbox"><span>PID Lítačka App (für Tram-Tickets)<small>(oder Bargeld im Tram)</small></span></li>
<li><input type="checkbox"><span>Notfall-Nummer: 112 (EU-Notruf)</span></li>
<li><input type="checkbox"><span>Kleiner tschechischer Sprachführer (Pivo, Děkuji, Účet prosím)</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">🎯</span>JGA-Spezial (nach Aktivität)</h2>
<ul class="checklist">
<li><input type="checkbox"><span>🎯 Für Schießstand: gültiger Ausweis (wird kontrolliert)</span></li>
<li><input type="checkbox"><span>⛳ Für Minigolf: nichts spezielles</span></li>
<li><input type="checkbox"><span>🔫 Für Lasertag: nichts spezielles</span></li>
<li><input type="checkbox"><span>🎨 Für Paintball: alte Klamotten (es wird schmutzig!)</span></li>
<li><input type="checkbox"><span>🏎️ Für Kart: lange Hose + feste Schuhe</span></li>
<li><input type="checkbox"><span>🔐 Für Escape Room: pünktlich da sein (sonst verpasst ihr eure Startzeit)</span></li>
<li><input type="checkbox"><span>👻 Für Geister-Tour: bequeme Schuhe, 1,75 h zu Fuß</span></li>
<li><input type="checkbox"><span>⛵ Für Beer Boat: nichts spezielles (Bier ist dabei 🍺)</span></li>
<li><input type="checkbox"><span>🔍 Für Enigma: Smartphone voll geladen</span></li>
</ul>
</div>
<div class="category">
<h2><span class="icon">🍺</span>Verpflegung</h2>
<ul class="checklist">
<li><input type="checkbox"><span>Wasserflasche (für unterwegs)</span></li>
<li><input type="checkbox"><span>Knabberzeug für den Zug</span></li>
<li><input type="checkbox"><span>Kaugummis / Pfefferminz<small>(für zwischendurch)</small></span></li>
</ul>
</div>
</div>
<script>
const STORAGE_KEY = 'jga-packliste-checked';
let checked = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
const checkboxes = document.querySelectorAll('.checklist input[type="checkbox"]');
const progressText = document.getElementById('progress-text');
const progressFill = document.getElementById('progress-fill');
checkboxes.forEach((cb, i) => {
if (checked[i]) {
cb.checked = true;
cb.parentElement.classList.add('checked');
}
cb.dataset.index = i;
});
function updateProgress() {
const total = checkboxes.length;
const done = Array.from(checkboxes).filter(cb => cb.checked).length;
const pct = (done / total * 100).toFixed(0);
progressFill.style.width = pct + '%';
progressText.textContent = `${done} von ${total} erledigt (${pct}%)`;
checked = Array.from(checkboxes).map(cb => cb.checked);
localStorage.setItem(STORAGE_KEY, JSON.stringify(checked));
}
checkboxes.forEach(cb => {
cb.addEventListener('change', () => {
cb.parentElement.classList.toggle('checked', cb.checked);
updateProgress();
});
});
document.getElementById('reset-btn').addEventListener('click', () => {
if (!confirm('Alle Häkchen wirklich zurücksetzen?')) return;
checkboxes.forEach(cb => {
cb.checked = false;
cb.parentElement.classList.remove('checked');
});
updateProgress();
});
updateProgress();
</script>
<script>
// PWA Service Worker registrieren
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('./sw.js')
.then(reg => console.log('[PWA] SW registered:', reg.scope))
.catch(err => console.warn('[PWA] SW registration failed:', err));
});
}
</script>
</body>
</html>