Files
AI-Vortrag/DESIGN.md
Erik Thiele 2633ca0e0d 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).
2026-07-25 16:29:28 +02:00

15 KiB
Raw Blame History

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: 2224 px) 1.4 normal
Body / Listen 2024 px 1.41.5 normal
Eyebrow / Label 1418 px 0.14em0.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 13001500 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 ~56 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 68 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.

<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.120.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): 412 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 48 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:

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.