Add full deck, config tool, and updated design docs
Adds the complete "KI verstehen" presentation (36 slides), the Präsentations-Konfigurator (config.html + slides-manifest.js) for curating which slides to show, and updates DESIGN.md/PATTERNS.md/ deck-template.html to reflect the new house font (General Sans) and newly established patterns (chapter dividers, term tooltips, the mitmach game, ambient sound, and the slide configurator).
This commit is contained in:
248
DESIGN.md
Normal file
248
DESIGN.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# CANCOM HTML Deck — Design System
|
||||
|
||||
Verbindliche Grundlage für alle HTML-Präsentationen im CANCOM-Look.
|
||||
Referenz-Implementierung: `cancom-html-vs-pptx-v7.html`
|
||||
Ausgebautes Praxisbeispiel (36 Slides, Kapitel-Trenner, Mitmach-Spiel, Begriffs-Tooltips,
|
||||
Präsentations-Konfigurator, Ambient-Sound): `ki-verstehen.html` + `config.html` + `slides-manifest.js`
|
||||
Startpunkt für neue Decks: `deck-template.html`
|
||||
Copy-Paste-Bausteine: `PATTERNS.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Grundprinzipien
|
||||
|
||||
1. **Ein File.** Kein Build, kein Bundler, keine Node-Dependencies. HTML + CSS + JS in einer Datei, per Doppelklick lauffähig, per Mail/Teams/SharePoint verteilbar. Einzige externe Abhängigkeit: die Fonts von Fontshare (mit lokalem Fallback).
|
||||
2. **Feste Bühne, skaliert.** Jede Slide ist exakt 1920×1080 px. Nichts wird responsiv umgebrochen — die gesamte Bühne wird per `transform: scale()` in den Viewport gerechnet. Dadurch sieht das Deck auf jedem Screen und jedem Beamer pixelidentisch aus.
|
||||
3. **Design in Tokens.** Farben, Fonts, Easings stehen ausschließlich in `:root`. Keine Hex-Codes im Slide-Markup. Ein neues Kunden-Theme = neue Token-Werte, kein Umbau.
|
||||
4. **Animation ist Argument.** Das Deck ist ein Beweis dafür, dass HTML mehr kann als PPTX. Jede Slide sollte mindestens eine Sache tun, die eine PowerPoint-Folie nicht kann — Live-Daten, echte Interaktion, GPU-Animation.
|
||||
5. **Ehrlichkeit im Ton.** Deutsch, direkt, kein Marketing-Sprech. Headlines sind kurze Sätze mit Punkt am Ende („PPTX ist Vergangenheit."), nicht Substantiv-Ketten.
|
||||
|
||||
---
|
||||
|
||||
## 2. Farb-Tokens
|
||||
|
||||
| Token | Wert | Verwendung |
|
||||
|---|---|---|
|
||||
| `--cancom-red` | `#E4002B` | Signalfarbe. Akzente, Zahlen, Eyebrows, genau **ein** Highlight pro Headline |
|
||||
| `--cancom-red-glow` | `rgba(228,0,43,0.55)` | `box-shadow` / `text-shadow` Glow |
|
||||
| `--cancom-red-dim` | `rgba(228,0,43,0.15)` | Flächige Rot-Hinterlegung, Hover-Auras |
|
||||
| `--ink` | `#0A0A0F` | Standard-Slide-Hintergrund |
|
||||
| `--ink-soft` | `#14141C` | Erhöhte Flächen, Hover-States |
|
||||
| `--ink-line` | `#23232E` | Alle Rahmen und Trennlinien |
|
||||
| `--paper` | `#F5F5F2` | Primärtext auf Dunkel, Hintergrund der Closing-Slide |
|
||||
| `--paper-dim` | `rgba(245,245,242,0.6)` | Fließtext, Lead-Absätze |
|
||||
| `--paper-mute` | `rgba(245,245,242,0.35)` | Labels, Slide-Nummern, HUD |
|
||||
| `--accent-cool` | `#4CC9F0` | Zweitfarbe in Charts und Code-Highlighting |
|
||||
| `--accent-warm` | `#FFB627` | Drittfarbe, Flash-States |
|
||||
|
||||
**Regeln**
|
||||
|
||||
- Rot ist Signal, nicht Dekoration. Pro Slide maximal ein rotes Wort in der Headline.
|
||||
- Rot nie als große Textfläche — nur Headline-Akzente, Zahlen, Linien, Glows.
|
||||
- Semantische Ausnahmen sind erlaubt und stehen bewusst außerhalb der Marke: `#4ade80` (grün, Kurs steigt) und `#ff5060` (hellrot, Kurs fällt).
|
||||
- Die Closing-Slide dreht das Schema um: `--paper` als Hintergrund, `--ink` als Text. Das ist der einzige helle Slide — er markiert das Ende.
|
||||
|
||||
---
|
||||
|
||||
## 3. Typografie
|
||||
|
||||
Drei Schriften, drei klar getrennte Jobs:
|
||||
|
||||
| Token | Font | Job |
|
||||
|---|---|---|
|
||||
| `--font-display` | General Sans (700/600/500) | Alle Headlines, Zahlen, Buttons, Brand-Marks |
|
||||
| `--font-body` | Satoshi (700/500/400) | Fließtext, Lead-Absätze, Listen |
|
||||
| `--font-mono` | JetBrains Mono (700/500/400) | Eyebrows, Labels, HUD, Code, alles Technische |
|
||||
|
||||
### Type-Scale (bei 1920×1080)
|
||||
|
||||
| Rolle | Größe | Line-Height | Letter-Spacing |
|
||||
|---|---|---|---|
|
||||
| Title-Headline | 220 px | 0.88 | −0.045em |
|
||||
| Closing-Headline | 240 px | 0.86 | −0.045em |
|
||||
| Counter-Value | 220 px | 0.90 | −0.05em |
|
||||
| Slide-Title | 112 px (eng: 92 px) | 0.94 | −0.035em |
|
||||
| Versus-Headline | 100 px | 0.92 | −0.035em |
|
||||
| Card-Title | 42 px | 1.05 | −0.02em |
|
||||
| Lead-Absatz | 30 px (eng: 22–24 px) | 1.4 | normal |
|
||||
| Body / Listen | 20–24 px | 1.4–1.5 | normal |
|
||||
| Eyebrow / Label | 14–18 px | — | 0.14em–0.3em, uppercase |
|
||||
|
||||
**Regeln**
|
||||
|
||||
- Je größer die Schrift, desto negativer das Tracking und desto enger die Line-Height. Große Display-Typo braucht optischen Zusammenzug.
|
||||
- Mono ist **immer** uppercase mit weitem Tracking (≥ 0.14em). Es ist die „Maschinen-Stimme" des Decks.
|
||||
- Body-Text nie über 1300–1500 px Breite (`max-width` am `.slide-lead`).
|
||||
- Headlines brechen manuell per `<br>`. Der Zeilenumbruch ist Gestaltung, nicht Zufall.
|
||||
- Zahlen, die sich live ändern, brauchen `font-variant-numeric: tabular-nums`, sonst springt das Layout.
|
||||
|
||||
**Schriftwahl:** Ursprünglich stand hier Clash Display. Bei sehr engem Tracking und großen
|
||||
Displaygrößen (Zahlen, Zwei-Wort-Headlines) wurde die Schrift auf Distanz schwerer lesbar —
|
||||
enge, kantige Formen laufen bei Beamer-Projektion schnell zusammen. **General Sans** ersetzt sie:
|
||||
gleiche Bühnengröße und Gewichtsstufen (500/600/700), aber offenere Punzen (a, e, s) und eine
|
||||
größere x-Höhe, die auch bei −0.04em Tracking klar bleibt. Fließtext (Satoshi) und Mono
|
||||
(JetBrains Mono) sind unverändert. Beim Schriftwechsel testen: `font-vorschau.html` zeigt
|
||||
Kandidaten direkt in Deck-Größe (92 px / 40 px) nebeneinander, bevor man sich festlegt.
|
||||
|
||||
---
|
||||
|
||||
## 4. Layout
|
||||
|
||||
### Die Bühne
|
||||
|
||||
```
|
||||
.deck-viewport → fixed, füllt das Browserfenster, schwarz, overflow hidden
|
||||
.deck-stage → 1920×1080, transform-origin 0 0, wird per JS skaliert + zentriert
|
||||
.slide → absolute inset 0, 1920×1080, default unsichtbar
|
||||
```
|
||||
|
||||
Der Scale-Faktor ist `Math.min(innerWidth/1920, innerHeight/1080)`, der Rest wird als Letterbox zentriert. **Diese Struktur ist nicht optional** — sie ist der Grund, warum das Deck überall gleich aussieht.
|
||||
|
||||
### Grid & Spacing
|
||||
|
||||
- **Slide-Padding:** 100 px oben/unten, 120 px links/rechts (`.slide-content`). Title- und Closing-Slide: 120 px rundum.
|
||||
- **Spacing-Rhythmus:** Vielfache von 4, praktisch 8/12/16/20/24/32/44/60. Kein 13, kein 27.
|
||||
- **Gap in Grids:** 20 px (dichte Feature-Tiles), 32 px (Cards), 60 px (Spalten-Splits).
|
||||
- Content-Bereiche nutzen `flex: 1`, damit sie den Rest der Höhe füllen. Bei Grids mit fester Zeilenzahl zusätzlich `min-height: 0`, sonst sprengt Inhalt die Slide-Höhe.
|
||||
|
||||
### Layout-Archetypen
|
||||
|
||||
| Klasse | Struktur | Wofür |
|
||||
|---|---|---|
|
||||
| `.title-slide` | Space-between, 3 Zonen (Topbar / Headline / Meta) + Canvas-Layer | Slide 1 |
|
||||
| `.slide-content` | Eyebrow → Titel → Lead → Content-Block | Der Standard-Slide, 80 % aller Fälle |
|
||||
| `.versus` | 2 Spalten randlos + zentraler VS-Kreis | Direktvergleich, Vorher/Nachher |
|
||||
| `.counter-grid` | 3 Spalten, große animierte Zahlen | Kennzahlen |
|
||||
| `.code-slide` | Text links, Code-Window + Live-Preview rechts | Beweis-Slides |
|
||||
| `.feature-grid` | 4×2 Tiles, `.wide` = span 2 | Feature-Showcase |
|
||||
| `.closing-slide` | Hell, Space-between, Blur-Blob | Letzter Slide |
|
||||
| `.section-slide` | Dunkel, zentriert, riesige „Geister-Zahl" im Hintergrund | Kapitel-Trenner bei Themenwechsel |
|
||||
| `.game-wrap` | Satz/Lücke + Options-Buttons, JS-gesteuert | Mitmach-Slides (Publikum rät mit) |
|
||||
|
||||
Die Slide-Nummer kommt automatisch aus `data-num="04 / 10"` am `.slide-content` (gerendert per `::before`). Sie muss beim Umbau des Decks von Hand nachgezogen werden. `.section-slide`, `.versus`, `.code-slide`, Title- und Closing-Slide tragen bewusst **kein** `data-num` — sie zählen als „Zwischenspiel", nicht als nummerierter Inhaltspunkt.
|
||||
|
||||
### Kapitel-Trenner (`.section-slide`)
|
||||
|
||||
Bei mehr als ~5–6 Slides pro Thema lohnt sich ein eigener Trenner-Slide vor jedem Themenwechsel — er gibt dem Publikum eine Atempause und macht die Dramaturgie sichtbar. Aufbau: riesige, transparente Zahl mit Outline (`-webkit-text-stroke`) im Hintergrund, davor ein roter Mono-Kicker („Kapitel 03 / 07") und eine kurze, große Headline plus ein Satz Unterzeile. Siehe `PATTERNS.md` Nr. 7 für den Code.
|
||||
|
||||
Faustregel: ein Trenner pro inhaltlichem Kapitel, nicht pro Slide. Bei 30+ Slides sind 6–8 Trenner ein guter Rhythmus — mehr wirkt zerhackt, weniger verliert die Orientierung.
|
||||
|
||||
---
|
||||
|
||||
## 5. Motion
|
||||
|
||||
### Reveal-System
|
||||
|
||||
Elemente mit `.reveal` starten bei `opacity: 0; translateY(40px)` und fahren ein, sobald die Slide `.visible` bekommt. Die Staffelung läuft über `.d1`–`.d7` (100 ms → 820 ms, Schritte von ~120 ms). `.reveal-slide-x` macht dasselbe horizontal (−60 px), gedacht für die linke Versus-Spalte.
|
||||
|
||||
```html
|
||||
<span class="slide-eyebrow reveal d1">Das Problem</span>
|
||||
<h2 class="slide-title reveal d2">Warum das <span class="accent">nervt.</span></h2>
|
||||
<p class="slide-lead reveal d3">…</p>
|
||||
<div class="pain-card reveal d4">…</div>
|
||||
```
|
||||
|
||||
**Regel:** Reihenfolge im DOM = Reihenfolge der Delays. Nie `d5` vor `d3` einfahren lassen. Mehrere gleichrangige Karten dürfen sich ein Delay teilen.
|
||||
|
||||
### Easings
|
||||
|
||||
| Token | Kurve | Wofür |
|
||||
|---|---|---|
|
||||
| `--ease-out-expo` | `cubic-bezier(0.16, 1, 0.3, 1)` | Standard für alles, was einfährt. Schnell rein, weich aus. |
|
||||
| `--ease-swift` | `cubic-bezier(0.65, 0, 0.35, 1)` | Kurze, entschiedene Bewegungen (Durchstreichen) |
|
||||
|
||||
### Timings
|
||||
|
||||
- Reveal-Einfahrt: **0.9 s**
|
||||
- Hover-Feedback: **0.12–0.15 s** (muss sich sofort anfühlen)
|
||||
- Chart-Balken: **1.2 s** mit gestaffeltem `transition-delay` von 0.4 s bis 0.9 s
|
||||
- Counter-Zählung: **1.6 s**, Easing `1 - (1-p)³`
|
||||
- Loops (Blob, Ticker, Cube): **4–12 s**, `linear` oder `ease-in-out`, damit sie nie „getaktet" wirken
|
||||
|
||||
### Performance
|
||||
|
||||
Animiert werden **nur** `transform` und `opacity` — die laufen auf der GPU. Kein `width`, `height`, `top`, `left` in Transitions. Ausnahme: `.demo-charts-bars` animiert `height`, aber auf 6 winzigen Divs, das ist vertretbar.
|
||||
|
||||
`prefers-reduced-motion` ist global verdrahtet: Animationen gehen auf 0.01 ms, Transitions auf 0.2 s. Slides bleiben voll funktionsfähig, nur ohne Show.
|
||||
|
||||
---
|
||||
|
||||
## 6. Interaktion
|
||||
|
||||
| Trigger | Wirkung |
|
||||
|---|---|
|
||||
| `→`, `Leertaste`, `PageDown` | nächster Slide |
|
||||
| `←`, `PageUp` | vorheriger Slide |
|
||||
| `Home` / `End` | erster / letzter Slide |
|
||||
| Mausrad | Slide-Wechsel, 900 ms Cooldown |
|
||||
| Swipe (> 60 px) | Slide-Wechsel auf Touch |
|
||||
| `E` | Edit-Modus |
|
||||
| `C` | Zum Präsentations-Konfigurator (`config.html`), falls vorhanden |
|
||||
| Hotzone oben links | blendet Edit- und Config-Button ein (400 ms Grace-Period) |
|
||||
| Klick auf `.term` | öffnet Begriffs-Tooltip |
|
||||
|
||||
**Edit-Modus:** Setzt `contenteditable` auf alle Text-Elemente, markiert sie mit rotem Dashed-Outline. Beim Verlassen wird der Stage-HTML in `localStorage` geschrieben. Das Zurückladen ist **absichtlich auskommentiert** — restauriertes HTML kollidiert mit den Animations-States. Der Edit-Modus ist ein Live-Korrektur-Werkzeug für die Bühne („Kunde will hier ein anderes Wort"), keine Persistenz-Schicht.
|
||||
|
||||
**Begriffs-Tooltips (`.term`):** Für Laien-Publikum unentbehrlich — Fachbegriffe (Token, LLM, MCP, GPT, ANI/AGI, …) bekommen eine gepunktete rote Unterstreichung plus kleines „?"-Badge. Klick öffnet eine kurze Erklärung. Das Tooltip-Element lebt **außerhalb** der 1920er-Bühne (ein einziges `#globalTooltip`, direkt an `<body>` gehängt, per JS in echten Viewport-Pixeln positioniert) — sonst schneiden `overflow:hidden`-Container wie `.pain-card` oder `.feature-tile` es ab. Es klappt automatisch ober- oder unterhalb des Begriffs aus, je nachdem was im Fenster noch Platz hat, und schließt bei Klick daneben, `Esc`, Resize oder Slide-Wechsel. Siehe `PATTERNS.md` Nr. 8.
|
||||
|
||||
**Präsentations-Konfigurator:** Bei Decks mit vielen Slides (Workshop-Varianten, 45/60/90-Minuten-Kürzungen) lohnt sich `config.html` + `slides-manifest.js` statt Slides von Hand zu löschen. Der Konfigurator listet alle Slides gruppiert nach Kapitel mit Checkbox; die Auswahl wird beim Wechsel zur Präsentation als `?slides=1,4,5,…`-Parameter an die Deck-URL gehängt (nicht nur `localStorage` — das wird zwischen einzelnen `file://`-Dateien nicht überall geteilt, vor allem Safari trennt es strikt). Titel- und Closing-Slide sind im Manifest als `locked: true` markiert und immer aktiv. Siehe `PATTERNS.md` Nr. 11.
|
||||
|
||||
**Ambient-Sound (optional, nur Titelfolie):** Ein per Web Audio API erzeugter Klangteppich (kein externes Audio-File) kann vor Vortragsbeginn Spannung aufbauen. Läuft nur, während die Titelfolie aktiv ist, blendet beim Verlassen automatisch aus. Browser blockieren Audio ohne Nutzer-Geste — deshalb immer über einen expliziten Icon-Button starten, nie automatisch. Siehe `PATTERNS.md` Nr. 10.
|
||||
|
||||
**Hover-Regel:** Cards heben sich um 4–8 px (`translateY`) und wechseln die Border auf Rot. `.pain-card` zieht zusätzlich eine Radial-Aura hinter dem Cursor her (`--mx`/`--my` per JS gesetzt).
|
||||
|
||||
**Wichtig bei Maus-Koordinaten:** Die Bühne ist skaliert. `e.clientX` sind Bildschirm-Pixel, das Element lebt im 1920er-Raum. Immer durch den Scale-Faktor teilen:
|
||||
|
||||
```js
|
||||
const rect = el.getBoundingClientRect();
|
||||
const scale = rect.width / el.offsetWidth;
|
||||
const x = (e.clientX - rect.left) / scale;
|
||||
```
|
||||
|
||||
Bei `.pain-card` fällt das nicht auf, weil dort in Prozent gerechnet wird — beim Ripple des Demo-Buttons schon.
|
||||
|
||||
---
|
||||
|
||||
## 7. Print / PDF
|
||||
|
||||
`@media print` löst die fixe Bühne auf: `.deck-stage` verliert `transform`, jede Slide wird `position: relative` mit `break-after: page`. HUD, Progress-Bar und Edit-Controls verschwinden. Export: **Strg/Cmd+P → Ziel „Als PDF sichern" → Papierformat Querformat, Ränder: keine, Hintergrundgrafiken: an.**
|
||||
|
||||
Ergebnis: eine Seite pro Slide. Animierte Inhalte frieren im jeweiligen Endzustand ein — Live-Daten (WebSocket) zeigen den letzten Wert.
|
||||
|
||||
---
|
||||
|
||||
## 8. Neues Deck bauen
|
||||
|
||||
1. `deck-template.html` kopieren und umbenennen.
|
||||
2. `<title>`, Brand-Mark, Datum, Sprecher-Name, Kontakt anpassen.
|
||||
3. Slides aus `PATTERNS.md` zusammenstellen. Bewährte Dramaturgie:
|
||||
**Titel → Problem → Vergleich → Zahlen → Beweis (Live) → Der ehrliche Deal → Closing.**
|
||||
4. `data-num` an allen `.slide-content` auf die neue Gesamtzahl ziehen. Das HUD zählt selbst, `data-num` nicht.
|
||||
5. Durchklicken bei 1920×1080 **und** bei kleinem Fenster. Der Scale muss sauber greifen, Text darf nirgends aus einer Card laufen.
|
||||
6. Print-Preview prüfen, bevor das Deck rausgeht.
|
||||
7. Bei vielen Slides oder mehreren Vortrags-Längen (45/60/90 Min.): `slides-manifest.js` mit der finalen Slide-Liste anlegen (ein Eintrag pro `<section class="slide" data-slide-id="…">`, gleiche Reihenfolge), `config.html` aus dem Beispiel-Projekt kopieren. Damit lässt sich die Slide-Auswahl kuratieren, ohne Markup zu löschen.
|
||||
|
||||
### Kunden-Theme
|
||||
|
||||
Nur die Tokens in `:root` tauschen: Signalfarbe, ggf. Display-Font. Alles andere bleibt. Wenn die Signalfarbe hell ist (Gelb, Cyan), zusätzlich prüfen: Kontrast von `.demo-button` (weißer Text auf Signalfarbe) und die Glow-Shadows — die brauchen dann weniger Alpha.
|
||||
|
||||
---
|
||||
|
||||
## 9. Do / Don't
|
||||
|
||||
**Do**
|
||||
|
||||
- Ein Gedanke pro Slide. Die Headline sagt ihn, alles andere belegt ihn.
|
||||
- Große Zahlen groß machen. 220 px ist kein Fehler.
|
||||
- Weißraum halten. Die 120 px Padding sind Design, kein Verschnitt.
|
||||
- Live-Elemente bekommen immer einen Fallback (siehe WebSocket-Fallback: simuliert Ticks, wenn kein Netz da ist). **Eine Demo, die auf der Bühne offline abstürzt, ist ein Eigentor gegen die eigene These.**
|
||||
- Ein Argument pro Slide beweisen statt behaupten.
|
||||
|
||||
**Don't**
|
||||
|
||||
- Keine Bullet-Point-Listen aus Gewohnheit. Wenn eine Liste, dann mit gestalteten Markern (`×` / `→`).
|
||||
- Keine Hex-Codes im Markup. Token benutzen.
|
||||
- Kein Scroll innerhalb einer Slide. Passt es nicht, ist es zu viel Inhalt — nicht zu wenig Platz.
|
||||
- Keine externen Libraries. Das Deck beweist, dass Vanilla reicht.
|
||||
- Kein Rot als Fläche hinter Text.
|
||||
- Keine Animation ohne Grund. Jeder Loop, den niemand anschaut, ist verbranntes Budget an Aufmerksamkeit.
|
||||
Reference in New Issue
Block a user