Correspondence Log with Compact Strip + Permanent Second Row. All design decisions from the exploration session locked in.
restrictToCorrespondentsOf — just surface the results)restrictToCorrespondentsOf prop — drives the suggestions/api/documents/conversation endpoint — no backend change for bilateral view?senderId=…&receiverId=…&from=…&to=…&dir=…goto()| Element | Tailwind classes | Real size | Notes |
|---|---|---|---|
| Strip Row 1 container | flex items-end gap-4 px-4 sm:px-6 py-3 bg-surface border-b border-line |
h ~56px, px 16–24px, py 12px | White background, 1px bottom border |
| Field label (.FL) | text-xs font-bold uppercase tracking-widest text-ink-2 mb-1.5 |
12px / 700 | "optional" suffix: font-normal not-italic text-ink-3 |
| Text input / typeahead | h-10 w-full px-3 text-sm border border-line bg-surface text-ink placeholder:text-ink-3 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none |
40px tall, 14px text | Optional field: border-dashed bg-muted when empty |
| Swap button | h-10 w-10 flex shrink-0 items-center justify-center border border-line text-ink-2 hover:text-ink hover:border-ink transition-colors self-end |
40×40px | Active (both set): border-ink text-ink |
| Strip Row 2 container | flex items-center gap-3 px-4 sm:px-6 py-2 bg-canvas border-b border-line |
h ~36px, py 8px | When no person selected: opacity-40 pointer-events-none |
| Row 2 period label | text-xs font-bold uppercase tracking-widest text-ink-3 shrink-0 |
12px / 700 | "Zeitraum" label before the date fields |
| Date input (Von / Bis) | h-8 w-24 px-2 text-xs border border-line bg-surface text-ink placeholder:text-ink-3 focus:border-ink focus:outline-none |
32px tall, 12px text, 96px wide | When set: border-ink. Format: dd.mm.yyyy |
| Letter count | ml-auto text-sm font-bold text-ink-2 |
14px / 700 | When filtered (≠ total): text-primary |
| Sort toggle button | h-8 px-3 text-xs font-bold border border-line text-ink-2 hover:text-ink hover:border-ink transition-colors |
32px tall, 12px text | Active: border-primary text-primary |
| Empty state icon circle | w-16 h-16 rounded-full bg-muted flex items-center justify-center text-3xl mb-4 |
64×64px, 30px icon | |
| Empty state heading | font-serif text-xl font-bold text-ink mb-2 |
20px / 700 | |
| Empty state sub-text | text-sm text-ink-2 max-w-xs text-center leading-relaxed mb-6 |
14px | |
| Recent person chip | inline-flex items-center gap-2 px-3 py-1.5 border border-line bg-surface text-sm font-semibold text-ink hover:border-primary transition-colors |
h ~32px, 14px text | Avatar: w-5 h-5 rounded-full text-[10px] |
restrictToCorrespondentsOf — only actual correspondents shown. "Alle Korrespondenten" row is the explicit opt-out. Log shows immediately (no blank screen), hint bar explains scope.documents.lengthdir param between ASC ↔ DESCsenderId and receiverId are setdocuments array: filter(d => d.sender?.id === senderId).length| Element | Tailwind classes | Real size | Notes |
|---|---|---|---|
| Log container | border border-line rounded-sm overflow-hidden bg-surface |
White card wrapping year bands + rows | |
| Year band (.LOG-YEAR) | flex items-baseline gap-3 px-4 py-2 bg-muted border-b border-line border-t border-t-line-2 |
h ~40px, py 8px, px 16px | First year band: omit border-t |
| Year number | text-2xl font-bold text-ink leading-none |
24px / 700 | This is the most commonly undersized element — 24px minimum |
| Year letter count | text-xs text-ink-3 font-medium |
12px | "5 Briefe" — always visible next to year |
| Log row (.LOG-ROW) | flex items-start gap-3 px-4 py-3 border-b border-line last:border-b-0 hover:bg-muted transition-colors cursor-pointer min-h-[44px] border-l-2 |
min 44px tall, py 12px, px 16px | Sent: border-l-primary. Received: border-l-accent |
| Direction arrow | text-sm font-black shrink-0 pt-0.5 w-4 text-center |
14px / 900, 16px wide | Sent: text-primary "→". Received: text-[#0F5755] "←" |
| Row body | flex-1 min-w-0 |
Flex column inside: title + meta | |
| Document title | text-sm font-semibold text-ink leading-snug truncate |
14px / 600 | Single line, truncate with ellipsis on overflow |
| Meta line (date · sender · status) | text-xs text-ink-2 mt-0.5 flex items-center gap-1.5 |
12px | Separator: text-line. Status dot: w-2 h-2 rounded-full shrink-0 |
| Row action chevron | shrink-0 w-6 h-6 flex items-center justify-center border border-line bg-muted text-ink-3 opacity-0 group-hover:opacity-100 transition-opacity |
24×24px | Add group to LOG-ROW; chevron fades in on hover |
| Asymmetry bar container | px-4 sm:px-6 py-2 bg-canvas border-b border-line |
py 8px | Only rendered when both senderId and receiverId are set |
| Asymmetry bar track | h-1.5 rounded-full bg-line overflow-hidden flex mt-1 |
6px tall | Navy fill: bg-primary. Mint fill: bg-accent |
| Single-person hint bar | px-4 sm:px-6 py-2 bg-amber-50 border-b border-amber-200 text-xs font-medium text-amber-800 flex items-center gap-2 |
h ~36px, 12px text | Amber warning tone. Only when senderId set but no receiverId. |
p-8 card with a two-row stripborder-bottom: 1px solid #EAE7E0, bg-whitebg-surface (#F7F5F2), border-bottom: 1.5px solid #E0DDD6opacity-40 pointer-events-none when no person setrestrictToCorrespondentsOf results when field focused + person A setdir via ontoggleSort — keep existing handlerdocuments.length passed as propLOG container, LOG-YEAR bands, LOG-ROW cardsisOut = doc.sender?.id === senderId → navy border + "→" arrowsenderId && receiverIddata-testid="conv-summary" but move count to Row 2 of filter stripcanWrite new-document link — move to bottom of log listdoc.location is setdoc.status to dot colour (5 states){#if !senderId || !receiverId} block replaced with empty-state component + single-person mode supportsenderId set, call GET /api/documents filtered by sender (or extend /api/documents/conversation to allow null receiver)localStorage, resolve names on mountsenderId && !receiverIdm.conv_heading() → update i18n key value to "Korrespondenz"+layout.svelte nav link text keypage.svelte.spec.ts: update selectors for new log markup, add single-person mode tests