UI/UX-Audit Silverscale – 06.06.2026
Ziel: Vom „Prototyp" zum „fertigen Produkt" – die letzten 20 % Polish, damit die App Jaqueline im Alltag präsentiert werden kann (Wife Acceptance Factor, WAF). Methodik: statische Code-Analyse (3 parallele Audits: Konsistenz · Gaps/TODOs · UX-Best-Practices) plus Playwright-Sweep über alle 16 Routen (mobil 390×844 hell/dunkel, Desktop 1280×900, interaktive Flows). Screenshots:
app/ui-audit/shots/(34 Stück), Skript:app/ui-audit/shoot.py(wiederverwendbar für Regressions-Checks).
1. Gesamteindruck
Die App ist deutlich näher am „fertigen Produkt" als am Prototyp. Das
maritime Design-System trägt, Dark Mode ist flächendeckend (nur Einzelfehler),
alle 16 Routen rendern fehlerfrei, Empty-States existieren fast überall, das
zentrale Fehler-Toast-System (lib/api.js) greift, Charts/Sparklines/Donut
sind liebevoll. Keine einzige TODO/FIXME-Markierung im Code – die Codebase
ist sauber gepflegt. Der Fitness-Strang (ADR-30–32) ist überraschend komplett.
Was fehlt, ist genau die gesuchte letzte Schicht: Vertrauens-Polish (Lösch-Schutz, Doppel-Submit, Eingabe-Validierung), Sprach-Polish (Bon-Rohnamen, Technik-Jargon) und Konsistenz-Polish (Spacing/Chips/ Buttons-Wildwuchs). Nichts davon ist architektonisch – alles ist in Abend-Sessions abarbeitbar.
Falsch-Alarm vorweg: Die Statistik-/Geräte-Charts wirkten in Full-Page- Screenshots leer – das ist ein Chart.js-Resize-Artefakt der Screenshot-Technik, im echten Viewport rendern sie korrekt (verifiziert).
2. Visuelle Befunde aus dem Screenshot-Sweep
Sortiert nach WAF-Relevanz (= „fällt Jaqueline sofort auf").
2.1 HOCH – Bon-Rohnamen verschmutzen die ganze App
Auf „Heute → Zuletzt gegessen" steht wörtlich:
Coca-Cola light Coca-Cola light Mehrweg Pet 1L X11l (1,29 € / 1l) zzgl. Pfand 0,15 €.
Dieselben Rohnamen stehen in Vorräten („ChickenNuggets o.Dip", „Apfel
grün,säuerlich", „WassereisWass.melone", „Toilettenpap.4-lagig"), in der
Artikel-Liste, im Tagebuch, in Statistik-Top-Produkten und in der
Einkaufslisten-Historie („laktosefreie H Milch fettarm"). Das ist der größte
einzelne Prototyp-Marker der App. Es gibt bereits foods.name als einzige
Quelle – ein Batch-AI-Job „Anzeigename generieren" (analog ai-resolve) würde
alle Oberflächen auf einmal heilen.
2.2 HOCH – Einstellungen sind eine Admin-Seite, keine Familien-Seite
einstellungen-m.png: Zwischen „Darstellung" und „Konto" stehen ein
Refresh-Token-Textfeld (im Dark Mode als hartes weißes Rechteck – einziger
echter Dark-Mode-Bruch), „Zur Klärung markiert" mit rohen EAN-Nummern
(EAN 4335619058507 ohne OFF-Tr…), „🤖 Jetzt per Claude auflösen" und
Gruppen-Sortier-Pfeile über 11 Gruppen. Für Jaqueline relevant sind nur:
Hell/Dunkel, Benachrichtigungen, ihr Profil (Avatar/Budget), Abmelden.
→ Trennung in „Einstellungen" (alle) und „⚙️ Verwaltung" (Dennis, eigene
Route oder Collapse) ist der schnellste WAF-Gewinn nach den Namen.
2.3 MITTEL – Vorräte: „Sonstiges (24)" ist die größte Gruppe
vorraete-m.png: Die Gruppierung läuft gut (Fleisch & Fisch, Getränke, Obst &
Gemüse …), aber „Sonstiges" enthält 24 Artikel inkl. Non-Food (Blend-A-Med,
Hundetrockennahrung, Pflaster, Toilettenpapier) zwischen Lebensmitteln.
Dazu wiederholt sich das Label „ohne Nährwerte" zeilenweise als Rauschen.
→ Einmalige (AI-)Nachgruppierung + Non-Food ans Ende/eigener Abschnitt +
„ohne Nährwerte" nur als dezentes Icon.
2.4 MITTEL – Titel-Truncation überall
Gerichte-Karten („BBQ Bowl mit Schv…", „Würziges Stir F…"), Tagebuch
(„CocaCola Zero Sugar – Null Zuc… "), Bon-Zeilen, Einkaufsliste. Auf 390 px
wird fast jeder Titel abgeschnitten. → 2-zeilige Titel zulassen
(-webkit-line-clamp: 2) kostet kaum Höhe und löst 80 % der Fälle; Rest löst
sich durch 2.1 (kürzere Anzeigenamen).
2.5 MITTEL – Fitness-Detail-Chart: X-Achse ohne Jahr
geraet-viewport-check.png (Abduktor, Range „1J"): Achse zeigt
08.06. · 15.06. · 22.06. · 19.07. · 29.04. · 06.05. · 21.05. – chronologisch
korrekt (2025→2026), liest sich aber als unsortiert, weil das Jahr fehlt.
→ Bei Ranges > 6 Monate Jahr ins Label (08.06.25) oder Monats-Ticks.
2.6 KLEIN – Einzelbefunde
- Heute-Hero: „+0 ~~Aktivität~~" mit Durchstreich-Optik wirkt wie ein Render-Fehler, wenn schlicht keine Aktivität geloggt ist → bei 0 ganz ausblenden oder „+ Aktivität loggen"-Link zeigen.
- ActivitySheet: CTA heißt „+0 kcal aufs Budget", solange kcal leer ist → besser disabled + „kcal eingeben".
- Tagebuch: leere Mahlzeiten zeigen nur „—" – charmanter wäre ein Mini-CTA („+ Abendessen eintragen").
- Geräte-Detail: Kopfkachel „44kg¹ Bestwert" – Einheit klebt am Wert, leichte Überlappung.
- Einkäufe: Filialname „Iserlohn - Refflingser Straße" wiederholt sich in jeder Zeile → nur bei Abweichung zeigen.
- „Claude" als UI-Begriff (FoodSheet „Foto → Claude schätzt", Einstellungen „Jetzt per Claude auflösen", AI-Pill) – für Familie eher „🤖 KI schätzt"; einheitlich entscheiden.
- Mehr-Menü-Overlay bleibt bei programmatischer Hash-Navigation offen und
blockiert die neue Seite (im Playwright-Lauf reproduziert; im Alltag selten,
aber: Overlays sollten auf
hashchangeschließen). - Konsole: SW-Registrierung scheitert auf
http://127.0.0.1(nur intern, prod via HTTPS ok) + ein 401 beim Laden (vermutlich Push/Status-Call vor Auth-Kontext) – einmal sauber abfangen, damit die Konsole leer ist.
2.7 Was visuell schon „fertig" ist ✨
Heute-Hero mit Ring + Makro-Balken (hell & dunkel top) · Tagebuch-Layout mit Mahlzeiten-Karten · Plan-Woche inkl. HF-Box-Karte und „eingeplant"-Chips · Einkaufsliste mit Gruppen + „Zuletzt verwendet" · FoodSheet-Suche (schnell, klare kcal/100g-Anzeige, drei Eingabewege) · Fitness-„Heute" mit Körperwert-Kacheln, Bio-Alter-Banner, „Frische Erfolge" · Besuchs-Detail mit Geräte-Fotos · Desktop-Sidebar-Layout wirkt erwachsen.
3. Statische Analyse A – Konsistenz (≈28 Befunde)
Design-Tokens & Farben
| # | Befund | Wo | Schwere |
|---|---|---|---|
| A1 | Hartcodierte #fff/Hex-Inks statt Token (--ss-primary-ink existiert, wird nicht konsequent genutzt) |
Today.svelte:190/193, ShoppingList.svelte:175, Articles.svelte:120, Receipt.svelte:141 u. a. | hoch |
| A2 | 4 verschiedene Backdrop-Farben/Blur für Modals (.45 vs .4 vs .7) |
App.svelte:245, Sheet.svelte:29, ScanResultPopup.svelte:62, ScanSheet.svelte:163 | mittel |
| A3 | Ad-hoc-Gradients statt --ss-grad-* |
Visit.svelte:97 (InBody-Lila), Today-Hero | mittel |
| A4 | Opacity-Werte (.3–.85) nicht theme-aware → Dark-Mode-Lesbarkeit | DishCard.svelte:43, ShoppingList.svelte:182, Settings.svelte:309 | mittel |
| A5 | rgba(10,30,50,.75)-Overlays statt Token |
DishCard.svelte:44–46 | niedrig |
Komponenten-Extraktion (Copy-Paste-Patterns)
| # | Befund | Wo | Schwere |
|---|---|---|---|
| A6 | 6+ Chip-Varianten (chip2, mc, schip, hffilter, planchip …) mit je eigenem Padding/Radius |
Visit, Plan, Diary, Dishes, ShoppingList, Article | hoch |
| A7 | Delete-Button 4× lokal definiert (.del, .x …) |
Today:229, Diary:204, ShoppingList:131 | mittel |
| A8 | 4 Empty-State-Implementierungen (Karte+Emoji vs. — vs. Langtext) |
Dishes:80, Diary:99, Pantry:64, Visit:85 | mittel |
| A9 | 2 Spinner-Typen, 5 Definitionen (.sonar-Keyframes 3× dupliziert) |
App, Article, Dish, Dishes, Settings | niedrig |
| A10 | 15+ lokale Page-Header, Paddings streuen (14–16px) | alle Seiten | mittel |
| A11 | Back-Button mal ‹ zurück, mal ‹ Einkäufe, Klasse .back nur teils definiert |
Article:136, Visit:34, Receipt:61 | mittel |
| A12 | „Mehr"-Menü nutzt eigenes Overlay statt Sheet.svelte; ScanResultPopup ebenso |
App.svelte:133–143 | mittel |
Microcopy & Formate
| # | Befund | Wo | Schwere |
|---|---|---|---|
| A13 | „löschen" vs. „entfernen" vs. „Entfernen" gemischt | Diary:96, ShoppingList:131, Dish:357, Article:259 | mittel |
| A14 | Toast-Schema uneinheitlich (Gespeichert ✓ vs ✓ Lieblingsartikel vs ohne ✓) – ~8 Varianten bei ~25 Aufrufen |
App-weit | mittel |
| A15 | Primär-Button-Labels: Speichern/Eintragen/Übernehmen/Verbrauchen ohne Regel | FoodSheet:170, Dishes:131, Pantry:111 | niedrig |
| A16 | Datums-Ad-hoc-Slicing neben fmtDate() |
Plan:99, ShoppingList:84, Stats:68, Settings:198 | mittel |
Spacing/Typo-Skala
| # | Befund | Zählung | Schwere |
|---|---|---|---|
| A17 | ~35 hartcodierte font-sizes (10/11/12/14/17/34/38px…) neben --ss-text-* |
App-weit | hoch |
| A18 | ~25 verschiedene Padding-Werte, keine Spacing-Skala (--ss-space-* fehlt) |
App-weit | hoch |
| A19 | 8 Border-Radius-Werte neben --ss-r-* (5/6/7/8/10px…) |
App-weit | mittel |
Empfohlene Reihenfolge: Erst --ss-space-*-Skala + font-size-Mapping in
app.css (1 h, mechanisch), dann Badge.svelte/EmptyState.svelte/
DeleteButton.svelte extrahieren (2–3 h), dann Farben/Backdrops (1 h).
4. Statische Analyse B – Gaps, TODOs, halbfertige Features
Code-Marker
✅ Keine TODO/FIXME/HACK im gesamten Code. Offene Punkte leben ausschließlich in REPORT/ARCHITEKTUR (gute Disziplin).
Validierungs-Lücken (echte Bugs-in-Wartestellung)
| # | Befund | Wo | Fix |
|---|---|---|---|
| B1 | DiaryIn.grams, ConsumeIn.qty, IngredientIn.grams ohne gt=0 → negative Gramm = negatives Budget möglich |
backend/main.py ~751/939/1059 | Field(..., gt=0) |
| B2 | ActivityIn.kcal ohne Grenzen → -100 kcal oder 99999 aufs Budget |
backend/main.py ~849 | gt=0, lt=5000 |
| B3 | type="number" ohne min/inputmode im Frontend (9 Dateien) |
Pantry:99, Article:208–211, Activity:458 … | min="0" inputmode="decimal/numeric" |
Fehlerbehandlungs-Lücken
| # | Befund | Wo |
|---|---|---|
| B4 | Raw-fetch ohne Toast-Wrapper: Push-Subscribe (3×), ai-resolve-Status, FoodSheet-Foto/by-ean |
stores.js:86–109/128, FoodSheet.svelte:67–69 |
| B5 | Backend-Fehlertexte landen 1:1 im Toast („Fehler: food_id 12345 not found") | api.js:16–19 |
Roadmap-Features – Code-Realität
| Feature | Status im Code |
|---|---|
| 🤖 Woche füllen | 0 % – kein Stub. Nur /api/plan-pick-Sortierung als Basis vorhanden |
| PVG-Packungsgewichte | PVG fertig (Dish.svelte:266–307, main.py ~1816), aber pack-Modus schätzt pauschal „1 Packung"; foods.packaging_weight_g fehlt im Schema + UI-Feld |
| Mehrfach-Scan Listen-Abhaken | 0 % (bewusst zurückgestellt) |
| Jaqueline-Login | Heuristik in auth.py fertig; es fehlt nur der Pocket-ID-User + Erstlogin |
| iPhone-Verifikation | Scan-Popup, Wir-Modus, Markdown, Donut – am Gerät ungetestet |
| Cross-User-Leak Fitness (ADR-30d) | ✅ geprüft: user_id-Filter überall korrekt (visit/machine/machines + Sub-Queries) |
Empty-/Lade-States (Rest-Lücken)
- Activity „Heute" ohne Daten: leere Sparkline-Kacheln statt „noch keine Daten" (Activity.svelte:86–100)
- Body-Tab: Laden ohne „Noch keine Messungen"-Text (Activity.svelte:440)
- Dish-Historie: leer = unsichtbar statt Hinweis (Dish.svelte:240)
5. Statische Analyse C – UX-Best-Practices / Mobile
Vertrauen & Datensicherheit (WAF-kritisch!)
| # | Befund | Wo | Schwere |
|---|---|---|---|
| C1 | window.confirm() beim Gericht-Löschen (OS-Dialog, bricht Design) |
Dish.svelte:177 | hoch |
| C2 | Tagebuch-/Listen-Löschen ohne Confirm und ohne Undo – ✕ tippen = weg | Diary.svelte:49, Today.svelte:41 | hoch |
| C3 | Kein Doppel-Submit-Schutz: FoodSheet.save(), Diary.saveEdit(), Dish.remove() ohne saving-Lock → bei langsamem Netz Duplikat-Einträge |
FoodSheet.svelte:92–109 u. a. | hoch |
| C4 | Submit-Buttons ohne Spinner (disabled-Pattern existiert nur in Settings) | FoodSheet:199, ActivitySheet:65 | mittel |
Touch & Eingabe
| # | Befund | Wo |
|---|---|---|
| C5 | ✕-Lösch-Buttons ~20×20px (iOS-Minimum 44px) | Today:128, Diary:96, Pantry:146 |
| C6 | Stepper ±-Buttons 32px, eng | Pantry:143 |
| C7 | Avatar-Switcher 38px, 6px Gap | App.svelte:174 |
| C8 | inputmode fehlt auf mehreren Zahlenfeldern (iOS zeigt Volltastatur) |
Pantry:99, Article:208–211 |
| C9 | Enter-Submit inkonsistent (FoodSheet/Liste ja, Pantry/Article nein) | div. |
| C10 | Keine visualViewport-Behandlung: iOS-Tastatur kann Sheet-Felder/Toast verdecken |
Sheet.svelte:38, App.svelte:228 |
Daten-Frische & Feedback
| # | Befund | Wo |
|---|---|---|
| C11 | Kein visibilitychange-Refresh: App aus Hintergrund = Stale-Daten (gerade im Wir-Modus relevant, wenn beide loggen) |
App.svelte |
| C12 | Optimistic Updates nur in ShoppingList.toggle(); Tagebuch/FoodSheet warten auf Server | ShoppingList:51 vs. Diary:34 |
Accessibility
| # | Befund | Wo |
|---|---|---|
| C13 | Bottom-Nav/Mehr/Stepper ohne aria-label (Sheet/Diary haben es vorbildlich) |
App.svelte:69/126, Pantry:85 |
| C14 | Kein button:focus-visible-Stil (Inputs haben einen) |
app.css:146 |
| C15 | prefers-reduced-motion nirgends beachtet (fadeUp/sonar/spin/Puls) |
global |
| C16 | .muted + 11px ≈ Kontrast 3,2:1 → WCAG-AA-Fail bei Kleintext |
app.css:164 + Pantry:79 |
PWA
| # | Befund | Wo |
|---|---|---|
| C17 | theme_color fix dunkel #0d2438 → falsche Statusbar-Farbe im Light Mode (Meta-Tag dynamisch per theme-Store setzen) |
manifest + index.html:7 |
| C18 | Offline = weiße Seite (bewusst kein SW-Cache, ADR-17 – aber ein navigator.onLine-Banner wäre billig) |
sw.js |
| C19 | Safe-Area/dvh/Overscroll: ✅ alles korrekt gelöst | – |
Navigation
| # | Befund | Wo |
|---|---|---|
| C20 | Browser-Back schließt Sheets nicht (Hash-Router weiß nichts von Overlays); Mehr-Menü bleibt bei Hash-Wechsel offen (reproduziert) | Sheet.svelte, App.svelte |
| C21 | Scroll-Position bei Liste→Detail→Zurück geht verloren | router.js |
| C22 | Unbekannte Route = stiller Fallback auf Heute (ok, kein 404 nötig) | App.svelte:114 |
Performance
- Bundle: 567 KB JS + 84 KB CSS (ungezippt), zxing-wasm korrekt lazy → für Heim-Server völlig ok, kein Code-Splitting nötig.
- Vorräte/Artikel rendern alle Zeilen ins DOM; Artikel hat Pagination („Mehr laden"), Vorräte (~120 Zeilen) noch unkritisch. Beobachten.
6. 🏆 Top 10 Improvements: Prototyp → Produkt
Priorisiert nach WAF × Aufwand. „Abend" = heute machbar.
| # | Improvement | Warum das den Unterschied macht | Aufwand |
|---|---|---|---|
| 1 | Anzeigenamen-Politur: Batch-AI-Job generiert für alle ~1050 Artikel kurze deutsche Anzeigenamen („Coca-Cola light 1L" statt Bon-Zeile); Anzeige überall, Rohname bleibt als Tooltip/Feld | Wirkt auf JEDER Seite gleichzeitig; der sichtbarste Prototyp-Marker verschwindet | 1 Abend (Job + Spalte display_name + Frontend-Fallback) |
| 2 | Lösch-Vertrauen: einheitliches Confirm-Sheet (statt window.confirm) + Undo-Toast fürs Tagebuch + 44px-Touch-Targets für alle ✕ |
„Ich hab aus Versehen mein Frühstück gelöscht" ist der schnellste Vertrauenskiller | 1–2 h |
| 3 | Submit-Härtung: saving-Lock + Spinner auf allen Save-Buttons (FoodSheet, ActivitySheet, Diary, Article, Settings) |
Verhindert Duplikat-Einträge bei Mobilfunk; sichtbares „es passiert was" | 1–2 h |
| 4 | Einstellungen splitten: Familien-Teil (Darstellung, Push, Profil, Abmelden) vs. „Verwaltung"-Bereich (HF-Token, EAN-Klärung, Gruppen, AI) – plus „Claude"→„KI" im UI | Die einzige Seite, die aktuell nach Bastelprojekt aussieht | 1–2 h |
| 5 | Eingabe-Validierung beidseitig: Pydantic gt=0-Felder + min/inputmode auf allen Zahlenfeldern + Enter-Submit überall |
Schützt Budget-Integrität; Zahlen-Pad statt Volltastatur ist täglich spürbar | 1 h |
| 6 | Frische-Garantie: visibilitychange-Refresh der aktiven Seite + Optimistic Toggle vereinheitlichen |
Wir-Modus: Jaqueline sieht sofort, was Dennis geloggt hat – sonst wirkt die App „kaputt" | 1 h |
| 7 | Vorräte entrümpeln: AI-Nachgruppierung der 24 „Sonstiges", Non-Food-Sektion ans Ende, „ohne Nährwerte" → Icon, 2-zeilige Titel app-weit (line-clamp: 2) |
Vorräte ist die Browsing-Seite für den Küchenalltag | 1 Abend |
| 8 | Design-System-Schulden: Spacing-/Type-Skala in app.css durchziehen, Badge/EmptyState/DeleteButton extrahieren, Backdrop-Token, weiße HF-Textarea im Dark fixen | Macht alle künftigen Features automatisch konsistent; stoppt den Wildwuchs | 1 Abend |
| 9 | A11y/Komfort-Paket: aria-labels (Nav, Stepper), :focus-visible, prefers-reduced-motion, Kontrast .muted-Kleintext, dynamische theme-color, Offline-Banner |
Die unsichtbaren 5 %, die „professionell" von „selbstgebaut" trennen | 2 h |
| 10 | Fitness-Feinschliff + Jaqueline-Onboarding: Geräte-Chart-Labels mit Jahr, Empty-States Activity/Body, „+0 Aktivität"-Hero-Fix – und: Pocket-ID-User für Jaqueline anlegen + gemeinsamer Erstlogin als „Launch-Moment" 🚀 | Der eigentliche Produkt-Launch: Sie loggt sich selbst ein, alles fühlt sich fertig an | 1–2 h |
Bewusst NICHT in den Top 10 (Roadmap, nicht Polish): 🤖 Woche füllen, PVG-Packungsgewichte, Mehrfach-Scan, Capacitor-iOS-App.
7. Abarbeitungsplan für heute Abend
Reihenfolge so gewählt, dass nach jedem Block deploybar ist:
Block 1 – Vertrauen (≈2 h): Top 2 + 3 + 5 → Confirm-Sheet-Komponente, Undo-Toast, 44px-Targets, saving-Locks, Pydantic-Validierung, inputmode/min.
Block 2 – Sprache (≈2 h): Top 1 + Teile von 4
→ display_name-Spalte + AI-Batch-Job anstoßen (läuft im Hintergrund),
Frontend auf display_name || name umstellen; Einstellungen-Split.
Block 3 – Wahrnehmung (≈1,5 h): Top 6 + 7 (line-clamp sofort, AI-Gruppen über Nacht) + Quick-Fixes aus §2.6 (Hero +0, ActivitySheet-CTA, weiße Textarea).
Block 4 – wenn noch Energie (≈1,5 h): Top 8/9 mechanische Teile (Spacing-Skala, aria-labels, focus-visible, reduced-motion, theme-color).
Danach: Frontend-Build + Deploy + gemeinsamer iPhone-Durchgang (erledigt nebenbei die offene iPhone-Verifikation aus REPORT §3) + Jaquelines Pocket-ID-User = Launch. 🎉
8. ✅ Abarbeitungs-Status (gleicher Abend, Blocks 1–4 umgesetzt)
| Block | Commit | Inhalt | Verifiziert |
|---|---|---|---|
| 1 Vertrauen | 7118095 |
Undo-Toast (DELETE→restore), ConfirmDialog statt window.confirm, saving-Locks+Spinner (6 Stellen), Pydantic gt-Grenzen, inputmode/min, 44px-Tap-Zonen, 422-Toasts lesbar |
Playwright: Undo-Roundtrip + Dialog-Screenshot; curl: 422 bei −50 g/−100 kcal |
| 2 Sprache | 38093b1 |
foods.display_name + COALESCE-Schicht (row2food + 6 Queries), polish_names.py (Haiku-Batch, alle ~1050 Artikel), Artikel-Seite mit Anzeigename/Bon-Name, Settings-Split (Verwaltung eingeklappt), Claude→KI, textarea.field Dark-Fix |
Screenshots Settings/Vorräte; Namen live („5 % Rinderhack", „Chicken Nuggets ohne Dip") |
| 3 Wahrnehmung | b7e5dde |
visibilitychange-Refresh (60 s Bump / 30 min Reload), .clamp2-Titel, Vorräte: Gruppen-Reihenfolge-Bugfix + Non-Food ans Ende, Tagebuch-„+ eintragen"-CTA (presetMeal), Geräte-Chart-Jahreslabels, Einkäufe-Filial-Dedupe |
Screenshots aller 5 Flächen |
| 4 A11y/Tokens | 74f21c3 |
Backdrop-Token, :focus-visible, prefers-reduced-motion, ink-3-Kontrast (WCAG), dynamische theme-color, Offline-Toast, aria-labels, Backfill-Endpoint + --groups-Pass |
Sweep ui-audit/shots-final/ |
| Bonus | b9020b3 |
eGYM-Sync-Fix: Netpulse meldet tote Sessions als 403 → Auth-Retry griff nie; jetzt 401+403 → Re-Login. Sync-Button pollt Status & zeigt Fehler als Toast | Heutiger Besuch (06.06., 13 Geräte, InBody) synct & rendert |
Doku: ADR-33 (display_name) + ADR-34 (UX-Härtung) in app/ARCHITEKTUR.md,
CLAUDE.md-Stand aktualisiert. Offen aus den Top 10: Jaquelines
Pocket-ID-Erstlogin (braucht euch beide + iPhone) und die iPhone-Verifikation
der neuen Flows – Rest ist live auf https://silverscale.dennisfisch.de.
9. Anhang
- Screenshots:
app/ui-audit/shots/–*-mmobil hell,*-m-darkmobil dunkel,*-dDesktop,flow-*interaktive Flows,*-viewport-checkChart-Verifikation. - Sweep-Skript:
app/ui-audit/shoot.py(nutztX-Internal-Token, läuft gegen 127.0.0.1:9300; nach jedem größeren UI-Block erneut laufen lassen = visueller Regressionstest). - Bekannte Nicht-Befunde: Charts in Full-Page-Screenshots leer = Artefakt; Fitness-Cross-User-Filter korrekt; Safe-Area/dvh/Overscroll korrekt; 404-Fallback auf Heute akzeptabel.