Files
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

735 lines
25 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.
# Vertrag 6: Platform Standards (Pflicht)
Was die V2-Plattform allen Modulen **liefert** und was sie von ihnen
**verlangt** — über die reine Schnittstellen-Definition hinaus. Damit
GeoGraSim als ein zusammenhängendes Produkt wirkt und nicht wie
eine Sammlung loser Apps.
Diese Standards sind nicht verhandelbar. Bei Konformitäts-Check
prüft Atlas auch die Einhaltung dieser Regeln (Bildstil-Eyeballing,
Touch-Target-Messung, Lexikon-Scan).
---
## 1. Design-Prinzipien (didaktisch)
### Wygotski-Lernarbeit, kein Spiel
GeoGraSim ist **Lernarbeit mit Simulationen**, kein Spiel. Wir
sprechen Schüler*innen als ernsthafte Bearbeiter*innen an, nicht als
Spieler*innen. Theoriebezug: Wygotski („Zone der nächsten Entwicklung").
**Verbindliches Lexikon** für alle UI-Texte:
| NICHT verwenden | STATTDESSEN |
|---|---|
| spielen, Spiel | arbeiten mit, Simulation, bearbeiten |
| Weiterspielen | Fortsetzen, weiterarbeiten |
| „Jetzt spielen" | „Simulation starten", „Los arbeiten" |
| Spielstand | Arbeitsstand, Fortschritt |
| Spieler*in | Lernende, Bearbeiter*in |
| Spielrunde | Durchgang, Arbeitsphase |
| Gameplay | Simulationsablauf, Arbeitsweise |
| „verloren", „Game Over" | „Ziel verfehlt", „Durchgang beendet" |
| Highscore | Beste Leistung, Bestwert |
| Level | OK, aber lieber „Schwierigkeit" oder „Stufe" |
**Ausnahmen**: Im Code (Variablennamen wie `gameState`, `gameTick`)
ok, da unsichtbar. Tabellennamen wie `game_levels`, `game_saves` ok.
Nur **sichtbare UI-Texte** und **Lehrer-/Schüler-Dokumentation**
folgen dem Lexikon.
### Inklusion: Easy-Sprache ist Pflicht
Jedes Modul muss alle UI-Texte in zwei Varianten anbieten:
- `<locale>-standard` — Standardsprache
- `<locale>-easy` — Leichte Sprache nach Netzwerk-Leichte-Sprache-
Regeln, A1A2-Niveau, kurze Sätze, keine Fachbegriffe ohne
Erklärung
Easy-Variante ist **kein nettes Add-on**, sondern Pflicht für die
Inklusion (Schüler*innen mit Lese-/Lernschwächen, Deutsch-als-
Zweitsprache, kognitive Behinderung).
### Keine KI im fertigen Produkt
**Auswertungen, Bewertungen, Insight-Cards** im Lehrer-Dashboard nutzen
**parametrische Regeln**, keine KI-API-Calls.
```
✅ if classScore < 40% then showWarning("Klasse hat Schwierigkeiten")
❌ if AI.summarize(class.results) then ...
```
Begründung: Lehrpersonen müssen sich auf deterministische,
nachvollziehbare Aussagen verlassen können. Keine Halluzinationen,
keine Datenschutz-Probleme durch externe LLM-Calls.
**Erlaubt**: KI-Generierung von Assets (Bilder, Audio) **vor** dem
Deployment — siehe Punkt 5 unten.
---
## 2. iPad als Hauptreferenzgerät
GeoGraSim wird primär auf **iPad Landscape (1180 × 820 CSS-Pixel)**
genutzt — Schulen in AT/DACH setzen iPads ein.
### Layout-Breakpoints
- Desktop ≥ 1200 px: dreispaltig (Sidebar + Canvas + Sidebar)
- iPad Landscape 9001199 px: dreispaltig (kompakter)
- iPad Portrait / Mobile < 900 px: einspaltig
### Touch-Pattern (Pflicht)
```html
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
```
`viewport-fit=cover` ist **Pflicht** in jeder Modul-HTML, sonst
funktioniert `env(safe-area-inset-*)` nicht.
**CSS-Pflichten** im Modul:
```css
body {
touch-action: manipulation; /* kein Double-Tap-Zoom */
-webkit-tap-highlight-color: transparent;
}
button, .interactive {
min-width: 36px;
min-height: 36px; /* Touch-Ziel-Minimum */
}
/* Hover NUR auf Geräten mit echtem Hover */
@media (hover: hover) {
button:hover { ... }
}
/* Touch-Feedback statt Hover */
button:active { ... }
/* Form-Inputs mind. 16px font-size, sonst zoomt iOS */
input, textarea, select { font-size: 16px; }
/* Drag-Elemente brauchen touch-action: none als Kind */
.canvas-draggable { touch-action: none; }
```
### Modal-/Overlay-Pattern (Pflicht!)
**Lerngeschichte 2026-04-28**: Park-Mini-Spiel hatte am iPad einen
unerreichbaren „Schließen"-Button. Stundenlanges Warten ohne
Abbrechen. Daraus die vier Pflicht-Regeln:
1. **Höhen mit `dvh` statt `vh`**:
```css
.modal { max-height: 94dvh; }
```
2. **Safe-area-padding-bottom**:
```css
.modal { padding-bottom: max(16px, env(safe-area-inset-bottom)); }
```
3. **Aktions-Buttons sticky am unteren Modal-Rand**:
```css
.modal-actions {
position: sticky;
bottom: 0;
background: linear-gradient(to top, var(--ggs-white) 80%, transparent);
}
```
4. **Float-✕ rechts oben** als Backup:
```css
.modal-close { position: absolute; top: 8px; right: 8px; width: 36px; height: 36px; }
```
Bei kritischen Buttons (Schließen, Abbrechen, Bestätigen) Touch-Ziel
≥ 44 px.
**Globale Klassen** in `v2-platform/assets/css/design-system.css`:
`.ggs-endscreen-overlay`, `.ggs-endscreen`, `.ggs-endscreen-actions`
haben das alles zentral. Module sollen diese Klassen verwenden, nicht
eigene Modale neu bauen.
---
## 3. UI-Design-Tokens
Module nutzen **CSS-Variablen** aus `design-system.css`, keine
hardcodierten Hex-Werte.
### Farben
```css
/* Akzent (Fjord) */
--ggs-fjord: #4a7c8a;
--ggs-fjord-dark: #1f4e5a;
--ggs-fjord-light: #dae8ec;
/* Erfolg (Moss) */
--ggs-moss: #5a8a5e;
--ggs-moss-dark: #3a6b3e;
--ggs-moss-light: #dcead0;
/* Neutral (Sand) */
--ggs-sand: #e8d5b5;
--ggs-sand-dark: #c4a97a;
/* Gefahr (Coral) */
--ggs-coral: #c85c4a;
--ggs-coral-light: #f0d0ca;
/* Warnung (Orange) */
--ggs-orange: #e8833a;
/* Hintergrund */
--ggs-bg: #f5f2eb;
--ggs-bg-dark: #e8e4d8;
--ggs-white: #ffffff;
/* Text */
--ggs-text: #2a2a2a;
--ggs-text-muted: #8a8a8a;
--ggs-text-light: #b0b0b0;
/* Sonstige */
--ggs-border: #e0ddd4;
--ggs-success: #5a8a5e;
--ggs-warning: #e8833a;
--ggs-danger: #c85c4a;
--ggs-info: #4a7c8a;
```
### Spacing & Layout
| Token | Wert | Verwendung |
|---|---|---|
| `--ggs-gap-xs` | 4 px | Inline-Abstände |
| `--ggs-gap-sm` | 8 px | Form-Felder |
| `--ggs-gap-md` | 16 px | Standard |
| `--ggs-gap-lg` | 24 px | Sektionen |
| `--ggs-gap-xl` | 32 px | Hero |
| `--ggs-radius-sm` | 6 px | Pills |
| `--ggs-radius-md` | 12 px | Karten |
| `--ggs-radius-lg` | 16 px | Hero-Cards |
| `--ggs-radius-pill` | 999 px | Avatar-Kreise |
| `--ggs-shadow-sm` | `0 1px 3px rgba(0,0,0,.08)` | Karten |
| `--ggs-shadow-md` | `0 2px 8px rgba(0,0,0,.12)` | Modale |
| `--ggs-shadow-lg` | `0 4px 16px rgba(0,0,0,.16)` | Tooltips |
### Typografie
```css
--ggs-font: 'Inter', system-ui, -apple-system, sans-serif;
--ggs-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
```
**Wichtig**: Modul-eigene Tokens (z.B. für besondere Stimmungen wie
Wintertag) als `--<modul>-*`-Variablen lokal definieren, aber GGS-
Tokens als Fallback referenzieren.
**Wichtig 2**: UI-Palette ≠ Bild-Palette. UI = Fjord/Moss/Sand.
Bilder = Scandinavian Flat (siehe Punkt 5).
---
## 4. Avatar-Pool
30 vorgenerierte Schüler-Avatare in 3 thematischen Gruppen.
Module dürfen den Avatar der Schüler*in aus `/api/student/me`
beziehen und für Begrüßungen / Belohnungen anzeigen.
**Pfad**: `/v2beta/assets/avatars/avatar-<slug>.png`
**Auflösung**: 1024×1024 PNG, kreisrund maskiert (`border-radius: 50%`)
### Geo-Welt
`pilotin` · `pilot` · `kartografin` · `geologe` · `meteorologin`
· `stadtplaner` · `forscherin` · `forscher` · `taucherin` · `astronaut`
### Cool & Lustig
`coole-girl` · `coole-boy` · `lustige-girl` · `lustige-boy`
· `nerd-girl` · `sportlich-boy` · `kuenstlerin` · `musiker`
· `gaertnerin` · `abenteurer`
### Tier-Begleiter
`fuchs-explorer` · `eule-prof` · `baer-foerster` · `pinguin-polar`
· `affe-tropen` · `delfin-meer` · `adler-pilot` · `schildkroete-w`
· `katze-stadt` · `biene-natur`
Bei Bedarf für neue Avatare: Plattform pflegt das, **Module
generieren keine eigenen Avatare**.
---
## 5. Bildstil — Flat Scandinavian Illustration (verbindlich)
Module-Sims stehen auf der Schülerseite nebeneinander. Ein
Stilbruch fällt sofort auf. Daher: **alle generierten Bilder**
(Splash, Cockpit-Card, Spielfeld-Hintergrund, Sprites, Marker, Glossar)
folgen demselben Stil.
### Offizieller Prompt-Block (verbatim, NICHT umformulieren)
> 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.
Bei jedem Bild diesen Block voranstellen, danach nur den Szenen-Teil
ergänzen.
### Bildtypen und Auflösungen
| Bildtyp | Auflösung | Quality |
|---|---|---|
| Splash (Sim-Intro) | 1792 × 1024 (16:9) | standard |
| Cockpit-Card | ≈ 800 × 450 (16:9) | standard |
| Glossar-Bild | 1792 × 1024 | standard |
| Avatar | 1024 × 1024 | standard |
### Tabu
- Keine Schrift im Bild
- Keine Logos / Wasserzeichen
- Keine Rahmen / Borders
- Keine Stockphoto-Übernahmen — bei Bedarf neu generieren
---
## 6. Zentrale API-Keys und Plattform-Dienste
API-Keys für externe Dienste werden **zentral von der Plattform
gehalten**, nicht von einzelnen Modulen. Modul-Instanzen rufen sie
über Plattform-Proxy-Endpoints auf, damit Keys nicht in
Modul-Code/Repos landen.
| Dienst | Zweck | Plattform-Endpoint | API-Key liegt in |
|---|---|---|---|
| **DALL-E 3** | Bild-Generierung (Splash, Cards, Glossar, Sprites) | `POST /v2beta/api/asset-gen/image` | `v2-platform/.env.local` → `OPENAI_API_KEY` |
| **ElevenLabs** | Sprach-Synthese (TTS für Aufgaben, Audio-Erzähler) | `POST /v2beta/api/asset-gen/voice` | `v2-platform/.env.local` → `ELEVENLABS_API_KEY` |
| **Suno** | Hintergrundmusik | manuell durch Thomas | (Suno hat kein klassisches API) |
| **OpenStreetMap-Tile-Proxy** | Karten-Tiles (Leaflet, Maplibre) | `GET /v2beta/proxy/tile/<z>/<x>/<y>.png` | (User-Agent gesetzt) |
| **OSRM** | Routing für Logistik-/Bus-Module | `GET /v2beta/proxy/osrm/route/...` | (öffentlich) |
### Wichtige Regeln (entschieden 2026-05-17)
- **API-Keys liegen NUR LOKAL**, niemals auf dem Server. Schlüssel-
Diebstahl-Risiko bei kompromittiertem Server ist real, Live-Kosten
wären unkontrollierbar. Server hat keine `OPENAI_API_KEY` /
`ELEVENLABS_API_KEY` in der `.env.local`.
- **Asset-Generierung läuft VOR Deployment**, lokal durch Atlas oder
Modul-Instanz. Keine Live-Generation zur Laufzeit.
- Modul speichert generierte Assets in `<modul>/public/assets/`
und committed sie ins Repo.
- Live-Aufrufe an OpenAI/ElevenLabs **aus dem Schüler-Browser sind
verboten** (siehe „Keine KI im Produkt" in Punkt 1).
- Live-Aufrufe an Tile-Proxy / OSRM sind ok (das ist Karten-Lieferung,
keine KI).
### Plattform-Proxy-Beispiel (asset-gen, im Build-Prozess)
```bash
# Modul-Instanz ruft das Plattform-Tool auf
cd v2-modules/<slug>
php ../../v2-platform/tools/asset-gen/image.php \
--prompt "<szenen-suffix>" \
--output public/assets/splash-level1.png \
--resolution 1792x1024
```
Das Tool liest den OpenAI-Key aus `v2-platform/.env.local`, schickt
DALL-E den Prompt-Block + Suffix, speichert das Ergebnis am
gewünschten Pfad. Modul committed das PNG.
---
## 7. Multi-Locale-Strategie
GeoGraSim startet AT-only, ist aber Spec-seitig multi-locale-fähig.
### Locale-Code-Format
`<sprache>-<land>-<variante>`, z.B.:
- `de-AT-standard`, `de-AT-easy` (Pflicht heute)
- `de-DE-standard`, `de-DE-easy` (später)
- `de-CH-standard`, `de-CH-easy` (später)
### Lehrplan-Codes mit Land-Prefix
- `AT-GW-1.4.2` — Österreichischer GW-Lehrplan (Sek I)
- `DE-NRW-GEO-7-3` — NRW-Erdkunde, Klasse 7 (später)
- `CH-LP21-RZG-2.2` — Schweizer Lehrplan 21, Räume Zeiten Gesellschaften (später)
### Lokalisierte Beispiele
Geographische Beispiele in Modulen (z.B. „Wien als Beobachtungsort"
im Sonnensystem) sollen **konfigurierbar** sein:
- `country: "AT"` → Default-Beispielort Wien
- `country: "DE"` → Default-Beispielort Berlin (oder Bundesland-
Hauptstadt)
- `country: "CH"` → Default-Beispielort Zürich
Modul liest `country` aus `/api/student/me` und wählt entsprechende
Beispiele. Wenn das Modul keine geografischen Beispiele hat
(z.B. Logistik mit ganz Europa), spielt das keine Rolle.
### Was heute zu tun ist
- **Sprache**: alle Texte in i18n-Files mit `de-AT-standard` und
`de-AT-easy`
- **Lehrplan**: alle Codes mit `AT-`-Prefix
- **Beispiele**: AT-zentriert, aber nicht „nur AT funktioniert"
hardcoden (z.B. nicht nur österreichische Stadtnamen erlauben)
### Was kommt wenn DE/CH dazu sollen
- **Inhaltsarbeit** (Übersetzungen, neue Lehrplan-Anker einpflegen) —
nicht Code-Refactor
- Neue i18n-Files anlegen
- Neue Beispielort-Mappings
- Neue `country`-Werte in der Plattform freischalten
---
## 9. Barrierefreiheit (Pflicht — Stufe 1 WCAG 2.1 AA)
A11y ist **kein Add-on**, sondern Pflicht für jedes V2-Modul ab Tag 1.
Begründung: EU Web Accessibility Directive verlangt für öffentlich
finanzierte Bildung WCAG 2.1 AA. Außerdem ist nachgereicht-A11y bei
12+ Modulen ein Refactor-Albtraum — heute eingebaut kostet ~5%
Mehraufwand pro Modul, später nachgerüstet ein Vielfaches.
### 9.1 Kontraste (WCAG 2.1 AA)
- **Body-Text auf Hintergrund**: mind. 4.5:1
- **Großer Text (≥ 18px) auf Hintergrund**: mind. 3:1
- **UI-Komponenten (Buttons, Form-Elemente, Icons)**: mind. 3:1
gegen umgebenden Hintergrund
- **Focus-Indikatoren**: mind. 3:1 gegen unfokussierten Zustand
Standard-Tokens müssen das erfüllen — Atlas prüft `--ggs-text` auf
`--ggs-bg` mit axe-core o.ä. im Konformitäts-Check.
### 9.2 High-Contrast-Mode — zwei Varianten (Tri-State)
Plattform liefert **zwei** Token-Sets für High-Contrast:
- **hell** (`data-high-contrast="light"`) — schwarz auf weiß, dunkel-
saturierte Farben (#001a4d, #003300, #800000). Default für
`preferences.highContrast === true`, weil visuell ruhiger und für
die meisten Schüler*innen mit Sehschwäche besser.
- **dunkel** (`data-high-contrast="dark"`) — gelb/grün auf schwarz.
Für Schüler*innen die ein dunkles Schema explizit bevorzugen.
```css
body[data-high-contrast="light"] {
--ggs-bg: #ffffff; --ggs-white: #ffffff;
--ggs-text: #000000; --ggs-text-muted: #000000;
--ggs-fjord: #003366; --ggs-fjord-dark: #001a4d;
--ggs-moss: #1a4d1a; --ggs-coral: #800000;
--ggs-border: #000000;
}
body[data-high-contrast="dark"] {
--ggs-bg: #000000; --ggs-white: #000000;
--ggs-text: #ffffff; --ggs-fjord: #ffff00;
--ggs-moss: #00ff00; --ggs-coral: #ff6060;
--ggs-border: #ffffff;
}
```
Aktiviert via `preferences.highContrast` aus `/api/student/me`. Bei
`true` setzt das Modul den Default `data-high-contrast="light"` und
bietet im Topbar einen **Tri-State-Toggle** an: aus → hell → dunkel →
aus. Schüler*in kann zwischen den beiden HC-Varianten wechseln.
### 9.3 Reduced Motion (Pflicht)
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
```
Plus: **alle Auto-Play-Animationen** (Sonnensystem-Drohnenflug,
Klima-Zeitraffer, Logistik-Tag-Ablauf) brauchen einen sichtbaren
Stop/Pause-Button. Bei `preferences.reducedMotion === true` aus dem
Profil: keine Auto-Play, manueller Start nötig.
### 9.4 Epilepsie-Trigger vermeiden
- Keine Blitze > 3 Hz (3 Wechsel pro Sekunde)
- Keine Vollbild-Farbänderungen (Rot-Schwarz-Wechsel etc.)
- Keine Stroboskop-Effekte
- Bei Explosions-/Crash-Animationen (Heli, Logistik): max. 1 Sekunde
intensives Effekt-Frame, dann Beruhigung
### 9.5 Keyboard-Navigation
Jedes interaktive Element ist per Tastatur erreichbar:
- **Tab/Shift+Tab**: Fokus-Wechsel in logischer Reihenfolge
- **Enter / Space**: aktiviert Buttons und Links
- **Esc**: schließt Modale und Overlays
- **Pfeiltasten**: navigieren in Listen, Tabs, Slider
- **Home/End**: erste/letzte Position in Listen
Kein `tabindex` > 0 (zerstört natürliche Reihenfolge). `tabindex="0"`
für Custom-Widgets erlaubt, `tabindex="-1"` für programmatischen
Fokus.
### 9.6 Focus-Indikatoren
```css
:focus-visible {
outline: 3px solid var(--ggs-fjord-dark);
outline-offset: 2px;
}
/* High-Contrast-Variante */
body[data-high-contrast="true"] :focus-visible {
outline: 3px solid #ffff00;
outline-offset: 2px;
}
```
**Niemals** `outline: none` ohne sichtbaren Ersatz.
### 9.7 Information nicht nur durch Farbe
❌ Nur grüne Markierung für „richtig", nur rote für „falsch"
✅ Grün **plus** Häkchen-Icon, Rot **plus** Kreuz-Icon
Gilt auch für Charts, Karten-Marker, Status-Pills. Daltonismus (8% der
männlichen Bevölkerung) verlangt das.
### 9.8 ARIA-Pattern (Mindeststandard)
- **Buttons**: `<button>` (nicht `<div onclick>`), bei Icon-only zusätzlich `aria-label`
- **Modale**: `<dialog>` oder `role="dialog" aria-modal="true"` mit `aria-labelledby`
- **Toggles**: `aria-pressed="true|false"`
- **Live-Updates** (Score, Telemetry-relevante Hinweise): `<div aria-live="polite">`, kritische Warnungen `aria-live="assertive"`
- **Form-Felder**: `<label for="...">` Pflicht, kein Floating-Label-only
- **Bilder**:
- inhaltlich: `alt="<Beschreibung>"`
- dekorativ: `alt=""` (nicht weglassen!)
- komplexe Diagramme: `alt="<Kurzbeschreibung>"` plus `aria-describedby` auf Lang-Beschreibung
### 9.9 Skalierbarer Text
- Body-Text in `rem` (basiert auf User-Browser-Zoom)
- Layout muss bei **200% Browser-Zoom** noch funktionieren (kein
horizontales Scrolling, keine abgeschnittenen Buttons)
- Touch-Ziele schon ≥ 36 px (haben wir), bei kritischen Buttons ≥ 44 px
- Min-Schriftgröße im Body: `0.95rem` (≈ 15.2 px)
### 9.10 Profil-Settings (über `/api/student/me`)
```json
"preferences": {
"soundOn": true,
"musicOn": false,
"highContrast": false,
"reducedMotion": false,
"screenReader": false,
"textScale": "normal" // "normal" | "large" | "xlarge"
}
```
`screenReader: true` bedeutet: Schüler*in nutzt Screen-Reader. Modul
soll dann visuelle Verzweigungen (z.B. „klicke auf das gelbe Land")
durch alternative Formulierungen ersetzen oder einen Hinweis an die
Lehrperson via Telemetry schicken (siehe unten).
### 9.11 Telemetry-Erweiterung für A11y
Wenn ein Modul für eine konkrete Schüler*in Barrieren erkennt, die
nicht überwindbar sind (z.B. Modul ist visuell-zwingend, Schüler*in
nutzt Screen-Reader), soll es ein neues Telemetry-Event emittieren:
```json
{
"type": "accessibility-blocker",
"moduleSlug": "...",
"blockerType": "visual-required" | "audio-required" | "mouse-required",
"hint": "Karten-Tap nicht per Tastatur ersetzbar in dieser Version",
"ts": "..."
}
```
Lehrer-Cockpit zeigt das prominent — Lehrperson kann der Schüler*in
ein anderes Modul oder eine offline-Alternative geben.
### 9.12 Roadmap (Stufe 2 + 3 — nicht heute Pflicht)
Modul-Instanzen sollen heute schon stufe-2-kompatibel bauen:
- **Stufe 2** (V2 stable, Modul für Modul nachziehen):
- Vollständige Screen-Reader-Verträglichkeit (NVDA, VoiceOver getestet)
- Live-Regions für Score-Updates und Phase-Wechsel
- Lehrer-A11y-Cockpit (sieht pro Schüler*in welche A11y-Settings aktiv sind, kann Modul-Vorschläge filtern auf „barrierefreie" Module)
- AAA-Kontrast-Mode (7:1)
- Erweiterte Schrift-Skalierung
- Sprachausgabe-Toggle pro Modul (TTS für alle Aufgaben-Texte)
- **Stufe 3** (Forschungs-Track, später):
- Audio-First-Varianten ausgewählter Module für blinde Schüler*innen
(binaurales Audio, sonifizierte Karten/Diagramme)
- Gebärdensprach-Videos für gehörlose Schüler*innen
- Eigene Module für besondere Bedürfnisse
Recherche-Snapshot zu Stufe 3 liegt in
`memory/project_a11y_audio_first_research.md` (für spätere
Verwendung — kein heutiger Implementierungs-Auftrag).
### 9.13 Konformitäts-Check (Stufe 1)
Atlas prüft beim Lieferungs-Empfang automatisiert:
1. ✅ **axe-core-Scan** auf gerendertem Modul-DOM (keine Critical/Serious-Issues)
2. ✅ **Kontrast-Audit** aller Text/Hintergrund-Kombinationen ≥ 4.5:1
3. ✅ **Keyboard-Navigation-Test**: Tab-Reihenfolge erreicht alle interaktiven Elemente
4. ✅ **Focus-Indikator vorhanden** (kein `outline: none` ohne Ersatz)
5. ✅ **`prefers-reduced-motion` respektiert** (Headless-Browser-Test mit gesetztem Flag)
6. ✅ **High-Contrast-Mode-Test**: Modul mit `body[data-high-contrast="true"]` rendert noch alle Texte sichtbar
7. ✅ **Alt-Texte vorhanden** auf allen `<img>` (auch leere für dekorative)
8. ✅ **Semantische Buttons**: keine `<div onclick>` für interaktive Aktionen
Bei Verstoß: Lieferung wird abgewiesen. A11y ist nicht verhandelbar.
---
## 11. Gemeinsame Ressourcen — Shared-Asset-Pool
Damit nicht jedes Modul, das Wien zeigt, sein eigenes Wien-Bild
generiert: Atlas pflegt einen zentralen Pool unter
`v2-platform/assets/shared/`, alle Module verlinken via URL.
### Pool-Kategorien
```
v2-platform/assets/shared/
├── cities/ ← Stadt-Bilder im GeoGraSim-Bildstil (1792×1024 PNG)
├── icons/ ← UI-Icons (SVG vorzugsweise)
├── glossar/ ← Glossar-Bilder (160 aus V1, Migration Welle 1)
├── bg-music/ ← Suno-Hintergrundmusik
└── ui-sounds/ ← UI-Feedback-Töne (Phase 2)
```
Pro Unterordner ein `PROVENIENZ.md`-File mit Inventar (welches Asset
wann von wo, Lizenz, welche Module nutzen es).
### Modul-Nutzung
Manifest deklariert `sharedAssets` als Map:
```json
"sharedAssets": {
"cities": ["wien", "innsbruck"],
"bg-music": ["fjord-calm"]
}
```
URL-Schema im Modul-Code: `/v2beta/assets/shared/<kategorie>/<slug>.<ext>`.
### Workflow „Asset noch nicht im Pool"
1. Modul-Instanz pingt Atlas in `_inbox/zentrale/`:
*„Brauche 'linz' im Cities-Pool. Verwendung: Logistik-V2-Auftrag."*
2. Atlas generiert lokal mit DALL-E (`tools/asset-gen/image.php …`),
committet ins Pool
3. Atlas antwortet mit URL + Inventar-Eintrag in `PROVENIENZ.md`
4. Modul-Instanz ergänzt `sharedAssets`-Manifest
### `.humanInput/` als Rohstoff-Quelle
Thomas pflegt `.humanInput/` als persönliches Werkstatt-Lager
(Audio-Files, Sprites, Pflichtenhefte, Prototyp-HTMLs). Das ist
**nicht** Teil des Repository-Deployment, sondern Vorrats-Sammlung.
Wenn ein Asset von dort in V2 wandert:
- **Modul-spezifisch** → kopiert nach `v2-modules/<slug>/public/assets/`
- **Geteilt** → kopiert nach `v2-platform/assets/shared/<kategorie>/`
- Provenienz in Modul-`docs/ASSET-PROVENIENZ.md` oder Pool-Inventar
`.humanInput/` selbst bleibt unverändert — auch wenn ein Asset schon
verbaut ist, bleibt das Original liegen als Backup.
### Konformitäts-Check
Atlas prüft beim Lieferung-Empfang: alle in `sharedAssets` deklarierten
Assets müssen im Pool existieren. Wenn nicht: Lieferung wird
abgewiesen mit konkretem Hinweis, was Modul-Instanz bei Atlas
bestellen muss.
### Was NICHT in den Shared-Pool gehört
- **Modul-spezifische Assets** (Modul-Logo, modul-eigene Sprites) →
`v2-modules/<slug>/public/assets/`
- **Avatare** → eigene Top-Level-Sektion `v2-platform/assets/avatars/`
(kein `shared/`, weil schon etabliert)
- **Schüler-Uploads** → `v2-platform/uploads/<slug>/student-<id>/`
---
## 10. Sprachregeln im Detail
### Lehrer-Anrede
- Du-Form für Lehrpersonen (modern, partnerschaftlich)
- „Lehrperson" / „Lehrperson" geschlechtsneutral, NICHT „Lehrer"
als Default
### Schüler-Anrede
- Du-Form für Schüler*innen
- „Schüler*in" mit Doppelpunkt-Form geschlechtsinklusiv
- Im Easy-Sprache-Modus: Du-Form, kurze Sätze, „Schüler" oder
„Kind" je nach Kontext (Doppelpunkt-Form ist für Easy-Sprache
schwer lesbar — Atlas-Empfehlung: in Easy „du" oder direkter
Plural „die Kinder")
### Tonalität
- Freundlich, aber nicht infantil
- Fehler nicht als „falsch" → „Probiere es nochmal" / „Schau dir
das nochmal an"
- Erfolg nicht als „toll, gewonnen" → „Geschafft" / „Ziel erreicht"
---
## Konformitäts-Check für diese Standards
Atlas prüft beim Konformitäts-Check (siehe [delivery-format.md](delivery-format.md)):
1. ✅ `viewport-fit=cover` im `<meta viewport>`
2. ✅ Alle Touch-Targets ≥ 36 px (auto-Scan)
3. ✅ Modale nutzen `dvh` und `safe-area-inset-bottom`
4. ✅ Keine hardcodierten Hex-Werte (nur `var(--ggs-*)` oder
`var(--<modul>-*)`)
5. ✅ Lexikon-Scan in i18n-Files: keine Spielsprache (siehe Punkt 1)
6. ✅ Keine `fetch('https://api.openai.com/...')` o.ä. im Modul-Code
(außer expliziter Plattform-Proxy)
7. ✅ Bildstil-Eyeballing (manueller Check durch Atlas: passen die
Bilder zum Flat-Scandinavian-Look)
8. ✅ Easy-Sprache-i18n vollständig (kein Schlüssel fehlt)
---
## ✅ Geklärt mit Thomas (2026-05-17)
- **Hex-Werte strikt blockieren**: ja, im Konformitäts-Check verboten.
Modul-eigene Spezialfarben als `--<modul>-*`-CSS-Variablen lokal,
Atlas pflegt Whitelist pro Modul. Hex direkt im Code → Lieferung
abgewiesen.
- **Zentrale Sound-Library**: Phase-2-TODO. Heute: Module nutzen
eigene Sounds, Atlas dokumentiert. In Phase 2 entsteht
`v2-platform/assets/sounds/`-Library mit UI-Standardtönen.
- **Multi-Locale Country-Erkennung**: nicht aus IP/Domain raten —
zu fehleranfällig. `country` bleibt Profil-Setting (von Lehrperson
beim Anlegen der Klasse, vererbt auf Schüler*innen, im Schüler-
Profil änderbar).
- **Suno-Musik**: bleibt manuell durch Thomas (Suno hat keine saubere
API, Musik-Wahl ist kreative Entscheidung).
- **ElevenLabs-Stimmen-Pool**: Atlas pflegt 35 deutsche Stimmen
(„Erzählerin warm", „Erzähler sachlich", „Kind freundlich") in
Plattform-Konfig. Module geben Pool-ID an, kein eigenes Stimmen-
Picking. Konsistenz + Wahlfreiheit.