# Branding-Umstellung auf Certvia — Inventar & Umsetzung > Branch `dev-branding-certvia` (Basis `dev`) · Quelle: `Aufgabenpaket-Branding-Certvia.md` + `Certvia-Assets/` > Leitplanke: **GEFIM bleibt Dachmarke** („Ein Produkt von GEFIM"), nur die **Produktmarke** wird Certvia. > Reines Branding — **keine Funktionsänderung**, kein Umbau von Logik oder Datenmodell. --- ## 1. Design-Tokens (verbindliche Referenz) **Markenfarben** (Logo, Print, Verläufe — `--brand-*`): | Rolle | Token | Hex | |---|---|---| | Violett (Marke) | `--brand-violet` | `#5d52a3` | | Magenta (Akzent „via", Haken) | `--brand-magenta` | `#812d80` | | Hellblau | `--brand-blue` | `#8dc4e0` | | Anthrazit (Text/Headlines) | `--brand-anthracite` | `#3b3b3a` | | Violett auf Dunkel | `--brand-violet-on-dark` | `#7d6fd6` | | Magenta auf Dunkel | `--brand-magenta-on-dark` | `#d17bcf` | **UI Dark-Theme** (unverändert — **ist** die Certvia-Produktpalette, nicht „korrigieren"): `--ui-primary #7d6fd6` · `--ui-primary-deep #5d52a3` · `--ui-blue #8dc4e0` · `--ui-magenta #b45bb0` · `--bg-0 #0e1220` · `--bg-1 #141a2e` · `--elevated #1a2138` · `--panel rgba(30,38,64,.72)` · `--panel-brd rgba(120,135,180,.18)` · `--foreground #e8ecf7` · `--muted-foreground #8b93ad` · `--ok #39c07f` · `--warn #f0ad4e` · `--risk #ff6b6b` · Primär-Verlauf `linear-gradient(135deg,#5d52a3,#7d6fd6)` · Fokus-Ring `rgba(125,111,214,.35)`. Single Source of Truth: **`src/app/globals.css`** (CSS) und **`src/lib/brand.ts`** (JS/TS — für alles, was CSS-Variablen nicht auflösen kann: Canvas-/PNG-Export, Metadaten, künftige Dokument-Exporte). **Typografie:** Headlines/Wortmarke **Poppins**, Fließtext **Open Sans** — self-hosted (`src/app/fonts/`). --- ## 2. Inventar (Story S0) ### 2.1 Produktmarke → Certvia | Datei | Fundstelle | Maßnahme | Story | |---|---|---|---| | `src/app/globals.css` | `--gefim-violet/-deep/-blue/-magenta`, Kommentare „GEFIM-Theme" | Umbenannt auf `--brand-*` / `--ui-*`, Kommentare auf Certvia | S1/S9 | | `src/app/globals.css` | Flächenfarben direkt als Hex (`#0e1220`, `#141a2e`, …) | Über `--bg-0`/`--bg-1`/`--elevated` geführt, semantische Tokens referenzieren sie | S1 | | `src/components/risk-modals.tsx` | `bg-[#0e1220]` (Rest-Risiko-Marker, Legende) | → `bg-[var(--bg-0)]` | S1 | | `src/app/(app)/risks/page.tsx` | `bg-[#0e1220]/75`, `hover:bg-[#0e1220]` (Heatmap-Chip) | → Token `--chip-overlay` / `var(--bg-0)` | S1 | | `src/components/dependency-graph.tsx` | `#8dc4e0`, `#ff6b6b`, `#141a2e`, `#0e1220`, `#4a5372`, `#8b93ad` | CSS-Vars wo möglich; PNG-Export nutzt `BRAND.ui` aus `src/lib/brand.ts` (html-to-image löst keine CSS-Vars auf) | S1 | | `public/gefim-logo.png` | Produktlogo in Sidebar + Login | Verschoben nach `public/assets/logo/gefim-logo.png`, dient nur noch der **Dachmarke** | S2 | | `src/app/(app)/layout.tsx` | Sidebar-Logo `/gefim-logo.png`, Alt-Text „GEFIM …" | `` über den Branding-Resolver | S2/S8 | | `src/app/login/page.tsx` | Logo `/gefim-logo.png`, Alt-Text | Certvia-Lockup + Tagline + Dachmarken-Fußnote | S2/S7 | | `src/app/platform/login/page.tsx` | kein Logo | Certvia-Lockup + „Plattform-Administration" | S2/S7 | | `src/app/(platform)/layout.tsx` | `ShieldCheck` + „ISMS · Plattform-Administration" | Certvia-Mark + „Certvia · Plattform-Administration" | S2/S3 | | `src/app/layout.tsx` | `title: "ISMS-Tool"`, keine Icons/OG/Manifest | Vollständige Certvia-Metadaten inkl. Icons, Manifest, `themeColor` | S3 | | `src/app/favicon.ico` | Next-Default-Favicon | Entfernt; Icons laufen über `public/favicon/` + `metadata.icons` | S2 | | `messages/de.json`, `messages/en.json` | `common.appName` = „ISMS-Tool"/„ISMS Tool" | → „Certvia" (+ `appTagline`, `appByline`) | S3 | | `src/server/mfa.ts` | TOTP-Issuer `"ISMS-Tool · Plattform"` | → `"Certvia · Plattform"` | S3 | | `src/components/ui/button.tsx` | Kommentar „GEFIM-Verlauf" | → „Certvia-Verlauf" | S9 | | `src/components/mockup-ui.tsx` | Kommentar-Referenz auf Mockup-Datei | Formulierung entschärft (Dateiname bleibt, s. u.) | S9 | | `src/lib/control-titles.ts` | Kommentar „aus dem GEFIM-Mockup übernommen" | → neutral „aus dem UI-Mockup" | S9 | | `src/app/(app)/settings/page.tsx` | Hinweis „Logo-Upload folgt in Phase 2" | Ergänzt um Certvia-Default-Aussage | S8 | | `src/proxy.ts` | Matcher schloss `.webmanifest` nicht aus | `/site.webmanifest` lieferte die Login-HTML statt JSON → Endung ergänzt (siehe §5) | S3 | ### 2.2 Dachmarke GEFIM → bleibt bewusst erhalten | Ort | Grund | |---|---| | `public/assets/logo/gefim-logo.png` | Dachmarken-Logo für „Ein Produkt von GEFIM" | | `src/components/brand/powered-by-gefim.tsx` | Neue Komponente, die genau diesen Hinweis rendert (Login, Plattform-Login, Print-/Export-Fußzeile, Mail-Footer) | | `docs/ISMS-*-GEFIM.html`, Verweise in `README.md`/`AGENTS.md`/`docs/SPEC.md` | Historische Mockups/Spezifikation — Projektartefakte, keine Produkt-UI | | `prisma/seed.ts` (`ORG_NAME` „GEFIM Demo GmbH") | **Demo-Mandantendaten** (fiktiver Kunde), nicht der Produktname | | `prisma/import-managed.ts` (`portal.gefim.example`) | Demo-Registerzeile, nicht der Produktname | Nach der Umstellung liefert `rg -i "gefim"` ausschließlich diese Kategorien. --- ## 3. Umgesetzte Stories | Story | Inhalt | Status | |---|---|---| | **S0** | Inventar (dieses Dokument) | ✅ | | **S1** | Token-Zentralisierung `--brand-*` / `--ui-*`, `src/lib/brand.ts`, hartkodierte Farben ersetzt | ✅ | | **S2** | Assets eingebunden, ``, Favicon/PWA-Icons, Sidebar + beide Logins | ✅ | | **S3** | App-Name/Meta/OG/Manifest/i18n/MFA-Issuer auf Certvia | ✅ | | **S4** | Poppins + Open Sans self-hosted bestätigt (waren es bereits), Fallback-Stack + `swap` geprüft | ✅ | | **S7** | Login, Plattform-Login, Change-Password, Enroll-MFA, Konto-deaktiviert, 404, 500 gebranded | ✅ | | **S9** | Produkt-Referenzen bereinigt, Dachmarke belassen | ✅ | | **S5** | Branding-Layer für Dokument-/Export-CD (`src/lib/brand.ts` + Print-Stylesheet) | ✅ (Andockpunkt) | | **S8** | Branding-Resolver mit Certvia-Default, Custom überschreibt nur wenn gesetzt | ✅ | | **S6** | Brandfähige E-Mail-Template-Basis (SMTP selbst folgt in Paket 4) | ✅ (Basis) | --- ## 4. Wo liegt was (neu) | Pfad | Inhalt | |---|---| | `src/lib/brand.ts` | Marken-/UI-Farben als JS-Konstanten, Produktname/Tagline/Byline, Asset-Pfade, `resolveTenantBranding()` | | `src/lib/document-brand.ts` | Dokument-CD (helles Theme, Kopf-/Fußzeilen-Bausteine) — Andockpunkt für DOCX/PDF | | `src/lib/email-brand.ts` | Brandfähige HTML-/Text-Mail-Basis für Paket 4 | | `src/components/brand/certvia-logo.tsx` | `` als Inline-SVG | | `src/components/brand/tenant-brand.tsx` | Mandanten-Marke mit Certvia-Fallback | | `src/components/brand/powered-by-gefim.tsx` | Dachmarken-Hinweis inkl. GEFIM-Logo | | `public/assets/logo/` | Certvia-SVGs/PNGs + GEFIM-Dachmarkenlogo | | `public/favicon/`, `public/favicon.ico`, `public/site.webmanifest` | App-Icons und PWA-Manifest | | `docs/branding/` | Aufgabenpaket + Logo-README aus dem Design-Paket | | `src/app/globals.css` (`@media print`) | Druck-/Dokument-CD | --- ## 5. Beim Einbau aufgefallen (Abweichungen vom Aufgabenpaket) - **Lockup-SVG trägt Poppins jetzt eingebettet.** `public/assets/logo/certvia-lockup-positiv.svg` enthält Poppins 300 + 700 als woff2-Data-URI (≈22 KB). Damit erscheint die Wortmarke auch außerhalb der App korrekt (Druck, Export, Mail) — der offene Punkt „Text in Pfade wandeln" aus `docs/branding/README-Logo.md` ist damit erledigt. Geometrie und Farben sind unverändert. In der App rendert `` das Zeichen ohnehin inline und nutzt die App-Schrift direkt. - **`/site.webmanifest` war nicht erreichbar.** Der Route-Gate-Matcher in `src/proxy.ts` nahm nur `svg|png|jpg|ico` aus — für `.webmanifest` lieferte der Server die Login-Seite statt JSON, das PWA-Manifest wäre also wirkungslos geblieben. Endung ergänzt. Bewusst **keine** Verzeichnis- Ausnahme für `assets/`: das ist zugleich die App-Route des Asset-Inventars und bleibt hinter dem Gate (nachgeprüft: `/assets`, `/assets/xyz` → 307 auf `/login`). - **`src/app/favicon.ico` entfernt.** Die Datei-Konvention von Next.js und eine `public/favicon.ico` schließen sich gegenseitig aus; die Icons laufen jetzt vollständig über `metadata.icons`. - **404-/500-Seiten neu angelegt** (`src/app/not-found.tsx`, `src/app/error.tsx`) — es gab bisher keine. Sie erscheinen für angemeldete Nutzer; anonyme Aufrufe fängt weiterhin das Login-Gate ab. ### Kontrast (WCAG AA, geprüft) | Kombination | Kontrast | Bewertung | |---|---|---| | Magenta `#812d80` auf Weiß (Wortmarke/Print) | 8,0 : 1 | AA + AAA | | Magenta `#d17bcf` auf Karte `#141a2e` | 6,1 : 1 | AA | | Magenta `#d17bcf` auf Seitengrund `#0e1220` | 6,6 : 1 | AA | --- ## 6. Bewusste Abgrenzungen - **UI-Palette unverändert.** Die Dark-Theme-Farben wurden nur konsolidiert/umbenannt, nicht geändert. `--brand-violet` (`#5d52a3`) gilt für Logo/Print/Verläufe, `--ui-primary` (`#7d6fd6`) für Interaktion. - **Kein Light-Mode.** Die App ist bewusst dark-only; `` existiert für Dokument-/Druck-/Mail-Kontexte, wird in der UI aber nicht verwendet. - **Poppins 400** ist nicht als woff2 im Repo (vorhanden: 300/500/600/700). Aktuell nutzt nichts Poppins 400 — Headlines laufen auf 600/700, die Wortmarke auf 300/700. Sollte 400 gebraucht werden, muss die woff2 ergänzt werden; ein CDN-Fetch bleibt ausgeschlossen. - **Logo-Upload je Mandant** braucht Objektspeicher (Admin Phase 2). Der Resolver ist bereits darauf vorbereitet (`logoUrl` optional), das Feld existiert im Schema noch nicht — bewusst keine Migration. - **DOCX/PDF-Export** existiert noch nicht. S5 liefert den Branding-Layer (Konstanten + Kopf-/Fußzeile + Print-CSS), an den das Export-Feature andockt.