fix: design critique findings, and the settings card that saved nothing

The critique found a functional bug I had shipped an hour earlier: the whole
e-mail configuration was never sent. `saveSettings` builds its body from a fixed
field list, and none of the smtp_* fields or share_default_days were in it, and
the password input had no state at all. Filling in the card and pressing save
lost everything while the toast said "Gespeichert." That card is the
precondition for password reset, job notifications and mailing share links, so
it would have looked like the whole feature was broken. Now sent, with the
password held separately like the other secrets, and a failed PATCH no longer
reports success.

The public page told recipients how to bypass "view only": the hint about
long-pressing to save was printed regardless of allow_download, two lines under
a caption saying "Nur ansehen". The backend takes that setting seriously enough
to withhold the original even for cutouts; the page undid it. Now the two cases
have separate copy, worded for Android as well as iOS, and the hint sits above
the grid where it is actually read rather than under twenty tiles.

The share dialog had two blue buttons in step two, the exact mistake DESIGN.md
records as having happened once before, and asked five questions before a link
existed when the common case ("one picture for grandma") needs none of them.
One blue button now, and the rarely-used settings collapse behind a summary
that states what currently applies.

/konto was unreachable on a phone: the only way in was the username in the top
bar, which is hidden below 480px. It is a tab bar entry now, with short labels
so eight items still fit at 390px (49x48px each).

Network failures rendered as content: a failed load showed "nothing shared yet"
alongside an invitation to share something, and /konto and /admin hung on
"loading" forever. All three have an error state with a retry now.

Also: the public page nested a second <main> inside the app shell and inherited
padding for a tab bar anonymous visitors never see; admin inputs were 14px, so
iOS zoomed on focus at tablet width; the admin had no media queries at all, so
"Postausgangsserver" got ~156px on a phone; "Jetzt umbenennen" was clickable
without the dry run PRODUCT.md requires; share_default_days did not reach the
dialog; partial mail success was coloured as failure by a regex on the message
text; the passphrase sheet ignored the home indicator; the privacy line claimed
"encrypted" for what is a salted hash.

Added PRODUCT.md and DESIGN.md, written from the code and the wiki rather than
invented, so future design work has something to be measured against.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BNhLunz586g6DeYMa7Qsd1
This commit is contained in:
tillandClaude Opus 5 committed 2026-09-01 03:41:10 +00:00
1 parent 1d78535662
commit 14dae8e550
9 files changed
+345 -60

No files matched your search

+96
View File
@@ -0,0 +1,96 @@
# Klarbild — Gestaltung
> Aus dem Code gelesen, nicht erfunden. Quelle der Wahrheit bleibt
> `src/styles/tokens.css`; diese Datei erklärt, **warum** die Werte so sind und wo sie
> hingehören.
## Haltung
Technisch-editorial. Das Vorbild ist der Andruckbogen, nicht das Dashboard: warmes
Papier, scharfe Ecken, feine Linien, eine Passermarke als Zeichen. Die Oberfläche soll
aussehen wie etwas, mit dem man **arbeitet** — nicht wie etwas, das verkauft werden will.
Farbstrategie: **restrained**. Getönte Neutrale tragen die Fläche, ein einziges kräftiges
Blau markiert das, was man anfassen soll. Der Akzent bleibt deutlich unter 10 % der
Fläche. Bewusst: Auf dem Bildschirm liegen ständig **Fotos**, und die sollen die
einzigen bunten Dinge sein.
## Theme
**Hell, ohne Alternative.** Die Szene: Till oder Lea am Küchentisch oder im Büro, Tageslicht,
ein Foto von Phoenix auf dem Schirm, gleich soll es auf Papier. Wer Bilder beurteilt, die
auf hellem Papier landen, braucht einen hellen Untergrund — auf Dunkel wirkt jedes Bild
heller und wärmer, als es gedruckt wird. Ein Dunkelmodus wäre hier kein Komfort, sondern
eine Fehlerquelle.
## Farben
Alle Werte in OKLCH, alle Neutralen zum Papierton hin getönt (Hue 95, Chroma 0.004–0.01).
Kein `#000`, kein `#fff` — nirgends.
| Rolle | Token | Verwendung |
|---|---|---|
| Papier | `--paper` | Seitengrund, vertiefte Flächen, Eingabefelder |
| Karte | `--card` | erhobene Flächen, Kopfleiste |
| Linie | `--line` | 1-px-Trennung; **nie** dicker als Zierde |
| Schrift | `--ink` / `--ink-soft` | Haupttext / Nebentext |
| Akzent | `--accent` | genau eine Sache je Ansicht: die Handlung, die weiterführt |
| Akzentgrund | `--accent-bg` | aktiver Zustand, 6 % Deckung |
| Zustände | `--ok` `--warn` `--err` | nur für Zustände, nie zur Zierde |
**Regel für den Akzent:** Pro Ansicht ein blauer Knopf. Steht ein zweiter daneben, ist
einer davon falsch eingestuft. (Genau dieser Fehler stand kurz im Teilen-Dialog —
„Per E-Mail schicken" und „Fertig" waren beide blau.)
## Typografie
- **Space Grotesk** für alles Gelesene, **Space Mono** für Marken, Maße, Kennungen.
Beide selbst gehostet (`@fontsource`) — keine Anfrage an einen fremden Server.
- `.mono-label`: 10 px, `letter-spacing: .18em`, Großbuchstaben, `--soft`. Das ist die
**einzige** Art, Abschnitte zu betiteln. Sie kommt aus der Druckvorstufe und hält die
Oberfläche ruhig, weil sie nie mit dem Inhalt konkurriert.
- Fließtext 15–16 px, Zeilenhöhe 1.55–1.6, Zeilenlänge höchstens ~68ch.
- Überschriften mit `letter-spacing: -0.02em`; Stufenverhältnis mindestens 1.25.
- **16 px in jedem Eingabefeld** — darunter zoomt iOS beim Fokus hinein. Steht als Regel
in `tokens.css` und gilt ohne Ausnahme.
## Form
- Radius **4 px** (`--radius`), innen 3 px. Nie mehr. Weiche Ecken erzählen „App-Store",
scharfe erzählen „Werkzeug".
- Schatten praktisch unsichtbar (`0 1px 2px` bei 5 % Deckung). Tiefe entsteht über
Fläche und Linie, nicht über Weichzeichner.
- **Glasoptik nirgends.** Einzige Ausnahme: der Hintergrund hinter einem Dialog, damit
klar ist, was gerade nicht anfassbar ist.
## Layout
- `--maxw: 1060px` für Textseiten. Arbeitsansichten dürfen breiter werden, wenn sie den
Platz auch nutzen.
- Karten gruppieren, sie dekorieren nicht. **Nie verschachtelt.**
- Umbruchpunkte, die tatsächlich benutzt werden: **1200** (Einstellungen zweispaltig),
**1080** (eine Spalte, Vorschau nach vorn), **768** (Kopfleiste → Tab-Leiste unten),
**720** (Bildkarten werden zu Zeilen), **640/560** (Dialoge werden zu Blättern von unten).
- Geprüft wird bei **390 / 820 / 1440 / 1680 px**. Kein waagerechtes Scrollen, nirgends.
## Bewegung
Sparsam. `transition` auf Farbe und Hintergrund (0.15 s), `transform: scale(0.97)` beim
Drücken (0.06 s). Kein Federn, kein Nachwippen. `prefers-reduced-motion` schaltet alles ab.
## Muster
- **Dialog**: mittig am Rechner, **Blatt von unten** am Handy. Fokus wird eingefangen,
Hintergrund festgehalten, Escape schließt.
- **Zustandsmarke**: Mono, 9–10 px, Großbuchstaben, gerundete Pille, getönter Grund.
Für „aktiv / abgeschaltet / abgelaufen / geschützt".
- **Leerer Zustand**: Passermarke, eine Überschrift, ein Satz, der sagt, was zu tun ist,
und ein Weg dorthin. Nie nur „Keine Einträge".
- **Gefahr**: Rot **nur** in der Schrift, nie als gefüllter Knopf. Ein rotes Rechteck lädt
zum Draufklicken ein; genau das will man beim Löschen nicht.
## Was hier nicht vorkommt
Farbverläufe. Farbige Seitenstreifen an Karten. Glasoptik als Deko. Verlaufstext.
Illustrationen. Emoji in der Oberfläche. Gleich große Icon-Karten in Reihe.
Em-Gedankenstriche in der Oberflächensprache.