Files
videogen/design/desktop-ansicht/README.md
JUSN 39e6aa20e7 Design-Handoff Desktop-Ansicht: Spezifikation + Referenz-Prototyp
Die Mobile-App laeuft im Browser bisher als schmale Handy-Spalte
(siehe design/desktop-ansicht/referenz/mobile-ansicht-im-browser.png).
Dieses Bundle beschreibt die Desktop-Adaption: dreispaltiges App-Layout
mit permanenter Sidebar, zentralem Kartenstapel und Detailspalte,
Swipe ersetzt durch Maus-Drag, Buttons und Tastatur.

- README.md: vollstaendige Spezifikation (App-Shell, Screens Feed/Profil/
  Erstellen/Einstellungen, Interaktionen, State-Modell, Design-Tokens)
- Videogen Web.dc.html + support.js: Referenz-Prototyp zum Ansehen,
  ausdruecklich kein Produktionscode
- PROMPT.md: Umsetzungsauftrag, Pfade an die Ablage im Repo angepasst

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 08:56:54 +02:00

267 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 15).
- 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, <hue0> 0%, <hue1> 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 <Name>' 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.