--- phase: quick-260917-jdf plan: 01 subsystem: ui tags: [react, nextjs, tailwind, vitest, svg, css-custom-properties, oklab] requires: [] provides: - "BRAND_OLIVE_MIX, BRAND_OLIVE_FILL (apps/web/src/components/brand/brand.ts) — Mischparameter und abgeleiteter color-mix()-Ausdruck fuer den Olivton der vier Kacheln" - "LogoMark: alle vier achsenparallelen Kacheln folgen jetzt --primary als abgeleiteter dunklerer Ton (bisher fest #9c9440); Signalkachel und Grundplatte unveraendert" affects: [brand] actuals: tokens: 4200 tasks: 2 commits: 2 plan_head_before: 38c14005c6bcb800b8bd6a48148646a4fdddafe0 tech-stack: added: [] patterns: - "color-mix(in oklab, var(--token, fallback) N%, #grau) im Inline-Style leitet einen Markenton aus einem CSS-Custom-Property ab, ohne Laufzeit-Farbrechnung in JS; festes Praesentationsattribut bleibt als Rueckfall fuer Browser ohne color-mix()" - "Mischparameter (Anteil + neutrales Mischgrau) einmalig als benannte Konstante notieren und den CSS-String daraus bilden; ein Test rechnet die Kalibrierung aus denselben Konstanten nach (sRGB<->OKLab nach CSS Color 4), statt die Zielfarbe als zweite, unabhaengige Zahl zu pflegen" key-files: created: - apps/web/src/components/brand/brand.test.ts modified: - apps/web/src/components/brand/brand.ts - apps/web/src/components/brand/tessera-logo.tsx - apps/web/src/components/brand/tessera-logo.test.tsx - CHANGELOG.md key-decisions: - "Mischung in oklab statt oklch: mit dem gewaehlten neutralen Mischgrau (#363636, OKLab a/b < 1e-4) liefert oklab dasselbe Ergebnis wie oklch (Farbton bleibt erhalten, Chroma und Helligkeit skalieren linear), aber ohne Abhaengigkeit von der CSS-Sonderregel fuer den powerless hue achromatischer Farben in polaren Farbraeumen (Entscheidung des Planers, im Plan begruendet und uebernommen)." - "Kein neuer Prop an TesseraLogo und keine JS-Farbrechnung zur Laufzeit — reine CSS-Loesung (color-mix), wie im Plan vorgegeben." requirements-completed: [QUICK-260917-JDF] coverage: - id: D1 description: "Vier achsenparallele Kacheln tragen Inline-Style fill: BRAND_OLIVE_FILL (color-mix aus --primary) plus Rueckfall-Attribut BRAND_OLIVE; Signalkachel und Grundplatte unveraendert" requirement: "QUICK-260917-JDF" verification: - kind: unit ref: "apps/web/src/components/brand/tessera-logo.test.tsx#renders exactly five tiles; the rotated one takes the accent token, the other four the derived olive tone with the fixed olive as fallback" status: pass human_judgment: true rationale: "Sichtbarer Farbwechsel des ganzen T in Kopfzeile/Seitenleiste/Anmeldeseite bei gesetzter bzw. zurueckgesetzter Akzentfarbe ist eine visuelle Bedienprobe im Browser — laut Plan Aufgabe des Orchestrators (Playwright), nicht Teil dieses Plans." - id: D2 description: "Kalibrierung 54 % / #363636 trifft #9c9440 exakt (0/0/0), CSS-Standardwert von --primary liegt hoechstens 4 Einheiten daneben, Mischgrau ist OKLab-neutral, Grenzfaelle (Weiss/Schwarz/Blau) dokumentiert inkl. Kippen bei sehr dunklen Akzentfarben" requirement: "QUICK-260917-JDF" verification: - kind: unit ref: "apps/web/src/components/brand/brand.test.ts (7 Tests)" status: pass human_judgment: false duration: ~15min completed: 2026-09-17 status: complete --- # Quick Task 260917-jdf: Bildmarke — ganzes T übernimmt die Akzentfarbe Summary **Die vier achsenparallelen Kacheln der Tessera-Bildmarke folgen jetzt per `color-mix(in oklab, var(--primary, #ffed00) 54%, #363636)` derselben Akzentfarbe wie die gedrehte Signalkachel — als abgeleiteter dunklerer Ton, kalibriert auf exakt `#9c9440` bei Markengelb.** ## Performance - **Duration:** ~15 min - **Completed:** 2026-09-17 - **Tasks:** 2/2 - **Files modified:** 5 (1 neu, 4 geändert) ## Accomplishments - `BRAND_OLIVE_MIX = { primaryShare: 54, mixWith: '#363636' } as const` (brand.ts) — einzige Quelle der Mischparameter, mit ausführlichem deutschem Kalibrierungskommentar (Rechnung, Ergebnis, Grenzfälle) - `BRAND_OLIVE_FILL` (brand.ts) — der daraus gebildete `color-mix(...)`-CSS-String, einzige Stelle im Quellcode, an der dieser Ausdruck entsteht - `LogoMark` (tessera-logo.tsx): alle vier achsenparallelen Kacheln tragen jetzt `style={{ fill: BRAND_OLIVE_FILL }}` plus weiterhin das Präsentationsattribut `fill={BRAND_OLIVE}` als Rückfall für Browser ohne `color-mix()`; die gedrehte Signalkachel und die Grundplatte sind unverändert - `brand.test.ts` (neu, 7 Tests): rechnet die Kalibrierung sRGB→OKLab→sRGB unabhängig nach — Treffer auf `#9c9440` (0/0/0), CSS-Standardwert von `--primary` (`≤ 4` je Kanal, `#9a903f`), Neutralität des Mischgraus, Grenzfälle #0057b8/#ffffff/#000000 - `tessera-logo.test.tsx`: Kacheltest zählt jetzt eine Token-Füllung (Signalkachel) und vier abgeleitete Füllungen (`BRAND_OLIVE_FILL`) mit Rückfall-Attribut - Ein CHANGELOG-Stichpunkt unter „Unveröffentlicht“ → „Geändert“ ## Befund des Planers (übernommen, siehe Objective/Key-Links im Plan) `--primary` ist über `globals.css` (`:root` und `.dark`, je `oklch(0.91 0.19 102)`) **immer** definiert — die laufende App lädt das Stylesheet immer, ob angemeldet oder nicht. Der `var(--primary, #ffed00)`-Rückfall in der Signalkachel greift deshalb **nie**, weder auf der Anmeldeseite noch bei Nutzern ohne persönliche Akzentfarbe. Für diese beiden Fälle war die Signalkachel schon seit quick-260917-gsh `#fbe405` statt `#ffed00`; mit diesem Task werden die vier Kacheln entsprechend `#9a903f` statt `#9c9440` — jeweils wenige Einheiten Abweichung (`−2/−4/−1`), visuell nicht unterscheidbar. Die Anmeldeseite bindet die Bildmarke ohne feste Farben ein und braucht keine Sonderbehandlung; der überkommene Kommentar in `tessera-logo.tsx`, wonach der Token ohne angemeldeten Nutzer nicht definiert sei, war falsch und wurde in diesem Task korrigiert. Bei sehr dunklen Akzentfarben (OKLab-L unter ≈ 0,333, Beispiel Schwarz → `#0c0c0c`) kippt die Ableitung: der abgeleitete Ton wird **heller** statt dunkler als die Signalkachel. Laut Auftrag hingenommen, kein Schutzmechanismus eingebaut — im Kalibrierungskommentar von `brand.ts` und in `brand.test.ts` dokumentiert. ## Task Commits Each task was committed atomically: 1. **Task 1: Vier Kacheln in abgeleiteter Akzentfarbe — Konstanten, Logo, Kalibrierungstest, Kacheltest** - `ecff144` (feat) 2. **Task 2: CHANGELOG — ein Stichpunkt, Gesamtlauf** - `29db4c0` (docs) **Plan metadata:** wird vom Orchestrator nach diesem SUMMARY committet. _Task 1 (`type="tracer" tdd="true"`) folgte RED→GREEN: Test- und Implementierungsänderungen wurden im selben Arbeitsschritt vorbereitet; die neuen Tests referenzieren `BRAND_OLIVE_MIX`/`BRAND_OLIVE_FILL`, die vor diesem Task nicht existierten, und der umgeschriebene Kacheltest prüft eine Füllung (`style.fill === BRAND_OLIVE_FILL`), die vor der Implementierung nicht vorhanden war — beide wären ohne die Implementierung zwingend rot gewesen. GREEN wurde empirisch bestätigt: `vitest run src/components/brand` 16/16 grün, `type-check` sauber, alle Zählgates aus dem `` (vier Inline-Füllungen, vier Rückfall-Attribute, genau eine Token-Füllung, Mischparameter in brand.ts, globals.css/icon.svg/login/auth-store unverändert) erfüllt._ ## Files Created/Modified - `apps/web/src/components/brand/brand.ts` - `BRAND_OLIVE_MIX`, `BRAND_OLIVE_FILL` (neu), erweiterter Kommentar zu `BRAND_OLIVE`, Kopfkommentar ergänzt - `apps/web/src/components/brand/brand.test.ts` - neu, 7 Testfälle (Kalibrierung, Mustertreffer, Neutralität, CSS-Standard, drei Grenzfälle) - `apps/web/src/components/brand/tessera-logo.tsx` - vier Kacheln mit Inline-Style `BRAND_OLIVE_FILL` + Rückfall-Attribut `BRAND_OLIVE`, Kommentar über der Kachelgruppe neu formuliert, JSDoc angepasst - `apps/web/src/components/brand/tessera-logo.test.tsx` - Kacheltest umgeschrieben (1× Token-Füllung, 4× abgeleitete Füllung mit Rückfall-Attribut) - `CHANGELOG.md` - ein Stichpunkt unter „Unveröffentlicht“ → „Geändert“ (Abschnittsüberschrift neu angelegt, da nach der 1.2.0-Freigabe leer) ## Decisions Made - Mischung in `oklab` statt `oklch` — mit dem gewählten neutralen Mischgrau identisches Ergebnis, aber ohne Abhängigkeit von der CSS-Sonderregel für den Farbton achromatischer Farben (Entscheidung des Planers, im Plan begründet, hier unverändert übernommen). - Kein neuer Prop an `TesseraLogo`, keine JS-Farbrechnung zur Laufzeit — reine CSS-Lösung wie im Plan vorgegeben. - Kommentare in `tessera-logo.tsx` zitieren die JSX-Attributschreibweise der Kacheln bewusst nicht (Prosa statt Code), damit die Zeilenzähl-Gates im `` nicht durch Kommentarzeilen verfälscht werden. ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Browser-Nachweis (Orchestrator per Playwright, nicht Teil dieses Plans): Einstellungen → Konto → Akzentfarbe `#0057b8` speichern → in Kopfzeile und Seitenleiste wird das ganze T blau, die vier Kacheln erkennbar dunkler als die Signalkachel (erwartet ≈ `#284a7b`); Zurücksetzen → gelb/oliv wie vorher; Abmelden → Anmeldeseite gelb/oliv wie vorher (Signalkachel ≈ `#fbe405`, Kacheln ≈ `#9a903f` — beides ununterscheidbar vom bisherigen Bild). Messung über `getComputedStyle(rect).fill` der Kacheln, nicht per `fetch` aus der Seite. - Kein Blocker für weitere Arbeit — kompletter Web-Testlauf 64/64 Dateien, 424/424 Tests grün (Grundstand 63/417 plus `brand.test.ts` mit 7 Tests), Typprüfung sauber. --- *Quick Task: 260917-jdf* *Completed: 2026-09-17* ## Self-Check: PASSED All 5 claimed files found on disk; both task commits (ecff144, 29db4c0) found in git history. ## Nachweis durch Orchestrator (2026-09-17, Playwright gegen lokale Container) - Akzentfarbe `#0057b8` gespeichert: gedrehte Kachel `#0057b8`, die vier Kacheln `#284a7b` (wie in der Referenzrechnung vorhergesagt). - „Zuruecksetzen": Kacheln `#9a903f`, gedrehte Kachel `#fbe405` — Standardbild unveraendert (Nebenbefund `--primary` aus globals.css bestaetigt). - Anmeldeseite: dieselben Werte, kein Unterschied zu vorher.