Files
geograsim/App/assets/js/glossar-experiments-neu1.js
Adminator f8e77910ea Glossar: 51 neue Einträge komplett — Bilder + 12 interaktive Widgets
Bilder (Flat-Scandinavian, gpt-image-1) für alle 51 neuen Begriffe; 12 Widgets in
neu1.js (strommix, eisschild, klimabilanz, megawattstunde, niederschlag, fruchtfolge)
und neu2.js (halbschatten, blockabfertigung, grundfreiheiten, synergie, aufenthaltsdauer,
grundwasser). image_path + module-Mappings, key_slug-basiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:17:59 +02:00

558 lines
26 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Glossar-Experimente „neu1" — Energie, Klima, Boden.
*
* Registrierung wie in glossar-experiments.js:
* window.GlossarExperiments[key_slug] = function (root) { … }
* Der Renderer (glossar.php) übergibt einen leeren Container; das Widget baut
* seinen DOM selbst und bindet seine Events. Styles: nur .ge-* aus glossar.php.
*
* Richtlinien:
* - Keine externen Libraries, Vanilla JS + SVG.
* - Mobile-/Tap-freundlich, keine Hover-Abhängigkeit.
* - Zahlen mit kurzer Quellenangabe in der .ge-note.
* - Rechenzeichen · und : (nie ×/÷), deutsche Zahlen via toLocaleString.
*/
(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 deInt = (n) => Math.round(n).toLocaleString('de-AT');
const deNum = (n, dec) => n.toFixed(dec === undefined ? 1 : dec).replace('.', ',');
// =====================================================================
// Experiment: strommix — 5 Regler, CO₂-Ampel für den Strom-Mix
// =====================================================================
function strommix(root) {
// Lebenszyklus-CO₂ je kWh (Median IPCC AR5), gerundet in g/kWh
const sources = [
{ key: 'wasser', label: '💧 Wasserkraft', co2: 24, color: '#4a7c8a', val: 40 },
{ key: 'wind', label: '🌬️ Windkraft', co2: 11, color: '#5a8a5e', val: 25 },
{ key: 'sonne', label: '☀️ Sonne (PV)', co2: 48, color: '#e8c547', val: 15 },
{ key: 'gas', label: '🔥 Erdgas', co2: 490, color: '#e8833a', val: 15 },
{ key: 'kohle', label: '🪨 Kohle', co2: 820, color: '#4a4a4a', val: 5 }
];
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🔌 Baue deinen Strom-Mix</h3>
<p>Stell mit den Reglern ein, woher der Strom kommt. Die Anteile werden immer auf <strong>100 %</strong> gerechnet. Beobachte die CO₂-Ampel!</p>
</div>
<svg class="ge-gh-svg" viewBox="0 0 600 70" preserveAspectRatio="none" aria-hidden="true"></svg>
<div class="ge-gh-slider" id="sm-sliders"></div>
<div class="ge-gh-result">
<div class="ge-gh-pill">CO₂ je Kilowattstunde: <strong id="sm-co2"></strong> g</div>
<div class="ge-gh-pill" id="sm-verdict"></div>
</div>
<div class="ge-calc-bar"><div class="ge-calc-fill" id="sm-bar" style="width:0%"></div></div>
<div class="ge-calc-scale"><span>0 g</span><span>sauber</span><span>schmutzig</span><span>820 g</span></div>
<p class="ge-note">CO₂-Werte je kWh über den ganzen Lebensweg (Median): Wind 11 g · Wasser 24 g · Sonne 48 g · Erdgas 490 g · Kohle 820 g. Quelle: IPCC AR5 (2014), Anhang III. Viel Wasser, Wind und Sonne = sehr wenig CO₂.</p>
</div>
`;
const bar = svgEl('g', {}, root.querySelector('.ge-gh-svg'));
const co2Out = root.querySelector('#sm-co2');
const verdict = root.querySelector('#sm-verdict');
const barFill = root.querySelector('#sm-bar');
const sliderBox = root.querySelector('#sm-sliders');
if (!sliderBox) return;
const shareEls = {};
sources.forEach(s => {
const row = document.createElement('div');
row.style.marginBottom = '.55rem';
row.innerHTML = `
<label for="sm-${s.key}" style="display:flex;justify-content:space-between;">
<span>${s.label}</span><strong id="sm-share-${s.key}">0 %</strong>
</label>
<input id="sm-${s.key}" type="range" min="0" max="100" step="5" value="${s.val}">
`;
sliderBox.appendChild(row);
shareEls[s.key] = row.querySelector('#sm-share-' + s.key);
const inp = row.querySelector('input');
inp.addEventListener('input', () => { s.val = +inp.value; update(); });
});
function update() {
const sum = sources.reduce((a, s) => a + s.val, 0) || 1;
// Gestapelter Farbbalken + Anteil-Texte
bar.innerHTML = '';
let x = 0;
let co2mix = 0;
sources.forEach(s => {
const share = s.val / sum;
co2mix += share * s.co2;
const w = share * 600;
if (w > 0.5) svgEl('rect', { x, y: 0, width: w, height: 70, fill: s.color }, bar);
x += w;
if (shareEls[s.key]) shareEls[s.key].textContent = Math.round(share * 100) + ' %';
});
co2Out.textContent = deInt(co2mix);
barFill.style.width = Math.min(100, (co2mix / 820) * 100) + '%';
let state, txt;
if (co2mix < 80) { state = 'good'; txt = '🟢 sehr sauber'; }
else if (co2mix < 250) { state = 'now'; txt = '🟡 noch ok'; }
else if (co2mix < 500) { state = 'warn'; txt = '🟠 zu viel CO₂'; }
else { state = 'bad'; txt = '🔴 sehr schmutzig'; }
barFill.style.background = state === 'good' ? '#5a8a5e' : state === 'now' ? '#4a7c8a' : state === 'warn' ? '#e8833a' : '#c85c4a';
verdict.textContent = txt;
verdict.dataset.state = state;
}
update();
}
// =====================================================================
// Experiment: eisschild — Temperatur → Eisschmelze → Meeresspiegel
// =====================================================================
function eisschild(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🧊 Wenn das Eis schmilzt</h3>
<p>Schiebe den Regler und mach es wärmer. Das Eis auf Grönland und der Antarktis schmilzt — und das Meer steigt. Was passiert mit der Küste?</p>
</div>
<svg class="ge-gh-svg" viewBox="0 0 600 320" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
<div class="ge-gh-slider">
<label for="es-range">Erwärmung: <strong id="es-temp">+0,0 °C</strong></label>
<input id="es-range" type="range" min="0" max="50" value="0" step="1">
<div class="ge-gh-markers"><span>0</span><span>+1,5</span><span>+3</span><span>+5 °C</span></div>
</div>
<div class="ge-gh-result">
<div class="ge-gh-pill">Meeresspiegel: <strong id="es-sea">+0,0 m</strong></div>
<div class="ge-gh-pill" id="es-verdict"></div>
</div>
<p class="ge-note">Vollständig geschmolzen hebt Grönland-Eis den Meeresspiegel um rund 7 m, das Antarktis-Eis um rund 58 m. Das dauert sehr lange, doch schon ab etwa +1,5 °C beginnt Grönland zu kippen. Quelle: AWI (Alfred-Wegener-Institut).</p>
</div>
`;
const svg = root.querySelector('.ge-gh-svg');
const rng = root.querySelector('#es-range');
const tempOut = root.querySelector('#es-temp');
const seaOut = root.querySelector('#es-sea');
const verdict = root.querySelector('#es-verdict');
if (!svg || !rng) return;
// Himmel + Sonne
svgEl('rect', { x: 0, y: 0, width: 600, height: 320, fill: '#dce9ee' }, svg);
const sun = svgEl('circle', { cx: 520, cy: 55, r: 30, fill: '#f4c94e' }, svg);
// Zwei Eisschilde als Blöcke, die von oben schrumpfen (y wächst, height sinkt)
// Grönland links, Antarktis Mitte-rechts. Basis auf Landsockel bei y=210.
const landY = 210;
svgEl('rect', { x: 40, y: landY, width: 150, height: 24, fill: '#6b8e6f' }, svg); // Grönland-Land
svgEl('rect', { x: 230, y: landY, width: 210, height: 24, fill: '#6b8e6f' }, svg); // Antarktis-Land
const groenIce = svgEl('rect', { x: 45, y: 90, width: 140, height: 120, fill: '#f4f8fb', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg);
const antaIce = svgEl('rect', { x: 235, y: 60, width: 200, height: 150, fill: '#f4f8fb', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg);
svgEl('text', { x: 115, y: 82, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Grönland';
svgEl('text', { x: 335, y: 52, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Antarktis';
// Küste rechts mit Häusern
svgEl('rect', { x: 470, y: landY, width: 130, height: 90, fill: '#c4a97a' }, svg);
const houses = [
{ x: 486, base: 200, h: 26 },
{ x: 522, base: 195, h: 32 },
{ x: 560, base: 190, h: 38 }
].map(hd => {
const g = svgEl('g', {}, svg);
svgEl('rect', { x: hd.x, y: hd.base - hd.h, width: 26, height: hd.h, fill: '#e8e4d8', stroke: '#1f4e5a', 'stroke-width': '1' }, g);
svgEl('polygon', { points: `${hd.x - 3},${hd.base - hd.h} ${hd.x + 13},${hd.base - hd.h - 12} ${hd.x + 29},${hd.base - hd.h}`, fill: '#c85c4a' }, g);
return { g, floodY: hd.base - hd.h + 6 };
});
// Wasser (steigt) ganz vorne
const seaMaxTop = 120, seaBottom = 320;
const sea = svgEl('rect', { x: 0, y: seaBottom - 40, width: 600, height: 40, fill: '#4a7c8a', opacity: '0.82' }, svg);
function update() {
const temp = +rng.value / 10; // 0..5 °C
tempOut.textContent = '+' + deNum(temp, 1) + ' °C';
// Schmelzanteile (vereinfachte Schwellen, langfristig)
const groenFrac = Math.max(0, Math.min(1, (temp - 1.5) / 3.5));
const antaFrac = Math.max(0, Math.min(1, (temp - 2.0) / 6.0));
const seaM = groenFrac * 7 + antaFrac * 58; // in Metern (langfristiges Maximum)
// Eisblöcke schrumpfen von oben
const gFullY = 90, gFullH = 120;
const gH = gFullH * (1 - groenFrac);
groenIce.setAttribute('y', gFullY + (gFullH - gH));
groenIce.setAttribute('height', Math.max(0, gH));
const aFullY = 60, aFullH = 150;
const aH = aFullH * (1 - antaFrac);
antaIce.setAttribute('y', aFullY + (aFullH - aH));
antaIce.setAttribute('height', Math.max(0, aH));
// Wasserstand: 0 m → y=280 (Höhe 40), 65 m → y=seaMaxTop
const frac = Math.min(1, seaM / 65);
const top = 280 - frac * (280 - seaMaxTop);
sea.setAttribute('y', top);
sea.setAttribute('height', seaBottom - top);
seaOut.textContent = '+' + deNum(seaM, seaM < 10 ? 1 : 0) + ' m';
houses.forEach(h => {
const flooded = top <= h.floodY;
h.g.setAttribute('opacity', flooded ? '0.35' : '1');
});
let state, txt;
if (temp < 1.5) { state = 'good'; txt = '🟢 Eis bleibt stabil'; }
else if (temp < 2.5) { state = 'now'; txt = '🟡 Grönland kippt'; }
else if (temp < 4) { state = 'warn'; txt = '🟠 Küsten in Gefahr'; }
else { state = 'bad'; txt = '🔴 Küsten überflutet'; }
sun.setAttribute('fill', temp > 3 ? '#e8833a' : '#f4c94e');
verdict.textContent = txt;
verdict.dataset.state = state;
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// Experiment: klimabilanz — Alltags-Entscheidungen → Jahres-CO₂
// =====================================================================
function klimabilanz(root) {
// Grundlast (Wohnen, Konsum, Öffentliches) fix
const BASE = 2.2;
const cats = [
{ key: 'food', q: '🍽️ Essen', opts: [
{ t: 'Viel Fleisch', v: 2.6 },
{ t: 'Gemischt', v: 1.7, sel: true },
{ t: 'Gemüse/vegetarisch', v: 1.0 } ] },
{ key: 'move', q: '🚗 Wege', opts: [
{ t: 'Meist Auto', v: 3.0 },
{ t: 'Gemischt', v: 1.5, sel: true },
{ t: 'Rad & Bus/Bahn', v: 0.4 } ] },
{ key: 'fly', q: '✈️ Flugreise', opts: [
{ t: 'Ein Fernflug', v: 2.0, sel: true },
{ t: 'Kein Flug', v: 0.0 } ] },
{ key: 'power', q: '💡 Strom', opts: [
{ t: 'Normalstrom', v: 1.2, sel: true },
{ t: 'Ökostrom', v: 0.2 } ] }
];
const chosen = {};
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🌍 Deine Klimabilanz für ein Jahr</h3>
<p>Tippe an, wie du lebst. Der Balken zählt zusammen, wie viel CO₂ du in einem Jahr verursachst.</p>
</div>
<div class="ge-calc" id="kb-calc"></div>
<div class="ge-calc-result">
<div>Dein Jahres-Ausstoß:</div>
<strong class="ge-calc-total" id="kb-total"></strong>
<div class="ge-calc-bar"><div class="ge-calc-fill" id="kb-bar" style="width:0%"></div></div>
<div class="ge-calc-scale"><span>0 t</span><span>Ziel 1 2 t</span><span>AT-Ø 8 t</span><span>12 t</span></div>
<div class="ge-calc-label" id="kb-verdict"></div>
</div>
<p class="ge-note">In Österreich verursacht jede Person rund 8 t CO₂ pro Jahr. Fürs Klima-Ziel wären es nur etwa 1 2 t. Quelle: Umweltbundesamt Österreich. Die Werte sind Richtgrößen, kein Messwert.</p>
</div>
`;
const box = root.querySelector('#kb-calc');
const totalOut = root.querySelector('#kb-total');
const barFill = root.querySelector('#kb-bar');
const verdict = root.querySelector('#kb-verdict');
if (!box) return;
cats.forEach(cat => {
const row = document.createElement('div');
row.className = 'ge-calc-row';
row.innerHTML = `<div class="ge-calc-q">${cat.q}</div><div class="ge-calc-opts" data-key="${cat.key}"></div>`;
const opts = row.querySelector('.ge-calc-opts');
cat.opts.forEach(o => {
const b = document.createElement('button');
b.className = 'ge-btn' + (o.sel ? ' ge-btn-primary' : '');
b.textContent = o.t;
b.dataset.val = o.v;
if (o.sel) chosen[cat.key] = o.v;
b.addEventListener('click', () => {
opts.querySelectorAll('.ge-btn').forEach(x => x.classList.remove('ge-btn-primary'));
b.classList.add('ge-btn-primary');
chosen[cat.key] = +b.dataset.val;
update();
});
opts.appendChild(b);
});
box.appendChild(row);
});
function update() {
const sum = BASE + Object.values(chosen).reduce((a, b) => a + b, 0);
totalOut.textContent = deNum(sum, 1) + ' t CO₂';
barFill.style.width = Math.min(100, (sum / 12) * 100) + '%';
let txt, col;
if (sum <= 2.5) { txt = '🟢 Super — nahe am Klima-Ziel!'; col = '#5a8a5e'; }
else if (sum <= 5) { txt = '🟡 Schon gut, geht noch weniger.'; col = '#4a7c8a'; }
else if (sum <= 8) { txt = '🟠 Etwa österreichischer Durchschnitt.'; col = '#e8833a'; }
else { txt = '🔴 Ziemlich viel — hier lässt sich sparen.'; col = '#c85c4a'; }
barFill.style.background = col;
verdict.textContent = txt;
}
update();
}
// =====================================================================
// Experiment: megawattstunde — wie lange reicht 1 MWh?
// =====================================================================
function megawattstunde(root) {
// 1 MWh = 1000 kWh
const items = [
{ key: 'led', label: '💡 LED-Lampe (10 W)', detail: (1000 / 0.010), unit: 'h', color: '#e8c547' },
{ key: 'kuehl',label: '🧊 Kühlschrank (150 kWh/Jahr)', detail: (1000 / 150) * 365, unit: 'd', color: '#4a7c8a' },
{ key: 'haus', label: '🏠 Haushalt (3.500 kWh/Jahr)', detail: (1000 / 3500) * 365, unit: 'd', color: '#5a8a5e' },
{ key: 'auto', label: '🚗 E-Auto (18 kWh/100 km)', detail: (1000 / 18) * 100, unit: 'km', color: '#c85c4a' }
];
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>⚡ Wie weit reicht 1 Megawattstunde?</h3>
<p>Eine Megawattstunde (1 MWh = 1.000 kWh) ist viel Energie. Tippe einen Verbraucher an und schau, wie lange oder wie weit sie reicht.</p>
</div>
<div class="ge-albedo-choice" id="mw-choice"></div>
<svg class="ge-gh-svg" viewBox="0 0 600 90" preserveAspectRatio="none" aria-hidden="true"></svg>
<div class="ge-gh-result">
<div class="ge-gh-pill">1 MWh reicht für: <strong id="mw-out"></strong></div>
</div>
<p class="ge-note">Ein Durchschnittshaushalt in Österreich braucht rund 3.500 kWh Strom pro Jahr. Quelle: E-Control. Rechnung: 1.000 kWh : Verbrauch.</p>
</div>
`;
const choice = root.querySelector('#mw-choice');
const svg = root.querySelector('.ge-gh-svg');
const out = root.querySelector('#mw-out');
if (!choice || !svg) return;
const bar = svgEl('rect', { x: 0, y: 25, width: 0, height: 40, fill: '#4a7c8a', rx: 6 }, svg);
function fmtReach(it) {
if (it.unit === 'h') {
const years = it.detail / 24 / 365;
return deInt(it.detail) + ' Stunden Dauerlicht (≈ ' + deNum(years, 0) + ' Jahre)';
}
if (it.unit === 'd') {
const years = it.detail / 365;
if (years >= 1) return deNum(years, 1) + ' Jahre';
return deInt(it.detail) + ' Tage';
}
return deInt(it.detail) + ' km weit fahren';
}
function select(it) {
out.textContent = fmtReach(it);
// Balkenlänge auf logarithmischer Skala (Werte reichen von ~100 bis 100.000)
const logv = Math.log10(Math.max(10, it.detail));
const w = Math.min(1, (logv - 1) / 4) * 590 + 10;
bar.setAttribute('width', w);
bar.setAttribute('fill', it.color);
Array.from(choice.children).forEach(b => b.classList.toggle('ge-btn-primary', b.dataset.key === it.key));
}
items.forEach((it, i) => {
const b = document.createElement('button');
b.className = 'ge-btn' + (i === 0 ? ' ge-btn-primary' : '');
b.textContent = it.label;
b.dataset.key = it.key;
b.addEventListener('click', () => select(it));
choice.appendChild(b);
});
select(items[0]);
}
// =====================================================================
// Experiment: niederschlag — Regenmenge formt die Landschaft
// =====================================================================
function niederschlag(root) {
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🌧️ Regen macht die Landschaft</h3>
<p>Schiebe den Regler von wenig zu viel Regen. Beobachte, wie aus trockener Steppe ein grüner Bergwald wird.</p>
</div>
<svg class="ge-track" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
<div class="ge-gh-slider">
<label for="ns-range">Regen pro Jahr: <strong id="ns-mm">300 mm</strong></label>
<input id="ns-range" type="range" min="300" max="3000" value="300" step="50">
<div class="ge-gh-markers"><span>300<br>Steppe</span><span>1.100<br>Wiese</span><span>3.000<br>Bergwald</span></div>
</div>
<div class="ge-gh-result">
<div class="ge-gh-pill" id="ns-verdict"></div>
</div>
<p class="ge-note">In Österreich fallen im trockenen Osten (Seewinkel) unter 600 mm, im nassen Bregenzerwald über 2.000 mm Regen pro Jahr. Quelle: GeoSphere Austria.</p>
</div>
`;
const svg = root.querySelector('.ge-track');
const rng = root.querySelector('#ns-range');
const mmOut = root.querySelector('#ns-mm');
const verdict = root.querySelector('#ns-verdict');
if (!svg || !rng) return;
const sky = svgEl('rect', { x: 0, y: 0, width: 600, height: 200, fill: '#cfe3ea' }, svg);
const sun = svgEl('circle', { cx: 90, cy: 55, r: 28, fill: '#f4c94e' }, svg);
const cloud = svgEl('g', { opacity: '0' }, svg);
svgEl('ellipse', { cx: 300, cy: 45, rx: 70, ry: 26, fill: '#8fa6ad' }, cloud);
svgEl('ellipse', { cx: 360, cy: 55, rx: 55, ry: 22, fill: '#9fb4bb' }, cloud);
const rainG = svgEl('g', {}, svg);
// Hügel / Boden
const ground = svgEl('path', { d: 'M0,200 Q150,150 300,190 T600,180 L600,300 L0,300 Z', fill: '#c9b483' }, svg);
const vegG = svgEl('g', {}, svg);
function update() {
const mm = +rng.value;
mmOut.textContent = deInt(mm) + ' mm';
const frac = (mm - 300) / (3000 - 300); // 0..1
// Himmel wird grauer, Sonne blasser, Wolke + Regen erscheinen
sky.setAttribute('fill', frac < 0.5 ? '#cfe3ea' : '#b9ccd3');
sun.setAttribute('opacity', (1 - frac * 0.8).toFixed(2));
cloud.setAttribute('opacity', Math.min(1, frac * 1.4).toFixed(2));
// Boden wird grüner
const r = Math.round(201 - frac * 127);
const g = Math.round(180 + frac * 20);
const b = Math.round(131 - frac * 60);
ground.setAttribute('fill', `rgb(${r},${g},${b})`);
// Regentropfen
rainG.innerHTML = '';
const drops = Math.round(frac * 40);
for (let i = 0; i < drops; i++) {
const x = 250 + Math.random() * 160;
const y = 70 + Math.random() * 110;
svgEl('line', { x1: x, y1: y, x2: x - 4, y2: y + 12, stroke: '#4a7c8a', 'stroke-width': '2', 'stroke-linecap': 'round', opacity: '0.7' }, rainG);
}
// Vegetation: von einzelnen Grasbüscheln zu vielen Bäumen
vegG.innerHTML = '';
const plants = Math.round(4 + frac * 22);
for (let i = 0; i < plants; i++) {
const x = 20 + (i / plants) * 560 + (Math.sin(i * 3.1) * 12);
const baseY = 205 + (i % 3) * 22;
if (frac > 0.55 && i % 2 === 0) {
// Baum
const h = 26 + frac * 20;
svgEl('rect', { x: x - 2, y: baseY - h * 0.35, width: 4, height: h * 0.35, fill: '#6b4a2e' }, vegG);
svgEl('polygon', { points: `${x},${baseY - h} ${x - 12},${baseY - h * 0.35} ${x + 12},${baseY - h * 0.35}`, fill: '#3a6b3e' }, vegG);
} else {
// Grasbüschel — Farbe je nach Regen
const col = frac < 0.4 ? '#a89a5e' : '#5a8a5e';
svgEl('path', { d: `M${x},${baseY} l-3,-10 M${x},${baseY} l0,-13 M${x},${baseY} l3,-10`, stroke: col, 'stroke-width': '2', 'stroke-linecap': 'round', fill: 'none' }, vegG);
}
}
let state, txt;
if (mm < 600) { state = 'warn'; txt = '🏜️ Trockene Steppe'; }
else if (mm < 1500) { state = 'now'; txt = '🌱 Grüne Wiesen & Felder'; }
else { state = 'good'; txt = '🌲 Dichter Bergwald'; }
verdict.textContent = txt;
verdict.dataset.state = state;
}
rng.addEventListener('input', update);
update();
}
// =====================================================================
// Experiment: fruchtfolge — 3 Jahre Feld planen, Bodengesundheit
// =====================================================================
function fruchtfolge(root) {
// effect = Wirkung auf Boden; legume = Stickstoff-Sammler
const plants = [
{ key: 'weizen', label: '🌾 Weizen', effect: -6, legume: false },
{ key: 'mais', label: '🌽 Mais', effect: -12, legume: false },
{ key: 'kartoffel', label: '🥔 Kartoffel', effect: -12, legume: false },
{ key: 'erbsen', label: '🫛 Erbsen', effect: 15, legume: true },
{ key: 'klee', label: '☘️ Klee', effect: 15, legume: true }
];
const years = [null, null, null];
root.innerHTML = `
<div class="ge-wrap">
<div class="ge-head">
<h3>🚜 Plane dein Feld für 3 Jahre</h3>
<p>Wähle für jedes Jahr eine Pflanze. Baust du immer dasselbe an (Monokultur), wird der Boden müde. Ein Wechsel — vor allem mit Erbsen oder Klee — hält ihn gesund.</p>
</div>
<div class="ge-calc" id="ff-years"></div>
<div class="ge-calc-result">
<div>Bodengesundheit nach 3 Jahren:</div>
<strong class="ge-calc-total" id="ff-total">60 %</strong>
<div class="ge-calc-bar"><div class="ge-calc-fill" id="ff-bar" style="width:60%"></div></div>
<div class="ge-calc-scale"><span>ausgelaugt</span><span></span><span>gesund</span></div>
<div class="ge-calc-label" id="ff-verdict"></div>
</div>
<p class="ge-note">Erbsen und Klee sind Hülsenfrüchte: Sie sammeln mit Knöllchenbakterien Stickstoff aus der Luft und düngen so den Boden. Deshalb wechseln Bäuerinnen und Bauern die Feldfrüchte planmäßig ab (Fruchtfolge). Quelle: AGES / Landwirtschaftskammer.</p>
</div>
`;
const box = root.querySelector('#ff-years');
const totalOut = root.querySelector('#ff-total');
const barFill = root.querySelector('#ff-bar');
const verdict = root.querySelector('#ff-verdict');
if (!box) return;
for (let y = 0; y < 3; y++) {
const row = document.createElement('div');
row.className = 'ge-calc-row';
row.innerHTML = `<div class="ge-calc-q">Jahr ${y + 1}</div><div class="ge-calc-opts" data-year="${y}"></div>`;
const opts = row.querySelector('.ge-calc-opts');
plants.forEach(p => {
const b = document.createElement('button');
b.className = 'ge-btn';
b.textContent = p.label;
b.dataset.key = p.key;
b.addEventListener('click', () => {
opts.querySelectorAll('.ge-btn').forEach(x => x.classList.remove('ge-btn-primary'));
b.classList.add('ge-btn-primary');
years[y] = p.key;
update();
});
opts.appendChild(b);
});
box.appendChild(row);
}
function update() {
let health = 60; // Startwert
let mono = 0;
for (let y = 0; y < 3; y++) {
const key = years[y];
if (!key) continue;
const p = plants.find(x => x.key === key);
health += p.effect;
// Monokultur-Strafe: gleiche Pflanze wie im Vorjahr
if (y > 0 && years[y - 1] === key) { health -= 10; mono++; }
}
health = Math.max(0, Math.min(100, health));
totalOut.textContent = Math.round(health) + ' %';
barFill.style.width = health + '%';
let txt, col;
if (health >= 75) { txt = '🟢 Toll — der Boden ist gesund und fruchtbar.'; col = '#5a8a5e'; }
else if (health >= 50) { txt = '🟡 Ok — mit mehr Wechsel geht es besser.'; col = '#4a7c8a'; }
else if (health >= 30) { txt = '🟠 Der Boden wird müde.'; col = '#e8833a'; }
else { txt = '🔴 Ausgelaugt — der Boden braucht eine Pause.'; col = '#c85c4a'; }
if (mono >= 2) txt = '🔴 Monokultur! Immer dasselbe laugt den Boden aus.';
barFill.style.background = col;
verdict.textContent = txt;
}
update();
}
// Registry — Keys = key_slug aus DB.
window.GlossarExperiments = Object.assign(window.GlossarExperiments || {}, {
'strommix': strommix,
'eisschild': eisschild,
'klimabilanz': klimabilanz,
'megawattstunde': megawattstunde,
'niederschlag': niederschlag,
'fruchtfolge': fruchtfolge
});
})();