Commit graph

4 commits

Author SHA1 Message Date
Till JS
870e2aea85 feat(decks): card-stack visualization + direct-launch study mode
Decks fühlen sich jetzt wie echte Karten an, statt flacher Boxen.
Eine zentrale CardSurface-Komponente trägt die Karten-Optik
(Border, Radius 0.875rem, Shadow, Color-Stripe links) — drei
Sizes (md/lg/hero), drei Konsumenten, ein visuelles Familien-Set.

Komponenten:
- CardSurface.svelte   Foundation für jede Card-Erscheinung in Cards
- DeckStack.svelte     5:7-Stapel mit 3 deterministisch tilted
                       Hintergrund-Layern (cyrb53-Hash der Deck-ID,
                       reproduzierbar pro Mount), Color-Stripe-Akzent,
                       Title/Description/Card-Count/Due-Badge
- DeckGrid.svelte      Auto-fill responsive Grid; selectedId-Prop
                       triggert Stufe-1-Animation (others fade-out,
                       selected scale-up)
- DeckFan.svelte       Auffächer-Detail-View (Hand of Cards) mit
                       Top-7-Karten als Spread, Mount-Animation
                       gestapelt → fanned via doppeltem rAF +
                       cubic-bezier-Transition
- utils/deck-tilt.ts   cyrb53 + stackLayers für Pseudo-Random-Tilts

Routing-Wechsel: Klick auf Deck-Stack → 220ms Stufe-1-Fade →
goto('/study/<id>') direkt in den Lernmodus. Detail-View
(/decks/<id>) bleibt erreichbar über "Karten verwalten →"-Link
in der Study-Sidebar.

Lernmodus visuell als Karte:
- Globale Header (Logo + Nav + Sprach-Switcher) im Lernmodus
  ausgeblendet (routes/+layout.svelte detektiert /study/<deckId>
  per Regex), volle Konzentration auf die Karte
- Lern-Karte ist CardSurface size="hero" mit aspect-ratio 5:7
  (Portrait, gleiches Verhältnis wie Deck-Stacks und Fan-Karten)
- Color-Stripe links zeigt die Deck-Farbe — visuelle Bindung an
  Herkunft
- Sidebar oben links absolute-positioniert: ← Decks, Deck-Name,
  Fortschritt, Karten verwalten → — kompakter UI-Block, der die
  Karten-Zentrierung NICHT beeinflusst (Karte bleibt geometrisch
  Bildschirm-Mitte)
- Reveal-Button + 4er-Grade-Grid (Wieder/Schwer/Gut/Leicht) als
  Aktions-Leiste UNTER der Karte — keine weiteren Karten, ein
  Review = eine Karte

Mobile (≤720px): Sidebar wird zur horizontalen Zeile oben, Karte
rückt darunter durch padding-top: 6.5rem.

Reduced-motion durchgängig respektiert (keine Tilts, keine Hover-
Lifts, keine Fan-Spread-Animation, kein Card-Transition).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:02:04 +02:00
Till JS
fd86d968a4 Phase 9h: A11y-Pass
Globaler :focus-visible-Outline (var(--color-primary), 2px) — Tailwind 4
strippt die Browser-Defaults, ohne Fokus-Ring sind Tastatur-Nutzer blind.
.sr-only-Utility (Standard-Rezept) und .skip-link in app.css. prefers-
reduced-motion: schaltet alle Transitions/Animationen auf 0.01ms.

Layout: Skip-Link "Zum Inhalt springen" → #main, main bekommt tabindex="-1"
und id, html-lang wird via $effect reaktiv mit i18n.current synchronisiert
(Initial-SSR rendert "de", Browser zieht nach).

Header: nav-aria-label aus i18n (common.main_nav), Locale-Switcher-Label
aus common.language_switcher. ToastStack: role=region + aria-live=polite,
einzelne Toasts role=alert (error) bzw. status (success/warning), Schließen-
Button-Label i18n-konform.

Hover-only Delete-Buttons (Decks-Liste, Deck-Detail-Karten) bekommen
focus-visible:opacity-100 — bisher waren sie für Tastatur-Nutzer
unsichtbar. opacity-0 statt hidden, damit Tab-Order intakt bleibt.

svelte-check 379 files 0 errors, prod-Build sauber.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:24:33 +02:00
Till
89a7a9250b Phase 4: Frontend-Core MVP — Decks, Cards, Study mit FSRS-Loop
Stack:
- Tailwind 4 via @tailwindcss/vite (oklch-Theme + Dark-Mode-Auto)
- marked + DOMPurify für Markdown (sanitized, SSR-Safe)
- Svelte 5 runes durchgängig ($state, $derived, $effect)
- @sveltejs/adapter-node für Production-Build

Infrastruktur:
- $lib/auth/dev-stub.svelte.ts: User-ID via sessionStorage (Phase 2
  ersetzt durch echtes JWT via @mana/shared-auth)
- $lib/api/{client,decks,cards,reviews}.ts: typed Fetch-Wrapper, ruft
  cards-api auf 3081 mit X-User-Id-Header
- $lib/stores/toasts.svelte.ts: Toast-Store mit info/success/warning/error
- $lib/markdown.ts: marked → DOMPurify-Pipeline
- $lib/components/{Header,ToastStack}.svelte: Layout-Shell

Routes:
- / → Dev-Login-Form oder Redirect zu /decks (wenn eingeloggt)
- /decks → Liste mit Color-Dot, Hover-Delete-Button
- /decks/new → Create-Form (Name, Beschreibung, Color-Picker)
- /decks/[id] → Detail mit Cards-Liste + dueCount + "Lernen"-Button
- /cards/new?deck=... → Type-Picker (basic|basic-reverse) +
  Side-by-Side Markdown-Editor mit Live-Preview
- /study → Übersicht aller Decks mit Due-Counts
- /study/[deckId] → Session-View mit Queue-Snapshot, Reveal/Grade,
  Hotkeys (Space/Enter=Reveal & Good, 1-4=Again/Hard/Good/Easy),
  INPUT-Skip im Keyboard-Handler

CORS auf cards-api für localhost-Origins + cardecky.mana.how.

Verifiziert:
- pnpm run type-check  4/4 packages, svelte-check 0 errors
- pnpm build (cards-web)  adapter-node bundle 140 kB server,
  alle Routen bundled
- Tailwind-CSS inlined in SSR-HTML, oklch-Theme korrekt
- CORS-Preflight funktioniert (OPTIONS 204 mit korrekten Allow-*-Headers)
- Live-Smoke-Test gegen localhost:3081 (cards-api) + localhost:3082
  (cards-web): Beide laufen parallel, Web → API CORS-fetch grün

Outside scope (Phase 4):
- Card-Edit-Page (/cards/[id]/edit) — heute nur Create + Delete
- Settings/Account/Credits/DSGVO-Pages — Phase 9 (Polish)
- Anki-Import — Phase 8

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:52:31 +02:00
Till
8605b1b517 Phase 0+1: Repo-Skelett für Cards-Greenfield
Strategie B (beschlossen 2026-05-08): Cards wird als eigenständige
föderierte App neu gebaut, ohne Code-Übernahme aus mana-monorepo.

Skelett enthält:
- apps/api: Hono+Bun mit /healthz, /version, Manifest-Endpoint, leere
  pgSchema('cards'), Drizzle-Config, erstem Vitest
- apps/web: SvelteKit 2 + Svelte 5 (runes), Vite auf 3082
- packages/cards-domain: Pure-TS, CardType-Discriminated-Union,
  SubIndex-Granularität für Reviews, Future-CardType-Set vorbereitet
- infrastructure/docker-compose.yml: Postgres 16 auf 5435
- app-manifest.json: v1.0.0, Verein-owned, beta-tier
- .github/workflows/ci.yml
- docs/LESSONS_FROM_MANA_MONOREPO.md (Read-Day-Output, 15 Lehren)

Pre-Flight für Phase 2 (Auth-Föderation): DNS cardecky.mana.how,
GitHub-Repo mana-ev/cards, Cards-App-Registrierung in mana-auth,
NPM_AUTH_TOKEN für Verdaccio.

Plan: mana/docs/playbooks/CARDS_GREENFIELD.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:08:41 +02:00