Compare commits

..

1 Commits

Author SHA1 Message Date
Adminator 97a8a2d0a2 Initial commit 2026-07-07 23:57:04 +00:00
1304 changed files with 3 additions and 1108364 deletions
-10
View File
@@ -1,10 +0,0 @@
node_modules/
App/node_modules/
App/dist/
App/.env.local
App/.env.production
App/Don_t_Deploy/.env
.claude/
# Tile-Proxy-Cache (regenerierbare Kartenkacheln, nicht ins Git)
App/data/tiles/
-594
View File
@@ -1,594 +0,0 @@
Pflichtenheft
Simulation „Flussmanagement“ für den Geografieunterricht
1. Ziel des Projekts
Ziel ist die Entwicklung einer interaktiven Simulation für den Geografieunterricht (Sekundarstufe I, 1015 Jahre), in der Schülerinnen und Schüler ein Flusssystem steuern und dabei Zielkonflikte zwischen:
Hochwasserschutz
Landwirtschaft
Ökologie
Wirtschaft
erkennen und ausbalancieren.
Die Simulation soll sich wie ein Spiel anfühlen, aber fachlich korrekt und didaktisch wirksam sein.
2. Zielgruppe
Schülerinnen und Schüler (1015 Jahre)
Lehrpersonen (Geografie, ggf. fächerübergreifend)
Einsatz im Klassenverband (Einzel- oder Gruppenarbeit)
3. Zentrale didaktische Ziele
Die Anwendung muss ermöglichen:
Verständnis von MenschUmwelt-Systemen
Erkennen von Zielkonflikten (Trade-offs)
Einsicht in nichtlineare Zusammenhänge
Bewertung von Eingriffen in Naturräume
Reflexion historischer Entwicklungen (optional)
4. Spielprinzip
Der Spieler übernimmt die Rolle eines Entscheidungsträgers (z. B. Region/Behörde) und steuert Maßnahmen an einem Fluss.
Grundmechanik
Spieler wählt Steuermaßnahmen
Simulation berechnet Auswirkungen
Spieler sieht visuelle Veränderungen
Spiel bewertet Ergebnis anhand mehrerer Ziele
5. Spieldauer
Das Spiel muss konfigurierbar sein:
Leveltyp Dauer
Kurzlevel 1015 Minuten
Standardlevel 2030 Minuten
Langlevel 3040 Minuten
Steuerung der Dauer über:
Anzahl der Runden
Anzahl aktiver Parameter
Ereignisdichte
Komplexität der Entscheidungen
6. Spielstruktur
6.1 Rundenbasiertes System
Ein Level besteht aus mehreren Runden:
Situation anzeigen
Spieler trifft Entscheidungen
Simulation wird berechnet
Ergebnisse werden visualisiert
ggf. Ereignis tritt ein
6.2 Levelstruktur
Levels unterscheiden sich durch:
Rahmenbedingungen
freigeschaltete Maßnahmen
Zielgewichtung
Schwierigkeit
7. Steuergrößen (Spieleraktionen)
Mindestens folgende Maßnahmen müssen implementiert werden:
Flussbegradigung
Dämme bauen
Ausbaggern
Auen freigeben
Renaturierung
Bewässerung
Jede Maßnahme:
hat Intensität (0100)
hat Kosten
hat positive und negative Effekte
8. Zustandsparameter (Simulation)
Alle Werte liegen im Bereich 0100:
Risiken
Lokales Hochwasser
Hochwasser flussabwärts
Erosion
Nutzen
Bodenfruchtbarkeit
Biodiversität
Grundwasser
Nutzbare Fläche
Wirtschaft
9. Rahmenbedingungen
Pro Level definierbar:
Niederschlag
Extremwetter
Gefälle
Bevölkerungsdruck
Budget
Diese sind nicht direkt steuerbar, beeinflussen aber die Simulation.
10. Simulationslogik
10.1 Grundprinzip
Die Simulation basiert auf:
direkten Effekten von Maßnahmen
indirekten Wechselwirkungen zwischen Parametern
nichtlinearen Funktionen
10.2 Anforderungen an die Logik
Die Simulation muss:
nichtlinear sein (keine einfachen +/ Beziehungen)
abnehmenden Nutzen bei steigender Intensität abbilden
überproportionale Nebenwirkungen bei starken Eingriffen erzeugen
Kettenreaktionen ermöglichen
10.3 Beispielhafte Effekte
Begradigung → mehr Fläche, aber mehr Hochwasser flussabwärts
Dämme → lokaler Schutz, aber Nachteile für Landwirtschaft
Renaturierung → ökologische Vorteile, aber weniger Fläche
11. Bewertungssystem
11.1 Zielbereiche
Das Spiel bewertet:
Sicherheit
Ökologie
Landwirtschaft
Wirtschaft
11.2 Mehrzielbewertung
Es gibt keine perfekte Lösung.
Gesamtscore basiert auf gewichteter Kombination:
Score = f(Sicherheit, Ökologie, Landwirtschaft, Wirtschaft)
Gewichtung ist je Level anpassbar.
12. Balancing-Anforderungen
Das System muss sicherstellen:
12.1 Keine dominante Strategie
Keine Maßnahme darf immer optimal sein
12.2 Zielkonflikte
Jede Maßnahme muss mindestens einen Nachteil haben
12.3 Kontextabhängigkeit
Wirkung hängt von Rahmenbedingungen ab
12.4 Extremwerte vermeiden
Maximale Eingriffe müssen Risiken erzeugen
13. Spielmechaniken gegen Fehlverhalten
Muss implementiert werden:
Budgetbegrenzung
Strafsystem für extreme Eingriffe
Katastrophen bei kritischen Zuständen
Bonus für ausgewogene Strategien
14. Visualisierung
Die Simulation muss visuell darstellen:
Hochwasser (Überflutung)
Flussverlauf (gerade vs. mäandrierend)
Vegetation / Biodiversität
Landwirtschaft (Ertrag sichtbar)
Bebauung
Wichtig:
Jede Änderung im Modell muss sichtbar sein.
15. Benutzeroberfläche
Anforderungen
einfache Bedienung (Schüler geeignet)
klare Rückmeldung
visuelle Feedbacks statt Zahlenlast
Parameter optional einblendbar
16. Admin-/Lehrermodus
Muss enthalten:
Auswahl von Levels
Anpassung von:
Budget
Klima
Zielgewichtung
Aktivieren/Deaktivieren von Maßnahmen
Festlegen der Spieldauer
17. Technische Anforderungen
Frontend
Web-basiert (HTML, JS, optional TypeScript)
responsiv
keine Installation nötig
Backend (optional)
für Speicherung von Szenarien
keine Pflicht für Minimalversion
18. Erweiterbarkeit
Das System muss modular aufgebaut sein, damit später ergänzt werden kann:
historische Level
weitere Naturprozesse
andere geografische Themen
19. Test- und Balancing-System
Das System muss ein internes oder separates Modul enthalten, das:
viele Strategien automatisch testet
dominante Strategien erkennt
Extremverhalten identifiziert
Balanceprobleme meldet
20. Abnahmekriterien
Das System gilt als erfolgreich, wenn:
ein Level in 1040 Minuten spielbar ist
mehrere unterschiedliche Strategien zum Erfolg führen
keine einzelne Maßnahme dominiert
Auswirkungen visuell nachvollziehbar sind
Schüler Zielkonflikte erkennen können
21. Anhänge
Anhang A: Datenmodell (JSON)
Anhang B: Beispiel-Simulationslogik
Anhang C: Balancing-Tester
(Diese basieren auf den zuvor entwickelten Modellen und werden als Referenz bereitgestellt.)
Fazit
Dieses Pflichtenheft beschreibt kein einfaches Spiel, sondern ein:
dynamisches, nichtlineares, mehrzieliges Simulationssystem für didaktisches Lernen
Wenn du willst, gehe ich im nächsten Schritt noch weiter und erstelle dir:
konkrete Level (z. B. Nildelta, Industrialisierung, Alpenfluss)
oder eine fertige Prompt-Version für eine Programmier-KI (z. B. Cursor, GPT, etc.)
Das wäre der nächste logische Schritt.
Ja mach das mit dem konkreten Level noch als Ergänzung
Gut — ich ergänze das Pflichtenheft jetzt um konkrete, sofort implementierbare Level-Spezifikationen.
Diese sind so formuliert, dass eine KI sie direkt in Datenstrukturen oder Code übersetzen kann.
Ergänzung zum Pflichtenheft: Konkrete Leveldefinitionen
22. Levelsystem Struktur
Jedes Level wird formal definiert durch:
type LevelDefinition = {
id: string;
title: string;
description: string;
durationTargetMinutes: number;
initialState: State;
conditions: Conditions;
allowedControls: (keyof Controls)[];
controlLimits: Partial<Controls>;
scoreWeights: {
safety: number;
ecology: number;
agriculture: number;
economy: number;
};
rounds: number;
events?: LevelEvent[];
winConditions: {
minScore?: number;
targetScores?: Partial<ScoreBreakdown>;
};
loseConditions?: {
maxFloodLocal?: number;
maxFloodDownstream?: number;
minGroundwater?: number;
};
};
23. Level 1 Einstieg: „Fluss und Siedlung“
Ziel
Grundverständnis von Hochwasser und einfachen Maßnahmen
const level1: LevelDefinition = {
id: "L1",
title: "Fluss und Siedlung",
description: "Eine kleine Siedlung liegt an einem Fluss und ist regelmäßig von Hochwasser betroffen.",
durationTargetMinutes: 10,
rounds: 5,
initialState: {
floodLocal: 60,
floodDownstream: 40,
erosion: 30,
soilFertility: 60,
biodiversity: 70,
groundwater: 55,
usableLand: 40,
economy: 40
},
conditions: {
rainfall: 60,
extremeWeather: 30,
slope: 40,
populationPressure: 30,
budget: 120
},
allowedControls: ["levees", "floodplainRelease"],
controlLimits: {
levees: 60,
floodplainRelease: 60
},
scoreWeights: {
safety: 0.5,
ecology: 0.2,
agriculture: 0.15,
economy: 0.15
},
winConditions: {
minScore: 60
},
loseConditions: {
maxFloodLocal: 85
}
};
24. Level 2 Landwirtschaft: „Fruchtbares Tal“
Fokus
Nutzen von Überschwemmungen vs. Risiko
const level2: LevelDefinition = {
id: "L2",
title: "Fruchtbares Tal",
description: "Ein Tal lebt von fruchtbaren Böden durch regelmäßige Überschwemmungen.",
durationTargetMinutes: 20,
rounds: 7,
initialState: {
floodLocal: 55,
floodDownstream: 35,
erosion: 35,
soilFertility: 75,
biodiversity: 65,
groundwater: 60,
usableLand: 45,
economy: 50
},
conditions: {
rainfall: 65,
extremeWeather: 40,
slope: 35,
populationPressure: 40,
budget: 150
},
allowedControls: ["levees", "floodplainRelease", "irrigation"],
scoreWeights: {
safety: 0.25,
ecology: 0.2,
agriculture: 0.4,
economy: 0.15
},
winConditions: {
targetScores: {
agriculture: 65,
safety: 50
}
}
};
25. Level 3 Industrialisierung: „Der gezähmte Fluss“
Fokus
Technische Eingriffe und ihre Folgen
const level3: LevelDefinition = {
id: "L3",
title: "Der gezähmte Fluss",
description: "Der Fluss soll kontrolliert werden, um Städte und Industrie zu schützen.",
durationTargetMinutes: 25,
rounds: 8,
initialState: {
floodLocal: 50,
floodDownstream: 45,
erosion: 40,
soilFertility: 55,
biodiversity: 50,
groundwater: 50,
usableLand: 55,
economy: 60
},
conditions: {
rainfall: 60,
extremeWeather: 45,
slope: 50,
populationPressure: 70,
budget: 180
},
allowedControls: [
"levees",
"straightening",
"dredging"
],
scoreWeights: {
safety: 0.4,
ecology: 0.1,
agriculture: 0.2,
economy: 0.3
},
events: [
{
round: 4,
type: "flood_event",
intensity: 70
}
],
winConditions: {
minScore: 65
}
};
26. Level 4 Systemdenken: „Fluss im Gleichgewicht“
Fokus
Mehrere Ziele gleichzeitig
const level4: LevelDefinition = {
id: "L4",
title: "Fluss im Gleichgewicht",
description: "Finde eine Balance zwischen Sicherheit, Natur und Nutzung.",
durationTargetMinutes: 30,
rounds: 10,
initialState: {
floodLocal: 55,
floodDownstream: 50,
erosion: 45,
soilFertility: 60,
biodiversity: 60,
groundwater: 50,
usableLand: 50,
economy: 55
},
conditions: {
rainfall: 60,
extremeWeather: 50,
slope: 45,
populationPressure: 60,
budget: 180
},
allowedControls: [
"levees",
"straightening",
"floodplainRelease",
"renaturation",
"irrigation"
],
scoreWeights: {
safety: 0.25,
ecology: 0.25,
agriculture: 0.25,
economy: 0.25
},
winConditions: {
minScore: 70
}
};
27. Level 5 Speziallevel: Nildelta
Bezug zur realen Welt und deinem Wunsch nach nicht einseitigem Denken
Fokus
Überschwemmung als Vorteil
const level5: LevelDefinition = {
id: "L5",
title: "Nildelta",
description: "Die Überschwemmungen bringen fruchtbare Böden aber auch Risiken.",
durationTargetMinutes: 35,
rounds: 10,
initialState: {
floodLocal: 65,
floodDownstream: 40,
erosion: 30,
soilFertility: 85,
biodiversity: 70,
groundwater: 65,
usableLand: 50,
economy: 60
},
conditions: {
rainfall: 40,
extremeWeather: 20,
slope: 20,
populationPressure: 70,
budget: 160
},
allowedControls: [
"levees",
"irrigation",
"floodplainRelease"
],
scoreWeights: {
safety: 0.2,
ecology: 0.2,
agriculture: 0.45,
economy: 0.15
},
winConditions: {
targetScores: {
agriculture: 75
}
},
loseConditions: {
minGroundwater: 25
}
};
28. Ereignissystem (für alle Levels)
type LevelEvent = {
round: number;
type: "flood_event" | "drought" | "economic_boost";
intensity: number;
};
Beispiele:
Hochwasser
Dürre
wirtschaftlicher Boom
29. Didaktische Progression
Level Konzept
1 Ursache-Wirkung
2 Nutzen vs Risiko
3 Technik vs Natur
4 Systemdenken
5 Realwelt + Transfer
30. Abschluss
Mit dieser Ergänzung hat deine KI jetzt:
ein vollständiges Spielsystem
ein Simulationsmodell
ein Balancing-Konzept
konkrete Leveldaten
klare didaktische Struktur
-14
View File
@@ -1,14 +0,0 @@
Pflichtenheft — Lernsimulation „Stadt & Raumplanung"
(Gespeichert aus User-Input, 2026-04-13)
Siehe Konversation fuer vollstaendiges Pflichtenheft.
Kernpunkte:
- Kachelbasierte Stadtsimulation, 2D Top-Down oder isometrisch
- Strassen mit Anschlusslogik (N/E/S/W Connections)
- Kacheltypen: Strasse, Wohngebiet, Geschaeft, Schule, Park, Industrie, Energie
- Zustandsparameter: traffic, environment, economy, satisfaction, accessibility
- Nichtlineare Simulation mit Zielkonflikten
- Runden- oder Echtzeit-basiert
- Lehrkraefte-Modul mit Vergleichsansicht
- Balancing: keine dominante Strategie
- 10-40 Minuten Spieldauer
File diff suppressed because it is too large Load Diff
-16
View File
@@ -1,16 +0,0 @@
# GeoGraSim — Environment Configuration
DB_HOST=localhost
DB_NAME=geograsim
DB_USER=root
DB_PASS=
DB_PORT=3306
# Tile-Proxy-Cache-Verzeichnis (optional; Default: APP_ROOT/data/tiles/)
# Produktion: persistentes Volume im Container, z.B.
# TILE_CACHE_DIR=/var/www/html/geograsim/data/tiles/
# OpenAI API Key — für DALL-E-Bildgenerierung (nur Dev-Zeit)
# OPENAI_API_KEY=sk-...
# ElevenLabs Sound Effects API — nur für generate-sounds.py (Dev-Zeit)
# ELEVENLABS_API_KEY=...
-24
View File
@@ -1,24 +0,0 @@
RewriteEngine On
# Kein RewriteBase — Apache nutzt den Request-Pfad automatisch.
# Funktioniert fuer alle Deploy-Ziele:
# localhost/geograsim/App/ (lokal, XAMPP)
# staatsgeheimnis.at/geograsim/ (Subpfad-Prod)
# geograsim.at/ (eigene Domain-Prod)
# Mit hart gesetztem RewriteBase gab es auf der eigenen Domain einen
# Endlos-Redirect-Loop (AH00124: 10 internal redirects).
# Statische Dateien direkt ausliefern
RewriteRule ^dist/ - [L]
RewriteRule ^assets/ - [L]
RewriteRule ^node_modules/ - [L]
RewriteRule ^src/ - [L]
# Bestehende Dateien/Ordner direkt ausliefern
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
# Alles andere -> Front Controller
RewriteRule ^(.*)$ index.php [QSA,L]
@@ -1,24 +0,0 @@
-- 2026-05-04: Tempo-Kontrolle + Live View
-- Idempotent.
-- 1) Pause-Schalter pro Klasse+Modul (Lehrer steuert das Tempo)
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'class_modules' AND COLUMN_NAME = 'paused'
);
SET @sql := IF(@col_exists = 0,
'ALTER TABLE class_modules ADD COLUMN paused TINYINT(1) NOT NULL DEFAULT 0 AFTER current_level',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 2) Live-Heartbeat-Tabelle für Live View
CREATE TABLE IF NOT EXISTS live_sessions (
student_id INT UNSIGNED PRIMARY KEY,
class_id INT UNSIGNED NOT NULL,
module_id VARCHAR(16) NOT NULL,
state_json LONGTEXT,
started_at TIMESTAMP NULL,
last_seen TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_class (class_id, last_seen),
INDEX idx_module (module_id, last_seen)
) ENGINE=InnoDB;
@@ -1,90 +0,0 @@
-- 2026-05-04: Lehrer Jakob + 3 Schüler in Klasse "Jakob 1" + je 1 Lizenz
-- Idempotent: kann mehrfach ausgeführt werden, ohne Daten zu duplizieren.
-- Passwörter als bcrypt-Hash (PHP_DEFAULT, $2y$10$).
START TRANSACTION;
-- 1) Lehrer Jakob (jakob@geograsim.at / hoppala3355!)
INSERT INTO teachers (username, email, password, display_name, email_verified)
VALUES ('jakob', 'jakob@geograsim.at',
'$2y$10$ofuRFIeNBm/UVZcATyI37eFmEph1vfC81SeP7lalIRNynxoLb77C6',
'Jakob', 1)
ON DUPLICATE KEY UPDATE
email = VALUES(email),
password = VALUES(password),
display_name = VALUES(display_name),
email_verified = VALUES(email_verified);
SET @teacher_id := (SELECT id FROM teachers WHERE username='jakob' LIMIT 1);
-- 2) Klasse "Jakob 1" mit Join-Code JAKOB1
INSERT INTO classes (teacher_id, name, school_year, join_code)
VALUES (@teacher_id, 'Jakob 1', '25/26', 'JAKOB1')
ON DUPLICATE KEY UPDATE
teacher_id = VALUES(teacher_id),
name = VALUES(name),
school_year = VALUES(school_year);
SET @class_id := (SELECT id FROM classes WHERE join_code='JAKOB1' LIMIT 1);
-- 3) Schüler:innen (Pseudonyme, anonym=1)
INSERT INTO students (class_id, username, password, password_plaintext, display_name, is_anonymous, emoji_avatar)
VALUES
(@class_id, 'Alexom', '$2y$10$FvNMeFn/ozKIZY0l2zbQEOx/UZefPQZIf2bbDcOA/igjNBWxj5H0a', '3322', 'Alexom', 1, '🧑‍🎓'),
(@class_id, 'Berturam', '$2y$10$uj6YrgOqTeI9nv9bV.5/XOEFYRLrlt5MdXBzxRX3dFREcw2Th9X1C', '7788', 'Berturam', 1, '🧑‍🎓'),
(@class_id, 'Sussama', '$2y$10$nOS5jXAY.kuMQ1mhr/6Zwug/fHglF94K3D5gSg.1RWrSoq7GIr7y6', '9991', 'Sussama', 1, '🧑‍🎓')
ON DUPLICATE KEY UPDATE
password = VALUES(password),
password_plaintext = VALUES(password_plaintext),
display_name = VALUES(display_name),
is_anonymous = VALUES(is_anonymous),
emoji_avatar = VALUES(emoji_avatar);
SET @stud_alex := (SELECT id FROM students WHERE class_id=@class_id AND username='Alexom' LIMIT 1);
SET @stud_bert := (SELECT id FROM students WHERE class_id=@class_id AND username='Berturam' LIMIT 1);
SET @stud_suss := (SELECT id FROM students WHERE class_id=@class_id AND username='Sussama' LIMIT 1);
-- 4) Lizenzen — pro Schüler eine Lizenz aus dem freien Pool nehmen, an Jakob redeemen, an Schüler zuweisen.
-- Wenn der Schüler schon eine Lizenz hat → die behalten (idempotent).
SET @lic_alex := IFNULL(
(SELECT id FROM licenses WHERE student_id=@stud_alex LIMIT 1),
(SELECT id FROM licenses WHERE student_id IS NULL AND teacher_id IS NULL ORDER BY id LIMIT 1)
);
UPDATE licenses
SET teacher_id = @teacher_id,
redeemed_at = COALESCE(redeemed_at, NOW()),
student_id = @stud_alex
WHERE id = @lic_alex;
SET @lic_bert := IFNULL(
(SELECT id FROM licenses WHERE student_id=@stud_bert LIMIT 1),
(SELECT id FROM licenses WHERE student_id IS NULL AND teacher_id IS NULL ORDER BY id LIMIT 1)
);
UPDATE licenses
SET teacher_id = @teacher_id,
redeemed_at = COALESCE(redeemed_at, NOW()),
student_id = @stud_bert
WHERE id = @lic_bert;
SET @lic_suss := IFNULL(
(SELECT id FROM licenses WHERE student_id=@stud_suss LIMIT 1),
(SELECT id FROM licenses WHERE student_id IS NULL AND teacher_id IS NULL ORDER BY id LIMIT 1)
);
UPDATE licenses
SET teacher_id = @teacher_id,
redeemed_at = COALESCE(redeemed_at, NOW()),
student_id = @stud_suss
WHERE id = @lic_suss;
COMMIT;
-- Bestätigung
SELECT t.id AS teacher_id, t.username, t.email
FROM teachers t WHERE t.username='jakob';
SELECT c.id AS class_id, c.name, c.school_year, c.join_code
FROM classes c WHERE c.teacher_id=(SELECT id FROM teachers WHERE username='jakob');
SELECT s.id, s.username, s.display_name, s.password_plaintext, l.code AS license_code
FROM students s
LEFT JOIN licenses l ON l.student_id = s.id
WHERE s.class_id=(SELECT id FROM classes WHERE join_code='JAKOB1')
ORDER BY s.id;
@@ -1,10 +0,0 @@
-- 2026-05-04: KI-Avatare für die 3 Test-Schüler in Klasse JAKOB1
-- Idempotent — kann mehrfach ausgeführt werden.
SET @class_id := (SELECT id FROM classes WHERE join_code='JAKOB1' LIMIT 1);
UPDATE students SET emoji_avatar='avatar:fuchs-explorer' WHERE class_id=@class_id AND username='Alexom';
UPDATE students SET emoji_avatar='avatar:adler-pilot' WHERE class_id=@class_id AND username='Berturam';
UPDATE students SET emoji_avatar='avatar:eule-prof' WHERE class_id=@class_id AND username='Sussama';
SELECT s.id, s.username, s.emoji_avatar
FROM students s WHERE s.class_id=@class_id ORDER BY s.id;
-359
View File
@@ -1,359 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Administration</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/vendor/leaflet/leaflet.css">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#f7f6f3;min-height:100vh}
.topbar{background:#fff;padding:.5rem 1rem;display:flex;align-items:center;gap:.6rem;border-bottom:1px solid rgba(0,0,0,.06);flex-wrap:wrap;position:sticky;top:0;z-index:100}
.topbar h1{font-size:.9rem;font-weight:800;color:#1f4e5a;display:flex;align-items:center;gap:.5rem}
.topbar h1 img{height:28px}
.topbar .spacer{flex:1}
.nav-btn{padding:.35rem .7rem;border:1.5px solid rgba(0,0,0,.08);border-radius:6px;background:#fff;font-size:.7rem;font-weight:600;cursor:pointer;color:#4a4a4a;text-decoration:none}
.nav-btn:hover{background:#dae8ec;color:#4a7c8a}
.nav-btn.on{background:#1f4e5a;color:#fff;border-color:#1f4e5a}
.wrap{max-width:1100px;margin:0 auto;padding:1rem}
.card{background:#fff;border-radius:10px;padding:1rem;box-shadow:0 1px 4px rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.04);margin-bottom:1rem}
.card-h{font-size:.62rem;font-weight:700;color:#4a7c8a;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.5rem}
.btn{padding:.4rem .8rem;border:none;border-radius:6px;background:#4a7c8a;color:#fff;font-size:.72rem;font-weight:700;cursor:pointer}
.btn:hover{background:#3a6470}
.btn-outline{background:transparent;color:#4a7c8a;border:1.5px solid #4a7c8a}
select,input[type=text],input[type=number]{padding:.35rem .5rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.75rem;font-family:inherit}
/* Sim Cards Grid */
.sim-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:.8rem;margin-bottom:1.5rem}
.sim-card{background:#fff;border-radius:12px;overflow:hidden;cursor:pointer;border:2px solid rgba(0,0,0,.05);transition:all .2s}
.sim-card:hover{border-color:#4a7c8a;transform:translateY(-2px);box-shadow:0 6px 20px rgba(74,124,138,.1)}
.sim-card.active{border-color:#1f4e5a;box-shadow:0 0 0 3px rgba(31,78,90,.15)}
.sim-card img{width:100%;height:100px;object-fit:cover}
.sim-card-body{padding:.6rem}
.sim-card-body h3{font-size:.78rem;font-weight:700;color:#1f4e5a}
.sim-card-body p{font-size:.6rem;color:#8a8a8a}
/* Slider rows */
.slider-row{display:grid;grid-template-columns:140px 1fr 40px;gap:8px;align-items:center;margin-bottom:.4rem;font-size:.75rem}
.slider-row label{color:#4a4a4a}
.slider-row input[type=range]{width:100%;accent-color:#4a7c8a}
.slider-row .sval{text-align:right;font-weight:700;color:#1f4e5a;font-variant-numeric:tabular-nums}
/* Waypoint rows */
.wp-row{display:grid;grid-template-columns:100px 1fr 80px 80px 70px 60px 110px 50px;gap:5px;align-items:center;padding:.4rem .2rem;border-bottom:1px solid rgba(0,0,0,.03);font-size:.7rem}
.wp-row:hover{background:#f0f8fa}
.wp-header{font-weight:700;font-size:.58rem;color:#8a8a8a;text-transform:uppercase;border-bottom:2px solid #dae8ec}
.wp-type{font-size:.58rem;padding:1px 5px;border-radius:3px;font-weight:600}
.wp-type-base{background:#f2eacc;color:#8a7020}
.wp-type-city{background:#dae8ec;color:#4a7c8a}
.wp-type-village{background:#f0eeea;color:#666}
.wp-type-peak{background:#dceadd;color:#3a6b3e}
.wp-type-target{background:#f2ddd8;color:#8a3a2a}
.wp-map-mini{width:110px;height:65px;border-radius:5px;border:1px solid rgba(0,0,0,.06)}
/* Level cards */
.level-card{border:1.5px solid rgba(0,0,0,.06);border-radius:8px;padding:.7rem;margin-bottom:.4rem}
.level-card h4{font-size:.78rem;font-weight:700;color:#1f4e5a}
.level-card .meta{font-size:.62rem;color:#8a8a8a}
/* Modal */
.modal{position:fixed;inset:0;background:rgba(0,0,0,.4);display:flex;align-items:center;justify-content:center;z-index:1000}
.modal-card{background:#fff;border-radius:14px;padding:1.2rem;max-width:600px;width:95%;max-height:90vh;overflow-y:auto}
.modal-card h3{font-size:.95rem;font-weight:800;color:#1f4e5a;margin-bottom:.6rem}
.modal-card label{display:block;font-size:.65rem;font-weight:600;color:#4a4a4a;margin-top:.5rem}
.modal-card input,.modal-card select{width:100%}
#editMap{height:400px;border-radius:8px;margin-top:.5rem}
.hidden{display:none}
/* Tab content */
.tab-content{display:none}
.tab-content.active{display:block}
</style>
</head>
<body>
<div class="topbar">
<h1><img src="assets/img/geograsim_t.svg" alt="">Administration</h1>
<span class="spacer"></span>
<a href="#" class="nav-btn on" onclick="showTab('sims')">Simulationen</a>
<a href="#" class="nav-btn" onclick="showTab('waypoints')">📍 Waypoints</a>
<a href="heli" class="nav-btn" target="_blank">🗺️ Gesamtkarte</a>
<a href="admin-modules.html" class="nav-btn">🧩 Module</a>
<a href="admin-licenses.html" class="nav-btn">🔑 Lizenzen</a>
<a href="admin-styleguide.html" class="nav-btn">🎨 Styleguide</a>
<a href="admin.html" class="nav-btn">Logout</a>
</div>
<div class="wrap">
<!-- TAB: Simulationen -->
<div class="tab-content active" id="tab-sims">
<div class="card">
<div class="card-h">Simulationen — Wähle ein Modul zur Konfiguration</div>
<div class="sim-grid" id="simGrid"></div>
</div>
<div id="simDetail"></div>
</div>
<!-- TAB: Waypoints -->
<div class="tab-content" id="tab-waypoints">
<div class="card">
<div class="card-h">📍 Waypoints — Koordinaten (<span id="wp-count">0</span>)</div>
<div style="display:flex;gap:.4rem;margin-bottom:.5rem;flex-wrap:wrap">
<select id="wp-filter-region" onchange="loadWaypoints()"><option value="">Alle</option><option value="vorarlberg">Vorarlberg</option><option value="tirol">Tirol</option></select>
<select id="wp-filter-type" onchange="loadWaypoints()"><option value="">Alle Typen</option><option value="base">Basis</option><option value="city">Stadt</option><option value="village">Dorf</option><option value="peak">Gipfel</option><option value="target">Einsatzort</option></select>
<button class="btn" onclick="openAdd()">+ Waypoint</button>
</div>
<div class="wp-row wp-header"><div>Key</div><div>Name</div><div>Lat</div><div>Lon</div><div>Region</div><div>Typ</div><div>Karte</div><div></div></div>
<div id="wp-list"></div>
</div>
</div>
</div>
<!-- Edit Modal -->
<div class="modal hidden" id="editModal">
<div class="modal-card">
<h3 id="editTitle">Waypoint bearbeiten</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem">
<div><label>Key</label><input type="text" id="e-key" placeholder="bregenz"></div>
<div><label>Name</label><input type="text" id="e-name" placeholder="Bregenz"></div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:.5rem">
<div><label>Lat</label><input type="number" id="e-lat" step="0.00001"></div>
<div><label>Lon</label><input type="number" id="e-lon" step="0.00001"></div>
<div><label>Region</label><select id="e-region"><option value="vorarlberg">Vorarlberg</option><option value="tirol">Tirol</option></select></div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem">
<div><label>Typ</label><select id="e-type"><option value="village">Dorf</option><option value="city">Stadt</option><option value="base">Basis</option><option value="peak">Gipfel</option><option value="target">Einsatzort</option><option value="pass">Pass</option></select></div>
<div><label>Info</label><input type="text" id="e-info" placeholder="Beschreibung"></div>
</div>
<p style="font-size:.68rem;color:#8a8a8a;margin-top:.4rem">Klicke auf die Karte um die Position zu setzen:</p>
<div id="editMap"></div>
<div style="display:flex;gap:.4rem;margin-top:.6rem">
<button class="btn" onclick="saveEdit()">Speichern</button>
<button class="btn btn-outline" onclick="closeEdit()">Abbrechen</button>
</div>
</div>
</div>
<script src="assets/vendor/leaflet/leaflet.js"></script>
<script>
var BASE = (window.__GGS__?.baseUrl) || '';
if (!BASE) { var p = location.pathname, i = p.indexOf('/geograsim'); if (i !== -1) { var rest = p.substring(i + '/geograsim'.length); BASE = rest.indexOf('/App/') === 0 ? p.substring(0, i) + '/geograsim/App' : p.substring(0, i) + '/geograsim'; } }
async function api(endpoint, data) {
var opts = data ? {method:'POST',headers:{'Content-Type':'application/json'},credentials:'same-origin',body:JSON.stringify(data)} : {credentials:'same-origin'};
return (await fetch(BASE + '/api/' + endpoint, opts)).json();
}
// ==========================================
// TABS
// ==========================================
function showTab(tab) {
document.querySelectorAll('.tab-content').forEach(function(el) { el.classList.toggle('active', el.id === 'tab-' + tab); });
document.querySelectorAll('.nav-btn').forEach(function(b) { b.classList.remove('on'); });
event.target.classList.add('on');
if (tab === 'waypoints') loadWaypoints();
}
// ==========================================
// SIMULATIONEN
// ==========================================
var SIMS = [
{id:'klima', name:'Klimawächter V2', icon:'🌍', img:'assets/img/card-climate.png',
params:{
start_budget:{min:100,max:2000,def:600,label:'Start-Budget (Mio €)'},
start_population:{min:1000,max:20000,def:6000,label:'Start-Bevölkerung'},
income_per_10k:{min:50,max:500,def:220,label:'Einnahmen pro 10.000 Bürger'},
budget_loss:{min:-2000,max:0,def:-500,label:'Pleite-Grenze (Mio €, negativ)'},
event_frequency:{min:0,max:1,def:0.3,step:0.1,label:'Ereignis-Häufigkeit (01)'},
time_limit:{min:30,max:150,def:75,label:'Simulationsdauer (Runden)'}
}},
{id:'sim-05', name:'Klimawächter 2D (V1)', icon:'🌡️', img:'assets/img/card-climate.png',
params:{start_co2:{min:300,max:600,def:425,label:'Start-CO₂ (ppm)'},start_temp:{min:14,max:18,def:15.2,label:'Start-Temperatur (°C)'},budget:{min:200,max:2000,def:950,label:'Budget (Mrd)'},income:{min:100,max:500,def:290,label:'Einkommen/Jahr'},damage_mult:{min:0.5,max:3,def:1,label:'Schadensmultiplikator'}}},
{id:'sim-05-3d', name:'Klimawächter 3D (V1)', icon:'🌊', img:'assets/img/card-climate.png',
params:{start_co2:{min:300,max:600,def:425,label:'Start-CO₂ (ppm)'},start_temp:{min:14,max:18,def:15.2,label:'Start-Temperatur (°C)'},budget:{min:200,max:2000,def:950,label:'Budget (Mrd)'},income:{min:100,max:500,def:290,label:'Einkommen/Jahr'}}},
{id:'sim-07', name:'Erdbeben', icon:'🌋', img:'assets/img/card-tectonic.png',
params:{quake_freq:{min:1,max:10,def:3,label:'Erdbeben-Häufigkeit'},build_cost:{min:50,max:500,def:200,label:'Baukosten'},population:{min:1000,max:50000,def:10000,label:'Bevölkerung'}}},
{id:'sim-09', name:'Energiemix', icon:'⚡', img:'assets/img/card-energy.png',
params:{demand_growth:{min:0,max:5,def:2,label:'Nachfrage-Wachstum (%/Jahr)'},co2_target:{min:20,max:80,def:50,label:'CO₂-Reduktionsziel (%)'},budget:{min:500,max:5000,def:2000,label:'Budget (Mio)'}}},
{id:'sim-10', name:'Lieferketten', icon:'👕', img:'assets/img/card-globe.png',
params:{price_weight:{min:0,max:100,def:40,label:'Preis-Gewichtung (%)'},fair_weight:{min:0,max:100,def:30,label:'Fairness-Gewichtung (%)'},co2_weight:{min:0,max:100,def:30,label:'CO₂-Gewichtung (%)'}}},
{id:'sim-11', name:'Regenwald', icon:'🌴', img:'assets/img/card-climate.png', params:{}},
{id:'sim-12', name:'Flussmanagement', icon:'🏞️', img:'assets/img/card-fluss.png',
params:{flood_freq:{min:1,max:10,def:3,label:'Hochwasser-Häufigkeit'},budget:{min:500,max:5000,def:2000,label:'Budget'},bio_weight:{min:0,max:100,def:40,label:'Biodiversitäts-Gewichtung (%)'}}},
{id:'sim-13', name:'Stadt & Raumplanung', icon:'🏗️', img:'assets/img/card-city.png',
params:{rounds:{min:5,max:20,def:10,label:'Runden'},budget_per_round:{min:100,max:1000,def:300,label:'Budget/Runde'},grid_size:{min:6,max:12,def:8,label:'Raster-Größe'}}},
{id:'sim-14', name:'Helikopter-Navigation', icon:'🚁', img:'assets/img/card-heli.png',
params:{houses:{min:0,max:14,def:8,label:'Häuser'},trees_tall:{min:0,max:14,def:6,label:'Hohe Bäume'},flocks:{min:0,max:8,def:2,label:'Vogelschwärme'},airliners:{min:0,max:3,def:1,label:'Verkehrsflugzeuge'},sportplanes:{min:0,max:4,def:2,label:'Sportflieger'},storms:{min:0,max:4,def:1,label:'Gewitterzellen'}}},
];
var selectedSim = null;
function renderSimGrid() {
var html = '';
SIMS.forEach(function(s) {
var cls = selectedSim === s.id ? ' active' : '';
html += '<div class="sim-card'+cls+'" onclick="selectSim(\''+s.id+'\')">';
html += '<img src="'+s.img+'" alt="">';
html += '<div class="sim-card-body"><h3>'+s.icon+' '+s.name+'</h3><p>'+Object.keys(s.params).length+' Parameter</p></div>';
html += '</div>';
});
document.getElementById('simGrid').innerHTML = html;
}
async function selectSim(id) {
selectedSim = id;
renderSimGrid();
var sim = SIMS.find(function(s){return s.id===id;});
if (!sim) return;
// Bestehende Levels laden
var levels = await api('levels?game_id=' + id);
if (levels.error) levels = [];
var html = '<div class="card"><div class="card-h">'+sim.icon+' '+sim.name+' — Level-Konfiguration</div>';
var params = sim.params || {};
var paramKeys = Object.keys(params);
// Für jedes der 3 Standard-Levels (Leicht/Mittel/Schwer) alle Schieberegler anzeigen
var levelNames = ['Leicht','Mittel','Schwer'];
var levelColors = ['#5a8a5e','#c4a35a','#c85c4a'];
levelNames.forEach(function(lName, li) {
var existingLevel = levels.find(function(l){return l.level_name===lName;});
var existingParams = existingLevel ? existingLevel.params : {};
var levelId = existingLevel ? existingLevel.id : 0;
html += '<div style="border-left:4px solid '+levelColors[li]+';padding:.6rem .8rem;margin-bottom:.6rem;background:rgba(0,0,0,.01);border-radius:0 8px 8px 0">';
html += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:.4rem">';
html += '<strong style="font-size:.85rem;color:'+levelColors[li]+'">'+lName+'</strong>';
html += '<button class="btn" style="font-size:.62rem;padding:.2rem .6rem" onclick="saveLevel(\''+id+'\',\''+lName+'\','+li+','+levelId+')">Speichern</button>';
html += '</div>';
paramKeys.forEach(function(key) {
var p = params[key];
var val = existingParams[key] !== undefined ? existingParams[key] : p.def;
var sliderId = 'sl-'+li+'-'+key;
var valId = 'sv-'+li+'-'+key;
html += '<div class="slider-row">';
html += '<label>'+p.label+'</label>';
html += '<input type="range" min="'+p.min+'" max="'+p.max+'" value="'+val+'" step="'+(p.max-p.min > 10 ? 1 : 0.1)+'" id="'+sliderId+'" oninput="document.getElementById(\''+valId+'\').textContent=this.value">';
html += '<span class="sval" id="'+valId+'">'+val+'</span>';
html += '</div>';
});
html += '</div>';
});
html += '</div>';
document.getElementById('simDetail').innerHTML = html;
}
async function saveLevel(gameId, levelName, levelIndex, existingId) {
var sim = SIMS.find(function(s){return s.id===gameId;});
var params = {};
Object.keys(sim.params||{}).forEach(function(key) {
var el = document.getElementById('sl-'+levelIndex+'-'+key);
if (el) params[key] = parseFloat(el.value);
});
var r = await api('levels', {action:'save', gameId:gameId, levelId:existingId||undefined, levelName:levelName, scenario:'standard', params:params, sortOrder:levelIndex+1});
if (r.error) { alert(r.error); return; }
alert(levelName + ' gespeichert!');
selectSim(gameId);
}
async function deleteLevel(id, gameId) {
if (!confirm('Level löschen?')) return;
await api('levels', {action:'delete', levelId:id});
selectSim(gameId);
}
// ==========================================
// WAYPOINTS
// ==========================================
var allWaypoints = [];
async function loadWaypoints() {
var region = document.getElementById('wp-filter-region').value;
var type = document.getElementById('wp-filter-type').value;
var url = 'waypoints?';
if (region) url += 'region=' + region + '&';
if (type) url += 'type=' + type;
var wps = await api(url);
if (wps.error) wps = [];
allWaypoints = wps;
document.getElementById('wp-count').textContent = wps.length;
var html = '';
wps.forEach(function(w) {
var typeClass = 'wp-type-' + w.wp_type;
var typeLabel = {base:'Basis',city:'Stadt',village:'Dorf',peak:'Gipfel',target:'Ziel',pass:'Pass'}[w.wp_type] || w.wp_type;
var lat = parseFloat(w.lat).toFixed(5), lon = parseFloat(w.lon).toFixed(5);
html += '<div class="wp-row">';
html += '<div style="font-family:monospace;font-size:.65rem;color:#4a7c8a;font-weight:600">'+w.wp_key+'</div>';
html += '<div><strong>'+w.name+'</strong>'+(w.info?'<br><span style="font-size:.58rem;color:#8a8a8a">'+w.info+'</span>':'')+'</div>';
html += '<div style="font-variant-numeric:tabular-nums;font-size:.65rem">'+lat+'</div>';
html += '<div style="font-variant-numeric:tabular-nums;font-size:.65rem">'+lon+'</div>';
html += '<div style="font-size:.58rem;color:#8a8a8a">'+w.region+'</div>';
html += '<div><span class="wp-type '+typeClass+'">'+typeLabel+'</span></div>';
html += '<div><img class="wp-map-mini" src="https://staticmap.openstreetmap.de/staticmap.php?center='+lat+','+lon+'&zoom=13&size=110x65&markers='+lat+','+lon+',ol-marker" loading="lazy"></div>';
html += '<div><button style="padding:.2rem .4rem;font-size:.6rem;border:1px solid rgba(0,0,0,.08);border-radius:4px;background:#fff;cursor:pointer" onclick="openEdit(\''+w.wp_key+'\')">✏️</button></div>';
html += '</div>';
});
document.getElementById('wp-list').innerHTML = html;
}
var editMap = null, editMarker = null;
function openEdit(key) {
var w = allWaypoints.find(function(x){return x.wp_key===key;});
if (!w) return;
document.getElementById('editTitle').textContent = 'Bearbeiten: ' + w.name;
document.getElementById('e-key').value = w.wp_key;
document.getElementById('e-name').value = w.name;
document.getElementById('e-lat').value = parseFloat(w.lat);
document.getElementById('e-lon').value = parseFloat(w.lon);
document.getElementById('e-region').value = w.region;
document.getElementById('e-type').value = w.wp_type;
document.getElementById('e-info').value = w.info || '';
document.getElementById('editModal').classList.remove('hidden');
setTimeout(function() {
if (!editMap) {
editMap = L.map('editMap').setView([w.lat, w.lon], 14);
L.tileLayer('php/tile-proxy.php?z={z}&x={x}&y={y}&p=osm',{attribution:'© OpenStreetMap',maxZoom:18}).addTo(editMap);
editMap.on('click',function(e){document.getElementById('e-lat').value=e.latlng.lat.toFixed(5);document.getElementById('e-lon').value=e.latlng.lng.toFixed(5);if(editMarker)editMap.removeLayer(editMarker);editMarker=L.marker(e.latlng).addTo(editMap);});
} else { editMap.setView([w.lat,w.lon],14); editMap.invalidateSize(); }
if(editMarker)editMap.removeLayer(editMarker);
editMarker=L.marker([w.lat,w.lon]).addTo(editMap);
}, 200);
}
function openAdd() {
document.getElementById('editTitle').textContent = 'Neuer Waypoint';
['e-key','e-name','e-lat','e-lon','e-info'].forEach(function(id){document.getElementById(id).value='';});
document.getElementById('editModal').classList.remove('hidden');
setTimeout(function(){if(!editMap){editMap=L.map('editMap').setView([47.3,10.5],9);L.tileLayer('php/tile-proxy.php?z={z}&x={x}&y={y}&p=osm',{attribution:'© OpenStreetMap',maxZoom:18}).addTo(editMap);editMap.on('click',function(e){document.getElementById('e-lat').value=e.latlng.lat.toFixed(5);document.getElementById('e-lon').value=e.latlng.lng.toFixed(5);if(editMarker)editMap.removeLayer(editMarker);editMarker=L.marker(e.latlng).addTo(editMap);});}else{editMap.setView([47.3,10.5],9);editMap.invalidateSize();}if(editMarker){editMap.removeLayer(editMarker);editMarker=null;}},200);
}
function closeEdit(){document.getElementById('editModal').classList.add('hidden');}
async function saveEdit() {
var r = await api('waypoints',{action:'save',wpKey:document.getElementById('e-key').value.trim().toLowerCase().replace(/[^a-z0-9_]/g,''),name:document.getElementById('e-name').value.trim(),lat:parseFloat(document.getElementById('e-lat').value),lon:parseFloat(document.getElementById('e-lon').value),region:document.getElementById('e-region').value,wpType:document.getElementById('e-type').value,info:document.getElementById('e-info').value.trim()});
if(r.error){alert(r.error);return;}
closeEdit(); loadWaypoints();
}
// ==========================================
// INIT
// ==========================================
fetch(BASE+'/api/admin',{method:'POST',headers:{'Content-Type':'application/json'},credentials:'same-origin',body:JSON.stringify({action:'status'})})
.then(function(r){return r.json()}).then(function(r){
if(!r.authenticated){location.href='admin.html';return;}
renderSimGrid();
});
</script>
</body>
</html>
-170
View File
@@ -1,170 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Lizenzverwaltung</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#f7f6f3;min-height:100vh}
.topbar{background:#fff;padding:.6rem 1.2rem;display:flex;align-items:center;gap:.8rem;border-bottom:1px solid rgba(0,0,0,.06)}
.topbar h1{font-size:.95rem;font-weight:800;color:#4a7c8a;flex:1;display:flex;align-items:center;gap:.5rem}
.topbar h1 img{height:28px}
.btn-sm{padding:.3rem .6rem;border:1px solid rgba(0,0,0,.08);border-radius:6px;background:#fff;font-size:.68rem;font-weight:600;cursor:pointer;color:#4a4a4a;text-decoration:none}
.btn-sm:hover{background:#dae8ec;color:#4a7c8a}
.wrap{max-width:1000px;margin:1rem auto;padding:0 1rem}
.card{background:#fff;border-radius:10px;padding:1rem;box-shadow:0 1px 4px rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.04);margin-bottom:1rem}
.card-h{font-size:.62rem;font-weight:700;color:#4a7c8a;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.5rem}
.stat-row{display:flex;gap:1rem;margin-bottom:1rem}
.stat{background:#f7f6f3;border-radius:8px;padding:.8rem 1.2rem;text-align:center;flex:1}
.stat .n{font-size:1.5rem;font-weight:900;color:#4a7c8a}
.stat .l{font-size:.62rem;color:#8a8a8a}
.btn{padding:.45rem .9rem;border:none;border-radius:6px;background:#4a7c8a;color:#fff;font-size:.75rem;font-weight:700;cursor:pointer}
.btn:hover{background:#3a6470}
.btn-outline{background:transparent;color:#4a7c8a;border:1.5px solid #4a7c8a}
table{width:100%;border-collapse:collapse;font-size:.72rem}
th{background:#f7f6f3;padding:.35rem .5rem;text-align:left;font-weight:600;font-size:.6rem;color:#8a8a8a}
td{padding:.35rem .5rem;border-bottom:1px solid rgba(0,0,0,.03)}
.code{font-family:'Courier New',monospace;font-weight:700;letter-spacing:.04em;font-size:.72rem}
.free{color:#5a8a5e}
.used{color:#8a8a8a}
.filter-bar{display:flex;gap:.4rem;margin-bottom:.8rem;flex-wrap:wrap;align-items:center}
.filter-bar select,.filter-bar input{padding:.35rem .5rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.72rem;font-family:inherit}
.toolbar{display:flex;gap:.4rem;margin-bottom:.8rem;flex-wrap:wrap}
.msg{font-size:.72rem;padding:.4rem .6rem;border-radius:6px;margin-top:.5rem}
.msg.ok{background:#dceadd;color:#5a8a5e}
</style>
</head>
<body>
<div class="topbar">
<h1><img src="assets/img/geograsim_t.svg" alt="GeoGraSim"> Lizenzverwaltung (Admin)</h1>
<a href="admin-modules.html" class="btn-sm">🧩 Module</a>
<a href="admin-levels.html" class="btn-sm">🎮 Level</a>
<a href="admin-styleguide.html" class="btn-sm">🎨 Styleguide</a>
<a href="admin.html" class="btn-sm">Logout</a>
</div>
<div class="wrap">
<div class="card">
<div class="stat-row">
<div class="stat"><div class="n" id="stat-total"></div><div class="l">Gesamt</div></div>
<div class="stat"><div class="n free" id="stat-free"></div><div class="l">Frei</div></div>
<div class="stat"><div class="n used" id="stat-used"></div><div class="l">Zugewiesen</div></div>
</div>
</div>
<div class="card">
<div class="card-h">Neue Lizenzen generieren</div>
<div style="display:flex;gap:.5rem;align-items:flex-end;flex-wrap:wrap">
<div>
<label style="font-size:.65rem;font-weight:600;color:#4a4a4a;display:block">Anzahl</label>
<input type="number" id="gen-count" value="100" min="1" max="1000" style="width:80px;padding:.35rem .5rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.78rem">
</div>
<div>
<label style="font-size:.65rem;font-weight:600;color:#4a4a4a;display:block">Jahr</label>
<input type="number" id="gen-year" value="2026" min="2025" max="2035" style="width:80px;padding:.35rem .5rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.78rem">
</div>
<button class="btn" onclick="generate()">Generieren</button>
</div>
<div id="gen-msg"></div>
</div>
<div class="card">
<div class="card-h">Lizenzen</div>
<div class="filter-bar">
<select id="filter-status" onchange="loadLicenses()">
<option value="">Alle</option>
<option value="free">Frei</option>
<option value="used">Zugewiesen</option>
</select>
<button class="btn btn-outline" onclick="exportFree()">Freie exportieren (CSV)</button>
</div>
<div id="license-table" style="max-height:500px;overflow-y:auto"></div>
<div style="display:flex;gap:.4rem;margin-top:.5rem">
<button class="btn btn-outline" id="btn-prev" onclick="prevPage()" disabled>← Zurück</button>
<span style="font-size:.68rem;color:#8a8a8a;padding:.35rem" id="page-info"></span>
<button class="btn btn-outline" id="btn-next" onclick="nextPage()">Weiter →</button>
</div>
</div>
</div>
<script>
var BASE = (window.__GGS__?.baseUrl) || '';
if (!BASE) { var p = location.pathname, i = p.indexOf('/geograsim'); if (i !== -1) { var rest = p.substring(i + '/geograsim'.length); BASE = rest.indexOf('/App/') === 0 ? p.substring(0, i) + '/geograsim/App' : p.substring(0, i) + '/geograsim'; } }
var page = 0, pageSize = 100;
async function api(endpoint, data) {
var opts = data ? {method:'POST',headers:{'Content-Type':'application/json'},credentials:'same-origin',body:JSON.stringify(data)} : {credentials:'same-origin'};
var r = await fetch(BASE + '/api/' + endpoint, opts);
return await r.json();
}
async function loadLicenses() {
var status = document.getElementById('filter-status').value;
var url = 'licenses?admin=1&limit='+pageSize+'&offset='+(page*pageSize);
if (status) url += '&status=' + status;
var r = await api(url);
if (r.error) return;
document.getElementById('stat-total').textContent = r.total;
document.getElementById('stat-free').textContent = r.free;
document.getElementById('stat-used').textContent = r.used;
var html = '<table><tr><th>Code</th><th>Schuljahr</th><th>Status</th><th>Schüler*in</th><th>Lehrperson</th></tr>';
r.licenses.forEach(function(l) {
var st = l.student_id ? '<span class="used">zugewiesen</span>' : '<span class="free">frei</span>';
html += '<tr>';
html += '<td class="code">'+l.code+'</td>';
html += '<td>'+l.school_year+'</td>';
html += '<td>'+st+'</td>';
html += '<td>'+(l.student_name||'—')+'</td>';
html += '<td>'+(l.teacher_name||'—')+'</td>';
html += '</tr>';
});
html += '</table>';
document.getElementById('license-table').innerHTML = html;
var totalPages = Math.ceil(r.total / pageSize);
document.getElementById('page-info').textContent = 'Seite '+(page+1)+' von '+totalPages;
document.getElementById('btn-prev').disabled = page === 0;
document.getElementById('btn-next').disabled = page >= totalPages - 1;
}
function prevPage() { if(page>0){page--;loadLicenses();} }
function nextPage() { page++; loadLicenses(); }
async function generate() {
var count = parseInt(document.getElementById('gen-count').value) || 100;
var year = parseInt(document.getElementById('gen-year').value) || 2026;
var r = await api('licenses', {action:'generate', count:count, year:year});
if (r.error) { document.getElementById('gen-msg').innerHTML = '<div class="msg" style="background:#f2ddd8;color:#c07a6b">'+r.error+'</div>'; return; }
document.getElementById('gen-msg').innerHTML = '<div class="msg ok">'+r.generated+' Lizenzen generiert.</div>';
loadLicenses();
}
function exportFree() {
api('licenses?admin=1&status=free&limit=10000').then(function(r) {
if (!r.licenses) return;
var csv = 'Code;Schuljahr\n';
r.licenses.forEach(function(l) { csv += l.code + ';' + l.school_year + '\n'; });
var blob = new Blob([csv], {type:'text/csv'});
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'lizenzen_frei.csv';
a.click();
});
}
// Admin auth check (2FA required)
fetch(BASE + '/api/admin', {method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin', body:JSON.stringify({action:'status'})})
.then(function(r){return r.json()})
.then(function(r) {
if (!r.authenticated) { location.href = 'admin.html'; return; }
loadLicenses();
});
</script>
</body>
</html>
-395
View File
@@ -1,395 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Modul-Verwaltung</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#f7f6f3;min-height:100vh}
.topbar{background:#fff;padding:.6rem 1.2rem;display:flex;align-items:center;gap:.8rem;border-bottom:1px solid rgba(0,0,0,.06)}
.topbar h1{font-size:.95rem;font-weight:800;color:#4a7c8a;flex:1;display:flex;align-items:center;gap:.5rem}
.topbar h1 img{height:28px}
.btn-sm{padding:.3rem .6rem;border:1px solid rgba(0,0,0,.08);border-radius:6px;background:#fff;font-size:.68rem;font-weight:600;cursor:pointer;color:#4a4a4a;text-decoration:none}
.btn-sm:hover{background:#dae8ec;color:#4a7c8a}
.wrap{max-width:1200px;margin:1rem auto;padding:0 1rem}
.intro{color:#4a4a4a;font-size:.82rem;margin-bottom:1rem}
.module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:1rem}
.module-card{background:#fff;border-radius:10px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.04);display:flex;flex-direction:column}
.module-img{position:relative;aspect-ratio:16/10;background:#dae8ec;overflow:hidden}
.module-img img{width:100%;height:100%;object-fit:cover;display:block}
.module-img .no-img{display:flex;align-items:center;justify-content:center;height:100%;color:#8a8a8a;font-size:.72rem}
.module-img .status-badge{position:absolute;top:8px;right:8px;padding:3px 8px;border-radius:12px;font-size:.62rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em}
.status-aktiv{background:#dceadd;color:#3a6b3e}
.status-beta{background:#fff3cd;color:#8a6400}
.status-geplant{background:#e0e0e0;color:#666}
.status-archiv{background:#f2ddd8;color:#c07a6b}
.module-body{padding:.9rem;display:flex;flex-direction:column;gap:.6rem;flex:1}
.module-title{display:flex;align-items:center;gap:.5rem}
.module-emoji{font-size:1.8rem;line-height:1}
.module-title-text{font-size:1rem;font-weight:800;color:#1f4e5a;flex:1}
.module-sub{font-size:.74rem;color:#4a4a4a;line-height:1.35}
.module-meta{display:flex;flex-wrap:wrap;gap:.3rem;margin-top:.3rem}
.meta-chip{background:#f7f6f3;padding:2px 8px;border-radius:10px;font-size:.62rem;color:#4a4a4a}
.module-actions{display:flex;gap:.4rem;margin-top:.6rem}
.btn{padding:.45rem .9rem;border:none;border-radius:6px;background:#4a7c8a;color:#fff;font-size:.72rem;font-weight:700;cursor:pointer;font-family:inherit}
.btn:hover{background:#3a6470}
.btn-outline{background:transparent;color:#4a7c8a;border:1.5px solid #4a7c8a}
/* Edit Modal */
.overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:flex-start;justify-content:center;z-index:100;padding:2rem;overflow-y:auto}
.overlay.open{display:flex}
.edit-card{background:#fff;border-radius:12px;max-width:600px;width:100%;padding:1.5rem;box-shadow:0 8px 30px rgba(0,0,0,.15)}
.edit-card h2{font-size:1.1rem;font-weight:800;color:#1f4e5a;margin-bottom:1rem;display:flex;align-items:center;gap:.5rem}
.form-grid{display:grid;gap:.8rem}
.form-row{display:grid;grid-template-columns:auto 1fr;gap:.8rem;align-items:center}
.form-row label{font-size:.72rem;font-weight:600;color:#4a4a4a}
.form-row input,.form-row select,.form-row textarea{padding:.45rem .6rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.82rem;font-family:inherit;width:100%}
.form-row textarea{min-height:80px;resize:vertical}
.form-row .emoji-preview{display:inline-flex;align-items:center;gap:.4rem;background:#f7f6f3;padding:.35rem .6rem;border-radius:6px;font-size:1.4rem;min-width:2.5rem;justify-content:center}
.form-footer{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem}
.emoji-picker{display:grid;grid-template-columns:repeat(10,1fr);gap:.3rem;margin-top:.4rem;max-height:140px;overflow-y:auto}
.emoji-pick{font-size:1.3rem;padding:.3rem;border:none;background:transparent;border-radius:6px;cursor:pointer}
.emoji-pick:hover{background:#dae8ec}
.upload-section{background:#f7f6f3;padding:.8rem;border-radius:8px}
.upload-section label{font-size:.72rem;font-weight:600;color:#4a4a4a;display:block;margin-bottom:.4rem}
.current-img{display:flex;align-items:center;gap:.6rem;margin-bottom:.6rem}
.current-img img{width:80px;height:50px;object-fit:cover;border-radius:4px}
.current-img .fname{font-family:monospace;font-size:.7rem;color:#8a8a8a}
.msg{font-size:.74rem;padding:.5rem .7rem;border-radius:6px;margin-top:.5rem}
.msg.ok{background:#dceadd;color:#3a6b3e}
.msg.err{background:#f2ddd8;color:#c07a6b}
.toolbar{display:flex;gap:.4rem;margin-bottom:1rem;flex-wrap:wrap;align-items:center}
.toolbar select{padding:.35rem .5rem;border:1.5px solid rgba(0,0,0,.1);border-radius:6px;font-size:.74rem;font-family:inherit}
</style>
</head>
<body>
<div class="topbar">
<h1><img src="assets/img/textlogo_geograsim.svg" alt="GeoGraSim"> Modul-Verwaltung (Admin)</h1>
<a href="admin-licenses.html" class="btn-sm">🎟️ Lizenzen</a>
<a href="admin-levels.html" class="btn-sm">🎮 Level</a>
<a href="admin-styleguide.html" class="btn-sm">🎨 Styleguide</a>
<a href="admin.html" class="btn-sm">Logout</a>
</div>
<div class="wrap">
<p class="intro">Hier kannst du Titel, Emoji, Bild und Status aller Module anpassen. Änderungen werden sofort in die Datenbank geschrieben und sind überall in der App wirksam (Landing Page, Detailseiten, Dashboards).</p>
<div class="toolbar">
<label style="font-size:.72rem;font-weight:600">Filter:</label>
<select id="filter-status" onchange="render()">
<option value="">Alle Status</option>
<option value="aktiv">Aktiv</option>
<option value="beta">Beta</option>
<option value="geplant">Geplant</option>
<option value="archiv">Archiv</option>
</select>
</div>
<div id="grid" class="module-grid">
<p style="color:#8a8a8a;font-size:.8rem">Lade Module …</p>
</div>
</div>
<!-- Edit Modal -->
<div class="overlay" id="overlay" onclick="if(event.target===this)closeEdit()">
<div class="edit-card">
<h2><span id="edit-emoji-display">🧩</span> <span id="edit-title-display">Modul bearbeiten</span></h2>
<div class="form-grid">
<div class="form-row">
<label>Modul-ID</label>
<input id="f-id" readonly style="background:#f7f6f3;color:#8a8a8a">
</div>
<div class="form-row">
<label>Emoji</label>
<div>
<div style="display:flex;gap:.5rem;align-items:center">
<span class="emoji-preview" id="emoji-preview">🧩</span>
<input id="f-icon" maxlength="16" style="max-width:80px" oninput="document.getElementById('emoji-preview').textContent=this.value||'';document.getElementById('edit-emoji-display').textContent=this.value||'🧩'">
<button class="btn-sm" type="button" onclick="togglePicker()">🎨 Auswählen</button>
</div>
<div id="emoji-picker" class="emoji-picker" style="display:none"></div>
</div>
</div>
<div class="form-row">
<label>Titel</label>
<input id="f-title" maxlength="128" oninput="document.getElementById('edit-title-display').textContent=this.value||'Modul bearbeiten'">
</div>
<div class="form-row">
<label>Untertitel</label>
<input id="f-subtitle" maxlength="255">
</div>
<div class="form-row">
<label>Status</label>
<select id="f-status">
<option value="aktiv">Aktiv</option>
<option value="beta">Beta</option>
<option value="geplant">Geplant</option>
<option value="archiv">Archiv</option>
</select>
</div>
<div class="form-row">
<label>Dauer (min)</label>
<input id="f-duration" type="number" min="0">
</div>
<div class="form-row">
<label>Alter</label>
<div style="display:flex;gap:.4rem;align-items:center">
<input id="f-agemin" type="number" min="5" max="20" style="width:70px">
<span>bis</span>
<input id="f-agemax" type="number" min="5" max="20" style="width:70px">
<span style="font-size:.7rem;color:#8a8a8a">Jahre</span>
</div>
</div>
<div class="form-row">
<label>Simulations-URL</label>
<input id="f-playurl" placeholder="klima-2d">
</div>
<div class="form-row">
<label>Seiten-URL</label>
<input id="f-pageurl" placeholder="modul-klima">
</div>
<div class="form-row">
<label>Reihenfolge</label>
<input id="f-sort" type="number">
</div>
<div class="upload-section">
<label>Card-Bild</label>
<div class="current-img">
<img id="current-img-preview" src="" alt="" style="display:none">
<span class="fname" id="current-img-name">(kein Bild)</span>
</div>
<input type="file" id="f-image" accept="image/png,image/jpeg,image/webp,image/svg+xml">
<div style="font-size:.66rem;color:#8a8a8a;margin-top:.3rem">Empfohlen: 1024×640 PNG/JPG, max 5 MB</div>
</div>
</div>
<div id="edit-msg"></div>
<div class="form-footer">
<button class="btn btn-outline" onclick="closeEdit()">Abbrechen</button>
<button class="btn" onclick="save()">Speichern</button>
</div>
</div>
</div>
<script>
var BASE = location.pathname.replace(/\/[^\/]*$/, '');
var modules = [];
var editingId = null;
// Kuratierte Emoji-Auswahl passend zu GeoGraSim-Themen
var EMOJI_SET = ['🌍','🌎','🌏','🗺️','🧭','🏔️','⛰️','🌋','🏕️','🏞️',
'🌊','💧','🌧️','☀️','☁️','❄️','🌡️','🌪️','🌈','💨',
'🏙️','🏛️','🏘️','🏠','🏭','🚁','✈️','🚆','🚌','🚲',
'🌲','🌳','🌴','🌿','🍃','🌱','🐟','🐝','🦋','🐼',
'⚡','🔥','💡','🔋','☢️','🛢️','⛽','🌬️','♻️','🌿',
'📊','📈','📉','🎯','🏆','🎮','📚','🧪','🔬','🧬'];
function loadModules() {
fetch(BASE + '/api/admin-modules', { credentials: 'same-origin' })
.then(r => r.json())
.then(d => {
if (d.modules) {
modules = d.modules;
render();
} else {
document.getElementById('grid').innerHTML = '<p style="color:#c07a6b">Fehler: ' + (d.error || 'unbekannt') + '</p>';
}
});
}
function render() {
var filter = document.getElementById('filter-status').value;
var filtered = filter ? modules.filter(m => m.status === filter) : modules;
var grid = document.getElementById('grid');
if (!filtered.length) {
grid.innerHTML = '<p style="color:#8a8a8a;font-size:.8rem">Keine Module vorhanden.</p>';
return;
}
grid.innerHTML = filtered.map(m => {
var imgSrc = m.card_image ? 'assets/img/' + m.card_image : '';
var img = imgSrc
? '<img src="' + imgSrc + '" alt="' + esc(m.title) + '">'
: '<div class="no-img">Kein Bild</div>';
var dur = m.duration_min ? m.duration_min + ' min' : '—';
var age = (m.age_min && m.age_max) ? m.age_min + '' + m.age_max + ' J' : '—';
return '<div class="module-card">' +
'<div class="module-img">' + img +
'<div class="status-badge status-' + m.status + '">' + m.status + '</div></div>' +
'<div class="module-body">' +
'<div class="module-title"><span class="module-emoji">' + (m.icon || '🧩') + '</span>' +
'<span class="module-title-text">' + esc(m.title) + '</span></div>' +
(m.subtitle ? '<div class="module-sub">' + esc(m.subtitle) + '</div>' : '') +
'<div class="module-meta">' +
'<span class="meta-chip">🆔 ' + m.module_id + '</span>' +
'<span class="meta-chip">⏱ ' + dur + '</span>' +
'<span class="meta-chip">👥 ' + age + '</span>' +
'</div>' +
'<div class="module-actions">' +
'<button class="btn" onclick="editModule(\'' + m.module_id + '\')">Bearbeiten</button>' +
(m.play_url ? '<a class="btn btn-outline" href="' + m.play_url + '" target="_blank">▶ Testen</a>' : '') +
'</div>' +
'</div></div>';
}).join('');
}
function esc(s) { return (s || '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c]); }
function editModule(id) {
var m = modules.find(x => x.module_id === id);
if (!m) return;
editingId = id;
document.getElementById('f-id').value = m.module_id;
document.getElementById('f-icon').value = m.icon || '';
document.getElementById('emoji-preview').textContent = m.icon || '';
document.getElementById('edit-emoji-display').textContent = m.icon || '🧩';
document.getElementById('f-title').value = m.title || '';
document.getElementById('edit-title-display').textContent = m.title || 'Modul bearbeiten';
document.getElementById('f-subtitle').value = m.subtitle || '';
document.getElementById('f-status').value = m.status || 'beta';
document.getElementById('f-duration').value = m.duration_min || '';
document.getElementById('f-agemin').value = m.age_min || '';
document.getElementById('f-agemax').value = m.age_max || '';
document.getElementById('f-playurl').value = m.play_url || '';
document.getElementById('f-pageurl').value = m.page_url || '';
document.getElementById('f-sort').value = m.sort_order || 0;
var imgPreview = document.getElementById('current-img-preview');
var imgName = document.getElementById('current-img-name');
if (m.card_image) {
imgPreview.src = 'assets/img/' + m.card_image;
imgPreview.style.display = '';
imgName.textContent = m.card_image;
} else {
imgPreview.style.display = 'none';
imgName.textContent = '(kein Bild)';
}
document.getElementById('f-image').value = '';
document.getElementById('edit-msg').innerHTML = '';
document.getElementById('overlay').classList.add('open');
renderEmojiPicker();
}
function renderEmojiPicker() {
var p = document.getElementById('emoji-picker');
p.innerHTML = EMOJI_SET.map(e =>
'<button type="button" class="emoji-pick" onclick="selectEmoji(\'' + e + '\')">' + e + '</button>'
).join('');
}
function togglePicker() {
var p = document.getElementById('emoji-picker');
p.style.display = p.style.display === 'none' ? 'grid' : 'none';
}
function selectEmoji(e) {
document.getElementById('f-icon').value = e;
document.getElementById('emoji-preview').textContent = e;
document.getElementById('edit-emoji-display').textContent = e;
document.getElementById('emoji-picker').style.display = 'none';
}
function closeEdit() {
document.getElementById('overlay').classList.remove('open');
editingId = null;
}
function save() {
if (!editingId) return;
var msg = document.getElementById('edit-msg');
msg.innerHTML = '';
var data = {
module_id: editingId,
title: document.getElementById('f-title').value.trim(),
subtitle: document.getElementById('f-subtitle').value.trim(),
icon: document.getElementById('f-icon').value.trim(),
status: document.getElementById('f-status').value,
duration_min: document.getElementById('f-duration').value || null,
age_min: document.getElementById('f-agemin').value || null,
age_max: document.getElementById('f-agemax').value || null,
play_url: document.getElementById('f-playurl').value.trim(),
page_url: document.getElementById('f-pageurl').value.trim(),
sort_order: document.getElementById('f-sort').value || 0
};
fetch(BASE + '/api/admin-modules', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify(data)
})
.then(r => r.json())
.then(r => {
if (r.ok) {
// Wenn Bild hochgeladen: zusätzlich POST
var file = document.getElementById('f-image').files[0];
if (file) return uploadImage(file);
msg.innerHTML = '<div class="msg ok">✓ Gespeichert</div>';
loadModules();
setTimeout(closeEdit, 800);
} else {
msg.innerHTML = '<div class="msg err">Fehler: ' + (r.error || 'unbekannt') + '</div>';
}
})
.catch(e => { msg.innerHTML = '<div class="msg err">Netzwerkfehler</div>'; });
}
function uploadImage(file) {
var msg = document.getElementById('edit-msg');
var fd = new FormData();
fd.append('module_id', editingId);
fd.append('image', file);
return fetch(BASE + '/api/admin-modules', {
method: 'POST',
credentials: 'same-origin',
body: fd
})
.then(r => r.json())
.then(r => {
if (r.ok) {
msg.innerHTML = '<div class="msg ok">✓ Gespeichert inkl. Bild</div>';
loadModules();
setTimeout(closeEdit, 800);
} else {
msg.innerHTML = '<div class="msg err">Bild-Upload fehlgeschlagen: ' + (r.error || '') + '</div>';
}
});
}
// Auth-Check
fetch(BASE + '/api/admin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify({ action: 'status' })
})
.then(r => r.json())
.then(r => {
if (!r.authenticated) { location.href = 'admin.html'; return; }
loadModules();
});
</script>
</body>
</html>
-331
View File
@@ -1,331 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Style-Guide (Admin)</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#f7f6f3;min-height:100vh;color:#2a2a2a}
.topbar{background:#fff;padding:.6rem 1.2rem;display:flex;align-items:center;gap:.8rem;border-bottom:1px solid rgba(0,0,0,.06)}
.topbar h1{font-size:.95rem;font-weight:800;color:#4a7c8a;flex:1;display:flex;align-items:center;gap:.5rem}
.topbar h1 img{height:28px}
.btn-sm{padding:.3rem .6rem;border:1px solid rgba(0,0,0,.08);border-radius:6px;background:#fff;font-size:.68rem;font-weight:600;cursor:pointer;color:#4a4a4a;text-decoration:none}
.btn-sm:hover{background:#dae8ec;color:#4a7c8a}
.wrap{max-width:980px;margin:1rem auto;padding:0 1rem}
.card{background:#fff;border-radius:10px;padding:1.2rem 1.3rem;box-shadow:0 1px 4px rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.04);margin-bottom:1rem}
.card-h{font-size:.65rem;font-weight:700;color:#4a7c8a;text-transform:uppercase;letter-spacing:.06em;margin-bottom:.65rem}
h2{font-size:1.15rem;font-weight:800;color:#1f4b37;margin-bottom:.4rem}
h3{font-size:.95rem;font-weight:700;color:#4a7c8a;margin:.9rem 0 .4rem}
p{font-size:.82rem;line-height:1.55;color:#4a4a4a;margin-bottom:.5rem}
p.lead{font-size:.78rem;color:#6a6a6a}
code{font-family:'JetBrains Mono','Fira Code',monospace;font-size:.78rem;background:#f0ede4;padding:.05rem .35rem;border-radius:4px;color:#1f4b37}
pre{font-family:'JetBrains Mono','Fira Code',monospace;font-size:.74rem;background:#f0ede4;padding:.7rem .9rem;border-radius:7px;color:#1f4b37;line-height:1.5;white-space:pre-wrap;word-break:break-word;margin:.4rem 0}
.copy-block{position:relative}
.copy-btn{position:absolute;top:.45rem;right:.5rem;font-size:.6rem;padding:.2rem .55rem;border:1.5px solid rgba(0,0,0,.1);border-radius:5px;background:#fff;cursor:pointer;font-weight:600;color:#4a7c8a}
.copy-btn:hover{background:#dae8ec}
.copy-btn.ok{background:#dceadd;color:#5a8a5e;border-color:#5a8a5e}
.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:.7rem;margin:.5rem 0}
.sw{border:1px solid rgba(0,0,0,.06);border-radius:7px;overflow:hidden;cursor:pointer;background:#fff;transition:transform .12s}
.sw:hover{transform:translateY(-1px);border-color:#4a7c8a}
.sw-color{height:60px}
.sw-meta{padding:.45rem .55rem;font-size:.68rem}
.sw-meta strong{display:block;color:#1f4b37}
.sw-meta span{color:#8a8a8a;font-family:'JetBrains Mono',monospace;font-size:.66rem}
.pill{display:inline-block;padding:.18rem .55rem;border-radius:999px;font-size:.65rem;font-weight:600;background:#dae8ec;color:#1f4e5a;margin-right:.3rem}
.pill.warn{background:#fde8d0;color:#a05a2b}
.pill.bad{background:#f2ddd8;color:#a04a3a}
table{width:100%;border-collapse:collapse;font-size:.76rem;margin:.4rem 0}
th{text-align:left;background:#f7f6f3;padding:.4rem .55rem;font-weight:700;color:#4a4a4a;border-bottom:2px solid rgba(0,0,0,.06)}
td{padding:.4rem .55rem;border-bottom:1px solid rgba(0,0,0,.04);vertical-align:top}
ul{margin:.3rem 0 .6rem 1.3rem;font-size:.82rem;line-height:1.55;color:#4a4a4a}
ul li{margin-bottom:.2rem}
.toc{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:1rem}
.toc a{padding:.3rem .65rem;background:#fff;border:1.5px solid rgba(0,0,0,.06);border-radius:6px;font-size:.7rem;color:#4a7c8a;text-decoration:none;font-weight:600}
.toc a:hover{background:#dae8ec;border-color:#4a7c8a}
</style>
</head>
<body>
<div class="topbar">
<h1><img src="assets/img/geograsim_t.svg" alt="GeoGraSim"> Style-Guide (Admin)</h1>
<a href="admin-licenses.html" class="btn-sm">🔑 Lizenzen</a>
<a href="admin-modules.html" class="btn-sm">🧩 Module</a>
<a href="admin-levels.html" class="btn-sm">🎮 Level</a>
<a href="admin.html" class="btn-sm">Logout</a>
</div>
<div class="wrap">
<div class="toc">
<a href="#bildstil">🎨 Bildstil</a>
<a href="#farben-bild">🌿 Bild-Farbpalette</a>
<a href="#farben-ui">🧩 UI-Farbtokens</a>
<a href="#layout">📐 Layout &amp; Spacing</a>
<a href="#typo">🔤 Typografie</a>
<a href="#bilder">🖼️ Bildformate</a>
<a href="#ipad">📱 iPad-Patterns</a>
<a href="#sprache">🗣️ Sprache</a>
</div>
<div class="card">
<h2>Style-Guide</h2>
<p class="lead">Verbindliche Stil-Referenz für alle GeoGraSim-Module. Klick auf Farbfelder oder „Kopieren" überträgt den Wert in die Zwischenablage. Diese Seite ist die Single-Source-of-Truth — wenn du etwas änderst, musst du es hier auch aktualisieren.</p>
</div>
<!-- ============================================================== -->
<div class="card" id="bildstil">
<div class="card-h">DALL-E / Bildgenerierung</div>
<h3>Offizieller Prompt-Block</h3>
<p>Verbatim verwenden, NICHT umformulieren. Bei jedem Bild diesen Block voranstellen, danach nur den Szenen-Teil ergänzen.</p>
<div class="copy-block">
<button class="copy-btn" data-copy="prompt-base">Kopieren</button>
<pre id="prompt-base">Flat Scandinavian illustration, wide panoramic landscape filling the entire 16:9 frame edge-to-edge, painted style with clean vector shapes, dark forest green (#1f4b37) and sage green (#4a7c4e) tones, yellow-mustard (#e8c547) accents, beige (#e8e4d8) buildings and valleys, white highlights. No text, no watermark, no logos, no borders, no frame.</pre>
</div>
<h3>Eckdaten</h3>
<table>
<tr><th>Feld</th><th>Wert</th></tr>
<tr><td>Modell</td><td><code>dall-e-3</code></td></tr>
<tr><td>Splash-Auflösung</td><td>1792 × 1024 (16:9 panoramisch)</td></tr>
<tr><td>Glossar-Bilder</td><td>1792 × 1024, standard quality</td></tr>
<tr><td>Avatar-Bilder</td><td>1024 × 1024, kreisrund maskiert via CSS</td></tr>
<tr><td>Format</td><td>PNG</td></tr>
<tr><td>API-Key</td><td><code>OPENAI_API_KEY</code> in <code>App/.env.local</code> (nicht im Git)</td></tr>
</table>
<h3>Tabu</h3>
<p>
<span class="pill bad">keine Schrift im Bild</span>
<span class="pill bad">keine Logos</span>
<span class="pill bad">keine Wasserzeichen</span>
<span class="pill bad">keine Rahmen / Borders</span>
</p>
<h3>Single-Source-of-Truth</h3>
<p>Lauffähiger Referenz-Generator: <code>App/sims/logistik/scripts/generate-splash-images.sh</code> (Variable <code>PROMPT_BASE</code>). Bei Pipeline-Fragen dort als Vorlage abschauen.</p>
<h3>Why</h3>
<p>Konsistenz über alle Module. Die Sims stehen auf der Schülerseite nebeneinander; wenn ein Modul aus dem Stil ausbricht, fällt es sofort auf. Gilt nicht nur für Splashes, sondern auch für Spielfeld-Hintergründe, Sprites, Marker-Icons, Bewertungs-Visuals.</p>
</div>
<!-- ============================================================== -->
<div class="card" id="farben-bild">
<div class="card-h">Bild-Farbpalette (verbindlich für DALL-E + Sprites + SVGs)</div>
<p>Klick auf eine Karte kopiert den Hex-Wert.</p>
<div class="swatches">
<div class="sw" data-copy-text="#1f4b37"><div class="sw-color" style="background:#1f4b37"></div><div class="sw-meta"><strong>Forest green</strong><span>#1f4b37</span></div></div>
<div class="sw" data-copy-text="#4a7c4e"><div class="sw-color" style="background:#4a7c4e"></div><div class="sw-meta"><strong>Sage green</strong><span>#4a7c4e</span></div></div>
<div class="sw" data-copy-text="#e8c547"><div class="sw-color" style="background:#e8c547"></div><div class="sw-meta"><strong>Yellow-mustard</strong><span>#e8c547</span></div></div>
<div class="sw" data-copy-text="#e8e4d8"><div class="sw-color" style="background:#e8e4d8"></div><div class="sw-meta"><strong>Beige</strong><span>#e8e4d8</span></div></div>
<div class="sw" data-copy-text="#ffffff"><div class="sw-color" style="background:#ffffff;border:1px solid #ccc"></div><div class="sw-meta"><strong>Weiß-Highlights</strong><span>#ffffff</span></div></div>
</div>
</div>
<!-- ============================================================== -->
<div class="card" id="farben-ui">
<div class="card-h">UI-Farbtokens (CSS-Variablen aus design-system.css)</div>
<p>Diese Tokens nutzen alle Plattform-UIs (Cockpits, Admin, Wrapper, Modale). In Sims als <code>var(--ggs-fjord)</code> referenzieren.</p>
<h3>Akzent (Fjord)</h3>
<div class="swatches">
<div class="sw" data-copy-text="#4a7c8a"><div class="sw-color" style="background:#4a7c8a"></div><div class="sw-meta"><strong>--ggs-fjord</strong><span>#4a7c8a</span></div></div>
<div class="sw" data-copy-text="#1f4e5a"><div class="sw-color" style="background:#1f4e5a"></div><div class="sw-meta"><strong>--ggs-fjord-dark</strong><span>#1f4e5a</span></div></div>
<div class="sw" data-copy-text="#dae8ec"><div class="sw-color" style="background:#dae8ec"></div><div class="sw-meta"><strong>--ggs-fjord-light</strong><span>#dae8ec</span></div></div>
</div>
<h3>Erfolg (Moss)</h3>
<div class="swatches">
<div class="sw" data-copy-text="#5a8a5e"><div class="sw-color" style="background:#5a8a5e"></div><div class="sw-meta"><strong>--ggs-moss</strong><span>#5a8a5e</span></div></div>
<div class="sw" data-copy-text="#3a6b3e"><div class="sw-color" style="background:#3a6b3e"></div><div class="sw-meta"><strong>--ggs-moss-dark</strong><span>#3a6b3e</span></div></div>
<div class="sw" data-copy-text="#dcead0"><div class="sw-color" style="background:#dcead0"></div><div class="sw-meta"><strong>--ggs-moss-light</strong><span>#dcead0</span></div></div>
</div>
<h3>Warnung &amp; Fehler</h3>
<div class="swatches">
<div class="sw" data-copy-text="#e8833a"><div class="sw-color" style="background:#e8833a"></div><div class="sw-meta"><strong>--ggs-orange / warning</strong><span>#e8833a</span></div></div>
<div class="sw" data-copy-text="#c85c4a"><div class="sw-color" style="background:#c85c4a"></div><div class="sw-meta"><strong>--ggs-coral / danger</strong><span>#c85c4a</span></div></div>
<div class="sw" data-copy-text="#f0d0ca"><div class="sw-color" style="background:#f0d0ca"></div><div class="sw-meta"><strong>--ggs-coral-light</strong><span>#f0d0ca</span></div></div>
</div>
<h3>Neutral &amp; Sand</h3>
<div class="swatches">
<div class="sw" data-copy-text="#f5f2eb"><div class="sw-color" style="background:#f5f2eb;border:1px solid #ddd"></div><div class="sw-meta"><strong>--ggs-bg</strong><span>#f5f2eb</span></div></div>
<div class="sw" data-copy-text="#e8e4d8"><div class="sw-color" style="background:#e8e4d8;border:1px solid #ddd"></div><div class="sw-meta"><strong>--ggs-bg-dark</strong><span>#e8e4d8</span></div></div>
<div class="sw" data-copy-text="#e8d5b5"><div class="sw-color" style="background:#e8d5b5"></div><div class="sw-meta"><strong>--ggs-sand</strong><span>#e8d5b5</span></div></div>
<div class="sw" data-copy-text="#c4a97a"><div class="sw-color" style="background:#c4a97a"></div><div class="sw-meta"><strong>--ggs-sand-dark</strong><span>#c4a97a</span></div></div>
<div class="sw" data-copy-text="#e0ddd4"><div class="sw-color" style="background:#e0ddd4"></div><div class="sw-meta"><strong>--ggs-border</strong><span>#e0ddd4</span></div></div>
</div>
<h3>Text</h3>
<div class="swatches">
<div class="sw" data-copy-text="#2a2a2a"><div class="sw-color" style="background:#2a2a2a"></div><div class="sw-meta"><strong>--ggs-text</strong><span>#2a2a2a</span></div></div>
<div class="sw" data-copy-text="#8a8a8a"><div class="sw-color" style="background:#8a8a8a"></div><div class="sw-meta"><strong>--ggs-text-muted</strong><span>#8a8a8a</span></div></div>
<div class="sw" data-copy-text="#b0b0b0"><div class="sw-color" style="background:#b0b0b0"></div><div class="sw-meta"><strong>--ggs-text-light</strong><span>#b0b0b0</span></div></div>
</div>
<h3>Komplette CSS-Variable als Block</h3>
<div class="copy-block">
<button class="copy-btn" data-copy="css-tokens">Kopieren</button>
<pre id="css-tokens">--ggs-fjord: #4a7c8a;
--ggs-fjord-dark: #1f4e5a;
--ggs-fjord-light: #dae8ec;
--ggs-moss: #5a8a5e;
--ggs-moss-dark: #3a6b3e;
--ggs-moss-light: #dcead0;
--ggs-sand: #e8d5b5;
--ggs-sand-dark: #c4a97a;
--ggs-coral: #c85c4a;
--ggs-coral-light: #f0d0ca;
--ggs-orange: #e8833a;
--ggs-bg: #f5f2eb;
--ggs-bg-dark: #e8e4d8;
--ggs-white: #ffffff;
--ggs-text: #2a2a2a;
--ggs-text-muted: #8a8a8a;
--ggs-text-light: #b0b0b0;
--ggs-border: #e0ddd4;
--ggs-success: #5a8a5e;
--ggs-warning: #e8833a;
--ggs-danger: #c85c4a;
--ggs-info: #4a7c8a;</pre>
</div>
</div>
<!-- ============================================================== -->
<div class="card" id="layout">
<div class="card-h">Layout &amp; Spacing</div>
<table>
<tr><th>Token</th><th>Wert</th><th>Verwendung</th></tr>
<tr><td><code>--ggs-gap-xs</code></td><td>4 px</td><td>Inline-Abstände, Pill-Padding</td></tr>
<tr><td><code>--ggs-gap-sm</code></td><td>8 px</td><td>Button-Innenabstand, Form-Felder</td></tr>
<tr><td><code>--ggs-gap-md</code></td><td>16 px</td><td>Card-Innenabstand, Standard-Layout</td></tr>
<tr><td><code>--ggs-gap-lg</code></td><td>24 px</td><td>Sektion-Abstand</td></tr>
<tr><td><code>--ggs-gap-xl</code></td><td>32 px</td><td>Hero-Bereiche</td></tr>
<tr><td><code>--ggs-radius-sm</code></td><td>6 px</td><td>Pills, kleine Buttons</td></tr>
<tr><td><code>--ggs-radius-md</code></td><td>12 px</td><td>Karten, Modale</td></tr>
<tr><td><code>--ggs-radius-lg</code></td><td>16 px</td><td>Hero-Cards, große Modale</td></tr>
<tr><td><code>--ggs-radius-pill</code></td><td>999 px</td><td>Pills, Avatar-Kreise</td></tr>
<tr><td><code>--ggs-shadow-sm</code></td><td><code>0 1px 3px rgba(0,0,0,.08)</code></td><td>Karten</td></tr>
<tr><td><code>--ggs-shadow-md</code></td><td><code>0 2px 8px rgba(0,0,0,.12)</code></td><td>Modale, schwebende Layers</td></tr>
<tr><td><code>--ggs-shadow-lg</code></td><td><code>0 4px 16px rgba(0,0,0,.16)</code></td><td>Tooltips, Spectator-Banner</td></tr>
</table>
</div>
<!-- ============================================================== -->
<div class="card" id="typo">
<div class="card-h">Typografie</div>
<table>
<tr><th>Token</th><th>Wert</th></tr>
<tr><td><code>--ggs-font</code></td><td><code>'Inter', system-ui, -apple-system, sans-serif</code></td></tr>
<tr><td><code>--ggs-font-mono</code></td><td><code>'JetBrains Mono', 'Fira Code', monospace</code></td></tr>
</table>
<h3>Größenrichtlinien</h3>
<ul>
<li><strong>0.62 rem</strong> — Card-Header (uppercase, letter-spacing .05em)</li>
<li><strong>0.7 rem</strong> — Hilfstexte, Subtitles</li>
<li><strong>0.78 rem</strong> — Body-Text in Karten</li>
<li><strong>0.85 rem</strong> — Modul-Namen, Tabs</li>
<li><strong>0.95 rem</strong> — H3 / Section-Titel</li>
<li><strong>1.15 rem</strong> — H2 / Page-Titel</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="bilder">
<div class="card-h">Bildformate &amp; Pfade</div>
<table>
<tr><th>Typ</th><th>Maße</th><th>Pfad</th></tr>
<tr><td>Modul-Card-Image (Cockpit)</td><td>≈ 800 × 450 (16:9)</td><td><code>App/assets/img/sim-NN-&lt;slug&gt;.png</code></td></tr>
<tr><td>Glossar-Bild</td><td>1792 × 1024</td><td><code>App/assets/img/glossar/&lt;slug&gt;.png</code></td></tr>
<tr><td>Glossar-SVG (Schemata)</td><td>vektor</td><td><code>App/assets/img/glossar/&lt;slug&gt;-schema.svg</code></td></tr>
<tr><td>Splash (Sim-Intro)</td><td>1792 × 1024</td><td><code>App/sims/&lt;slug&gt;/assets/splash-*.png</code></td></tr>
<tr><td>Avatar (User)</td><td>1024 × 1024</td><td><code>App/assets/img/avatars/avatar-&lt;slug&gt;.png</code></td></tr>
<tr><td>Logo (SVG)</td><td>vektor</td><td><code>App/assets/img/geograsim_t.svg</code></td></tr>
</table>
<h3>Avatar-Slugs (30 Stück, 3 Gruppen)</h3>
<ul>
<li><strong>Geo-Welt:</strong> pilotin · pilot · kartografin · geologe · meteorologin · stadtplaner · forscherin · forscher · taucherin · astronaut</li>
<li><strong>Cool &amp; lustig:</strong> coole-girl · coole-boy · lustige-girl · lustige-boy · nerd-girl · sportlich-boy · kuenstlerin · musiker · gaertnerin · abenteurer</li>
<li><strong>Tier-Begleiter:</strong> fuchs-explorer · eule-prof · baer-foerster · pinguin-polar · affe-tropen · delfin-meer · adler-pilot · schildkroete-w · katze-stadt · biene-natur</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="ipad">
<div class="card-h">iPad-Patterns (Hauptzielgerät: iPad Landscape 1180 × 820)</div>
<ul>
<li><strong>Touch-Ziele</strong> ≥ 36 px Höhe, idealerweise 44 px für primäre Aktionen</li>
<li><strong>Kein Hover-Kleber</strong> — alle Interaktionen müssen ohne Hover funktionieren</li>
<li><strong>Modale nutzen</strong> <code>height: 100dvh</code> + <code>safe-area-inset-bottom</code></li>
<li><strong>Sticky Aktions-Buttons</strong> unten im Modal — nicht außerhalb scrollen lassen</li>
<li><strong>Float-✕ oben rechts</strong> bei Modalen, damit „Schließen" immer erreichbar ist</li>
<li><strong>Layout breit statt hoch</strong> — Badges horizontal, 2-Spalten-Grids wo möglich</li>
<li><strong>viewport-fit=cover</strong> + <code>100dvh</code> für Vollbild-Sims</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="sprache">
<div class="card-h">Sprache (Lernarbeit-Lexikon)</div>
<p>Niemals „spielen / Spiel / Spieler:in" verwenden. GeoGraSim ist Lernarbeit nach Wygotski, kein Spiel.</p>
<table>
<tr><th>Statt</th><th>Verwende</th></tr>
<tr><td>spielen</td><td>arbeiten mit · bearbeiten</td></tr>
<tr><td>Spiel</td><td>Simulation · Modul</td></tr>
<tr><td>Spieler:in</td><td>Bearbeiter:in · Schüler:in</td></tr>
<tr><td>Spielrunde</td><td>Durchgang</td></tr>
<tr><td>Game Over</td><td>Durchgang beendet</td></tr>
</table>
<p>Ausnahme: in Code-Variablen (<code>state.gameOver</code>, <code>player_progress</code>) ist „game/player" als technischer Begriff unkritisch — Hauptsache an der UI nicht sichtbar.</p>
</div>
</div>
<script>
function copyText(text, el) {
navigator.clipboard.writeText(text).then(function() {
if (el) {
var orig = el.textContent;
el.textContent = '✓ kopiert';
el.classList.add('ok');
setTimeout(function() { el.textContent = orig; el.classList.remove('ok'); }, 1100);
}
});
}
// Copy-Buttons mit data-copy=ID
document.querySelectorAll('.copy-btn[data-copy]').forEach(function(btn) {
btn.addEventListener('click', function() {
var src = document.getElementById(btn.getAttribute('data-copy'));
if (src) copyText(src.textContent, btn);
});
});
// Swatches mit data-copy-text
document.querySelectorAll('.sw[data-copy-text]').forEach(function(sw) {
sw.addEventListener('click', function() {
var txt = sw.getAttribute('data-copy-text');
copyText(txt, null);
var meta = sw.querySelector('.sw-meta strong');
if (meta) {
var orig = meta.textContent;
meta.textContent = '✓ kopiert';
setTimeout(function() { meta.textContent = orig; }, 900);
}
});
});
// Auth-Check: nur eingeloggter Admin darf hier sein
fetch('/api/admin', {
method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin',
body: JSON.stringify({action:'status'})
}).then(function(r) { return r.json(); }).then(function(r) {
if (!r.authenticated) location.href = 'admin.html';
}).catch(function() {});
</script>
<script src="assets/js/version-tag.js" defer></script>
</body>
</html>
-109
View File
@@ -1,109 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Administration</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#1f4e5a;min-height:100vh;display:flex;align-items:center;justify-content:center}
.card{background:#fff;border-radius:16px;padding:2rem;max-width:380px;width:90%;box-shadow:0 12px 40px rgba(0,0,0,.2)}
.logo{text-align:center;margin-bottom:1rem}
.logo img{height:36px}
.logo p{font-size:.7rem;color:#8a8a8a;margin-top:.3rem}
h2{font-size:1rem;font-weight:800;color:#1f4e5a;margin-bottom:.8rem;text-align:center}
label{display:block;font-size:.7rem;font-weight:600;color:#4a4a4a;margin-bottom:.15rem;margin-top:.6rem}
input{width:100%;padding:.55rem .7rem;border:1.5px solid rgba(0,0,0,.1);border-radius:7px;font-size:.82rem;font-family:inherit;outline:none;transition:border .15s}
input:focus{border-color:#4a7c8a}
.pin-input{text-align:center;font-size:1.5rem;font-weight:900;letter-spacing:.3em;font-family:'Courier New',monospace;color:#1f4e5a}
.btn{width:100%;padding:.6rem;border:none;border-radius:8px;background:#1f4e5a;color:#fff;font-size:.85rem;font-weight:700;cursor:pointer;margin-top:.8rem;transition:background .15s}
.btn:hover{background:#163a44}
.msg{margin-top:.6rem;font-size:.72rem;padding:.4rem .6rem;border-radius:6px;display:none}
.msg.err{display:block;background:#f2ddd8;color:#c07a6b}
.msg.ok{display:block;background:#dceadd;color:#5a8a5e}
.hidden{display:none}
.step-hint{font-size:.68rem;color:#8a8a8a;text-align:center;margin-bottom:.6rem}
</style>
</head>
<body>
<div class="card">
<div class="logo">
<img src="assets/img/geograsim_t.svg" alt="GeoGraSim">
<p>Administration</p>
</div>
<!-- Schritt 1: Login -->
<div id="step-login">
<h2>🔐 Admin-Anmeldung</h2>
<label>Benutzername</label>
<input type="text" id="a-user" autocomplete="off">
<label>Passwort</label>
<input type="password" id="a-pass">
<button class="btn" onclick="doLogin()">Anmelden</button>
</div>
<!-- Schritt 2: PIN -->
<div id="step-pin" class="hidden">
<h2>📧 PIN eingeben</h2>
<p class="step-hint">Ein 4-stelliger PIN wurde an <strong id="pin-email"></strong> gesendet.</p>
<input type="text" id="a-pin" class="pin-input" maxlength="4" placeholder="0000" autocomplete="off">
<button class="btn" onclick="doVerify()">Bestätigen</button>
</div>
<div class="msg" id="msg"></div>
</div>
<script>
var BASE = (window.__GGS__?.baseUrl) || '';
if (!BASE) { var p = location.pathname, i = p.indexOf('/geograsim'); if (i !== -1) { var rest = p.substring(i + '/geograsim'.length); BASE = rest.indexOf('/App/') === 0 ? p.substring(0, i) + '/geograsim/App' : p.substring(0, i) + '/geograsim'; } }
async function api(data) {
var r = await fetch(BASE + '/api/admin', {
method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin',
body: JSON.stringify(data)
});
return await r.json();
}
function showMsg(text, type) {
var m = document.getElementById('msg');
m.textContent = text; m.className = 'msg ' + type;
}
async function doLogin() {
var user = document.getElementById('a-user').value.trim();
var pass = document.getElementById('a-pass').value;
if (!user || !pass) { showMsg('Bitte ausfüllen.', 'err'); return; }
showMsg('Anmelden...', 'ok');
var r = await api({action:'login', username:user, password:pass});
if (r.error) { showMsg(r.error, 'err'); return; }
document.getElementById('pin-email').textContent = r.email || '***';
document.getElementById('step-login').classList.add('hidden');
document.getElementById('step-pin').classList.remove('hidden');
document.getElementById('msg').className = 'msg';
document.getElementById('a-pin').focus();
}
async function doVerify() {
var pin = document.getElementById('a-pin').value.trim();
if (pin.length !== 4) { showMsg('Bitte 4-stelligen PIN eingeben.', 'err'); return; }
var r = await api({action:'verify_pin', pin:pin});
if (r.error) { showMsg(r.error, 'err'); return; }
showMsg('Zugang gewährt!', 'ok');
setTimeout(function() { location.href = 'admin-licenses.html'; }, 600);
}
// Auto-redirect if already authenticated
api({action:'status'}).then(function(r) {
if (r.authenticated) location.href = 'admin-licenses.html';
});
// Enter key handling
document.getElementById('a-pass').addEventListener('keydown', function(e) { if(e.key==='Enter') doLogin(); });
document.getElementById('a-pin').addEventListener('keydown', function(e) { if(e.key==='Enter') doVerify(); });
</script>
<script src="assets/js/version-tag.js" defer></script>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because it is too large Load Diff
-15
View File
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" lang="en"/>
<title>OSM3S Response</title>
</head>
<body>
<p>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</p>
<p><strong style="color:#FF0000">Error</strong>: runtime error: open64: 0 Success /osm3s_osm_base Dispatcher_Client::request_read_and_idx::timeout. The server is probably too busy to handle your request. </p>
</body>
</html>
-10
View File
@@ -1,10 +0,0 @@
[
{ "id": "electronics", "name": "Elektronik", "emoji": "📱", "category": "Hochwertig", "typicalOriginRegions": ["asia"], "typicalDestinationRegions": ["central_europe","western_europe"], "didacticInfo": "Elektronik wird häufig aus Ostasien importiert." },
{ "id": "clothing", "name": "Kleidung", "emoji": "👕", "category": "Konsumgut", "typicalOriginRegions": ["asia"], "typicalDestinationRegions": ["central_europe","western_europe"], "didacticInfo": "Kleidung kommt oft aus Bangladesch, Vietnam, der Türkei." },
{ "id": "machinery", "name": "Maschinen", "emoji": "⚙️", "category": "Investitionsgut","typicalOriginRegions": ["central_europe"], "typicalDestinationRegions": ["usa","asia"], "didacticInfo": "Maschinen sind ein typisches Exportgut Europas." },
{ "id": "food", "name": "Lebensmittel", "emoji": "🥫", "category": "Alltag", "typicalOriginRegions": ["europe_intern"], "typicalDestinationRegions": ["europe_intern"], "didacticInfo": "Ein großer Teil der Lebensmittel-Transporte findet innerhalb Europas statt." },
{ "id": "chemicals", "name": "Chemie", "emoji": "🧪", "category": "Industrie", "typicalOriginRegions": ["central_europe"], "typicalDestinationRegions": ["europe_intern"], "didacticInfo": "Chemie-Produkte werden oft per Zug oder Binnenschiff bewegt." },
{ "id": "auto_parts", "name": "Fahrzeugteile", "emoji": "🔩", "category": "Industrie", "typicalOriginRegions": ["europe_intern"], "typicalDestinationRegions": ["europe_intern"], "didacticInfo": "Fahrzeugteile pendeln zwischen Werken quer durch Europa." },
{ "id": "paper_wood", "name": "Holz und Papier", "emoji": "🪵", "category": "Rohstoff", "typicalOriginRegions": ["scandinavia"], "typicalDestinationRegions": ["central_europe"], "didacticInfo": "Papier und Holz kommen oft aus Skandinavien." },
{ "id": "raw_materials","name": "Rohstoffe", "emoji": "🪨", "category": "Rohstoff", "typicalOriginRegions": ["ports"], "typicalDestinationRegions": ["central_europe"], "didacticInfo": "Rohstoffe laufen meistens über große Seehäfen." }
]
@@ -1,22 +0,0 @@
[
{
"_comment": "Platzhalter — Logistik-Instanz füllt in Phase 2 auf. Struktur (aus Pflichtenheft Kap 9.6):",
"_example": {
"id": "tpl_standard_short",
"code": "STD-001",
"type": "standard",
"originLocationId": "wien",
"targetLocationId": "salzburg",
"cargoTypeId": "food",
"quantityContainers": 2,
"rewardBase": 1000,
"rewardBonus": 0,
"penaltyLatePerHour": 200,
"recommendedMode": "TRUCK_SMALL",
"difficulty": 1,
"hintMode": "BLINK_EXACT",
"narrativeText": "Lieferung: 2 Container Lebensmittel von Wien nach Salzburg. Standard-Frist.",
"availableFromLevel": 1
}
}
]
-59
View File
@@ -1,59 +0,0 @@
[
{ "id": "wien", "name": "Wien", "countryId": "AT", "regionId": "central_europe", "type": "CAPITAL", "lat": 48.2082, "lon": 16.3738, "didacticInfo": "Hauptstadt Österreichs; rund 2 Mio. Einwohner im Großraum. Wichtiger Verkehrsknoten zwischen Mittel- und Südosteuropa." },
{ "id": "muenchen", "name": "München", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 48.1351, "lon": 11.5820, "didacticInfo": "Drittgrößte Stadt Deutschlands, Wirtschaftsdrehkreuz Süddeutschlands. Starke Automobil- und Maschinenbau-Industrie." },
{ "id": "berlin", "name": "Berlin", "countryId": "DE", "regionId": "central_europe", "type": "CAPITAL", "lat": 52.5200, "lon": 13.4050, "didacticInfo": "Hauptstadt Deutschlands, größte Stadt des Landes. Zentrum für Politik, Tech und Kultur." },
{ "id": "hamburg", "name": "Hamburg", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 53.5511, "lon": 9.9937, "didacticInfo": "Zweitgrößte Stadt Deutschlands. Tor zur Welt durch den größten deutschen Seehafen." },
{ "id": "hamburg_hafen", "name": "Hamburg Hafen", "countryId": "DE", "regionId": "central_europe", "type": "PORT", "lat": 53.5461, "lon": 9.9661, "didacticInfo": "Drittgrößter Seehafen Europas, ca. 130 Mio. Tonnen Umschlag pro Jahr. Spezialisiert auf Container." },
{ "id": "rotterdam", "name": "Rotterdam", "countryId": "NL", "regionId": "benelux", "type": "CITY", "lat": 51.9244, "lon": 4.4777, "didacticInfo": "Zweitgrößte Stadt der Niederlande, maritime Drehscheibe. Wohnt direkt am Mündungsdelta von Rhein und Maas." },
{ "id": "rotterdam_hafen","name": "Rotterdam Hafen","countryId": "NL", "regionId": "benelux", "type": "PORT", "lat": 51.9519, "lon": 4.1378, "didacticInfo": "Größter Seehafen Europas, ca. 470 Mio. Tonnen Umschlag pro Jahr. Wichtigstes Import-Tor für Rohstoffe aus Übersee." },
{ "id": "paris", "name": "Paris", "countryId": "FR", "regionId": "western_europe", "type": "CAPITAL", "lat": 48.8566, "lon": 2.3522, "didacticInfo": "Hauptstadt Frankreichs, Großraum 12 Mio. Einwohner. Wirtschaftsmotor Frankreichs." },
{ "id": "mailand", "name": "Mailand", "countryId": "IT", "regionId": "southern_europe","type": "CITY", "lat": 45.4642, "lon": 9.1900, "didacticInfo": "Wirtschaftsmetropole Italiens, Finanz- und Modezentrum. Zugang zum Alpentransit über den Brenner." },
{ "id": "salzburg", "name": "Salzburg", "countryId": "AT", "regionId": "central_europe", "type": "CITY", "lat": 47.8095, "lon": 13.0550, "didacticInfo": "Landeshauptstadt im Salzkammergut, wichtiger Ost-West-Transit-Knoten auf der A1." },
{ "id": "warschau", "name": "Warschau", "countryId": "PL", "regionId": "central_europe", "type": "CAPITAL", "lat": 52.2297, "lon": 21.0122, "didacticInfo": "Hauptstadt Polens, 1,8 Mio. Einwohner. Wirtschaftszentrum zwischen West- und Osteuropa." },
{ "id": "madrid", "name": "Madrid", "countryId": "ES", "regionId": "iberia", "type": "CAPITAL", "lat": 40.4168, "lon": -3.7038, "didacticInfo": "Hauptstadt Spaniens, geographisches Zentrum der iberischen Halbinsel. Großer Binnenmarkt ohne direkten Seezugang." },
{ "id": "kopenhagen", "name": "Kopenhagen", "countryId": "DK", "regionId": "scandinavia", "type": "CAPITAL", "lat": 55.6761, "lon": 12.5683, "didacticInfo": "Hauptstadt Dänemarks. Knoten zwischen Skandinavien und dem europäischen Kontinent (Öresundbrücke)." },
{ "id": "rom", "name": "Rom", "countryId": "IT", "regionId": "southern_europe","type": "CAPITAL", "lat": 41.9028, "lon": 12.4964, "didacticInfo": "Hauptstadt Italiens, 2,8 Mio. Einwohner. Verwaltungszentrum, weniger Industrie als Mailand." },
{ "id": "london", "name": "London", "countryId": "GB", "regionId": "western_europe", "type": "CAPITAL", "lat": 51.5074, "lon": -0.1278, "didacticInfo": "Hauptstadt Großbritanniens, Finanzmetropole. Seit Brexit (2020) mit Zollkontrolle zur EU." },
{ "id": "bruessel", "name": "Brüssel", "countryId": "BE", "regionId": "benelux", "type": "CAPITAL", "lat": 50.8503, "lon": 4.3517, "didacticInfo": "Hauptstadt Belgiens und de-facto der EU. Sitz von EU-Kommission und NATO." },
{ "id": "amsterdam", "name": "Amsterdam", "countryId": "NL", "regionId": "benelux", "type": "CAPITAL", "lat": 52.3676, "lon": 4.9041, "didacticInfo": "Hauptstadt der Niederlande. Luftfahrt-Drehkreuz (Flughafen Schiphol), Agrarexport-Zentrum." },
{ "id": "prag", "name": "Prag", "countryId": "CZ", "regionId": "central_europe", "type": "CAPITAL", "lat": 50.0755, "lon": 14.4378, "didacticInfo": "Hauptstadt Tschechiens. Industriestandort, enge Verflechtung mit deutscher Automobil-Lieferkette." },
{ "id": "budapest", "name": "Budapest", "countryId": "HU", "regionId": "central_europe", "type": "CAPITAL", "lat": 47.4979, "lon": 19.0402, "didacticInfo": "Hauptstadt Ungarns, Donaumetropole. Wichtig für Verkehr Richtung Südosteuropa und Schwarzes Meer." },
{ "id": "athen", "name": "Athen", "countryId": "GR", "regionId": "southern_europe","type": "CAPITAL", "lat": 37.9838, "lon": 23.7275, "didacticInfo": "Hauptstadt Griechenlands, mit Seehafen Piräus zweitgrößter Containerhafen des Mittelmeers." },
{ "id": "stockholm", "name": "Stockholm", "countryId": "SE", "regionId": "scandinavia", "type": "CAPITAL", "lat": 59.3293, "lon": 18.0686, "didacticInfo": "Hauptstadt Schwedens, Inselstadt auf 14 Inseln. Hightech- und Pharma-Zentrum." },
{ "id": "oslo", "name": "Oslo", "countryId": "NO", "regionId": "scandinavia", "type": "CAPITAL", "lat": 59.9139, "lon": 10.7522, "didacticInfo": "Hauptstadt Norwegens. Erdöl- und Schifffahrts-Drehscheibe, kein EU-Mitglied (aber EWR)." },
{ "id": "helsinki", "name": "Helsinki", "countryId": "FI", "regionId": "scandinavia", "type": "CAPITAL", "lat": 60.1699, "lon": 24.9384, "didacticInfo": "Hauptstadt Finnlands, nördlichste EU-Hauptstadt am Festland. Tor zum Baltikum und nach St. Petersburg." },
{ "id": "dublin", "name": "Dublin", "countryId": "IE", "regionId": "western_europe", "type": "CAPITAL", "lat": 53.3498, "lon": -6.2603, "didacticInfo": "Hauptstadt Irlands. EU-Standort vieler Tech-Konzerne, verkehrstechnisch Insellage." },
{ "id": "lissabon", "name": "Lissabon", "countryId": "PT", "regionId": "iberia", "type": "CAPITAL", "lat": 38.7223, "lon": -9.1393, "didacticInfo": "Hauptstadt Portugals, westlichste Hauptstadt des europäischen Festlandes. Atlantik-Hafen." },
{ "id": "bern", "name": "Bern", "countryId": "CH", "regionId": "central_europe", "type": "CAPITAL", "lat": 46.9481, "lon": 7.4474, "didacticInfo": "Hauptstadt der Schweiz. Nicht EU, daher eigenes Zollsystem — wichtig für logistische Abwicklung." },
{ "id": "frankfurt", "name": "Frankfurt a. M.","countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 50.1109, "lon": 8.6821, "didacticInfo": "Finanzmetropole und zentrale Logistik-Drehscheibe Deutschlands. Frankfurt-Flughafen: größtes Luftfracht-Drehkreuz des Kontinents." },
{ "id": "koeln", "name": "Köln", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 50.9375, "lon": 6.9603, "didacticInfo": "Großstadt am Rhein, Autobahn-Drehkreuz A1/A3/A4. Wichtig für Rhein-Güterverkehr und Binnenschifffahrt." },
{ "id": "stuttgart", "name": "Stuttgart", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 48.7758, "lon": 9.1829, "didacticInfo": "Landeshauptstadt Baden-Württemberg, Zentrum der Automobilindustrie (Mercedes, Porsche). Lieferketten weltweit." },
{ "id": "leipzig", "name": "Leipzig", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 51.3397, "lon": 12.3731, "didacticInfo": "Logistik-Drehkreuz Ostdeutschland, DHL-Hub am Flughafen Leipzig/Halle. Zugknoten Ost-West." },
{ "id": "nuernberg", "name": "Nürnberg", "countryId": "DE", "regionId": "central_europe", "type": "CITY", "lat": 49.4521, "lon": 11.0767, "didacticInfo": "Größte Stadt Frankens, Bayern-Nord-Süd-Knoten A9/A3. Wichtiger Güterverkehrs-Knoten im Schienennetz." },
{ "id": "innsbruck", "name": "Innsbruck", "countryId": "AT", "regionId": "central_europe", "type": "CITY", "lat": 47.2692, "lon": 11.4041, "didacticInfo": "Alpenstadt in Tirol, Brenner-Nordknoten. Über 2 Mio. LKW pro Jahr durch den Brenner-Korridor Richtung Italien." },
{ "id": "graz", "name": "Graz", "countryId": "AT", "regionId": "central_europe", "type": "CITY", "lat": 47.0707, "lon": 15.4395, "didacticInfo": "Zweitgrößte Stadt Österreichs, Landeshauptstadt Steiermark. Starke Automobilzulieferer (Magna Steyr)." },
{ "id": "zuerich", "name": "Zürich", "countryId": "CH", "regionId": "central_europe", "type": "CITY", "lat": 47.3769, "lon": 8.5417, "didacticInfo": "Größte Stadt der Schweiz, Finanzplatz. Nördlicher Eingang zu den Alpentransit-Routen (Gotthard)." },
{ "id": "turin", "name": "Turin", "countryId": "IT", "regionId": "southern_europe","type": "CITY", "lat": 45.0703, "lon": 7.6869, "didacticInfo": "Viertgrößte Stadt Italiens, traditionell Fiat/Stellantis-Heimat. Westlicher Alpenquerungs-Knoten (Mont Blanc, Fréjus)." },
{ "id": "neapel", "name": "Neapel", "countryId": "IT", "regionId": "southern_europe","type": "CITY", "lat": 40.8518, "lon": 14.2681, "didacticInfo": "Drittgrößte Stadt Italiens, Süditalienisches Wirtschaftszentrum am Vesuv. Bedeutender Mittelmeerhafen." },
{ "id": "lyon", "name": "Lyon", "countryId": "FR", "regionId": "western_europe", "type": "CITY", "lat": 45.7640, "lon": 4.8357, "didacticInfo": "Zweit-/Drittgrößte Stadt Frankreichs, Rhône-Tal-Knoten. Autobahnkreuz A6/A7 — Paris nach Südfrankreich/Italien." },
{ "id": "marseille", "name": "Marseille", "countryId": "FR", "regionId": "western_europe", "type": "CITY", "lat": 43.2965, "lon": 5.3698, "didacticInfo": "Zweitgrößte Stadt Frankreichs, bedeutendster französischer Mittelmeerhafen. Tor zu Nordafrika und Nahost." },
{ "id": "barcelona", "name": "Barcelona", "countryId": "ES", "regionId": "iberia", "type": "CITY", "lat": 41.3851, "lon": 2.1734, "didacticInfo": "Zweitgrößte Stadt Spaniens, Katalonien. Mittelmeer-Hafenstadt, südwestliches Tor zu Nordeuropa." },
{ "id": "valencia", "name": "Valencia", "countryId": "ES", "regionId": "iberia", "type": "CITY", "lat": 39.4699, "lon": -0.3763, "didacticInfo": "Drittgrößte Stadt Spaniens, Orangenexport-Zentrum. Containerhafen unter den Top 5 des Mittelmeers." },
{ "id": "porto", "name": "Porto", "countryId": "PT", "regionId": "iberia", "type": "CITY", "lat": 41.1579, "lon": -8.6291, "didacticInfo": "Zweitgrößte Stadt Portugals, Dourotal. Exportstadt (Portwein, Textilien), Hafen Leixões in der Nähe." },
{ "id": "manchester", "name": "Manchester", "countryId": "GB", "regionId": "western_europe", "type": "CITY", "lat": 53.4808, "lon": -2.2426, "didacticInfo": "Drittgrößter Großraum Großbritanniens, ehemalige Industrie-Hochburg. Heute Logistik und Dienstleistungen." },
{ "id": "krakau", "name": "Krakau", "countryId": "PL", "regionId": "central_europe", "type": "CITY", "lat": 50.0647, "lon": 19.9450, "didacticInfo": "Zweitgrößte Stadt Polens, Süd-Polens Wirtschaftszentrum. Autobahnkreuz A4 Richtung Deutschland/Ukraine." },
{ "id": "thessaloniki", "name": "Thessaloniki", "countryId": "GR", "regionId": "southern_europe","type": "CITY", "lat": 40.6401, "lon": 22.9444, "didacticInfo": "Zweitgrößte Stadt Griechenlands, Hafen für den Balkan. Tor zu Nord-Griechenland und Mazedonien." },
{ "id": "antwerpen_hafen","name": "Antwerpen Hafen","countryId": "BE", "regionId": "benelux", "type": "PORT", "lat": 51.2296, "lon": 4.4020, "didacticInfo": "Zweitgrößter Seehafen Europas, an der Schelde. Spezialisiert auf Chemie-Umschlag und Rohöl." },
{ "id": "bremerhaven_hafen","name":"Bremerhaven","countryId": "DE", "regionId": "central_europe", "type": "PORT", "lat": 53.5396, "lon": 8.5810, "didacticInfo": "Wichtigster Auto-Umschlagplatz Europas, ca. 2 Mio. Fahrzeuge pro Jahr. Tiefwasserhafen an der Wesermündung." },
{ "id": "duisburg_terminal","name":"Duisburg","countryId": "DE", "regionId": "central_europe", "type": "TERMINAL","lat": 51.4344, "lon": 6.7623, "didacticInfo": "Europas größter Binnenhafen am Rhein-Ruhr-Zusammenfluss. Neue Seidenstraßen-Endstation für chinesische Züge." },
{ "id": "basel_terminal", "name": "Basel Terminal", "countryId": "CH", "regionId": "central_europe", "type": "TERMINAL","lat": 47.5596, "lon": 7.5886, "didacticInfo": "Größter Rheinhafen der Schweiz. Seehafen-Ersatz für Binnenland Schweiz über Rhein bis Rotterdam." },
{ "id": "marseille_hafen","name": "Marseille Hafen","countryId": "FR", "regionId": "western_europe", "type": "PORT", "lat": 43.3485, "lon": 5.2954, "didacticInfo": "Größter französischer Hafen, Mittelmeer-Eingang. Container, Kreuzfahrten, Rohölpipeline nach Deutschland." },
{ "id": "barcelona_hafen","name": "Barcelona Hafen","countryId": "ES", "regionId": "iberia", "type": "PORT", "lat": 41.3443, "lon": 2.1700, "didacticInfo": "Größter Mittelmeerhafen Spaniens. Strategisch an der Route Asien-Europa, Umschlagplatz für Afrika-Handel." },
{ "id": "genua_hafen", "name": "Genua Hafen", "countryId": "IT", "regionId": "southern_europe","type": "PORT", "lat": 44.4056, "lon": 8.8691, "didacticInfo": "Wichtigster italienischer Seehafen. Tor für Nord-Italien und Süddeutschland Richtung Mittelmeer." },
{ "id": "triest_hafen", "name": "Triest Hafen", "countryId": "IT", "regionId": "southern_europe","type": "PORT", "lat": 45.6495, "lon": 13.7680, "didacticInfo": "Schnellster Mittelmeer-Zugang für Zentraleuropa. Wichtiger Öl-Hub und wachsender Container-Hafen." },
{ "id": "piraeus_hafen", "name": "Piräus", "countryId": "GR", "regionId": "southern_europe","type": "PORT", "lat": 37.9475, "lon": 23.6364, "didacticInfo": "Haupthafen Athens, viertgrößter Container-Hafen Europas. Teilweise in chinesischem Besitz (COSCO), Tor Richtung Asien." },
{ "id": "gdansk_hafen", "name": "Danzig Hafen", "countryId": "PL", "regionId": "central_europe", "type": "PORT", "lat": 54.3520, "lon": 18.6466, "didacticInfo": "Größter polnischer Ostsee-Hafen. Wichtig für Container-Verkehr und Kohle-Umschlag, Tiefwasser-Terminal." },
{ "id": "goeteborg_hafen","name": "Göteborg Hafen", "countryId": "SE", "regionId": "scandinavia", "type": "PORT", "lat": 57.6882, "lon": 11.8462, "didacticInfo": "Größter Hafen Skandinaviens. Hauptumschlag für die nordischen Länder, 90 % aller schwedischen Container." }
]
File diff suppressed because one or more lines are too long
-234
View File
@@ -1,234 +0,0 @@
{
"_comment": "Hand-gepflegte OSM-Approximation der wichtigsten Hauptstrecken zwischen den 13 Logistik-Locations (Phase 3). Stützpunkte sind bekannte Knotenpunkte (Städte/Pässe) auf den realen Autobahnverbindungen. Bidirektional: Lookup A→B fällt auf B→A zurück. Die Polyline-Länge wird zur Laufzeit berechnet (Haversine-Summe), die hier angegebenen approxKm sind didaktische Referenzwerte.",
"routes": [
{
"id": "wien-salzburg",
"originLocationId": "wien",
"targetLocationId": "salzburg",
"approxKm": 295,
"polyline": [
[48.2082, 16.3738],
[48.2050, 15.6160],
[48.3069, 14.2858],
[48.1660, 14.0320],
[47.8095, 13.0550]
]
},
{
"id": "wien-muenchen",
"originLocationId": "wien",
"targetLocationId": "muenchen",
"approxKm": 435,
"polyline": [
[48.2082, 16.3738],
[48.2050, 15.6160],
[48.3069, 14.2858],
[47.8095, 13.0550],
[47.8500, 12.1300],
[48.1351, 11.5820]
]
},
{
"id": "salzburg-muenchen",
"originLocationId": "salzburg",
"targetLocationId": "muenchen",
"approxKm": 145,
"polyline": [
[47.8095, 13.0550],
[47.8500, 12.1300],
[48.1351, 11.5820]
]
},
{
"id": "muenchen-berlin",
"originLocationId": "muenchen",
"targetLocationId": "berlin",
"approxKm": 590,
"polyline": [
[48.1351, 11.5820],
[49.4521, 11.0767],
[50.9837, 11.0297],
[51.3397, 12.3731],
[52.5200, 13.4050]
]
},
{
"id": "muenchen-hamburg",
"originLocationId": "muenchen",
"targetLocationId": "hamburg",
"approxKm": 790,
"polyline": [
[48.1351, 11.5820],
[49.4521, 11.0767],
[49.7913, 9.9534],
[50.1109, 8.6821],
[51.5200, 9.9000],
[52.3759, 9.7320],
[53.5511, 9.9937]
]
},
{
"id": "muenchen-mailand",
"originLocationId": "muenchen",
"targetLocationId": "mailand",
"approxKm": 480,
"polyline": [
[48.1351, 11.5820],
[47.2692, 11.4041],
[47.0040, 11.5070],
[46.4983, 11.3548],
[45.4385, 10.9916],
[45.4642, 9.1900]
]
},
{
"id": "wien-berlin",
"originLocationId": "wien",
"targetLocationId": "berlin",
"approxKm": 680,
"polyline": [
[48.2082, 16.3738],
[49.1951, 16.6068],
[50.0755, 14.4378],
[51.0504, 13.7373],
[52.5200, 13.4050]
]
},
{
"id": "berlin-hamburg",
"originLocationId": "berlin",
"targetLocationId": "hamburg",
"approxKm": 290,
"polyline": [
[52.5200, 13.4050],
[52.9926, 11.7541],
[53.2519, 10.4147],
[53.5511, 9.9937]
]
},
{
"id": "hamburg-rotterdam",
"originLocationId": "hamburg",
"targetLocationId": "rotterdam",
"approxKm": 480,
"polyline": [
[53.5511, 9.9937],
[53.0793, 8.8017],
[52.2799, 8.0472],
[51.9606, 7.6261],
[52.0000, 5.9000],
[51.9244, 4.4777]
]
},
{
"id": "hamburg-rotterdam-hafen",
"originLocationId": "hamburg",
"targetLocationId": "rotterdam_hafen",
"approxKm": 490,
"polyline": [
[53.5511, 9.9937],
[53.0793, 8.8017],
[52.2799, 8.0472],
[51.9606, 7.6261],
[52.0000, 5.9000],
[51.9519, 4.1378]
]
},
{
"id": "rotterdam-paris",
"originLocationId": "rotterdam",
"targetLocationId": "paris",
"approxKm": 510,
"polyline": [
[51.9244, 4.4777],
[51.2194, 4.4025],
[50.8503, 4.3517],
[50.6292, 3.0573],
[49.4944, 2.8278],
[48.8566, 2.3522]
]
},
{
"id": "paris-muenchen",
"originLocationId": "paris",
"targetLocationId": "muenchen",
"approxKm": 830,
"polyline": [
[48.8566, 2.3522],
[49.2583, 4.0317],
[48.5839, 7.7455],
[48.7758, 9.1829],
[48.3705, 10.8978],
[48.1351, 11.5820]
]
},
{
"id": "paris-madrid",
"originLocationId": "paris",
"targetLocationId": "madrid",
"approxKm": 1280,
"polyline": [
[48.8566, 2.3522],
[47.3220, 0.6800],
[44.8378, -0.5792],
[43.2630, -2.9350],
[42.3439, -3.6969],
[41.6526, -4.7286],
[40.4168, -3.7038]
]
},
{
"id": "wien-warschau",
"originLocationId": "wien",
"targetLocationId": "warschau",
"approxKm": 700,
"polyline": [
[48.2082, 16.3738],
[49.1951, 16.6068],
[50.0647, 19.9450],
[51.7592, 19.4560],
[52.2297, 21.0122]
]
},
{
"id": "kopenhagen-hamburg",
"originLocationId": "kopenhagen",
"targetLocationId": "hamburg",
"approxKm": 340,
"polyline": [
[55.6761, 12.5683],
[54.7806, 11.0850],
[54.4921, 9.5358],
[54.1980, 9.1000],
[53.5511, 9.9937]
]
},
{
"id": "wien-mailand",
"originLocationId": "wien",
"targetLocationId": "mailand",
"approxKm": 870,
"polyline": [
[48.2082, 16.3738],
[47.8095, 13.0550],
[47.2692, 11.4041],
[47.0040, 11.5070],
[46.4983, 11.3548],
[45.4385, 10.9916],
[45.4642, 9.1900]
]
},
{
"id": "berlin-warschau",
"originLocationId": "berlin",
"targetLocationId": "warschau",
"approxKm": 580,
"polyline": [
[52.5200, 13.4050],
[52.4082, 16.9335],
[52.4064, 19.5800],
[52.2297, 21.0122]
]
}
]
}
-47
View File
@@ -1,47 +0,0 @@
[
{
"id": "truck_small",
"code": "TRUCK_SMALL",
"name": "Kleiner LKW",
"mode": "TRUCK_SMALL",
"capacityUnits": 1,
"averageSpeedKmh": 70,
"costPerKm": 1.2,
"costPerHour": 25,
"loadMinutesPerUnit": 5,
"unloadMinutesPerUnit": 5,
"transferAllowed": true,
"displayName_de": "Kleiner LKW (bis 1 Container)",
"displayName_easy": "Kleiner Lastwagen"
},
{
"id": "truck_large",
"code": "TRUCK_LARGE",
"name": "Großer LKW",
"mode": "TRUCK_LARGE",
"capacityUnits": 3,
"averageSpeedKmh": 60,
"costPerKm": 2.5,
"costPerHour": 45,
"loadMinutesPerUnit": 8,
"unloadMinutesPerUnit": 8,
"transferAllowed": true,
"displayName_de": "Großer LKW (bis 3 Container)",
"displayName_easy": "Großer Lastwagen"
},
{
"id": "train",
"code": "TRAIN",
"name": "Güterzug",
"mode": "TRAIN",
"capacityUnits": 20,
"averageSpeedKmh": 90,
"costPerKm": 8,
"costPerHour": 150,
"loadMinutesPerUnit": 2,
"unloadMinutesPerUnit": 2,
"transferAllowed": true,
"displayName_de": "Güterzug (bis 20 Container)",
"displayName_easy": "Güterzug"
}
]
-15
View File
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" lang="en"/>
<title>OSM3S Response</title>
</head>
<body>
<p>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</p>
<p><strong style="color:#FF0000">Error</strong>: runtime error: open64: 0 Success /osm3s_osm_base Dispatcher_Client::request_read_and_idx::timeout. The server is probably too busy to handle your request. </p>
</body>
</html>
-167
View File
@@ -1,167 +0,0 @@
CREATE TABLE IF NOT EXISTS geo_waypoints (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
wp_key VARCHAR(32) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
lat DECIMAL(8,5) NOT NULL,
lon DECIMAL(8,5) NOT NULL,
region VARCHAR(32) DEFAULT 'vorarlberg',
wp_type ENUM('base','city','village','peak','target','pass') DEFAULT 'village',
info VARCHAR(255),
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;
DELETE FROM geo_waypoints;
INSERT INTO geo_waypoints (wp_key, name, lat, lon, region, wp_type, info) VALUES
('oberwart_c16','C16 Oberwart (ÖAMTC)',47.28278,16.19333,'burgenland','base','Flugplatz Pinkafeld/Oberwart, ÖAMTC Christophorus 16.'),
('eisenstadt','Eisenstadt',47.84500,16.52330,'burgenland','city','Landeshauptstadt Burgenland, Haydn-Stadt.'),
('mattersburg','Mattersburg',47.73330,16.40000,'burgenland','city','Wein- und Handelsstadt Nordburgenland.'),
('neusiedl','Neusiedl am See',47.95000,16.84310,'burgenland','city','Am Nordufer des Neusiedler Sees.'),
('oberwart','Oberwart',47.28330,16.21670,'burgenland','city','Bezirkshauptstadt Südburgenland.'),
('podersdorf','Podersdorf am See',47.85030,16.83310,'burgenland','village','Bade- und Windsurfort am Neusiedler See.'),
('rust','Rust',47.80000,16.67500,'burgenland','village','Freistadt, bekannt für Störche.'),
('see_neusiedl','Seerettung Neusiedler See',47.85030,16.77000,'burgenland','target','Surfer:in in Seenot vor Podersdorf.'),
('klagenfurt_c11','C11 Klagenfurt (ÖAMTC)',46.64278,14.33778,'kaernten','base','Flughafen Klagenfurt, ÖAMTC Christophorus 11.'),
('klagenfurt','Klagenfurt',46.62450,14.30830,'kaernten','city','Landeshauptstadt, Lindwurm.'),
('spittal','Spittal an der Drau',46.80060,13.49640,'kaernten','city','Oberkärnten, Drau-Tal.'),
('villach','Villach',46.61060,13.85580,'kaernten','city','Zweitgrößte Stadt Kärntens, Dreiländereck.'),
('heiligenblut','Heiligenblut',47.04000,12.84420,'kaernten','village','Fuß des Großglockners, Wallfahrtsort.'),
('millstatt','Millstatt am See',46.80250,13.56920,'kaernten','village','Barockes Kloster am Millstätter See.'),
('poertschach','Pörtschach am Wörthersee',46.64310,14.14860,'kaernten','village','Badeort am Wörthersee.'),
('velden','Velden am Wörthersee',46.61360,14.03940,'kaernten','village','Mondäner Badeort am West-Wörthersee.'),
('woerthersee','Wörthersee (Seemitte)',46.62500,14.14500,'kaernten','village','Größter See Kärntens, bis zu 28 °C Badewasser.'),
('berg_glockner','Bergrettung Großglockner',47.07440,12.69390,'kaernten','target','Absturz im Gipfelbereich Großglockner.'),
('see_millstatt','Seerettung Millstätter See',46.80000,13.59000,'kaernten','target','Segelboot gekentert, Millstätter See.'),
('see_woerth','Seerettung Wörthersee',46.64310,14.14860,'kaernten','target','Badegast in Seenot vor Pörtschach.'),
('verkehr_a2_klagenfurt','Unfall A2 bei Klagenfurt',46.65000,14.30000,'kaernten','target','Auffahrunfall Südautobahn bei Klagenfurt-Ost.'),
('krems_c2','C2 Krems (ÖAMTC)',48.43194,15.62556,'niederoesterreich','base','Flugplatz Gneixendorf bei Krems, ÖAMTC Christophorus 2.'),
('wr_neustadt_c3','C3 Wiener Neustadt (ÖAMTC)',47.84278,16.26472,'niederoesterreich','base','Flugplatz Wr. Neustadt Ost, ÖAMTC Christophorus 3.'),
('baden','Baden bei Wien',48.00680,16.23400,'niederoesterreich','city','Kurstadt südlich von Wien, an der A2.'),
('krems','Krems an der Donau',48.40900,15.61000,'niederoesterreich','city','Weinbau-Zentrum Wachau, UNESCO-Welterbe.'),
('moedling','Mödling',48.08670,16.28370,'niederoesterreich','city','An der Südbahn, Wiener Alpen.'),
('st_poelten','St. Pölten',48.20470,15.62560,'niederoesterreich','city','Landeshauptstadt Niederösterreichs.'),
('wr_neustadt','Wiener Neustadt',47.81350,16.24000,'niederoesterreich','city','Zweitgrößte Stadt Niederösterreichs.'),
('gutenstein','Gutenstein',47.87190,15.88190,'niederoesterreich','village','Wiener Alpen, Wallfahrtsort.'),
('puchberg','Puchberg am Schneeberg',47.78250,15.90830,'niederoesterreich','village','Bahnhof der Schneebergbahn.'),
('semmering','Semmering',47.64310,15.83330,'niederoesterreich','village','Pass zwischen NÖ und Stmk, Weltkulturerbe-Bahn.'),
('rax','Rax (Gipfel)',47.70970,15.71860,'niederoesterreich','peak','Wanderberg bei Wien, Plateau 2007 m.'),
('schneeberg','Schneeberg (Gipfel)',47.76670,15.80670,'niederoesterreich','peak','Höchster Berg Niederösterreichs, 2076 m.'),
('berg_schneeberg','Bergunfall Schneeberg',47.77000,15.80000,'niederoesterreich','target','Kletterunfall am Schneeberg-Nordgrat.'),
('berg_wechsel','Bergunfall Wechsel',47.60330,15.91500,'niederoesterreich','target','Wanderunfall am Hochwechsel.'),
('verkehr_a2_baden','Unfall A2 Baden',47.99530,16.24450,'niederoesterreich','target','Schwerer Unfall Südautobahn bei Baden.'),
('berg_rax','Wanderunfall Rax',47.71000,15.72000,'niederoesterreich','target','Wanderunfall am Raxplateau.'),
('linz_c10','C10 Linz (ÖAMTC)',48.23306,14.18722,'oberoesterreich','base','Flughafen Linz-Hörsching, ÖAMTC Christophorus 10.'),
('bad_ischl','Bad Ischl',47.71080,13.62580,'oberoesterreich','city','Kaiserstadt, Salzkammergut-Zentrum.'),
('gmunden','Gmunden',47.91780,13.80000,'oberoesterreich','city','Am Nordufer des Traunsees, Traunstein-Blick.'),
('linz','Linz',48.30690,14.28580,'oberoesterreich','city','Landeshauptstadt, Donau, Industriestandort.'),
('wels','Wels',48.15940,14.02360,'oberoesterreich','city','Messestadt, zweitgrößte Stadt OÖ.'),
('hallstatt','Hallstatt',47.56220,13.64890,'oberoesterreich','village','UNESCO-Welterbe, ältestes Salzbergwerk der Welt.'),
('sattledt','Sattledt',48.06670,14.03440,'oberoesterreich','village','A1/A8-Knoten, Verkehrsdrehscheibe.'),
('traunsee','Traunsee (Seemitte)',47.87610,13.82920,'oberoesterreich','village','Salzkammergut-See, max. 191 m tief.'),
('dachstein','Dachstein (Gipfel)',47.47500,13.60640,'oberoesterreich','peak','Hoher Dachstein 2995 m, Gletscher.'),
('berg_dachstein','Bergrettung Dachstein',47.47500,13.60500,'oberoesterreich','target','Absturz am Dachstein-Südwandsteig.'),
('see_hallstatt','Seerettung Hallstätter See',47.56220,13.66000,'oberoesterreich','target','Taucher:in in Seenot, Hallstätter See.'),
('see_traun','Seerettung Traunsee',47.87610,13.82920,'oberoesterreich','target','Boot in Not auf dem Traunsee.'),
('verkehr_a1_sattledt','Unfall A1 Sattledt',48.06670,14.03440,'oberoesterreich','target','Massenkarambolage Westautobahn-Knoten Sattledt.'),
('salzburg_c6','C6 Salzburg (ÖAMTC)',47.79367,13.00433,'salzburg','base','Flughafen Salzburg, ÖAMTC Christophorus 6.'),
('flachau','Flachau',47.34500,13.38970,'salzburg','city','Skiort, Anschluss A10 vor Tauerntunnel-Nordportal.'),
('golling','Golling an der Salzach',47.59310,13.17170,'salzburg','city','Salzachklamm, A10-Anschluss, Tennengebirge.'),
('hallein','Hallein',47.68360,13.09700,'salzburg','city','Salzabbau Dürrnberg, Stille-Nacht.'),
('salzburg','Salzburg',47.80950,13.05500,'salzburg','city','Mozartstadt, Festspielstadt, UNESCO-Welterbe.'),
('zell_see','Zell am See',47.32310,12.79360,'salzburg','city','Pinzgau, Zeller See, Schmittenhöhe.'),
('kaprun','Kaprun',47.27080,12.75310,'salzburg','village','Kitzsteinhorn-Gletscher, Stauseen.'),
('lofer','Lofer',47.58690,12.69330,'salzburg','village','Pinzgauer Grenzort, Steinernes Meer.'),
('st_wolfgang','St. Wolfgang',47.73920,13.44280,'salzburg','village','Wallfahrt, Schafbergbahn, Wolfgangsee.'),
('wolfgangsee','Wolfgangsee (Seemitte)',47.74500,13.40000,'salzburg','village','Salzkammergut-See zwischen Stmk/Sbg/OÖ.'),
('grossglockner','Großglockner (Gipfel)',47.07440,12.69390,'salzburg','peak','Höchster Berg Österreichs, 3798 m.'),
('berg_tennengebirge','Bergrettung Tennengebirge',47.55000,13.30000,'salzburg','target','Bergeinsatz Tennengebirge.'),
('see_wolfgang','Seerettung Wolfgangsee',47.74500,13.43000,'salzburg','target','Segler:in gekentert am Wolfgangsee.'),
('verkehr_a10_tauern','Unfall A10 Tauerntunnel',47.26500,13.47670,'salzburg','target','LKW-Unfall Tauern-Autobahn zwischen Flachau und Zederhaus.'),
('graz_c12','C12 Graz (ÖAMTC)',46.99111,15.43944,'steiermark','base','Flughafen Graz-Thalerhof, ÖAMTC Christophorus 12.'),
('niederoeblarn_c14','C14 Niederöblarn (ÖAMTC)',47.50750,14.01056,'steiermark','base','Flugplatz Niederöblarn, ÖAMTC Christophorus 14.'),
('bad_aussee','Bad Aussee',47.60920,13.78250,'steiermark','city','Zentrum des Ausseerlandes.'),
('bruck_mur','Bruck an der Mur',47.41060,15.27310,'steiermark','city','Knotenpunkt Mur-/Mürztal.'),
('graz','Graz',47.07070,15.43940,'steiermark','city','Landeshauptstadt, UNESCO-Altstadt.'),
('leoben','Leoben',47.38310,15.09060,'steiermark','city','Obersteiermark, Montanuniversität.'),
('schladming','Schladming',47.39440,13.68330,'steiermark','city','Ski- und WM-Ort, Planai.'),
('grundlsee','Grundlsee',47.62860,13.82280,'steiermark','village','„Steirisches Meer", Ausseerland.'),
('mariazell','Mariazell',47.77500,15.31670,'steiermark','village','Größter Wallfahrtsort Mitteleuropas.'),
('niederoeblarn','Niederöblarn',47.50750,14.01060,'steiermark','village','Ennstal, Flugsportzentrum.'),
('hochschwab','Hochschwab (Gipfel)',47.61810,15.14830,'steiermark','peak','Obersteirischer Wallfahrts- und Wanderberg, 2277 m.'),
('berg_hochschwab','Bergrettung Hochschwab',47.61810,15.14830,'steiermark','target','Alpinunfall Hochschwab-Massiv.'),
('verkehr_a9_pyhrn','Unfall A9 Bosruck',47.50330,14.33330,'steiermark','target','Unfall Pyhrn-Autobahn nahe Bosrucktunnel.'),
('verkehr_s6_semmering','Unfall S6 Semmering',47.60000,15.90000,'steiermark','target','Schneeglätte-Unfall Semmering-Schnellstraße.'),
('innsbruck','C1 Innsbruck (ÖAMTC)',47.25970,11.34190,'tirol','base','Klinik Innsbruck'),
('kitzbuehel_c4','C4 Kitzbühel (ÖAMTC)',47.48870,12.36480,'tirol','base','Reith bei Kitzbühel'),
('zams_c5','C5 Zams (ÖAMTC)',47.15972,10.59333,'tirol','base','KH Zams'),
('lienz_c7','C7 Lienz (ÖAMTC)',46.83505,12.76460,'tirol','base','Osttirol'),
('hall','Hall in Tirol',47.28166,11.50753,'tirol','city','Münzstadt'),
('imst','Imst',47.23815,10.74070,'tirol','city','Schemenlaufen'),
('jenbach','Jenbach',47.39222,11.77500,'tirol','city','Dampfzahnradbahn'),
('kitzbuehel_ort','Kitzbühel',47.44639,12.39222,'tirol','city','Hahnenkamm'),
('kufstein','Kufstein',47.58333,12.16667,'tirol','city','Festungsstadt'),
('landeck','Landeck',47.14241,10.57046,'tirol','city','Inn und Sanna'),
('mayrhofen','Mayrhofen',47.16722,11.86387,'tirol','city','Zillertal'),
('reutte','Reutte',47.48911,10.71880,'tirol','city','Außerfern'),
('schwaz','Schwaz',47.34495,11.70843,'tirol','city','Silberstadt'),
('st_johann','St. Johann in Tirol',47.52241,12.42868,'tirol','city','Kaisergebirge'),
('telfs','Telfs',47.30465,11.07152,'tirol','city','Fasnacht'),
('woergl','Wörgl',47.48889,12.06389,'tirol','city','Freigeld-Experiment'),
('zell_ziller','Zell am Ziller',47.23360,11.88199,'tirol','city','Gauder Fest'),
('fulpmes','Fulpmes',47.15310,11.34906,'tirol','village','Stubaital'),
('hintertux','Hintertux',47.11500,11.68250,'tirol','village','Gletscher 3250m'),
('kals','Kals am Großglockner',47.00238,12.64585,'tirol','village','Glockner-Zugang'),
('matrei','Matrei in Osttirol',47.00000,12.53333,'tirol','village','Iseltal'),
('neustift','Neustift im Stubaital',47.11064,11.30758,'tirol','village','Stubaital'),
('obergurgl','Obergurgl',46.87000,11.03000,'tirol','village','1930m Höhe'),
('oetz','Ötz',47.19860,10.90310,'tirol','village','Ötztal'),
('scharnitz','Scharnitz',47.38889,11.26472,'tirol','village','Karwendel-Tor'),
('seefeld','Seefeld',47.33000,11.19000,'tirol','village','Olympia-Ort'),
('sillian','Sillian',46.74729,12.41803,'tirol','village','Grenze Italien'),
('soelden','Sölden',46.96660,11.00730,'tirol','village','Gletscherskigebiet'),
('st_anton','St. Anton am Arlberg',47.12861,10.26528,'tirol','village','Wiege des Skilaufs'),
('steinach','Steinach am Brenner',47.08861,11.46722,'tirol','village','Wipptal'),
('skiunfall_soelden','Skiunfall Sölden',46.97564,10.97486,'tirol','target','Skigebiet'),
('brenner','Brenner',47.00740,11.50670,'tirol','pass','Alpenpass nach Italien'),
('nenzing','C8 Nenzing (ÖAMTC)',47.20900,9.66000,'vorarlberg','base','ÖAMTC Stützpunkt'),
('hohenems','Hohenems (Flugplatz)',47.38440,9.69930,'vorarlberg','base','Flugplatz LOIH'),
('bezau','Bezau',47.38611,9.90000,'vorarlberg','city','Käsetradition'),
('bludenz','Bludenz',47.15444,9.82167,'vorarlberg','city','Tor zu 3 Tälern'),
('bregenz','Bregenz',47.50278,9.74722,'vorarlberg','city','Landeshauptstadt'),
('dornbirn','Dornbirn',47.41250,9.74167,'vorarlberg','city','Größte Stadt Vlbg'),
('egg','Egg',47.43167,9.89444,'vorarlberg','city','Bregenzerwald'),
('feldkirch','Feldkirch',47.23528,9.59806,'vorarlberg','city','Grenzstadt CH/FL'),
('goetzis','Götzis',47.33513,9.64401,'vorarlberg','city','Hypomeeting'),
('lustenau','Lustenau',47.42765,9.65994,'vorarlberg','city','Grenzgemeinde CH'),
('rankweil','Rankweil',47.27222,9.64444,'vorarlberg','city','Wallfahrtsort'),
('schruns','Schruns',47.07972,9.91667,'vorarlberg','city','Montafon Hauptort'),
('au','Au',47.32246,9.97748,'vorarlberg','village','Bregenzerwald'),
('brand','Brand',47.10425,9.73788,'vorarlberg','village','Brandnertal'),
('buers','Bürs',47.15139,9.80000,'vorarlberg','village',NULL),
('damuels','Damüls',47.28045,9.89096,'vorarlberg','village','Schneereichstes Dorf'),
('fontanella','Fontanella',47.24750,9.90880,'vorarlberg','village','Großes Walsertal'),
('gaschurn','Gaschurn',46.98333,10.03333,'vorarlberg','village','Hinteres Montafon'),
('innerbraz','Innerbraz',47.14443,9.91579,'vorarlberg','village','Klostertal'),
('kloesterle','Klösterle',47.13128,10.09213,'vorarlberg','village','Klostertal'),
('langen','Langen am Arlberg',47.13211,10.12073,'vorarlberg','village','Arlbergtunnel'),
('laterns','Laterns',47.27040,9.76590,'vorarlberg','village','Laternsertal'),
('mellau','Mellau',47.35000,9.88056,'vorarlberg','village','Canyoning'),
('mittelberg','Mittelberg',47.32410,10.15445,'vorarlberg','village','Kleinwalsertal'),
('nueziders','Nüziders',47.17083,9.80000,'vorarlberg','village',NULL),
('partenen','Partenen',46.96889,10.06389,'vorarlberg','village','Silvretta-Zugang'),
('riezlern','Riezlern',47.35833,10.19167,'vorarlberg','village','Kleinwalsertal'),
('schoppernau','Schoppernau',47.31336,10.01509,'vorarlberg','village','Bregenzerwald'),
('schroecken','Schröcken',47.25833,10.09167,'vorarlberg','village','Hochtannberg'),
('sonntag','Sonntag',47.23779,9.89587,'vorarlberg','village','Großes Walsertal'),
('stgallenk','St. Gallenkirch',47.02222,9.97222,'vorarlberg','village','Montafon'),
('stuben','Stuben am Arlberg',47.13775,10.17627,'vorarlberg','village','Arlberg'),
('thueringen','Thüringen',47.20000,9.76667,'vorarlberg','village','Walgau'),
('tschagguns','Tschagguns',47.07778,9.90000,'vorarlberg','village','Montafon'),
('warth','Warth',47.25817,10.18335,'vorarlberg','village','Ski Arlberg'),
('zwischenwasser','Zwischenwasser',47.28160,9.66390,'vorarlberg','village','Walgau'),
('bergrettung_muels','Skiunfall Damüls-Mellau',47.29325,9.88957,'vorarlberg','target','Skigebiet'),
('verkehr_a14','Unfall A14 Rankweil',47.27063,9.62238,'vorarlberg','target','Autobahnabfahrt'),
('wien_c9','C9 Wien (ÖAMTC)',48.22220,16.50470,'wien','base','Wien-Aspern, ÖAMTC Christophorus 9.'),
('wien','Wien (Stephansplatz)',48.20850,16.37190,'wien','city','Hauptstadt, 1,9 Mio Einwohner:innen.'),
('wien_donau','Neue Donau Wien',48.24000,16.42000,'wien','village','Erholungsgebiet am Hochwasserarm der Donau.'),
('see_donau_wien','Donau-Rettung Wien',48.24000,16.42000,'wien','target','Schwimmer:in in Sog der Neuen Donau.');
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>Thats an error.</ins>
<p>The requested URL <code>/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hjQ.woff2</code> was not found on this server. <ins>Thats all we know.</ins>
-42
View File
@@ -1,42 +0,0 @@
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfMZg.ttf) format('truetype');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf) format('truetype');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf) format('truetype');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuFuYMZg.ttf) format('truetype');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuDyYMZg.ttf) format('truetype');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuBWYMZg.ttf) format('truetype');
}
-7
View File
@@ -1,7 +0,0 @@
/* Inter Font — lokal gehostet (kein Google-Server) */
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('inter-400.ttf') format('truetype'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('inter-500.ttf') format('truetype'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('inter-600.ttf') format('truetype'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap; src: url('inter-700.ttf') format('truetype'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 800; font-display: swap; src: url('inter-800.ttf') format('truetype'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 900; font-display: swap; src: url('inter-900.ttf') format('truetype'); }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 857 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 68 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 64 KiB

-147
View File
@@ -1,147 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 440" font-family="Inter, system-ui, sans-serif" width="900" height="440">
<defs>
<marker id="al-in" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#e8833a"/>
</marker>
<marker id="al-out" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f4c94e"/>
</marker>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Albedo — Wie viel Sonnenlicht wirft die Oberfläche zurück?
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Helle Oberflächen reflektieren viel, dunkle absorbieren Wärme. 1,0 = Spiegel · 0,0 = schwarz
</text>
<!-- 5 vertikale Spalten: Schnee, Wüste, Wald, Ozean, Asphalt -->
<!-- Jede Spalte: 160 px breit. Startet x=60 -->
<!-- SURFACE, Albedo, Color -->
<!-- Column 1: Frischer Schnee A=0.85 -->
<g transform="translate(80, 90)">
<text y="-10" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle" x="70">❄ Frischer Schnee</text>
<!-- Sonne-Pfeil rein -->
<line x1="10" y1="0" x2="60" y2="70" stroke="#e8833a" stroke-width="2.5" marker-end="url(#al-in)"/>
<!-- 85% raus (mehrere Pfeile) -->
<g stroke="#f4c94e" stroke-width="2" fill="none" marker-end="url(#al-out)">
<line x1="60" y1="70" x2="130" y2="10"/>
<line x1="60" y1="70" x2="115" y2="0"/>
<line x1="60" y1="70" x2="100" y2="-5"/>
<line x1="60" y1="70" x2="130" y2="25"/>
</g>
<!-- Oberfläche -->
<rect x="0" y="70" width="140" height="50" fill="#fff" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Schnee-Sparkle -->
<g fill="#4a7c8a" opacity=".4">
<circle cx="20" cy="85" r="1"/><circle cx="50" cy="98" r="1"/>
<circle cx="85" cy="82" r="1"/><circle cx="110" cy="100" r="1"/>
<circle cx="130" cy="90" r="1"/>
</g>
<text x="70" y="140" font-size="24" font-weight="900" fill="#1f4e5a" text-anchor="middle">0,85</text>
<text x="70" y="158" font-size="9" fill="#4a7c8a" text-anchor="middle">85 % zurückgeworfen</text>
<!-- Balken 0-100% -->
<rect x="10" y="175" width="120" height="8" fill="#dae8ec" rx="2"/>
<rect x="10" y="175" width="102" height="8" fill="#4a7c8a" rx="2"/>
</g>
<!-- Column 2: Wüste/Sand A=0.35 -->
<g transform="translate(240, 90)">
<text y="-10" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle" x="70">🏜 Wüste · Sand</text>
<line x1="10" y1="0" x2="60" y2="70" stroke="#e8833a" stroke-width="2.5" marker-end="url(#al-in)"/>
<g stroke="#f4c94e" stroke-width="2" fill="none" marker-end="url(#al-out)" opacity=".6">
<line x1="60" y1="70" x2="115" y2="20"/>
<line x1="60" y1="70" x2="100" y2="5"/>
</g>
<rect x="0" y="70" width="140" height="50" fill="#e8d5b5" stroke="#1f4e5a" stroke-width="1.5"/>
<g fill="#c4a97a" opacity=".6">
<circle cx="30" cy="88" r="2"/><circle cx="70" cy="100" r="2"/>
<circle cx="110" cy="85" r="2"/>
<path d="M 10 110 Q 35 106 60 110 Q 85 114 110 110 Q 125 108 130 110" fill="none" stroke="#c4a97a" stroke-width=".8"/>
</g>
<text x="70" y="140" font-size="24" font-weight="900" fill="#1f4e5a" text-anchor="middle">0,35</text>
<text x="70" y="158" font-size="9" fill="#c4a97a" text-anchor="middle">35 % zurückgeworfen</text>
<rect x="10" y="175" width="120" height="8" fill="#dae8ec" rx="2"/>
<rect x="10" y="175" width="42" height="8" fill="#c4a97a" rx="2"/>
</g>
<!-- Column 3: Wald A=0.12 -->
<g transform="translate(400, 90)">
<text y="-10" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle" x="70">🌲 Wald</text>
<line x1="10" y1="0" x2="60" y2="70" stroke="#e8833a" stroke-width="2.5" marker-end="url(#al-in)"/>
<g stroke="#f4c94e" stroke-width="1.5" fill="none" marker-end="url(#al-out)" opacity=".4">
<line x1="60" y1="70" x2="95" y2="35"/>
</g>
<rect x="0" y="70" width="140" height="50" fill="#3a6b3e" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Baumsymbole -->
<g fill="#5a8a5e">
<polygon points="15,115 22,92 29,115"/>
<polygon points="42,115 50,88 58,115"/>
<polygon points="70,115 80,85 90,115"/>
<polygon points="100,115 108,90 116,115"/>
<polygon points="122,115 130,93 138,115"/>
</g>
<text x="70" y="140" font-size="24" font-weight="900" fill="#1f4e5a" text-anchor="middle">0,12</text>
<text x="70" y="158" font-size="9" fill="#3a6b3e" text-anchor="middle">12 % zurückgeworfen</text>
<rect x="10" y="175" width="120" height="8" fill="#dae8ec" rx="2"/>
<rect x="10" y="175" width="14" height="8" fill="#3a6b3e" rx="2"/>
</g>
<!-- Column 4: Ozean A=0.06 -->
<g transform="translate(560, 90)">
<text y="-10" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle" x="70">🌊 Ozean</text>
<line x1="10" y1="0" x2="60" y2="70" stroke="#e8833a" stroke-width="2.5" marker-end="url(#al-in)"/>
<g stroke="#f4c94e" stroke-width="1" fill="none" marker-end="url(#al-out)" opacity=".3">
<line x1="60" y1="70" x2="85" y2="45"/>
</g>
<rect x="0" y="70" width="140" height="50" fill="#1f4e5a" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Wellen -->
<g fill="none" stroke="#4a7c8a" stroke-width=".8" opacity=".5">
<path d="M 5 85 Q 20 82 35 85 Q 50 88 65 85 Q 80 82 95 85 Q 110 88 125 85 Q 135 83 138 85"/>
<path d="M 5 100 Q 20 97 35 100 Q 50 103 65 100 Q 80 97 95 100 Q 110 103 125 100 Q 135 98 138 100"/>
</g>
<text x="70" y="140" font-size="24" font-weight="900" fill="#1f4e5a" text-anchor="middle">0,06</text>
<text x="70" y="158" font-size="9" fill="#1f4e5a" text-anchor="middle">6 % zurückgeworfen</text>
<rect x="10" y="175" width="120" height="8" fill="#dae8ec" rx="2"/>
<rect x="10" y="175" width="7" height="8" fill="#1f4e5a" rx="2"/>
</g>
<!-- Column 5: Asphalt A=0.05 -->
<g transform="translate(720, 90)">
<text y="-10" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle" x="70">🛣 Asphalt</text>
<line x1="10" y1="0" x2="60" y2="70" stroke="#e8833a" stroke-width="2.5" marker-end="url(#al-in)"/>
<g stroke="#f4c94e" stroke-width="1" fill="none" marker-end="url(#al-out)" opacity=".25">
<line x1="60" y1="70" x2="80" y2="50"/>
</g>
<rect x="0" y="70" width="140" height="50" fill="#2a2a2a" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Straßenmarkierung -->
<g fill="#fff" opacity=".8">
<rect x="20" y="93" width="14" height="3"/>
<rect x="50" y="93" width="14" height="3"/>
<rect x="80" y="93" width="14" height="3"/>
<rect x="110" y="93" width="14" height="3"/>
</g>
<text x="70" y="140" font-size="24" font-weight="900" fill="#1f4e5a" text-anchor="middle">0,05</text>
<text x="70" y="158" font-size="9" fill="#2a2a2a" text-anchor="middle">5 % zurückgeworfen</text>
<rect x="10" y="175" width="120" height="8" fill="#dae8ec" rx="2"/>
<rect x="10" y="175" width="6" height="8" fill="#2a2a2a" rx="2"/>
</g>
<!-- Erklärung Rückkopplung -->
<g transform="translate(50, 310)">
<rect x="0" y="0" width="800" height="110" rx="8" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="20" y="22" font-size="12" font-weight="800" fill="#1f4e5a">⚠ Warum das Klima betrifft: Die Eis-Albedo-Rückkopplung</text>
<text x="20" y="46" font-size="10" fill="#4a4a4a">1.</text>
<text x="38" y="46" font-size="10" fill="#4a4a4a">Das Klima wird wärmer → Meereis und Gletscher schmelzen.</text>
<text x="20" y="64" font-size="10" fill="#4a4a4a">2.</text>
<text x="38" y="64" font-size="10" fill="#4a4a4a">Statt weißem Eis (A=0,85) liegt nun dunkler Ozean (A=0,06) oder dunkler Boden unter der Sonne.</text>
<text x="20" y="82" font-size="10" fill="#4a4a4a">3.</text>
<text x="38" y="82" font-size="10" fill="#4a4a4a">Die Oberfläche absorbiert viel mehr Wärme → das Klima wird noch wärmer → mehr Eis schmilzt.</text>
<text x="20" y="100" font-size="10" fill="#c85c4a" font-weight="700">→ Eine sich selbst verstärkende Rückkopplung — einer der Gründe für den beschleunigten Klimawandel in der Arktis.</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.2 KiB

@@ -1,58 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 440" font-family="Inter, system-ui, sans-serif" width="900" height="440">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Living Planet Index — Wirbeltier-Populationen haben sich seit 1970 mehr als gedrittelt
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Mittelwert von weltweit 34.836 beobachteten Populationen · Datenstand 2024
</text>
<!-- Plot: x 80..750, y 90..340. X: 1970..2020 = 50 a in 670 px → 13.4 px/a. Y: 100%..25% = 75% in 250 px → 3.33 px/% -->
<line x1="80" y1="340" x2="750" y2="340" stroke="#1f4e5a" stroke-width="1.5"/>
<line x1="80" y1="90" x2="80" y2="340" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Y Grid -->
<g font-size="10" fill="#4a4a4a" text-anchor="end">
<line x1="80" y1="90" x2="750" y2="90" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="93">100 %</text>
<line x1="80" y1="173.3" x2="750" y2="173.3" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="176.3">75 %</text>
<line x1="80" y1="256.7" x2="750" y2="256.7" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="259.7">50 %</text>
<line x1="80" y1="340" x2="750" y2="340" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="343">25 %</text>
</g>
<text x="20" y="215" font-size="11" font-weight="700" fill="#1f4e5a" transform="rotate(-90 20 215)" text-anchor="middle">Population Index</text>
<!-- X Achse -->
<g font-size="10" fill="#4a4a4a" text-anchor="middle">
<line x1="80" y1="340" x2="80" y2="345" stroke="#1f4e5a"/><text x="80" y="360">1970</text>
<line x1="214" y1="340" x2="214" y2="345" stroke="#1f4e5a"/><text x="214" y="360">1980</text>
<line x1="348" y1="340" x2="348" y2="345" stroke="#1f4e5a"/><text x="348" y="360">1990</text>
<line x1="482" y1="340" x2="482" y2="345" stroke="#1f4e5a"/><text x="482" y="360">2000</text>
<line x1="616" y1="340" x2="616" y2="345" stroke="#1f4e5a"/><text x="616" y="360">2010</text>
<line x1="750" y1="340" x2="750" y2="345" stroke="#1f4e5a"/><text x="750" y="360">2020</text>
</g>
<!-- Linie — grobe Approximation der globalen LPI-Kurve 1970→2020 (100→27%) -->
<!-- Stützpunkte %: 1970=100, 1980=84, 1990=67, 2000=52, 2010=42, 2020=27
y(%) = 90 + (100-%)*3.333 -->
<polyline fill="none" stroke="#c85c4a" stroke-width="3" stroke-linejoin="round"
points="80,90 214,143.3 348,200 482,250 616,283.3 750,333.3"/>
<!-- Unsicherheitsband (sehr vereinfacht) -->
<polyline fill="#c85c4a" fill-opacity=".12" stroke="none"
points="80,90 214,120 348,175 482,220 616,260 750,305 750,360 616,305 482,280 348,230 214,170 80,110"/>
<!-- Endmarke -->
<circle cx="750" cy="333.3" r="6" fill="#c85c4a"/>
<text x="740" y="325" font-size="12" font-weight="800" fill="#c85c4a" text-anchor="end">2020 · 27 %</text>
<text x="740" y="310" font-size="10" fill="#c85c4a" text-anchor="end">(73 % gegenüber 1970)</text>
<!-- Startmarke -->
<circle cx="80" cy="90" r="6" fill="#5a8a5e"/>
<text x="90" y="86" font-size="12" font-weight="800" fill="#5a8a5e">1970 · 100 % (Referenz)</text>
<!-- Ursachen-Icons -->
<g transform="translate(80,380)">
<rect x="0" y="0" width="670" height="35" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="15" font-size="10" font-weight="800" fill="#1f4e5a">Hauptursachen:</text>
<text x="96" y="15" font-size="10" fill="#4a4a4a">🌾 Landnutzung · 🌡️ Klimawandel · 🪓 Übernutzung · 🐀 Invasive Arten · 🏭 Verschmutzung</text>
<text x="10" y="28" font-size="10" font-weight="800" fill="#1f4e5a">Quelle:</text>
<text x="56" y="28" font-size="10" fill="#4a4a4a">WWF &amp; Zoological Society of London (2024): Living Planet Report 2024 · IPBES Global Assessment 2019</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

-110
View File
@@ -1,110 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 480" font-family="Inter, system-ui, sans-serif" width="900" height="480">
<text x="450" y="32" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
CO₂-Fußabdruck in Österreich — 8 Tonnen pro Person pro Jahr
</text>
<text x="450" y="52" font-size="11" fill="#8a8a8a" text-anchor="middle">
Aufgeteilt auf die vier großen Lebensbereiche. Klimaneutral wären unter 1 t.
</text>
<!-- Vier Säulen, jede 2 t CO₂ = Höhe 140 px. 1t = 70 px -->
<!-- Basis bei y=340 -->
<g>
<!-- Säule Wohnen (Heizung + Strom) 2 t -->
<g transform="translate(165, 340)">
<rect x="-55" y="-140" width="110" height="140" fill="#4a7c8a" stroke="#1f4e5a" stroke-width="1"/>
<rect x="-55" y="-140" width="110" height="15" fill="#3a6470"/>
<text y="-150" font-size="16" font-weight="900" fill="#1f4e5a" text-anchor="middle">2,0 t</text>
<text y="-132" font-size="12" font-weight="700" fill="#fff" text-anchor="middle">🏠 Wohnen</text>
<text y="-115" font-size="9" fill="#dae8ec" text-anchor="middle">Heizung · Strom</text>
<text y="-102" font-size="9" fill="#dae8ec" text-anchor="middle">Warmwasser</text>
<text y="14" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Wohnen</text>
<text y="28" font-size="9" fill="#8a8a8a" text-anchor="middle">25 % Anteil</text>
</g>
<!-- Säule Verkehr 2 t -->
<g transform="translate(335, 340)">
<rect x="-55" y="-140" width="110" height="140" fill="#c85c4a" stroke="#1f4e5a" stroke-width="1"/>
<rect x="-55" y="-140" width="110" height="15" fill="#a9443a"/>
<text y="-150" font-size="16" font-weight="900" fill="#1f4e5a" text-anchor="middle">2,0 t</text>
<text y="-132" font-size="12" font-weight="700" fill="#fff" text-anchor="middle">🚗 Verkehr</text>
<text y="-115" font-size="9" fill="#f0d0ca" text-anchor="middle">Auto · Flug</text>
<text y="-102" font-size="9" fill="#f0d0ca" text-anchor="middle">Pendeln</text>
<text y="14" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Verkehr</text>
<text y="28" font-size="9" fill="#8a8a8a" text-anchor="middle">25 % Anteil</text>
</g>
<!-- Säule Ernährung 2 t -->
<g transform="translate(505, 340)">
<rect x="-55" y="-140" width="110" height="140" fill="#5a8a5e" stroke="#1f4e5a" stroke-width="1"/>
<rect x="-55" y="-140" width="110" height="15" fill="#3a6b3e"/>
<text y="-150" font-size="16" font-weight="900" fill="#1f4e5a" text-anchor="middle">2,0 t</text>
<text y="-132" font-size="12" font-weight="700" fill="#fff" text-anchor="middle">🥩 Ernährung</text>
<text y="-115" font-size="9" fill="#dcead0" text-anchor="middle">Fleisch · Milch</text>
<text y="-102" font-size="9" fill="#dcead0" text-anchor="middle">Importe</text>
<text y="14" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Ernährung</text>
<text y="28" font-size="9" fill="#8a8a8a" text-anchor="middle">25 % Anteil</text>
</g>
<!-- Säule Konsum 2 t -->
<g transform="translate(675, 340)">
<rect x="-55" y="-140" width="110" height="140" fill="#e8833a" stroke="#1f4e5a" stroke-width="1"/>
<rect x="-55" y="-140" width="110" height="15" fill="#b8641d"/>
<text y="-150" font-size="16" font-weight="900" fill="#1f4e5a" text-anchor="middle">2,0 t</text>
<text y="-132" font-size="12" font-weight="700" fill="#fff" text-anchor="middle">🛒 Konsum</text>
<text y="-115" font-size="9" fill="#f5e0c8" text-anchor="middle">Kleidung</text>
<text y="-102" font-size="9" fill="#f5e0c8" text-anchor="middle">Elektronik</text>
<text y="14" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Konsum</text>
<text y="28" font-size="9" fill="#8a8a8a" text-anchor="middle">25 % Anteil</text>
</g>
</g>
<!-- Klimaneutralitäts-Linie bei 1 t (= 70 px über Basis) -->
<g>
<line x1="90" y1="270" x2="750" y2="270" stroke="#3a6b3e" stroke-width="2" stroke-dasharray="6 4"/>
<text x="760" y="266" font-size="10" fill="#3a6b3e" font-weight="800">1 t = Klimaneutral-Ziel</text>
<text x="760" y="278" font-size="9" fill="#8a8a8a">(pro Person pro Jahr)</text>
</g>
<!-- Summen-Ballon oben -->
<g transform="translate(450, 110)">
<circle r="42" fill="#c85c4a" stroke="#1f4e5a" stroke-width="1.5"/>
<text y="-6" font-size="22" font-weight="900" fill="#fff" text-anchor="middle">8 t</text>
<text y="13" font-size="10" font-weight="700" fill="#fff" text-anchor="middle">CO₂ / Jahr</text>
<text y="25" font-size="9" fill="#f0d0ca" text-anchor="middle">pro Person</text>
</g>
<!-- X-Achse -->
<line x1="90" y1="340" x2="750" y2="340" stroke="#1f4e5a" stroke-width="2"/>
<!-- Y-Achse mit Tonnen-Markierungen -->
<g>
<line x1="90" y1="130" x2="90" y2="340" stroke="#1f4e5a" stroke-width="1.5"/>
<g font-size="9" fill="#4a4a4a" text-anchor="end">
<line x1="86" y1="340" x2="90" y2="340" stroke="#1f4e5a"/><text x="84" y="343">0 t</text>
<line x1="86" y1="270" x2="90" y2="270" stroke="#1f4e5a"/><text x="84" y="273">1 t</text>
<line x1="86" y1="200" x2="90" y2="200" stroke="#1f4e5a"/><text x="84" y="203">2 t</text>
<line x1="86" y1="130" x2="90" y2="130" stroke="#1f4e5a"/><text x="84" y="133">3 t</text>
</g>
</g>
<!-- Vergleichsbox unten -->
<g transform="translate(0, 370)">
<rect x="50" y="0" width="800" height="95" rx="8" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="70" y="22" font-size="11" fill="#1f4e5a" font-weight="800">So viel CO₂ ist das konkret:</text>
<text x="70" y="45" font-size="10" fill="#4a4a4a">🚗 Ein Jahr Auto (10.000 km):</text>
<text x="270" y="45" font-size="10" fill="#c85c4a" font-weight="700">1,6 t CO₂</text>
<text x="400" y="45" font-size="10" fill="#4a4a4a">✈ Flug WienBali + zurück:</text>
<text x="580" y="45" font-size="10" fill="#c85c4a" font-weight="700">3,5 t CO₂</text>
<text x="70" y="63" font-size="10" fill="#4a4a4a">🍖 Ein Jahr Fleisch essen:</text>
<text x="270" y="63" font-size="10" fill="#c85c4a" font-weight="700">1,2 t CO₂</text>
<text x="400" y="63" font-size="10" fill="#4a4a4a">🥗 Ein Jahr vegan statt Fleisch:</text>
<text x="580" y="63" font-size="10" fill="#5a8a5e" font-weight="700">0,7 t CO₂</text>
<text x="70" y="81" font-size="10" fill="#4a4a4a">🏭 Welt-Durchschnitt pro Kopf:</text>
<text x="270" y="81" font-size="10" fill="#4a7c8a" font-weight="700">4,7 t CO₂</text>
<text x="400" y="81" font-size="10" fill="#4a4a4a">🇺🇸 USA: 14 t · 🇮🇳 Indien: 1,9 t · 🌍 Klima-Ziel:</text>
<text x="650" y="81" font-size="10" fill="#5a8a5e" font-weight="700">unter 1 t</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

@@ -1,82 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 460" font-family="Inter, system-ui, sans-serif" width="900" height="460">
<defs>
<linearGradient id="co2-fill" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#c85c4a" stop-opacity=".35"/>
<stop offset="1" stop-color="#c85c4a" stop-opacity="0"/>
</linearGradient>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
CO₂ in der Atmosphäre — seit 1750 um rund 50 % gestiegen
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Datengrundlage: Eisbohrkerne (Law Dome, Antarktis) + NOAA Mauna Loa 19582024
</text>
<!-- Achsen -->
<!-- Plot-Fläche: x 80..870, y 90..380 -->
<line x1="80" y1="380" x2="870" y2="380" stroke="#1f4e5a" stroke-width="1.5"/>
<line x1="80" y1="90" x2="80" y2="380" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- Y-Grid + Labels (ppm) -->
<g font-size="10" fill="#4a4a4a" text-anchor="end">
<!-- Range: 250 → 450 ppm = 200 ppm auf 290 px → 1,45 px/ppm -->
<!-- Positionen: 250(380), 300(307.5), 350(235), 400(162.5), 450(90) -->
<line x1="80" y1="380" x2="870" y2="380" stroke="#dae8ec" stroke-width=".5"/>
<line x1="80" y1="307.5" x2="870" y2="307.5" stroke="#dae8ec" stroke-width=".5"/>
<line x1="80" y1="235" x2="870" y2="235" stroke="#dae8ec" stroke-width=".5"/>
<line x1="80" y1="162.5" x2="870" y2="162.5" stroke="#dae8ec" stroke-width=".5"/>
<line x1="80" y1="90" x2="870" y2="90" stroke="#dae8ec" stroke-width=".5"/>
<text x="74" y="383">250</text>
<text x="74" y="310.5">300</text>
<text x="74" y="238">350</text>
<text x="74" y="165.5">400</text>
<text x="74" y="93">450</text>
</g>
<text x="30" y="240" font-size="11" font-weight="700" fill="#1f4e5a" transform="rotate(-90 30 240)" text-anchor="middle">CO₂-Konzentration in ppm</text>
<!-- X-Achse: 1750 → 2025 = 275 Jahre auf 790 px → 2,87 px/Jahr -->
<!-- Jahre: 1750(80), 1800(223.5), 1850(367), 1900(510), 1950(654), 2000(797), 2025(870) -->
<g font-size="10" fill="#4a4a4a" text-anchor="middle">
<line x1="80" y1="380" x2="80" y2="385" stroke="#1f4e5a"/><text x="80" y="400">1750</text>
<line x1="223.5" y1="380" x2="223.5" y2="385" stroke="#1f4e5a"/><text x="223.5" y="400">1800</text>
<line x1="367" y1="380" x2="367" y2="385" stroke="#1f4e5a"/><text x="367" y="400">1850</text>
<line x1="510" y1="380" x2="510" y2="385" stroke="#1f4e5a"/><text x="510" y="400">1900</text>
<line x1="654" y1="380" x2="654" y2="385" stroke="#1f4e5a"/><text x="654" y="400">1950</text>
<line x1="797" y1="380" x2="797" y2="385" stroke="#1f4e5a"/><text x="797" y="400">2000</text>
<line x1="870" y1="380" x2="870" y2="385" stroke="#1f4e5a"/><text x="870" y="400">2024</text>
</g>
<text x="475" y="425" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Jahr</text>
<!-- Daten-Polyline (approximiert, Hauptstützpunkte aus Law Dome + NOAA) -->
<!-- Year → ppm:
1750→277, 1800→281, 1850→285, 1880→290, 1900→296, 1920→303,
1940→311, 1958→315, 1970→326, 1980→339, 1990→354, 2000→370,
2010→389, 2020→413, 2024→422
x = 80 + (year-1750)*2.87 y = 380 - (ppm-250)*1.45 -->
<polyline fill="url(#co2-fill)" stroke="none"
points="80,380 80,340.85 223.5,335.05 367,329.25 453.1,321.95 510,314.65 567.4,308.85 624.8,301.55 676.46,297.75 710.86,284 739.44,266.05 768.03,239.4 796.61,206.95 825.19,173.05 853.77,143.5 870,141.9 870,380"/>
<polyline fill="none" stroke="#c85c4a" stroke-width="2.5" stroke-linejoin="round"
points="80,340.85 223.5,335.05 367,329.25 453.1,321.95 510,314.65 567.4,308.85 624.8,301.55 676.46,297.75 710.86,284 739.44,266.05 768.03,239.4 796.61,206.95 825.19,173.05 853.77,143.5 870,141.9"/>
<!-- Markante Punkte -->
<g fill="#1f4e5a">
<circle cx="80" cy="340.85" r="4"/>
<text x="90" y="338" font-size="10" font-weight="700">1750 · 277 ppm</text>
<circle cx="367" cy="329.25" r="4"/>
<text x="377" y="326" font-size="10" font-weight="700">1850 · 285 ppm</text>
<circle cx="676.46" cy="297.75" r="4"/>
<text x="560" y="293" font-size="10" font-weight="700">1958 · 315 ppm (Mauna-Loa-Start)</text>
<circle cx="870" cy="141.9" r="5" fill="#c85c4a"/>
<text x="862" y="132" font-size="11" font-weight="800" fill="#c85c4a" text-anchor="end">2024 · 422 ppm</text>
</g>
<!-- Vorindustriell-Band -->
<rect x="80" y="329.25" width="790" height="22" fill="#5a8a5e" opacity=".12"/>
<text x="86" y="346" font-size="9" fill="#3a6b3e" font-weight="700">Vorindustriell: 280 ppm</text>
<!-- Fußzeile -->
<g transform="translate(50,430)">
<text x="0" y="15" font-size="10" fill="#4a4a4a" font-weight="700">Quellen:</text>
<text x="65" y="15" font-size="10" fill="#4a4a4a">NOAA Global Monitoring Lab (Mauna Loa Zeitreihe) · Etheridge et al. 1996 (Law Dome Eisbohrkern, CSIRO) · WMO Greenhouse Gas Bulletin 2023</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

@@ -1,104 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 480" font-family="Inter, system-ui, sans-serif" width="900" height="480">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Strommix Österreich 2023 — 84 % erneuerbar, aber im Gesamtenergiemix noch 62 % fossil
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Anteile am Endverbrauch · Daten: E-Control · Statistik Austria
</text>
<!-- ====== LINKS: Strom-Kuchen ====== -->
<g transform="translate(230,260)">
<text x="0" y="-140" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">Strommix</text>
<text x="0" y="-124" font-size="11" fill="#8a8a8a" text-anchor="middle">Bruttoinlandserzeugung 2023</text>
<!-- Kuchenstücke auf r=100 -->
<!-- Reihenfolge startet oben (12 Uhr), im Uhrzeigersinn:
Wasser 58%, Wind 11%, Biomasse 8%, PV 7%, Gas 10%, Sonstige 6% -->
<!-- Mathematische Hilfe: Winkel in Grad, x = r*sin(a), y = -r*cos(a) -->
<!-- Wasser: 0 → 208.8° -->
<path d="M 0 0 L 0 -100 A 100 100 0 1 1 -48.17 87.63 Z" fill="#4a7c8a"/>
<!-- Wind: 208.8 → 248.4° -->
<path d="M 0 0 L -48.17 87.63 A 100 100 0 0 1 -92.99 36.81 Z" fill="#5a8a5e"/>
<!-- Biomasse: 248.4 → 277.2° -->
<path d="M 0 0 L -92.99 36.81 A 100 100 0 0 1 -99.20 -12.62 Z" fill="#3a6b3e"/>
<!-- PV: 277.2 → 302.4° -->
<path d="M 0 0 L -99.20 -12.62 A 100 100 0 0 1 -84.43 -53.58 Z" fill="#f4c94e"/>
<!-- Gas: 302.4 → 338.4° -->
<path d="M 0 0 L -84.43 -53.58 A 100 100 0 0 1 -36.81 -92.99 Z" fill="#c85c4a"/>
<!-- Sonstige: 338.4 → 360° -->
<path d="M 0 0 L -36.81 -92.99 A 100 100 0 0 1 0 -100 Z" fill="#c4a97a"/>
<!-- Zentrale Beschriftung -->
<circle r="42" fill="#fff"/>
<text y="-3" font-size="18" font-weight="900" fill="#1f4e5a" text-anchor="middle">84 %</text>
<text y="14" font-size="9" font-weight="700" fill="#5a8a5e" text-anchor="middle">erneuerbar</text>
<!-- Segmentlabels -->
<text x="55" y="-45" font-size="11" font-weight="800" fill="#fff" text-anchor="middle">58 %</text>
<text x="55" y="-28" font-size="9" fill="#fff" text-anchor="middle">Wasser</text>
<text x="-62" y="75" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">11 %</text>
<text x="-62" y="88" font-size="8" fill="#fff" text-anchor="middle">Wind</text>
</g>
<!-- Legende rechts neben Kuchen -->
<g transform="translate(370,160)" font-size="11">
<g><rect x="0" y="0" width="14" height="14" fill="#4a7c8a"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Wasserkraft 58 %</text></g>
<g transform="translate(0,22)"><rect width="14" height="14" fill="#5a8a5e"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Windenergie 11 %</text></g>
<g transform="translate(0,44)"><rect width="14" height="14" fill="#3a6b3e"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Biomasse 8 %</text></g>
<g transform="translate(0,66)"><rect width="14" height="14" fill="#f4c94e"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Photovoltaik 7 %</text></g>
<g transform="translate(0,88)"><rect width="14" height="14" fill="#c85c4a"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Erdgas 10 %</text></g>
<g transform="translate(0,110)"><rect width="14" height="14" fill="#c4a97a"/><text x="22" y="11" fill="#1f4e5a" font-weight="700">Sonstige 6 %</text></g>
</g>
<!-- ====== RECHTS: Gesamtenergie-Balken (horizontal) ====== -->
<g transform="translate(550,130)">
<text x="0" y="0" font-size="14" font-weight="800" fill="#1f4e5a">Gesamtenergie 2023</text>
<text x="0" y="16" font-size="11" fill="#8a8a8a">(Strom + Wärme + Verkehr)</text>
<!-- Balken 300 × 60 horizontal stacked, Anteile: Öl 36%, Gas 19%, Kohle 6%, EE 38%, Sonst 1% -->
<!-- Gesamtbreite 300 px -->
<g transform="translate(0,35)">
<rect x="0" y="0" width="108" height="60" fill="#6b4a2e"/>
<text x="54" y="28" font-size="12" font-weight="800" fill="#fff" text-anchor="middle">36 %</text>
<text x="54" y="44" font-size="10" fill="#fff" text-anchor="middle">Erdöl</text>
<rect x="108" y="0" width="57" height="60" fill="#c85c4a"/>
<text x="136" y="28" font-size="11" font-weight="800" fill="#fff" text-anchor="middle">19 %</text>
<text x="136" y="42" font-size="9" fill="#fff" text-anchor="middle">Gas</text>
<rect x="165" y="0" width="18" height="60" fill="#1a1a1a"/>
<text x="174" y="33" font-size="9" font-weight="800" fill="#fff" text-anchor="middle">6%</text>
<text x="174" y="45" font-size="8" fill="#fff" text-anchor="middle">Kohle</text>
<rect x="183" y="0" width="114" height="60" fill="#5a8a5e"/>
<text x="240" y="28" font-size="12" font-weight="800" fill="#fff" text-anchor="middle">38 %</text>
<text x="240" y="44" font-size="10" fill="#fff" text-anchor="middle">Erneuerbar</text>
<rect x="297" y="0" width="3" height="60" fill="#c4a97a"/>
</g>
<!-- Fossil-Klammer -->
<path d="M 0 105 L 0 112 L 183 112 L 183 105" stroke="#c85c4a" stroke-width="1.5" fill="none"/>
<text x="91.5" y="128" font-size="11" font-weight="800" fill="#c85c4a" text-anchor="middle">fossil 61 %</text>
<path d="M 183 105 L 183 112 L 297 112 L 297 105" stroke="#5a8a5e" stroke-width="1.5" fill="none"/>
<text x="240" y="128" font-size="11" font-weight="800" fill="#5a8a5e" text-anchor="middle">erneuerbar 38 %</text>
<!-- Mini-Vergleich Verkehr -->
<text x="0" y="175" font-size="12" font-weight="800" fill="#1f4e5a">Im Verkehr dominieren Benzin &amp; Diesel:</text>
<g transform="translate(0,185)">
<rect x="0" y="0" width="280" height="14" fill="#6b4a2e"/>
<rect x="280" y="0" width="20" height="14" fill="#5a8a5e"/>
<text x="140" y="10" font-size="9" fill="#fff" font-weight="800" text-anchor="middle">über 93 % fossil</text>
<text x="295" y="28" font-size="9" fill="#5a8a5e" font-weight="700" text-anchor="end">7 % erneuerbar (Strom + Bio)</text>
</g>
</g>
<!-- Footer -->
<g transform="translate(50,420)">
<rect x="0" y="0" width="800" height="50" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="16" font-size="10" font-weight="800" fill="#1f4e5a">Ziel Österreich:</text>
<text x="130" y="16" font-size="10" fill="#4a4a4a">100 % erneuerbarer Strom bis 2030 (EAG) · Klimaneutralität bis 2040.</text>
<text x="12" y="32" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="70" y="32" font-size="10" fill="#4a4a4a">E-Control, Betriebsstatistik Strom 2023 · Statistik Austria, Energiebilanz 2023 · BMK, Energiestatus 2024</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

@@ -1,137 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 420" font-family="Inter, system-ui, sans-serif" width="900" height="420">
<defs>
<pattern id="fb-rock" width="8" height="8" patternUnits="userSpaceOnUse">
<rect width="8" height="8" fill="#6b4a2e"/>
<circle cx="3" cy="3" r=".7" fill="#4a2f1a"/>
<circle cx="6" cy="6" r=".6" fill="#8a6a4a"/>
</pattern>
<linearGradient id="fb-flame" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#f4c94e"/>
<stop offset=".6" stop-color="#e8833a"/>
<stop offset="1" stop-color="#c85c4a"/>
</linearGradient>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Fossile Brennstoffe — 300 Millionen Jahre Speicherung, Sekunden Verbrennung
</text>
<!-- Zeitachse: 300 Mio Jahre als Balken -->
<g transform="translate(50, 90)">
<!-- Balken (Geschichte der Erde) -->
<rect x="0" y="0" width="800" height="42" fill="#4a7c8a" rx="3"/>
<rect x="0" y="0" width="800" height="42" fill="none" stroke="#1f4e5a" stroke-width="1.5" rx="3"/>
<!-- Karbon-Zeitalter (Entstehung der Kohle) -->
<rect x="0" y="0" width="120" height="42" fill="#3a6b3e" rx="3"/>
<text x="60" y="25" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">Karbon</text>
<!-- Dinosaurier -->
<circle cx="260" cy="21" r="3" fill="#fff"/>
<text x="260" y="58" font-size="8" fill="#4a4a4a" text-anchor="middle">Dinosaurier</text>
<text x="260" y="68" font-size="8" fill="#8a8a8a" text-anchor="middle">vor 200 Mio J.</text>
<!-- Säugetiere -->
<circle cx="620" cy="21" r="3" fill="#fff"/>
<text x="620" y="58" font-size="8" fill="#4a4a4a" text-anchor="middle">Säugetiere</text>
<!-- Menschheit (ganz am Ende) -->
<rect x="795" y="-6" width="5" height="54" fill="#c85c4a"/>
<text x="790" y="-10" font-size="10" fill="#c85c4a" font-weight="800" text-anchor="end">Homo sapiens</text>
<text x="790" y="-22" font-size="9" fill="#8a8a8a" text-anchor="end">(letzte 300.000 Jahre)</text>
<!-- Achsen-Labels -->
<text x="0" y="80" font-size="10" fill="#1f4e5a" font-weight="700">vor 350 Mio Jahren</text>
<text x="800" y="80" font-size="10" fill="#1f4e5a" font-weight="700" text-anchor="end">heute</text>
<text x="400" y="-18" font-size="11" fill="#1f4e5a" font-weight="800" text-anchor="middle">Zeitachse: 350 Millionen Jahre</text>
<!-- Pfeil runter zur Entstehung -->
<path d="M 60 42 L 60 105" stroke="#3a6b3e" stroke-width="1.5" marker-end="url(#fb-a-green)" fill="none" stroke-dasharray="3 2"/>
</g>
<!-- Entstehung der Kohle (links) -->
<g transform="translate(110, 240)">
<text y="-10" font-size="12" font-weight="800" fill="#3a6b3e" text-anchor="middle">Über Millionen Jahre:</text>
<!-- Pflanzen -->
<g>
<polygon points="-40,-5 -35,-25 -30,-5" fill="#5a8a5e"/>
<polygon points="-25,-5 -20,-30 -15,-5" fill="#3a6b3e"/>
<polygon points="-10,-5 -5,-28 0,-5" fill="#5a8a5e"/>
<polygon points="5,-5 10,-25 15,-5" fill="#3a6b3e"/>
<polygon points="20,-5 25,-30 30,-5" fill="#5a8a5e"/>
<rect x="-50" y="-5" width="100" height="6" fill="#6b4a2e"/>
</g>
<!-- Pfeil nach unten -->
<path d="M 0 5 L 0 35" stroke="#6b4a2e" stroke-width="2" fill="none"/>
<polygon points="-4,30 4,30 0,40" fill="#6b4a2e"/>
<!-- Schichten (Gestein) -->
<rect x="-60" y="45" width="120" height="10" fill="#e8d5b5"/>
<rect x="-60" y="55" width="120" height="10" fill="#c4a97a"/>
<rect x="-60" y="65" width="120" height="15" fill="url(#fb-rock)"/>
<!-- Kohle-Flöz -->
<rect x="-60" y="80" width="120" height="10" fill="#1a1a1a"/>
<text y="103" font-size="11" fill="#1f4e5a" font-weight="700" text-anchor="middle">Kohle-Flöz</text>
<text y="118" font-size="9" fill="#8a8a8a" text-anchor="middle">(gepresste Urwälder)</text>
</g>
<!-- Pfeil: Entstehung dauert lange -->
<g>
<path d="M 230 280 L 380 280" stroke="#4a7c8a" stroke-width="2" fill="none" stroke-dasharray="6 4"/>
<polygon points="380,280 370,275 370,285" fill="#4a7c8a"/>
<text x="305" y="272" font-size="11" fill="#4a7c8a" font-weight="700" text-anchor="middle">~300.000.000 Jahre</text>
<text x="305" y="295" font-size="9" fill="#8a8a8a" text-anchor="middle">Druck · Wärme · kein Sauerstoff</text>
</g>
<!-- Verbrennung (Mitte-Rechts) -->
<g transform="translate(510, 260)">
<text y="-25" font-size="12" font-weight="800" fill="#c85c4a" text-anchor="middle">Heute in Sekunden:</text>
<!-- Schornstein / Feuerstelle -->
<rect x="-20" y="-5" width="40" height="45" fill="#4a4a4a"/>
<rect x="-25" y="-10" width="50" height="8" fill="#2a2a2a"/>
<!-- Flamme -->
<path d="M -15 -10 Q -20 -35 -10 -55 Q 0 -40 5 -60 Q 15 -35 20 -45 Q 15 -20 -15 -10 Z" fill="url(#fb-flame)"/>
<!-- Rauch: CO₂-Wölkchen -->
<g fill="#c85c4a" opacity=".75">
<circle cx="-5" cy="-75" r="7"/>
<circle cx="8" cy="-82" r="9"/>
<circle cx="20" cy="-75" r="6"/>
<circle cx="12" cy="-95" r="7"/>
</g>
<text x="10" y="-72" font-size="7" font-weight="800" fill="#fff">CO₂</text>
<text y="60" font-size="11" fill="#1f4e5a" font-weight="700" text-anchor="middle">Verbrennung</text>
<text y="76" font-size="9" fill="#8a8a8a" text-anchor="middle">setzt in Sekunden frei,</text>
<text y="89" font-size="9" fill="#8a8a8a" text-anchor="middle">was in Jahrmillionen</text>
<text y="102" font-size="9" fill="#8a8a8a" text-anchor="middle">gebunden wurde.</text>
</g>
<!-- Mahnungs-Pfeil: Ungleichgewicht -->
<g>
<path d="M 600 280 L 760 280" stroke="#c85c4a" stroke-width="3" fill="none" marker-end="url(#fb-red)"/>
</g>
<defs>
<marker id="fb-red" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#c85c4a"/>
</marker>
<marker id="fb-a-green" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="4" markerHeight="4" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#3a6b3e"/>
</marker>
</defs>
<!-- CO₂-Block rechts -->
<g transform="translate(820, 240)">
<circle r="35" fill="#c85c4a"/>
<text y="-3" font-size="18" font-weight="900" fill="#fff" text-anchor="middle">CO₂</text>
<text y="15" font-size="9" fill="#fff" text-anchor="middle">ansteigend</text>
</g>
<!-- Footer Vergleiche -->
<g transform="translate(0, 370)">
<rect x="50" y="0" width="800" height="40" rx="6" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="70" y="16" font-size="10" fill="#1f4e5a" font-weight="800">Zum Einordnen:</text>
<text x="155" y="16" font-size="10" fill="#4a4a4a">1 Liter Benzin = Energie aus ≈ 25 t Urzeit-Pflanzenmaterial · 75 % der weltweiten CO₂-Emissionen aus Fossilen</text>
<text x="70" y="32" font-size="10" fill="#1f4e5a" font-weight="800">In Österreich:</text>
<text x="155" y="32" font-size="10" fill="#4a4a4a">jährlich ca. 8 Mio. Tonnen Erdöl — vor allem für den Verkehr (Diesel, Benzin, Kerosin)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.0 KiB

@@ -1,133 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 500" font-family="Inter, system-ui, sans-serif" width="900" height="500">
<defs>
<marker id="fs-arr-in" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4a7c8a"/>
</marker>
<marker id="fs-arr-out" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#3a6b3e"/>
</marker>
<marker id="fs-arr-light" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#e8833a"/>
</marker>
<linearGradient id="fs-leaf" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#5a8a5e"/>
<stop offset="1" stop-color="#3a6b3e"/>
</linearGradient>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Fotosynthese — wie Pflanzen aus Licht Nahrung machen
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Grundlage aller Nahrungsketten · produziert den Sauerstoff unserer Atmosphäre
</text>
<!-- Sonne oben links -->
<g>
<circle cx="130" cy="130" r="38" fill="#f4c94e"/>
<g stroke="#f4c94e" stroke-width="2">
<line x1="130" y1="75" x2="130" y2="60"/>
<line x1="130" y1="185" x2="130" y2="200"/>
<line x1="75" y1="130" x2="60" y2="130"/>
<line x1="185" y1="130" x2="200" y2="130"/>
<line x1="95" y1="95" x2="82" y2="82"/>
<line x1="165" y1="95" x2="178" y2="82"/>
<line x1="95" y1="165" x2="82" y2="178"/>
<line x1="165" y1="165" x2="178" y2="178"/>
</g>
<text x="130" y="135" font-size="22" text-anchor="middle"></text>
<text x="130" y="220" font-size="12" font-weight="700" fill="#e8833a" text-anchor="middle">Sonnenlicht</text>
</g>
<!-- Lichtstrahl zum Blatt -->
<line x1="165" y1="160" x2="360" y2="260" stroke="#e8833a" stroke-width="2.5" marker-end="url(#fs-arr-light)"/>
<!-- CO₂-Moleküle links unten -->
<g transform="translate(90,340)">
<text x="0" y="-30" font-size="12" font-weight="700" fill="#4a7c8a">CO₂ aus der Luft</text>
<g>
<circle cx="0" cy="0" r="14" fill="#c85c4a"/>
<text x="0" y="4" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">CO₂</text>
</g>
<g transform="translate(40,15)">
<circle cx="0" cy="0" r="14" fill="#c85c4a"/>
<text x="0" y="4" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">CO₂</text>
</g>
<g transform="translate(5,40)">
<circle cx="0" cy="0" r="14" fill="#c85c4a"/>
<text x="0" y="4" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">CO₂</text>
</g>
</g>
<line x1="155" y1="340" x2="330" y2="290" stroke="#4a7c8a" stroke-width="2" marker-end="url(#fs-arr-in)"/>
<!-- H₂O-Moleküle unten -->
<g transform="translate(200,430)">
<text x="0" y="-20" font-size="12" font-weight="700" fill="#4a7c8a">H₂O aus dem Boden</text>
<g>
<circle cx="0" cy="0" r="14" fill="#4a7c8a"/>
<text x="0" y="4" font-size="9" font-weight="800" fill="#fff" text-anchor="middle">H₂O</text>
</g>
<g transform="translate(35,10)">
<circle cx="0" cy="0" r="14" fill="#4a7c8a"/>
<text x="0" y="4" font-size="9" font-weight="800" fill="#fff" text-anchor="middle">H₂O</text>
</g>
</g>
<line x1="250" y1="410" x2="390" y2="330" stroke="#4a7c8a" stroke-width="2" marker-end="url(#fs-arr-in)"/>
<!-- ZENTRUM: Blatt/Pflanze -->
<g transform="translate(450,280)">
<!-- Blattform -->
<path d="M 0 -80 Q 80 -70 90 0 Q 80 70 0 80 Q -80 70 -90 0 Q -80 -70 0 -80 Z" fill="url(#fs-leaf)"/>
<!-- Blattader -->
<line x1="0" y1="-80" x2="0" y2="80" stroke="#1f4e5a" stroke-width="1.5" opacity=".5"/>
<g stroke="#1f4e5a" stroke-width=".8" opacity=".4">
<path d="M 0 -60 Q 30 -55 50 -30" fill="none"/>
<path d="M 0 -30 Q 40 -25 60 0" fill="none"/>
<path d="M 0 0 Q 40 5 60 30" fill="none"/>
<path d="M 0 30 Q 30 35 50 55" fill="none"/>
<path d="M 0 -60 Q -30 -55 -50 -30" fill="none"/>
<path d="M 0 -30 Q -40 -25 -60 0" fill="none"/>
<path d="M 0 0 Q -40 5 -60 30" fill="none"/>
<path d="M 0 30 Q -30 35 -50 55" fill="none"/>
</g>
<text y="5" font-size="16" font-weight="900" fill="#fff" text-anchor="middle">Chloroplast</text>
</g>
<!-- Reaktionsformel darunter -->
<g transform="translate(450,410)">
<rect x="-220" y="-20" width="440" height="44" rx="6" fill="#fff" stroke="#dae8ec"/>
<text y="3" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">6 CO₂ + 6 H₂O + Licht → C₆H₁₂O₆ + 6 O₂</text>
<text y="18" font-size="10" fill="#8a8a8a" text-anchor="middle">Kohlenstoffdioxid + Wasser + Sonnenenergie werden zu Zucker (Glukose) + Sauerstoff</text>
</g>
<!-- O₂ rechts oben raus -->
<line x1="540" y1="240" x2="760" y2="170" stroke="#3a6b3e" stroke-width="2.5" marker-end="url(#fs-arr-out)"/>
<g transform="translate(780,160)">
<text x="0" y="-20" font-size="12" font-weight="700" fill="#3a6b3e" text-anchor="middle">Sauerstoff O₂</text>
<g>
<circle cx="-25" cy="0" r="14" fill="#5a8a5e"/>
<text x="-25" y="4" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">O₂</text>
</g>
<g>
<circle cx="15" cy="10" r="14" fill="#5a8a5e"/>
<text x="15" y="14" font-size="10" font-weight="800" fill="#fff" text-anchor="middle">O₂</text>
</g>
</g>
<!-- Glukose als Zucker-Icon rechts mitte -->
<line x1="540" y1="310" x2="760" y2="360" stroke="#e8833a" stroke-width="2.5" marker-end="url(#fs-arr-out)"/>
<g transform="translate(800,370)">
<text x="0" y="-20" font-size="12" font-weight="700" fill="#c4a97a" text-anchor="middle">Zucker</text>
<rect x="-30" y="-10" width="60" height="30" rx="4" fill="#e8d5b5" stroke="#c4a97a"/>
<text x="0" y="10" font-size="11" font-weight="800" fill="#8a6a2a" text-anchor="middle">C₆H₁₂O₆</text>
</g>
<!-- Footer Fakten -->
<g transform="translate(50,450)">
<rect x="0" y="0" width="800" height="40" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="16" font-size="10" font-weight="800" fill="#1f4e5a">Pro Jahr weltweit:</text>
<text x="130" y="16" font-size="10" fill="#4a4a4a">Landpflanzen binden ≈ 120 Gt Kohlenstoff · Phytoplankton im Meer liefert rund die Hälfte des Luft-Sauerstoffs.</text>
<text x="12" y="32" font-size="10" font-weight="800" fill="#1f4e5a">Quelle:</text>
<text x="65" y="32" font-size="10" fill="#4a4a4a">IPCC AR6 WG1, Kap. 5 · Campbell / Reece, Biology 11e · Friedlingstein et al. 2023 (Global Carbon Budget)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

-125
View File
@@ -1,125 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 480" font-family="Inter, system-ui, sans-serif" width="900" height="480">
<text x="450" y="28" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Kipppunkt — wenn eine Veränderung nicht mehr umzudrehen ist
</text>
<text x="450" y="46" font-size="11" fill="#8a8a8a" text-anchor="middle">
Didaktische Metapher + 8 der 16 bekannten Kippelemente im Klimasystem
</text>
<!-- LINKS: Tisch-Metapher in drei Phasen -->
<g transform="translate(30,90)">
<text x="180" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">So funktioniert ein Kipppunkt</text>
<!-- Phase 1 -->
<g transform="translate(0,20)">
<rect x="0" y="80" width="100" height="6" fill="#8a8a8a"/>
<rect x="5" y="86" width="4" height="30" fill="#8a8a8a"/>
<rect x="91" y="86" width="4" height="30" fill="#8a8a8a"/>
<circle cx="30" cy="72" r="10" fill="#5a8a5e"/>
<text x="50" y="135" font-size="10" font-weight="700" fill="#3a6b3e" text-anchor="middle">1. Stabil</text>
<text x="50" y="148" font-size="9" fill="#8a8a8a" text-anchor="middle">kleine Störungen</text>
<text x="50" y="159" font-size="9" fill="#8a8a8a" text-anchor="middle">schieben zurück</text>
</g>
<!-- Phase 2 -->
<g transform="translate(120,20)">
<rect x="0" y="80" width="100" height="6" fill="#8a8a8a"/>
<rect x="5" y="86" width="4" height="30" fill="#8a8a8a"/>
<rect x="91" y="86" width="4" height="30" fill="#8a8a8a"/>
<circle cx="88" cy="72" r="10" fill="#e8833a"/>
<text x="88" y="55" font-size="14" font-weight="900" fill="#e8833a" text-anchor="middle"></text>
<text x="50" y="135" font-size="10" font-weight="700" fill="#e8833a" text-anchor="middle">2. Am Rand</text>
<text x="50" y="148" font-size="9" fill="#8a8a8a" text-anchor="middle">kritische Schwelle</text>
<text x="50" y="159" font-size="9" fill="#8a8a8a" text-anchor="middle">fast erreicht</text>
</g>
<!-- Phase 3 -->
<g transform="translate(240,20)">
<rect x="0" y="80" width="100" height="6" fill="#8a8a8a"/>
<rect x="5" y="86" width="4" height="30" fill="#8a8a8a"/>
<rect x="91" y="86" width="4" height="30" fill="#8a8a8a"/>
<circle cx="115" cy="130" r="10" fill="#c85c4a"/>
<!-- Fallbahn -->
<path d="M 95 75 Q 110 105 115 120" stroke="#c85c4a" stroke-width="1.2" fill="none" stroke-dasharray="3 2"/>
<text x="50" y="135" font-size="10" font-weight="700" fill="#c85c4a" text-anchor="middle">3. Gekippt</text>
<text x="50" y="148" font-size="9" fill="#8a8a8a" text-anchor="middle">unumkehrbar —</text>
<text x="50" y="159" font-size="9" fill="#8a8a8a" text-anchor="middle">neuer Zustand</text>
</g>
<!-- Erklärung unten -->
<g transform="translate(0,200)">
<rect x="0" y="0" width="360" height="62" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="17" font-size="10" font-weight="800" fill="#1f4e5a">Übertragen aufs Klimasystem:</text>
<text x="10" y="32" font-size="10" fill="#4a4a4a">Steigt die globale Temperatur über eine kritische</text>
<text x="10" y="44" font-size="10" fill="#4a4a4a">Schwelle, verändert sich ein Teil der Erde</text>
<text x="10" y="56" font-size="10" fill="#4a4a4a">selbstverstärkend — auch ohne weitere Erwärmung.</text>
</g>
</g>
<!-- RECHTS: Kippelemente-Liste auf stilisierter Welt -->
<g transform="translate(430,80)">
<text x="220" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">16 Kippelemente — ab welcher Erwärmung kritisch</text>
<!-- Vereinfachte Weltkarte als farbiger Hintergrund (Ellipsen statt Kontinente) -->
<g transform="translate(0,20)">
<rect x="0" y="0" width="440" height="180" rx="6" fill="#eff5f6"/>
<!-- Grönland -->
<ellipse cx="205" cy="40" rx="18" ry="22" fill="#dae8ec" stroke="#4a7c8a" stroke-width=".5"/>
<circle cx="205" cy="40" r="6" fill="#c85c4a"/>
<text x="205" y="22" font-size="9" font-weight="700" fill="#c85c4a" text-anchor="middle">Grönland-Eisschild</text>
<text x="205" y="78" font-size="9" fill="#c85c4a" text-anchor="middle">ab 1,5 °C</text>
<!-- West-Antarktis -->
<ellipse cx="220" cy="160" rx="42" ry="12" fill="#dae8ec" stroke="#4a7c8a" stroke-width=".5"/>
<circle cx="200" cy="160" r="5" fill="#c85c4a"/>
<text x="220" y="176" font-size="9" font-weight="700" fill="#c85c4a" text-anchor="middle">West-Antarktis · ab 1,5 °C</text>
<!-- AMOC Nordatlantik -->
<circle cx="170" cy="60" r="5" fill="#e8833a"/>
<text x="110" y="58" font-size="9" font-weight="700" fill="#e8833a" text-anchor="middle">AMOC-Umwälzung</text>
<text x="110" y="69" font-size="9" fill="#e8833a" text-anchor="middle">1,4 8 °C</text>
<!-- Permafrost Sibirien -->
<circle cx="310" cy="50" r="5" fill="#e8833a"/>
<text x="360" y="48" font-size="9" font-weight="700" fill="#e8833a" text-anchor="middle">Permafrost</text>
<text x="360" y="59" font-size="9" fill="#e8833a" text-anchor="middle">1,0 2,3 °C</text>
<!-- Amazonas -->
<circle cx="160" cy="110" r="5" fill="#c85c4a"/>
<text x="100" y="108" font-size="9" font-weight="700" fill="#c85c4a" text-anchor="middle">Amazonas-Regenwald</text>
<text x="100" y="119" font-size="9" fill="#c85c4a" text-anchor="middle">3,5 °C</text>
<!-- Korallenriffe trop. -->
<circle cx="330" cy="105" r="5" fill="#c85c4a"/>
<text x="385" y="103" font-size="9" font-weight="700" fill="#c85c4a" text-anchor="middle">Korallenriffe</text>
<text x="385" y="114" font-size="9" fill="#c85c4a" text-anchor="middle">1,0 1,5 °C</text>
<!-- Boreale Wälder -->
<circle cx="290" cy="75" r="5" fill="#e8833a"/>
<text x="345" y="75" font-size="9" font-weight="700" fill="#e8833a" text-anchor="middle">Boreale Wälder</text>
<text x="345" y="86" font-size="9" fill="#e8833a" text-anchor="middle">1,5 5 °C</text>
<!-- Westafrik. Monsun -->
<circle cx="225" cy="120" r="5" fill="#e8833a"/>
<text x="220" y="140" font-size="9" font-weight="700" fill="#e8833a" text-anchor="middle">Sahel-Monsun</text>
<text x="220" y="151" font-size="9" fill="#e8833a" text-anchor="middle">2,0 3,5 °C</text>
</g>
<!-- Legende -->
<g transform="translate(0,215)">
<circle cx="10" cy="6" r="5" fill="#c85c4a"/>
<text x="22" y="10" font-size="10" fill="#1f4e5a" font-weight="700">Schwelle liegt nahe am heutigen Erwärmungsniveau (+ 1,2 °C)</text>
<circle cx="10" cy="25" r="5" fill="#e8833a"/>
<text x="22" y="29" font-size="10" fill="#1f4e5a" font-weight="700">Schwelle bei stärkerer Erwärmung erreichbar</text>
</g>
</g>
<!-- Footer -->
<g transform="translate(50,430)">
<rect x="0" y="0" width="800" height="40" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="16" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="70" y="16" font-size="10" fill="#4a4a4a">Armstrong McKay, D. et al. (2022): Exceeding 1.5 °C global warming could trigger multiple climate tipping points. Science 377, eabn7950.</text>
<text x="70" y="32" font-size="10" fill="#4a4a4a">IPCC AR6 WG1 (2021), Kap. 9 · PIK Potsdam-Institut für Klimafolgenforschung.</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

@@ -1,64 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 480" font-family="Inter, system-ui, sans-serif" width="900" height="480">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Erderwärmung — Österreich steigt rund 2,6-mal schneller als der globale Mittelwert
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Temperaturabweichung vom Mittel 19611990 · Datenstand 2023
</text>
<!-- Plot: x 80..870, y 90..390. X: 1900..2024 = 124 a in 790 px → 6,37 px/a -->
<line x1="80" y1="390" x2="870" y2="390" stroke="#1f4e5a" stroke-width="1.5"/>
<line x1="80" y1="90" x2="80" y2="390" stroke="#1f4e5a" stroke-width="1.5"/>
<!-- 0°C Bezugslinie (mitte y=290) -->
<!-- Y-Range: -0,5 bis +3,5 = 4°C auf 300 px → 75 px/°C. y(T)=290 - T*75 -->
<line x1="80" y1="290" x2="870" y2="290" stroke="#1f4e5a" stroke-width="1" stroke-dasharray="3 2"/>
<text x="875" y="293" font-size="10" fill="#1f4e5a" font-weight="700">0 °C (Referenz)</text>
<g font-size="10" fill="#4a4a4a" text-anchor="end">
<line x1="80" y1="365" x2="870" y2="365" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="368">0,5</text>
<line x1="80" y1="215" x2="870" y2="215" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="218">+1,0</text>
<line x1="80" y1="140" x2="870" y2="140" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="143">+2,0</text>
<line x1="80" y1="90" x2="870" y2="90" stroke="#dae8ec" stroke-width=".5"/><text x="74" y="93">+2,7</text>
</g>
<text x="22" y="240" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle" transform="rotate(-90 22 240)">Temperaturabweichung (°C)</text>
<!-- X-Achse 1900..2020 Grid -->
<g font-size="10" fill="#4a4a4a" text-anchor="middle">
<line x1="80" y1="390" x2="80" y2="395" stroke="#1f4e5a"/><text x="80" y="410">1900</text>
<line x1="207.4" y1="390" x2="207.4" y2="395" stroke="#1f4e5a"/><text x="207.4" y="410">1920</text>
<line x1="334.8" y1="390" x2="334.8" y2="395" stroke="#1f4e5a"/><text x="334.8" y="410">1940</text>
<line x1="462.2" y1="390" x2="462.2" y2="395" stroke="#1f4e5a"/><text x="462.2" y="410">1960</text>
<line x1="589.6" y1="390" x2="589.6" y2="395" stroke="#1f4e5a"/><text x="589.6" y="410">1980</text>
<line x1="717" y1="390" x2="717" y2="395" stroke="#1f4e5a"/><text x="717" y="410">2000</text>
<line x1="844.4" y1="390" x2="844.4" y2="395" stroke="#1f4e5a"/><text x="844.4" y="410">2020</text>
</g>
<!-- Globale Kurve (HadCRUT5-artig, vereinfacht): y = 290 - T*75 -->
<!-- Stützstellen (Jahr/Anomalie °C): 1900:-0.2, 1920:-0.25, 1940:-0.1, 1960:-0.05, 1980:0.15, 2000:0.4, 2020:1.02, 2023:1.17 -->
<polyline fill="none" stroke="#4a7c8a" stroke-width="2.2" stroke-linejoin="round"
points="80,305 207.4,308.75 334.8,297.5 462.2,293.75 589.6,278.75 717,260 844.4,213.5 864,202.25"/>
<text x="870" y="199" font-size="11" font-weight="800" fill="#4a7c8a">Welt</text>
<text x="870" y="212" font-size="10" fill="#4a7c8a">+1,2 °C (2023)</text>
<!-- AT Kurve (GeoSphere-artig, Jahr/°C): 1900:-0.5, 1920:-0.2, 1940:0.25, 1960:-0.05, 1980:0.25, 2000:1.3, 2020:2.4, 2023:2.6 -->
<polyline fill="none" stroke="#c85c4a" stroke-width="2.5" stroke-linejoin="round"
points="80,327.5 207.4,305 334.8,271.25 462.2,293.75 589.6,271.25 717,192.5 844.4,110 864,95"/>
<text x="870" y="92" font-size="11" font-weight="800" fill="#c85c4a">Österreich</text>
<text x="870" y="105" font-size="10" fill="#c85c4a">+3,1 °C (2023)</text>
<!-- Pariser Zielzonen -->
<rect x="80" y="178.75" width="790" height="6" fill="#e8833a" opacity=".35"/>
<text x="86" y="176" font-size="9" fill="#e8833a" font-weight="700">Pariser Ziel: unter +1,5 °C</text>
<rect x="80" y="140" width="790" height="6" fill="#c85c4a" opacity=".25"/>
<text x="86" y="137" font-size="9" fill="#c85c4a" font-weight="700">Pariser Schwelle: unter +2,0 °C</text>
<!-- Fußzeile -->
<g transform="translate(50,435)">
<rect x="0" y="0" width="800" height="35" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="15" font-size="10" fill="#1f4e5a" font-weight="700">Lesehilfe:</text>
<text x="70" y="15" font-size="10" fill="#4a4a4a">Die Kurve zeigt, wie stark die Jahresdurchschnitts-Temperatur gegenüber dem Mittel 19611990 gestiegen ist.</text>
<text x="12" y="30" font-size="10" fill="#1f4e5a" font-weight="700">Quellen:</text>
<text x="70" y="30" font-size="10" fill="#4a4a4a">Met Office HadCRUT5 (global) · GeoSphere Austria, Klimastatusbericht 2023 (Österreich)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

@@ -1,76 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 540" font-family="Inter, system-ui, sans-serif" width="900" height="540">
<defs>
<marker id="kk-arr-nat" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#3a6b3e"/>
</marker>
<marker id="kk-arr-h" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#c85c4a"/>
</marker>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Der Kohlenstoffkreislauf — so wandert Kohlenstoff zwischen Erde, Luft und Meer
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Reservoire in Gigatonnen Kohlenstoff (Gt C) · Flüsse als Pfeile · Stand 2022
</text>
<!-- Reservoire: Atmosphäre oben, Landpflanzen/Böden Mitte, Ozeane rechts unten, Fossile links unten -->
<!-- Atmosphäre (oben) -->
<rect x="300" y="80" width="300" height="70" rx="8" fill="#4a7c8a"/>
<text x="450" y="110" font-size="15" font-weight="900" fill="#fff" text-anchor="middle">Atmosphäre</text>
<text x="450" y="130" font-size="14" font-weight="700" fill="#fff" text-anchor="middle">≈ 875 Gt C (als CO₂)</text>
<!-- Landpflanzen & Böden (Mitte links) -->
<rect x="80" y="250" width="270" height="80" rx="8" fill="#5a8a5e"/>
<text x="215" y="278" font-size="14" font-weight="900" fill="#fff" text-anchor="middle">Landpflanzen + Böden</text>
<text x="215" y="296" font-size="12" fill="#dcead0" text-anchor="middle">Wälder, Wiesen, Moore</text>
<text x="215" y="316" font-size="14" font-weight="700" fill="#fff" text-anchor="middle">≈ 2.300 Gt C</text>
<!-- Ozeane (Mitte rechts) -->
<rect x="550" y="250" width="270" height="80" rx="8" fill="#1f4e5a"/>
<text x="685" y="278" font-size="14" font-weight="900" fill="#fff" text-anchor="middle">Ozeane</text>
<text x="685" y="296" font-size="12" fill="#dae8ec" text-anchor="middle">größtes aktives Reservoir</text>
<text x="685" y="316" font-size="14" font-weight="700" fill="#fff" text-anchor="middle">≈ 38.000 Gt C</text>
<!-- Fossile Lagerstätten (unten) -->
<rect x="300" y="410" width="300" height="70" rx="8" fill="#6b4a2e"/>
<text x="450" y="438" font-size="14" font-weight="900" fill="#fff" text-anchor="middle">Fossile Lagerstätten</text>
<text x="450" y="458" font-size="12" fill="#e8d5b5" text-anchor="middle">Kohle, Erdöl, Erdgas — rund 4.000 Gt C</text>
<!-- Natürliche Flüsse (grün) -->
<!-- Fotosynthese: Atmosphäre → Landpflanzen -->
<path d="M 370 150 Q 300 195 240 250" stroke="#3a6b3e" stroke-width="2" fill="none" marker-end="url(#kk-arr-nat)"/>
<text x="245" y="195" font-size="10" font-weight="700" fill="#3a6b3e" text-anchor="middle">Fotosynthese</text>
<text x="245" y="207" font-size="9" fill="#3a6b3e" text-anchor="middle">≈ 120 Gt C/Jahr</text>
<!-- Atmung & Verwesung: Landpflanzen → Atmosphäre -->
<path d="M 310 250 Q 330 195 410 150" stroke="#3a6b3e" stroke-width="2" fill="none" marker-end="url(#kk-arr-nat)"/>
<text x="400" y="195" font-size="10" font-weight="700" fill="#3a6b3e" text-anchor="middle">Atmung + Verwesung</text>
<text x="400" y="207" font-size="9" fill="#3a6b3e" text-anchor="middle">≈ 118 Gt C/Jahr</text>
<!-- Ozean ↔ Atmosphäre (bidirektional) -->
<path d="M 540 150 Q 600 195 645 250" stroke="#3a6b3e" stroke-width="2" fill="none" marker-end="url(#kk-arr-nat)"/>
<path d="M 685 250 Q 650 195 570 150" stroke="#3a6b3e" stroke-width="2" fill="none" marker-end="url(#kk-arr-nat)"/>
<text x="680" y="195" font-size="10" font-weight="700" fill="#3a6b3e" text-anchor="middle">CO₂-Austausch Meer</text>
<text x="680" y="207" font-size="9" fill="#3a6b3e" text-anchor="middle">je ca. 80 Gt C/Jahr</text>
<!-- Menschlicher Fluss (rot): Fossile → Atmosphäre -->
<path d="M 440 410 Q 420 280 430 150" stroke="#c85c4a" stroke-width="3" fill="none" marker-end="url(#kk-arr-h)"/>
<rect x="110" y="365" width="230" height="30" rx="4" fill="#f0d0ca"/>
<text x="225" y="384" font-size="10" font-weight="800" fill="#c85c4a" text-anchor="middle">Verbrennung fossiler Energie + Landnutzung</text>
<!-- Pfeil zu Beschriftung -->
<line x1="340" y1="380" x2="420" y2="380" stroke="#c85c4a" stroke-width="1.2" stroke-dasharray="3 2"/>
<text x="465" y="285" font-size="11" font-weight="800" fill="#c85c4a" text-anchor="middle">+ 10,9 Gt C/Jahr</text>
<text x="465" y="298" font-size="10" fill="#c85c4a" text-anchor="middle">= 40,6 Gt CO₂</text>
<!-- Natürliche Senken nehmen rund die Hälfte auf -->
<g transform="translate(80,495)">
<rect x="0" y="0" width="760" height="35" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="15" font-size="10" font-weight="800" fill="#1f4e5a">So reagiert der Kreislauf:</text>
<text x="155" y="15" font-size="10" fill="#4a4a4a">Landpflanzen + Ozeane nehmen ca. 55 % der menschgemachten Emissionen auf; der Rest bleibt in der Luft.</text>
<text x="12" y="30" font-size="10" font-weight="800" fill="#1f4e5a">Quelle:</text>
<text x="65" y="30" font-size="10" fill="#4a4a4a">Friedlingstein et al. (2023), Global Carbon Budget 2023 · IPCC AR6 WG1, Kapitel 5</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.2 KiB

-93
View File
@@ -1,93 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 460" font-family="Inter, system-ui, sans-serif" width="900" height="460">
<defs>
<linearGradient id="kw-kwh" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#f4c94e"/>
<stop offset="1" stop-color="#e8833a"/>
</linearGradient>
</defs>
<text x="450" y="32" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
1 Kilowattstunde (kWh) — was kannst du damit machen?
</text>
<text x="450" y="52" font-size="11" fill="#8a8a8a" text-anchor="middle">
Eine kWh kostet in Österreich rund 25 Cent. Alle Zahlen gerundet.
</text>
<!-- Zentrale "1 kWh" Scheibe -->
<g transform="translate(450, 225)">
<circle r="62" fill="url(#kw-kwh)"/>
<circle r="62" fill="none" stroke="#1f4e5a" stroke-width="2.5"/>
<text y="-4" font-size="28" font-weight="900" fill="#1f4e5a" text-anchor="middle">1</text>
<text y="22" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">kWh</text>
</g>
<!-- 6 Vergleiche um das Zentrum -->
<!-- Positionen (x, y) für die Karten -->
<!-- Oben links: Wäsche -->
<g transform="translate(160, 110)">
<rect x="-90" y="-45" width="180" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle">🧺</text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">1 Maschine Wäsche</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">waschen (60 °C)</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">≈ 1 kWh</text>
</g>
<!-- Oben rechts: Fernsehen -->
<g transform="translate(740, 110)">
<rect x="-90" y="-45" width="180" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle">📺</text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">7 Stunden TV</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">moderner 55"-Fernseher</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">140 W × 7 h</text>
</g>
<!-- Mitte links: E-Auto -->
<g transform="translate(130, 225)">
<rect x="-85" y="-45" width="170" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle">🚗</text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">7 km E-Auto</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">Wien → Grinzing</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">15 kWh / 100 km</text>
</g>
<!-- Mitte rechts: Smartphone -->
<g transform="translate(770, 225)">
<rect x="-85" y="-45" width="170" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle">📱</text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">65 × Smartphone</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">voll aufladen</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">15 Wh pro Ladung</text>
</g>
<!-- Unten links: Kochen -->
<g transform="translate(160, 340)">
<rect x="-90" y="-45" width="180" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle">🍝</text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">30 min Herdplatte</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">Nudeln kochen</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">2.000 W × 0,5 h</text>
</g>
<!-- Unten rechts: Kaffee -->
<g transform="translate(740, 340)">
<rect x="-90" y="-45" width="180" height="90" rx="10" fill="#fff" stroke="#dae8ec" stroke-width="1.5"/>
<text y="-22" font-size="28" text-anchor="middle"></text>
<text y="3" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">90 Tassen Kaffee</text>
<text y="22" font-size="10" fill="#8a8a8a" text-anchor="middle">aus der Siebträgermaschine</text>
<text y="36" font-size="9" fill="#5a8a5e" text-anchor="middle" font-weight="600">11 Wh pro Tasse</text>
</g>
<!-- Linien vom Zentrum zu den Karten -->
<g stroke="#4a7c8a" stroke-width="1" stroke-dasharray="3 3" opacity=".5">
<line x1="400" y1="210" x2="260" y2="130"/>
<line x1="500" y1="210" x2="640" y2="130"/>
<line x1="388" y1="225" x2="215" y2="225"/>
<line x1="512" y1="225" x2="685" y2="225"/>
<line x1="400" y1="240" x2="260" y2="320"/>
<line x1="500" y1="240" x2="640" y2="320"/>
</g>
<!-- Footer-Vergleich -->
<g transform="translate(0, 410)">
<rect x="50" y="0" width="800" height="40" rx="6" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="70" y="16" font-size="10" fill="#1f4e5a" font-weight="800">Jahresverbrauch:</text>
<text x="180" y="16" font-size="10" fill="#4a4a4a">Einfamilienhaus ≈ 4.000 kWh · Tesla Model 3 Akku = 75 kWh · Österreich gesamt ≈ 70.000.000.000 kWh</text>
<text x="70" y="32" font-size="10" fill="#1f4e5a" font-weight="800">Solardach:</text>
<text x="180" y="32" font-size="10" fill="#4a4a4a">1 m² Photovoltaik liefert in Österreich ca. 150180 kWh pro Jahr — 30 m² decken einen Haushalt.</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

@@ -1,47 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 420" font-family="Inter, system-ui, sans-serif" width="900" height="420">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Methan — kurzlebig, aber in der Wirkung viel stärker als CO₂
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Treibhauspotenzial GWP 20 und GWP 100 nach IPCC AR6 (2021) · 1 kg des Gases im Vergleich
</text>
<!-- Drei Balken: 1 kg CO₂ (1), 1 kg CH4 GWP-100 (28), 1 kg CH4 GWP-20 (82) -->
<!-- Skala: 82 ≙ max 600 px. 1 Einheit = 7,32 px -->
<g font-size="12">
<!-- CO₂ -->
<g transform="translate(100,110)">
<text x="0" y="-8" font-weight="800" fill="#1f4e5a">1 kg CO₂</text>
<text x="600" y="-8" font-size="11" fill="#8a8a8a" text-anchor="end">Referenz: 1 × CO₂eq</text>
<rect x="0" y="0" width="7.32" height="38" fill="#4a7c8a"/>
<text x="15" y="25" font-size="14" font-weight="800" fill="#1f4e5a">= 1 kg CO₂eq</text>
</g>
<!-- Methan GWP-100 -->
<g transform="translate(100,180)">
<text x="0" y="-8" font-weight="800" fill="#c85c4a">1 kg Methan (CH₄) — auf 100 Jahre</text>
<text x="600" y="-8" font-size="11" fill="#8a8a8a" text-anchor="end">GWP-100 = 28</text>
<rect x="0" y="0" width="205" height="38" fill="#c85c4a"/>
<text x="215" y="25" font-size="14" font-weight="800" fill="#c85c4a">= 28 kg CO₂eq</text>
</g>
<!-- Methan GWP-20 -->
<g transform="translate(100,250)">
<text x="0" y="-8" font-weight="800" fill="#e8833a">1 kg Methan (CH₄) — auf 20 Jahre</text>
<text x="600" y="-8" font-size="11" fill="#8a8a8a" text-anchor="end">GWP-20 = 82</text>
<rect x="0" y="0" width="600" height="38" fill="#e8833a"/>
<text x="300" y="25" font-size="14" font-weight="800" fill="#fff" text-anchor="middle">= 82 kg CO₂eq</text>
</g>
</g>
<!-- Hinweis -->
<g transform="translate(100,310)">
<rect x="0" y="0" width="700" height="42" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="17" font-size="10.5" font-weight="800" fill="#1f4e5a">Warum zwei Zahlen?</text>
<text x="12" y="34" font-size="10.5" fill="#4a4a4a">Methan zerfällt in der Luft im Mittel nach 12 Jahren. Kurzfristig (20 Jahre) wirkt es deshalb viel stärker als langfristig (100 Jahre).</text>
</g>
<!-- Fußzeile Quellen -->
<g transform="translate(100,370)">
<text x="0" y="0" font-size="10" font-weight="800" fill="#1f4e5a">Quelle:</text>
<text x="50" y="0" font-size="10" fill="#4a4a4a">IPCC AR6 WG1 (2021), Tabelle 7.15 · NOAA Methan-Konzentration 2023: 1.929 ppb</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

-107
View File
@@ -1,107 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 460" font-family="Inter, system-ui, sans-serif" width="900" height="460">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Permafrost — 14 Millionen km² auf der Nordhalbkugel
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Nördliche Halbkugel + Bodenquerschnitt · Datengrundlage IPA Permafrost Map 2020
</text>
<!-- LINKS: Polansicht Nordhalbkugel -->
<g transform="translate(60,80)">
<text x="170" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">Verbreitung Nordhalbkugel</text>
<!-- Polar-Projektion als Kreis -->
<circle cx="170" cy="170" r="150" fill="#eff5f6" stroke="#4a7c8a" stroke-width="1.5"/>
<!-- Permafrost-Zonen (schematisch): kontinuierlich innen, diskontinuierlich außen -->
<!-- Kontinuierlicher Permafrost (innen) -->
<circle cx="170" cy="170" r="80" fill="#c85c4a" fill-opacity=".55"/>
<!-- Diskontinuierlich -->
<path d="M 170 170 m -115 0 a 115 115 0 1 0 230 0 a 115 115 0 1 0 -230 0 Z M 170 170 m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0 Z"
fill="#e8833a" fill-opacity=".5" fill-rule="evenodd"/>
<!-- Sporadisch außen -->
<path d="M 170 170 m -145 0 a 145 145 0 1 0 290 0 a 145 145 0 1 0 -290 0 Z M 170 170 m -115 0 a 115 115 0 1 1 230 0 a 115 115 0 1 1 -230 0 Z"
fill="#c4a97a" fill-opacity=".4" fill-rule="evenodd"/>
<!-- Pol-Stern -->
<text x="170" y="175" font-size="14" font-weight="900" fill="#1f4e5a" text-anchor="middle"></text>
<text x="170" y="188" font-size="8" fill="#1f4e5a" text-anchor="middle">Nordpol</text>
<!-- Grobe Kontinentumrisse -->
<g fill="none" stroke="#3a6b3e" stroke-width="1.5">
<!-- Grönland -->
<path d="M 140 85 Q 160 75 175 90 Q 172 110 155 115 Q 140 105 140 85 Z"/>
<!-- Sibirien (Ost) -->
<path d="M 230 130 Q 280 115 300 150 Q 310 180 290 195 Q 250 185 230 170 Z"/>
<!-- Nord-Amerika/Kanada/Alaska -->
<path d="M 60 160 Q 80 130 130 140 Q 140 170 110 190 Q 80 190 60 160 Z"/>
<!-- Europa klein -->
<path d="M 175 220 Q 200 215 210 240 Q 195 250 175 245 Z"/>
</g>
<!-- Alpen-Markierung -->
<circle cx="185" cy="236" r="3" fill="#1f4e5a"/>
<line x1="185" y1="236" x2="240" y2="270" stroke="#1f4e5a" stroke-width=".8"/>
<text x="245" y="274" font-size="9" font-weight="700" fill="#1f4e5a">Alpen (ab ~2.500 m)</text>
<!-- Legende -->
<g transform="translate(0,340)">
<g><rect width="12" height="12" fill="#c85c4a" fill-opacity=".55"/><text x="18" y="10" font-size="10" fill="#1f4e5a">kontinuierlich</text></g>
<g transform="translate(105,0)"><rect width="12" height="12" fill="#e8833a" fill-opacity=".5"/><text x="18" y="10" font-size="10" fill="#1f4e5a">diskontinuierlich</text></g>
<g transform="translate(225,0)"><rect width="12" height="12" fill="#c4a97a" fill-opacity=".4"/><text x="18" y="10" font-size="10" fill="#1f4e5a">sporadisch</text></g>
</g>
</g>
<!-- RECHTS: Bodenquerschnitt -->
<g transform="translate(500,80)">
<text x="170" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">Bodenquerschnitt</text>
<!-- Luft oben -->
<rect x="0" y="15" width="340" height="30" fill="#eff5f6"/>
<text x="10" y="35" font-size="10" fill="#8a8a8a">Luft</text>
<!-- Aktive Schicht (taut im Sommer) -->
<rect x="0" y="45" width="340" height="30" fill="#c4a97a"/>
<text x="170" y="65" font-size="10" font-weight="700" fill="#fff" text-anchor="middle">aktive Schicht (30150 cm)</text>
<text x="345" y="61" font-size="9" fill="#8a6a2a">taut im Sommer</text>
<!-- Permafrost -->
<rect x="0" y="75" width="340" height="200" fill="#4a7c8a"/>
<!-- Eis-Einschlüsse -->
<g fill="#dae8ec" opacity=".7">
<circle cx="50" cy="120" r="5"/>
<circle cx="120" cy="150" r="6"/>
<circle cx="220" cy="130" r="4"/>
<circle cx="280" cy="170" r="7"/>
<circle cx="80" cy="200" r="5"/>
<circle cx="180" cy="220" r="6"/>
<circle cx="300" cy="250" r="5"/>
<circle cx="140" cy="260" r="4"/>
</g>
<text x="170" y="180" font-size="13" font-weight="900" fill="#fff" text-anchor="middle">Permafrost</text>
<text x="170" y="198" font-size="10" fill="#dae8ec" text-anchor="middle">dauerhaft ≤ 0 °C</text>
<text x="170" y="215" font-size="10" fill="#dae8ec" text-anchor="middle">stellenweise bis 1.500 m tief</text>
<!-- Organische Substanz markiert -->
<g>
<path d="M 15 100 L 20 95 L 25 100 L 30 95" stroke="#c85c4a" stroke-width="1.5" fill="none" opacity=".7"/>
<path d="M 100 175 L 105 170 L 110 175 L 115 170" stroke="#c85c4a" stroke-width="1.5" fill="none" opacity=".7"/>
<path d="M 230 225 L 235 220 L 240 225 L 245 220" stroke="#c85c4a" stroke-width="1.5" fill="none" opacity=".7"/>
</g>
<text x="345" y="180" font-size="9" fill="#c85c4a" font-weight="700">organische</text>
<text x="345" y="192" font-size="9" fill="#c85c4a" font-weight="700">Reste · ≈ 1.500 Gt</text>
<text x="345" y="204" font-size="9" fill="#c85c4a">Kohlenstoff</text>
<!-- Klammer rechts -->
<path d="M 340 75 L 345 75 L 345 275 L 340 275" fill="none" stroke="#c85c4a" stroke-width="1"/>
</g>
<!-- Footer -->
<g transform="translate(50,405)">
<rect x="0" y="0" width="800" height="42" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="17" font-size="10" font-weight="800" fill="#1f4e5a">Warum wichtig:</text>
<text x="110" y="17" font-size="10" fill="#4a4a4a">Taut der Permafrost auf, wird organisches Material abgebaut — CO₂ und Methan gelangen in die Atmosphäre (Kipppunkt).</text>
<text x="12" y="33" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="70" y="33" font-size="10" fill="#4a4a4a">International Permafrost Association (2020): Permafrost Map · Schuur et al. (2022): Permafrost and Climate Change · IPCC AR6 WG1, Kap. 9</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

@@ -1,109 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 480" font-family="Inter, system-ui, sans-serif" width="900" height="480">
<defs>
<marker id="pv-arr" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#e8833a"/>
</marker>
<marker id="pv-e" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4a7c8a"/>
</marker>
</defs>
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Photovoltaik — Sonnenlicht wird direkt in Strom verwandelt
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
Aufbau einer Silizium-Solarzelle · Wirkungsgrad heutiger Module 2023 %
</text>
<!-- LINKS: Solarzellen-Querschnitt -->
<g transform="translate(60,100)">
<text x="180" y="0" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">So funktioniert eine Solarzelle</text>
<!-- Sonne + Lichtstrahlen -->
<circle cx="40" cy="40" r="22" fill="#f4c94e"/>
<text x="40" y="46" font-size="14" font-weight="900" fill="#1f4e5a" text-anchor="middle"></text>
<g stroke="#e8833a" stroke-width="2" fill="none" marker-end="url(#pv-arr)">
<line x1="70" y1="55" x2="130" y2="120"/>
<line x1="90" y1="55" x2="170" y2="120"/>
<line x1="110" y1="55" x2="210" y2="120"/>
<line x1="130" y1="55" x2="250" y2="120"/>
<line x1="150" y1="55" x2="290" y2="120"/>
</g>
<!-- Zell-Querschnitt -->
<rect x="80" y="125" width="260" height="12" fill="#8a8a8a"/>
<text x="350" y="134" font-size="9" fill="#8a8a8a">Anti-Reflex-Schicht</text>
<rect x="80" y="137" width="260" height="26" fill="#4a7c8a"/>
<text x="350" y="155" font-size="9" fill="#4a7c8a" font-weight="700">n-Silizium</text>
<rect x="80" y="163" width="260" height="26" fill="#3a6470"/>
<text x="350" y="181" font-size="9" fill="#3a6470" font-weight="700">p-Silizium</text>
<rect x="80" y="189" width="260" height="10" fill="#1a1a1a"/>
<text x="350" y="198" font-size="9" fill="#1a1a1a">Rück-Kontakt</text>
<!-- Übergangslinie markieren -->
<line x1="80" y1="163" x2="340" y2="163" stroke="#c85c4a" stroke-width="1" stroke-dasharray="3 2"/>
<text x="210" y="178" font-size="9" font-weight="700" fill="#c85c4a" text-anchor="middle">p-n-Übergang</text>
<!-- Elektronen-Pfeil -->
<path d="M 210 150 L 210 220 L 20 220 L 20 150" stroke="#4a7c8a" stroke-width="2" fill="none" marker-end="url(#pv-e)"/>
<circle cx="20" cy="180" r="8" fill="#4a7c8a"/>
<text x="20" y="184" font-size="11" font-weight="900" fill="#fff" text-anchor="middle">e⁻</text>
<text x="10" y="258" font-size="10" fill="#4a7c8a" font-weight="700">Elektronen fließen</text>
<text x="10" y="271" font-size="10" fill="#4a7c8a" font-weight="700">als Strom</text>
<!-- Lampe anschließen -->
<circle cx="210" cy="260" r="18" fill="none" stroke="#c4a97a" stroke-width="2"/>
<line x1="210" y1="248" x2="210" y2="254" stroke="#1f4e5a" stroke-width="1"/>
<path d="M 200 258 L 220 258" stroke="#1f4e5a" stroke-width="1" fill="none"/>
<circle cx="210" cy="260" r="6" fill="#f4c94e"/>
<text x="210" y="293" font-size="9" fill="#8a8a8a" text-anchor="middle">Verbraucher</text>
</g>
<!-- RECHTS: Ertrag-Vergleich -->
<g transform="translate(520,100)">
<text x="160" y="0" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">Was liefert 1 m² Dachfläche?</text>
<text x="160" y="15" font-size="10" fill="#8a8a8a" text-anchor="middle">in Österreich, nach Süden ausgerichtet</text>
<!-- Haus mit Solardach -->
<g transform="translate(20,40)">
<rect x="0" y="60" width="100" height="60" fill="#e8d5b5" stroke="#1f4e5a" stroke-width="1"/>
<polygon points="-6,60 50,15 106,60" fill="#4a7c8a" stroke="#1f4e5a" stroke-width="1"/>
<!-- PV-Module -->
<g>
<rect x="8" y="21" width="18" height="22" fill="#1f4e5a" stroke="#4a7c8a" stroke-width=".5" transform="skewX(-38)"/>
<rect x="30" y="21" width="18" height="22" fill="#1f4e5a" stroke="#4a7c8a" stroke-width=".5" transform="skewX(-38)"/>
<rect x="52" y="21" width="18" height="22" fill="#1f4e5a" stroke="#4a7c8a" stroke-width=".5" transform="skewX(-38)"/>
</g>
<rect x="45" y="85" width="12" height="25" fill="#6b4a2e"/>
<text x="50" y="145" font-size="10" fill="#1f4e5a" font-weight="700" text-anchor="middle">1 m² PV</text>
</g>
<!-- Ergebnis -->
<g transform="translate(160,40)">
<rect x="0" y="30" width="160" height="80" rx="6" fill="#f4c94e"/>
<text x="80" y="58" font-size="22" font-weight="900" fill="#1f4e5a" text-anchor="middle">≈ 170</text>
<text x="80" y="78" font-size="12" font-weight="800" fill="#1f4e5a" text-anchor="middle">kWh pro Jahr</text>
<text x="80" y="100" font-size="10" fill="#1f4e5a" text-anchor="middle">(Jahresertrag je m²)</text>
</g>
<!-- Vergleich Waschmaschinen -->
<g transform="translate(0,200)">
<text x="160" y="0" font-size="11" font-weight="700" fill="#1f4e5a" text-anchor="middle">Das reicht für …</text>
<g transform="translate(10,15)" font-size="11">
<text y="18">🧺 170 × Waschmaschine</text>
<text y="38">📺 1.200 Stunden Fernsehen</text>
<text y="58">🚗 1.200 km im Elektroauto</text>
<text y="78">💡 17.000 h mit einer 10-W-LED-Lampe</text>
</g>
</g>
</g>
<!-- Footer Quellen -->
<g transform="translate(50,430)">
<rect x="0" y="0" width="800" height="40" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="16" font-size="10" font-weight="800" fill="#1f4e5a">AT 2024:</text>
<text x="75" y="16" font-size="10" fill="#4a4a4a">ca. 6.400 MWp installiert — das entspricht rund 64 km² Modulfläche.</text>
<text x="12" y="32" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="75" y="32" font-size="10" fill="#4a4a4a">Fraunhofer ISE, Photovoltaics Report 2024 · PV Austria, Marktbericht 2024</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

-117
View File
@@ -1,117 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 640" font-family="Inter, system-ui, sans-serif" width="1100" height="640">
<defs>
<!-- Feines Hintergrund-Raster für den 1000x1000-Block -->
<pattern id="fineGrid" x="0" y="0" width="5" height="5" patternUnits="userSpaceOnUse">
<path d="M 5 0 L 0 0 L 0 5" fill="none" stroke="#4a7c8a" stroke-width="0.05" opacity="0.35"/>
</pattern>
<pattern id="coarseGrid" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse">
<path d="M 50 0 L 0 0 L 0 50" fill="none" stroke="#4a7c8a" stroke-width="0.25" opacity="0.5"/>
</pattern>
<!-- Grobes Raster für den Zoom-Ausschnitt (10x10) -->
<pattern id="zoomGrid" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 L 0 40" fill="none" stroke="#4a7c8a" stroke-width="1" opacity="0.35"/>
</pattern>
<!-- Pfeilspitze -->
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#c85c4a"/>
</marker>
</defs>
<!-- ========== LINKE SEITE: 1.000.000 Teilchen ========== -->
<g transform="translate(50, 70)">
<!-- Titel -->
<text x="250" y="-30" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">
1 Quadrat = 1.000.000 Luftteilchen
</text>
<text x="250" y="-12" font-size="11" fill="#8a8a8a" text-anchor="middle">
1000 × 1000 Kästchen
</text>
<!-- Hintergrundblock -->
<rect x="0" y="0" width="500" height="500" fill="#eff5f6" stroke="#4a7c8a" stroke-width="2" rx="3"/>
<!-- Feines Raster (alle 5 Units = alle 0,5% des Blocks) -->
<rect x="0" y="0" width="500" height="500" fill="url(#fineGrid)"/>
<!-- Grobes Raster (alle 50 Units = alle 5%) -->
<rect x="0" y="0" width="500" height="500" fill="url(#coarseGrid)"/>
<!-- DAS EINE TEILCHEN — mathematisch korrekt 0,5 × 0,5 SVG-Units bei 500×500-Block = 1/1.000.000 -->
<!-- Position (250, 250) — in der Mitte -->
<rect x="249.75" y="249.75" width="0.5" height="0.5" fill="#c85c4a"/>
<!-- Pulsierender Glow-Kreis, damit man das Pixel überhaupt findet -->
<circle cx="250" cy="250" r="0" fill="none" stroke="#c85c4a" stroke-width="1.5">
<animate attributeName="r" values="4;45;4" dur="2.8s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.9;0;0.9" dur="2.8s" repeatCount="indefinite"/>
<animate attributeName="stroke-width" values="2;0.3;2" dur="2.8s" repeatCount="indefinite"/>
</circle>
<!-- Zweiter Glow, versetzt für sanfteren Puls -->
<circle cx="250" cy="250" r="0" fill="none" stroke="#c85c4a" stroke-width="1">
<animate attributeName="r" values="0;30;0" dur="2.8s" begin="1.4s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.7;0;0.7" dur="2.8s" begin="1.4s" repeatCount="indefinite"/>
</circle>
<!-- Lupen-Ausschnitt als gestricheltes Viereck (10×10 Einheiten) — zeigt was im Zoom rechts vergrössert wird -->
<rect x="245" y="245" width="10" height="10" fill="none" stroke="#c85c4a" stroke-width="0.8" stroke-dasharray="2 1.5"/>
<!-- Pfeil zum Pixel -->
<path d="M 400 150 Q 330 200 265 245" fill="none" stroke="#c85c4a" stroke-width="1.5" marker-end="url(#arrow)"/>
<text x="405" y="138" font-size="13" font-weight="700" fill="#c85c4a">1 Teilchen</text>
<text x="405" y="152" font-size="11" fill="#c85c4a">(1 ppm)</text>
<!-- Erklärung unter dem Block -->
<text x="0" y="525" font-size="11" fill="#4a4a4a" font-weight="600">
Jedes Mini-Kästchen = 1 Luftteilchen (N₂, O₂, Ar …)
</text>
<text x="0" y="543" font-size="10" fill="#8a8a8a">
Das rote Kästchen ist so klein, dass du es kaum siehst — genau darum geht es.
</text>
</g>
<!-- Verbindungslinien vom Lupen-Ausschnitt zum Zoom-Block -->
<g stroke="#c85c4a" stroke-width="0.8" stroke-dasharray="3 2" fill="none" opacity="0.6">
<line x1="305" y1="315" x2="650" y2="120"/>
<line x1="305" y1="325" x2="650" y2="520"/>
</g>
<!-- ========== RECHTE SEITE: Zoom 100× (10×10 Ausschnitt) ========== -->
<g transform="translate(650, 70)">
<!-- Titel -->
<text x="200" y="-30" font-size="14" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Zoom 100×: Ausschnitt 10 × 10
</text>
<text x="200" y="-12" font-size="11" fill="#8a8a8a" text-anchor="middle">
Hier: 1 von 100 Teilchen sichtbar markiert
</text>
<!-- Zoom-Block -->
<rect x="0" y="0" width="400" height="400" fill="#eff5f6" stroke="#c85c4a" stroke-width="2" stroke-dasharray="4 3" rx="3"/>
<!-- Grobes Raster (10×10) -->
<rect x="0" y="0" width="400" height="400" fill="url(#zoomGrid)"/>
<!-- Das markierte Teilchen = 40×40 im Zoom (= 1/100 der Zoom-Fläche, entspricht 1/1.000.000 im Original) -->
<rect x="180" y="180" width="40" height="40" fill="#c85c4a">
<animate attributeName="opacity" values="1;0.6;1" dur="2.8s" repeatCount="indefinite"/>
</rect>
<!-- Weißes Fragezeichen / Hinweis im Pixel -->
<text x="200" y="208" font-size="22" font-weight="900" fill="#fff" text-anchor="middle">CO₂</text>
<!-- Erklärung -->
<text x="0" y="425" font-size="11" fill="#4a4a4a" font-weight="600">
Das ist der kleine Lupen-Ausschnitt aus dem linken Block.
</text>
<text x="0" y="443" font-size="10" fill="#8a8a8a">
In dieser Lupe hat sich das CO₂-Teilchen 100× vergrössert — nur so sieht man es.
</text>
</g>
<!-- ========== UNTEN: Didaktische Vergleiche ========== -->
<g transform="translate(50, 590)">
<rect x="0" y="0" width="1000" height="40" fill="#fff" stroke="#dae8ec" stroke-width="1" rx="6"/>
<text x="20" y="18" font-size="11" fill="#1f4e5a" font-weight="700">
Vergleiche für 1 ppm:
</text>
<text x="20" y="33" font-size="10.5" fill="#4a4a4a">
1 Tropfen Tinte in 50 Litern Wasser · 1 Cent von 10.000 Euro · 1 Sekunde in 11,5 Tagen
</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.9 KiB

-139
View File
@@ -1,139 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 500" font-family="Inter, system-ui, sans-serif" width="900" height="500">
<defs>
<marker id="th-arrow-in" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#e8833a"/>
</marker>
<marker id="th-arrow-out" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#c85c4a"/>
</marker>
<marker id="th-arrow-esc" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#8a8a8a"/>
</marker>
<linearGradient id="th-space" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0f2230"/>
<stop offset="1" stop-color="#1f4e5a"/>
</linearGradient>
<linearGradient id="th-atm" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#4a7c8a" stop-opacity=".18"/>
<stop offset="1" stop-color="#4a7c8a" stop-opacity=".45"/>
</linearGradient>
<linearGradient id="th-earth" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#5a8a5e"/>
<stop offset="1" stop-color="#3a6b3e"/>
</linearGradient>
</defs>
<!-- Titel -->
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Treibhauseffekt — Wie die Erde warm bleibt
</text>
<!-- Weltraum (schwarzer Hintergrund oben) -->
<rect x="0" y="55" width="900" height="90" fill="url(#th-space)"/>
<!-- Sterne -->
<g fill="#fff" opacity=".7">
<circle cx="80" cy="80" r="1"/><circle cx="220" cy="70" r=".8"/>
<circle cx="420" cy="95" r="1.2"/><circle cx="640" cy="75" r="1"/>
<circle cx="780" cy="90" r=".8"/><circle cx="160" cy="110" r=".7"/>
<circle cx="540" cy="115" r="1"/><circle cx="720" cy="120" r=".9"/>
</g>
<text x="880" y="75" font-size="10" fill="#dae8ec" text-anchor="end" opacity=".8">Weltraum</text>
<!-- Sonne oben links -->
<circle cx="110" cy="100" r="32" fill="#f4c94e"/>
<circle cx="110" cy="100" r="38" fill="none" stroke="#f4c94e" stroke-width="1.5" opacity=".5"/>
<circle cx="110" cy="100" r="46" fill="none" stroke="#f4c94e" stroke-width="1" opacity=".3"/>
<text x="110" y="104" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle"></text>
<text x="110" y="160" font-size="11" fill="#dae8ec" text-anchor="middle" font-weight="600">Sonne</text>
<!-- Atmosphäre -->
<rect x="0" y="145" width="900" height="100" fill="url(#th-atm)"/>
<line x1="0" y1="145" x2="900" y2="145" stroke="#4a7c8a" stroke-width="1" stroke-dasharray="4 3" opacity=".7"/>
<line x1="0" y1="245" x2="900" y2="245" stroke="#4a7c8a" stroke-width="1" stroke-dasharray="4 3" opacity=".5"/>
<text x="20" y="200" font-size="11" fill="#1f4e5a" font-weight="700">Atmosphäre</text>
<text x="20" y="215" font-size="9" fill="#4a7c8a">CO₂ · CH₄ · H₂O · N₂O</text>
<!-- Treibhausgas-Moleküle in der Atmosphäre -->
<g>
<circle cx="280" cy="180" r="8" fill="#c85c4a" opacity=".75"/>
<text x="280" y="184" font-size="8" font-weight="700" fill="#fff" text-anchor="middle">CO₂</text>
<circle cx="380" cy="210" r="8" fill="#c85c4a" opacity=".75"/>
<text x="380" y="214" font-size="8" font-weight="700" fill="#fff" text-anchor="middle">CO₂</text>
<circle cx="500" cy="175" r="8" fill="#e8833a" opacity=".75"/>
<text x="500" y="179" font-size="8" font-weight="700" fill="#fff" text-anchor="middle">CH₄</text>
<circle cx="620" cy="205" r="8" fill="#c85c4a" opacity=".75"/>
<text x="620" y="209" font-size="8" font-weight="700" fill="#fff" text-anchor="middle">CO₂</text>
<circle cx="740" cy="180" r="8" fill="#4a7c8a" opacity=".65"/>
<text x="740" y="184" font-size="7" font-weight="700" fill="#fff" text-anchor="middle">H₂O</text>
</g>
<!-- Erde/Boden -->
<rect x="0" y="385" width="900" height="115" fill="url(#th-earth)"/>
<!-- Bäume & Häuser -->
<g>
<polygon points="140,385 150,360 160,385" fill="#3a6b3e"/>
<rect x="148" y="385" width="4" height="10" fill="#6b4a2e"/>
<polygon points="220,385 233,358 246,385" fill="#3a6b3e"/>
<rect x="230" y="385" width="6" height="12" fill="#6b4a2e"/>
<rect x="400" y="360" width="28" height="25" fill="#e8d5b5" stroke="#4a7c8a" stroke-width="1"/>
<polygon points="398,361 414,348 430,361" fill="#c85c4a"/>
<rect x="410" y="370" width="6" height="15" fill="#4a7c8a"/>
<rect x="580" y="350" width="36" height="35" fill="#e8d5b5" stroke="#4a7c8a" stroke-width="1"/>
<polygon points="578,351 598,334 618,351" fill="#c85c4a"/>
<rect x="590" y="365" width="7" height="20" fill="#4a7c8a"/>
<polygon points="720,385 735,356 750,385" fill="#3a6b3e"/>
<rect x="731" y="385" width="6" height="10" fill="#6b4a2e"/>
</g>
<text x="20" y="425" font-size="11" fill="#fff" font-weight="700">Erdoberfläche</text>
<text x="20" y="441" font-size="9" fill="#dceadd">absorbiert Licht · strahlt Wärme ab</text>
<!-- ========= STRAHLENGANG ========= -->
<!-- Einkommende Sonnenstrahlung (gelb/orange) -->
<g stroke="#e8833a" stroke-width="2" fill="none" marker-end="url(#th-arrow-in)" opacity=".9">
<line x1="145" y1="125" x2="270" y2="370"/>
<line x1="170" y1="130" x2="345" y2="370"/>
<line x1="195" y1="135" x2="425" y2="370"/>
</g>
<text x="210" y="280" font-size="10" fill="#e8833a" font-weight="700" transform="rotate(58 210 280)">Sonnenlicht (kurzwellig)</text>
<!-- Abgestrahlte Wärme, die teilweise zurückgeworfen wird (rot) -->
<g stroke="#c85c4a" stroke-width="2" fill="none" marker-end="url(#th-arrow-out)" opacity=".85">
<!-- Nach oben vom Boden -->
<line x1="470" y1="370" x2="500" y2="175"/>
<line x1="610" y1="370" x2="620" y2="205"/>
<line x1="350" y1="370" x2="380" y2="210"/>
</g>
<!-- Rückreflexion von Treibhausgasen wieder zurück zur Erde -->
<g stroke="#c85c4a" stroke-width="2" fill="none" marker-end="url(#th-arrow-out)" opacity=".8" stroke-dasharray="3 2">
<path d="M 500 175 Q 540 270 550 370" />
<path d="M 380 210 Q 360 290 410 370"/>
<path d="M 620 205 Q 680 285 700 370"/>
</g>
<text x="550" y="330" font-size="10" fill="#c85c4a" font-weight="700">Wärmestrahlung zurück zur Erde</text>
<!-- Etwas Wärme entweicht ins All (grau) -->
<g stroke="#8a8a8a" stroke-width="1.5" fill="none" marker-end="url(#th-arrow-esc)" opacity=".8" stroke-dasharray="2 2">
<line x1="800" y1="370" x2="840" y2="80"/>
</g>
<text x="840" y="220" font-size="9" fill="#8a8a8a" text-anchor="end">Rest entweicht</text>
<!-- ========= VERGLEICHSBOX ========= -->
<g transform="translate(0, 460)">
<rect x="0" y="0" width="900" height="40" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="20" y="16" font-size="10" fill="#1f4e5a" font-weight="800">Ohne Atmosphäre:</text>
<text x="165" y="16" font-size="10" fill="#c85c4a" font-weight="700">18 °C</text>
<text x="220" y="16" font-size="10" fill="#8a8a8a">(lebensfeindlich kalt)</text>
<text x="400" y="16" font-size="10" fill="#1f4e5a" font-weight="800">Mit natürlichem Treibhauseffekt:</text>
<text x="615" y="16" font-size="10" fill="#5a8a5e" font-weight="700">+15 °C</text>
<text x="660" y="16" font-size="10" fill="#8a8a8a">(Lebensraum Erde)</text>
<text x="20" y="32" font-size="10" fill="#1f4e5a" font-weight="800">Venus (extremer THE):</text>
<text x="165" y="32" font-size="10" fill="#c85c4a" font-weight="700">+465 °C</text>
<text x="400" y="32" font-size="10" fill="#1f4e5a" font-weight="800">Erde seit 1850 (zusätzlich):</text>
<text x="615" y="32" font-size="10" fill="#e8833a" font-weight="700">+1,2 °C</text>
<text x="660" y="32" font-size="10" fill="#8a8a8a">(vom Menschen verursacht)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.7 KiB

@@ -1,98 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 460" font-family="Inter, system-ui, sans-serif" width="900" height="460">
<text x="450" y="30" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Die wichtigsten Treibhausgase — Wirkung und Anteil in Österreich
</text>
<text x="450" y="50" font-size="11" fill="#8a8a8a" text-anchor="middle">
GWP-100 = Wirkung auf 100 Jahre, CO₂ als Referenz · Anteile AT 2023
</text>
<!-- LINKS: log-Skala GWP-100 -->
<g transform="translate(40,90)">
<text x="250" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">Wie stark wirkt 1 kg dieses Gases wie x kg CO₂?</text>
<text x="250" y="15" font-size="10" fill="#8a8a8a" text-anchor="middle">(logarithmische Skala)</text>
<!-- Achse log: 1, 10, 100, 1000, 10000, 100000 -->
<!-- x = 70 + log10(GWP) * 80 -->
<line x1="70" y1="265" x2="540" y2="265" stroke="#1f4e5a" stroke-width="1.5"/>
<g font-size="9" fill="#4a4a4a" text-anchor="middle">
<line x1="70" y1="265" x2="70" y2="270" stroke="#1f4e5a"/><text x="70" y="283">1</text>
<line x1="150" y1="265" x2="150" y2="270" stroke="#1f4e5a"/><text x="150" y="283">10</text>
<line x1="230" y1="265" x2="230" y2="270" stroke="#1f4e5a"/><text x="230" y="283">100</text>
<line x1="310" y1="265" x2="310" y2="270" stroke="#1f4e5a"/><text x="310" y="283">1.000</text>
<line x1="390" y1="265" x2="390" y2="270" stroke="#1f4e5a"/><text x="390" y="283">10.000</text>
<line x1="470" y1="265" x2="470" y2="270" stroke="#1f4e5a"/><text x="470" y="283">100.000</text>
</g>
<!-- Balken (horizontal, log-skaliert) -->
<!-- CO₂ GWP=1 → Balken bis 70 = 0 Länge. Minimalbreite 6 -->
<g font-size="10">
<!-- CO₂ -->
<rect x="70" y="40" width="6" height="28" fill="#4a7c8a"/>
<text x="66" y="57" fill="#1f4e5a" font-weight="800" text-anchor="end">CO₂</text>
<text x="82" y="57" fill="#1f4e5a" font-weight="700">= 1 (Referenz)</text>
<!-- Methan GWP-100 = 28 → x = 70 + 1.447 * 80 = 185.8. Länge 115.8 -->
<rect x="70" y="80" width="115.8" height="28" fill="#e8833a"/>
<text x="66" y="97" fill="#1f4e5a" font-weight="800" text-anchor="end">Methan CH₄</text>
<text x="192" y="97" fill="#1f4e5a" font-weight="700">= 28</text>
<!-- Lachgas N₂O = 273 → x = 70 + 2.436 * 80 = 264.9. Länge 194.9 -->
<rect x="70" y="120" width="194.9" height="28" fill="#c85c4a"/>
<text x="66" y="137" fill="#1f4e5a" font-weight="800" text-anchor="end">Lachgas N₂O</text>
<text x="272" y="137" fill="#1f4e5a" font-weight="700">= 273</text>
<!-- HFC-134a = 1530 → log=3.185, x=70+3.185*80 = 324.8. Länge 254.8 -->
<rect x="70" y="160" width="254.8" height="28" fill="#b07aa1"/>
<text x="66" y="177" fill="#1f4e5a" font-weight="800" text-anchor="end">HFC-134a</text>
<text x="332" y="177" fill="#1f4e5a" font-weight="700">= 1.530 (Kälte-/Klimagase)</text>
<!-- SF₆ = 23500 → log=4.371, x=70+4.371*80 = 419.7. Länge 349.7 -->
<rect x="70" y="200" width="349.7" height="28" fill="#1a1a1a"/>
<text x="66" y="217" fill="#1f4e5a" font-weight="800" text-anchor="end">SF₆</text>
<text x="427" y="217" fill="#1f4e5a" font-weight="700">= 23.500 (Elektro-Schaltanlagen)</text>
</g>
<text x="250" y="308" font-size="10" fill="#8a8a8a" text-anchor="middle">Treibhauspotenzial (GWP-100 nach IPCC AR6)</text>
</g>
<!-- RECHTS: Kuchen AT-Anteile 2023 -->
<g transform="translate(720,220)">
<text x="0" y="-135" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">AT-Emissionen 2023</text>
<text x="0" y="-120" font-size="10" fill="#8a8a8a" text-anchor="middle">68,7 Mt CO₂eq, aufgeteilt nach Gas</text>
<!-- Anteile: CO₂ 80%, CH₄ 11%, N₂O 6%, F-Gase 3% -->
<!-- 80%: 0 → 288° -->
<path d="M 0 0 L 0 -90 A 90 90 0 1 1 -85.59 27.81 Z" fill="#4a7c8a"/>
<!-- CH₄ 11%: 288 → 327.6° -->
<path d="M 0 0 L -85.59 27.81 A 90 90 0 0 1 -48.08 -75.94 Z" fill="#e8833a"/>
<!-- N₂O 6%: 327.6 → 349.2° -->
<path d="M 0 0 L -48.08 -75.94 A 90 90 0 0 1 -16.84 -88.41 Z" fill="#c85c4a"/>
<!-- F-Gase 3%: 349.2 → 360° -->
<path d="M 0 0 L -16.84 -88.41 A 90 90 0 0 1 0 -90 Z" fill="#b07aa1"/>
<!-- Zentrum -->
<circle r="35" fill="#fff"/>
<text y="-3" font-size="14" font-weight="900" fill="#1f4e5a" text-anchor="middle">68,7</text>
<text y="12" font-size="9" font-weight="700" fill="#4a7c8a" text-anchor="middle">Mt CO₂eq</text>
<!-- Labels -->
<text x="40" y="-30" font-size="11" font-weight="800" fill="#fff" text-anchor="middle">80 %</text>
<text x="40" y="-15" font-size="9" fill="#fff" text-anchor="middle">CO₂</text>
</g>
<!-- Legende rechts unterhalb -->
<g transform="translate(640,335)" font-size="10">
<g><rect width="12" height="12" fill="#4a7c8a"/><text x="18" y="10" fill="#1f4e5a" font-weight="700">CO₂ 80 %</text></g>
<g transform="translate(90,0)"><rect width="12" height="12" fill="#e8833a"/><text x="18" y="10" fill="#1f4e5a" font-weight="700">CH₄ 11 %</text></g>
<g transform="translate(0,18)"><rect width="12" height="12" fill="#c85c4a"/><text x="18" y="10" fill="#1f4e5a" font-weight="700">N₂O 6 %</text></g>
<g transform="translate(90,18)"><rect width="12" height="12" fill="#b07aa1"/><text x="18" y="10" fill="#1f4e5a" font-weight="700">F-Gase 3 %</text></g>
</g>
<!-- Footer -->
<g transform="translate(50,410)">
<rect x="0" y="0" width="800" height="40" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="16" font-size="10" font-weight="800" fill="#1f4e5a">Wasserdampf:</text>
<text x="100" y="16" font-size="10" fill="#4a4a4a">mengenmäßig stärkstes Treibhausgas, aber durch Temperatur gesteuert — nicht direkt vom Menschen reguliert.</text>
<text x="12" y="32" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="70" y="32" font-size="10" fill="#4a4a4a">IPCC AR6 WG1 (2021), Tab. 7.15 (GWP-Werte) · Umweltbundesamt Österreich, Klimaschutzbericht 2024</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

@@ -1,123 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 460" font-family="Inter, system-ui, sans-serif" width="900" height="460">
<defs>
<linearGradient id="wk-water" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#4a7c8a"/>
<stop offset="1" stop-color="#1f4e5a"/>
</linearGradient>
<linearGradient id="wk-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#eff5f6"/>
<stop offset="1" stop-color="#dae8ec"/>
</linearGradient>
<marker id="wk-arr" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4a7c8a"/>
</marker>
</defs>
<text x="450" y="28" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Wasserkraft — die Topografie Österreichs als Stromspeicher
</text>
<text x="450" y="46" font-size="11" fill="#8a8a8a" text-anchor="middle">
Zwei wichtige Bauformen im Querschnitt · Anteil am AT-Strom 2023: 58 %
</text>
<!-- LINKS: Laufkraftwerk (Fluss-Stau) -->
<g transform="translate(30,80)">
<text x="200" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">Laufkraftwerk (z. B. Donau)</text>
<!-- Himmel -->
<rect x="0" y="15" width="400" height="110" fill="url(#wk-sky)"/>
<!-- Bergflanke rechts -->
<polygon points="0,125 400,125 400,260 0,260" fill="#c4a97a"/>
<!-- Fluss oben -->
<rect x="0" y="90" width="220" height="35" fill="url(#wk-water)"/>
<!-- Wehr-Anlage -->
<rect x="220" y="60" width="40" height="120" fill="#8a8a8a" stroke="#1f4e5a" stroke-width="1"/>
<rect x="220" y="60" width="40" height="12" fill="#1f4e5a"/>
<!-- Turbinenhaus -->
<rect x="260" y="95" width="90" height="85" fill="#c85c4a" stroke="#1f4e5a" stroke-width="1"/>
<rect x="260" y="95" width="90" height="10" fill="#a04030"/>
<!-- Turbine (Kreis) -->
<circle cx="305" cy="140" r="20" fill="#fff" stroke="#1f4e5a" stroke-width="1.5"/>
<g transform="translate(305,140)" stroke="#4a7c8a" stroke-width="2" fill="none">
<line x1="-14" y1="0" x2="14" y2="0"/>
<line x1="0" y1="-14" x2="0" y2="14"/>
<line x1="-10" y1="-10" x2="10" y2="10"/>
<line x1="-10" y1="10" x2="10" y2="-10"/>
</g>
<text x="305" y="175" font-size="9" fill="#fff" font-weight="700" text-anchor="middle">Turbine</text>
<!-- Fluss nach Kraftwerk, niedriger -->
<rect x="350" y="115" width="50" height="25" fill="url(#wk-water)"/>
<!-- Wasser-Pfeil Stau→Turbine -->
<path d="M 195 107 Q 240 135 290 140" stroke="#4a7c8a" stroke-width="2" fill="none" marker-end="url(#wk-arr)"/>
<!-- Höhen-Markierung -->
<line x1="15" y1="90" x2="15" y2="140" stroke="#c85c4a" stroke-width="1" stroke-dasharray="3 2"/>
<text x="18" y="118" font-size="9" fill="#c85c4a" font-weight="700">310 m</text>
<text x="18" y="131" font-size="9" fill="#c85c4a">Fallhöhe</text>
<!-- Label -->
<g transform="translate(10,205)">
<rect x="0" y="0" width="380" height="48" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="16" font-size="10" font-weight="800" fill="#1f4e5a">Laufend am Fluss — rund um die Uhr verfügbar.</text>
<text x="10" y="32" font-size="10" fill="#4a4a4a">Beispiel AT: Kraftwerk Freudenau (Wien) · 172 MW · versorgt</text>
<text x="10" y="44" font-size="10" fill="#4a4a4a">rechnerisch ca. 230.000 Haushalte.</text>
</g>
</g>
<!-- RECHTS: Speicherkraftwerk -->
<g transform="translate(470,80)">
<text x="200" y="0" font-size="13" font-weight="800" fill="#1f4e5a" text-anchor="middle">Speicherkraftwerk (z. B. Kaprun)</text>
<!-- Himmel -->
<rect x="0" y="15" width="400" height="55" fill="url(#wk-sky)"/>
<!-- Berge -->
<polygon points="0,70 80,30 140,70" fill="#e8d5b5" stroke="#1f4e5a" stroke-width="1"/>
<polygon points="100,70 170,25 240,70" fill="#c4a97a" stroke="#1f4e5a" stroke-width="1"/>
<!-- Stauseefläche -->
<rect x="45" y="70" width="180" height="40" fill="url(#wk-water)"/>
<!-- Wehr links -->
<rect x="225" y="70" width="15" height="60" fill="#8a8a8a" stroke="#1f4e5a"/>
<!-- Berge auf Kraftwerks-Seite -->
<polygon points="225,70 280,55 360,70" fill="#c4a97a" stroke="#1f4e5a" stroke-width="1"/>
<polygon points="225,70 400,70 400,260 225,260" fill="#c4a97a"/>
<!-- Falllleitung (Druckrohr) durch den Berg -->
<path d="M 235 130 Q 240 170 280 210" stroke="#4a7c8a" stroke-width="5" fill="none"/>
<path d="M 235 130 Q 240 170 280 210" stroke="#fff" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
<text x="266" y="180" font-size="9" fill="#fff" font-weight="700" transform="rotate(65 266 180)">Druckrohr</text>
<!-- Turbinenhaus unten -->
<rect x="270" y="210" width="90" height="50" fill="#c85c4a" stroke="#1f4e5a"/>
<rect x="270" y="210" width="90" height="8" fill="#a04030"/>
<circle cx="315" cy="235" r="14" fill="#fff" stroke="#1f4e5a" stroke-width="1.5"/>
<g transform="translate(315,235)" stroke="#4a7c8a" stroke-width="1.5" fill="none">
<line x1="-10" y1="0" x2="10" y2="0"/>
<line x1="0" y1="-10" x2="0" y2="10"/>
<line x1="-7" y1="-7" x2="7" y2="7"/>
<line x1="-7" y1="7" x2="7" y2="-7"/>
</g>
<text x="315" y="255" font-size="9" fill="#fff" font-weight="700" text-anchor="middle">Turbine</text>
<!-- Höhen-Markierung -->
<line x1="385" y1="80" x2="385" y2="230" stroke="#c85c4a" stroke-width="1" stroke-dasharray="3 2"/>
<text x="378" y="150" font-size="9" fill="#c85c4a" font-weight="700" transform="rotate(-90 378 150)">bis 800 m Fallhöhe</text>
<!-- Label -->
<g transform="translate(10,205)">
<rect x="-7" y="68" width="380" height="48" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="3" y="84" font-size="10" font-weight="800" fill="#1f4e5a">Wasser sammelt sich im Stausee — kann bei Bedarf abgelassen werden.</text>
<text x="3" y="100" font-size="10" fill="#4a4a4a">Beispiel AT: Pumpspeicher Kops II (Vorarlberg) · 525 MW.</text>
<text x="3" y="112" font-size="10" fill="#4a4a4a">Wirkt wie eine gigantische Batterie für Wind- und Solarstrom.</text>
</g>
</g>
<!-- Footer -->
<g transform="translate(50,415)">
<rect x="0" y="0" width="800" height="35" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="15" font-size="10" font-weight="800" fill="#1f4e5a">AT 2023:</text>
<text x="72" y="15" font-size="10" fill="#4a4a4a">58 % der Stromerzeugung aus Wasserkraft · ca. 15.000 MW installierte Leistung · mehr als 2.700 Anlagen.</text>
<text x="12" y="30" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="70" y="30" font-size="10" fill="#4a4a4a">E-Control, Betriebsstatistik Strom 2023 · VERBUND · WWF Österreich (ökologische Bewertung)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

-180
View File
@@ -1,180 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 560" font-family="Inter, system-ui, sans-serif" width="900" height="560">
<defs>
<linearGradient id="wl-bar" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#c85c4a"/>
<stop offset=".25" stop-color="#e8833a"/>
<stop offset=".55" stop-color="#f4c94e"/>
<stop offset=".8" stop-color="#5a8a5e"/>
<stop offset="1" stop-color="#4a7c8a"/>
</linearGradient>
</defs>
<text x="450" y="32" font-size="17" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Die Leistungs-Leiter — Watt, Kilowatt, Megawatt, Gigawatt im Überblick
</text>
<text x="450" y="52" font-size="11" fill="#8a8a8a" text-anchor="middle">
Logarithmische Skala · jeder Schritt = 10× mehr Leistung · Beispiele gerundet
</text>
<!-- Vertikale Leiter im Zentrum: x=450, y 90..520 (430 px für 10 Schritte: 10⁰ W..10⁹ W) -->
<!-- Jeweils 43 px pro Dekade -->
<rect x="440" y="80" width="20" height="450" rx="10" fill="url(#wl-bar)"/>
<!-- Skala-Beschriftung: 10⁰..10⁹ Watt -->
<!-- yByLogW: y = 520 - logW * 43. logW = log10(watt) -->
<!-- Beispiele links (Haushalt) -->
<g font-family="Inter, system-ui, sans-serif">
<!-- 5 W — LED Lampe -->
<g transform="translate(0, 497)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#c85c4a" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="2" font-size="22" text-anchor="start">💡</text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">LED-Lampe</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">510 W</text>
</g>
<!-- 100 W — Mensch -->
<g transform="translate(0, 413)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#c85c4a" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="5" font-size="22">🚶</text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">Mensch beim Gehen</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">≈ 100 W Muskelkraft</text>
</g>
<!-- 2.000 W (2 kW) — Wasserkocher -->
<g transform="translate(0, 327)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#e8833a" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="5" font-size="22">🫖</text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">Wasserkocher</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">2 kW = 2.000 W</text>
</g>
<!-- 150 kW — E-Auto Motor -->
<g transform="translate(0, 229)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#f4c94e" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="5" font-size="22">🚗</text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">E-Auto-Motor</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">150 kW · 0,15 MW</text>
</g>
<!-- 6 MW — Windrad -->
<g transform="translate(0, 155)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#5a8a5e" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="5" font-size="22">🌬</text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">Modernes Windrad</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">36 MW</text>
</g>
<!-- 1.400 MW (1,4 GW) — AKW-Block -->
<g transform="translate(0, 92)">
<line x1="420" y1="3" x2="435" y2="3" stroke="#4a7c8a" stroke-width="1.5"/>
<rect x="250" y="-18" width="170" height="40" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="265" y="5" font-size="22"></text>
<text x="300" y="-2" font-size="11" font-weight="800" fill="#1f4e5a">AKW-Block</text>
<text x="300" y="13" font-size="10" fill="#8a8a8a">1.400 MW = 1,4 GW</text>
</g>
</g>
<!-- Skala mit Einheit und Vielfachen rechts -->
<g font-family="Inter, system-ui, sans-serif" fill="#1f4e5a">
<!-- 1 W (10⁰) -->
<g transform="translate(465, 520)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#c85c4a" stroke-width="1.5"/>
<text x="22" y="3" font-size="11" font-weight="800">1 W</text>
<text x="22" y="16" font-size="9" fill="#8a8a8a">100 Watt</text>
</g>
<!-- 10 W (10¹) -->
<g transform="translate(465, 477)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#c85c4a" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800">10 W</text>
</g>
<!-- 100 W (10²) -->
<g transform="translate(465, 434)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#c85c4a" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800">100 W</text>
</g>
<!-- 1 kW (10³) -->
<g transform="translate(465, 391)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#e8833a" stroke-width="1.5"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#b8641d">1 kW</text>
<text x="22" y="16" font-size="9" fill="#8a8a8a">1.000 W</text>
</g>
<!-- 10 kW (10⁴) -->
<g transform="translate(465, 348)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#e8833a" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#b8641d">10 kW</text>
</g>
<!-- 100 kW (10⁵) -->
<g transform="translate(465, 305)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#e8833a" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#b8641d">100 kW</text>
</g>
<!-- 1 MW (10⁶) -->
<g transform="translate(465, 262)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#5a8a5e" stroke-width="1.5"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#3a6b3e">1 MW</text>
<text x="22" y="16" font-size="9" fill="#8a8a8a">1.000 kW · 1.000.000 W</text>
</g>
<!-- 10 MW (10⁷) -->
<g transform="translate(465, 219)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#5a8a5e" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#3a6b3e">10 MW</text>
</g>
<!-- 100 MW (10⁸) -->
<g transform="translate(465, 176)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#5a8a5e" stroke-width="1"/>
<text x="22" y="3" font-size="11" font-weight="800" fill="#3a6b3e">100 MW</text>
</g>
<!-- 1 GW (10⁹) -->
<g transform="translate(465, 133)">
<line x1="0" y1="0" x2="15" y2="0" stroke="#4a7c8a" stroke-width="1.5"/>
<text x="22" y="3" font-size="11" font-weight="800">1 GW</text>
<text x="22" y="16" font-size="9" fill="#8a8a8a">1.000 MW · 1 Mrd. W</text>
</g>
<!-- Weitere Beispiele rechts unten -->
<g transform="translate(600, 455)">
<rect x="0" y="-14" width="280" height="36" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="2" font-size="11" font-weight="800" fill="#1f4e5a">📱 Handy-Ladegerät</text>
<text x="10" y="16" font-size="10" fill="#8a8a8a">20 W — zwischen LED und Mensch</text>
</g>
<g transform="translate(600, 370)">
<rect x="0" y="-14" width="280" height="36" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="2" font-size="11" font-weight="800" fill="#1f4e5a">🏠 Hausdach-Solaranlage</text>
<text x="10" y="16" font-size="10" fill="#8a8a8a">10 kWp — deckt 2 Haushalte</text>
</g>
<g transform="translate(600, 283)">
<rect x="0" y="-14" width="280" height="36" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="2" font-size="11" font-weight="800" fill="#1f4e5a">⚡ Kraftwerk Freudenau (Donau)</text>
<text x="10" y="16" font-size="10" fill="#8a8a8a">172 MW — 230.000 Haushalte</text>
</g>
<g transform="translate(600, 196)">
<rect x="0" y="-14" width="280" height="36" rx="6" fill="#fff" stroke="#dae8ec"/>
<text x="10" y="2" font-size="11" font-weight="800" fill="#1f4e5a">🇦🇹 Österreich gesamt installiert</text>
<text x="10" y="16" font-size="10" fill="#8a8a8a">~29.000 MW = 29 GW</text>
</g>
</g>
<!-- Fußzeile Quellen -->
<g transform="translate(50, 540)">
<rect x="0" y="-14" width="800" height="28" rx="4" fill="#fff" stroke="#dae8ec"/>
<text x="12" y="4" font-size="10" font-weight="800" fill="#1f4e5a">Quellen:</text>
<text x="62" y="4" font-size="10" fill="#4a4a4a">E-Control Betriebsstatistik Strom 2023 · IG Windkraft Österreich · Hersteller-Angaben Haushaltsgeräte · Physik-Richtwert Muskelarbeit</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

@@ -1,149 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 520" font-family="Inter, system-ui, sans-serif" width="900" height="520">
<defs>
<linearGradient id="wr-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#eff5f6"/>
<stop offset="1" stop-color="#dae8ec"/>
</linearGradient>
</defs>
<!-- Hintergrund -->
<rect x="0" y="40" width="900" height="420" fill="url(#wr-sky)"/>
<!-- Boden -->
<rect x="0" y="440" width="900" height="20" fill="#5a8a5e"/>
<rect x="0" y="460" width="900" height="60" fill="#3a6b3e"/>
<text x="450" y="26" font-size="16" font-weight="800" fill="#1f4e5a" text-anchor="middle">
Wie groß ist ein modernes Windrad wirklich?
</text>
<!-- Vergleichsfiguren. Höhe aus Boden y=440 nach oben berechnet -->
<!-- SKALA: 1 m = ca. 1.4 px → Gesamthöhe sichtbar ~280 m -->
<!-- Boden = y=440, 1 m = 1.4 px → y = 440 - höhe*1.4 -->
<!-- 1) Mensch (1,8 m) -->
<g transform="translate(80, 437.5)">
<!-- Kopf+Körper Kompakt bei dieser Skala -->
<circle cx="0" cy="-2" r=".8" fill="#1f4e5a"/>
<rect x="-.6" y="-1.5" width="1.2" height="3" fill="#1f4e5a"/>
<text x="20" y="0" font-size="10" font-weight="700" fill="#1f4e5a">Mensch</text>
<text x="20" y="11" font-size="9" fill="#8a8a8a">1,8 m</text>
</g>
<!-- 2) Einfamilienhaus (8 m = 11px) -->
<g transform="translate(150, 440)">
<rect x="-12" y="-11" width="24" height="11" fill="#e8d5b5" stroke="#1f4e5a" stroke-width=".6"/>
<polygon points="-14,-11 0,-18 14,-11" fill="#c85c4a"/>
<rect x="-2" y="-6" width="4" height="6" fill="#4a7c8a"/>
<text x="30" y="-8" font-size="10" font-weight="700" fill="#1f4e5a">Einfamilienhaus</text>
<text x="30" y="3" font-size="9" fill="#8a8a8a">≈ 8 m</text>
</g>
<!-- 3) Baum (25 m = 35px) -->
<g transform="translate(250, 440)">
<rect x="-1.5" y="-10" width="3" height="10" fill="#6b4a2e"/>
<ellipse cx="0" cy="-22" rx="14" ry="22" fill="#3a6b3e"/>
<text x="25" y="-42" font-size="10" font-weight="700" fill="#1f4e5a">Alter Baum</text>
<text x="25" y="-31" font-size="9" fill="#8a8a8a">25 m</text>
</g>
<!-- 4) Kirchturm (60 m = 84px) -->
<g transform="translate(345, 440)">
<rect x="-8" y="-60" width="16" height="60" fill="#c4a97a" stroke="#1f4e5a" stroke-width=".6"/>
<rect x="-10" y="-60" width="20" height="4" fill="#c85c4a"/>
<polygon points="-10,-60 0,-84 10,-60" fill="#c85c4a"/>
<rect x="-2" y="-48" width="4" height="8" fill="#1a1a1a"/>
<circle cx="0" cy="-68" r="3" fill="#e8d5b5"/>
<text x="20" y="-80" font-size="10" font-weight="700" fill="#1f4e5a">Kirchturm</text>
<text x="20" y="-69" font-size="9" fill="#8a8a8a">≈ 60 m</text>
</g>
<!-- 5) Altes Windrad (60 m) -->
<g transform="translate(440, 440)">
<rect x="-2" y="-84" width="4" height="84" fill="#8a8a8a"/>
<circle cx="0" cy="-84" r="2.5" fill="#1f4e5a"/>
<!-- 3 Rotorblätter, L ≈ 22m -->
<g stroke="#1f4e5a" stroke-width="2" stroke-linecap="round">
<line x1="0" y1="-84" x2="0" y2="-115"/>
<line x1="0" y1="-84" x2="27" y2="-69"/>
<line x1="0" y1="-84" x2="-27" y2="-69"/>
</g>
<text x="32" y="-112" font-size="10" font-weight="700" fill="#1f4e5a">Windrad 2000</text>
<text x="32" y="-100" font-size="9" fill="#8a8a8a">Nabe 60 m · 1 MW</text>
</g>
<!-- 6) DC Tower Wien (220 m = 308 px) -->
<g transform="translate(580, 440)">
<rect x="-12" y="-308" width="24" height="308" fill="#4a7c8a" stroke="#1f4e5a" stroke-width=".6"/>
<g fill="#e8d5b5" opacity=".75">
<rect x="-10" y="-300" width="20" height="3"/>
<rect x="-10" y="-280" width="20" height="3"/>
<rect x="-10" y="-260" width="20" height="3"/>
<rect x="-10" y="-240" width="20" height="3"/>
<rect x="-10" y="-220" width="20" height="3"/>
<rect x="-10" y="-200" width="20" height="3"/>
<rect x="-10" y="-180" width="20" height="3"/>
<rect x="-10" y="-160" width="20" height="3"/>
<rect x="-10" y="-140" width="20" height="3"/>
<rect x="-10" y="-120" width="20" height="3"/>
<rect x="-10" y="-100" width="20" height="3"/>
<rect x="-10" y="-80" width="20" height="3"/>
<rect x="-10" y="-60" width="20" height="3"/>
<rect x="-10" y="-40" width="20" height="3"/>
</g>
<text x="18" y="-304" font-size="10" font-weight="700" fill="#1f4e5a">DC Tower Wien</text>
<text x="18" y="-293" font-size="9" fill="#8a8a8a">220 m (höchstes AT)</text>
<line x1="-14" y1="-308" x2="20" y2="-308" stroke="#4a7c8a" stroke-width="1" stroke-dasharray="2 2"/>
</g>
<!-- 7) Modernes Windrad (240 m Gesamthöhe: Nabe 160m + Rotor 80m) -->
<g transform="translate(770, 440)">
<!-- Turm -->
<polygon points="-4,0 4,0 2.5,-224 -2.5,-224" fill="#fff" stroke="#1f4e5a" stroke-width="1"/>
<!-- Gondel (Maschinenhaus) -->
<rect x="-6" y="-228" width="12" height="8" fill="#1f4e5a" rx="1"/>
<!-- Nabe -->
<circle cx="0" cy="-224" r="3.5" fill="#c85c4a"/>
<!-- 3 Rotorblätter, L = 85 m = 119 px -->
<g stroke="#1f4e5a" stroke-width="2.6" stroke-linecap="round" fill="none">
<line x1="0" y1="-224" x2="0" y2="-343"/>
<line x1="0" y1="-224" x2="103" y2="-164"/>
<line x1="0" y1="-224" x2="-103" y2="-164"/>
</g>
<!-- Maß-Pfeil Gesamthöhe -->
<line x1="80" y1="-343" x2="80" y2="0" stroke="#c85c4a" stroke-width="1" stroke-dasharray="3 2"/>
<polygon points="78,-340 82,-340 80,-348" fill="#c85c4a"/>
<polygon points="78,-3 82,-3 80,5" fill="#c85c4a"/>
<text x="87" y="-170" font-size="11" fill="#c85c4a" font-weight="800">240 m</text>
<text x="87" y="-156" font-size="9" fill="#c85c4a">Gesamthöhe</text>
<text x="-125" y="-338" font-size="10" font-weight="700" fill="#1f4e5a">Modernes Windrad</text>
<text x="-125" y="-326" font-size="9" fill="#8a8a8a">Nabe 160 m · 7 MW</text>
<text x="-125" y="-313" font-size="9" fill="#5a8a5e" font-weight="700">5.000 Haushalte</text>
</g>
<!-- Höhenlinien im Hintergrund -->
<g stroke="#4a7c8a" stroke-width=".5" opacity=".25" stroke-dasharray="2 3">
<line x1="30" y1="440" x2="870" y2="440"/>
<line x1="30" y1="356" x2="870" y2="356"/> <!-- 60 m -->
<line x1="30" y1="272" x2="870" y2="272"/> <!-- 120 m -->
<line x1="30" y1="216" x2="870" y2="216"/> <!-- 160 m -->
<line x1="30" y1="132" x2="870" y2="132"/> <!-- 220 m -->
<line x1="30" y1="97" x2="870" y2="97"/> <!-- 245 m -->
</g>
<g font-size="8" fill="#4a7c8a" opacity=".7">
<text x="35" y="358">60 m</text>
<text x="35" y="274">120 m</text>
<text x="35" y="218">160 m (Nabe)</text>
<text x="35" y="134">220 m</text>
</g>
<!-- Footer Fakten -->
<g transform="translate(0, 465)">
<rect x="50" y="0" width="800" height="50" rx="6" fill="#fff" stroke="#dae8ec" stroke-width="1"/>
<text x="70" y="18" font-size="10" fill="#1f4e5a" font-weight="800">Ein Windrad liefert:</text>
<text x="185" y="18" font-size="10" fill="#4a4a4a">820 Millionen kWh pro Jahr — Strom für 2.500 bis 6.000 Haushalte.</text>
<text x="70" y="36" font-size="10" fill="#1f4e5a" font-weight="800">Österreich 2024:</text>
<text x="185" y="36" font-size="10" fill="#4a4a4a">ca. 1.400 Windräder · zusammen rund 3.900 MW · decken ~12 % des Strombedarfs.</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

-583
View File
@@ -1,583 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.00 0.00 1008.00 159.00">
<path fill="#2eabac" d="
M 639.6017 14.2979
A 14.14 13.50 -179.1 0 1 653.9520 1.0217
A 14.14 13.50 -179.1 0 1 667.8783 14.7421
A 14.14 13.50 -179.1 0 1 653.5280 28.0183
A 14.14 13.50 -179.1 0 1 639.6017 14.2979
Z"
/>
<path fill="#f18215" d="
M 958.91 93.20
L 958.90 92.29
Q 958.76 91.36 959.23 90.70
A 0.81 0.77 -28.5 0 0 959.38 90.24
L 959.38 60.73
A 0.63 0.63 0.0 0 0 958.75 60.10
L 950.20 60.10
A 1.55 1.55 0.0 0 1 948.65 58.55
L 948.65 43.17
A 0.80 0.79 90.0 0 1 949.44 42.37
L 957.55 42.37
A 1.36 1.36 0.0 0 0 958.91 41.01
L 958.91 23.73
A 0.27 0.25 83.1 0 1 959.10 23.47
Q 959.34 23.41 959.37 23.39
A 0.26 0.26 0.0 0 0 959.36 22.95
Q 959.26 22.90 959.20 22.74
A 0.15 0.15 0.0 0 1 959.29 22.55
Q 960.93 21.96 961.51 21.95
Q 971.27 21.86 981.52 21.90
A 1.98 1.97 -90.0 0 1 983.49 23.88
L 983.49 41.17
A 1.17 1.17 0.0 0 0 984.66 42.34
L 1002.66 42.34
A 1.42 1.42 0.0 0 1 1004.08 43.76
L 1004.08 58.54
A 1.86 1.86 0.0 0 1 1002.22 60.40
L 984.13 60.40
A 0.56 0.56 0.0 0 0 983.57 60.96
L 983.57 97.43
A 2.30 2.21 35.8 0 0 983.71 98.21
Q 985.24 102.41 990.20 104.08
Q 991.53 104.53 993.32 104.01
Q 994.25 103.75 995.46 103.86
Q 996.27 103.93 997.50 103.40
Q 999.72 102.43 1001.78 101.40
A 0.56 0.55 67.1 0 1 1002.55 101.72
L 1007.39 116.00
A 1.19 1.18 65.2 0 1 1006.88 117.40
Q 998.23 122.64 989.50 123.28
C 975.60 124.30 963.82 118.37 960.38 104.37
Q 959.76 101.88 958.91 93.20
Z"
/>
<path fill="#143b4b" d="
M 67.41 42.82
Q 67.57 44.51 68.77 45.22
A 0.48 0.47 -63.5 0 0 69.45 44.99
Q 69.99 43.66 69.11 42.97
L 69.59 35.41
A 1.67 1.66 -88.2 0 1 71.25 33.85
L 92.64 33.85
A 1.17 1.16 90.0 0 1 93.80 35.02
Q 93.69 86.70 93.74 113.26
Q 93.75 118.58 93.38 121.21
Q 92.39 128.25 92.09 128.96
Q 91.03 131.40 90.53 134.27
Q 90.47 134.59 90.31 134.68
Q 90.25 134.72 90.09 134.81
A 0.63 0.60 86.4 0 0 89.81 135.14
C 86.62 144.38 77.88 151.31 69.02 154.27
Q 67.28 154.86 63.72 155.90
A 6.38 5.92 33.1 0 1 62.32 156.14
C 58.05 156.41 53.99 157.54 49.73 157.52
Q 43.78 157.49 40.03 157.41
A 3.20 3.15 55.0 0 1 39.17 157.25
Q 35.67 156.06 31.76 156.37
A 0.44 0.42 78.2 0 1 31.33 156.08
Q 31.31 156.00 31.30 155.87
A 0.26 0.25 -88.7 0 0 31.09 155.64
Q 21.55 154.04 12.55 148.99
Q 10.82 148.02 9.28 146.62
A 1.00 0.99 -57.7 0 1 9.03 145.50
L 15.62 129.71
A 0.33 0.33 0.0 0 1 16.21 129.68
Q 16.57 130.34 18.08 130.83
Q 18.64 131.01 19.87 131.73
Q 27.47 136.20 36.14 137.70
A 1.12 0.17 35.4 0 1 36.77 138.02
Q 36.90 138.10 37.12 138.12
C 44.49 138.82 51.75 139.33 57.73 136.54
Q 67.37 132.04 69.05 120.63
Q 69.88 115.05 69.13 108.72
Q 69.67 107.54 69.31 106.46
A 0.46 0.45 -23.5 0 0 68.66 106.21
Q 67.36 106.90 68.02 108.02
C 66.49 109.05 64.69 109.93 63.40 111.10
Q 58.45 115.60 53.07 117.28
Q 43.27 120.35 32.52 118.35
Q 22.18 116.43 14.40 108.89
Q 5.16 99.95 1.94 86.58
Q 1.12 83.15 1.40 82.29
Q 1.44 82.18 0.90 79.71
C 0.20 76.51 0.23 71.00 0.71 69.44
Q 1.42 67.11 1.48 64.62
A 5.99 5.85 -36.9 0 1 1.73 62.99
Q 2.76 59.43 3.93 56.68
Q 8.42 46.12 17.16 38.91
Q 21.44 35.38 27.76 33.50
Q 39.41 30.04 51.35 32.59
A 1.93 0.17 24.3 0 1 52.29 32.92
Q 52.81 33.14 54.34 33.65
Q 61.75 36.09 66.46 42.31
Q 66.65 42.56 67.41 42.82
Z
M 41.28 97.88
Q 45.12 99.32 49.34 98.77
A 0.31 0.31 0.0 0 0 49.59 98.58
Q 49.66 98.42 49.63 98.30
C 66.86 97.37 70.27 80.00 66.73 66.48
Q 64.46 57.76 56.56 53.80
Q 55.42 53.23 54.20 53.13
Q 53.25 53.05 51.69 52.40
A 2.21 2.11 57.7 0 0 51.05 52.24
L 44.30 51.73
A 3.45 3.44 -48.9 0 0 43.29 51.80
Q 31.02 54.52 27.61 66.79
Q 24.74 77.10 28.51 86.66
Q 29.45 89.03 31.14 91.04
Q 32.09 92.18 34.70 94.56
Q 36.93 96.60 41.28 97.88
Z"
/>
<g stroke-width="2.00" fill="none" stroke-linecap="butt">
<path stroke="#21737c" vector-effect="non-scaling-stroke" d="
M 41.28 97.88
Q 45.12 99.32 49.34 98.77
A 0.31 0.31 0.0 0 0 49.59 98.58
Q 49.66 98.42 49.63 98.30"
/>
<path stroke="#21737c" vector-effect="non-scaling-stroke" d="
M 45.79 97.86
L 48.46 97.90"
/>
</g>
<path fill="#143b4b" d="
M 192.95 85.39
Q 178.82 85.45 157.50 85.33
Q 155.77 85.32 151.57 85.02
Q 142.07 84.34 132.86 85.35
A 0.59 0.59 0.0 0 0 132.34 85.96
Q 132.53 90.28 134.78 94.27
Q 137.08 98.34 141.21 101.19
Q 144.64 103.55 150.01 104.45
Q 154.96 105.28 160.47 104.45
Q 165.36 103.71 169.80 101.09
Q 174.10 98.55 177.84 95.10
A 0.86 0.86 0.0 0 1 179.08 95.16
L 190.77 108.35
A 0.58 0.57 46.9 0 1 190.75 109.14
Q 180.17 119.66 165.73 122.39
Q 155.72 124.28 144.99 122.56
Q 139.45 121.67 135.82 120.51
C 121.41 115.89 111.51 102.48 108.29 88.04
Q 107.41 84.10 107.44 78.84
Q 107.48 71.48 107.63 69.57
Q 107.95 65.39 110.59 58.25
Q 110.78 57.73 111.25 57.43
C 111.60 57.20 111.53 56.10 112.02 55.29
Q 118.26 45.16 125.03 39.78
Q 130.26 35.62 139.36 32.95
Q 146.36 30.89 157.27 31.65
Q 176.28 32.98 187.63 48.73
C 189.34 51.10 190.64 54.61 192.17 57.55
A 2.59 2.58 28.5 0 1 192.44 58.46
Q 192.55 59.69 193.13 60.80
C 194.13 62.73 194.40 66.29 194.72 67.54
C 195.92 72.22 195.49 77.76 195.17 83.28
A 2.24 2.23 -88.5 0 1 192.95 85.39
Z
M 133.58 69.33
L 171.04 69.39
A 0.65 0.65 0.0 0 0 171.69 68.74
L 171.70 67.91
A 17.58 17.19 -89.9 0 0 154.54 50.30
L 150.16 50.30
A 17.58 17.19 -89.9 0 0 132.94 67.85
L 132.93 68.68
A 0.65 0.65 0.0 0 0 133.58 69.33
Z"
/>
<path fill="#143b4b" d="
M 298.47 76.50
Q 298.50 78.06 298.47 78.76
Q 297.40 103.35 278.53 116.04
C 268.92 122.50 257.43 124.36 245.81 123.52
C 229.83 122.36 216.95 114.22 209.23 100.53
Q 205.68 94.23 204.75 87.75
C 204.28 84.45 203.66 82.06 203.58 78.69
C 203.51 75.33 204.01 72.91 204.33 69.60
Q 204.96 63.08 208.21 56.62
C 215.29 42.59 227.78 33.86 243.69 31.96
C 255.26 30.59 266.82 31.91 276.72 37.92
Q 296.16 49.73 298.37 74.24
Q 298.43 74.93 298.47 76.50
Z
M 251.43 103.41
Q 252.56 103.40 252.99 103.34
Q 267.97 101.38 271.69 87.03
Q 273.13 81.48 272.91 75.25
C 272.85 73.37 272.15 71.97 271.99 70.25
Q 271.82 68.46 271.16 66.52
Q 266.90 54.12 253.47 51.91
Q 252.49 51.74 250.76 51.76
Q 249.04 51.79 248.06 51.97
Q 234.69 54.53 230.75 67.04
Q 230.14 68.99 230.02 70.79
C 229.90 72.51 229.24 73.93 229.23 75.81
Q 229.17 82.04 230.75 87.55
Q 234.83 101.80 249.86 103.38
Q 250.29 103.43 251.43 103.41
Z"
/>
<path fill="#143b4b" d="
M 372.63 42.80
Q 373.09 44.04 374.13 44.66
A 0.61 0.61 0.0 0 0 375.05 44.16
Q 375.09 43.19 374.79 42.79
L 375.19 35.55
A 1.28 1.28 0.0 0 1 376.47 34.34
L 397.58 34.34
A 1.81 1.80 89.8 0 1 399.38 36.14
Q 399.47 48.02 399.43 113.92
Q 399.42 116.72 399.10 119.32
Q 398.80 121.79 398.91 124.20
A 3.19 3.18 52.0 0 1 398.79 125.20
C 397.71 129.15 396.61 133.40 395.01 136.74
Q 388.84 149.66 374.74 154.74
Q 369.67 156.57 366.43 156.62
Q 366.00 156.62 365.13 157.19
A 2.01 2.00 -62.8 0 1 364.17 157.50
Q 356.13 158.11 344.76 157.62
Q 342.98 157.55 340.49 156.77
Q 338.25 156.08 336.00 156.39
Q 334.87 156.55 334.61 155.74
A 0.68 0.67 79.4 0 0 333.93 155.27
C 331.48 155.38 329.83 153.78 327.38 153.45
Q 326.80 153.37 325.48 152.82
Q 319.45 150.29 314.70 146.91
A 0.40 0.39 -60.9 0 1 314.57 146.45
L 321.31 130.29
A 0.80 0.80 0.0 0 1 322.49 129.93
Q 330.93 135.49 340.51 138.01
C 342.61 138.56 344.90 138.16 346.59 139.06
A 2.23 2.12 -27.0 0 0 347.43 139.31
Q 355.50 139.94 360.87 137.84
C 372.77 133.20 376.49 121.02 374.43 109.31
Q 375.10 108.33 374.77 107.56
A 0.53 0.53 0.0 0 0 374.03 107.29
Q 372.87 107.87 373.26 109.10
Q 372.01 109.43 371.40 109.91
Q 366.36 113.95 362.80 116.04
Q 358.47 118.58 351.23 119.55
Q 347.21 120.09 340.45 119.28
Q 334.71 118.60 330.17 116.22
Q 322.44 112.15 316.65 105.39
Q 311.27 99.12 308.62 90.15
Q 305.04 78.07 307.65 64.67
Q 309.72 54.03 317.44 44.70
Q 320.61 40.87 323.23 39.00
Q 334.95 30.64 349.27 31.58
Q 353.39 31.85 357.78 32.70
Q 358.06 32.76 358.34 33.06
A 1.08 1.03 -10.3 0 0 358.78 33.35
C 364.56 35.41 367.66 38.28 372.63 42.80
Z
M 360.30 97.84
Q 368.00 95.55 370.77 89.71
Q 376.54 77.54 371.88 64.44
Q 369.26 57.08 361.16 53.58
A 3.73 3.56 -27.9 0 0 360.24 53.32
Q 358.49 53.08 354.88 52.18
C 352.45 51.57 346.97 52.99 345.36 53.57
C 335.30 57.15 331.73 67.60 331.91 77.61
C 331.96 80.25 333.18 83.33 333.66 85.50
Q 334.28 88.32 336.11 90.96
Q 340.54 97.33 348.03 99.10
Q 354.15 100.55 359.72 98.05
A 4.42 3.10 -55.0 0 1 360.30 97.84
Z"
/>
<path fill="#143b4b" d="
M 441.02 47.80
Q 440.58 48.79 440.61 49.38
Q 440.69 50.66 441.73 49.73
Q 442.41 49.12 442.42 47.55
Q 443.24 47.23 443.44 46.90
Q 451.32 33.98 466.77 34.56
A 1.16 1.16 0.0 0 1 467.62 34.98
Q 468.61 36.17 468.44 38.02
C 468.05 42.53 468.53 45.49 468.31 49.65
Q 468.09 53.61 467.85 56.06
A 1.29 1.29 0.0 0 1 466.50 57.22
Q 457.84 56.84 450.53 61.01
C 445.94 63.63 443.22 68.90 441.76 74.10
Q 440.80 77.49 440.79 83.51
Q 440.73 105.64 440.80 120.30
A 1.25 1.24 85.7 0 1 439.75 121.53
L 436.28 122.07
A 0.48 0.48 0.0 0 1 435.92 121.98
Q 435.16 121.44 431.23 121.72
Q 430.42 121.78 430.31 121.94
Q 430.04 122.36 429.78 121.89
A 0.42 0.40 75.0 0 0 429.42 121.67
L 418.20 121.67
A 1.44 1.43 0.0 0 1 416.76 120.24
L 416.76 37.10
A 0.83 0.83 0.0 0 1 417.59 36.27
L 439.62 36.27
A 0.65 0.65 0.0 0 1 440.27 36.88
L 441.02 47.80
Z"
/>
<path fill="#143b4b" d="
M 526.35 114.30
Q 526.92 113.68 526.71 112.96
A 0.79 0.79 0.0 0 0 525.20 112.93
Q 524.89 113.79 524.97 114.23
Q 519.11 119.08 517.02 120.07
Q 508.73 124.01 495.47 123.34
A 4.12 4.10 56.5 0 1 494.21 123.08
Q 492.64 122.50 490.34 122.50
A 3.80 3.79 54.9 0 1 489.04 122.27
Q 486.31 121.25 484.61 120.42
Q 479.37 117.87 475.87 113.39
C 471.33 107.58 470.49 99.53 471.92 92.45
Q 472.98 87.13 476.33 83.19
Q 479.63 79.29 484.62 77.11
Q 487.75 75.75 490.48 75.03
C 496.58 73.43 501.67 72.52 507.97 72.51
Q 523.34 72.50 524.81 72.44
A 0.78 0.77 -87.3 0 0 525.54 71.77
Q 526.88 62.40 519.65 58.29
Q 513.12 54.57 505.51 55.82
Q 500.48 56.64 496.82 57.71
Q 493.63 58.66 493.43 58.84
Q 492.61 59.60 491.64 59.53
Q 490.89 59.49 490.50 60.11
Q 490.16 60.66 489.20 60.57
A 0.75 0.74 -76.2 0 0 488.46 61.02
Q 488.19 61.69 487.32 61.56
A 1.12 1.10 25.9 0 0 486.37 61.88
Q 485.45 62.83 485.04 62.74
A 3.67 3.18 -87.4 0 1 482.54 59.57
Q 482.43 58.38 481.94 57.57
Q 481.16 56.28 479.23 51.82
Q 478.16 49.35 477.53 48.69
Q 477.42 48.58 476.93 47.35
A 1.09 1.09 0.0 0 1 477.35 46.02
Q 484.58 41.32 492.72 39.00
Q 509.16 34.31 524.70 37.50
Q 539.91 40.63 546.54 54.20
Q 549.78 60.83 549.78 68.48
Q 549.77 99.53 549.79 111.51
A 4.52 4.23 -53.4 0 0 549.90 112.49
Q 550.64 116.02 550.23 120.17
A 1.67 1.67 0.0 0 1 548.57 121.67
L 528.06 121.67
A 1.55 1.55 0.0 0 1 526.51 120.16
L 526.35 114.30
Z
M 495.68 99.88
Q 496.32 102.01 497.84 103.28
Q 498.35 103.71 500.81 104.92
C 506.75 107.84 515.11 107.11 520.30 102.78
Q 526.48 97.63 525.55 88.08
A 0.77 0.76 -1.7 0 0 524.81 87.39
Q 517.19 87.17 506.47 87.29
Q 500.18 87.36 496.92 90.84
A 3.64 3.51 -11.2 0 0 496.30 91.73
Q 494.39 95.59 495.68 99.88
Z"
/>
<path fill="#2eabac" d="
M 570.30 97.97
C 579.68 103.02 588.05 107.23 598.99 106.55
C 602.59 106.33 606.61 104.04 606.49 99.90
C 606.37 96.00 601.94 92.74 598.58 91.69
Q 587.97 88.41 580.70 85.37
Q 574.37 82.73 569.31 77.87
C 562.15 71.02 561.61 60.69 566.14 52.23
C 571.37 42.49 580.25 37.66 591.03 36.57
Q 610.68 34.60 626.41 46.30
A 0.97 0.97 0.0 0 1 626.67 47.57
L 619.12 60.65
A 0.64 0.64 0.0 0 1 618.24 60.89
C 609.57 55.88 597.81 50.23 587.92 56.15
A 3.16 3.16 0.0 0 0 586.43 58.34
Q 585.39 64.45 591.14 66.89
C 600.34 70.81 612.97 73.58 621.57 81.02
C 629.07 87.50 629.24 95.13 628.04 104.50
A 3.88 3.61 61.4 0 1 627.80 105.44
C 623.68 116.26 612.78 121.89 601.73 123.09
Q 584.19 124.99 567.59 116.67
Q 563.80 114.77 560.46 111.68
A 0.59 0.58 39.6 0 1 560.38 110.90
L 569.57 98.14
A 0.57 0.57 0.0 0 1 570.30 97.97
Z"
/>
<path fill="#2eabac" d="
M 682.39 120.98
Q 681.90 118.57 681.89 117.28
Q 681.41 77.58 681.79 40.05
A 1.63 1.63 0.0 0 1 683.42 38.43
L 704.85 38.43
A 0.65 0.64 0.0 0 1 705.50 39.07
L 705.50 48.36
A 0.50 0.50 0.0 0 0 705.98 48.86
C 707.21 48.91 707.75 48.80 708.56 47.74
C 715.99 38.07 728.73 34.30 740.36 38.23
Q 749.41 41.28 755.48 50.15
A 1.61 1.61 0.0 0 0 758.09 50.22
C 764.84 41.37 775.23 36.30 786.02 36.57
Q 795.86 36.82 802.81 42.55
C 810.28 48.71 812.84 56.21 814.30 65.65
Q 814.75 68.58 814.55 73.88
Q 814.40 77.85 814.51 85.00
Q 814.76 100.98 814.59 120.17
A 1.44 1.43 -89.8 0 1 813.16 121.60
L 790.84 121.60
A 0.55 0.55 0.0 0 1 790.29 121.02
Q 790.49 117.64 790.26 115.99
Q 789.91 113.42 789.91 110.99
Q 789.96 77.88 789.80 71.50
C 789.70 67.36 787.29 62.54 783.56 60.02
C 779.63 57.37 771.68 58.27 767.77 60.48
C 759.68 65.04 760.71 77.86 760.66 86.12
Q 760.57 102.06 760.66 121.12
A 0.34 0.33 -0.8 0 1 760.32 121.46
L 737.53 121.46
A 1.00 0.99 0.0 0 1 736.53 120.47
Q 736.60 92.20 736.44 75.26
C 736.34 64.41 731.27 57.60 719.74 58.17
C 709.84 58.67 706.30 67.27 706.34 75.93
Q 706.45 99.49 706.40 120.53
A 0.91 0.91 0.0 0 1 705.49 121.44
L 682.94 121.44
A 0.57 0.56 84.4 0 1 682.39 120.98
Z"
/>
<path fill="#2eabac" d="
M 665.57 120.36
A 1.25 1.25 0.0 0 1 664.32 121.61
L 642.64 121.61
A 1.25 1.25 0.0 0 1 641.39 120.36
L 641.39 39.50
A 1.25 1.25 0.0 0 1 642.64 38.25
L 664.32 38.25
A 1.25 1.25 0.0 0 1 665.57 39.50
L 665.57 120.36
Z"
/>
<path fill="#f18215" d="
M 915.55 73.16
C 915.76 66.63 914.22 61.35 907.77 58.97
Q 907.40 58.84 901.88 57.60
A 7.50 7.37 -40.8 0 0 899.55 57.45
Q 893.26 58.02 887.50 59.40
C 883.22 60.42 877.98 63.20 874.53 64.55
A 0.33 0.32 -24.1 0 1 874.14 64.41
L 865.94 50.21
A 1.01 1.00 -30.4 0 1 866.30 48.84
C 878.38 41.70 890.91 37.65 905.24 38.34
C 919.04 39.01 932.19 46.29 937.18 59.60
Q 939.51 65.84 939.48 74.01
Q 939.36 103.96 939.49 120.90
A 0.72 0.72 0.0 0 1 938.77 121.62
L 917.23 121.62
A 0.81 0.81 0.0 0 1 916.42 120.81
L 916.42 115.34
A 1.41 1.41 0.0 0 0 914.06 114.30
C 910.30 117.76 907.24 120.23 902.51 121.76
Q 894.21 124.46 885.52 123.48
C 873.42 122.11 863.05 114.55 861.55 101.69
Q 860.63 93.81 865.30 86.88
C 870.58 79.06 882.88 75.38 891.99 74.49
A 2.55 1.91 -55.8 0 0 892.92 74.17
C 894.07 73.48 904.71 73.86 914.91 73.78
A 0.64 0.64 0.0 0 0 915.55 73.16
Z
M 915.40 89.52
A 0.35 0.35 0.0 0 0 915.05 89.20
L 893.02 89.20
A 4.50 4.31 -53.3 0 0 891.59 89.44
Q 883.19 92.34 885.91 100.81
Q 887.20 104.81 890.50 105.97
Q 898.06 108.62 906.16 106.51
Q 910.68 105.33 913.45 100.02
Q 915.89 95.33 915.40 89.52
Z"
/>
<path fill="#2eabac" d="
M 69.11 42.97
Q 69.99 43.66 69.45 44.99
A 0.48 0.47 -63.5 0 1 68.77 45.22
Q 67.57 44.51 67.41 42.82
Q 67.88 42.68 69.11 42.97
Z"
/>
<path fill="#2eabac" d="
M 374.79 42.79
Q 375.09 43.19 375.05 44.16
A 0.61 0.61 0.0 0 1 374.13 44.66
Q 373.09 44.04 372.63 42.80
L 374.79 42.79
Z"
/>
<path fill="#2eabac" d="
M 442.42 47.55
Q 442.41 49.12 441.73 49.73
Q 440.69 50.66 440.61 49.38
Q 440.58 48.79 441.02 47.80
L 442.42 47.55
Z"
/>
<path fill="#143b4b" d="
M 958.90 92.29
L 958.91 93.20
Q 958.83 92.77 958.90 92.29
Z"
/>
<path fill="#2eabac" d="
M 45.79 97.86
L 48.46 97.90
L 49.63 98.30
Q 49.66 98.42 49.59 98.58
A 0.31 0.31 0.0 0 1 49.34 98.77
Q 45.12 99.32 41.28 97.88
L 45.79 97.86
Z"
/>
<path fill="#143b4b" d="
M 48.46 97.90
L 45.79 97.86
L 48.46 97.90
Z"
/>
<path fill="#f18215" d="
M 827.5821 107.0823
A 12.87 12.44 -164.6 0 1 843.2935 98.5067
A 12.87 12.44 -164.6 0 1 852.3979 113.9177
A 12.87 12.44 -164.6 0 1 836.6865 122.4933
A 12.87 12.44 -164.6 0 1 827.5821 107.0823
Z"
/>
<path fill="#2eabac" d="
M 69.13 108.72
L 68.02 108.02
Q 67.36 106.90 68.66 106.21
A 0.46 0.45 -23.5 0 1 69.31 106.46
Q 69.67 107.54 69.13 108.72
Z"
/>
<path fill="#2eabac" d="
M 374.43 109.31
Q 374.10 109.00 373.26 109.10
Q 372.87 107.87 374.03 107.29
A 0.53 0.53 0.0 0 1 374.77 107.56
Q 375.10 108.33 374.43 109.31
Z"
/>
<path fill="#2eabac" d="
M 526.35 114.30
L 524.97 114.23
Q 524.89 113.79 525.20 112.93
A 0.79 0.79 0.0 0 1 526.71 112.96
Q 526.92 113.68 526.35 114.30
Z"
/>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

-547
View File
@@ -1,547 +0,0 @@
/**
* Glossar-Experimente — kleine interaktive Widgets im Detail-Modal.
*
* Registrierung: window.GlossarExperiments[key_slug] = function (root) { … }
* Der Renderer (glossar.php) hängt einen leeren Container ein und ruft die
* Funktion mit diesem Container als einzigem Argument auf. Das Widget baut
* selbst seinen DOM und bindet seine Events.
*
* Richtlinien:
* - Keine externen Libraries.
* - Mobile-/Tap-freundlich: grosse Buttons, keine Hover-Abhängigkeit.
* - Zahlen quellenbar, kurze Begründung in der UI sichtbar.
*/
(function () {
'use strict';
const NS = 'http://www.w3.org/2000/svg';
const svgEl = (tag, attrs, parent) => {
const el = document.createElementNS(NS, tag);
if (attrs) for (const k in attrs) el.setAttribute(k, attrs[k]);
if (parent) parent.appendChild(el);
return el;
};
// =====================================================================
// Experiment: kWh-Rennen — wie weit kommt man mit 1 Kilowattstunde?
// =====================================================================
function kwhRace(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🏁 Das kWh-Rennen</h3>
<p>Drei Fahrzeuge starten rechts mit <strong>derselben Energie</strong>: 1 Kilowattstunde. Wie weit kommen sie nach links?</p>
</div>
<svg class="ge-track" viewBox="0 0 600 320" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
<div class="ge-controls">
<button class="ge-btn ge-btn-primary" data-act="start">▶ Start</button>
<button class="ge-btn" data-act="reset">↺ Zurück</button>
</div>
<ul class="ge-legend">
<li><span class="ge-dot" style="background:#5a8a5e"></span>E-Fahrrad · <strong>10 Wh/km</strong> → ca. 100 km</li>
<li><span class="ge-dot" style="background:#4a7c8a"></span>E-Auto · <strong>150 Wh/km</strong> → ca. 6,5 km</li>
<li><span class="ge-dot" style="background:#c85c4a"></span>Benzin-Auto · <strong>530 Wh/km</strong> aus Kraftstoffenergie → ca. 1,9 km</li>
</ul>
<p class="ge-note">Quellen: ADAC Stromverbrauchstests E-Auto · Hersteller-Angaben E-Bike Bosch Performance · WLTP Benziner 6 L/100 km × 8,8 kWh/L. Der Benziner verliert rund 70 % der Kraftstoffenergie als Motor-Wärme — deshalb kommt er weniger weit.</p>
</div>
`;
const svg = root.querySelector('.ge-track');
// Emoji-Fahrzeuge: auf Windows/Chrome schauen 🚴 🚗 🚙 nach links → sie fahren
// von rechts nach links, Emojis passen zur Fahrtrichtung ohne Plattform-Trick.
const vehicles = [
{ label: 'E-Fahrrad', emoji: '🚴', km: 100, color: '#5a8a5e', y: 100 },
{ label: 'E-Auto', emoji: '🚗', km: 6.5, color: '#4a7c8a', y: 190 },
{ label: 'Benzin-Auto', emoji: '🚙', km: 1.9, color: '#c85c4a', y: 280 }
];
const MAX_KM = 100;
const TRACK_L = 50, TRACK_R = 560;
const trackLen = TRACK_R - TRACK_L;
// Skala oben — Start rechts (0 km), Ziel links (100 km)
const axis = svgEl('g', { class: 'ge-axis' }, svg);
svgEl('line', { x1: TRACK_L, y1: 52, x2: TRACK_R, y2: 52, stroke: '#1f4e5a', 'stroke-width': '1.2' }, axis);
[0, 25, 50, 75, 100].forEach(km => {
const x = TRACK_R - (km / MAX_KM) * trackLen;
svgEl('line', { x1: x, y1: 48, x2: x, y2: 56, stroke: '#1f4e5a', 'stroke-width': '1' }, axis);
const t = svgEl('text', { x, y: 40, 'text-anchor': 'middle', 'font-size': '11', fill: '#4a4a4a', 'font-weight': '600' }, axis);
t.textContent = km + ' km';
});
// „Start" Marker ganz rechts
const startTxt = svgEl('text', { x: TRACK_R, y: 20, 'text-anchor': 'end', 'font-size': '11', fill: '#1f4e5a', 'font-weight': '700' }, svg);
startTxt.textContent = '← Start mit 1 kWh';
// Spuren + Fahrzeuge
const nodes = vehicles.map(v => {
const g = svgEl('g', { class: 'ge-lane' }, svg);
// Label ÜBER der Spur, rechts beim Start
const label = svgEl('text', { x: TRACK_R, y: v.y - 22, 'text-anchor': 'end', 'font-size': '12', 'font-weight': '800', fill: v.color }, g);
label.textContent = v.label;
// Straßenlinie
svgEl('line', { x1: TRACK_L, y1: v.y, x2: TRACK_R, y2: v.y, stroke: '#dae8ec', 'stroke-width': '5', 'stroke-linecap': 'round' }, g);
// Ziel-Markierung (links vom Start)
const xEnd = TRACK_R - (v.km / MAX_KM) * trackLen;
svgEl('line', { x1: xEnd, y1: v.y - 16, x2: xEnd, y2: v.y + 16, stroke: v.color, 'stroke-width': '2', 'stroke-dasharray': '3 2', opacity: '.55' }, g);
// Emoji-Fahrzeug
const icon = svgEl('text', { x: TRACK_R, y: v.y + 8, 'text-anchor': 'middle', 'font-size': '30' }, g);
icon.textContent = v.emoji;
// Ergebnis-Label LINKS vom Ziel (in Fahrtrichtung weiter)
const result = svgEl('text', { x: xEnd - 10, y: v.y + 4, 'text-anchor': 'end', 'font-size': '12', 'font-weight': '800', fill: v.color, opacity: '0' }, g);
result.textContent = v.km.toFixed(1).replace('.', ',') + ' km';
return { v, icon, result, xStart: TRACK_R, xEnd };
});
// Animation
let animId = null;
function setX(n, x) { n.icon.setAttribute('x', x); }
function animate() {
cancelAnimationFrame(animId);
const dur = 6500; // ms — bewusst langsam
const start = performance.now();
nodes.forEach(n => { setX(n, n.xStart); n.result.setAttribute('opacity', '0'); });
function tick(now) {
const t = Math.min(1, (now - start) / dur);
const e = 1 - Math.pow(1 - t, 3);
nodes.forEach(n => {
const x = n.xStart + (n.xEnd - n.xStart) * e;
setX(n, x);
if (t > 0.96) n.result.setAttribute('opacity', '1');
});
if (t < 1) animId = requestAnimationFrame(tick);
}
animId = requestAnimationFrame(tick);
}
function reset() {
cancelAnimationFrame(animId);
nodes.forEach(n => { setX(n, n.xStart); n.result.setAttribute('opacity', '0'); });
}
root.querySelector('[data-act="start"]').addEventListener('click', animate);
root.querySelector('[data-act="reset"]').addEventListener('click', reset);
}
// =====================================================================
// Experiment: ppm-Raster — 1 Teilchen von 1.000.000 findet man kaum
// =====================================================================
function ppmGrid(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🔍 Finde das eine Teilchen</h3>
<p>Unten siehst du ein Gitter mit <strong>10.000 Punkten</strong>. Ein einziger Punkt ist rot — das entspräche 100 ppm (echte 1 ppm wäre nochmal 100× feiner). Versuche, ihn zu finden und zu tippen!</p>
</div>
<div class="ge-ppm-grid" id="ge-ppm"></div>
<div class="ge-ppm-msg" aria-live="polite"></div>
<div class="ge-controls">
<button class="ge-btn ge-btn-primary" data-act="highlight">💡 Tipp zeigen</button>
<button class="ge-btn" data-act="new">🎲 Neues Teilchen</button>
</div>
<p class="ge-note">Bei der aktuellen CO₂-Konzentration von 422 ppm sind 422 von 1.000.000 Luftteilchen CO₂. Das klingt winzig — reicht aber, um die Erde messbar zu erwärmen. Quelle: NOAA Mauna Loa (2024).</p>
</div>
`;
const grid = root.querySelector('#ge-ppm');
const msg = root.querySelector('.ge-ppm-msg');
const COLS = 100, ROWS = 100;
let special = Math.floor(Math.random() * COLS * ROWS);
let found = false;
function render() {
grid.innerHTML = '';
grid.style.gridTemplateColumns = `repeat(${COLS}, 1fr)`;
for (let i = 0; i < COLS * ROWS; i++) {
const cell = document.createElement('span');
if (i === special) cell.className = 'ge-ppm-special';
grid.appendChild(cell);
}
msg.textContent = '';
msg.classList.remove('show', 'miss');
found = false;
}
function highlight() {
const el = grid.children[special];
if (!el) return;
el.classList.add('ge-ppm-flash');
setTimeout(() => el.classList.remove('ge-ppm-flash'), 1800);
}
function newOne() {
special = Math.floor(Math.random() * COLS * ROWS);
render();
}
function onHit(cell) {
if (found) return;
found = true;
cell.classList.add('ge-ppm-hit');
msg.textContent = '🎉 Getroffen! Das war 1 von 10.000 Punkten.';
msg.classList.remove('miss');
msg.classList.add('show');
}
function onMiss() {
if (found) return;
msg.textContent = 'Daneben — probier "Tipp zeigen" für eine kurze Hilfe.';
msg.classList.remove('show');
msg.classList.add('show', 'miss');
}
// Click-Handler delegiert auf das Grid (funktioniert auch bei 4-px-Zellen)
grid.addEventListener('click', ev => {
const target = ev.target;
if (target === grid) return;
if (target.classList && target.classList.contains('ge-ppm-special')) onHit(target);
else onMiss();
});
render();
root.querySelector('[data-act="highlight"]').addEventListener('click', highlight);
root.querySelector('[data-act="new"]').addEventListener('click', newOne);
}
// =====================================================================
// Experiment: Albedo-Slider — Oberfläche wechseln, Reflexion beobachten
// =====================================================================
function albedoSlider(root) {
const surfaces = [
{ key: 'snow', label: 'Frischer Schnee', albedo: 0.85, color: '#ffffff', border: '#b5c9cf' },
{ key: 'desert', label: 'Sand-Wüste', albedo: 0.35, color: '#e8d5b5', border: '#c4a97a' },
{ key: 'forest', label: 'Wald', albedo: 0.12, color: '#3a6b3e', border: '#2a5030' },
{ key: 'ocean', label: 'Ozean', albedo: 0.06, color: '#1f4e5a', border: '#0f2f3a' },
{ key: 'asphalt', label: 'Asphalt', albedo: 0.05, color: '#2a2a2a', border: '#1a1a1a' }
];
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>☀ Welche Oberfläche reflektiert wie viel?</h3>
<p>Wähle eine Oberfläche. Die Pfeile zeigen, wie viel Sonnenlicht zurückgeworfen wird.</p>
</div>
<div class="ge-albedo-choice" role="tablist">
${surfaces.map((s, i) => `
<button class="ge-btn ${i===0?'ge-btn-primary':''}" data-key="${s.key}">${s.label}</button>
`).join('')}
</div>
<svg class="ge-albedo-svg" viewBox="0 0 600 320" preserveAspectRatio="xMidYMid meet"></svg>
<div class="ge-albedo-stats">
<div>Albedo: <strong id="ge-alb-val">0,85</strong></div>
<div>Reflektiert: <strong id="ge-alb-refl">85 %</strong></div>
<div>Absorbiert: <strong id="ge-alb-abs">15 %</strong></div>
</div>
<p class="ge-note">Darum erwärmt sich die Arktis 4-mal schneller als die Erde insgesamt: Schmilzt Eis, kommt darunter dunkler Ozean zum Vorschein, der viel mehr Sonnenenergie aufnimmt. Quelle: Rantanen et al. 2022.</p>
</div>
`;
const svg = root.querySelector('.ge-albedo-svg');
const valEl = root.querySelector('#ge-alb-val');
const reflEl = root.querySelector('#ge-alb-refl');
const absEl = root.querySelector('#ge-alb-abs');
// Statischer Aufbau: Himmel + Sonne + Bodenrechteck
svgEl('rect', { x: 0, y: 0, width: 600, height: 210, fill: '#eff5f6' }, svg);
svgEl('circle', { cx: 90, cy: 70, r: 30, fill: '#f4c94e' }, svg);
const surfaceRect = svgEl('rect', { x: 0, y: 210, width: 600, height: 110, fill: '#ffffff', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg);
// Einfallender Lichtstrahl (Sonne → Boden)
svgEl('line', { x1: 110, y1: 100, x2: 300, y2: 210, stroke: '#e8833a', 'stroke-width': '3', 'stroke-linecap': 'round' }, svg);
svgEl('polygon', { points: '295,205 306,208 300,215', fill: '#e8833a' }, svg);
// Reflexions-Pfeile (dynamisch nach Albedo)
const reflG = svgEl('g', { class: 'ge-albedo-refl' }, svg);
function setSurface(key) {
const s = surfaces.find(x => x.key === key) || surfaces[0];
surfaceRect.setAttribute('fill', s.color);
surfaceRect.setAttribute('stroke', s.border);
// Anzahl reflektierter Pfeile proportional zur Albedo (1 bis 9 Pfeile)
reflG.innerHTML = '';
const nArrows = Math.max(1, Math.round(s.albedo * 10));
for (let i = 0; i < nArrows; i++) {
const angle = -60 + i * (120 / Math.max(1, nArrows - 1));
const rad = angle * Math.PI / 180;
const startX = 300, startY = 210;
const len = 120;
const endX = startX + Math.cos(rad) * len;
const endY = startY - Math.sin(Math.abs(rad) * Math.PI / 180 + 0.3) * Math.abs(len * Math.cos(rad) / 90) - 60;
// Simpler: Linien gleichmäßig nach oben gefächert
const e2x = 300 + Math.sin(rad) * len;
const e2y = 210 - Math.cos(rad) * len;
svgEl('line', { x1: startX, y1: startY, x2: e2x, y2: e2y, stroke: '#f4c94e', 'stroke-width': '2', 'stroke-linecap': 'round', opacity: '0.85' }, reflG);
}
valEl.textContent = s.albedo.toFixed(2).replace('.', ',');
reflEl.textContent = Math.round(s.albedo * 100) + ' %';
absEl.textContent = Math.round((1 - s.albedo) * 100) + ' %';
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.classList.toggle('ge-btn-primary', b.dataset.key === s.key);
});
}
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.addEventListener('click', () => setSurface(b.dataset.key));
});
setSurface('snow');
}
// =====================================================================
// Experiment: CO₂-Fußabdruck-Rechner — schneller Alltags-Schätzer
// =====================================================================
function footprintCalc(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🧮 Schätze deinen CO₂-Fußabdruck</h3>
<p>Einfache Auswahl pro Bereich. Das Ergebnis ist eine Richtgröße — kein genauer Wert.</p>
</div>
<div class="ge-calc">
<div class="ge-calc-row">
<div class="ge-calc-q">🏠 Wohnen</div>
<div class="ge-calc-opts" data-key="home">
<button class="ge-btn" data-val="1.0">Wärmepumpe / Fernwärme</button>
<button class="ge-btn ge-btn-primary" data-val="2.0">Gas/Öl, mittlere Größe</button>
<button class="ge-btn" data-val="3.5">Altbau, schlecht isoliert</button>
</div>
</div>
<div class="ge-calc-row">
<div class="ge-calc-q">🚗 Verkehr</div>
<div class="ge-calc-opts" data-key="car">
<button class="ge-btn" data-val="0.3">meist zu Fuß / Rad / ÖV</button>
<button class="ge-btn ge-btn-primary" data-val="1.8">Pkw mittel, kein Flug</button>
<button class="ge-btn" data-val="4.5">Pkw viel + 1 Fernflug/Jahr</button>
</div>
</div>
<div class="ge-calc-row">
<div class="ge-calc-q">🍽 Ernährung</div>
<div class="ge-calc-opts" data-key="food">
<button class="ge-btn" data-val="1.2">vegan / vegetarisch</button>
<button class="ge-btn ge-btn-primary" data-val="1.8">gemischt, wenig Fleisch</button>
<button class="ge-btn" data-val="2.6">viel Fleisch und Milchprodukte</button>
</div>
</div>
<div class="ge-calc-row">
<div class="ge-calc-q">🛒 Konsum</div>
<div class="ge-calc-opts" data-key="shop">
<button class="ge-btn" data-val="1.0">bewusst, wenig Neues</button>
<button class="ge-btn ge-btn-primary" data-val="2.0">durchschnittlich</button>
<button class="ge-btn" data-val="3.0">häufig Neues / Elektronik</button>
</div>
</div>
</div>
<div class="ge-calc-result">
<div>Dein geschätzter Fußabdruck:</div>
<strong class="ge-calc-total">7,6 t CO₂ / Jahr</strong>
<div class="ge-calc-bar"><div class="ge-calc-fill" style="width: 76%"></div></div>
<div class="ge-calc-scale"><span>0 t</span><span>Welt-Ø 4,7</span><span>AT-Ø 7,7</span><span>10 t</span></div>
<div class="ge-calc-label">Klimaneutral-Ziel: unter 1 t — Welt-Durchschnitt: 4,7 t — Österreich: 7,7 t.</div>
</div>
<p class="ge-note">Die Anteile decken sich mit den Haupt-Kategorien im Klimaschutzbericht 2024 des Umweltbundesamts Österreich. Details pro Kategorie unter <a href="?term=co2-fussabdruck#gl-source-3" class="gl-inline-link" data-key="co2-fussabdruck">CO₂-Fußabdruck</a>.</p>
</div>
`;
const totals = { home: 2.0, car: 1.8, food: 1.8, shop: 2.0 };
function update() {
const sum = Object.values(totals).reduce((a, b) => a + b, 0);
root.querySelector('.ge-calc-total').textContent = sum.toFixed(1).replace('.', ',') + ' t CO₂ / Jahr';
const pct = Math.min(100, (sum / 10) * 100);
root.querySelector('.ge-calc-fill').style.width = pct + '%';
}
root.querySelectorAll('.ge-calc-opts').forEach(group => {
const key = group.dataset.key;
group.querySelectorAll('.ge-btn').forEach(btn => {
btn.addEventListener('click', () => {
group.querySelectorAll('.ge-btn').forEach(b => b.classList.remove('ge-btn-primary'));
btn.classList.add('ge-btn-primary');
totals[key] = parseFloat(btn.dataset.val);
update();
});
});
});
update();
}
// =====================================================================
// Experiment: Treibhauseffekt-Slider — CO₂-ppm → globale Erwärmung
// =====================================================================
function greenhouseSlider(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🌡 Wie viel CO₂ verträgt das Klima?</h3>
<p>Schiebe den Regler und beobachte, wie sich die Atmosphäre füllt und die Erde wärmer wird.</p>
</div>
<svg class="ge-gh-svg" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
<div class="ge-gh-slider">
<label for="ge-gh-range">CO₂-Konzentration: <strong id="ge-gh-ppm">420</strong> ppm</label>
<input id="ge-gh-range" type="range" min="200" max="800" value="420" step="10">
<div class="ge-gh-markers">
<span>200</span><span>280<br>1750</span><span>420<br>heute</span><span>560<br>Verdopplung</span><span>800</span>
</div>
</div>
<div class="ge-gh-result">
<div class="ge-gh-pill">Temperaturanstieg gegenüber 1850: <strong id="ge-gh-dt">+1,2 °C</strong></div>
<div class="ge-gh-pill" id="ge-gh-verdict">nahe heutiger Wert</div>
</div>
<p class="ge-note">Vereinfachte Faustformel: ΔT = 3 °C × log₂(CO₂ / 280 ppm). Das bildet die IPCC-Klimasensitivität (rund 3 °C pro Verdopplung) grob ab. Quellen: IPCC AR6 WG1 Kap. 7 · NOAA Mauna Loa.</p>
</div>
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#ge-gh-range');
const ppmOut = root.querySelector('#ge-gh-ppm');
const dtOut = root.querySelector('#ge-gh-dt');
const verdict = root.querySelector('#ge-gh-verdict');
// Statisches Szenen-Layout
// Sonne
svgEl('circle', { cx: 90, cy: 55, r: 28, fill: '#f4c94e' }, svg);
svgEl('text', { x: 90, y: 62, 'text-anchor': 'middle', 'font-size': '22' }, svg).textContent = '☀';
// Atmosphäre (gradient wird per Opacity per Zustand gesteuert)
const sky = svgEl('rect', { x: 0, y: 30, width: 600, height: 190, fill: '#4a7c8a', opacity: '0.15' }, svg);
// Erdoberfläche
const earth = svgEl('rect', { x: 0, y: 220, width: 600, height: 80, fill: '#5a8a5e' }, svg);
// Baum und Haus dekorativ
svgEl('polygon', { points: '100,220 115,195 130,220', fill: '#3a6b3e' }, svg);
svgEl('rect', { x: 112, y: 220, width: 6, height: 10, fill: '#6b4a2e' }, svg);
svgEl('rect', { x: 470, y: 198, width: 36, height: 22, fill: '#e8d5b5', stroke: '#1f4e5a', 'stroke-width': '1' }, svg);
svgEl('polygon', { points: '468,199 488,182 508,199', fill: '#c85c4a' }, svg);
// Container für dynamische Moleküle
const molGroup = svgEl('g', { class: 'ge-gh-mols' }, svg);
// Temperatur-Anzeige rechts oben
const thermo = svgEl('g', { transform: 'translate(540, 40)' }, svg);
svgEl('rect', { x: -10, y: 0, width: 20, height: 140, fill: '#fff', stroke: '#1f4e5a', rx: '10' }, thermo);
const mercury = svgEl('rect', { x: -6, y: 130, width: 12, height: 0, fill: '#c85c4a', rx: '6' }, thermo);
svgEl('circle', { cx: 0, cy: 148, r: 10, fill: '#c85c4a' }, thermo);
function update() {
const ppm = +rng.value;
ppmOut.textContent = ppm;
// ΔT gegen 1850 (≈ 280 ppm als Referenz)
const dt = 3 * Math.log2(ppm / 280);
const dtRounded = Math.round(dt * 10) / 10;
dtOut.textContent = (dtRounded >= 0 ? '+' : '') + dtRounded.toFixed(1).replace('.', ',') + ' °C';
// Sky-Farbton rotläuft je höher der CO₂-Wert (rotes Leuchten)
const warmth = Math.min(1, Math.max(0, (ppm - 280) / 520));
const redAmount = Math.round(40 + warmth * 140);
sky.setAttribute('fill', `rgb(${40 + redAmount}, ${140 - warmth * 50}, ${170 - warmth * 80})`);
sky.setAttribute('opacity', (0.15 + warmth * 0.35).toFixed(2));
earth.setAttribute('fill', warmth > 0.6 ? '#c4a97a' : (warmth > 0.3 ? '#9bab74' : '#5a8a5e'));
// Moleküle proportional zu ppm
molGroup.innerHTML = '';
const nMols = Math.round((ppm - 200) / 8); // 0..75 Moleküle
for (let i = 0; i < nMols; i++) {
const mx = 40 + Math.random() * 520;
const my = 50 + Math.random() * 155;
const isMethane = Math.random() < 0.12;
svgEl('circle', {
cx: mx, cy: my, r: 5,
fill: isMethane ? '#e8833a' : '#c85c4a', opacity: '0.7'
}, molGroup);
}
// Mercury-Säule (0 °C = y=130, max +5°C bei y=10 → 120 px / 5°C = 24 px/°C)
const mh = Math.max(0, Math.min(120, dt * 24));
mercury.setAttribute('y', 130 - mh);
mercury.setAttribute('height', mh);
// Verdict-Text
let v, cls;
if (ppm < 300) { v = '🟢 Vorindustrielles Klima'; cls = 'good'; }
else if (ppm < 450) { v = '🟡 nahe heutiger Wert'; cls = 'now'; }
else if (ppm < 600) { v = '🟠 Verdopplung — kritisch'; cls = 'warn'; }
else { v = '🔴 weit jenseits 2 °C-Ziel'; cls = 'bad'; }
verdict.textContent = v;
verdict.dataset.state = cls;
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// Experiment: Methan-GWP-Waage — 1 kg Methan gegen wie viel CO₂?
// =====================================================================
function methaneBalance(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>⚖ Wie stark ist 1 kg Methan?</h3>
<p>Auf der linken Waagschale liegt 1 kg Methan. Lege so viele kg CO₂ auf die rechte Schale, bis die Waage im Gleichgewicht ist (auf 100 Jahre).</p>
</div>
<svg class="ge-bal-svg" viewBox="0 0 600 360" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
<div class="ge-gh-slider">
<label for="ge-bal-range">CO₂ auf der rechten Schale: <strong id="ge-bal-kg">10</strong> kg</label>
<input id="ge-bal-range" type="range" min="1" max="60" value="10" step="1">
</div>
<div class="ge-gh-result">
<div class="ge-gh-pill" id="ge-bal-verdict">noch zu leicht</div>
</div>
<p class="ge-note">Laut IPCC AR6 (2021) hat 1 kg Methan auf 100 Jahre die Klimawirkung von 28 kg CO₂ (GWP-100). Auf 20 Jahre sogar 82 kg.</p>
</div>
`;
const svg = root.querySelector('.ge-bal-svg');
const rng = root.querySelector('#ge-bal-range');
const kgOut = root.querySelector('#ge-bal-kg');
const verdict = root.querySelector('#ge-bal-verdict');
// Grundaufbau: Ständer + Balken
svgEl('rect', { x: 296, y: 200, width: 8, height: 120, fill: '#6b4a2e' }, svg);
svgEl('rect', { x: 260, y: 316, width: 80, height: 10, fill: '#6b4a2e', rx: '3' }, svg);
svgEl('circle', { cx: 300, cy: 200, r: 6, fill: '#1f4e5a' }, svg);
// Balken (rotiert um 300,200)
const beam = svgEl('g', { transform: 'rotate(0, 300, 200)' }, svg);
svgEl('rect', { x: 100, y: 196, width: 400, height: 8, fill: '#4a4a4a', rx: '4' }, beam);
// Aufhängungen
svgEl('line', { x1: 120, y1: 200, x2: 120, y2: 150, stroke: '#4a4a4a', 'stroke-width': '1.2' }, beam);
svgEl('line', { x1: 480, y1: 200, x2: 480, y2: 150, stroke: '#4a4a4a', 'stroke-width': '1.2' }, beam);
// Schalen
svgEl('ellipse', { cx: 120, cy: 152, rx: 45, ry: 8, fill: '#c4a97a', stroke: '#1f4e5a', 'stroke-width': '1' }, beam);
svgEl('path', { d: 'M 75 152 L 85 170 L 155 170 L 165 152 Z', fill: '#c4a97a', stroke: '#1f4e5a', 'stroke-width': '1' }, beam);
svgEl('ellipse', { cx: 480, cy: 152, rx: 45, ry: 8, fill: '#c4a97a', stroke: '#1f4e5a', 'stroke-width': '1' }, beam);
svgEl('path', { d: 'M 435 152 L 445 170 L 515 170 L 525 152 Z', fill: '#c4a97a', stroke: '#1f4e5a', 'stroke-width': '1' }, beam);
// Links: 1 Methan-Molekül (dick und orange)
const methaneG = svgEl('g', {}, beam);
svgEl('circle', { cx: 120, cy: 140, r: 14, fill: '#e8833a', stroke: '#1f4e5a', 'stroke-width': '1' }, methaneG);
const methaneLabel = svgEl('text', { x: 120, y: 144, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#fff' }, methaneG);
methaneLabel.textContent = 'CH₄';
const methaneCount = svgEl('text', { x: 120, y: 125, 'text-anchor': 'middle', 'font-size': '10', 'font-weight': '700', fill: '#1f4e5a' }, methaneG);
methaneCount.textContent = '1 kg';
// Rechts: variable CO₂-Moleküle
const co2G = svgEl('g', {}, beam);
const co2Count = svgEl('text', { x: 480, y: 125, 'text-anchor': 'middle', 'font-size': '10', 'font-weight': '700', fill: '#1f4e5a' }, beam);
function update() {
const kg = +rng.value;
kgOut.textContent = kg;
co2Count.textContent = kg + ' kg';
// CO₂-Moleküle auf rechte Schale (gestapelt, maximal 60)
co2G.innerHTML = '';
const perRow = 8;
const cols = Math.min(perRow, kg);
const rows = Math.ceil(kg / perRow);
for (let i = 0; i < Math.min(kg, 60); i++) {
const r = Math.floor(i / perRow);
const c = i % perRow;
const cx = 480 - ((cols - 1) * 9) / 2 + c * 9;
const cy = 145 - r * 9;
svgEl('circle', { cx, cy, r: 4, fill: '#c85c4a', opacity: '0.95' }, co2G);
}
// Balken-Rotation: Methan ist immer gleich "schwer" wie 28 kg CO₂
// Diff in kg-Äquivalent; Max-Rotation ±18°
const diff = kg - 28;
const angle = Math.max(-18, Math.min(18, diff * 0.8));
beam.setAttribute('transform', `rotate(${angle}, 300, 200)`);
// Verdict
if (kg < 20) verdict.textContent = '⬇ noch zu leicht';
else if (kg < 27) verdict.textContent = '🟡 fast — mehr CO₂ drauf';
else if (kg <= 29) verdict.textContent = '🎯 genau! 1 kg Methan ≈ 28 kg CO₂';
else verdict.textContent = '⬆ jetzt zu viel CO₂';
verdict.dataset.state = (kg >= 27 && kg <= 29) ? 'good' : 'now';
}
rng.addEventListener('input', update);
update();
}
// Registry — Key entspricht key_slug aus DB
window.GlossarExperiments = {
'kilowattstunde': kwhRace,
'ppm': ppmGrid,
'albedo': albedoSlider,
'co2-fussabdruck': footprintCalc,
'treibhauseffekt': greenhouseSlider,
'methan': methaneBalance
// 'windenergie' bewusst raus — redundant mit windrad-groessenvergleich.svg
};
})();
-118
View File
@@ -1,118 +0,0 @@
/**
* GeoGraSim Plattform: Live-Client
*
* Sendet Heartbeats an /api/live (Live-View für Lehrkräfte) und pollt das
* Pause-Flag aus /api/modules?student=1. Wird vom Sim-Wrapper als Plattform-
* Asset geladen — Sims selbst müssen nichts implementieren.
*
* Erwartet: window.__GGS__ = { sessionId, simId, baseUrl, basePath, apiUrl }.
*
* Sims können optional window.GGS_LIVE_STATE() zurückgeben, um einen kleinen
* State-Snapshot mitzusenden (max 50 KB). Ohne diese Funktion wird nur ein
* leerer State gemeldet — Lehrer sieht trotzdem WER online ist und WAS spielt.
*/
(function () {
'use strict';
if (window.__GGS_LIVE_INITIALIZED__) return;
window.__GGS_LIVE_INITIALIZED__ = true;
var ctx = window.__GGS__ || {};
// Ohne simId können wir nicht melden, welches Modul gespielt wird.
if (!ctx.simId) return;
// sessionId nicht vorab prüfen — der Browser sendet das ggs_session-Cookie
// automatisch mit den fetch-Calls (credentials:'same-origin'), und der
// Server entscheidet, ob es eine gültige Schüler-Session ist.
var apiBase = ctx.apiUrl || ((ctx.baseUrl || '') + '/php/api');
var simId = ctx.simId;
// --- Heartbeat ---
var heartbeatTimer = null;
function snapshotState() {
try {
if (typeof window.GGS_LIVE_STATE === 'function') {
var s = window.GGS_LIVE_STATE();
if (s && typeof s === 'object') return s;
}
} catch (_) {}
return {};
}
function sendHeartbeat() {
fetch(apiBase + '/live.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify({ action: 'heartbeat', module_id: simId, state: snapshotState() })
}).catch(function () {});
}
// --- Pause-Polling ---
var pauseTimer = null;
var pauseOverlay = null;
function ensureOverlay() {
if (pauseOverlay) return pauseOverlay;
var el = document.createElement('div');
el.id = 'ggs-pause-overlay';
el.style.cssText = 'position:fixed;inset:0;background:rgba(31,75,55,.78);color:#fff;z-index:99999;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:Inter,sans-serif;font-weight:700;text-align:center;padding:2rem;backdrop-filter:blur(3px)';
el.innerHTML = '<div style="font-size:4rem;margin-bottom:.6rem">⏸</div>'
+ '<div style="font-size:1.6rem;margin-bottom:.4rem">Auftrag pausiert</div>'
+ '<div style="font-size:.95rem;font-weight:500;opacity:.85;max-width:420px;line-height:1.4">Deine Lehrperson hat das Tempo angehalten. Sobald sie freigibt, kannst du weitermachen.</div>';
document.body.appendChild(el);
pauseOverlay = el;
return el;
}
function showPause() { ensureOverlay().style.display = 'flex'; }
function hidePause() { if (pauseOverlay) pauseOverlay.style.display = 'none'; }
function checkPause() {
fetch(apiBase + '/modules.php?student=1&module_id=' + encodeURIComponent(simId), {
credentials: 'same-origin'
}).then(function (r) { return r.json(); })
.then(function (m) {
if (m && m.paused && m.mode === 'teacher_started') showPause();
else hidePause();
})
.catch(function () {});
}
// --- Spectator-Mode für Lehrkräfte ---
// ?view=teacher schaltet Input ab und blendet ein dezentes Banner ein.
function isSpectator() {
try { return new URLSearchParams(location.search).get('view') === 'teacher'; }
catch (_) { return false; }
}
function applySpectator() {
if (!isSpectator()) return;
var s = document.createElement('style');
s.textContent = 'html,body{pointer-events:none!important}'
+ '#ggs-spectator-banner{pointer-events:auto!important;position:fixed;top:0;left:0;right:0;background:#4a7c8a;color:#fff;padding:.5rem;text-align:center;font-family:Inter,sans-serif;font-size:.78rem;font-weight:700;z-index:99998}'
+ '#ggs-spectator-banner button{pointer-events:auto;margin-left:.6rem;padding:.2rem .6rem;border:none;border-radius:5px;background:#fff;color:#4a7c8a;font-weight:700;cursor:pointer}';
document.head.appendChild(s);
var bar = document.createElement('div');
bar.id = 'ggs-spectator-banner';
bar.innerHTML = '👁 Live-Ansicht (Lehrkraft) — Eingaben sind deaktiviert. <button onclick="window.close()">Fenster schließen</button>';
document.body.appendChild(bar);
}
// --- Lifecycle ---
function start() {
if (isSpectator()) { applySpectator(); return; } // Spectator nicht heartbeaten
sendHeartbeat();
heartbeatTimer = setInterval(sendHeartbeat, 4000);
checkPause();
pauseTimer = setInterval(checkPause, 5000);
// Bei Tab-Schließung sauberer „end"-Heartbeat (keepalive für unload)
window.addEventListener('beforeunload', function () {
try {
navigator.sendBeacon && navigator.sendBeacon(
apiBase + '/live.php',
new Blob([JSON.stringify({ action: 'end' })], { type: 'application/json' })
);
} catch (_) {}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
})();
-59
View File
@@ -1,59 +0,0 @@
/**
* GeoGraSim — Versions-Tag
* Rendert kleinen Hinweis rechts unten auf jeder Seite, damit lokal vs.
* produktiv schnell abzugleichen ist.
*
* Einbinden: <script src="assets/js/version-tag.js" defer></script>
* (Pfad relativ zur Datei, die es einbindet. Im PHP-Wrapper aus BASE_PATH.)
*
* Liest version.json, zeigt Commit-SHA + Datum. Bei Fetch-Fehler (z.B.
* CORS, offline) zeigt es nichts — stumm, statt kaputt.
*/
(function () {
'use strict';
if (window.__GGS_VERSION_TAG_DONE__) return;
window.__GGS_VERSION_TAG_DONE__ = true;
// Pfad zur version.json ermitteln
var script = document.currentScript;
var versionUrl = 'version.json';
if (script && script.src) {
// Script-Src: .../assets/js/version-tag.js -> version.json auf gleicher Ebene wie assets/
var base = script.src.replace(/\/assets\/js\/version-tag\.js.*$/, '/');
versionUrl = base + 'version.json';
}
fetch(versionUrl, { cache: 'no-store' })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (v) {
if (!v) return;
var el = document.createElement('div');
el.className = 'ggs-version-tag';
el.title = 'Commit ' + v.commit + ' · ' + v.date;
el.innerHTML = '<span class="ggs-version-sha">' + v.commit + '</span>' +
'<span class="ggs-version-date">' + v.date + '</span>';
Object.assign(el.style, {
position: 'fixed',
right: '6px',
bottom: '6px',
zIndex: '99998',
background: 'rgba(20,40,50,0.7)',
color: 'rgba(255,255,255,0.75)',
fontFamily: 'ui-monospace, Menlo, Consolas, monospace',
fontSize: '10px',
lineHeight: '1.2',
padding: '3px 7px',
borderRadius: '4px',
pointerEvents: 'auto',
userSelect: 'all',
cursor: 'help',
display: 'flex',
gap: '6px',
alignItems: 'center'
});
el.querySelector('.ggs-version-sha').style.fontWeight = '700';
el.querySelector('.ggs-version-date').style.opacity = '0.7';
document.body.appendChild(el);
})
.catch(function () { /* stumm */ });
})();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

-661
View File
@@ -1,661 +0,0 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
max-width: none !important;
max-height: none !important;
}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
width: auto;
padding: 0;
}
.leaflet-container img.leaflet-tile {
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
mix-blend-mode: plus-lighter;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
svg.leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline-offset: 1px;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-size: 12px;
font-size: 0.75rem;
line-height: 1.5;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
font-size: 13px;
font-size: 1.08333em;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.8);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
line-height: 1.4;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
text-decoration: underline;
}
.leaflet-attribution-flag {
display: inline !important;
vertical-align: baseline !important;
width: 1em;
height: 0.6669em;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
white-space: nowrap;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
text-shadow: 1px 1px #fff;
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 24px 13px 20px;
line-height: 1.3;
font-size: 13px;
font-size: 1.08333em;
min-height: 1px;
}
.leaflet-popup-content p {
margin: 17px 0;
margin: 1.3em 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-top: -1px;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
pointer-events: auto;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
border: none;
text-align: center;
width: 24px;
height: 24px;
font: 16px/24px Tahoma, Verdana, sans-serif;
color: #757575;
text-decoration: none;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
color: #585858;
}
.leaflet-popup-scrolled {
overflow: auto;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-interactive {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/* Printing */
@media print {
/* Prevent printers from removing background-images of controls. */
.leaflet-control {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}

Some files were not shown because too many files have changed in this diff Show More