Files
familienarchiv/docs/specs/dashboard-expansion-patterns.html
Marcel 78abc7f726 docs(#240): add Mission Control Strip spec and pattern alternatives
Adds the design decision record for how to expand the dashboard without
pushing content below the fold: a full-width 3-column strip (Segmentierung /
Transkription / Lesefertig) below the existing grid.

- dashboard-expansion-patterns.html — four pattern alternatives evaluated
  (Tabs, Accordion, Mission Control, Priority Queue) with annotated mockups,
  engagement feature proposal, and final recommendation.
- mission-control-strip-final.html — clean implementation blueprint with
  pipeline diagram, column definitions, seeded-weekly-shuffle sorting,
  expert-flag escape hatch, all Tailwind impl-ref values, and backend
  contracts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 10:42:07 +02:00

1123 lines
75 KiB
HTML
Raw 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>Dashboard Expansion — 4 Layout-Muster (Issue #240)</title>
<style>
:root{
--navy:#002850;--mint:#A6DAD8;--sand:#E4E2D7;
--surface:#FAFAF7;--bg:#E8E7E2;--border:#D8D7D0;
--text:#1C1C18;--muted:#6B6A63;--subtle:#9B9A93;
--orange:#C26A00;--orange-bg:#FEF4E2;
--green:#2E6E39;--green-bg:#EAF5EA;
--font:system-ui,sans-serif;--mono:'Courier New',monospace;
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
body{font-family:var(--font);background:var(--bg);color:var(--text);font-size:14px;line-height:1.6;}
.doc{max-width:1100px;margin:0 auto;padding:48px 32px 96px;}
/* Header */
.doc-header{background:var(--navy);color:#fff;padding:32px 32px 28px;border-radius:8px 8px 0 0;}
.doc-header h1{font-family:Georgia,serif;font-size:26px;font-weight:400;letter-spacing:-.02em;margin-bottom:8px;}
.badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:4px;font-size:10px;font-weight:600;letter-spacing:.05em;background:var(--mint);color:var(--navy);}
.badge-ghost{background:rgba(255,255,255,.15);color:rgba(255,255,255,.9);}
.badges{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px;}
.doc-meta{font-family:var(--mono);font-size:11px;color:rgba(255,255,255,.45);}
.intro-box{background:#fff;border:1px solid var(--border);border-top:none;border-radius:0 0 6px 6px;padding:20px 28px 24px;margin-bottom:40px;}
.intro-box h2{font-family:Georgia,serif;font-size:16px;font-weight:400;color:var(--navy);margin-bottom:8px;}
.prose{font-size:13px;color:var(--muted);line-height:1.65;max-width:720px;margin-bottom:12px;}
.prose:last-child{margin-bottom:0;}
/* Sections */
.section{margin-bottom:56px;}
.section-label{font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);padding-bottom:8px;border-bottom:1px solid var(--border);margin-bottom:24px;}
hr{border:none;border-top:1px solid var(--border);margin:48px 0;}
/* Pattern header */
.pattern-title{font-family:Georgia,serif;font-size:22px;font-weight:400;color:var(--navy);margin-bottom:4px;}
.pattern-sub{font-size:13px;color:var(--muted);margin-bottom:14px;}
.tag-list{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:16px;}
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:10px;font-weight:600;letter-spacing:.04em;}
.tag-pro{background:var(--green-bg);color:var(--green);}
.tag-con{background:var(--orange-bg);color:var(--orange);}
.tag-rec{background:var(--navy);color:#fff;}
/* Frames row */
.frames-row{display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start;margin-bottom:20px;}
.caption{font-family:var(--mono);font-size:10px;color:var(--muted);display:block;margin-top:6px;}
/* Desktop frame */
.frame-desktop{background:var(--surface);border-radius:8px;overflow:hidden;border:1px solid var(--border);box-shadow:0 4px 16px rgba(0,0,0,.08);}
.f-nav{height:26px;background:var(--navy);display:flex;align-items:center;padding:0 8px;gap:5px;}
.f-logo{font-size:6.5px;font-weight:700;color:#fff;letter-spacing:.7px;border-bottom:1px solid var(--mint);padding-bottom:1px;}
.f-navlinks{display:flex;gap:5px;margin-left:8px;}
.f-navlink{font-size:5.5px;color:rgba(255,255,255,.4);font-weight:600;text-transform:uppercase;}
.f-navlink.on{color:rgba(255,255,255,.9);}
.f-navr{margin-left:auto;display:flex;gap:4px;align-items:center;}
.f-av{width:14px;height:14px;border-radius:50%;background:rgba(255,255,255,.12);display:flex;align-items:center;justify-content:center;font-size:4.5px;font-weight:800;color:rgba(255,255,255,.5);}
.f-body{padding:10px;}
/* Search bar mock */
.f-search{background:#fff;border:1px solid var(--border);border-radius:4px;height:24px;display:flex;align-items:center;padding:0 8px;gap:5px;margin-bottom:5px;}
.f-search-icon{font-size:9px;color:var(--muted);}
.f-search-txt{font-size:7.5px;color:var(--subtle);flex:1;}
.f-chip-sm{font-size:6px;padding:1px 5px;border-radius:3px;border:1px solid var(--border);color:var(--muted);background:#fff;}
.f-chip-sm.on{background:var(--navy);color:#fff;border-color:var(--navy);}
/* Resume strip */
.f-resume{background:var(--mint);opacity:.2;height:7px;border-radius:3px;margin-bottom:8px;}
/* Grid */
.f-grid-2{display:grid;grid-template-columns:1fr 155px;gap:7px;}
.f-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px;}
/* Cards */
.f-card{background:#fff;border:1px solid var(--sand);border-radius:3px;padding:7px;}
.f-htitle{font-size:6px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:5px;}
.f-htitle.orange{color:var(--orange);}
.f-htitle.green{color:var(--green);}
.f-htitle.navy{color:var(--navy);}
.f-row{display:flex;align-items:flex-start;border-bottom:1px solid var(--sand);padding:3px 0;gap:3px;}
.f-row:last-of-type{border-bottom:none;}
.f-doc-name{font-family:Georgia,serif;font-size:7.5px;color:var(--navy);line-height:1.3;}
.f-doc-sub{font-size:6px;color:var(--muted);margin-top:1px;}
.f-doc-date{font-size:5.5px;color:var(--subtle);margin-left:auto;white-space:nowrap;flex-shrink:0;padding-top:1px;}
.f-dot{width:4px;height:4px;border-radius:50%;flex-shrink:0;margin-top:3px;}
.f-dot.orange{background:var(--orange);}
.f-dot.navy{background:var(--navy);}
.f-dot.green{background:var(--green);}
.f-link{font-size:6px;color:var(--navy);display:block;margin-top:5px;}
.f-link.green{color:var(--green);}
.f-stats{font-size:5.5px;color:var(--muted);margin-top:5px;}
/* DropZone */
.f-dz{border:1.5px dashed var(--mint);background:rgba(166,218,216,.07);border-radius:3px;padding:7px;text-align:center;}
.f-dz-icon{font-size:12px;color:var(--navy);opacity:.35;margin-bottom:2px;}
.f-dz-txt{font-size:6px;font-weight:700;color:var(--navy);}
.f-dz-sub{font-size:5px;color:var(--muted);}
/* Tabs */
.f-tabs{display:flex;border-bottom:1px solid var(--border);margin-bottom:5px;}
.f-tab{font-size:6.5px;padding:3px 5px;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;}
.f-tab.on{color:var(--navy);border-bottom-color:var(--navy);font-weight:600;}
/* Accordion */
.f-acc-item{border-bottom:1px solid var(--sand);}
.f-acc-item:last-child{border-bottom:none;}
.f-acc-head{display:flex;align-items:center;justify-content:space-between;padding:4px 0;}
.f-acc-label{font-size:6.5px;font-weight:600;color:var(--navy);}
.f-acc-label.orange{color:var(--orange);}
.f-acc-label.green{color:var(--green);}
.f-acc-body{padding-bottom:3px;}
/* Phone frame */
.frame-phone{width:200px;flex-shrink:0;background:var(--surface);border-radius:24px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.12),0 0 0 1px rgba(0,0,0,.06);display:flex;flex-direction:column;border:4px solid #1C1C18;}
.ph-nav{height:20px;background:var(--navy);display:flex;align-items:center;padding:0 6px;}
.ph-logo{font-size:5.5px;font-weight:700;color:#fff;letter-spacing:.6px;border-bottom:1px solid var(--mint);padding-bottom:1px;}
.ph-body{flex:1;overflow:hidden;padding:6px;display:flex;flex-direction:column;gap:4px;}
.ph-search{background:#fff;border:1px solid var(--border);border-radius:3px;height:18px;display:flex;align-items:center;padding:0 6px;gap:3px;}
.ph-search-txt{font-size:6.5px;color:var(--subtle);flex:1;}
/* Problem callout */
.problem-strip{border:1.5px dashed var(--orange);border-radius:3px;padding:5px 7px;background:var(--orange-bg);opacity:.7;margin-bottom:3px;}
.problem-txt{font-size:6px;color:var(--orange);font-weight:700;}
/* impl-ref */
.impl-ref{margin-top:20px;}
.impl-ref table{width:100%;border-collapse:collapse;font-size:12px;}
.impl-ref th{background:var(--navy);color:#fff;padding:6px 10px;text-align:left;font-size:10px;font-weight:600;letter-spacing:.06em;}
.impl-ref td{padding:7px 10px;border-bottom:1px solid var(--border);vertical-align:top;}
.impl-ref tr:nth-child(even) td{background:var(--surface);}
.impl-ref code{font-family:var(--mono);font-size:11px;background:rgba(0,40,80,.06);padding:1px 4px;border-radius:2px;}
.impl-ref .note{font-size:11px;color:var(--muted);}
/* Comparison table */
.cmp{width:100%;border-collapse:collapse;font-size:12px;margin-bottom:24px;}
.cmp th{background:var(--navy);color:#fff;padding:7px 10px;font-size:10px;font-weight:600;letter-spacing:.05em;text-align:left;}
.cmp td{padding:7px 10px;border-bottom:1px solid var(--border);vertical-align:top;}
.cmp tr:nth-child(even) td{background:var(--surface);}
.cmp .pass{color:var(--green);font-weight:600;}
.cmp .fail{color:var(--orange);font-weight:600;}
.cmp .warn{color:#8A6800;font-weight:600;}
.cmp td.best{background:rgba(0,40,80,.05) !important;}
/* Recommendation */
.rec{background:var(--navy);color:#fff;padding:24px 28px;border-radius:6px;margin-top:32px;}
.rec h3{font-family:Georgia,serif;font-size:20px;font-weight:400;margin-bottom:12px;}
.rec p{font-size:13px;line-height:1.65;color:rgba(255,255,255,.8);margin-bottom:8px;}
.rec ul{margin:8px 0 0 18px;}
.rec li{font-size:13px;color:rgba(255,255,255,.75);margin-bottom:6px;line-height:1.5;}
.rec strong{color:var(--mint);}
/* Right-column stack helper */
.rhs{display:flex;flex-direction:column;gap:6px;}
</style>
</head>
<body>
<div class="doc">
<!-- ── HEADER ───────────────────────────────────────────────────────── -->
<div class="doc-header">
<h1>Dashboard Expansion — 4 Layout-Muster</h1>
<div class="badges">
<span class="badge">Issue #240</span>
<span class="badge badge-ghost">Leonie Voss — UX &amp; Accessibility</span>
<span class="badge badge-ghost">15. April 2026</span>
</div>
<div class="doc-meta">src/routes/+page.svelte &nbsp;·&nbsp; src/lib/components/Dashboard*.svelte &nbsp;·&nbsp; Muster A Tabs · B Accordion · C Mission Control · D Priority Queue</div>
</div>
<div class="intro-box">
<h2>Das Problem</h2>
<p class="prose">
Die rechte Spalte der Startseite ist mit <strong>DropZone + „Metadaten fehlen"</strong> bereits ausgelastet.
Issue #240 möchte zwei weitere Karten ergänzen: <em>Transkription ausstehend</em> und <em>Lesefertig</em>.
Direkt gestapelt scrollt die Spalte sofort aus dem sichtbaren Bereich — ein 67-jähriger Nutzer auf einem kleinen
Display sieht die unteren Karten nie.
</p>
<p class="prose">
Der Nutzer schlug <strong>Tabs</strong> vor (Neueste Aktivität / Transkription fehlt / Metadaten fehlen / Lesefertig).
Diese Spec bewertet diesen Vorschlag und zeigt drei weitere Muster im Vergleich.
Alle Muster werden bei <strong>320 px (Mobiltelefon)</strong> und <strong>Desktop (~55 % Skalierung)</strong> gezeigt.
</p>
</div>
<!-- ── CURRENT STATE ─────────────────────────────────────────────────── -->
<div class="section">
<div class="section-label">Ist-Zustand — rechte Spalte überfüllt</div>
<div class="frames-row">
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div><div class="f-navlink">Gespräche</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div><div class="f-chip-sm">↑↓ Datum</div><div class="f-chip-sm">+ Filter</div></div>
<div class="f-resume"></div>
<div class="f-grid-2">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div><div class="f-doc-sub">Karl Raddatz</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div><div class="f-doc-sub">Standesamt</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div><div class="f-doc-sub">Martha Raddatz</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto Sommer 1952</div><div class="f-doc-sub">Unbekannt</div></div><div class="f-doc-date">3. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop oder klicken</div></div>
<div class="f-card">
<div class="f-htitle orange">Metadaten fehlen</div>
<div class="f-row"><div class="f-doc-name">Familienfoto 1952</div></div>
<div class="f-row"><div class="f-doc-name">Standesamtsurkunde</div></div>
<div class="f-row"><div class="f-doc-name">Reisepass Opa Heinrich</div></div>
<a class="f-link">Alle anzeigen →</a>
</div>
<div class="problem-strip"><div class="problem-txt">▼ TRANSKRIPTION FEHLT (neu) — scrollt aus dem Sichtfeld</div></div>
<div class="problem-strip"><div class="problem-txt">▼ LESEFERTIG (neu) — nie sichtbar ohne Scrollen</div></div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 % Skalierung) — zwei neue Karten würden die rechte Spalte sprengen</span>
</div>
</div>
</div>
<hr/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- PATTERN A: TABS -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-label">Muster A — Tabs in der rechten Spalte (Vorschlag des Nutzers)</div>
<div class="pattern-title">Aufgaben-Karte mit Tab-Strip</div>
<div class="pattern-sub">DropZone bleibt oben. Darunter: eine Karte mit drei Tabs (Metadaten / Transkription / Lesefertig).</div>
<div class="tag-list">
<span class="tag tag-pro">+ Kein zusätzlicher Scroll in der rechten Spalte</span>
<span class="tag tag-pro">+ Bekanntes Muster für jüngere Nutzer</span>
<span class="tag tag-pro">+ Platzsparend in 300 px</span>
<span class="tag tag-con"> Inaktive Kategorien unsichtbar — Senioren übersehen sie</span>
<span class="tag tag-con"> Drei kurze Labels kaum lesbar bei 300 px / 320 px</span>
<span class="tag tag-con"> JS-Zustand nötig (aktiver Tab)</span>
</div>
<p class="prose">
Der ursprüngliche Vorschlag nannte vier Tabs für die <em>gesamte Seite</em> (Neueste Aktivität / Transkription / Metadaten / Lesefertig).
Das ist ein UX-Antipattern: „Neueste Aktivität" ist der häufigste Anwendungsfall — ihn hinter einem Klick zu verstecken erhöht den Aufwand für jeden Dashboard-Besuch.
<strong>Tabs sollten ausschließlich auf die drei To-do-Widget-Kategorien in der rechten Spalte angewendet werden</strong>, nicht auf die gesamte Seite.
</p>
<p class="prose">
Accessibility: Tab-Elemente müssen <code>role="tablist"</code>, <code>role="tab"</code>, <code>aria-selected</code> und
<code>role="tabpanel"</code> tragen. Jeder Tab braucht <code>min-h-[44px]</code> (WCAG 2.2 Touchziel).
Drei Tabs in einer 300-px-Spalte = ~100 px pro Tab — grenzwertig auf Deutsch mit langen Wörtern.
</p>
<div class="frames-row">
<!-- Phone A -->
<div>
<div class="frame-phone">
<div class="ph-nav"><div class="ph-logo">FAMILIENARCHIV</div></div>
<div class="ph-body">
<div class="ph-search"><div class="ph-search-txt">⌕ Dokumente…</div></div>
<div class="f-dz" style="padding:5px;"><div class="f-dz-icon" style="font-size:10px;"></div><div class="f-dz-txt">Hochladen</div></div>
<!-- Tabbed card -->
<div class="f-card" style="padding:5px;">
<div class="f-tabs">
<div class="f-tab on">Metadaten</div>
<div class="f-tab">Transkr.</div>
<div class="f-tab">Lesefertig</div>
</div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Reisepass Opa</div><div class="f-doc-sub">Absender fehlt</div></div></div>
<a class="f-link">Alle anzeigen →</a>
</div>
<!-- Recent below -->
<div class="f-card" style="padding:5px;">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div class="f-doc-name">Brief von Oma Martha</div></div>
<div class="f-row"><div class="f-doc-name">Taufurkunde Karl R.</div></div>
<div class="f-stats">47 Dok. · 12 Pers.</div>
</div>
</div>
</div>
<span class="caption">Mobil 320 px</span>
</div>
<!-- Desktop A -->
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div></div>
<div class="f-resume"></div>
<div class="f-grid-2">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto Sommer 1952</div></div><div class="f-doc-date">3. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop</div></div>
<div class="f-card" style="flex:1;">
<div class="f-tabs">
<div class="f-tab on">Metadaten</div>
<div class="f-tab">Transkr.</div>
<div class="f-tab">Lesefertig</div>
</div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Reisepass Opa Heinrich</div><div class="f-doc-sub">Absender fehlt</div></div></div>
<a class="f-link">Alle anzeigen →</a>
</div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 %) — DropZone + Tabbed-Karte; zwei Kategorien versteckt hinter Klick</span>
</div>
</div>
<div class="impl-ref">
<table>
<thead><tr><th>Element</th><th>Tailwind-Klassen</th><th>Wert</th><th>Hinweis</th></tr></thead>
<tbody>
<tr><td>Tab-Strip</td><td><code>flex border-b border-line</code></td><td></td><td>ARIA: <code>role="tablist"</code></td></tr>
<tr><td>Tab inaktiv</td><td><code>px-3 py-3 text-xs font-medium text-gray-500 border-b-2 border-transparent whitespace-nowrap -mb-px</code></td><td>min-h 44 px ✓</td><td><code>role="tab" aria-selected="false"</code></td></tr>
<tr><td>Tab aktiv</td><td><code>px-3 py-3 text-xs font-semibold text-ink border-b-2 border-ink -mb-px</code></td><td>2 px navy Unterlinie</td><td><code>aria-selected="true"</code></td></tr>
<tr><td>Tab-Panel</td><td><code>pt-3 focus:outline-none</code></td><td></td><td><code>role="tabpanel" tabindex="0"</code></td></tr>
<tr><td>Aufgaben-Karte</td><td><code>rounded-sm border border-line bg-white p-4 flex-1</code></td><td>padding 16 px</td><td>Ersetzt 3 separate Karten</td></tr>
<tr><td>Zeile mit Kontext</td><td><code>flex flex-col py-2 border-b border-line last:border-0</code></td><td>min-h ~44 px</td><td>z. B. „3 von 8 Blöcken geprüft"</td></tr>
</tbody>
</table>
</div>
</div>
<hr/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- PATTERN B: ACCORDION -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-label">Muster B — Accordion-Stapel in der rechten Spalte</div>
<div class="pattern-title">Aufklappbare Kategorien</div>
<div class="pattern-sub">DropZone oben. Darunter: drei Accordion-Sektionen, standardmäßig nur die dringlichste offen.</div>
<div class="tag-list">
<span class="tag tag-pro">+ Alle drei Kategorien-Überschriften immer sichtbar</span>
<span class="tag tag-pro">+ Kein JS — implementierbar mit nativem <code>&lt;details&gt;</code></span>
<span class="tag tag-pro">+ Vertraut für 60+ (wie FAQ)</span>
<span class="tag tag-con"> Inhalt zu 2/3 verborgen (nur Überschriften sichtbar)</span>
<span class="tag tag-con"> „Lesefertig" wird meist zugeklappt bleiben und übersehen</span>
</div>
<p class="prose">
Jede Sektion zeigt eine klickbare Kopfzeile (Pfeil + Label + Anzahl). Server-seitig wird die Sektion mit der
höchsten Anzahl als <code>&lt;details open&gt;</code> gerendert. Kein Client-JS nötig — native
<code>&lt;details&gt;</code>/<code>&lt;summary&gt;</code>-Elemente liefern ARIA-Accessibility gratis.
Sortierung der offenen Sektion nach Dringlichkeit: Metadaten → Transkription → Lesefertig.
</p>
<div class="frames-row">
<!-- Phone B -->
<div>
<div class="frame-phone">
<div class="ph-nav"><div class="ph-logo">FAMILIENARCHIV</div></div>
<div class="ph-body">
<div class="ph-search"><div class="ph-search-txt">⌕ Dokumente…</div></div>
<div class="f-dz" style="padding:5px;"><div class="f-dz-icon" style="font-size:10px;"></div><div class="f-dz-txt">Hochladen</div></div>
<div class="f-card" style="padding:4px 6px;">
<div class="f-acc-item">
<div class="f-acc-head"><span class="f-acc-label orange">▼ Metadaten fehlen (5)</span></div>
<div class="f-acc-body">
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<a class="f-link">Alle 5 anzeigen →</a>
</div>
</div>
<div class="f-acc-item"><div class="f-acc-head"><span class="f-acc-label">▶ Transkription fehlt (8)</span></div></div>
<div class="f-acc-item"><div class="f-acc-head"><span class="f-acc-label green">▶ Lesefertig ✓ (3)</span></div></div>
</div>
<div class="f-card" style="padding:5px;">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div class="f-doc-name">Brief von Oma Martha</div></div>
<div class="f-row"><div class="f-doc-name">Taufurkunde Karl R.</div></div>
</div>
</div>
</div>
<span class="caption">Mobil 320 px</span>
</div>
<!-- Desktop B -->
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div></div>
<div class="f-resume"></div>
<div class="f-grid-2">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto Sommer 1952</div></div><div class="f-doc-date">3. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop</div></div>
<div class="f-card" style="flex:1;padding:4px 8px;">
<div class="f-acc-item">
<div class="f-acc-head"><span class="f-acc-label orange">▼ Metadaten fehlen (5)</span></div>
<div class="f-acc-body">
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<a class="f-link">Alle 5 anzeigen →</a>
</div>
</div>
<div class="f-acc-item"><div class="f-acc-head"><span class="f-acc-label">▶ Transkription fehlt (8)</span></div></div>
<div class="f-acc-item"><div class="f-acc-head"><span class="f-acc-label green">▶ Lesefertig ✓ (3)</span></div></div>
</div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 %) — Metadaten-Sektion offen, Transkription und Lesefertig zugeklappt</span>
</div>
</div>
<div class="impl-ref">
<table>
<thead><tr><th>Element</th><th>HTML / Tailwind-Klassen</th><th>Wert</th><th>Hinweis</th></tr></thead>
<tbody>
<tr><td>Accordion-Wrapper</td><td><code>&lt;details&gt;</code> nativ</td><td></td><td>Accessibility gratis, kein JS</td></tr>
<tr><td>Accordion-Header</td><td><code>&lt;summary class="flex items-center justify-between min-h-[44px] cursor-pointer list-none"&gt;</code></td><td>min-h 44 px ✓</td><td>WCAG 2.2 Touchziel</td></tr>
<tr><td>Pfeil-Icon</td><td><code>transition-transform group-open:rotate-90</code></td><td>w-4 h-4</td><td>CSS-only; kein JS</td></tr>
<tr><td>Zähler-Badge</td><td><code>ml-auto font-mono text-xs text-gray-400</code></td><td></td><td>z. B. „(5)"</td></tr>
<tr><td>Dringlichste Sektion</td><td><code>&lt;details open&gt;</code></td><td></td><td>Server-seitig rendern: <code>if incompleteDocs.length &gt;= needsTrans.length</code></td></tr>
<tr><td>Accordion-Inhalt</td><td><code>pt-1 pb-2</code> direkt nach <code>&lt;summary&gt;</code></td><td></td><td>Keine <code>overflow:hidden</code>-Animation nötig</td></tr>
</tbody>
</table>
</div>
</div>
<hr/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- PATTERN C: MISSION CONTROL — RECOMMENDATION -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-label">Muster C — Mission-Control-Streifen &nbsp;<span class="tag tag-rec">★ Empfohlen</span></div>
<div class="pattern-title">Volle Breite unterhalb des Hauptgitters</div>
<div class="pattern-sub">Rechte Spalte bleibt unverändert. Unterhalb des Gitters: drei gleichwertige Spalten als neuer horizontaler Aktionsbereich.</div>
<div class="tag-list">
<span class="tag tag-pro">+ Alle drei Kategorien gleichzeitig sichtbar — kein Klick nötig</span>
<span class="tag tag-pro">+ „Neueste Aktivität" bleibt primärer Inhalt, nichts rückt dahinter</span>
<span class="tag tag-pro">+ Kein JS-Zustand</span>
<span class="tag tag-pro">+ „Lesefertig" bekommt eigene mint-Karte als visuellen Applaus</span>
<span class="tag tag-pro">+ Mobil stapeln die drei Spalten natürlich</span>
<span class="tag tag-con"> Leichtes Scrollen auf Desktop erforderlich</span>
<span class="tag tag-con"> Sechster API-Aufruf beim Dashboard-Load (via <code>Promise.allSettled</code> isoliert)</span>
</div>
<p class="prose">
Der Ist-Zustand der rechten Spalte bleibt vollständig erhalten. Die zwei neuen Karten des Issue #240 werden
<em>nicht</em> in die rechte Spalte gepackt, sondern in einen neuen vollbreiten Abschnitt direkt unterhalb des
bestehenden Zwei-Spalten-Gitters. Der Abschnitt ist nur sichtbar, wenn mindestens eine der beiden Kategorien
Einträge hat (<code>{#if needsTranscription.length &gt; 0 || readyToRead.length &gt; 0}</code>).
</p>
<p class="prose">
Die „Lesefertig"-Spalte erhält einen mint-gefärbten Hintergrund (<code>bg-mint/10 border-mint</code>) als positives Signal — kein
neutrales To-do, sondern eine Einladung zum Lesen. Leere Zustände zeigen eine kurze Erfolgsmeldung in
<code>bg-mint/5</code>, nicht eine tote weiße Box.
</p>
<div class="frames-row">
<!-- Phone C -->
<div>
<div class="frame-phone" style="height:580px;">
<div class="ph-nav"><div class="ph-logo">FAMILIENARCHIV</div></div>
<div class="ph-body" style="overflow-y:auto;">
<div class="ph-search"><div class="ph-search-txt">⌕ Dokumente…</div></div>
<!-- Right col first on mobile (lg:order-last) -->
<div class="f-dz" style="padding:5px;"><div class="f-dz-icon" style="font-size:10px;"></div><div class="f-dz-txt">Hochladen</div></div>
<div class="f-card" style="padding:5px;">
<div class="f-htitle orange">Metadaten fehlen</div>
<div class="f-row"><div class="f-doc-name">Familienfoto 1952</div></div>
<div class="f-row"><div class="f-doc-name">Standesamtsurkunde</div></div>
<a class="f-link">Alle anzeigen →</a>
</div>
<!-- Left col (recent docs) -->
<div class="f-card" style="padding:5px;">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div class="f-doc-name">Brief von Oma Martha</div></div>
<div class="f-row"><div class="f-doc-name">Taufurkunde Karl R.</div></div>
<div class="f-stats">47 Dok. · 12 Pers.</div>
</div>
<!-- Mission control strip — stacks on mobile -->
<div style="background:#fff;border:1px solid var(--sand);border-radius:3px;padding:6px;">
<div class="f-htitle" style="margin-bottom:6px;">Was braucht Aufmerksamkeit?</div>
<div class="f-card" style="margin-bottom:4px;padding:4px;border-color:#DDD;">
<div class="f-htitle navy">Transkription fehlt</div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl R.</div><div class="f-doc-sub">Noch nicht begonnen</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Reisepass Opa Heinrich</div><div class="f-doc-sub">3 von 8 Blöcken geprüft</div></div></div>
<a class="f-link">Alle 8 anzeigen →</a>
</div>
<div class="f-card" style="padding:4px;background:rgba(166,218,216,.10);border-color:var(--mint);">
<div class="f-htitle green">Lesefertig ✓</div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div><div class="f-doc-sub">100 % geprüft</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Brief Oma Martha 1938</div><div class="f-doc-sub">95 % geprüft</div></div></div>
<a class="f-link green">Alle 3 anzeigen →</a>
</div>
</div>
</div>
</div>
<span class="caption">Mobil 320 px — Streifen stapelt vertikal</span>
</div>
<!-- Desktop C -->
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div></div>
<div class="f-resume"></div>
<!-- Existing grid — unchanged -->
<div class="f-grid-2" style="margin-bottom:7px;">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto Sommer 1952</div></div><div class="f-doc-date">3. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop</div></div>
<div class="f-card" style="flex:1;">
<div class="f-htitle orange">Metadaten fehlen</div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Reisepass Opa Heinrich</div><div class="f-doc-sub">Absender fehlt</div></div></div>
<a class="f-link">Alle anzeigen →</a>
</div>
</div>
</div>
<!-- ★ Mission control strip — new, full width -->
<div style="background:#fff;border:1px solid var(--sand);border-radius:3px;padding:8px;">
<div class="f-htitle" style="margin-bottom:7px;">Was braucht Aufmerksamkeit?</div>
<div class="f-grid-3">
<!-- Col 1: needs transcription -->
<div style="background:rgba(0,40,80,.03);border:1px solid var(--sand);border-radius:3px;padding:6px;">
<div class="f-htitle navy">Transkription fehlt</div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl R.</div><div class="f-doc-sub">Noch nicht begonnen</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Reisepass Opa Heinrich</div><div class="f-doc-sub">3 von 8 Blöcken geprüft</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamt 1889</div><div class="f-doc-sub">Noch nicht begonnen</div></div></div>
<a class="f-link">Alle 8 anzeigen →</a>
</div>
<!-- Col 2: ready to read -->
<div style="background:rgba(166,218,216,.10);border:1px solid var(--mint);border-radius:3px;padding:6px;">
<div class="f-htitle green">Lesefertig ✓</div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div><div class="f-doc-sub">100 % geprüft</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Brief Oma Martha 1938</div><div class="f-doc-sub">95 % geprüft</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Heiratsurkunde 1921</div><div class="f-doc-sub">91 % geprüft</div></div></div>
<a class="f-link green">Alle 3 lesen →</a>
</div>
<!-- Col 3: empty state example -->
<div style="background:rgba(166,218,216,.06);border:1.5px dashed var(--mint);border-radius:3px;padding:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;min-height:72px;">
<div style="font-size:12px;margin-bottom:3px;color:var(--green);"></div>
<div style="font-size:6px;color:var(--green);font-weight:700;">Alle Dokumente transkribiert</div>
<div style="font-size:5.5px;color:var(--muted);margin-top:2px;">Keine offenen Aufgaben</div>
</div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 %) — Hauptgitter unberührt; Streifen darunter zeigt leeren Zustand in Spalte 3</span>
</div>
</div>
<div class="impl-ref">
<table>
<thead><tr><th>Element</th><th>Tailwind-Klassen</th><th>Wert</th><th>Hinweis</th></tr></thead>
<tbody>
<tr><td>Streifen-Wrapper</td><td><code>mt-4 bg-white border border-line rounded-sm p-6</code></td><td>padding 24 px</td><td>Direkt nach bestehendem <code>div.mt-4.grid</code></td></tr>
<tr><td>Streifen-Titel</td><td><code>text-xs font-bold uppercase tracking-widest text-gray-400 mb-4</code></td><td>12 px / 700</td><td>Standard-Section-Title-Muster</td></tr>
<tr><td>3-Spalten-Grid</td><td><code>grid grid-cols-1 gap-4 sm:grid-cols-3</code></td><td>gap 16 px</td><td>Mobil: 1 Spalte, sm+: 3</td></tr>
<tr><td>Transkription-Spalte</td><td><code>bg-surface rounded-sm border border-line p-4</code></td><td></td><td>Neutral — es ist eine Aufgabe</td></tr>
<tr><td>Lesefertig-Spalte</td><td><code>bg-mint/10 rounded-sm border border-mint p-4</code></td><td></td><td>Mint-Ton = positives Signal</td></tr>
<tr><td>Leerer Zustand</td><td><code>flex flex-col items-center justify-center text-center bg-mint/5 border border-dashed border-mint rounded-sm p-6 min-h-[80px]</code></td><td>min-h 80 px</td><td>Niemals leere graue Box</td></tr>
<tr><td>Untertext-Zeile</td><td><code>text-xs text-gray-400 mt-0.5</code></td><td>12 px</td><td>z. B. „3 von 8 Blöcken geprüft"</td></tr>
<tr><td>Sichtbarkeit</td><td><code>{#if needsTranscription.length &gt; 0 || readyToRead.length &gt; 0}</code></td><td></td><td>Streifen komplett ausgeblendet wenn leer</td></tr>
</tbody>
</table>
</div>
</div>
<hr/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- PATTERN D: PRIORITY QUEUE -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-label">Muster D — Priorisierte Aufgabenliste (Priority Queue)</div>
<div class="pattern-title">„Was als nächstes?" — zusammengeführte Liste</div>
<div class="pattern-sub">Alle drei Kategorien in einer sortierten Liste mit Typ-Badge. Ersetzt die separaten drei Karten in der rechten Spalte.</div>
<div class="tag-list">
<span class="tag tag-pro">+ Keine mentale Auswahl zwischen Kategorien</span>
<span class="tag tag-pro">+ Eine einzelne Entscheidungsfläche</span>
<span class="tag tag-con"> „Lesefertig" verliert seinen Belohnungscharakter (gemischt mit Aufgaben)</span>
<span class="tag tag-con"> Merge-Logik auf dem Server ist komplexer als zwei separate Queries</span>
<span class="tag tag-con"> Farb-Badge allein reicht nicht — Icon + Label immer nötig (WCAG 1.4.1)</span>
</div>
<p class="prose">
Alle drei Kategorien werden in einer einzigen sortierten Liste zusammengeführt. Sortierung:
Metadaten fehlen (blockiert Suche) → Transkription fehlt → Lesefertig. Jede Zeile trägt ein farbkodiertes Label;
Farbe darf niemals der einzige Indikator sein — Icon und Text sind Pflicht (WCAG 1.4.1).
</p>
<p class="prose">
Kontrast-Check: Orange-700 auf Weiß = 5,4:1 ✓ AA. Navy auf Weiß = 14,5:1 ✓ AAA. Green-800 auf Weiß = 9,7:1 ✓ AAA.
</p>
<div class="frames-row">
<!-- Phone D -->
<div>
<div class="frame-phone">
<div class="ph-nav"><div class="ph-logo">FAMILIENARCHIV</div></div>
<div class="ph-body">
<div class="ph-search"><div class="ph-search-txt">⌕ Dokumente…</div></div>
<div class="f-dz" style="padding:5px;"><div class="f-dz-icon" style="font-size:10px;"></div><div class="f-dz-txt">Hochladen</div></div>
<div class="f-card" style="padding:5px;">
<div class="f-htitle">Was als nächstes?</div>
<div class="f-row"><div class="f-dot orange" style="margin-top:2px;"></div><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub" style="color:var(--orange);">⚠ Metadaten fehlen</div></div></div>
<div class="f-row"><div class="f-dot navy" style="margin-top:2px;"></div><div><div class="f-doc-name">Taufurkunde Karl R.</div><div class="f-doc-sub">✏ Noch nicht begonnen</div></div></div>
<div class="f-row"><div class="f-dot navy" style="margin-top:2px;"></div><div><div class="f-doc-name">Reisepass Opa</div><div class="f-doc-sub">✏ 3 von 8 Blöcken</div></div></div>
<div class="f-row" style="border-bottom:none;"><div class="f-dot green" style="margin-top:2px;"></div><div><div class="f-doc-name">Postkarte 1943</div><div class="f-doc-sub" style="color:var(--green);">✓ Lesefertig</div></div></div>
</div>
<div class="f-card" style="padding:5px;">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div class="f-doc-name">Brief von Oma Martha</div></div>
<div class="f-row"><div class="f-doc-name">Taufurkunde Karl R.</div></div>
</div>
</div>
</div>
<span class="caption">Mobil 320 px</span>
</div>
<!-- Desktop D -->
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div></div>
<div class="f-resume"></div>
<div class="f-grid-2">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto Sommer 1952</div></div><div class="f-doc-date">3. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop</div></div>
<div class="f-card" style="flex:1;">
<div class="f-htitle">Was als nächstes?</div>
<div class="f-row"><div class="f-dot orange"></div><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub" style="color:var(--orange);">⚠ Metadaten fehlen</div></div></div>
<div class="f-row"><div class="f-dot orange"></div><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub" style="color:var(--orange);">⚠ Datum fehlt</div></div></div>
<div class="f-row"><div class="f-dot navy"></div><div><div class="f-doc-name">Taufurkunde Karl R.</div><div class="f-doc-sub">✏ Noch nicht begonnen</div></div></div>
<div class="f-row"><div class="f-dot navy"></div><div><div class="f-doc-name">Reisepass Opa Heinrich</div><div class="f-doc-sub">✏ 3 von 8 Blöcken</div></div></div>
<div class="f-row" style="border-bottom:none;"><div class="f-dot green"></div><div><div class="f-doc-name">Postkarte aus Breslau</div><div class="f-doc-sub" style="color:var(--green);">✓ Lesefertig</div></div></div>
</div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 %) — eine Liste, drei Typen durch Farbe + Icon + Label unterschieden</span>
</div>
</div>
<div class="impl-ref">
<table>
<thead><tr><th>Element</th><th>Tailwind-Klassen</th><th>Wert</th><th>Hinweis</th></tr></thead>
<tbody>
<tr><td>Listen-Wrapper</td><td><code>rounded-sm border border-line bg-white p-4 flex-1</code></td><td></td><td>Ersetzt separate 3 Karten</td></tr>
<tr><td>Prioritäts-Zeile</td><td><code>flex items-start gap-3 py-2 border-b border-line last:border-0 min-h-[44px]</code></td><td>min-h 44 px ✓</td><td>WCAG touch target</td></tr>
<tr><td>Typ-Punkt</td><td><code>w-2 h-2 rounded-full mt-1.5 shrink-0</code></td><td>8 × 8 px</td><td>Nie allein — Label ist Pflicht</td></tr>
<tr><td>Label orange</td><td><code>text-xs text-orange-700</code></td><td>12 px</td><td>Kontrast 5,4:1 ✓ AA</td></tr>
<tr><td>Label navy</td><td><code>text-xs text-ink</code></td><td>12 px</td><td>Kontrast 14,5:1 ✓ AAA</td></tr>
<tr><td>Label grün</td><td><code>text-xs text-green-800</code></td><td>12 px</td><td>Kontrast 9,7:1 ✓ AAA</td></tr>
<tr><td>Merge-Service</td><td><code>findWhatsNext(int size)</code> auf <code>DashboardController</code></td><td></td><td>Sortierung: Metadaten → Trans → Lesefertig; per Markus: Threshold als <code>@Param</code></td></tr>
</tbody>
</table>
</div>
</div>
<hr/>
<!-- ── COMPARISON TABLE ──────────────────────────────────────────────── -->
<div class="section">
<div class="section-label">Vergleich aller vier Muster</div>
<table class="cmp">
<thead>
<tr>
<th>Kriterium</th>
<th>A — Tabs</th>
<th>B — Accordion</th>
<th>C — Mission Control ★</th>
<th>D — Priority Queue</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Alle 3 Kategorien sofort sichtbar</strong></td>
<td class="fail">Nein</td>
<td class="warn">Nur Überschriften</td>
<td class="pass best">Ja</td>
<td class="fail">Nein (gemischt)</td>
</tr>
<tr>
<td><strong>Neueste Aktivität bleibt Primärinhalt</strong></td>
<td class="pass">Ja</td>
<td class="pass">Ja</td>
<td class="pass best">Ja</td>
<td class="pass">Ja</td>
</tr>
<tr>
<td><strong>60+ Usability (Discovery ohne Klick)</strong></td>
<td class="warn">Mittel</td>
<td class="warn">Überschriften sichtbar</td>
<td class="pass best">Sehr gut</td>
<td class="warn">Mittel — gemischte Liste</td>
</tr>
<tr>
<td><strong>JS-Zustand nötig</strong></td>
<td class="fail">Ja (aktiver Tab)</td>
<td class="pass">Nein</td>
<td class="pass best">Nein</td>
<td class="pass">Nein</td>
</tr>
<tr>
<td><strong>WCAG 2.2 compliance (out of the box)</strong></td>
<td class="warn">tablist + aria-selected nötig</td>
<td class="pass">details/summary nativ</td>
<td class="pass best">Keine neuen Anforderungen</td>
<td class="warn">Farbe + Icon + Label alle Pflicht</td>
</tr>
<tr>
<td><strong>Mobile 320 px</strong></td>
<td class="warn">3 Tabs zu schmal</td>
<td class="pass">Gut</td>
<td class="pass best">Sehr gut — stapelt natürlich</td>
<td class="pass">Gut</td>
</tr>
<tr>
<td><strong>„Lesefertig" als visueller Applaus</strong></td>
<td class="warn">Nur wenn Tab aktiv</td>
<td class="warn">Nur wenn offen</td>
<td class="pass best">Ja — eigene mint-Karte</td>
<td class="fail">Nein — gleichwertig mit Aufgaben</td>
</tr>
<tr>
<td><strong>Backend-Merge-Komplexität</strong></td>
<td class="pass">Gering</td>
<td class="pass">Gering</td>
<td class="pass best">Gering (2 separate Queries)</td>
<td class="warn">Mittel (Merge + Sortierung)</td>
</tr>
<tr>
<td><strong>Implementierungsaufwand Frontend</strong></td>
<td class="warn">Mittel</td>
<td class="pass">Gering</td>
<td class="pass best">Gering</td>
<td class="pass">Gering</td>
</tr>
</tbody>
</table>
</div>
<!-- ── RECOMMENDATION ────────────────────────────────────────────────── -->
<div class="rec">
<h3>Empfehlung: Muster C — Mission-Control-Streifen</h3>
<p>
Der Mission-Control-Streifen ist das einzige Muster, das alle drei Kategorien gleichzeitig sichtbar macht,
ohne den Primärinhalt zu verstecken oder JS-Zustand zu erzeugen. Scrollen nach unten ist kein Fehler —
versteckter Inhalt schon.
</p>
<ul>
<li><strong>Tabs (A)</strong> — Gut für kompakten Platz, aber inaktive Kategorien werden von 60+-Nutzern übersehen. Tabs für die <em>gesamte Seite</em> (wie ursprünglich vorgeschlagen) wäre ein Antipattern — Neueste Aktivität wäre hinter einem Klick.</li>
<li><strong>Accordion (B)</strong> — Solide Fallback-Option ohne JS, wenn der Streifen aus Platzgründen abgelehnt wird. Alle Kategorien-Überschriften bleiben sichtbar.</li>
<li><strong>Priority Queue (D)</strong> — Elegant, aber „Lesefertig" verliert seinen Belohnungscharakter. Die Merge-Logik ist auch komplexer als zwei separate Queries.</li>
<li><strong>Mission Control (C)</strong> — Keine versteckten Inhalte. Kein JS. „Lesefertig" bekommt eine eigene mint-getönte Spalte als visuellen Applaus. Mobil stapeln die Spalten ohne weiteren Code. Der einzige Trade-off ist ein leichtes Scrollen auf Desktop.</li>
</ul>
<p style="margin-top:12px;">
<strong>Quick win:</strong> Wenn C abgelehnt wird — <strong>Muster B (Accordion)</strong> als Zweitstimme. Kein Refactoring der rechten Spalte, kein JS, alle Kategorien-Überschriften immer sichtbar.
</p>
</div>
<hr/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- MISSION CONTROL v2: SEGMENTATION SPLIT + ENGAGEMENT -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-label">Mission-Control-Streifen v2 — Segmentierung / Transkription / Lesefertig</div>
<div class="pattern-title">Beitragspyramide: Skill-basierte Aufgabentrennung</div>
<div class="pattern-sub">
Die ursprüngliche „Transkription fehlt"-Spalte wird in zwei klar getrennte Aufgaben aufgeteilt, die
unterschiedliche Fähigkeiten erfordern. Das löst gleichzeitig das Problem der leeren dritten Spalte.
</div>
<!-- Lifecycle diagram -->
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:20px;padding:16px 20px;background:#fff;border:1px solid var(--border);border-radius:6px;font-size:12px;">
<div style="text-align:center;">
<div style="background:var(--navy);color:#fff;border-radius:4px;padding:4px 10px;font-weight:600;font-size:11px;margin-bottom:4px;">Kein Segment</div>
<div style="font-size:10px;color:var(--muted);">0 Annotationen</div>
</div>
<div style="color:var(--muted);font-size:18px;"></div>
<div style="text-align:center;">
<div style="background:var(--navy);color:#fff;border-radius:4px;padding:4px 10px;font-weight:600;font-size:11px;margin-bottom:4px;">Segmentiert</div>
<div style="font-size:10px;color:var(--muted);">Rahmen vorhanden, kein Text</div>
</div>
<div style="color:var(--muted);font-size:18px;"></div>
<div style="text-align:center;">
<div style="background:var(--navy);color:#fff;border-radius:4px;padding:4px 10px;font-weight:600;font-size:11px;margin-bottom:4px;">Transkribiert</div>
<div style="font-size:10px;color:var(--muted);">Text vorhanden, review &lt; 90 %</div>
</div>
<div style="color:var(--muted);font-size:18px;"></div>
<div style="text-align:center;">
<div style="background:var(--green);color:#fff;border-radius:4px;padding:4px 10px;font-weight:600;font-size:11px;margin-bottom:4px;">Lesefertig ✓</div>
<div style="font-size:10px;color:var(--muted);">review ≥ 90 %</div>
</div>
<div style="margin-left:auto;font-size:11px;color:var(--muted);max-width:220px;line-height:1.4;">
Jede Stufe landet in einer eigenen Spalte. Die dritte Spalte ist strukturell nie leer —
Lesefertig-Dokumente erscheinen sobald auch nur eines fertig ist.
</div>
</div>
<!-- Column content definitions -->
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:24px;">
<div style="background:#fff;border:1px solid var(--border);border-radius:6px;padding:14px;">
<div style="font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--navy);margin-bottom:6px;">Spalte 1 — Segmentierung</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;margin-bottom:8px;">
Dokumente ohne Annotationsrahmen. <strong>Keine Vorkenntnisse nötig</strong> — Rahmen um Textblöcke einzeichnen. Niedrigste Einstiegshürde, breiteste Zielgruppe.
</div>
<div style="font-size:11px;color:var(--navy);font-weight:600;">Query: <code>SELECT … WHERE annotation_count = 0</code></div>
</div>
<div style="background:#fff;border:1px solid var(--border);border-radius:6px;padding:14px;">
<div style="font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--navy);margin-bottom:6px;">Spalte 2 — Transkription</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;margin-bottom:8px;">
Dokumente mit Rahmen, aber wenig/kein Text (<code>text IS NULL OR LENGTH(text) &lt; threshold</code>). <strong>Kurrent-Kenntnisse empfohlen.</strong>
</div>
<div style="font-size:11px;color:var(--navy);font-weight:600;">Query: <code>annotation_count &gt; 0 AND reviewed &lt; 75 %</code></div>
</div>
<div style="background:rgba(166,218,216,.10);border:1px solid var(--mint);border-radius:6px;padding:14px;">
<div style="font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--green);margin-bottom:6px;">Spalte 3 — Lesefertig ✓</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;margin-bottom:8px;">
Dokumente mit reviewed ≥ 90 %. Belohnungsbereich — kein Auftrag, sondern eine Einladung zum Lesen.
</div>
<div style="font-size:11px;color:var(--green);font-weight:600;">Query: <code>reviewed_pct &gt;= 0.90</code> (bestehend)</div>
</div>
</div>
<!-- ── ENGAGEMENT FEATURES ── -->
<div style="margin-bottom:20px;">
<div style="font-size:10px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;padding-bottom:6px;border-bottom:1px solid var(--border);">Engagement-Elemente — 5 Ideen</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px;">
<div style="background:#fff;border-left:3px solid var(--navy);padding:12px 16px;border-radius:0 4px 4px 0;">
<div style="font-size:12px;font-weight:700;color:var(--navy);margin-bottom:4px;">① Fortschritt — drei verschiedene Granularitäten</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;">
<strong style="color:var(--orange);">Kein globaler Balken</strong> bei 1 500 Dokumenten.
Ein Balken bei 0,8 % Füllstand ist psychologisch demotivierender als gar kein Balken
(endowed-progress-Effekt: Menschen brechen auf, wenn das Ziel unerreichbar wirkt).
<br/><br/>
Stattdessen drei zielgruppengerechte Ansätze:
<ul style="margin:6px 0 0 14px;line-height:1.7;">
<li><strong>Segmentierung-Spalte:</strong> Wochenpuls — „Diese Woche: +5 Dokumente". Zeigt Schwung, nicht den Berg. Query: <code style="font-size:10px;">COUNT(*) WHERE created_at > NOW() - INTERVAL '7 days'</code></li>
<li><strong>Transkription-Zeilen:</strong> Balkensegment pro Dokument — „3 von 8 Blöcken". Hier ist der Maßstab korrekt: 8 Blöcke sind in einer Sitzung erreichbar. Nur sichtbar wenn annotation_count > 0.</li>
<li><strong>Lesefertig-Zeilen:</strong> Prozentzahl als Text — „94 % geprüft". Kein Balken nötig — der Erfolg ist bereits kommuniziert durch die mint-Spalte selbst.</li>
</ul>
</div>
</div>
<div style="background:#fff;border-left:3px solid var(--navy);padding:12px 16px;border-radius:0 4px 4px 0;">
<div style="font-size:12px;font-weight:700;color:var(--navy);margin-bottom:4px;">② Skill-Label als Zugangsfilter</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;">
Unter dem Spaltentitel: ein kleines Pill-Label mit der Anforderung. „Ohne Vorkenntnisse" (grün) vs.
„Kurrent-Kenntnisse" (neutral). Senkt die Hemmschwelle für Neueinsteiger drastisch — sie sehen sofort,
was sie tun können.
</div>
</div>
<div style="background:#fff;border-left:3px solid var(--mint);padding:12px 16px;border-radius:0 4px 4px 0;">
<div style="font-size:12px;font-weight:700;color:var(--navy);margin-bottom:4px;">③ Contributor-Avatare (Social Proof)</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;">
Unter dem Titel: kleine Initialen-Bubbles der letzten 3 Beitragenden. Kein Leaderboard (erzeugt
Wettbewerb), aber soziale Sichtbarkeit (erzeugt Zugehörigkeit). „MR, TG und 2 weitere haben hier
mitgemacht."
</div>
</div>
<div style="background:#fff;border-left:3px solid var(--mint);padding:12px 16px;border-radius:0 4px 4px 0;">
<div style="font-size:12px;font-weight:700;color:var(--navy);margin-bottom:4px;">④ „Starte hier →" CTA-Button</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;">
Jede Aufgaben-Spalte endet mit einem einzelnen, klaren CTA, der direkt zum nächsten zu bearbeitenden
Dokument springt. Kein Auswahlprozess, kein Überlegen — ein Klick, sofort im Dokument. Entscheidungslähmung
ist der Hauptgrund für Non-Participation.
</div>
</div>
<div style="background:#fff;border-left:3px solid var(--orange);padding:12px 16px;border-radius:0 4px 4px 0;grid-column:span 2;">
<div style="font-size:12px;font-weight:700;color:var(--navy);margin-bottom:4px;">⑤ Lesefertig-Leerstand → Cross-Column-Redirect</div>
<div style="font-size:12px;color:var(--muted);line-height:1.5;">
Wenn Lesefertig leer ist (frühe Projektphase), zeigt die Spalte <em>nicht</em> „Noch nichts fertig" als
stille Sackgasse. Stattdessen: „Dokumente erscheinen hier, wenn die Transkription abgeschlossen ist —
<a style="color:var(--navy);">jetzt mithelfen →</a>". Der Link springt direkt zur Segmentierungs-Spalte. Leerer Zustand = aktive
Einladung, kein toter Endpunkt.
</div>
</div>
</div>
</div>
<!-- Desktop mockup v2 -->
<div class="frames-row">
<div style="flex:1;min-width:0;">
<div class="frame-desktop">
<div class="f-nav">
<div class="f-logo">FAMILIENARCHIV</div>
<div class="f-navlinks"><div class="f-navlink on">Archiv</div><div class="f-navlink">Personen</div></div>
<div class="f-navr"><div class="f-av">MR</div></div>
</div>
<div class="f-body">
<div class="f-search"><div class="f-search-icon"></div><div class="f-search-txt">Dokumente durchsuchen…</div></div>
<div class="f-resume"></div>
<div class="f-grid-2" style="margin-bottom:7px;">
<div class="f-card">
<div class="f-htitle">Neueste Aktivität</div>
<div class="f-row"><div><div class="f-doc-name">Brief von Oma Martha, 1943</div></div><div class="f-doc-date">12. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl Raddatz</div></div><div class="f-doc-date">9. Apr</div></div>
<div class="f-row"><div><div class="f-doc-name">Postkarte aus Breslau</div></div><div class="f-doc-date">7. Apr</div></div>
<div class="f-stats">47 Dokumente · 12 Personen</div>
</div>
<div class="rhs">
<div class="f-dz"><div class="f-dz-icon"></div><div class="f-dz-txt">Datei hochladen</div><div class="f-dz-sub">Drag &amp; Drop</div></div>
<div class="f-card" style="flex:1;">
<div class="f-htitle orange">Metadaten fehlen</div>
<div class="f-row"><div><div class="f-doc-name">Familienfoto 1952</div><div class="f-doc-sub">Titel fehlt</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamtsurkunde</div><div class="f-doc-sub">Datum fehlt</div></div></div>
<a class="f-link">Alle 5 anzeigen →</a>
</div>
</div>
</div>
<!-- ★★ Enhanced strip v2 -->
<div style="background:#fff;border:1px solid var(--sand);border-radius:3px;padding:8px;">
<div class="f-htitle" style="margin-bottom:7px;">Was braucht Aufmerksamkeit?</div>
<div class="f-grid-3">
<!-- Col 1: SEGMENTIERUNG — weekly pulse replaces global bar -->
<div style="background:rgba(0,40,80,.03);border:1px solid var(--sand);border-radius:3px;padding:6px;display:flex;flex-direction:column;gap:4px;">
<div>
<div class="f-htitle navy" style="margin-bottom:2px;">Rahmen einzeichnen</div>
<div style="display:inline-flex;align-items:center;gap:2px;padding:1px 5px;border-radius:8px;background:var(--green-bg);border:1px solid rgba(46,110,57,.2);font-size:5px;font-weight:700;color:var(--green);margin-bottom:3px;">✓ Ohne Vorkenntnisse</div>
<!-- Weekly pulse: shows momentum, not the mountain -->
<div style="display:flex;align-items:center;gap:4px;margin-bottom:3px;">
<div style="font-size:5.5px;color:var(--green);font-weight:700;">↑ +5 diese Woche</div>
<div style="font-size:5px;color:var(--muted);">· 1 480 offen</div>
</div>
<div style="display:flex;gap:2px;margin-bottom:4px;">
<div style="width:10px;height:10px;border-radius:50%;background:var(--navy);display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">MR</div>
<div style="width:10px;height:10px;border-radius:50%;background:#5B5EA6;display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">TG</div>
<div style="width:10px;height:10px;border-radius:50%;background:#8C6E3F;display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">AS</div>
<div style="font-size:5px;color:var(--muted);line-height:10px;margin-left:2px;">+ 2</div>
</div>
</div>
<div class="f-row"><div><div class="f-doc-name">Taufurkunde Karl R.</div><div class="f-doc-sub">Noch keine Rahmen</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Standesamt 1889</div><div class="f-doc-sub">Noch keine Rahmen</div></div></div>
<div class="f-row"><div><div class="f-doc-name">Heiratsurkunde 1921</div><div class="f-doc-sub">Noch keine Rahmen</div></div></div>
<a style="display:block;font-size:6px;font-weight:700;color:#fff;background:var(--navy);border-radius:2px;padding:3px 6px;text-align:center;margin-top:3px;">Jetzt einzeichnen →</a>
</div>
<!-- Col 2: TRANSKRIPTION — per-document mini bar, no global bar -->
<div style="background:rgba(0,40,80,.03);border:1px solid var(--sand);border-radius:3px;padding:6px;display:flex;flex-direction:column;gap:4px;">
<div>
<div class="f-htitle navy" style="margin-bottom:2px;">Text eintippen</div>
<div style="display:inline-flex;align-items:center;gap:2px;padding:1px 5px;border-radius:8px;background:rgba(0,40,80,.08);border:1px solid rgba(0,40,80,.15);font-size:5px;font-weight:700;color:var(--navy);margin-bottom:3px;">Kurrent hilfreich</div>
<div style="display:flex;align-items:center;gap:4px;margin-bottom:3px;">
<div style="font-size:5.5px;color:var(--navy);font-weight:700;">↑ +2 diese Woche</div>
<div style="font-size:5px;color:var(--muted);">· 8 offen</div>
</div>
<div style="display:flex;gap:2px;margin-bottom:4px;">
<div style="width:10px;height:10px;border-radius:50%;background:var(--navy);display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">MR</div>
<div style="font-size:5px;color:var(--muted);line-height:10px;margin-left:2px;">1 Person</div>
</div>
</div>
<!-- Per-document mini bar — right granularity, achievable in one session -->
<div style="display:flex;flex-direction:column;gap:2px;border-bottom:1px solid var(--sand);padding-bottom:4px;">
<div class="f-doc-name">Brief v. Oma Martha 1943</div>
<div style="display:flex;align-items:center;gap:3px;">
<div style="flex:1;height:3px;background:rgba(0,40,80,.12);border-radius:2px;overflow:hidden;"><div style="width:0%;height:100%;background:var(--navy);border-radius:2px;"></div></div>
<div style="font-size:5px;color:var(--muted);white-space:nowrap;">0 / 6 Blöcke</div>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:2px;border-bottom:1px solid var(--sand);padding-bottom:4px;">
<div class="f-doc-name">Reisepass Opa Heinrich</div>
<div style="display:flex;align-items:center;gap:3px;">
<div style="flex:1;height:3px;background:rgba(0,40,80,.12);border-radius:2px;overflow:hidden;"><div style="width:37%;height:100%;background:var(--navy);border-radius:2px;"></div></div>
<div style="font-size:5px;color:var(--muted);white-space:nowrap;">3 / 8 Blöcke</div>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:2px;">
<div class="f-doc-name">Postkarte aus Breslau</div>
<div style="display:flex;align-items:center;gap:3px;">
<div style="flex:1;height:3px;background:rgba(0,40,80,.12);border-radius:2px;overflow:hidden;"><div style="width:0%;height:100%;background:var(--navy);border-radius:2px;"></div></div>
<div style="font-size:5px;color:var(--muted);white-space:nowrap;">0 / 4 Blöcke</div>
</div>
</div>
<a style="display:block;font-size:6px;font-weight:700;color:#fff;background:var(--navy);border-radius:2px;padding:3px 6px;text-align:center;margin-top:3px;">Jetzt tippen →</a>
</div>
<!-- Col 3: LESEFERTIG — filled: % as text; empty: cross-column redirect -->
<div style="background:rgba(166,218,216,.10);border:1px solid var(--mint);border-radius:3px;padding:6px;display:flex;flex-direction:column;gap:4px;">
<div>
<div class="f-htitle green" style="margin-bottom:2px;">Lesefertig ✓</div>
<div style="font-size:5.5px;color:var(--green);font-weight:600;margin-bottom:4px;">3 Dokumente bereit</div>
<div style="display:flex;gap:2px;margin-bottom:4px;">
<div style="width:10px;height:10px;border-radius:50%;background:var(--green);display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">MR</div>
<div style="width:10px;height:10px;border-radius:50%;background:#5B5EA6;display:flex;align-items:center;justify-content:center;font-size:4px;font-weight:700;color:#fff;">TG</div>
</div>
</div>
<!-- % as text — no bar, the mint column itself signals success -->
<div style="display:flex;flex-direction:column;gap:1px;border-bottom:1px solid rgba(166,218,216,.4);padding-bottom:3px;">
<div class="f-doc-name">Postkarte aus Breslau 1943</div>
<div style="font-size:5.5px;color:var(--green);font-weight:600;">100 % geprüft</div>
</div>
<div style="display:flex;flex-direction:column;gap:1px;border-bottom:1px solid rgba(166,218,216,.4);padding-bottom:3px;">
<div class="f-doc-name">Brief Oma Martha 1938</div>
<div style="font-size:5.5px;color:var(--green);font-weight:600;">95 % geprüft</div>
</div>
<div style="display:flex;flex-direction:column;gap:1px;">
<div class="f-doc-name">Heiratsurkunde 1921</div>
<div style="font-size:5.5px;color:var(--green);font-weight:600;">91 % geprüft</div>
</div>
<a class="f-link green" style="margin-top:3px;">Alle 3 lesen →</a>
</div>
</div>
</div>
</div>
</div>
<span class="caption">Desktop (55 %) — v2: Spalten 1+2 aufgeteilt, Lesefertig-Leerstand mit aktivem Cross-Column-CTA</span>
</div>
</div>
<!-- impl-ref v2 -->
<div class="impl-ref">
<table>
<thead><tr><th>Element</th><th>Tailwind-Klassen / Logik</th><th>Wert</th><th>Hinweis</th></tr></thead>
<tbody>
<tr><td>Skill-Pill „Ohne Vorkenntnisse"</td><td><code>inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold bg-green-50 border border-green-200 text-green-800</code></td><td>Kontrast 9,7:1 ✓</td><td>Klärung für 60+ und Neueinsteiger</td></tr>
<tr><td>Skill-Pill „Kurrent hilfreich"</td><td><code>inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold bg-surface border border-line text-ink</code></td><td>neutral — kein Schreckpunkt</td><td>Nicht „Experten nötig" sondern „hilfreich"</td></tr>
<tr><td>Wochenpuls (Segmentierung + Transkription)</td><td><code>text-xs font-semibold text-green-700</code> (Seg.) / <code>text-ink</code> (Trans.)</td><td>12 px</td><td>Query: <code>COUNT WHERE created_at &gt; NOW() - INTERVAL '7 days'</code>; kein globaler Balken</td></tr>
<tr><td>Per-Dokument-Balken Track</td><td><code>flex-1 h-1 bg-navy/20 rounded-full overflow-hidden</code></td><td>h: 4 px</td><td>Nur in Transkription-Spalte, nur wenn <code>annotation_count &gt; 0</code></td></tr>
<tr><td>Per-Dokument-Balken Füllstand</td><td><code>h-full bg-navy rounded-full</code> + <code>style="width:{pct}%"</code></td><td></td><td>pct = textedBlocks / totalBlocks * 100; Guard: totalBlocks = 0 → width 0</td></tr>
<tr><td>Lesefertig-Prozentzahl</td><td><code>text-xs font-semibold text-green-800</code></td><td>12 px</td><td>Kein Balken — die mint-Spalte selbst ist das Erfolgssignal</td></tr>
<tr><td>Contributor-Avatar</td><td><code>w-6 h-6 rounded-full flex items-center justify-center text-[10px] font-bold text-white</code></td><td>24 × 24 px</td><td>Farbe per User-ID deterministisch (kein API-Feld nötig)</td></tr>
<tr><td>„Starte hier"-CTA</td><td><code>block w-full text-center text-xs font-semibold text-white bg-ink rounded-sm py-1.5 mt-2 hover:bg-ink-2 transition-colors focus-visible:ring-2 focus-visible:ring-ink</code></td><td>min-h 36 px</td><td>Link: <code>/enrich?filter=NEEDS_SEGMENTATION&amp;next=1</code></td></tr>
<tr><td>Lesefertig-Leerstand CTA</td><td><code>inline-flex items-center text-xs font-semibold text-ink border border-ink rounded-sm px-3 py-1 hover:bg-ink hover:text-white transition-colors</code></td><td></td><td>Link springt zur Segmentierungs-Ansicht</td></tr>
<tr><td>Contributor-API-Feld</td><td><code>GET /api/documents/needs-segmentation</code> → DTO enthält <code>lastContributors: [{initials, colorSeed}]</code></td><td>max 3 Avatare</td><td>Neues DTO-Feld — beachte Nora: nur Initialen, keine Namen</td></tr>
<tr><td>Segmentierung-Query</td><td><code>WHERE NOT EXISTS (SELECT 1 FROM document_annotations WHERE document_id = d.id)</code></td><td></td><td>Index auf <code>document_annotations.document_id</code> prüfen (Tobias)</td></tr>
<tr><td>Transkription-Query</td><td><code>EXISTS annotation AND (no blocks OR reviewed_pct &lt; 0.75)</code></td><td></td><td>Guard gegen Division durch 0 (Sara)</td></tr>
</tbody>
</table>
</div>
<!-- Security note -->
<div style="margin-top:16px;background:var(--orange-bg);border-left:3px solid var(--orange);padding:12px 16px;border-radius:0 4px 4px 0;font-size:12px;">
<strong style="color:var(--orange);">Datenschutz-Hinweis (Nora):</strong> Contributor-Avatare zeigen nur Initialen, niemals volle Namen im DOM.
Das DTO liefert <code>initials</code> + einen deterministischen <code>colorSeed</code> (z. B. Hash der User-ID mod 6 Farben),
keine E-Mail-Adressen oder echten Namen. Das <code>@RequirePermission(READ_ALL)</code> auf den neuen Endpoints gilt auch hier.
</div>
</div>
</div><!-- /doc -->
</body>
</html>