/**
* Glossar-Experimente — Gruppe „geowelt".
*
* Kleine interaktive SVG-Widgets für das Detail-Modal eines Glossar-Eintrags
* (Abschnitt „Selbst ausprobieren"). Registrierung am Ende der Datei via
* window.GlossarExperiments[key_slug] = fn.
*
* Richtlinien: Vanilla JS, keine Libraries, nur bestehende .ge-*-CSS-Klassen.
* Grosse Tap-Ziele, keine Hover-Abhängigkeit. rAF-Schleifen stoppen, sobald das
* Modal geschlossen ist (root.isConnected-Guard). Zahlen quellenbar (ge-note).
*/
(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;
};
const fmtInt = n => Math.round(n).toLocaleString('de-AT');
const fmtDec = (n, d) => n.toLocaleString('de-AT', { minimumFractionDigits: d, maximumFractionDigits: d });
// =====================================================================
// gletscher — Zeit-Schieberegler 1900 → heute, Gletscher zieht sich zurück
// =====================================================================
function gletscher(root) {
root.innerHTML = `
🏔 Wie ein Alpengletscher schrumpft
Schiebe durch die Jahre. Beobachte, wie sich die Gletscherzunge das Tal hinaufzieht und der Eis-Vorrat sinkt.
Eis-Vorrat (1900 = 100 %): 100 %
noch fast unberührt
Werte veranschaulichen den Volumen-Rückgang der Alpengletscher seit 1900. Allein zwischen 2022 und 2023 verloren die Schweizer Gletscher rund 10 % ihres Volumens. Quelle: GLAMOS (Gletschermessnetz Schweiz).
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#ge-gl-range');
const yearOut = root.querySelector('#ge-gl-year');
const volOut = root.querySelector('[data-ref="vol"]');
const verdict = root.querySelector('[data-ref="verdict"]');
if (!svg || !rng) return;
// Statische Szene: Himmel, Berge, Tal
svgEl('rect', { x: 0, y: 0, width: 600, height: 300, fill: '#eaf2f6' }, svg);
svgEl('polygon', { points: '0,300 130,70 260,300', fill: '#b9c3c9' }, svg);
svgEl('polygon', { points: '180,300 320,50 470,300', fill: '#a7b3ba' }, svg);
svgEl('polygon', { points: '380,300 520,90 600,300', fill: '#b9c3c9' }, svg);
// Schneekappen
svgEl('polygon', { points: '130,70 108,105 152,105', fill: '#ffffff' }, svg);
svgEl('polygon', { points: '320,50 292,95 348,95', fill: '#ffffff' }, svg);
// Talboden (grün)
svgEl('rect', { x: 0, y: 250, width: 600, height: 50, fill: '#6f9c5f' }, svg);
// Gletscher als dicke Linie von der Quelle (oben) zur wandernden Zunge (unten)
const SRC = { x: 300, y: 78 }, TIP = { x: 300, y: 258 };
const glacierShade = svgEl('line', { x1: SRC.x, y1: SRC.y, x2: TIP.x, y2: TIP.y, stroke: '#9cc4e4', 'stroke-width': '34', 'stroke-linecap': 'round' }, svg);
const glacier = svgEl('line', { x1: SRC.x, y1: SRC.y, x2: TIP.x, y2: TIP.y, stroke: '#e2eef7', 'stroke-width': '24', 'stroke-linecap': 'round' }, svg);
const tipLabel = svgEl('text', { x: 300, y: 250, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#1f4e5a' }, svg);
tipLabel.textContent = 'Zunge';
// Volumen-Balken rechts
svgEl('rect', { x: 552, y: 60, width: 26, height: 200, fill: '#ffffff', stroke: '#1f4e5a', 'stroke-width': '1.4', rx: '6' }, svg);
const volBar = svgEl('rect', { x: 555, y: 63, width: 20, height: 194, fill: '#4a9cc4', rx: '5' }, svg);
svgEl('text', { x: 565, y: 52, 'text-anchor': 'middle', 'font-size': '10', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Eis';
const anchors = [[1900, 100], [1950, 88], [1980, 78], [2000, 70], [2010, 60], [2020, 48], [2022, 44], [2023, 40]];
function volAt(y) {
if (y <= anchors[0][0]) return anchors[0][1];
for (let i = 0; i < anchors.length - 1; i++) {
const [y0, v0] = anchors[i], [y1, v1] = anchors[i + 1];
if (y <= y1) { const t = (y - y0) / (y1 - y0); return v0 + (v1 - v0) * t; }
}
return anchors[anchors.length - 1][1];
}
function update() {
const year = +rng.value;
const vol = volAt(year);
yearOut.textContent = year;
volOut.textContent = Math.round(vol) + ' %';
// Zunge wandert nach oben, je weniger Eis
const frac = vol / 100;
const tipY = SRC.y + (TIP.y - SRC.y) * frac;
glacier.setAttribute('y2', tipY);
glacierShade.setAttribute('y2', tipY);
tipLabel.setAttribute('y', Math.min(255, tipY + 22));
// Balken
const full = 194;
const h = full * frac;
volBar.setAttribute('y', 63 + (full - h));
volBar.setAttribute('height', h);
let txt, state;
if (vol >= 85) { txt = 'noch fast unberührt'; state = 'good'; }
else if (vol >= 65) { txt = 'Eis geht spürbar zurück'; state = 'now'; }
else if (vol >= 45) { txt = 'Zunge zieht sich stark zurück'; state = 'warn'; }
else { txt = 'rasanter Rückgang — allein 2022 – 2023 rund −10 %'; state = 'bad'; }
verdict.textContent = txt;
verdict.dataset.state = state;
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// lawinenwarnstufe — Regler Stufe 1 – 5, Gefahr steigt sprunghaft
// =====================================================================
function lawinenwarnstufe(root) {
root.innerHTML = `
🏔 Die Lawinen-Warnstufen
Stelle die Warnstufe ein. Achte darauf: Die Gefahr steigt nicht gleichmäßig — der Sprung von Stufe 3 auf 4 ist besonders groß.
Fünfstufige Europäische Lawinen-Gefahrenskala (EAWS). Die Skala ist nicht linear: Jede Stufe steht ungefähr für eine Verdopplung der Gefahr, der Schritt von 3 (erheblich) auf 4 (groß) ist besonders deutlich. Quelle: European Avalanche Warning Services.
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#ge-lw-range');
const numOut = root.querySelector('#ge-lw-num');
const nameOut = root.querySelector('#ge-lw-name');
const riskOut = root.querySelector('[data-ref="risk"]');
const info = root.querySelector('[data-ref="info"]');
if (!svg || !rng) return;
const levels = {
1: { name: 'gering', risk: 8, state: 'good', txt: 'Meist sichere Verhältnisse. Auslösen nur bei sehr großer Belastung an wenigen Steilstellen.' },
2: { name: 'mäßig', risk: 20, state: 'now', txt: 'An einzelnen steilen Hängen möglich. Sorgfältige Routenwahl nötig.' },
3: { name: 'erheblich', risk: 45, state: 'warn', txt: 'An vielen Steilhängen möglich — oft reicht schon eine Person. Die meisten Unfälle passieren bei Stufe 3.' },
4: { name: 'groß', risk: 80, state: 'bad', txt: 'An den meisten Steilhängen wahrscheinlich, auch von selbst. Sehr gefährlich — Touren nur mit viel Erfahrung.' },
5: { name: 'sehr groß', risk: 100, state: 'bad', txt: 'Zahlreiche große, auch spontane Lawinen bis ins flache Gelände. Extrem — Touren tabu.' }
};
// Statische Szene: Himmel + Hang
svgEl('rect', { x: 0, y: 0, width: 600, height: 300, fill: '#eaf2f6' }, svg);
// Hang als weißes Schnee-Dreieck
svgEl('polygon', { points: '0,300 0,120 600,260 600,300', fill: '#f4f8fb', stroke: '#c4d4de', 'stroke-width': '1.5' }, svg);
// Fels-Untergrund unten
svgEl('polygon', { points: '0,300 600,300 600,278 0,150', fill: '#8a7d6b', opacity: '0.5' }, svg);
// Bäume am Hangfuß
[ [90, 262], [150, 274] ].forEach(([x, y]) => {
svgEl('polygon', { points: `${x},${y - 26} ${x - 11},${y} ${x + 11},${y}`, fill: '#3a6b3e' }, svg);
});
// Dynamische Gruppen: Risse + abgehendes Schneebrett
const cracksG = svgEl('g', {}, svg);
const slabG = svgEl('g', {}, svg);
// Gefahren-Balken
svgEl('rect', { x: 40, y: 40, width: 520, height: 20, fill: '#ffffff', stroke: '#1f4e5a', 'stroke-width': '1.2', rx: '10' }, svg);
const riskBar = svgEl('rect', { x: 42, y: 42, width: 10, height: 16, fill: '#6f9c5f', rx: '8' }, svg);
svgEl('text', { x: 40, y: 32, 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Gefahr';
const stateColor = { good: '#6f9c5f', now: '#4a7c8a', warn: '#e08a2a', bad: '#c85c4a' };
function update() {
const n = +rng.value;
const L = levels[n];
numOut.textContent = n;
nameOut.textContent = L.name;
riskOut.textContent = L.name + ' (Stufe ' + n + ')';
info.textContent = L.txt;
info.dataset.state = L.state;
// Balken (nicht-linear → zeigt den Sprung 3→4)
riskBar.setAttribute('width', Math.max(8, (516 * L.risk) / 100));
riskBar.setAttribute('fill', stateColor[L.state]);
// Risse proportional zur Stufe
cracksG.innerHTML = '';
const nCracks = n - 1;
for (let i = 0; i < nCracks; i++) {
const x = 220 + i * 70 + Math.sin(i * 2) * 20;
const y = 150 + i * 18;
svgEl('path', { d: `M ${x} ${y} q 14 12 8 30 q -6 14 10 26`, stroke: '#7c8a94', 'stroke-width': '2', fill: 'none', 'stroke-linecap': 'round' }, cracksG);
}
// Abgehendes Schneebrett ab Stufe 4
slabG.innerHTML = '';
if (n >= 4) {
svgEl('polygon', { points: '300,175 470,205 460,240 300,215', fill: '#dbe7ef', stroke: '#c85c4a', 'stroke-width': '2.5', 'stroke-dasharray': n >= 5 ? '0' : '6 4' }, slabG);
// Bruchkante
svgEl('line', { x1: 300, y1: 173, x2: 300, y2: 213, stroke: '#c85c4a', 'stroke-width': '3', 'stroke-linecap': 'round' }, slabG);
if (n >= 5) {
svgEl('polygon', { points: '150,225 340,250 330,285 150,260', fill: '#eef4f8', stroke: '#c85c4a', 'stroke-width': '2' }, slabG);
}
}
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// lichtgeschwindigkeit — Ziel-Auswahl, Lichtlaufzeit-Uhr
// =====================================================================
function lichtgeschwindigkeit(root) {
root.innerHTML = `
💡 Wie lange braucht das Licht?
Wähle ein Ziel. Ein Lichtblitz startet auf der Erde. Sieh, wie lange das Licht bis dorthin unterwegs ist.
🌙 Mond
☀ Sonne
🔴 Mars
⭐ Proxima Centauri
Entfernung: 384.400 km
Lichtlaufzeit: 1,3 Sekunden
Licht legt rund 299.792 km pro Sekunde zurück — extrem schnell. Und doch braucht es bis zum nächsten Stern über 4 Jahre: Das All ist unvorstellbar groß. Entfernungen gerundet, Quelle: NASA.
`;
const svg = root.querySelector('.ge-gh-svg');
const distOut = root.querySelector('[data-ref="dist"]');
const timeOut = root.querySelector('[data-ref="time"]');
if (!svg) return;
const targets = {
mond: { name: 'Mond', dist: '384.400 km', time: '1,3 Sekunden', emoji: '🌙' },
sonne: { name: 'Sonne', dist: '149,6 Mio. km', time: '8 Minuten 20 Sekunden', emoji: '☀' },
mars: { name: 'Mars', dist: 'im Schnitt 225 Mio. km', time: 'rund 12,5 Minuten (3 – 22 min je nach Bahn)', emoji: '🔴' },
proxima: { name: 'Proxima Centauri', dist: 'rund 40 Billionen km', time: 'etwa 4,2 Jahre', emoji: '⭐' }
};
// Statische Szene: Erde links, Ziel rechts, Bahn dazwischen
svgEl('rect', { x: 0, y: 0, width: 600, height: 200, fill: '#10233a' }, svg);
// ein paar Sterne
for (let i = 0; i < 26; i++) {
svgEl('circle', { cx: 20 + Math.random() * 560, cy: 10 + Math.random() * 180, r: Math.random() * 1.3 + 0.4, fill: '#dfe8f2', opacity: (0.4 + Math.random() * 0.5).toFixed(2) }, svg);
}
svgEl('line', { x1: 70, y1: 100, x2: 520, y2: 100, stroke: '#3a5a7a', 'stroke-width': '2', 'stroke-dasharray': '5 6' }, svg);
svgEl('circle', { cx: 60, cy: 100, r: 22, fill: '#3a7cc4' }, svg);
svgEl('circle', { cx: 60, cy: 100, r: 22, fill: 'none', stroke: '#6fae5e', 'stroke-width': '3', 'stroke-dasharray': '10 8' }, svg);
svgEl('text', { x: 60, y: 150, 'text-anchor': 'middle', 'font-size': '12', 'font-weight': '700', fill: '#dfe8f2' }, svg).textContent = 'Erde';
const targetIcon = svgEl('text', { x: 530, y: 108, 'text-anchor': 'middle', 'font-size': '34' }, svg);
const targetLabel = svgEl('text', { x: 530, y: 150, 'text-anchor': 'middle', 'font-size': '12', 'font-weight': '700', fill: '#dfe8f2' }, svg);
// Lichtblitz (Photon)
const photon = svgEl('circle', { cx: 82, cy: 100, r: 6, fill: '#f4e04a' }, svg);
const photonGlow = svgEl('circle', { cx: 82, cy: 100, r: 12, fill: '#f4e04a', opacity: '0.35' }, svg);
const X0 = 82, X1 = 508;
let animId = null, current = 'mond';
function animate() {
cancelAnimationFrame(animId);
const dur = 2200;
const start = performance.now();
function tick(now) {
if (!root.isConnected) { cancelAnimationFrame(animId); return; }
const raw = (now - start) / dur;
const t = raw % 1;
const x = X0 + (X1 - X0) * t;
photon.setAttribute('cx', x);
photonGlow.setAttribute('cx', x);
const op = t > 0.9 ? (1 - t) * 10 : 1;
photon.setAttribute('opacity', op.toFixed(2));
photonGlow.setAttribute('opacity', (op * 0.35).toFixed(2));
animId = requestAnimationFrame(tick);
}
animId = requestAnimationFrame(tick);
}
function select(key) {
const T = targets[key] || targets.mond;
current = key;
distOut.textContent = T.dist;
timeOut.textContent = 'Lichtlaufzeit: ' + T.time;
timeOut.dataset.state = key === 'proxima' ? 'bad' : (key === 'sonne' || key === 'mars' ? 'warn' : 'now');
targetIcon.textContent = T.emoji;
targetLabel.textContent = T.name;
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.classList.toggle('ge-btn-primary', b.dataset.key === key);
});
animate();
}
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.addEventListener('click', () => select(b.dataset.key));
});
select('mond');
}
// =====================================================================
// gigawattstunde — Schieberegler GWh, „Strom für X Haushalte einen Tag"
// =====================================================================
function gigawattstunde(root) {
root.innerHTML = `
⚡ Wie viel ist eine Gigawattstunde?
Schiebe den Regler. Sieh, für wie viele Haushalte diese Strommenge einen ganzen Tag lang reicht.
Ein durchschnittlicher österreichischer Haushalt verbraucht rund 3.500 kWh Strom pro Jahr, also etwa 9,6 kWh pro Tag. Quelle: E-Control. Schon 1 GWh ist eine riesige Strommenge.
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#ge-gw-range');
const valOut = root.querySelector('#ge-gw-val');
const kwhOut = root.querySelector('[data-ref="kwh"]');
const hhOut = root.querySelector('[data-ref="hh"]');
if (!svg || !rng) return;
const PER_DAY = 3500 / 365; // ≈ 9,589 kWh pro Haushalt und Tag
const housesG = svgEl('g', {}, svg);
// jedes Symbol steht für eine feste Anzahl Haushalte
const HOUSES_PER_ICON = 5000;
const COLS = 20;
function drawHouse(x, y, s) {
const g = svgEl('g', { transform: `translate(${x},${y})` }, housesG);
svgEl('rect', { x: -s / 2, y: -s * 0.55, width: s, height: s * 0.7, fill: '#f4c94e' }, g);
svgEl('polygon', { points: `${-s / 2 - 1},${-s * 0.55} 0,${-s * 1.05} ${s / 2 + 1},${-s * 0.55}`, fill: '#c85c4a' }, g);
}
function update() {
const gwh = +rng.value;
valOut.textContent = gwh;
kwhOut.textContent = fmtInt(gwh * 1e6) + ' kWh';
const households = (gwh * 1e6) / PER_DAY;
hhOut.textContent = 'Strom für ca. ' + fmtInt(households) + ' Haushalte einen Tag lang';
housesG.innerHTML = '';
const nIcons = Math.max(1, Math.min(60, Math.round(households / HOUSES_PER_ICON)));
const s = 20;
for (let i = 0; i < nIcons; i++) {
const c = i % COLS, r = Math.floor(i / COLS);
drawHouse(30 + c * 28, 60 + r * 46, s);
}
svgEl('text', { x: 300, y: 168, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '600', fill: '#4a7c8a' }, housesG)
.textContent = '1 Haus-Symbol ≈ ' + fmtInt(HOUSES_PER_ICON) + ' Haushalte';
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// netzspannung — Land-Buttons, Volt + Steckertyp + Lade-Hinweis
// =====================================================================
function netzspannung(root) {
root.innerHTML = `
🔌 Netzspannung rund um die Welt
Tippe ein Land an. Sieh die Spannung, die Steckerform und ob dein Handy-Netzteil dort direkt lädt.
🇦🇹 Österreich / EU
🇺🇸 USA
🇯🇵 Japan
🇬🇧 Großbritannien
Spannung: 230 V
Steckertyp: Typ C / F
Nennspannungen und Steckertypen nach IEC: EU 230 V, USA 120 V, Japan 100 V, Großbritannien 230 V. Handy-Netzteile sind fast immer für 100 – 240 V gebaut und gleichen die Spannung selbst aus — nur die Steckerform ist weltweit verschieden.
`;
const svg = root.querySelector('.ge-gh-svg');
const voltOut = root.querySelector('[data-ref="volt"]');
const plugOut = root.querySelector('[data-ref="plug"]');
const chargeOut = root.querySelector('[data-ref="charge"]');
if (!svg) return;
const lands = {
at: { volt: 230, plug: 'Typ C / F (Schuko)', home: true },
us: { volt: 120, plug: 'Typ A / B', home: false },
jp: { volt: 100, plug: 'Typ A / B', home: false },
gb: { volt: 230, plug: 'Typ G', home: false }
};
// Spannungs-Skala als Balken (Bezug 240 V)
svgEl('rect', { x: 40, y: 60, width: 520, height: 26, fill: '#ffffff', stroke: '#1f4e5a', 'stroke-width': '1.2', rx: '13' }, svg);
const voltBar = svgEl('rect', { x: 42, y: 62, width: 100, height: 22, fill: '#4a7c8a', rx: '11' }, svg);
const voltLabel = svgEl('text', { x: 300, y: 78, 'text-anchor': 'middle', 'font-size': '14', 'font-weight': '800', fill: '#ffffff' }, svg);
svgEl('text', { x: 40, y: 50, 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = '0 V';
svgEl('text', { x: 560, y: 50, 'text-anchor': 'end', 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = '240 V';
// Blitz-Icon + Steckerform
const plugIcon = svgEl('text', { x: 300, y: 135, 'text-anchor': 'middle', 'font-size': '13', 'font-weight': '700', fill: '#1f4e5a' }, svg);
function select(key) {
const L = lands[key] || lands.at;
voltOut.textContent = L.volt + ' V';
plugOut.textContent = L.plug;
voltBar.setAttribute('width', Math.max(20, (516 * L.volt) / 240));
voltBar.setAttribute('fill', L.volt >= 220 ? '#c85c4a' : '#4a7c8a');
voltLabel.textContent = L.volt + ' V';
plugIcon.textContent = 'Steckerform: ' + L.plug;
if (L.home) {
chargeOut.textContent = 'Dein Netzteil lädt direkt — und der Stecker passt (deine Heimat-Norm).';
chargeOut.dataset.state = 'good';
} else {
chargeOut.textContent = 'Dein Handy-Netzteil (100 – 240 V) lädt direkt — aber für die Steckerform brauchst du einen Reise-Adapter.';
chargeOut.dataset.state = 'warn';
}
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.classList.toggle('ge-btn-primary', b.dataset.key === key);
});
}
root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => {
b.addEventListener('click', () => select(b.dataset.key));
});
select('at');
}
// =====================================================================
// kartenmaßstab — Maßstab-Schieberegler, gleicher Ort in versch. Ausschnitten
// =====================================================================
function kartenmassstab(root) {
root.innerHTML = `
🗺 Der Kartenmaßstab
Schiebe den Regler vom Detail bis zum Landausschnitt. Sieh, wie derselbe Ort immer kleiner wird — und das Lineal, wie weit 1 cm auf der Karte in echt sind.
Rechenweg: 1 cm auf der Karte · Maßstabszahl = Strecke in echt. Merke: großer Maßstab (kleine Zahl) = kleiner Ausschnitt mit vielen Details, kleiner Maßstab (große Zahl) = großer Ausschnitt mit wenig Details.
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#ge-km-range');
const scaleOut = root.querySelector('#ge-km-scale');
const rulerOut = root.querySelector('[data-ref="ruler"]');
const viewOut = root.querySelector('[data-ref="view"]');
if (!svg || !rng) return;
const scales = [100, 200, 500, 1000, 2000, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000];
const sceneG = svgEl('g', {}, svg);
const rulerG = svgEl('g', {}, svg);
function levelOf(scale) {
if (scale <= 500) return 0; // Haus
if (scale <= 5000) return 1; // Straßenzug
if (scale <= 50000) return 2; // Ort / Viertel
if (scale <= 250000) return 3; // Region
return 4; // Land
}
function drawScene(level) {
sceneG.innerHTML = '';
svgEl('rect', { x: 20, y: 20, width: 560, height: 180, fill: '#eef4ee', stroke: '#c4d4ca', 'stroke-width': '1.5', rx: '8' }, sceneG);
const cx = 300, cy = 110;
if (level === 0) {
// Ein Haus mit Garten
svgEl('rect', { x: 40, y: 40, width: 520, height: 140, fill: '#d8ead0' }, sceneG);
svgEl('rect', { x: 210, y: 70, width: 180, height: 100, fill: '#f4c94e', stroke: '#1f4e5a', 'stroke-width': '2' }, sceneG);
svgEl('polygon', { points: '200,70 300,20 400,70', fill: '#c85c4a' }, sceneG);
svgEl('rect', { x: 285, y: 120, width: 30, height: 50, fill: '#6b4a2e' }, sceneG);
svgEl('polygon', { points: '110,175 128,135 146,175', fill: '#3a6b3e' }, sceneG);
svgEl('polygon', { points: '450,175 468,135 486,175', fill: '#3a6b3e' }, sceneG);
} else if (level === 1) {
// Straßenzug mit mehreren Häusern
svgEl('rect', { x: 40, y: 100, width: 520, height: 28, fill: '#c9cdd2' }, sceneG);
svgEl('line', { x1: 40, y1: 114, x2: 560, y2: 114, stroke: '#ffffff', 'stroke-width': '2', 'stroke-dasharray': '16 12' }, sceneG);
for (let i = 0; i < 6; i++) {
const x = 70 + i * 80;
svgEl('rect', { x, y: 55, width: 44, height: 34, fill: '#f4c94e', stroke: '#1f4e5a', 'stroke-width': '1.2' }, sceneG);
svgEl('polygon', { points: `${x - 3},55 ${x + 22},38 ${x + 47},55`, fill: '#c85c4a' }, sceneG);
svgEl('rect', { x: x + 6, y: 138, width: 36, height: 26, fill: '#a9c99a' }, sceneG);
}
} else if (level === 2) {
// Ort / Viertel: Häuserblöcke + Straßenraster
svgEl('rect', { x: 40, y: 40, width: 520, height: 140, fill: '#dfe8df' }, sceneG);
for (let gx = 0; gx < 5; gx++) for (let gy = 0; gy < 3; gy++) {
svgEl('rect', { x: 70 + gx * 96, y: 55 + gy * 42, width: 70, height: 28, fill: '#c4a97a', stroke: '#8a7256', 'stroke-width': '1' }, sceneG);
}
for (let i = 1; i < 5; i++) svgEl('line', { x1: 40 + i * 104, y1: 40, x2: 40 + i * 104, y2: 180, stroke: '#c9cdd2', 'stroke-width': '6' }, sceneG);
for (let i = 1; i < 3; i++) svgEl('line', { x1: 40, y1: 40 + i * 47, x2: 560, y2: 40 + i * 47, stroke: '#c9cdd2', 'stroke-width': '6' }, sceneG);
} else if (level === 3) {
// Region: Grün-/Wasserflächen, Fluss, Ortspunkte
svgEl('rect', { x: 40, y: 40, width: 520, height: 140, fill: '#cfe3c4' }, sceneG);
svgEl('path', { d: 'M 40 60 Q 200 90 300 70 T 560 120', stroke: '#4a9cc4', 'stroke-width': '9', fill: 'none', 'stroke-linecap': 'round' }, sceneG);
svgEl('polygon', { points: '380,90 470,110 440,175 350,150', fill: '#b7d59e' }, sceneG);
[ [140, 120], [300, 150], [470, 70], [230, 90] ].forEach(([x, y]) => {
svgEl('circle', { cx: x, cy: y, r: 7, fill: '#c85c4a', stroke: '#fff', 'stroke-width': '1.5' }, sceneG);
});
} else {
// Land: großer Ausschnitt mit Städten
svgEl('rect', { x: 40, y: 40, width: 520, height: 140, fill: '#cfe3c4' }, sceneG);
svgEl('path', { d: 'M 60 150 Q 120 60 240 90 Q 360 120 440 70 Q 520 40 545 120 L 545 175 L 60 175 Z', fill: '#b7d59e', stroke: '#6f9c5f', 'stroke-width': '2' }, sceneG);
svgEl('path', { d: 'M 40 40 Q 120 55 180 45 L 180 40 Z', fill: '#9cc4e4' }, sceneG);
[ [140, 130, 'groß'], [300, 100, 'mittel'], [430, 130, 'klein'], [230, 155, 'klein'] ].forEach(([x, y, sz]) => {
const r = sz === 'groß' ? 8 : (sz === 'mittel' ? 6 : 4);
svgEl('circle', { cx: x, cy: y, r, fill: '#c85c4a', stroke: '#fff', 'stroke-width': '1.5' }, sceneG);
});
}
}
function drawRuler(scale) {
rulerG.innerHTML = '';
// Referenzlinie „1 cm auf der Karte" (fixe Länge 90 px als Anschauung)
const x0 = 40, x1 = 130, y = 218;
svgEl('line', { x1: x0, y1: y, x2: x1, y2: y, stroke: '#1f4e5a', 'stroke-width': '3', 'stroke-linecap': 'round' }, rulerG);
svgEl('line', { x1: x0, y1: y - 6, x2: x0, y2: y + 6, stroke: '#1f4e5a', 'stroke-width': '3' }, rulerG);
svgEl('line', { x1: x1, y1: y - 6, x2: x1, y2: y + 6, stroke: '#1f4e5a', 'stroke-width': '3' }, rulerG);
svgEl('text', { x: 85, y: y + 24, 'text-anchor': 'middle', 'font-size': '12', 'font-weight': '700', fill: '#1f4e5a' }, rulerG).textContent = '1 cm auf der Karte';
const realM = scale / 100; // 1 cm * scale = scale cm = scale/100 m
let real;
if (realM >= 1000) real = fmtDec(realM / 1000, realM % 1000 === 0 ? 0 : 1) + ' km';
else real = fmtInt(realM) + ' m';
svgEl('text', { x: 150, y: y + 4, 'font-size': '14', 'font-weight': '800', fill: '#c85c4a' }, rulerG).textContent = '= ' + real + ' in echt';
return real;
}
function update() {
const scale = scales[+rng.value];
scaleOut.textContent = fmtInt(scale);
const level = levelOf(scale);
drawScene(level);
const real = drawRuler(scale);
rulerOut.textContent = '1 cm = ' + real;
const viewNames = ['Einzelnes Haus mit Garten', 'Ein Straßenzug', 'Ein Ort / Stadtviertel', 'Eine ganze Region', 'Großer Landausschnitt'];
const big = scale <= 5000;
viewOut.textContent = viewNames[level] + ' — ' + (big ? 'großer Maßstab, viele Details' : 'kleiner Maßstab, wenig Details');
viewOut.dataset.state = big ? 'good' : (level >= 3 ? 'warn' : 'now');
}
rng.addEventListener('input', update);
update();
}
// Registry — Keys entsprechen key_slug aus DB.
window.GlossarExperiments = Object.assign(window.GlossarExperiments || {}, {
'gletscher': gletscher,
'lawinenwarnstufe': lawinenwarnstufe,
'lichtgeschwindigkeit': lichtgeschwindigkeit,
'gigawattstunde': gigawattstunde,
'netzspannung': netzspannung,
'kartenmaßstab': kartenmassstab
});
})();