Files
geograsim/App/docs/sim-spec-2026-06-12.md
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

524 lines
20 KiB
Markdown
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.
# GeoGraSim — Sim-Spec für externe KI-Entwicklung
**Stand: 2026-06-12** · Ergänzung zu [`module-interface.md`](module-interface.md) und [`integration-konzept.md`](integration-konzept.md).
> **Wichtig:** Dieses Dokument fasst nur das Neue / Geänderte seit Juni 2026 zusammen und bündelt die für eine externe KI essentiellen Schnittstellen. Die historischen Files bleiben gültig für: Sprache (Lernarbeit statt Spiel · Leichte Sprache), iPad-Pattern, Persistenz/Resume, Datei-Struktur, Datenmodell-Grundlagen.
---
## 0. TL;DR — Was eine neue Sim aus Plattform-Sicht ist
```
App/sims/<sim-id>/game.html ← deine HTML-Datei
App/sims/<sim-id>/engine.js ← optional, separate JS-Logik
App/sims/<sim-id>/assets/ ← optional, sim-eigene Bilder/Sounds
App/pages/<sim-id>.php ← PHP-Wrapper (Plattform-Standard, Atlas legt an)
```
Plus 1 Eintrag in der DB-Tabelle `module_info` (Title, Icon, Status, sort_order — Atlas macht das).
Die Sim selbst ist ein **selbst-laufender Browser-Frontend-Block**. Sie spricht mit der Plattform NUR über die 4 Window-Globals (siehe §2) und einen einzigen HTTP-Endpoint `/api/progress.php` zum Speichern (siehe §3).
---
## 1. Plattform-Conventions (Stand Juni 2026)
Drei Window-Globals + ein optionales Lib. Vollständige Doku im Header von [`/assets/js/live-client.js`](../assets/js/live-client.js).
### 1.1 `window.__GGS__` — Plattform setzt, Sim liest
Wird vom PHP-Wrapper VOR der Sim-Logik gesetzt:
```js
window.__GGS__ = {
sessionId: 'uuid', // anonyme Session
studentId: 12, // optional, null bei Gast
classId: 3, // optional
simId: 'kofferdetektiv',
simName: 'Kofferdetektiv',
level: 1,
baseUrl: '/geograsim/App', // oder '' auf Prod
apiUrl: '/geograsim/App/php/api',
basePath: '/geograsim/App',
mode: 'free', // 'free' | 'teacher_started' | 'locked'
forcedLevel: null, // wenn 'teacher_started': Pflicht-Level
easy: false, // Leichte Sprache aktiv?
};
```
Wenn `__GGS__` nicht da ist, läuft die Sim trotzdem (Dev/Direkt-URL) — sie sollte robust mit `undefined` umgehen.
### 1.2 `window.GGS_LIVE_STATE` — Sim setzt eine Funktion
Funktion, die einen Snapshot des aktuellen Sim-Zustands zurückgibt. Wird vom Plattform-Live-Client alle 4 s aufgerufen und ans Lehrer-Cockpit gestreamt.
```js
window.GGS_LIVE_STATE = function () {
if (!gameReady) return null;
return {
simId: 'kofferdetektiv',
phase: 'fall-3-zoll', // freier Text — was passiert gerade
progressPct: 60, // 0-100, didaktische Empfehlung
score: 42, // wenn schon scorebar
health: 'good', // good | ok | struggle (für Status-Punkt)
// weitere sim-spezifische Felder — Cockpit picked sich, was es kann
};
};
```
**Fallstrick** (echter Bug von Fluss am 2026-06-11): Nutze KEINE Property `params` auf einem Objekt, wenn `params` nicht direkt darauf existiert. `if (!game.params)` true → Snapshot null → Cockpit zeigt „meldet keine Live-Werte" obwohl die Sim läuft. Lies State direkt aus dem Computed-Result.
### 1.3 `window.GGS_TUTORIAL` — Sim registriert Replay-Hook
Damit der -Button im Header das Onboarding nochmal öffnet:
```js
window.GGS_TUTORIAL = {
simId: 'kofferdetektiv',
title: '🕵️ Kofferdetektiv',
replay: function () { startTutorial(); }, // deine eigene Funktion
};
```
Der Button wird in der Sim selbst eingefügt (siehe §4.2 Header-Standard).
### 1.4 `window.__GGS_LIVE__` — Plattform setzt, Sim liest
Read-only Proxy, von [`live-client.js`](../assets/js/live-client.js) bereitgestellt:
```js
window.__GGS_LIVE__ = {
activeMs: number, // aktive Spielzeit (gecappt bei 7_200_000 = 120 min)
idleMs: number, // Zeit seit letzter Interaktion
sessionStartedAt: timestamp,
lastInteractionAt: timestamp,
capped: boolean,
MAX_SESSION_MS: 7200000,
IDLE_THRESHOLD_MS: 90000,
};
```
**Wann lesen:** Beim Submit als `duration_ms` — bitte `__GGS_LIVE__.activeMs` statt `Date.now() - start` benutzen. Sonst landet auch Idle-Zeit (Tab vergessen) in der DB. Plattform-Cap zusätzlich im Backend defensiv.
### 1.5 Reservierte `__`-Heartbeat-Keys
Der Live-Client mischt automatisch in jeden `GGS_LIVE_STATE`-Snapshot:
```
state.__activeMs, state.__idleMs, state.__lastInteractionAt,
state.__sessionStartedAt, state.__capped
```
**Niemals überschreiben** — Cockpit liest diese aus.
---
## 2. Plattform-Bibliotheken (optional einbindbar)
### 2.1 Glossar-Tooltip
```html
<script src="/assets/js/glossar-tooltip.js" defer></script>
<script>
window.addEventListener('DOMContentLoaded', () => {
GlossarTooltip.init({
apiBase: '/php/api',
moduleId: 'kofferdetektiv', // filtert DB auf sim-eigene Begriffe
});
});
</script>
```
Im Markup:
```html
<span class="ggs-g" data-glossar="zollkontrolle">Zollkontrolle</span>
```
Wirkung: Tap/Klick → Popup mit Kurztext + Link zum vollen Glossar-Eintrag. Tooltip-CSS wird automatisch injiziert. Hat zentralen Style — nicht selbst CSS für `.ggs-g` schreiben.
Vorgehen für neue Glossar-Begriffe: in der DB-Tabelle `glossar` anlegen, `module_id` setzen. Atlas oder Glossar-Instanz macht das.
### 2.2 Quick-Intro (Mini-Onboarding-Modal)
Für Sims OHNE volles Tutorial. Bietet ein einheitliches Modal beim 1. Besuch + Replay-Funktion.
```html
<script src="/assets/js/ggs-quick-intro.js" defer></script>
<script>
window.addEventListener('DOMContentLoaded', () => {
GgsQuickIntro.init({
simId: 'kofferdetektiv',
title: '🕵️ Kofferdetektiv',
lead: 'Du untersuchst beschlagnahmte Koffer am Flughafen. Was darf rein, was nicht — und warum?',
steps: [
'Koffer öffnen — du siehst Inhalt + Herkunft + Zielland.',
'Gegenstände prüfen — viele Vorschriften erschließen sich aus Geografie + Politik.',
'Entscheidung treffen: durchlassen, beanstanden oder beschlagnahmen.',
'Feedback bekommen — pro Entscheidung Lehrtext + Glossar.',
],
goals: [
'Zoll- und Einreisebestimmungen verstehen',
'Herkunftsländer von Produkten geografisch einordnen',
'Gesetzeskunde im Kontext (Artenschutz, Drogen, Lebensmittel)',
],
});
});
</script>
```
Verhalten: 1. Besuch → Modal auto-open. localStorage merkt sich „gesehen" (`ggs.intro.<simId>`). Library registriert automatisch `window.GGS_TUTORIAL.replay()`. -Header-Button öffnet das Modal wieder.
Du kannst alternativ ein **volles, sim-spezifisches Tutorial** bauen (mehrere Schritte mit Bildern + Glossar-Begriffen — siehe weltkueche/game.html als Referenz). Dann musst du nur `window.GGS_TUTORIAL = {simId, title, replay: deineFunktion}` selbst setzen.
### 2.3 Live-Client (live-client.js)
Wird vom PHP-Wrapper automatisch eingebunden — Sim muss nichts tun. Library trackt Idle (siehe §1.4), sendet Heartbeats an `/api/live.php`, pollt Pause-Flag.
---
## 3. Submit-Pfad — Wie die Sim ihre Daten persistiert
Drei Aktionen via `POST /api/progress.php` mit JSON-Body. Auth läuft automatisch über die Session-Cookie aus `__GGS__`.
### 3.1 Live-Fortschritt (optional, alle paar Aktionen)
```js
fetch(__GGS__.apiUrl + '/progress.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'same-origin',
body: JSON.stringify({
sim_id: 'kofferdetektiv',
action: 'update',
data: { phase: 'fall-3', score: 42 },
}),
});
```
Selten nötig — GGS_LIVE_STATE deckt das eigentlich ab. Nur wenn du persistente Zwischenstände in der DB willst.
### 3.2 Reflexionsantwort (zwischen Phasen)
```js
fetch(__GGS__.apiUrl + '/progress.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'same-origin',
body: JSON.stringify({
sim_id: 'kofferdetektiv',
action: 'reflection',
data: {
level: 1,
question: 'Was war dein schwierigster Fall?',
answer: 'Der Koffer aus Kenia',
},
}),
});
```
### 3.3 Abschluss-Submit (Pflicht — am Ende einer Stufe)
```js
fetch(__GGS__.apiUrl + '/progress.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'same-origin',
body: JSON.stringify({
sim_id: 'kofferdetektiv',
action: 'submit_assessment',
data: {
level: 1,
stars: 3,
score: 72,
duration_ms: (window.__GGS_LIVE__ && window.__GGS_LIVE__.activeMs) || 0,
completed: true,
results: {
// SIM-SPEZIFISCHE Felder. Die Plattform-Benchmark-Engine
// erwartet von dir konkrete Keys (siehe §5) — bitte mit Atlas
// abstimmen, bevor du das Schema festschreibst.
cases_solved: 8,
cases_total: 10,
correct_first_try: 6,
wrong_decisions: 1,
glossar_consulted: 4,
},
},
}),
});
```
**Wichtig:** `results` ist sim-spezifisches JSON. Es wird in `assessments.results` als String gespeichert und sowohl im Lehrer-Cockpit (live.php) als auch im Ergebnisse-Tab (results.php) ausgelesen. Konventionen pro Sim folgen aus der Benchmark-Formel — siehe §5.
---
## 4. Design-System (Pflicht)
CSS-Variablen + Layout-Klassen aus [`/assets/css/design-system.css`](../assets/css/design-system.css).
### 4.1 Farb-Variablen
```css
--ggs-fjord /* Primärblau, Headlines */
--ggs-fjord-dark /* Dunkler Akzent */
--ggs-moss /* Erfolg/Grün */
--ggs-sand /* Kosten/Neutral */
--ggs-coral /* Gefahr/Rot */
--ggs-orange /* Warnung */
```
UI-Farben sind NICHT die Bild-Palette (siehe §6).
### 4.2 Header-Standard (Plattform-konform)
```html
<header class="ggs-header">
<a href="/schueler" class="ggs-header-logo">
<img src="/assets/img/bildLogo.png" alt="" class="ggs-header-logo-icon">
<img src="/assets/img/textlogo_geograsim.svg" alt="GeoGraSim" class="ggs-header-logo-text">
</a>
<div class="ggs-header-separator"></div>
<span class="ggs-header-module">Kofferdetektiv</span>
<span class="ggs-header-badge">Stufe 1</span>
<div class="ggs-header-spacer"></div>
<div class="ggs-header-actions">
<!-- Plattform-Standard: als ERSTER Button vor 📚 -->
<button class="ggs-btn-ghost" id="btn-info"
title="Anleitung nochmal zeigen"
onclick="if(window.GGS_TUTORIAL&&typeof window.GGS_TUTORIAL.replay==='function')window.GGS_TUTORIAL.replay();"></button>
<a class="ggs-btn-ghost" id="ggs-lehrplan-link" href="#" target="_blank" title="Lehrplan-Bezug">📚</a>
<button class="ggs-btn-ghost" id="btn-mute" title="Ton aus/an">🔊</button>
<button class="ggs-btn-ghost" id="btn-reset" title="Fortschritt zurücksetzen">🔄</button>
<a href="/schueler" class="ggs-btn-ghost" title="Zurück zum Cockpit">🏠</a>
</div>
</header>
```
**Regel:** = Tutorial-Replay (Plattform-Convention). Wenn deine Sim einen anderen Info-Inhalt hat (z.B. Fachinfo/Glossar in Farmer), kommt der mit eigenem Icon — `📖` für Glossar, `📚` für Lehrplan.
### 4.3 Layout-Zonen
`ggs-sim-layout` 3-Spalten-Grid (Status links, Sim Mitte, Aktionen rechts). Details in [`module-interface.md`](module-interface.md) §5.
### 4.4 Cockpit-Sichtbarkeit (LIVE_PRIMARY_FIELDS)
Damit deine Sim im Lehrer-Cockpit sinnvolle Spalten zeigt, muss Atlas in [`teacher.html`](../teacher.html) einen `LIVE_PRIMARY_FIELDS['kofferdetektiv']`-Eintrag setzen. Beispiel:
```js
'kofferdetektiv': [
{k:'health', label:'Status', align:'center', fmt: v => LIVE_VALUE_LABELS.health[v] || '—'},
{k:'phase', label:'Phase'},
{k:'progressPct', label:'Fortschritt', fmt: v => _liveBar(v, 0, 100, 'mid')},
{k:'score', label:'🏅 Score', fmt: v => _liveBar(v, 0, 100, 'high')},
{k:'cases_solved', label:'Gelöst'},
{k:'correct_first_try',label:'1.-Versuch ✓'},
],
```
Range-Bars: Helfer `_liveBar(val, min, max, goodWhen)`. `goodWhen`: `'high'` (grün ab 60% Range), `'low'` (invers — niedrig=gut), `'mid'` (neutral grau).
**Vorgehen für externe KI:** Liefere Atlas einfach die Liste deiner GGS_LIVE_STATE-Felder + welche davon Range-Bars wert sind. Atlas patcht teacher.html.
---
## 5. Benchmark-Engine — Sim braucht eine Scoring-Formel
Die Plattform berechnet pro Submission einen 0100-Modul-Score (für Lehrer-Cockpit Top 3 / Bottom 3 und Ergebnisse-Tab). Die Formel lebt in [`App/php/lib/Benchmark.php`](../php/lib/Benchmark.php) als private statische Methode.
Pro neuer Sim: **du lieferst die Formel-Idee, Atlas integriert sie**. Beispiel-Briefing (Kofferdetektiv):
```
scoreKofferdetektiv($results) {
$solved = $results['cases_solved'] ?? 0;
$total = $results['cases_total'] ?? 0;
$firstTry = $results['correct_first_try'] ?? 0;
$wrong = $results['wrong_decisions'] ?? 0;
if ($total === 0) return null;
$base = ($solved / $total) * 70; // 70 % Lösung
$bonus = ($firstTry / $total) * 30; // 30 % Sauberkeit
$malus = min(20, $wrong * 5); // bis -20 für Fehlentscheidung
return max(0, min(100, $base + $bonus - $malus));
}
```
Wichtig:
- Wenn keine bewertbaren Daten → `null` (lieber „noch keine Bewertung" als geratene Zahl).
- Pro Modul max. die 3 besten Sessions zählen — macht die Engine selbst.
---
## 6. Bildstil — Flat Scandinavian
Für ALLE Bilder in der Sim (Onboarding, Kategorie-Icons, Karten-Backgrounds, Charakter-Avatare):
**Palette:**
```
Background #e8e4d8 (warmer Sand)
Primär #1f4b37 (Forest)
Sekundär #4a7c4e (Moss)
Akzent #e8c547 (Honey)
Detail #b04a3e (Coral, sparsam)
```
**DALL-E-Prompt-Block (Standard):**
```
Flat scandinavian illustration, geometric shapes, soft warm color palette
(#1f4b37 forest, #4a7c4e moss, #e8c547 honey, #e8e4d8 sand background,
#b04a3e coral accent sparingly). No people unless explicit, no text, no
photo-realism. Clean educational style for children 10-14, Sek I.
[hier deine Sim-Szene]. Square 1024x1024.
```
Auflösungen:
- Onboarding-Karten: 1024×1024 → WebP, max 200 KB
- Sim-eigene Bilder: 512×512 oder 1024×1024 je nach Verwendung
- Glossar-Illustrationen: 512×512 (Atlas verwaltet das zentral)
Standorte: `App/sims/<sim-id>/assets/img/` für sim-eigene; `App/assets/img/glossar/` für Glossar.
---
## 7. Sprache (Pflicht — schon in [`module-interface.md`](module-interface.md) §4a)
Kurz zur Erinnerung:
| Nicht | Sondern |
|---|---|
| spielen, Spiel | arbeiten mit, Simulation, bearbeiten |
| Spieler:in | Lernende, Bearbeiter:in |
| Game Over | Ziel verfehlt / Durchgang beendet |
| Highscore | Beste Leistung |
| Lehrkraft | **Lehrperson** (österreichisches Pädagog:innen-Bildungsgesetz) |
Begründung: Wygotski-basierte Lernarbeit-Sprache. Wenn die Sim für Schüler:innen sichtbar wird, gilt das strikt.
Plus: Sek-I-Tonalität (1014 Jahre). Nicht infantil, nicht erwachsen. Du-Form, aber höflich.
---
## 8. Persistenz, iPad-Pattern, Leichte Sprache
Alle drei sind in [`module-interface.md`](module-interface.md) abgehandelt und gelten weiter:
- **Persistenz (§7b):** localStorage Autosave + Server-Mirror, Reload führt nie zum Neustart, expliziter Reset-Button mit Bestätigung.
- **iPad (§4c):** 1180×820 Referenz, Touch-Ziele 3640 px, kein Hover-Kleber, `font-size: 16px` für Inputs.
- **Leichte Sprache (§4b):** Plattform-DB liefert Easy-Varianten von Glossar/Lehrplan automatisch, wenn Lehrperson das pro Schüler:in setzt.
---
## 9. Workflow für eine neue Sim (Pragmatisch)
1. **Konzept-Skizze** an Atlas: Was lernen sie? Wie ist die Mechanik? Welche Stufen? Welche Lehrplan-Anbindung?
2. **Atlas legt an:**
- `module_info`-Eintrag (Title, Icon, Status='entwurf', sort_order)
- `App/pages/<sim-id>.php`-Wrapper
- Routing in `.htaccess`
- Glossar-Begriffe einsammeln (an Glossar-Instanz weitergeben)
3. **Externe KI baut** `App/sims/<sim-id>/`:
- `game.html` mit Plattform-Header + GGS_LIVE_STATE + GGS_TUTORIAL/QuickIntro
- Engine in JS (vanilla, kein Build-Step)
- Submit-Pfad bei Phasen-Ende
- localStorage-Autosave
4. **Atlas integriert:**
- `LIVE_PRIMARY_FIELDS['<sim-id>']` in teacher.html
- `Benchmark::score<SimName>()` in Benchmark.php
- Playwright-Tests in `.dontDeploy/playwright/tests/stufe1-smoke/`
- Deploy + Test
5. **Status auf `aktiv`** schalten (über admin-modules.html oder direktes SQL).
---
## 10. Test-Pattern (Stufe 1 Smoke)
Pro Sim mindestens 1 Test in `.dontDeploy/playwright/tests/stufe1-smoke/`:
```js
test('Sim kofferdetektiv · __GGS__ + live-client + GGS_LIVE_STATE', async ({ page }) => {
await page.goto('https://geograsim.at/kofferdetektiv');
await page.waitForTimeout(2500);
const info = await page.evaluate(() => ({
ggs: typeof window.__GGS__,
state: typeof window.GGS_LIVE_STATE,
tutorial: typeof window.GGS_TUTORIAL,
}));
expect(info.ggs).toBe('object');
expect(info.state).toBe('function');
expect(info.tutorial).toBe('object');
});
```
Existing Pattern in [`sim-platform-context.spec.js`](../../.dontDeploy/playwright/tests/stufe1-smoke/sim-platform-context.spec.js) deckt alle Sims ab — Atlas ergänzt deinen Sim-Slug dort.
---
## 11. Referenz-Sims als Vorbild
Wenn die externe KI ein gutes Vorbild für die Code-Struktur braucht:
- **`App/sims/weltkueche/game.html`** — full Tutorial-Pattern + Glossar-Tooltip in Tutorial-Texten + saubere Submit-Logik. Mittelgroß (~2000 LoC).
- **`App/sims/busfahrt/game.html`** — Karten-basierte Sim mit Quick-Intro statt full Tutorial. Topbar mit eigenem Styling.
- **`App/sims/eu-werkstatt/game.html`** — Drag-and-Drop / Card-Sorting-Pattern.
- **`App/sims/sonnensystem/game.html`** — 3D-Canvas (Three.js) + state-driven Aufgaben.
Die externe KI sollte **mindestens eine dieser Sims lesen**, bevor sie ihre eigene baut — um Plattform-Header, Glossar-Anbindung und Submit-Pattern abzukucken.
---
## 12. Was die externe KI explizit NICHT machen soll
- Keine eigenen URL-Routen / .htaccess-Eingriffe — Atlas macht das.
- Keine Schema-Änderungen an DB-Tabellen ohne Rückfrage.
- Keine API-Calls in Endpoints, die nicht in §3 stehen.
- Keine eigenen Plattform-Bibliotheken in `/assets/js/` ergänzen — wenn dir was zentral fehlt, melde es Atlas.
- Keine Spiel-Sprache. Ernsthaft — siehe §7.
- Keine echten KI-Calls IM Produkt (OpenAI/Claude/Anthropic-API). Auswertung ist parametrisch. (Tutorial-Inhalte mit KI vorgenerieren ist OK, im Produkt landet das als statischer Content.)
---
## 13. Erstkontakt-Briefing für die externe KI (Copy-Paste)
```
Du baust ein neues GeoGraSim-Sim-Modul namens "<sim-id>".
Plattform-Kontext + Conventions: docs/sim-spec-2026-06-12.md (dieses Doc) +
docs/module-interface.md.
Hard Constraints:
- Vanilla HTML/JS/CSS. Kein Build-Step. Kein React/TypeScript.
- Plattform-Header genau wie in §4.2.
- window.GGS_LIVE_STATE() liefern (§1.2).
- window.GGS_TUTORIAL setzen oder ggs-quick-intro.js nutzen (§1.3 / §2.2).
- Submit am Ende via POST /api/progress.php (§3.3).
- duration_ms aus __GGS_LIVE__.activeMs lesen (§1.4).
- Sprache: Lernarbeit, nicht Spiel (§7).
- iPad-tauglich (siehe module-interface.md §4c).
- Persistenz: Reload darf nie neu starten (siehe module-interface.md §7b).
Liefere am Ende:
- App/sims/<sim-id>/game.html (+ engine.js wenn separat)
- Liste deiner GGS_LIVE_STATE-Felder + welche Range-Bars Sinn machen
- Vorschlag für Scoring-Formel (Benchmark §5)
- Glossar-Begriffe, die du im Tutorial verwendest
Atlas integriert dann teacher.html, Benchmark.php, .htaccess, DB.
```
---
## 14. Ansprechpartner & Files-Map
| Fragen zu | Wer / Wo |
|---|---|
| Plattform-API / live-client / Cockpit | Atlas, `/assets/js/live-client.js`, `/teacher.html`, `/php/api/live.php` |
| Submit-Endpoint, assessments-Schema | Atlas, `/php/api/progress.php`, `/php/api/assessment.php` |
| Benchmark-Formel pro Sim | Atlas, `/php/lib/Benchmark.php` |
| Glossar-Begriffe / Tooltip-Pattern | Glossar-Instanz / Atlas, DB-Tabelle `glossar` + `/assets/js/glossar-tooltip.js` |
| Lehrplan-Anbindung / Kompetenz-Mapping | Lehrplan-Instanz / Atlas, DB-Tabellen `kompetenzen`/`kompetenz_modules`/`lehrplan_anchors` |
| Design-System-Klassen | `/assets/css/design-system.css` |
| Bildstil + DALL-E-Prompts | Atlas, §6 hier + Memory `reference_bildstil` |
---
**Fragen?** An Atlas (Plattform-Instanz). Diese Spec wird laufend gepflegt — bei jeder neuen Convention bitte hier ein Update einreichen statt Side-Doc.