# Handoff: Videogen — Web-App (Desktop-Adaption der Mobile-App) ## Überblick Die bestehende Mobile-App („videogen", Swipe-Feed für Creator-/Produkt-Posts) als Desktop-Web-App. Statt einer schmalen Handy-Spalte im Browser: dreispaltiges App-Layout mit permanenter Navigation, zentralem Kartenstapel und Detailspalte. Swipen wird durch Maus-Drag, Buttons und Tastatur ersetzt. ## Zu den Design-Dateien Die Dateien in diesem Bundle sind **Design-Referenzen in HTML** — Prototypen, die Aussehen und Verhalten zeigen, **kein Produktionscode zum Kopieren**. Aufgabe ist, diese Designs in der bestehenden Umgebung des Ziel-Codebases nachzubauen (React, Vue, Svelte, Next.js …) mit dessen etablierten Patterns und Bibliotheken. Existiert noch keine Umgebung, das passendste Framework wählen (Empfehlung: React + TypeScript, Motion/Framer Motion für die Kartenanimation) und dort umsetzen. Die HTML-Datei ist ein „Design Component"-Format: `Videogen Web.dc.html` enthält Template + Logikklasse, `support.js` ist die Laufzeit dazu. Zum Ansehen: beide Dateien im selben Ordner belassen und die `.dc.html` im Browser öffnen. Die Logikklasse am Dateiende ist lesbarer JS-Code und dient als Referenz für Zustand und Interaktion. ## Fidelity **High-fidelity.** Farben, Typografie, Abstände, Radien, Übergänge und Interaktionen sind final gemeint und sollen pixelgenau nachgebaut werden — mit den Komponenten/Utilities des Ziel-Codebases. --- ## Globales Layout (App-Shell) - Wurzel: `display:flex`, `min-height:100vh`, **`min-width:1180px`** (darunter horizontales Scrollen, die App ist Desktop-only gedacht). - Hintergrund (fix, nicht mitscrollend): `radial-gradient(120% 80% at 50% 0%, #0d4c3d 0%, #0a3a30 34%, #24121a 68%, #40161b 100%)`, `background-attachment: fixed`. Oben Tannengrün, unten Weinrot — direkt aus der App übernommen. - Grundschrift `#f2efe9` auf diesem Verlauf. ### 1. Sidebar (links) - Breite `236px`, `flex:none`, `position:sticky; top:0; height:100vh`. - `background: rgba(8,26,22,.42)`, `backdrop-filter: blur(14px)`, rechte Kante `1px solid rgba(255,255,255,.08)`. - Padding `26px 20px`, Inhalt als Flex-Spalte, `gap:28px`. - **Brand**: 30×30 Kachel, `border-radius:9px`, `linear-gradient(150deg,#2fa87f,#0e5442)`, Buchstabe „V" 15px/700; daneben Wortmarke „videogen" 16px/600, `letter-spacing:-.01em`. - **Nav** (Flex-Spalte, `gap:4px`), Einträge: Feed, Profil, Erstellen, Einstellungen. - Item: `display:flex; gap:11px; padding:11px 13px; border-radius:11px; font:500 14px Manrope; text-align:left; cursor:pointer`. - Inaktiv: transparent, Text `rgba(242,239,233,.7)`, Border transparent. - Aktiv: `background: rgba(126,226,184,.12)`, `border:1px solid rgba(126,226,184,.4)`, Text `#d6fbec`. - Hover: `background: rgba(255,255,255,.09)`, Text `#ffffff`. Transition `.18s ease`. - Icon-Slot 20px breit (im Prototyp Glyphen ◧ ◍ + ⚙ — **in der Implementierung durch Lucide-Icons ersetzen**: `layout-grid`, `user`, `plus`, `settings`). - **Fußbereich** (`margin-top:auto`): - Statistik-Karte: `1px solid rgba(255,255,255,.12)`, `radius:14px`, `padding:14px`, `background: rgba(255,255,255,.03)`. Kicker „HEUTE" 11px, `letter-spacing:.14em`, uppercase, `rgba(242,239,233,.5)`; Zahl 22px JetBrains Mono, `font-variant-numeric: tabular-nums`, zweistellig mit führender Null; Label „Karten gesichtet" 12px `rgba(242,239,233,.55)`. - Konto-Zeile: 32px Kreis `linear-gradient(140deg,#b2323c,#5d1620)`, Name 13px/600, Rolle 11px `rgba(242,239,233,.5)`. ### 2. Kopfzeile (über dem Inhalt) - Höhe `72px`, `padding: 0 34px`, Unterkante `1px solid rgba(255,255,255,.07)`, Inhalt `space-between`. - **Tabs** links (`gap:6px`): „Videos", „Folge ich", „Posts". Jeder Tab wechselt den Kartenstapel und springt zurück auf den Feed-Screen (Index/History zurücksetzen). - `padding:9px 18px; border-radius:999px; font:500 16px Manrope`. - Aktiv: `background: rgba(255,255,255,.08)`, `border:1px solid rgba(255,255,255,.22)`, Text `#fff`, 600. - Inaktiv: transparent, Text `rgba(242,239,233,.58)`; Hover → `#fff`. - **Rechts**: Zähler „3 / 5" (12px JetBrains Mono, tabular-nums, `rgba(242,239,233,.5)`) und runder Info-Button 36px (`border:1px solid rgba(255,255,255,.18)`, `background: rgba(255,255,255,.04)`; Hover `rgba(255,255,255,.12)` + `translateY(-1px)`), toggelt das Kürzel-Panel. --- ## Screens ### A. Feed (Startansicht) **Zweck:** Karten sichten, merken oder überspringen. **Layout:** `display:grid; grid-template-columns: minmax(0,1fr) 372px; flex:1; min-height:0; overflow:auto`. #### A1 Kartenbühne (linke Spalte) - Zentriert, `padding:26px 20px 30px`, `gap:22px`, `position:relative`. - Bühne: `position:relative; width:min(404px,100%); height:560px; flex:none`. - Es werden **bis zu 3 Karten** gestapelt gerendert (konfigurierbar 1–5). - Karte k (0 = oben): `transform: translate3d(0, -12px·k, 0) scale(1 - 0.045·k)`, `z-index: 10-k`, `pointer-events` nur auf der obersten. - Karte: `position:absolute; inset:0; border-radius:26px; overflow:hidden; border:1px solid rgba(255,255,255,.14); box-shadow: 0 26px 60px rgba(0,0,0,.45); touch-action:none; user-select:none; cursor:grab` (beim Ziehen `grabbing`). - Transition: `transform .34s cubic-bezier(.22,.9,.3,1), opacity .3s ease` — während des aktiven Drags `none`. - **Karteninhalt (von unten nach oben gestapelt):** 1. Grundfläche: `linear-gradient(155deg, 0%, 100%)` (pro Karte, siehe Daten unten). 2. Streifen-Overlay: `repeating-linear-gradient(<40+9·i>deg, rgba(255,255,255,.08) 0 2px, transparent 2px 16px)`, `opacity:.5`. (Im Prototyp Platzhalter für das Video-/Bild-Asset — im Produkt liegt hier das Medium.) 3. Lesbarkeits-Verlauf: `linear-gradient(180deg, rgba(0,0,0,.32) 0%, transparent 26%, transparent 52%, rgba(0,0,0,.66) 100%)`. 4. **Pills** oben links (`padding:18px`, `gap:9px`): Art („Produkt"/„Video") und Assets („3 Bilder"). `padding:7px 15px; border-radius:999px; border:1px solid rgba(255,255,255,.34); background: rgba(0,0,0,.22); backdrop-filter: blur(6px); font:600 13px`. 5. **Caption** mittig, 118px über der Unterkante: JetBrains Mono 15px, `padding:9px 16px`, `border-radius:9px`, `background: rgba(0,0,0,.5)`, `backdrop-filter: blur(4px)`. 6. **Creator-Zeile** unten (`padding:20px`, `gap:13px`): 46px Avatar-Kreis (Farbverlauf, `border:2px solid rgba(255,255,255,.3)`), Name 19px/700 `letter-spacing:-.01em`, Untertitel 14px `rgba(255,255,255,.72)`. 7. **Entscheidungs-Badge** (nur oberste Karte, erscheint ab 40px Drag oder beim Exit): `top:86px`, links bei „GEMERKT" / rechts bei „SKIP", `padding:8px 16px; border-radius:10px; font:800 15px; letter-spacing:.12em`, `border:2px solid` und Text in Grün `rgba(126,226,184,.9)` / `#a9f0d0` bzw. Rot `rgba(232,120,120,.9)` / `#f0a8a8`, `rotate(-10deg)` bzw. `rotate(10deg)`, Opacity `min(1, |dx|/110)`, Transition `.16s`. - **Leerzustand** (Stapel durch): gestrichelter Rahmen `1px dashed rgba(255,255,255,.2)`, `radius:26px`, Titel „Alles gesichtet" 20px/600, Text „Für heute sind keine neuen Karten mehr in dieser Ansicht.", Outline-Button „Stapel neu laden" (`border:1px solid rgba(126,226,184,.6)`, Text `#8fe3c1`, Hover `background: rgba(126,226,184,.14)`), Einblendung `fadeIn .3s`. - **Aktions-Buttons** unter der Bühne (`gap:18px`), alle `border-radius:50%`, `background: rgba(14,10,12,.72)`, `border:1px solid rgba(255,255,255,.16)`, Transition `.18s`, Hover `translateY(-3px) scale(1.05)`, Active `scale(.95)`: - ✕ Ablehnen — 62px, Hover-Border `rgba(230,120,120,.75)`, Hover-BG `rgba(120,32,38,.5)`. - ↺ Zurück — 52px, Hover-Border `rgba(255,255,255,.4)`. - ♥ Merken — 70px, Text `#8fe3c1`, Border `rgba(126,226,184,.45)`, Hover-BG `rgba(20,88,68,.6)`, Hover `scale(1.06)`. (Icons in der Implementierung: Lucide `x`, `rotate-ccw`, `heart`.) - **Kürzel-Panel** (Info-Button): absolut `right:26px; top:26px`, 250px, `radius:14px`, `background: rgba(10,26,22,.9)`, `blur(12px)`, `border:1px solid rgba(255,255,255,.14)`, Einblendung `riseIn .22s`. Inhalt: ← Ablehnen, → Merken, ↑ Zurücknehmen, Maus Karte ziehen. #### A2 Detailspalte (rechts, 372px) - `border-left:1px solid rgba(255,255,255,.07)`, `background: rgba(8,22,19,.34)`, `padding:30px 28px`, Flex-Spalte `gap:24px`, `overflow:auto`. - Kicker „AKTUELLE KARTE" (11px, `letter-spacing:.16em`, uppercase, `rgba(242,239,233,.45)`), Titel = Caption der obersten Karte 26px/600 `letter-spacing:-.02em`, darunter „Name · Untertitel" 14px `rgba(242,239,233,.62)`. - Hairline `1px rgba(255,255,255,.09)`. - **Statistik-Raster** 3 Spalten, `gap:12px`: Kachel `border:1px solid rgba(255,255,255,.1)`, `radius:12px`, `padding:12px`; Wert 17px JetBrains Mono tabular-nums, Label 11px `rgba(242,239,233,.5)`. - **Beschreibung**: Kicker + Fließtext 14px, `line-height:1.75`, `rgba(242,239,233,.78)`, `text-wrap:pretty`. - **Tags**: Pills `padding:6px 12px`, `radius:999px`, `border:1px solid rgba(255,255,255,.18)`, 12px. - **Aktionen unten** (`margin-top:auto`, `gap:10px`), beide `padding:13px; radius:12px`: „Zur Sammlung hinzufügen" (Akzent-Outline `rgba(126,226,184,.55)`, Text `#8fe3c1`, Hover `rgba(126,226,184,.14)`) = gleiche Aktion wie ♥; „Überspringen" (neutrale Outline) = gleiche Aktion wie ✕. ### B. Profil - `padding:38px 44px`, `overflow:auto`, Einblendung `riseIn .26s`. - Kopf: 96px Avatar-Kreis (`linear-gradient(140deg,#b2323c,#5d1620)`, `border:2px solid rgba(255,255,255,.2)`), Name 32px/600 `letter-spacing:-.02em`, Meta „Studio-Konto · seit März 2026" 14px `rgba(242,239,233,.6)`; rechts drei Kennzahlen (`gap:34px`): Posts 38, Gemerkt (live aus dem Feed), Follower 1.204 — Werte 22px JetBrains Mono tabular-nums, Labels 12px. Unterkante Hairline `rgba(255,255,255,.09)`, `padding-bottom:26px`. - Galerie: `grid-template-columns: repeat(4,1fr)`, `gap:18px`, `margin-top:28px`. Kachel: Höhe 230px, `radius:16px`, `border:1px solid rgba(255,255,255,.12)`, Kartenverlauf + Streifen (`opacity:.45`), Titel unten auf `linear-gradient(0deg, rgba(0,0,0,.7), transparent)`, 13px/600, `padding:14px`. Hover: `translateY(-4px)`, Border `rgba(126,226,184,.5)`, Transition `.2s`. ### C. Erstellen - `padding:38px 44px`; Inhalt `max-width:920px`, `grid-template-columns: 1fr 320px`, `gap:34px`. - Titel „Neuen Post erstellen" 30px/600, Untertitel 14px `rgba(242,239,233,.6)`. - **Dropzone**: Höhe 220px, `border:1px dashed rgba(255,255,255,.24)`, `radius:18px`, `background: rgba(255,255,255,.03)`; Hover Border `rgba(126,226,184,.6)`, BG `rgba(126,226,184,.06)`. Text „Dateien hierher ziehen" 15px/600 + „MP4, MOV oder bis zu 10 Bilder" 13px. - **Felder** Titel und Untertitel: Label 12px uppercase `letter-spacing:.14em` `rgba(242,239,233,.5)`; Input `padding:13px 15px`, `radius:11px`, `border:1px solid rgba(255,255,255,.16)`, `background: rgba(0,0,0,.24)`, Text `#f2efe9`, 15px. Beide sind an die Live-Vorschau gebunden. - **Art**: Segmented Pills „Produkt / Video / Serie", `padding:10px 18px`, `radius:999px`; aktiv `border rgba(126,226,184,.6)`, `background rgba(126,226,184,.12)`, Text `#a9f0d0`. - **Aktionen**: „Veröffentlichen" (Akzent-Outline, löst Toast „Post veröffentlicht" aus), „Als Entwurf sichern" (neutrale Outline), beide `padding:13px 24px`, `radius:12px`. - **Vorschau** (rechte Spalte): Kicker + Karte 420px hoch, `radius:22px`, `linear-gradient(155deg,#1f8163,#0d4034)` + `repeating-linear-gradient(48deg, rgba(255,255,255,.07) 0 2px, transparent 2px 15px)`, unten Titel 18px/700 und Untertitel 13px auf schwarzem Verlauf — spiegelt die Eingaben live. ### D. Einstellungen - `padding:38px 44px`, Inhalt `max-width:660px`. Titel „Einstellungen" 30px/600. - Liste: Container `border:1px solid rgba(255,255,255,.1)`, `radius:16px`, `overflow:hidden`. Zeile `padding:18px 20px`, `background: rgba(255,255,255,.02)`, Trenner `1px solid rgba(255,255,255,.07)`; Label 15px/600, Hinweis 13px `rgba(242,239,233,.55)`. - Toggle: Track 52×30, `radius:999px`; aus → `background rgba(255,255,255,.05)`, `border rgba(255,255,255,.2)`, Knopf links 3px, `rgba(242,239,233,.55)`; an → `background rgba(126,226,184,.18)`, `border rgba(126,226,184,.6)`, Knopf links 25px, `#8fe3c1`. Knopf 22px, Transition `left .2s cubic-bezier(.22,.9,.3,1), background .2s`. - Einträge: Videos automatisch abspielen (an), Ton beim Öffnen (aus), Wochenrückblick (an), Bewegte Übergänge (an). --- ## Interaktion & Verhalten **Karte entscheiden — drei gleichwertige Wege:** 1. **Maus-Drag**: Pointer Events auf der obersten Karte (`pointerdown` → `setPointerCapture`, `pointermove` → Delta, `pointerup`/`pointercancel` → Auswertung). Live-Transform: `translate3d(dx, dy, 0) rotate(dx/22 deg)`, Transition währenddessen aus. Schwelle **±120px**: `dx > 120` = merken, `dx < -120` = ablehnen, sonst Rücksprung (Transition wieder an). 2. **Buttons** ✕ / ↺ / ♥ unter der Bühne (und die beiden Buttons in der Detailspalte). 3. **Tastatur** (global, nur auf dem Feed-Screen, mit `preventDefault`): `ArrowLeft` = ablehnen, `ArrowRight` = merken, `ArrowUp` = zurücknehmen. **Exit-Animation:** `transform: translate3d(±620px, -40px, 0) rotate(±22deg)`, `opacity: 0`, Dauer **320ms**, danach Index +1 und `exiting` zurücksetzen. Während `exiting` sind weitere Entscheidungen gesperrt. **Undo:** letzte Entscheidung aus der History, Index zurück, „Gemerkt"-Zähler ggf. −1. Leere History → Toast „Nichts zurückzunehmen". **Toast:** fixiert `bottom:34px`, horizontal zentriert, `padding:12px 22px`, `radius:999px`, `background: rgba(10,24,20,.92)`, `blur(10px)`, `border:1px solid rgba(255,255,255,.16)`, 14px, Einblendung `riseIn .2s`, verschwindet nach **1700ms**. Texte: „Zu ‚' gemerkt", „Übersprungen", „Nichts zurückzunehmen", „Post veröffentlicht". **Keyframes:** - `riseIn`: `opacity:0; translateY(14px)` → `opacity:1; none` (.2–.26s ease) - `fadeIn`: `opacity:0` → `1` - Fokus: `:focus-visible { outline: 2px solid #7ee2b8; outline-offset: 2px; }` — nie der Browser-Default. **Responsive:** Desktop-only, `min-width:1180px`; darunter horizontal scrollen. Der Feed-Bereich scrollt bei geringer Fensterhöhe (`min-height:0; overflow:auto`). --- ## State | State | Typ | Zweck | |---|---|---| | `screen` | `'feed' \| 'profile' \| 'create' \| 'settings'` | aktive Ansicht (Sidebar) | | `tab` | `'videos' \| 'following' \| 'posts'` | aktiver Stapel; Wechsel setzt `idx`/`history` zurück und springt auf `feed` | | `idx` | number | Index der obersten Karte im aktuellen Stapel | | `drag` | `{x, y, active} \| null` | laufende Drag-Geste | | `exiting` | `'left' \| 'right' \| null` | laufende Exit-Animation (sperrt Eingaben) | | `history` | `{idx, dir}[]` | für Undo | | `seen`, `saved` | number | Zähler Sidebar / Profil | | `showInfo` | boolean | Kürzel-Panel | | `toast` | string | Toast-Text (leer = versteckt) | | `draftTitle`, `draftSub`, `draftKind` | string | Formular „Erstellen", live in der Vorschau | | `settings` | `{autoplay, sound, digest, motion}` booleans | Einstellungen | **Datenbedarf pro Karte:** `name`, `sub`, `kind`, `assets`, `caption`, `hue: [from, to]`, `avatar` (Verlauf oder Bild-URL), `body`, `tags: string[]`, `stats: [wert, label][]`. Im Produkt ersetzt das Medium (Bild/Video) die Verlaufs-/Streifenfläche; alles andere bleibt. Die drei Tabs liefern drei Stapel (Videos, Folge ich, Posts). --- ## Design-Tokens **Farben** | Rolle | Wert | |---|---| | Seitenverlauf | `#0d4c3d` → `#0a3a30` → `#24121a` → `#40161b` | | Text | `#f2efe9` | | Text gedämpft | `rgba(242,239,233,.62)` / `.55` / `.5` / `.45` | | Akzent (Mint) | `#8fe3c1`, hell `#a9f0d0` / `#d6fbec`, Fokus `#7ee2b8` | | Akzent-Tint | `rgba(126,226,184,.12)` Fläche, `.4–.6` Rahmen, `.14` Hover | | Ablehnen | `rgba(232,120,120,.9)` Rahmen, `#f0a8a8` Text, `rgba(120,32,38,.5)` Hover | | Flächen | `rgba(8,26,22,.42)` Sidebar, `rgba(8,22,19,.34)` Detailspalte, `rgba(255,255,255,.02–.09)` | | Rahmen | `rgba(255,255,255,.07)` / `.1` / `.12` / `.16` / `.18` / `.22` | | Karten-Verläufe | grün `#1f8163→#0d4034`, blau `#256f8b→#0c2f3f`, ocker `#8a6a2f→#3a2a11`, rot `#7a2f38→#2c1014`, tannen `#2f6f5a→#0e332b`, türkis `#1c6f7f→#0a2c33`, violett `#6a2f7a→#26102c`, gold `#7a5a2a→#2f2110` | **Typografie** — Manrope 400/500/600/700 (UI), JetBrains Mono 400/500 (Zahlen, Captions). Skala: 32 / 30 / 26 / 22 / 19 / 17 / 16 / 15 / 14 / 13 / 12 / 11 px. Große Überschriften `letter-spacing:-.02em`, Kicker `+.14em`/`.16em` uppercase. Alle Zahlen mit `font-variant-numeric: tabular-nums`. **Abstände** 3 / 4 / 6 / 8 / 9 / 10 / 12 / 13 / 14 / 18 / 20 / 22 / 26 / 28 / 34 / 38 / 44 px. **Radien** 9 / 11 / 12 / 14 / 16 / 18 / 22 / 26 px, Pills `999px`, Kreise `50%`. **Schatten** nur an der Karte: `0 26px 60px rgba(0,0,0,.45)`. **Blur** 4 / 6 / 10 / 12 / 14 px (`backdrop-filter`). **Transitions** `.16s` / `.18s` / `.2s` / `.3s` ease, Karten-Bewegung `.34s cubic-bezier(.22,.9,.3,1)`, Exit `320ms`. --- ## Assets Keine Binärdateien. Alle Medien sind Platzhalter aus CSS-Verläufen und Streifenmustern — im Produkt durch echte Bilder/Videos ersetzen. Icons: **Lucide** (im Prototyp Unicode-Glyphen als Platzhalter). Fonts: Google Fonts — Manrope, JetBrains Mono. ## Dateien in diesem Bundle - `PROMPT.md` — fertiger Auftrag zum Einfügen in Claude Code. - `Videogen Web.dc.html` — der Prototyp (Template oben, Logikklasse mit Zustand/Interaktion unten, Beispieldaten in `DATA`). - `support.js` — Laufzeit, damit die HTML-Datei sich lokal öffnen lässt. Nicht portieren. - `README.md` — dieses Dokument. - `referenz/mobile-ansicht-im-browser.png` — Ausgangslage: die Mobile-App als schmale Spalte unter `videogen.project.webklar.com`, die diese Desktop-Adaption ersetzt.