Files
familienarchiv/docs/specs/document-topbar-final-spec.html
2026-04-14 23:21:15 +02:00

731 lines
70 KiB
HTML
Raw Permalink 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.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DocumentTopBar — Final Implementation Spec</title>
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Helvetica Neue',Arial,sans-serif;background:#ECEAE4;color:#1A1A1A;line-height:1.5}
.page{max-width:1360px;margin:0 auto;padding:48px 32px}
.mh{padding-bottom:24px;border-bottom:3px solid #012851;margin-bottom:32px}
.mh h1{font-size:22px;font-weight:900;color:#012851;letter-spacing:-.4px}
.mh p{font-size:12.5px;color:#555;max-width:680px;line-height:1.7;margin-top:6px}
.mh .byline{font-size:9px;color:#AAA;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;margin-top:8px}
.sh{margin:56px 0 28px;padding-bottom:12px;border-bottom:2px solid #E0DDD6}
.sh h2{font-size:16px;font-weight:900;color:#012851}
.sh p{font-size:12px;color:#666;margin-top:4px;max-width:700px;line-height:1.6}
.grid{display:flex;gap:20px;flex-wrap:wrap;margin-bottom:32px;align-items:flex-start}
.col{display:flex;flex-direction:column;gap:6px}
.lbl{font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:1.2px;color:#888;display:flex;align-items:center;gap:5px}
.tag{background:#E4E0DA;color:#666;padding:1px 5px;border-radius:2px;font-size:7px;font-weight:700}
.cap{font-size:9.5px;color:#999;font-style:italic;line-height:1.55;max-width:460px}
.chrome{background:#F0EFE9;border:1.5px solid #C4C0BA;border-radius:7px;overflow:hidden;box-shadow:0 3px 14px rgba(0,0,0,.09)}
.chrome.dark{background:#060C12;border-color:#0A1520}
.bar{height:20px;background:#E0DDD6;border-bottom:1px solid #C4C0BA;display:flex;align-items:center;padding:0 7px;gap:3px}
.chrome.dark .bar{background:#0A1218;border-bottom-color:#0A1520}
.dot{width:5px;height:5px;border-radius:50%;background:#BDB8B1}
.chrome.dark .dot{background:#1A2A3A}
.url{flex:1;height:8px;background:#CCC8C2;border-radius:5px;margin-left:4px}
.chrome.dark .url{background:#1A2A3A}
.nav{height:32px;background:#012851;display:flex;align-items:center;padding:0 12px;gap:8px;flex-shrink:0}
.nav.dark{background:#060C12}
.nav-logo{font-size:7px;font-weight:900;color:#fff;letter-spacing:.8px;border-bottom:2px solid #A1DCD8;padding-bottom:1px}
.nav-link{font-size:5.5px;color:rgba(255,255,255,.4);font-weight:700;text-transform:uppercase}
.nav-r{margin-left:auto;display:flex;gap:5px;align-items:center}
.nav-av{width:16px;height:16px;background:rgba(255,255,255,.1);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:5px;font-weight:800;color:rgba(255,255,255,.5)}
.pdf{background:#D4D0C8;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.pdf.dark{background:#08121C}
.paper{background:#FFFEF8;width:55%;box-shadow:0 2px 8px rgba(0,0,0,.14);border-radius:1px;padding:9px 11px;display:flex;flex-direction:column;gap:2px}
.paper.dark{background:#0D1820}
.pl{height:3px;background:#C4BDB0;border-radius:1px;opacity:.5;margin-bottom:2px}
.ps{height:2px;background:#C4BDB0;border-radius:1px;opacity:.28;margin-bottom:1.5px}
.paper.dark .pl{background:#1E2D3D}
.paper.dark .ps{background:#162230}
.chip{display:inline-flex;align-items:center;gap:2px;padding:2px 6px 2px 3px;background:#F0EFE9;border:1px solid #DDD9D0;border-radius:10px;white-space:nowrap;flex-shrink:0}
.chip.dk{background:#0A1218;border-color:#1E2D3D}
.av{border-radius:50%;background:#012851;display:flex;align-items:center;justify-content:center;font-weight:800;color:#A1DCD8;flex-shrink:0}
.av.purple{background:#5A3080;color:#fff}
.av.teal{background:#007596;color:#fff}
.av.moss{background:#2A6040;color:#fff}
.av.rust{background:#803020;color:#fff}
.cn{font-weight:600;color:#333;white-space:nowrap}
.cn.dk{color:#8AAABB}
.ov{display:inline-flex;align-items:center;padding:2px 6px;background:#E8E4DC;border:1px solid #DDD9D0;border-radius:10px;font-weight:700;color:#666;white-space:nowrap;flex-shrink:0}
.ov.dk{background:#0A1218;border-color:#1E2D3D;color:#4E6070}
.arr{color:#C4C0B8;flex-shrink:0}
.arr.dk{color:#1E2D3D}
.btn-p{height:26px;padding:0 10px;background:#012851;color:#A1DCD8;font-size:6.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;border-radius:3px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap;flex-shrink:0}
.btn-p.dk{background:#A1DCD8;color:#012851}
.btn-g{height:26px;padding:0 9px;border:1.5px solid #C8C4BE;color:#444;font-size:6.5px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;border-radius:3px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap;flex-shrink:0}
.btn-g.dk{border-color:#1E2D3D;color:#6080A0}
.btn-g.on{background:#012851;border-color:#012851;color:#A1DCD8}
.btn-g.on.dk{background:#A1DCD8;border-color:#A1DCD8;color:#012851}
.ico{width:26px;height:26px;border:1.5px solid #C8C4BE;border-radius:3px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#888}
.ico.dk{border-color:#1E2D3D;color:#4E6070}
.dv{width:1px;background:#E4E2D8;flex-shrink:0}
.dv.dk{background:#1E2D3D}
.dl::before{content:'';display:block;width:2px;height:5px;background:currentColor;margin:0 auto}
.dl{width:9px;height:6px;border-bottom:2px solid currentColor;border-left:2px solid transparent;border-right:2px solid transparent}
.hint{height:18px;background:rgba(1,40,81,.05);border-top:1px dashed rgba(1,40,81,.12);display:flex;align-items:center;padding:0 14px;gap:8px}
.hint.dk{background:rgba(161,220,216,.04);border-top-color:rgba(161,220,216,.1)}
.hint-lbl{font-size:5.5px;font-weight:800;color:#012851;text-transform:uppercase;letter-spacing:.5px}
.hint-lbl.dk{color:#A1DCD8}
.hint-txt{font-size:5.5px;color:#888}
.st-up{display:inline-flex;align-items:center;gap:2px;padding:1px 5px;border-radius:3px;font-size:5.5px;font-weight:800;text-transform:uppercase;letter-spacing:.4px;background:#D1FAE5;border:1px solid #6EE7B7;color:#065F46;flex-shrink:0}
.st-up.dk{background:rgba(209,250,229,.07);color:#6EE7B7;border-color:rgba(110,231,183,.2)}
.st-dot{width:4px;height:4px;border-radius:50%;background:#10B981}
hr{border:none;border-top:2px dashed #C8C4BE;margin:60px 0}
.rules{background:#fff;border:1px solid #E0DDD6;border-radius:6px;overflow:hidden;margin-top:28px}
.rules table{width:100%;border-collapse:collapse}
.rules th{background:#F4F2EC;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;color:#888;padding:8px 12px;text-align:left;border-bottom:1px solid #E0DDD6}
.rules td{font-size:11px;color:#444;padding:8px 12px;border-bottom:1px solid #F0EEE8;vertical-align:top;line-height:1.55}
.rules tr:last-child td{border-bottom:none}
.rules td:first-child{font-size:9px;font-weight:700;color:#012851;white-space:nowrap;width:110px}
.rules td code{font-size:9px;background:#F0EFE9;padding:1px 4px;border-radius:2px;color:#555}
/* ── spec-disclaimer ── */
.spec-disclaimer{background:#FFF8E1;border:1.5px solid #FFC107;border-radius:6px;padding:11px 16px;font-size:11px;color:#6D4C00;margin-bottom:32px;line-height:1.6}
.spec-disclaimer strong{font-weight:800}
/* ── impl-ref ── */
.impl-ref{background:#0d1117;border-radius:8px;margin-top:20px;overflow:hidden;border:1px solid #30363d}
.impl-ref-hdr{background:#161b22;padding:9px 16px;font-size:9.5px;font-weight:800;color:#f0883e;border-bottom:1px solid #30363d;display:flex;align-items:center;gap:8px;letter-spacing:.4px;text-transform:uppercase}
.impl-ref-hdr::before{content:'⚙';font-size:12px}
.impl-ref-hdr span{color:rgba(240,136,62,.55);font-weight:400;margin-left:auto;font-size:9px;text-transform:none;letter-spacing:0}
.impl-ref table{width:100%;border-collapse:collapse;font-size:10px}
.impl-ref th{text-align:left;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;color:#8b949e;padding:8px 14px;border-bottom:1px solid #21262d}
.impl-ref td{padding:6px 14px;border-bottom:1px solid #161b22;vertical-align:top;line-height:1.6;color:#c9d1d9}
.impl-ref tr:last-child td{border-bottom:none}
.impl-ref td:first-child{color:#79c0ff;font-weight:700;white-space:nowrap;width:200px}
.impl-ref td code{font-family:'SFMono-Regular',Consolas,monospace;font-size:9.5px;background:#161b22;color:#a5d6ff;padding:1px 5px;border-radius:3px;white-space:nowrap}
.impl-ref .ir-px{color:#7ee787;font-family:monospace;font-size:9.5px}
.impl-ref .ir-warn{color:#f0883e;font-style:italic}
</style>
</head>
<body>
<div class="page">
<div class="mh">
<h1>DocumentTopBar — Final Implementation Spec</h1>
<p>Authoritative implementation reference for the responsive DocumentTopBar component. Incorporates all resolutions from the issue #161 team review (Felix Brandt, Markus Keller, Sara Holt, Nora Steiner, Tobias Wendt, Leonie Voss). Supersedes <code>document-topbar-b1-responsive.html</code> — refer to that file for additional visual mockup detail.</p>
<div class="byline">Familienarchiv · 2026-03-31 · Leonie Voss, UX Lead — Final spec after review</div>
</div>
<div class="spec-disclaimer">
<strong>📐 Mockup scale notice —</strong> all font-size, height, and padding values in the mockup CSS below are scaled to ~55% of actual implementation values.
<strong>Do not copy sizes from mockup CSS.</strong> Use the ⚙ Implementation Reference tables after each section. Mockup CSS is for visual preview only.
<br><strong>⚠ This spec overrides the B1 spec</strong> — font sizes, heights, status chip, overflow pill, and touch targets have all changed. Key corrections: title min <code>text-[11px]</code>, chip names <code>text-[9px]</code>, topbar heights <code>h-12/h-14</code>, status chip dot-only, edit button icon-only on mobile.
</div>
<!-- ══════════════════════════════════════════
SECTION 0 — COMPONENT ARCHITECTURE
══════════════════════════════════════════ -->
<div class="sh">
<h2>0 · Component architecture</h2>
<p>Decompose into these components. Never merge into a single monolith — each has a clear single visual responsibility and must be independently testable.</p>
</div>
<div class="rules">
<table>
<thead><tr><th>Component file</th><th>Props</th><th>Responsibility</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>DocumentTopBar.svelte</td><td><code>doc, canWrite, canAnnotate, fileUrl, annotateMode (bindable)</code></td><td>Orchestrator. Owns <code>overflowOpen: $state(false)</code>. Passes props down. Contains back link, title, action buttons.</td><td>Parent layout must wrap in <code>&lt;header&gt;</code>. No direct DOM measurement.</td></tr>
<tr><td>PersonChipRow.svelte</td><td><code>sender, receivers, abbreviated: boolean</code></td><td>Chip row with arrow. Visible at ≥375px. Hidden at XS via <code>hidden xs:flex</code>.</td><td>Renders plain-text fallback slot at XS via parent.</td></tr>
<tr><td>PersonChip.svelte</td><td><code>person, abbreviated: boolean</code></td><td>Single chip: avatar initials + name. Abbreviated = first initial + last name.</td><td>Avatar colour from <code>personAvatarColor(person.id)</code>.</td></tr>
<tr><td>OverflowPill.svelte</td><td><code>extraCount, persons (for tooltip), open (bindable)</code></td><td>At ≥768px: interactive <code>&lt;button&gt;</code> with tooltip. At &lt;768px: <code>&lt;span aria-hidden="true"&gt;</code> — non-interactive.</td><td><code>aria-haspopup="listbox"</code>, <code>aria-expanded</code>, <code>aria-label</code>. See tooltip rules.</td></tr>
<tr><td>DocumentStatusChip.svelte</td><td><code>status: DocumentStatus</code></td><td>Dot-only indicator. Hidden below 768px. <code>title</code> + <code>aria-label</code> carry the label text.</td><td>No text label — removes i18n requirement.</td></tr>
<tr><td>AnnotateHintStrip.svelte</td><td><code>annotateMode: boolean</code></td><td>18px strip below main row. Only rendered when <code>annotateMode === true</code> AND viewport ≥768px.</td><td>Use <code>{#if annotateMode}</code> — no CSS height animation. Hidden via parent responsive class.</td></tr>
</tbody>
</table>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Svelte state &amp; derived values <span>Svelte 5 runes</span></div>
<table>
<thead><tr><th>Value</th><th>Type</th><th>Implementation</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>overflowOpen</td><td><code>$state(false)</code></td><td><code>let overflowOpen = $state(false)</code></td><td>In DocumentTopBar. Passed as bindable to OverflowPill.</td></tr>
<tr><td>visibleReceivers</td><td><code>$derived</code></td><td><code>$derived(doc.receivers.slice(0, viewportGe768 ? 2 : 1))</code></td><td>CSS-only: at &lt;768px always 1 shown. At ≥768px show 2 if count==2, else 1. Use CSS to hide — no JS.</td></tr>
<tr><td>extraCount</td><td><code>$derived</code></td><td><code>$derived(doc.receivers.length - visibleReceivers.length)</code></td><td>0 = no pill needed.</td></tr>
<tr><td>formattedDate</td><td><code>$derived</code></td><td>See utility module — <code>formatDate(doc.documentDate, format)</code></td><td>Format switches via CSS responsive classes, not JS viewport check.</td></tr>
<tr><td>xsMetaLine</td><td><code>$derived</code></td><td><code>$derived(formatXsMeta(doc))</code></td><td>Used only at XS. Import from <code>$lib/utils/personFormat</code>.</td></tr>
<tr><td>annotateMode</td><td>bindable prop</td><td><code>let { annotateMode = $bindable(false) } = $props()</code></td><td>Parent page owns state. TopBar toggles it.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 1 — DESIGN TOKENS
══════════════════════════════════════════ -->
<div class="sh"><h2>1 · Design tokens</h2><p>All CSS custom properties used by the topbar. No hardcoded colours in any component — all must reference these tokens.</p></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:20px">
<div style="background:#fff;border:1px solid #E0DDD6;border-radius:6px;overflow:hidden">
<div style="background:#F4F2EC;padding:8px 14px;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;color:#888;border-bottom:1px solid #E0DDD6">Light theme</div>
<table style="width:100%;border-collapse:collapse;font-size:11px">
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700;width:160px">bg-surface</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#fff;border:1px solid #DDD;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#FFFFFF — topbar bg</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">border-line</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#E4E2D8;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#E4E2D8 — bottom border, dividers, chip borders</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">bg-primary</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#012851;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#012851 — accent bar (light), primary btn, avatars</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">text-primary-fg</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#A1DCD8;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#A1DCD8 — text on navy bg</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">text-ink</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#1A1A1A;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#1A1A1A — title, chip names</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">text-ink-2</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#AAA;border:1px solid #EEE;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#AAAAAA — date, meta (spec ink-3 mapped here)</td></tr>
<tr style="border-bottom:1px solid #F0EEE8"><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">bg-muted</td><td style="padding:6px 14px"><span style="display:inline-block;width:12px;height:12px;background:#F0EFE9;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#F0EFE9 — chip bg, back btn bg at XS</td></tr>
<tr><td style="padding:6px 14px;color:#888;font-size:9px;font-weight:700">Accent bar</td><td style="padding:6px 14px"><code style="font-size:9px;background:#F0EFE9;padding:1px 4px;border-radius:2px">border-l-[3px] border-primary</code> — always present, all breakpoints</td></tr>
</table>
</div>
<div style="background:#0F1923;border:1px solid #1E2D3D;border-radius:6px;overflow:hidden">
<div style="background:#0A1218;padding:8px 14px;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;color:#4E6070;border-bottom:1px solid #1E2D3D">Dark theme</div>
<table style="width:100%;border-collapse:collapse;font-size:11px">
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700;width:160px">bg-surface</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#0F1923;border:1px solid #1E2D3D;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#0F1923</td></tr>
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">border-line</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#1E2D3D;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#1E2D3D</td></tr>
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">Accent bar (dark)</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#A1DCD8;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#A1DCD8 — teal replaces navy for accent bar</td></tr>
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">text-ink</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#EAE8E2;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#EAE8E2 — title</td></tr>
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">text-ink-2 (meta)</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#3E5065;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#3E5065 — date, meta</td></tr>
<tr style="border-bottom:1px solid #1A2830"><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">Chip bg</td><td style="padding:6px 14px;color:#8AAABB"><span style="display:inline-block;width:12px;height:12px;background:#0A1218;border:1px solid #1E2D3D;border-radius:2px;vertical-align:middle;margin-right:6px"></span>#0A1218 · border #1E2D3D</td></tr>
<tr><td style="padding:6px 14px;color:#4E6070;font-size:9px;font-weight:700">Primary btn (dark)</td><td style="padding:6px 14px;color:#8AAABB">bg #A1DCD8 · text #012851 — inverted</td></tr>
</table>
</div>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Design Tokens <span>Real values · CSS custom properties</span></div>
<table>
<thead><tr><th>Token / concern</th><th>Tailwind class</th><th>CSS var</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Accent bar</td><td><code>border-l-[3px] border-primary</code></td><td><code>var(--color-primary)</code></td><td>Light: #012851. Dark: resolves to #A1DCD8 via theme. Never hardcode.</td></tr>
<tr><td>Topbar bg</td><td><code>bg-surface</code></td><td><code>var(--color-surface)</code></td><td>Auto light/dark via CSS custom property.</td></tr>
<tr><td>Bottom border</td><td><code>border-b border-line</code></td><td><code>var(--color-line)</code></td><td>1px, both themes.</td></tr>
<tr><td>Chip bg</td><td><code>bg-muted</code></td><td><code>var(--color-muted)</code></td><td>Light #F0EFE9, dark #0A1218.</td></tr>
<tr><td>Chip border</td><td><code>border-line</code></td><td></td><td>Same token as bottom border.</td></tr>
<tr><td>Hint strip bg (light)</td><td><code>bg-[rgba(1,40,81,0.05)]</code></td><td></td><td class="ir-warn">⚠ --color-primary must be RGB format (1 40 81) for bg-primary/5 to work. If hex, use explicit rgba fallback.</td></tr>
<tr><td>Hint strip bg (dark)</td><td><code>dark:bg-[rgba(161,220,216,0.04)]</code></td><td></td><td>Use explicit rgba. Verify --color-primary-fg is also RGB.</td></tr>
<tr><td>Avatar palette</td><td>inline style only</td><td></td><td>5 values: <code>['#012851','#5A3080','#007596','#2A6040','#803020']</code>. Index = <code>hash(id) % 5</code>.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 2 — OVERFLOW PATTERNS (visual)
══════════════════════════════════════════ -->
<div class="sh"><h2>2 · Receiver overflow patterns</h2><p>Rule: always show sender + 1st receiver, collapse remaining. At &lt;768px: max 1 receiver shown, overflow pill is a non-interactive span. At ≥768px: show 2 receivers if count==2 (no pill); show 1 + pill if count≥3.</p></div>
<div style="background:#fff;border:1.5px solid #E0DDD6;border-radius:6px;overflow:hidden;margin-bottom:20px">
<div style="background:#F4F2EC;border-bottom:1px solid #E0DDD6;padding:7px 14px;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;color:#012851">Light theme — all receiver counts</div>
<div style="padding:16px 14px;display:flex;flex-direction:column;gap:14px">
<div style="display:flex;align-items:center;gap:10px">
<div style="font-size:8px;font-weight:700;color:#AAA;text-transform:uppercase;letter-spacing:.5px;width:90px;flex-shrink:0">0 receivers</div>
<div style="display:flex;align-items:center;gap:5px;padding:6px 10px;background:#FAFAF8;border:1px dashed #E0DDD6;border-radius:4px">
<div class="chip"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
</div>
<div style="font-size:9.5px;color:#999;font-style:italic">Sender only. No arrow. Diary entries, certificates.</div>
</div>
<div style="display:flex;align-items:center;gap:10px">
<div style="font-size:8px;font-weight:700;color:#AAA;text-transform:uppercase;letter-spacing:.5px;width:90px;flex-shrink:0">1 receiver</div>
<div style="display:flex;align-items:center;gap:5px;padding:6px 10px;background:#FAFAF8;border:1px dashed #E0DDD6;border-radius:4px">
<div class="chip"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr" style="font-size:9px"></span>
<div class="chip"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
</div>
<div style="font-size:9.5px;color:#999;font-style:italic">Both shown. No pill.</div>
</div>
<div style="display:flex;align-items:center;gap:10px">
<div style="font-size:8px;font-weight:700;color:#AAA;text-transform:uppercase;letter-spacing:.5px;width:90px;flex-shrink:0">2 receivers</div>
<div style="display:flex;align-items:center;gap:5px;padding:6px 10px;background:#FAFAF8;border:1px dashed #E0DDD6;border-radius:4px">
<div class="chip"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr" style="font-size:9px"></span>
<div class="chip"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
<span style="font-size:8px;color:#DDD">·</span>
<div class="chip"><div class="av teal" style="width:14px;height:14px;font-size:5px">HR</div><div class="cn" style="font-size:6.5px">Hans Raddatz</div></div>
</div>
<div style="font-size:9.5px;color:#999;font-style:italic">≥768px only: both shown, no pill. At &lt;768px: collapse to 1st + "+1" span.</div>
</div>
<div style="display:flex;align-items:center;gap:10px">
<div style="font-size:8px;font-weight:700;color:#AAA;text-transform:uppercase;letter-spacing:.5px;width:90px;flex-shrink:0">3 receivers</div>
<div style="display:flex;align-items:center;gap:5px;padding:6px 10px;background:#FAFAF8;border:1px dashed #E0DDD6;border-radius:4px">
<div class="chip"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr" style="font-size:9px"></span>
<div class="chip"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
<div class="ov" style="font-size:6.5px">+2 weitere</div>
</div>
<div style="font-size:9.5px;color:#999;font-style:italic">≥768px: "+2 weitere" interactive button. &lt;768px: "+2" non-interactive span, aria-hidden.</div>
</div>
<div style="display:flex;align-items:center;gap:10px">
<div style="font-size:8px;font-weight:700;color:#AAA;text-transform:uppercase;letter-spacing:.5px;width:90px;flex-shrink:0">No sender</div>
<div style="display:flex;align-items:center;gap:5px;padding:6px 10px;background:#FAFAF8;border:1px dashed #E0DDD6;border-radius:4px">
<div class="chip"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
</div>
<div style="font-size:9.5px;color:#999;font-style:italic">First available person shown. No arrow. Photos, undated documents.</div>
</div>
</div>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Chip &amp; Overflow Logic <span>Real values · mockup above is ~55% scale</span></div>
<table>
<thead><tr><th>Element</th><th>Tailwind classes</th><th>Real size</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>PersonChip container</td><td><code>inline-flex items-center gap-1 rounded-full border border-line bg-muted px-2 py-1 whitespace-nowrap shrink-0</code></td><td><span class="ir-px">h ~28px, px 8px, py 4px</span></td><td>Not interactive — no hover/focus styles needed.</td></tr>
<tr><td>Avatar circle</td><td><code>flex w-[18px] h-[18px] shrink-0 items-center justify-center rounded-full text-[7px] font-bold</code></td><td><span class="ir-px">18×18px</span></td><td>bg from <code>personAvatarColor(id)</code> — inline style. text-primary-fg for navy bg, white for others.</td></tr>
<tr><td>Chip name (full)</td><td><code>text-[9px] font-semibold text-ink</code></td><td><span class="ir-px">9px / 600</span></td><td class="ir-warn">⚠ Most commonly undersized — minimum 9px. Original spec said 6.5px — corrected.</td></tr>
<tr><td>Chip name (abbreviated)</td><td><code>text-[9px] font-semibold text-ink</code></td><td><span class="ir-px">9px / 600</span></td><td>"K. Raddatz" format at &lt;768px. Same styling as full name.</td></tr>
<tr><td>Arrow between chips</td><td><code>text-ink-2 shrink-0 text-[11px]</code> aria-hidden="true"</td><td><span class="ir-px">11px</span></td><td>Unicode → (U+2192). aria-hidden always present.</td></tr>
<tr><td>Overflow pill (≥768px)</td><td><code>inline-flex items-center rounded-full border border-line bg-muted px-2 py-1 text-[9px] font-bold text-ink-2 whitespace-nowrap shrink-0 min-h-[44px] md:min-h-0</code></td><td><span class="ir-px">9px / 700</span></td><td>Interactive button at ≥768px. Active state: <code>bg-primary border-primary text-primary-fg</code>.</td></tr>
<tr><td>Overflow pill (&lt;768px)</td><td><code>inline-flex items-center rounded-full border border-line bg-muted px-2 py-1 text-[9px] font-bold text-ink-2 whitespace-nowrap shrink-0</code></td><td><span class="ir-px">9px / 700</span></td><td><code>&lt;span aria-hidden="true"&gt;</code> — not a button. No tap behaviour.</td></tr>
<tr><td>PersonChipRow wrapper</td><td><code>hidden xs:flex items-center gap-1.5 min-w-0 overflow-hidden</code></td><td></td><td>Hidden at XS (<375px). flex at 375px.</td></tr>
<tr><td>XS plain-text meta</td><td><code>block xs:hidden text-[9px] text-ink-2 truncate mt-0.5</code></td><td><span class="ir-px">9px</span></td><td>Format: "K.Raddatz → E.Raddatz +4 · 24.12.1943". From <code>formatXsMeta(doc)</code>.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 3 — VIEWPORT MOCKUPS
══════════════════════════════════════════ -->
<div class="sh"><h2>3 · Viewport-by-viewport</h2><p>Visual reference for each breakpoint. See <a href="document-topbar-b1-responsive.html" style="color:#012851">B1 spec</a> for full set. Key states shown below.</p></div>
<!-- 320px -->
<div style="margin-bottom:10px;font-size:11px;font-weight:700;color:#012851;border-left:3px solid #012851;padding-left:10px">320 px · XS Mobile</div>
<div class="grid">
<div class="col">
<div class="lbl"><span class="tag">320px</span>Light</div>
<div class="chrome" style="width:200px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav"><div class="nav-logo">FA</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#fff;border-bottom:1.5px solid #E4E2D8;border-left:3px solid #012851">
<div style="display:flex;align-items:center;padding:0 9px;height:26px;gap:7px">
<div style="width:24px;height:24px;border-radius:3px;background:#F0EFE9;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:5px;height:5px;border-left:1.5px solid #666;border-bottom:1.5px solid #666;transform:rotate(45deg);margin-left:1px"></div></div>
<div style="flex:1;min-width:0">
<div style="font-size:10px;font-weight:800;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Brief a. Großmutter</div>
<div style="font-size:5.5px;color:#AAA;margin-top:1px">K.Raddatz → E.Raddatz · 24.12.1943</div>
</div>
<div style="width:14px;height:14px;border:1px solid #C8C4BE;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:6px;height:6px;border-left:1.5px solid #888;border-bottom:1.5px solid #888;position:relative"><div style="position:absolute;width:1.5px;height:5px;background:#888;top:-4px;left:1.5px"></div></div></div>
</div>
</div>
<div class="pdf" style="height:120px"><div class="paper" style="height:95px;width:80%"><div class="pl" style="width:65%"></div><div class="ps"></div><div class="ps" style="width:88%"></div><div class="ps" style="width:70%"></div></div></div>
</div>
<div class="cap">XS: square back btn, plain-text meta below title, icon-only edit button. No chips, no annotate, no download.</div>
</div>
<div class="col">
<div class="lbl"><span class="tag">320px</span>Dark</div>
<div class="chrome dark" style="width:200px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav dark"><div class="nav-logo">FA</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#0F1923;border-bottom:1.5px solid #1E2D3D;border-left:3px solid #A1DCD8">
<div style="display:flex;align-items:center;padding:0 9px;height:26px;gap:7px">
<div style="width:24px;height:24px;border-radius:3px;background:#0A1218;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:5px;height:5px;border-left:1.5px solid #4E6070;border-bottom:1.5px solid #4E6070;transform:rotate(45deg);margin-left:1px"></div></div>
<div style="flex:1;min-width:0">
<div style="font-size:10px;font-weight:800;color:#EAE8E2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Brief a. Großmutter</div>
<div style="font-size:5.5px;color:#3E5065;margin-top:1px">K.Raddatz → E.Raddatz · 24.12.1943</div>
</div>
<div style="width:14px;height:14px;border:1px solid #1E2D3D;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#4E6070"><div style="width:6px;height:6px;border-left:1.5px solid currentColor;border-bottom:1.5px solid currentColor;position:relative"><div style="position:absolute;width:1.5px;height:5px;background:currentColor;top:-4px;left:1.5px"></div></div></div>
</div>
</div>
<div class="pdf dark" style="height:120px"><div class="paper dark" style="height:95px;width:80%"><div class="pl"></div><div class="ps"></div><div class="ps" style="width:88%"></div></div></div>
</div>
<div class="cap">Dark XS: teal accent bar, icon-only edit, dark chip-less meta.</div>
</div>
</div>
<!-- 375px -->
<div style="margin:24px 0 10px;font-size:11px;font-weight:700;color:#012851;border-left:3px solid #012851;padding-left:10px">375 px · Standard Mobile</div>
<div class="grid">
<div class="col">
<div class="lbl"><span class="tag">375px</span>Light · 1 receiver</div>
<div class="chrome" style="width:230px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav"><div class="nav-logo">FA</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#fff;border-bottom:1.5px solid #E4E2D8;border-left:3px solid #012851">
<div style="display:flex;align-items:center;padding:0 10px;height:30px;gap:8px">
<div style="width:26px;height:26px;border-radius:50%;border:1.5px solid #E0DDD6;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:5px;height:5px;border-left:1.5px solid #666;border-bottom:1.5px solid #666;transform:rotate(45deg);margin-left:1px"></div></div>
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:2px">
<div style="font-size:10.5px;font-weight:800;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Brief a. Großmutter, 1943</div>
<div style="display:flex;align-items:center;gap:3px">
<div class="chip" style="padding:1.5px 5px 1.5px 2px;gap:2px"><div class="av" style="width:12px;height:12px;font-size:4.5px">KR</div><div class="cn" style="font-size:6px">K. Raddatz</div></div>
<span class="arr" style="font-size:8px"></span>
<div class="chip" style="padding:1.5px 5px 1.5px 2px;gap:2px"><div class="av purple" style="width:12px;height:12px;font-size:4.5px">ER</div><div class="cn" style="font-size:6px">E. Raddatz</div></div>
</div>
</div>
<div style="width:14px;height:14px;border:1px solid #C8C4BE;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#888"><div style="width:6px;height:6px;border-left:1.5px solid currentColor;border-bottom:1.5px solid currentColor;position:relative"><div style="position:absolute;width:1.5px;height:5px;background:currentColor;top:-4px;left:1.5px"></div></div></div>
</div>
</div>
<div class="pdf" style="height:130px"><div class="paper" style="height:103px;width:78%"><div class="pl" style="width:65%"></div><div class="ps"></div><div class="ps" style="width:88%"></div><div class="ps" style="width:70%"></div></div></div>
</div>
<div class="cap">375px: circle back btn, chip row with abbreviated names, icon-only edit. Annotate hidden.</div>
</div>
<div class="col">
<div class="lbl"><span class="tag">375px</span>Light · 3+ receivers</div>
<div class="chrome" style="width:230px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav"><div class="nav-logo">FA</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#fff;border-bottom:1.5px solid #E4E2D8;border-left:3px solid #012851">
<div style="display:flex;align-items:center;padding:0 10px;height:30px;gap:8px">
<div style="width:26px;height:26px;border-radius:50%;border:1.5px solid #E0DDD6;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:5px;height:5px;border-left:1.5px solid #666;border-bottom:1.5px solid #666;transform:rotate(45deg);margin-left:1px"></div></div>
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:2px">
<div style="font-size:10.5px;font-weight:800;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Rundbrief, 1951</div>
<div style="display:flex;align-items:center;gap:3px">
<div class="chip" style="padding:1.5px 5px 1.5px 2px;gap:2px"><div class="av" style="width:12px;height:12px;font-size:4.5px">KR</div><div class="cn" style="font-size:6px">K. Raddatz</div></div>
<span class="arr" style="font-size:8px"></span>
<div class="chip" style="padding:1.5px 5px 1.5px 2px;gap:2px"><div class="av purple" style="width:12px;height:12px;font-size:4.5px">ER</div><div class="cn" style="font-size:6px">E. Raddatz</div></div>
<div class="ov" style="font-size:6px;padding:1.5px 5px">+2</div>
</div>
</div>
<div style="width:14px;height:14px;border:1px solid #C8C4BE;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#888"><div style="width:6px;height:6px;border-left:1.5px solid currentColor;border-bottom:1.5px solid currentColor;position:relative"><div style="position:absolute;width:1.5px;height:5px;background:currentColor;top:-4px;left:1.5px"></div></div></div>
</div>
</div>
<div class="pdf" style="height:130px"><div class="paper" style="height:103px;width:78%"><div class="pl" style="width:65%"></div><div class="ps"></div></div></div>
</div>
<div class="cap">375px overflow: "+2" is a non-interactive &lt;span aria-hidden&gt;. No "weitere" — no tooltip on mobile.</div>
</div>
</div>
<!-- 768px Tablet -->
<div style="margin:24px 0 10px;font-size:11px;font-weight:700;color:#012851;border-left:3px solid #012851;padding-left:10px">768 px · Tablet</div>
<div class="grid">
<div class="col">
<div class="lbl"><span class="tag">768px</span>Light · 1 receiver</div>
<div class="chrome" style="width:420px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav"><div class="nav-logo">FAMILIENARCHIV</div><div class="nav-link">Dokumente</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#fff;border-bottom:1.5px solid #E4E2D8;border-left:3px solid #012851;display:flex;align-items:center;padding:0 12px;height:30px;gap:10px">
<div style="width:28px;height:28px;border-radius:50%;border:1.5px solid #E0DDD6;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:6px;height:6px;border-left:1.5px solid #666;border-bottom:1.5px solid #666;transform:rotate(45deg);margin-left:2px"></div></div>
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:3px">
<div style="display:flex;align-items:center;gap:5px">
<div style="font-size:11.5px;font-weight:800;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Brief an Großmutter, Weihnachten 1943</div>
<div class="st-dot" style="width:6px;height:6px;flex-shrink:0" title="Hochgeladen"></div>
</div>
<div style="display:flex;align-items:center;gap:4px">
<div style="font-size:6.5px;color:#AAA">24.12.1943</div>
<span style="font-size:8px;color:#DDD">·</span>
<div class="chip" style="padding:2px 6px 2px 3px"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr" style="font-size:9px"></span>
<div class="chip" style="padding:2px 6px 2px 3px"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
</div>
</div>
<div style="display:flex;align-items:center;gap:4px;flex-shrink:0">
<div class="btn-g" style="display:inline-flex;align-items:center;gap:3px"><div style="width:7px;height:7px;border:1.5px solid #888;border-radius:50%"></div>Annotieren</div>
<div class="btn-p" style="display:inline-flex;align-items:center;gap:3px"><div style="width:6px;height:6px;border-left:1.5px solid #A1DCD8;border-bottom:1.5px solid #A1DCD8;position:relative"><div style="position:absolute;width:1.5px;height:5px;background:#A1DCD8;top:-4px;left:1.5px"></div></div>Bearbeiten</div>
<div class="dv" style="height:16px"></div>
<div class="ico"><div class="dl" style="color:#888"></div></div>
</div>
</div>
<div class="pdf" style="height:150px"><div class="paper" style="height:118px"><div class="pl" style="width:65%"></div><div class="ps"></div><div class="ps" style="width:88%"></div><div class="ps" style="width:72%"></div></div></div>
</div>
<div class="cap">768px: full names, dot-only status indicator, Annotate + Bearbeiten + download icon. Status dot replaces text chip.</div>
</div>
<div class="col">
<div class="lbl"><span class="tag">768px</span>Dark · annotate active</div>
<div class="chrome dark" style="width:380px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav dark"><div class="nav-logo">FAMILIENARCHIV</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#0F1923;border-bottom:1.5px solid #1E2D3D;border-left:3px solid #A1DCD8">
<div style="display:flex;align-items:center;padding:0 12px;height:30px;gap:10px">
<div style="width:28px;height:28px;border-radius:50%;border:1.5px solid #1E2D3D;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:6px;height:6px;border-left:1.5px solid #4E6070;border-bottom:1.5px solid #4E6070;transform:rotate(45deg);margin-left:2px"></div></div>
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:3px">
<div style="font-size:11.5px;font-weight:800;color:#EAE8E2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Brief an Großmutter</div>
<div style="display:flex;align-items:center;gap:4px">
<div class="chip dk" style="padding:2px 6px 2px 3px"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn dk" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr dk" style="font-size:9px"></span>
<div class="chip dk" style="padding:2px 6px 2px 3px"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn dk" style="font-size:6.5px">Elfriede Raddatz</div></div>
</div>
</div>
<div class="btn-g on dk" style="display:inline-flex;align-items:center;gap:3px"><div style="width:7px;height:7px;border:1.5px solid #012851;border-radius:50%"></div>Beenden</div>
</div>
<div class="hint dk"><div class="hint-lbl dk">Annotierungsmodus aktiv</div><div class="hint-txt">Klicken Sie auf eine Textstelle.</div></div>
</div>
<div class="pdf dark" style="height:142px"><div class="paper dark" style="height:112px;outline:2px solid rgba(161,220,216,.15)"><div class="pl"></div><div class="ps"></div><div class="ps" style="width:88%"></div></div></div>
</div>
<div class="cap">Annotate active: Edit + Download removed. "Beenden" fills teal. Hint strip visible. PDF outline teal at 15%.</div>
</div>
</div>
<!-- 1024px -->
<div style="margin:24px 0 10px;font-size:11px;font-weight:700;color:#012851;border-left:3px solid #012851;padding-left:10px">1024 px · Laptop / 1440 px · Desktop</div>
<div class="grid">
<div class="col">
<div class="lbl"><span class="tag">1024px</span>Light · 5 receivers (overflow open)</div>
<div class="chrome" style="width:560px">
<div class="bar"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="url"></div></div>
<div class="nav"><div class="nav-logo">FAMILIENARCHIV</div><div class="nav-link">Dokumente</div><div class="nav-link">Personen</div><div class="nav-r"><div class="nav-av">KL</div></div></div>
<div style="background:#fff;border-bottom:1.5px solid #E4E2D8;border-left:3px solid #012851;display:flex;align-items:center;padding:0 14px;height:30px;gap:10px;position:relative">
<div style="width:28px;height:28px;border-radius:50%;border:1.5px solid #E0DDD6;display:flex;align-items:center;justify-content:center;flex-shrink:0"><div style="width:6px;height:6px;border-left:1.5px solid #666;border-bottom:1.5px solid #666;transform:rotate(45deg);margin-left:2px"></div></div>
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:3px">
<div style="display:flex;align-items:center;gap:6px">
<div style="font-size:12px;font-weight:800;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Georgia,serif">Rundbrief an die Familie, Sommer 1951</div>
<div class="st-dot" style="width:6px;height:6px;flex-shrink:0" title="Archiviert"></div>
</div>
<div style="display:flex;align-items:center;gap:5px;position:relative">
<div style="font-size:6.5px;color:#AAA">18.07.1951 · Berlin</div>
<span style="font-size:8px;color:#DDD">·</span>
<div class="chip"><div class="av" style="width:14px;height:14px;font-size:5px">KR</div><div class="cn" style="font-size:6.5px">Karl Raddatz</div></div>
<span class="arr" style="font-size:9px"></span>
<div class="chip"><div class="av purple" style="width:14px;height:14px;font-size:5px">ER</div><div class="cn" style="font-size:6.5px">Elfriede Raddatz</div></div>
<div style="display:inline-flex;align-items:center;padding:2px 6px;background:#012851;border:1px solid #012851;border-radius:10px;font-size:6.5px;font-weight:700;color:#A1DCD8;position:relative">
+4 weitere
<div style="position:absolute;top:18px;left:0;background:#fff;border:1.5px solid #E0DDD6;border-radius:5px;padding:10px 12px;min-width:155px;z-index:10;box-shadow:0 4px 16px rgba(0,0,0,.12)">
<div style="font-size:7px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:.6px;margin-bottom:7px;border-bottom:1px solid #F0EEE8;padding-bottom:5px">Weitere Empfänger</div>
<div style="display:flex;align-items:center;gap:6px;margin-bottom:5px"><div class="av teal" style="width:16px;height:16px;font-size:5.5px">HR</div><div style="font-size:9.5px;color:#333;font-weight:500">Hans Raddatz</div></div>
<div style="display:flex;align-items:center;gap:6px;margin-bottom:5px"><div class="av moss" style="width:16px;height:16px;font-size:5.5px">MR</div><div style="font-size:9.5px;color:#333;font-weight:500">Maria Raddatz</div></div>
<div style="display:flex;align-items:center;gap:6px"><div class="av rust" style="width:16px;height:16px;font-size:5.5px">GR</div><div style="font-size:9.5px;color:#333;font-weight:500">Gerhard Raddatz</div></div>
</div>
</div>
</div>
</div>
<div style="display:flex;align-items:center;gap:5px;flex-shrink:0">
<div class="btn-g" style="display:inline-flex;align-items:center;gap:3px"><div style="width:7px;height:7px;border:1.5px solid #888;border-radius:50%"></div>Annotieren</div>
<div class="btn-p">Bearbeiten</div>
<div class="dv" style="height:16px"></div>
<div class="ico"><div class="dl" style="color:#888"></div></div>
</div>
</div>
<div class="pdf" style="height:155px"><div class="paper" style="height:122px"><div class="pl" style="width:65%"></div><div class="ps"></div><div class="ps" style="width:88%"></div></div></div>
</div>
<div class="cap">Active overflow pill fills navy. Tooltip drops below: "Weitere Empfänger" + avatar + name link per person.</div>
</div>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Topbar Layout per Breakpoint <span>Real values · mockup above is ~55% scale</span></div>
<table>
<thead><tr><th>Element</th><th>XS &lt;375px</th><th>Mobile 375767px</th><th>Tablet/Desktop ≥768px</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Topbar height</td><td><code>h-12</code> <span class="ir-px">48px</span></td><td><code>h-14</code> <span class="ir-px">56px</span></td><td><code>h-14</code> <span class="ir-px">56px</span></td><td class="ir-warn">⚠ Increased from B1 spec (was 44/50/52px) to fit text-[11px]+ chip row.</td></tr>
<tr><td>Back button wrapper</td><td colspan="3"><code>a href="/documents" w-11 h-11 -ml-2 flex items-center justify-center shrink-0 focus-visible:ring-2</code></td><td><code>w-11 h-11</code> = 44×44px touch area. -ml-2 = visual alignment. aria-label="Zurück zur Dokumentenliste" always.</td></tr>
<tr><td>Back button visual</td><td><code>w-6 h-6 rounded-sm bg-muted flex items-center justify-center</code></td><td><code>w-6 h-6 rounded-full border border-line flex items-center justify-center</code></td><td><code>w-7 h-7 rounded-full border border-line flex items-center justify-center</code></td><td>Shape changes at xs breakpoint. Inner chevron SVG 10×10px.</td></tr>
<tr><td>Title</td><td><code>font-serif font-extrabold text-[11px] text-ink truncate</code></td><td><code>font-serif font-extrabold text-[11px] text-ink truncate</code></td><td><code>font-serif font-extrabold text-[12px] lg:text-[13px] text-ink truncate</code></td><td class="ir-warn">⚠ Minimum 11px — original spec said 10px, corrected.</td></tr>
<tr><td>Status indicator</td><td>Hidden <code>hidden</code></td><td>Hidden <code>hidden</code></td><td><code>hidden md:block w-2.5 h-2.5 rounded-full shrink-0</code></td><td>Dot only. title + aria-label carry label. See statusDotClass() for colours.</td></tr>
<tr><td>Date text</td><td>In xsMetaLine string</td><td><code>text-xs text-ink-2 shrink-0</code> format: "24.12.1943"</td><td><code>text-xs text-ink-2 shrink-0</code> format: ≥1024px long ("24. Dezember 1943")</td><td>Date format switches via Tailwind: <code>&lt;span class="lg:hidden"&gt;24.12.1943&lt;/span&gt;&lt;span class="hidden lg:inline"&gt;{longDate}&lt;/span&gt;</code></td></tr>
<tr><td>Location in meta</td><td>Hidden</td><td>Hidden</td><td>Shown if doc.location present at ≥768px: <code>hidden md:inline</code></td><td>// TODO: show location when doc.location field available on DTO</td></tr>
<tr><td>Edit button (XS/mobile)</td><td colspan="2"><code>inline-flex items-center justify-center w-11 h-11 -mr-2 shrink-0</code> with pencil SVG 18×18px. aria-label="Bearbeiten".</td><td></td><td class="ir-warn">⚠ Icon-only on mobile. "Bearbeiten" text hidden below 768px.</td></tr>
<tr><td>Edit button (tablet+)</td><td></td><td></td><td><code>hidden md:inline-flex h-10 items-center gap-2 px-4 bg-primary text-primary-fg text-[11px] font-bold uppercase tracking-wide rounded-sm</code></td><td>Shows pencil icon + "Bearbeiten" label at ≥768px.</td></tr>
<tr><td>Annotate button</td><td>Hidden <code>hidden</code></td><td>Hidden <code>hidden</code></td><td><code>hidden md:inline-flex h-10 items-center gap-2 px-3 border border-line text-ink-2 text-[11px] font-bold uppercase tracking-wide rounded-sm</code></td><td>Active: <code>bg-primary border-primary text-primary-fg</code>. Label "Annotieren" → "Beenden". aria-pressed={annotateMode}.</td></tr>
<tr><td>Download button</td><td>Hidden</td><td>Hidden</td><td><code>hidden md:inline-flex w-10 h-10 items-center justify-center border border-line rounded-sm text-ink-2</code></td><td>Icon only — download SVG 18×18px.</td></tr>
<tr><td>Divider</td><td>Hidden</td><td>Hidden</td><td><code>hidden md:block w-px h-4 bg-line shrink-0</code></td><td>Between download icon and Bearbeiten button.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 4 — RESPONSIVE RULES TABLE (updated)
══════════════════════════════════════════ -->
<div class="sh"><h2>4 · Responsive rules (authoritative)</h2><p>All heights and font sizes updated from resolved review. These values override the B1 spec.</p></div>
<div class="rules">
<table>
<thead><tr><th>Element</th><th>≤ 374px (XS)</th><th>375767px (mobile)</th><th>7681023px (tablet)</th><th>≥ 1024px (desktop)</th></tr></thead>
<tbody>
<tr><td>Topbar height</td><td>h-12 (48px)</td><td>h-14 (56px)</td><td>h-14 (56px)</td><td>h-14 (56px)</td></tr>
<tr><td>Back button</td><td>Square 24×24 <code>rounded-sm bg-muted</code></td><td>Circle 24×24 <code>rounded-full border-line</code></td><td>Circle 28×28 <code>rounded-full border-line</code></td><td>Circle 28×28</td></tr>
<tr><td>Touch target</td><td colspan="4"><code>w-11 h-11 -ml-2</code> wrapper around all back button variants. Always 44×44px.</td></tr>
<tr><td>Title size</td><td>text-[11px] / 800</td><td>text-[11px] / 800</td><td>text-[12px] / 800</td><td>text-[13px] / 800</td></tr>
<tr><td>Chip row</td><td>Hidden → plain-text xsMetaLine</td><td>Shown — abbreviated names</td><td>Shown — full names</td><td>Shown — full names + location</td></tr>
<tr><td>Chip name text</td><td>N/A</td><td>text-[9px] / 600</td><td>text-[9px] / 600</td><td>text-[9px] / 600</td></tr>
<tr><td>Date format</td><td><code>dd.mm.yyyy</code> in xsMetaLine</td><td><code>24.12.1943</code></td><td><code>24.12.1943</code></td><td><code>24. Dezember 1943</code></td></tr>
<tr><td>Status indicator</td><td>Hidden</td><td>Hidden</td><td>Dot only — <code>w-2.5 h-2.5 rounded-full</code></td><td>Dot only</td></tr>
<tr><td>Annotate button</td><td>Hidden</td><td>Hidden</td><td>Shown — "Annotieren"</td><td>Shown — "Annotieren"</td></tr>
<tr><td>Edit button</td><td>Icon only (pencil SVG)</td><td>Icon only</td><td>Icon + "Bearbeiten"</td><td>Icon + "Bearbeiten"</td></tr>
<tr><td>Download button</td><td>Hidden</td><td>Hidden</td><td>Icon only</td><td>Icon only</td></tr>
<tr><td>Overflow pill</td><td>N/A (chips hidden)</td><td><code>&lt;span aria-hidden&gt;</code> "+N"</td><td><code>&lt;button&gt;</code> "+N weitere" → tooltip</td><td><code>&lt;button&gt;</code> "+N weitere" → tooltip</td></tr>
<tr><td>Hint strip</td><td>Hidden</td><td>Hidden</td><td>18px strip when annotateMode</td><td>18px strip when annotateMode</td></tr>
</tbody>
</table>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Tailwind breakpoint setup <span>tailwind.config.ts</span></div>
<table>
<thead><tr><th>Item</th><th>Value</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Custom xs breakpoint</td><td><code>xs: '375px'</code> in <code>theme.extend.screens</code></td><td class="ir-warn">⚠ Tailwind 4 may use different config syntax — verify before using <code>xs:</code> prefix classes. Without this, <code>xs:flex</code> silently does nothing.</td></tr>
<tr><td>Usage for chip row</td><td><code>hidden xs:flex</code></td><td>Hidden at &lt;375px, flex at ≥375px.</td></tr>
<tr><td>Usage for XS meta</td><td><code>block xs:hidden</code></td><td>Only visible below 375px.</td></tr>
<tr><td>Usage for overflow pill type</td><td>CSS only: <code>hidden xs:inline-flex</code> for button, always-rendered span for mobile with <code>md:hidden</code></td><td>Prefer CSS over JS viewport check — no SSR issues.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 5 — OVERFLOW TOOLTIP
══════════════════════════════════════════ -->
<div class="sh"><h2>5 · Overflow tooltip</h2><p>Clicking "+N weitere" opens a floating panel. Only at ≥768px. Mobile overflow pill is a non-interactive span.</p></div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — OverflowPill component <span>Real values · Svelte 5</span></div>
<table>
<thead><tr><th>Element</th><th>Tailwind classes</th><th>Real size</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Pill (interactive ≥768px)</td><td><code>inline-flex items-center rounded-full border border-line bg-muted px-2 py-1 text-[9px] font-bold text-ink-2 whitespace-nowrap shrink-0 cursor-pointer</code></td><td><span class="ir-px">h ~28px, 9px text</span></td><td>Active state: <code>bg-primary border-primary text-primary-fg</code>. aria-haspopup="listbox" aria-expanded={open} aria-label="{count} weitere Empfänger".</td></tr>
<tr><td>Pill (non-interactive &lt;768px)</td><td>same visual classes as above on <code>&lt;span aria-hidden="true"&gt;</code></td><td></td><td>No button, no onclick, no tooltip. Users access full receiver list via document edit page.</td></tr>
<tr><td>Tooltip panel</td><td><code>absolute top-full left-0 mt-1 bg-surface border border-line rounded-md shadow-lg p-3 min-w-[160px] z-50</code></td><td><span class="ir-px">min 160px wide, p 12px</span></td><td>position:relative on chip row container. role="listbox".</td></tr>
<tr><td>Tooltip header</td><td><code>text-[9px] font-bold uppercase tracking-wide text-ink-2 border-b border-line pb-2 mb-2</code></td><td><span class="ir-px">9px / 700</span></td><td>Text: "Weitere Empfänger".</td></tr>
<tr><td>Person row</td><td><code>flex items-center gap-2 py-1 rounded hover:bg-muted</code></td><td><span class="ir-px">min 32px tall</span></td><td>role="option". Each row is an &lt;a href="/persons/{id}"&gt;. Avatar 16×16px.</td></tr>
<tr><td>Person name in tooltip</td><td><code>text-[11px] font-medium text-ink</code></td><td><span class="ir-px">11px / 500</span></td><td>Full name always shown in tooltip.</td></tr>
<tr><td>Keyboard: open</td><td></td><td></td><td>Enter/Space on pill → open tooltip → focus first role="option".</td></tr>
<tr><td>Keyboard: navigate</td><td></td><td></td><td>Tab/Shift+Tab between options inside tooltip.</td></tr>
<tr><td>Keyboard: close</td><td></td><td></td><td>Escape → close + return focus to pill. Click-outside → close. Second click on pill → close.</td></tr>
<tr><td>Click-outside</td><td></td><td></td><td>Use <code>use:clickOutside</code> Svelte action — do not use document.addEventListener directly in $effect.</td></tr>
</tbody>
</table>
</div>
<div class="impl-ref">
<div class="impl-ref-hdr">Implementation Reference — Annotate hint strip <span>AnnotateHintStrip.svelte</span></div>
<table>
<thead><tr><th>Element</th><th>Tailwind classes</th><th>Real size</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Strip wrapper</td><td><code>hidden md:flex h-[18px] items-center gap-2 border-t border-dashed px-3.5</code></td><td><span class="ir-px">h 18px</span></td><td>Only rendered when annotateMode===true via Svelte {#if}. hidden below md.</td></tr>
<tr><td>Strip bg (light)</td><td><code>bg-[rgba(1,40,81,0.05)]</code></td><td></td><td class="ir-warn">⚠ Use explicit rgba — bg-primary/5 requires RGB --color-primary. Fallback if not converted.</td></tr>
<tr><td>Strip border (light)</td><td><code>border-[rgba(1,40,81,0.20)]</code></td><td></td><td>Same caveat — explicit rgba.</td></tr>
<tr><td>Strip bg (dark)</td><td><code>dark:bg-[rgba(161,220,216,0.04)]</code></td><td></td><td>Explicit rgba.</td></tr>
<tr><td>Label text</td><td><code>text-[9px] font-bold uppercase tracking-wide text-primary</code></td><td><span class="ir-px">9px / 700</span></td><td class="ir-warn">⚠ Corrected from spec's 5.5px — minimum 9px. Dark: text-primary-fg.</td></tr>
<tr><td>Body text</td><td><code>text-[9px] text-ink-2</code></td><td><span class="ir-px">9px</span></td><td>"Klicken Sie auf eine Textstelle im Dokument, um eine Anmerkung hinzuzufügen."</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 6 — UTILITY FUNCTIONS
══════════════════════════════════════════ -->
<div class="sh"><h2>6 · Utility functions — <code>src/lib/utils/personFormat.ts</code></h2><p>Pure functions. Write Vitest unit tests for each before implementing. No DOM, no side effects.</p></div>
<div class="rules">
<table>
<thead><tr><th>Function</th><th>Signature</th><th>Behaviour &amp; edge cases</th></tr></thead>
<tbody>
<tr>
<td>abbreviateName</td>
<td><code>abbreviateName(person: Person): string</code></td>
<td>
"Karl Raddatz" → "K. Raddatz"<br>
"Elfriede" (single name) → "Elfriede" (no initial, return as-is)<br>
"Karl Müller-Schmidt" → "K. Müller-Schmidt" (preserve hyphenated last name)<br>
Split on first space only. First character of first word + ". " + rest.
</td>
</tr>
<tr>
<td>formatXsMeta</td>
<td><code>formatXsMeta(doc: Document): string</code></td>
<td>
0 receivers: "K.Raddatz · 24.12.1943"<br>
1 receiver: "K.Raddatz → E.Raddatz · 24.12.1943"<br>
3 receivers: "K.Raddatz → E.Raddatz +2 · 24.12.1943"<br>
No sender: "E.Raddatz · 24.12.1943"<br>
Abbreviated format: first initial + dot + last name, no space (e.g. "K.Raddatz").<br>
Date: <code>dd.mm.yyyy</code> format, no spaces.
</td>
</tr>
<tr>
<td>personAvatarColor</td>
<td><code>personAvatarColor(personId: string): string</code></td>
<td>
Returns one of: <code>['#012851','#5A3080','#007596','#2A6040','#803020']</code><br>
Must be deterministic: same ID always returns same colour.<br>
Implementation: <code>PALETTE[simpleHash(id) % PALETTE.length]</code><br>
<strong>simpleHash</strong>: sum of char codes, or djb2. Never interpolate the ID string into CSS directly.<br>
Test: 1000 random UUIDs → all map to valid palette entry.
</td>
</tr>
<tr>
<td>formatDate</td>
<td><code>formatDate(isoDate: string, format: 'short' | 'long'): string</code></td>
<td>
short: "24.12.1943" — use <code>Intl.DateTimeFormat('de-DE', {day:'2-digit', month:'2-digit', year:'numeric'})</code><br>
long: "24. Dezember 1943" — use <code>month: 'long'</code><br>
Always parse with <code>new Date(isoDate + 'T12:00:00')</code> to avoid UTC off-by-one.
</td>
</tr>
<tr>
<td>statusDotClass</td>
<td><code>statusDotClass(status: DocumentStatus): string</code></td>
<td>
PLACEHOLDER → <code>'bg-gray-400'</code><br>
UPLOADED → <code>'bg-emerald-500'</code><br>
TRANSCRIBED → <code>'bg-blue-400'</code><br>
REVIEWED → <code>'bg-amber-400'</code><br>
ARCHIVED → <code>'bg-emerald-600'</code>
</td>
</tr>
<tr>
<td>statusLabel (for title/aria)</td>
<td><code>statusLabel(status: DocumentStatus): string</code></td>
<td>
German labels (not shown as text, used in title + aria-label only):<br>
PLACEHOLDER → "Platzhalter" · UPLOADED → "Hochgeladen" · TRANSCRIBED → "Transkribiert"<br>
REVIEWED → "Geprüft" · ARCHIVED → "Archiviert"
</td>
</tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 7 — ACCESSIBILITY
══════════════════════════════════════════ -->
<div class="sh"><h2>7 · Accessibility requirements (WCAG 2.2 AA)</h2></div>
<div class="rules">
<table>
<thead><tr><th>Element</th><th>Requirement</th></tr></thead>
<tbody>
<tr><td>Landmark</td><td>Parent page must wrap topbar in <code>&lt;header role="banner"&gt;</code> or the topbar must itself be in <code>&lt;header&gt;</code>. Verify parent layout.</td></tr>
<tr><td>Back link</td><td><code>aria-label="Zurück zur Dokumentenliste"</code> always present — icon is the only visible element at XS.</td></tr>
<tr><td>Edit button (icon-only mobile)</td><td><code>aria-label="Bearbeiten"</code> always present, even at mobile where it renders icon-only.</td></tr>
<tr><td>Annotate button</td><td><code>aria-pressed={annotateMode}</code>. Label changes: "Annotieren" → "Beenden".</td></tr>
<tr><td>Overflow pill</td><td><code>aria-haspopup="listbox"</code> (not "true"), <code>aria-expanded={overflowOpen}</code>, <code>aria-label="{extraCount} weitere Empfänger anzeigen"</code>.</td></tr>
<tr><td>Overflow tooltip</td><td><code>role="listbox"</code> on panel. <code>role="option"</code> on each person row. Not a modal — no focus trap needed.</td></tr>
<tr><td>Tooltip focus flow</td><td>Opening tooltip moves focus to first <code>role="option"</code>. Tab/Shift+Tab navigates within. Escape closes + returns focus to pill.</td></tr>
<tr><td>Arrow between chips</td><td><code>aria-hidden="true"</code> on the → character. Directionality conveyed by order, not just the arrow.</td></tr>
<tr><td>Status dot</td><td><code>title={statusLabel(doc.status)}</code> for hover tooltip. <code>aria-label={statusLabel(doc.status)}</code>. No text label rendered.</td></tr>
<tr><td>Touch targets</td><td>Back button: 44×44px via wrapper. Edit (mobile): 44×44px via wrapper. Overflow pill: naturally ≥44px wide at ≥375px. All verified.</td></tr>
<tr><td>Focus rings</td><td>Never <code>outline:none</code> without a replacement. All interactive elements: <code>focus-visible:ring-2 focus-visible:ring-primary</code>.</td></tr>
<tr><td>Colour alone</td><td>Status uses colour + aria-label. Never colour as only signal. Annotate mode uses label change "Beenden" + visual fill + hint strip.</td></tr>
</tbody>
</table>
</div>
<!-- ══════════════════════════════════════════
SECTION 8 — ACCEPTANCE CRITERIA
══════════════════════════════════════════ -->
<div class="sh"><h2>8 · Acceptance criteria</h2></div>
<div class="rules">
<table>
<thead><tr><th>ID</th><th>Criterion</th></tr></thead>
<tbody>
<tr><td>AC-01</td><td>Topbar renders correctly at 320px, 375px, 768px, 1024px, 1440px — matches spec screenshots. Verified by /proofshot at all 5 widths.</td></tr>
<tr><td>AC-02</td><td>Light and dark themes match token table — no hardcoded hex values in any component file.</td></tr>
<tr><td>AC-03</td><td>0-receiver, 1-receiver, 2-receiver, 3-receiver, and 5-receiver cases all render correctly per Section 2.</td></tr>
<tr><td>AC-04</td><td>No-sender case: chip row shows receivers only (or first person if no sender), no arrow rendered.</td></tr>
<tr><td>AC-05</td><td>Overflow tooltip opens/closes on click, Enter/Space, Escape. Escape returns focus to pill. Click-outside closes.</td></tr>
<tr><td>AC-06</td><td>Opening tooltip moves focus to first person link inside tooltip.</td></tr>
<tr><td>AC-07</td><td>Overflow tooltip links navigate to correct /persons/{id} URL.</td></tr>
<tr><td>AC-08</td><td>Overflow pill at &lt;768px is a non-interactive span — no tooltip, no tap action.</td></tr>
<tr><td>AC-09</td><td>Annotate mode: Edit + Download hidden; hint strip visible; button label "Beenden"; aria-pressed=true.</td></tr>
<tr><td>AC-10</td><td>Annotate hint strip NOT rendered below 768px even when annotateMode===true.</td></tr>
<tr><td>AC-11</td><td>Status dot visible at ≥768px with correct colour per status. Hidden below.</td></tr>
<tr><td>AC-12</td><td>All touch targets ≥44×44px at mobile (back button, edit button, overflow pill where interactive).</td></tr>
<tr><td>AC-13</td><td>aria-pressed, aria-haspopup="listbox", aria-expanded, aria-label on all interactive elements.</td></tr>
<tr><td>AC-14</td><td>svelte-check passes with no new type errors.</td></tr>
<tr><td>AC-15</td><td>Unit tests pass for: abbreviateName (full, single, hyphenated), formatXsMeta (0/1/3+ receivers, no sender), personAvatarColor (deterministic, palette-only), statusDotClass (all 5 values), statusLabel (all 5 values), formatDate (short, long, UTC boundary).</td></tr>
<tr><td>AC-16</td><td>Visual proof: /proofshot against document detail page at all 5 viewport widths, both light and dark themes (10 screenshots).</td></tr>
</tbody>
</table>
</div>
<hr>
<div style="font-size:10px;color:#AAA;text-align:center;padding:16px 0">
DocumentTopBar Final Spec · Familienarchiv · 2026-03-31 · Leonie Voss<br>
Supersedes <code>document-topbar-b1-responsive.html</code> · All resolutions from issue #161 review incorporated
</div>
</div><!-- /page -->
</body>
</html>