# Phase 0 — Design-Tokens vereinheitlichen > **Ziel**: Single Source of Truth für alle Design-Tokens (Farben, Fonts, > Radii, Schatten). Sowohl Hub-Build als auch Portal-Build beziehen ihre > Werte aus derselben Datei. **Visuell ändert sich noch nichts.** **Status**: ✅ abgeschlossen am 2026-05-19 **Risiko**: sehr niedrig **Aufwand (tatsächlich)**: ~½ Tag ## Ergebnis-Check (2026-05-19) - Single Source of Truth liegt in `resources/css/shared/design-tokens.css`. - Web-Build und Portal-Build importieren sie beide. - **Visuelle Unverändertheit verifiziert**: - Hub (`pressekonto.test/`, `/login`, `/register`) — unverändert. - Portal (`/dashboard`) — FluxUI-Defaults bleiben dominant (`--font-sans: "Instrument Sans"`, Zinc-Palette, `#3ea3dc`-Akzent). - Build-Sizes: - `theme-pressekonto: 193 kB` (vorher 189 kB · +4 kB für neue Tokens) - `theme-presseecho`, `theme-businessportal24`: praktisch unverändert - `portal: 408 kB` (vorher 397 kB · +12 kB für zusätzlich bereitgestellte Token-Vars im `:root`) - Details: `PROGRESS.md` (Eintrag vom 2026-05-19). ## Warum Heute leben Tokens an zwei Orten: - `resources/css/web/theme-pressekonto.css` — Hub-Tokens (Hub-Blau, Bernstein, Buchpapier, Inter Tight) - `resources/css/portal.css` — Portal-Tokens (Zinc, `#3ea3dc`, Instrument Sans) Solange diese parallel gepflegt werden, **driften** sie auseinander. Wir ziehen die gemeinsame Wahrheit in eine eigene Datei und referenzieren sie aus beiden Welten. ## Liefergegenstand ``` resources/css/shared/ └── design-tokens.css ← NEU ``` Inhalt: alle `--color-*`, `--font-*`, `--radius-*`, `--shadow-*` Tokens, die in Hub und Portal gleichermaßen gelten. Strukturiert als `@theme`-Block, sodass Tailwind v4 die Variablen sowohl als CSS-Custom-Properties als auch als Tailwind-Utility-Klassen erkennt. ## Schritte ### 1. Token-Inventur aus `theme-pressekonto.css` Die folgenden Tokens werden aus `theme-pressekonto.css` extrahiert und nach `shared/design-tokens.css` verschoben: #### Surfaces - `--color-bg`, `--color-bg-elev`, `--color-bg-rule`, `--color-bg-rule-strong` - `--color-bg-dark`, `--color-bg-card`, `--color-bg-card-warm`, `--color-bg-card-warm-border`, `--color-bg-card-warm-hover`, `--color-bg-card-warm-rule` #### Hub-Palette - `--color-hub`, `--color-hub-2`, `--color-hub-3` - `--color-hub-soft`, `--color-hub-soft-2`, `--color-hub-line` - `--color-topbar`, `--color-topbar2`, `--color-topbar-deep` #### Akzent (Bernstein) - `--color-accent`, `--color-accent-deep`, `--color-accent-soft`, `--color-accent-warm` #### Ink (Anthrazit) - `--color-ink`, `--color-ink-2`, `--color-ink-3`, `--color-ink-4` - `--color-ink-on-dark`, `--color-ink-on-dark-2`, `--color-ink-on-dark-3`, `--color-ink-on-dark-muted`, `--color-ink-on-dark-rule` #### Brand-Aliase + Status - `--color-brand`, `--color-brand-deep`, `--color-brand-soft` - `--color-live`, `--color-gain`, `--color-loss`, `--color-ok` #### Editorial / Cards - `--color-card-warm-cat`, `--color-card-warm-title`, `--color-feature-line`, `--color-feature-dot` #### Status (für KPI-Cards / Badges — laut Mockup ergänzen) - `--color-warn` `#A87A1F`, `--color-warn-soft` `#F6EAC8` - `--color-err` `#A8331F`, `--color-err-soft` `#F4DAD2` - `--color-ok-soft` `#E2F1E5` #### Fonts - `--font-sans` (Inter Tight) - `--font-serif` (Source Serif 4 — nur für Brand-Mark) - `--font-mono` (JetBrains Mono) #### Layout - `--container-layout: 1280px` #### Radii (laut Mockup) - `--radius-xs: 3px`, `--radius-sm: 4px`, `--radius-md: 6px`, `--radius-lg: 8px` #### Schatten (laut Mockup + Hub-Login) - `--shadow-soft`: leicht warm, für Cards - `--shadow-card`: Standard-Card-Schatten - `--shadow-card-hover`: Hover-Stufe - `--shadow-auth`: weiche Glocke unter Auth-Card ### 2. Datei `resources/css/shared/design-tokens.css` anlegen Aufbau: ```css /** * Hub × FluxUI — Gemeinsame Design-Tokens * * Single Source of Truth für Hub-Frontend (build/web) und Portal-Backend * (build/portal). Beide CSS-Builds @import diese Datei. * * Token-Names sind STABIL — Werte können sich ändern (z.B. Dark Mode in * Phase 5), Namen nicht. */ @theme { /* Surfaces */ --color-bg: #f6f4ef; --color-bg-elev: #fbfaf6; /* … alle Tokens aus der Inventur … */ } /* Dark Mode (vorbereitet, in Phase 5 finalisiert) */ @media (prefers-color-scheme: dark) { @theme { /* Spätere Dark-Werte */ } } ``` ### 3. `theme-pressekonto.css` refactoren Die `@theme {}`-Definitionen werden durch einen `@import "../shared/design-tokens.css";` ersetzt. Nur die `@layer components {}`-Klassen (`.eyebrow`, `.auth-card`, `.field-input`, etc.) bleiben in `theme-pressekonto.css`. `:root { … --background, --primary … }`-HSL-Variablen für Legacy-Komponenten bleiben ebenfalls hier (sind Portal-unspezifisch). ### 4. `portal.css` minimal vorbereiten (noch keine Werte übernehmen) In Phase 0 importieren wir die Token-Datei in `portal.css`, **aber lassen das alte `@theme`-Setup mit Zinc/Accent zunächst stehen**. Damit: - Beide Welten greifen technisch auf die gleiche Datei zu - Aber Portal bleibt visuell unverändert (Zinc-Palette gewinnt durch Reihenfolge im `@theme`) In Phase 1 wird das Zinc-Setup dann **gezielt durch Hub-Werte ersetzt**. ### 5. Build & Verifikation ```bash npm run build:web # → erzeugt theme-pressekonto.css ohne Drift npm run build:portal # → erzeugt portal.css unverändert ``` Erwartung: - Hub-Landing rendert visuell **identisch** wie vorher - Hub-Auth-Pages rendern visuell **identisch** wie vorher - Portal rendert visuell **identisch** wie vorher Smoke-Test (kein neues Test-Schreiben nötig): ```bash php artisan tinker --execute ' $urls = [ "https://pressekonto.test/", "https://pressekonto.test/login", "https://pressekonto.test/dashboard", ]; foreach ($urls as $u) { echo $u . " => " . app(\Illuminate\Contracts\Http\Kernel::class) ->handle(\Illuminate\Http\Request::create($u, "GET")) ->getStatusCode() . "\n"; }' ``` Alle 3 URLs müssen weiterhin `200` liefern (für `/dashboard` ggf. `302`-Redirect, je nach Auth-Status — beides ist okay, solange kein `500`). ## Akzeptanzkriterien - [ ] `resources/css/shared/design-tokens.css` existiert mit allen Hub-Tokens - [ ] `theme-pressekonto.css` importiert die Token-Datei und enthält keine doppelten `--color-*`-Definitionen mehr - [ ] `portal.css` importiert die Token-Datei (Werte werden in Phase 1 genutzt) - [ ] `npm run build:web` und `npm run build:portal` laufen ohne Fehler durch - [ ] Hub-Landing, Hub-Auth und Portal-Login visuell **unverändert** - [ ] Pint passed (`vendor/bin/sail bin pint --dirty --format agent`) ## Risiken & Fallstricke - **Tailwind v4 + `@theme`**: Mehrere `@theme {}`-Blöcke in importierten Dateien werden zusammengeführt. Das funktioniert, solange die Token-Namen eindeutig sind. - **Reihenfolge der Imports**: Tokens müssen **vor** den `@layer components {}`-Definitionen importiert werden, sonst greifen die Variablen in den Komponenten nicht. - **Portal-Tailwind-Config**: `tailwind.portal.config.js` darf die Token-Datei nicht ausschließen. `@source`-Direktiven prüfen. ## Was Phase 0 NICHT macht - Portal sieht **noch nicht** wie der Hub aus — das ist Phase 1 - Keine Änderung am Sidebar-Layout, am Logo oder am Dashboard - Keine Dark-Mode-Aktivierung (nur vorbereitet)