# 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 `
`. 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 Das Problem

Warum das nervt.

``` **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 `` 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. ``, 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.