---
type: prinzip
agent_ready: true
description: "Eiserne Layout-Regeln für alle HTML-Präsentationen aus Stefans Second Brain (Warm Navigator Deck v1). Definiert Header-Zone, SigLine-Konsistenz und Footer-Safe-Zone als nicht verhandelbare Regeln. Wird vom Skill neue-praesentation als Pflicht-Lektüre referenziert. Verhindert Layout-Pannen wie springende Designlinien oder Inhalts-Footer-Kollisionen."
tags:
  - prinzip
  - designsystem
  - praesentation
  - layout
created: 2026-05-05
updated: 2026-05-05
---

# Layout-Regeln Warm Navigator Deck

Eiserne Regeln für jede HTML-Präsentation aus dem Vault. Diese Karte ist das Gegenstück zu den Code-Templates unter `Templates/Praesentation/`. Was hier steht, ist nicht verhandelbar — bei Verstößen wirkt das Deck unruhig und unprofessionell, egal wie gut die Inhalte sind.

## 0. Umlaut-Regel (HÖCHSTE PRIORITÄT)

In allen Folien-Inhalten zwingend echte Unicode-Zeichen für deutsche Umlaute und Eszett verwenden: **ä ö ü Ä Ö Ü ß**. Niemals als Ersatz "ae", "oe", "ue", "Ae", "Oe", "Ue", "AE", "OE", "UE" oder "ss" statt "ß". Diese Regel überschreibt alle anderen, gilt auch in JSX-Strings, in Frontmatter, in Kommentaren, in Datei-Inhalten. Vor jedem Build mental prüfen: stehen irgendwo "ae"/"oe"/"ue" als Umlaut-Ersatz oder "ss" wo "ß" hingehört? Falls ja, korrigieren. Hintergrund: globale Vault-Regel aus `~/.claude/CLAUDE.md`, mehrfach von Stefan eingefordert. Verstöße sind nicht tolerierbar.

Pflicht-Check beim Bauen: nach `esbuild` einmal über alle JSX-Quellen `grep -E '[Aa]e[a-z]|[Oo]e[a-z]|[Uu]e[a-z]'` (manuell oder per Skript) und **jeden Treffer einzeln** prüfen. Kein Filter-Bypass per "vermutlich okay"-Liste — sonst rutscht z.B. `Aelteren` durch, weil es mit "Aufsteller" oder "ausser" kollidiert. Treffer wie "fuer", "koennen", "muessen", "ueber", "Aussen", "draussen", "Massnahme", "Aelter", "Aerm", "Oeffnung" gegen Eigennamen-Whitelist (z.B. `Soeren`, `Goethe`, `aap`) prüfen. Was nicht Eigenname ist, muss Umlaut sein.

## 0b. Natur-Sprech-Check (PFLICHT bei jedem Slide-Inhalt)

Jeder Folien-Inhaltstext (Headlines, Body, Bullet-Texte, Pill-Labels, Quotes, alles im DOM-Output) ist eine nach außen gerichtete Kommunikation und unterliegt damit zwingend dem Skill `natur-sprech-check` Modus B. Der Skill muss vor dem Schreiben der JSX-Inhalte geladen werden, die Fallen-Liste aus `00 Kontext/KI-Sprech-Fallen.md` und der Schreibstil aus `00 Kontext/Schreibstil.md` müssen beim Formulieren mental gegengeprüft werden.

Häufigste Verstöße in Folien-Inhalten (Pflicht-Check vor jedem Build):

- **Falle #4 — Komma vor "und"/"oder"** bei gleichrangigen Hauptsätzen oder Aufzählungen. Im Deutschen falsch oder schwer wirkend, typischer KI-Anglizismus. Grep-Check: `grep -nE ', (und|oder)\b'`. Treffer einzeln prüfen — bei zwei Hauptsätzen mit "und" lieber den Satz teilen.
- **Falle #5/#6 — Doppelpunkt mitten im Satz als Pointen-Einleitung** oder Meta-Ansage ("Wirkung: …", "Vorbemerkung: …", "Eindruck: …", "Auffällig: …", "Zum Vergleich: …", "Warum das die beste Investition ist: …"). Sehr verräterisch. Pointe direkt liefern, Doppelpunkt auflösen.
- **Falle #18 — Doppelpunkt in normaler Prosa generell sparsam.** Legitim nur (a) vor Bullet Points/echten Aufzählungen, (b) vor direkter Rede. Alles andere als vollen Satz formulieren.
- **Falle #10 — Drei-Adjektiv-Ketten** ("klar, schnell, effizient"). Auflösen.
- **Falle #11 — Antithese als Zwei-Satz-Konstrukt** ("Es ist nicht X. Es ist Y."). In Folien-Body vermeiden, in Headlines als Schlagzeilen-Handwerk erlaubt.
- **Falle #15 — Bemühte Metaphern** ("wie ein Anker im Sturm"). Streichen, konkret formulieren.
- **Falle #17 — Substantivierungen** statt aktiver Verben ("die Umsetzung erfolgt"). In aktive Hauptsätze wandeln ("wir setzen um").

Pflicht-Check beim Bauen: nach esbuild einmal `grep -nE ', (und|oder)\b'` und `grep -nE '[a-zäöü]+: [a-zäöüA-ZÄÖÜ]'` über alle JSX-Quellen laufen lassen. Alle Treffer im Folien-Body prüfen. Was nicht Doppelpunkt vor Liste oder direkter Rede ist und keine Komma-vor-und-Ausnahme erfüllt, umformulieren.

Hintergrund: Folien sind Kommunikation an einen externen Empfänger. Externe Kommunikation triggert Modus B des Skills `natur-sprech-check` automatisch (siehe Skill-Karte). Mehrfach von Stefan eingefordert. Verstöße sind nicht tolerierbar.

## Drei eiserne Konsistenz-Achsen

Jede Inhaltsfolie hat drei Zonen mit fester Y-Position: **Header oben, Inhalt mitte, Footer unten**. Header und Footer dürfen zwischen Folien NIEMALS springen, der Inhalt fließt dazwischen — aber nie in die Footer-Zone hinein.

## 1. Header-Zone — `.slide-head`

### Regel

Eyebrow, H2 und SigLine bilden zusammen die **Header-Zone**. Sie ist auf jeder Inhaltsfolie gleich aufgebaut und hat eine konsistente Y-Position.

### Mechanik

```jsx
<div className="slide-head anim-in">
  <div className="eyebrow">Kapitel · Untertitel</div>
  <h2>Titel der Folie</h2>
  <SigLine />
</div>
```

- **Eyebrow** (`.eyebrow`) sitzt oben mit fixem `margin-bottom: 24px`.
- **H2** hat `min-height: 140px` (zwei Zeilen Reserve), damit ein- und zweizeilige Titles **gleich hoch** sind.
- **SigLine** sitzt direkt unter H2 mit natürlichem `margin-top: 28px`. **Niemals** `margin-top: auto` — das drückt die Linie unkontrolliert nach unten.

### Folien ohne H2 (Big-Number-Stats)

Pflicht-Platzhalter einbauen, damit SigLine auf gleicher Y-Position sitzt wie auf normalen Folien:

```jsx
<div className="slide-head anim-in">
  <div className="eyebrow">Beweis 1 · ...</div>
  <div className="slide-head__title-placeholder" aria-hidden="true" />
  <SigLine />
</div>
```

### Was NICHT geht

- ❌ `<div className="anim-in">` ohne `slide-head`-Wrapper (Header springt)
- ❌ Eyebrow und H2 mit eigenem `gap` zwischen Container-Children, statt der CSS-definierten Margins
- ❌ Stat-Folien ohne Title-Platzhalter
- ❌ SigLine außerhalb des `slide-head`-Containers (außer Pull-Quote-Sonderfälle)

### Pull-Quote-Sonderfälle

Cover, CTA, Reframe, Elevator-Pitch sind bewusst zentriert/anders aufgebaut und nutzen `.slide-head` **nicht**. Das ist OK — ihre Konsistenz ergibt sich aus dem Pull-Quote-Layout selbst.

### Eyebrow mit Indikator-Punkt (Ampel) — `.eyebrow-dot`

Wenn vor dem Eyebrow-Text ein farbiger Indikator-Punkt sitzen soll (z.B. Ampel für Befund-Schwere, Kapitel-Status, Severity-Marker), ist die **Pflicht-Mechanik** der Inline-Punkt direkt im Eyebrow-Text — **nicht** ein separates Flex-Element neben dem Eyebrow.

#### Mechanik (Pflicht)

```jsx
<div className="eyebrow">
  <EyebrowDot tone="red" /> Beobachtung 01 · §92 AktG
</div>
```

Oder als reines Markup ohne den React-Helper:

```jsx
<div className="eyebrow">
  <span className="eyebrow-dot" data-tone="red" aria-hidden="true" /> Beobachtung 01 · §92 AktG
</div>
```

#### Tone-Varianten

| Wert | Farbe | Verwendung |
|---|---|---|
| `red` (Default) | `--sem-negative` (gedämpftes Rotbraun) | sehr hohe Schwere, Pflichtverstoß, harter Widerspruch |
| `orange` / `gold` | `--c-gold` | hohe Schwere, fragwürdige Bewertung |
| `green` | `--accent` (Teal) | positiver Anker, „gut gemacht" |

Knallige Ampel-Farben (`#FF0000`, `#00FF00`) sind **verboten**, siehe Designsystem-Goldene-Regeln. Der `.eyebrow-dot` mappt automatisch auf die Warm-Navigator-Palette.

#### Warum diese Mechanik (nicht Flex)

Ein als Flex-Sibling positionierter Punkt mit `alignItems: center` zentriert sich auf die **Box-Höhe** der Eyebrow inklusive Line-Height-Padding. Bei Uppercase-Text mit `line-height: 1.4` ist diese Box deutlich höher als die optische Buchstaben-Höhe (Cap-Height) — der Punkt wandert dadurch ca. 4–6 px unter die optische Mitte der Schrift.

Der `.eyebrow-dot` als inline-block direkt im Text-Flow nutzt `vertical-align: 0.08em`, was font-size-unabhängig und unabhängig von der Container-Mechanik korrekt auf der Schrift-Mittelachse sitzt. Größe ist mit `width: 0.55em` em-basiert und skaliert damit automatisch mit `--fs-scale`.

#### Was NICHT geht

- ❌ Punkt als separates Flex-Element mit `<Ampel />` neben dem Eyebrow-`<div>`
- ❌ Punkt-Position über `marginTop`, `translateY` oder `position: absolute` manuell justieren
- ❌ Punkt-Größe in `px` setzen (skaliert nicht mit `--fs-scale`)
- ❌ Eigene Hex-Farben für den Punkt — nur Designsystem-Tokens (`--sem-negative`, `--c-gold`, `--accent`)

#### Lehrfall 2026-05-10 (Marc-Langner-Präsentation)

Initiale Befund-Folien wurden mit Flex-Layout `<Ampel /> + <div className="eyebrow">` gebaut. Der Punkt saß optisch deutlich zu tief, weil Flex-Center die Line-Height-Box zentriert, nicht die Cap-Height-Mitte. Mehrere Korrekturversuche (`lineHeight: 1` auf Wrapper, dann auf Eyebrow, dann Ampel kleiner) brachten keine zufriedenstellende Position. Auflösung: Punkt ins Text-Flow integriert via `.eyebrow-dot`-Klasse. Seither sauber auf der Schrift-Mittelachse. Helper-Komponente `EyebrowDot` und CSS-Klasse jetzt im Master-Template, damit das Problem nicht wieder entsteht.

## 2. SigLine — Designlinie

### Regel

Die SigLine ist der angedeutete Schluss-Strich der Header-Zone. Sie hat eine **immer gleiche Höhe und Standardbreite**.

### Spezifikation

| Eigenschaft | Wert | Ausnahme |
|---|---|---|
| Höhe | **2 px** | keine |
| Standard-Breite | **120 px** | Pull-Quote-Slides |
| Cover/CTA-Breite | 220 px | nur dort |
| Reframe-Breite | 180 px | nur dort |
| Farbverlauf | Teal → Gold → transparent | immer (`.sig-line` Klasse) |
| Margin-Top im `slide-head` | 28 px | nicht überschreiben |

### Was NICHT geht

- ❌ `<SigLine width={80} />` auf normalen Inhaltsfolien (Stat-Slides früher → springt sichtbar)
- ❌ `<SigLine width={56} />` (zu kurz, wirkt verloren)
- ❌ Eigene `height` oder `background` per Inline-Style

### Pflicht-Check vor Auslieferung

Beim Durchklicken aller Folien darf die SigLine optisch **nicht springen** — weder in Y-Position noch in Breite. Wenn sie springt, verletzt das Layout eine der beiden Regeln oben.

## 3. Footer-Safe-Zone — `--safe-footer` (EISERNE REGEL)

### Regel

Der Inhaltsbereich (`.frame`) darf **niemals** in den Footer-Bereich hineinragen. Es muss eine sichtbare Sicherheitsluft zwischen Inhalt und Footer bleiben. **Diese Regel hat keinen Verhandlungsspielraum.** Bei Konflikt zwischen Inhaltsmenge und Safe-Zone gewinnt immer die Safe-Zone.

### Mechanik

CSS-Variablen und Frame-Definition in `theme.css`:

```css
:root {
  --safe-footer: 170px;
  --safe-top:    72px;
}

.frame {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--safe-top) 120px var(--safe-footer);
  gap: 32px;
  position: relative;
  overflow: hidden;
}
```

Drei Werte sind **eiserne Untergrenzen** und dürfen nicht gesenkt werden.

| Wert | Untergrenze | Warum |
|---|---|---|
| `--safe-footer` | **170 px** | Footer-Chrome wächst mit `fs-scale` auf bis zu 40 px Höhe; 170 px Padding-Bottom geben ca. 75 px Reserve. |
| `--safe-top` | **72 px** | Header-Eyebrow plus erste Headline brauchen Atmungsraum oben, sonst wirkt der Header gequetscht. |
| `.frame { gap }` | **32 px** | Bei vier Inhalts-Blöcken summieren sich die Gaps schnell auf 100+ px; mit 32 px statt 48 px bleibt der entscheidende Puffer zur Footer-Safe-Zone. |

### Berechnung der Sicherheits-Lücke

- Slide-Höhe: **1080 px**
- Footer (`.chrome`): position absolute, `bottom: 44px`, Höhe je nach `fs-scale` ca. **30–40 px** → reicht bis 74–84 px vom unteren Rand
- Frame-Padding-Bottom: **170 px** → Inhalt endet bei 910 px (= 170 px vom unteren Rand)
- **Sicherheits-Lücke: ca. 75 px** zwischen Inhalt-Ende und Footer-Top, auch bei skaliertem Footer

### Verbotene Inline-Overrides

Auf `.frame` darf man inline überschreiben — aber nur **vergrößernd**:

- ✅ `style={{ padding: '100px 120px 200px' }}` — Bottom 200 ≥ 170, ok
- ❌ `style={{ padding: '100px 120px 120px' }}` — Bottom 120 < 170, verboten
- ❌ `style={{ paddingBottom: 100 }}` — verboten

Dasselbe gilt für `gap` auf `.frame` und für jede Hero-Slide mit eigenem padding (Bottom-Wert immer ≥ 140 px).

### Was NICHT geht

- ❌ Frame-Padding-Bottom kleiner als `--safe-footer` setzen
- ❌ Inhalts-Container mit `position: absolute` in den Footer-Bereich legen
- ❌ Inhalts-Karten oder Grids, die größer sind als `1080 - safe-top - safe-footer = 838 px`
- ❌ Animationen, die Inhalt aus der Safe-Zone heraus in den Footer-Bereich schieben
- ❌ Hero-Slides mit `padding: '120px'` (Bottom 120 < 140 px Mindest-Reserve für Hero)

### Wenn der Inhalt nicht passt

Wenn ein Slide-Inhalt die 838-px-Höhe überschreitet, **niemals** die Safe-Zone reduzieren, sondern:

1. Inhalt verdichten (kürzere Body-Texte, Card-Padding `20px 24px` statt `24px 28px`, body--sm statt body)
2. Auf zwei Folien splitten — eine Sub-Folie für die Fußnote oder die letzte Karte
3. Anderen Slide-Typ wählen (z.B. 2-spaltig statt 4-Karten-Grid, Donut-Chart statt Tabelle)
4. Eine Hero-Slide mit Bild im Hintergrund nehmen, die den Inhalt visuell reduziert

### Pflicht-Grep nach jedem Build

```bash
# Frame-Padding-Bottom kleiner als 170 → Verstoß
grep -nE "padding:\s*['\"][^'\"]*\s+(1[0-6][0-9]|[1-9][0-9])px['\"]" src/slides-*.jsx | grep -v "px 120px" | head

# safe-footer-Override in Inline-Style → Verstoß
grep -nE "paddingBottom:\s*([1-9][0-9]?|1[0-6][0-9])\b" src/slides-*.jsx | head
```

Wenn ein Treffer auftaucht, der nicht auf einer Hero-Slide mit `padding: '... 140px'` oder größer liegt, ist es ein Regelbruch. Build wird nicht ausgeliefert, bevor der Treffer gefixt ist.

### Lehrfall 2026-05-06 (Slide06 Leierkasten-Konzept)

Frühere Werte (`--safe-footer: 110`, `--safe-top: 88`, `gap: 48`) waren in der Theorie ausreichend, in der Praxis aber zu knapp. Bei einer Folie mit Header + Stat-Reihe + 2x2-Quote-Grid + Fußnote summierten sich Header-Höhe (140) + 3 Frame-Gaps (144) + Inhaltsblöcke auf >970 px Frame-Inhalt — und die Fußnote rutschte sichtbar in den Chrome-Bereich. Lösung: globaler Eingriff (`safe-footer: 170`, `safe-top: 72`, `gap: 32`) plus Slide-spezifisches Aufräumen (Fußnote ohne extra `marginTop`). Seither stabil.

## A4-PDF (druckoptimiert, randlos) — Pflicht-Mechanik

Wenn Stefan ein druckoptimiertes A4-PDF einer Präsentation verlangt (Trigger: „DIN A4", „A4 quer", „druckoptimiert", „druckfähig", „A4-Variante", „PDF zum Ausdrucken"), gilt zwingend:

1. **Helper `print-to-a4-pdf.py`** verwenden, nicht `print-to-pdf.py` und nicht den Browser-Druckdialog. Der Helper rendert in 1920×1358 px (A4-quer-Aspect 1.4143:1) statt 1920×1080 px (16:9) und hängt `?mode=a4` an die URL an.
2. **`theme-a4.css` muss im Bundle (`_runtime/`-Ordner) liegen.** Der `?mode=a4`-Hook in `deck-stage.js` lädt diese Datei zur Laufzeit nach, ohne sie bleibt die Slide im 16:9-Layout und das A4-PDF hat weiße Ränder unten.
3. **Vor jedem A4-PDF-Aufruf** prüfen, ob `theme-a4.css` im Bundle existiert. Falls nicht, aus dem Master nachkopieren — alle Bundles, die vor 2026-05-10 mit `neue-praesentation.py` erzeugt wurden, haben sie nicht.

### Was NICHT geht

- ❌ `print-to-pdf.py` für A4-Ausgabe (rendert in 16:9, A4 hat dann Letterbox)
- ❌ Browser-Druckdialog mit „Auf Seitengröße skalieren" (verzieht das Layout)
- ❌ A4-PDF ohne `theme-a4.css` im Bundle (weiße Ränder unten, 1080→1358 px Differenz)
- ❌ Nachträgliches Skalieren einer 16:9-PDF auf A4 (lässt 4:1-Bereich oder Letterbox)

### Lehrfall 2026-05-10 (Marc-Langner-Präsentation)

Das A4-PDF zeigte weiße Ränder unten, obwohl der A4-Helper aufgerufen wurde. Ursache: `neue-praesentation.py` kopierte `theme.css` ins Bundle, aber **nicht** `theme-a4.css`. Der `?mode=a4`-Hook in `deck-stage.js` konnte sie damit nicht nachladen, die Slide blieb im 16:9-Layout. Fix: `theme-a4.css` zu `RUNTIME_FILES` in `neue-praesentation.py` hinzugefügt, alle neuen Bundles bekommen sie ab jetzt automatisch mit. Altbundles brauchen einen einmaligen `cp theme-a4.css` aus dem Master.

## Pflicht-Check beim Bauen einer Präsentation

Vor jedem Soft-Launch eines Decks (Versand, Vortrag, Online-Abnahme) der Stefan-Augen-Test:

1. **Durchklicken aller Folien** — Springt die SigLine in Y-Position oder Breite? Springt die Eyebrow?
2. **Footer-Test** — Berührt irgendein Inhaltselement (Karte, Text, Bild) den Footer? Falls ja: Inhalt verdichten. Niemals die Safe-Zone reduzieren. Diese Regel wird hart durchgesetzt.
3. **Header-Test** — Bei einzeiliger H2 vs. zweizeiliger H2: Sitzt die SigLine an gleicher Position?
4. **Stat-Folien-Test** — Sitzt die SigLine bei Big-Number-Stats genauso wie bei Title-Folien?
5. **Hero-Slide-Test** — Hat jede Hero-Slide (data-mode="dark") `padding-bottom` ≥ 140 px im Inline-Style? Bei `'120px'` rundherum ist der Footer in Gefahr.

Wenn ein Test versagt, liegt es fast immer an einer Verletzung der drei Regeln oben.

## Verknüpfungen

- [[../00-Einstieg|Designsystem-Einstieg]]
- [[../../../.claude/skills/neue-praesentation/SKILL|Skill neue-praesentation]] — referenziert diese Karte als Pflicht-Lektüre
- [[../Tokens/00-Tokens|Tokens]] — Farb-, Typo-, Spacing-Tokens
- Code-Templates: `slides-a.jsx`, `slides-b.jsx`, `theme.css` im selben Ordner
