Files
JGA-2026/packliste.html
T
Hermes AI Bot 3a9bdd55ed Home-Button oben links auf allen Seiten + ÖPNV-Control einklappbar + Mobile-Anpassungen
User-Requests:
1. Legendenmenü auf Mobile war außerhalb des Displays -> jetzt
   eingeklappt (nur Header) auf beiden Map-Files. Body scrollbar
   bei Bedarf.
2. ÖPNV-Control soll auch klappbar sein -> gleiche Einklapp-Logik
   wie Legende auf tourenplan-mit-tram.html.
3. Home-Button oben links auf jeder Seite -> alle 9 HTML-Files
   (index ausgenommen weil es die Startseite ist) haben jetzt einen
   🏠 Startseite Button fixed-position oben links.

Mobile-Optimierungen (max-width: 768px):
- Home-Button + Theme-Toggle kleiner (10px margin statt 16px,
  padding 8x12 statt 10x16)
- Leaflet-Controls kleinere Margins
- Legende + ÖPNV-Control max-width 180px (von 220px)
- topleft-Control margin-top 56px damit es unter dem Home-Button
  sitzt statt ihn zu überdecken

Auch im jga_wetter_update.py (für Cron-generierte wetter.html):
- CSS-Variablen statt hardcoded Farben
- home-btn CSS + Mobile-Override
- Home-Button HTML-Injection in get_body()
2026-06-27 09:56:04 +00:00

395 lines
14 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="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">
<script>
(function() {
const saved = localStorage.getItem('jga-theme');
document.documentElement.setAttribute('data-theme', saved || 'dark');
})();
</script>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🧭</text></svg>">
<style>
/* ====== Theme-Variablen ====== */
:root, [data-theme="dark"] {
--bg: #1c1c1f;
--card-bg: #26262a;
--card-border: #353539;
--text: #e8e8ea;
--text-muted: #999;
--text-strong: #fff;
--accent: #3b82f6;
--accent-text: #60a5fa;
--progress-bg: #2a2a2d;
}
[data-theme="light"] {
--bg: #f5f5f7;
--card-bg: #ffffff;
--card-border: #e0e0e3;
--text: #1a1a1a;
--text-muted: #666;
--text-strong: #000;
--accent: #2563eb;
--accent-text: #2563eb;
--progress-bg: #e0e0e3;
}
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
transition: background 0.3s, color 0.3s;
}
.container { max-width: 900px; margin: 0 auto; padding: 40px 24px; }
h1 {
font-size: 38px;
margin: 0 0 8px 0;
color: var(--text-strong);
font-weight: 700;
}
.subtitle { color: var(--text-muted); margin-bottom: 32px; font-size: 16px; }
.back-link {
display: inline-block;
margin-bottom: 24px;
color: var(--accent-text);
text-decoration: none;
font-size: 14px;
}
.back-link:hover { text-decoration: underline; }
/* Theme-Toggle Button */
.home-btn {
position: fixed;
top: 16px; left: 16px;
z-index: 1000;
background: var(--card-bg);
border: 1px solid var(--card-border);
color: var(--text);
text-decoration: none;
padding: 10px 16px;
border-radius: 22px;
font-size: 14px;
font-weight: 600;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 6px;
}
@media (max-width: 768px) {
.home-btn { top: 10px; left: 10px; padding: 8px 12px; font-size: 13px; }
.theme-toggle { top: 10px; right: 10px; width: 38px; height: 38px; font-size: 18px; }
}
.home-btn:hover {
transform: translateX(-2px);
border-color: var(--accent);
color: var(--accent);
}
.theme-toggle {
position: fixed;
top: 16px;
right: 16px;
width: 44px; height: 44px;
border-radius: 50%;
background: var(--card-bg);
border: 1px solid var(--card-border);
color: var(--text);
font-size: 20px;
cursor: pointer;
z-index: 100;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
transition: all 0.2s;
display: flex; align-items: center; justify-content: center;
}
.theme-toggle:hover {
transform: rotate(15deg) scale(1.1);
border-color: var(--accent);
}
.category {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 12px;
padding: 20px 24px;
margin-bottom: 16px;
}
.category h2 {
margin: 0 0 16px 0;
font-size: 20px;
color: var(--text-strong);
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 var(--card-border);
display: flex;
align-items: flex-start;
gap: 10px;
font-size: 15px;
color: var(--text);
}
.checklist li:last-child { border-bottom: none; }
.checklist input[type="checkbox"] {
appearance: none;
width: 18px;
height: 18px;
border: 2px solid var(--accent);
border-radius: 4px;
flex-shrink: 0;
margin-top: 2px;
cursor: pointer;
position: relative;
background: transparent;
}
.checklist input[type="checkbox"]:checked {
background: var(--accent);
border-color: var(--accent);
}
.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: var(--text-muted);
}
.checklist li small {
display: block;
color: var(--text-muted);
font-size: 12px;
margin-top: 2px;
}
.progress-bar {
background: var(--progress-bg);
height: 8px;
border-radius: 4px;
overflow: hidden;
margin: 24px 0;
}
.progress-bar .fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width 0.3s ease;
}
.progress-text {
text-align: center;
color: var(--text-muted);
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>
<a href="index.html" class="home-btn" title="Zurück zur Startseite">🏠 Startseite</a>
<button class="theme-toggle" id="theme-toggle" aria-label="Theme wechseln" title="Light/Dark Mode">🌙</button>
<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();
});
// Theme-Toggle
const themeBtn = document.getElementById('theme-toggle');
function updateThemeIcon() {
const cur = document.documentElement.getAttribute('data-theme') || 'dark';
themeBtn.textContent = cur === 'dark' ? '☀️' : '🌙';
themeBtn.title = cur === 'dark' ? 'Light Mode aktivieren' : 'Dark Mode aktivieren';
}
updateThemeIcon();
themeBtn.addEventListener('click', () => {
const cur = document.documentElement.getAttribute('data-theme') || 'dark';
const next = cur === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('jga-theme', next);
updateThemeIcon();
});
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>