Files
familienarchiv/docs/specs/stammbaum-person-edit-spec.html
Marcel 33ca2df45b
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m12s
CI / OCR Service Tests (push) Successful in 29s
CI / Backend Unit Tests (push) Failing after 3m1s
docs(specs): add Stammbaum UI specs — tree, document badge, person edit
Three standalone HTML spec files covering the initial Stammbaum release:
- stammbaum-tree-spec.html — desktop/tablet/mobile tree canvas with side panel, light + dark
- stammbaum-doc-badge-spec.html — inline relationship pill on document detail
- stammbaum-person-edit-spec.html — relationship editor card on person edit page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 13:09:47 +02:00

1136 lines
54 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="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stammbaum — Person Edit · Stammbaum &amp; Beziehungen Card · Familienarchiv</title>
<link href="https://fonts.googleapis.com/css2?family=Tinos:ital,wght@0,400;0,700&family=Montserrat:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Montserrat',system-ui,sans-serif;background:#ECEAE4;color:#1A1A1A;line-height:1.5;font-size:13px}
.doc{max-width:1300px;margin:0 auto;padding:48px 32px 120px}
/* ── Masthead ── */
.mh{padding-bottom:24px;border-bottom:3px solid #012851;margin-bottom:60px}
.mh h1{font-size:23px;font-weight:900;color:#012851;letter-spacing:-.4px}
.mh p{font-size:13px;color:#555;max-width:740px;line-height:1.75;margin-top:8px}
.mh .byline{font-size:9px;color:#999;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;margin-top:10px}
.tag-row{display:flex;gap:6px;margin-top:10px;flex-wrap:wrap}
.tag{background:#012851;color:#A1DCD8;padding:2px 8px;border-radius:2px;font-size:8px;font-weight:700;letter-spacing:.8px;text-transform:uppercase}
.tag.amber{background:#7c4a00;color:#fde68a}
/* ── Section headers ── */
.sh{margin:0 0 28px}
.sh h2{font-size:16px;font-weight:900;color:#012851;letter-spacing:-.2px}
.sh p{font-size:12.5px;color:#666;max-width:720px;line-height:1.7;margin-top:5px}
.section{margin-bottom:80px;padding-bottom:80px;border-bottom:2px dashed #C8C4BE}
.section:last-of-type{border-bottom:none;margin-bottom:0;padding-bottom:0}
/* ── Token tables ── */
.token-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.token-table{border-radius:6px;overflow:hidden}
.token-table.light{background:#fff;border:1px solid #E0DDD6}
.token-table.dark{background:#0F1923;border:1px solid #1E2D3D}
.token-head{padding:8px 14px;font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.8px;border-bottom:1px solid #E0DDD6}
.token-table.light .token-head{background:#F4F2EC;color:#888;border-bottom-color:#E0DDD6}
.token-table.dark .token-head{background:#0A1218;color:#4E6070;border-bottom-color:#1E2D3D}
.token-table table{width:100%;border-collapse:collapse;font-size:11px}
.token-table.light td{padding:6px 14px;border-bottom:1px solid #F0EEE8;vertical-align:middle}
.token-table.dark td{padding:6px 14px;border-bottom:1px solid #1A2830;vertical-align:middle;color:#8AAABB}
.token-table tr:last-child td{border-bottom:none}
.token-table.light td:first-child{font-size:9px;font-weight:700;color:#888;width:160px}
.token-table.dark td:first-child{font-size:9px;font-weight:700;color:#4E6070;width:160px}
.swatch{display:inline-block;width:12px;height:12px;border-radius:2px;vertical-align:middle;margin-right:6px}
.swatch.bordered{border:1px solid #DDD}
.warn{display:inline-block;background:#FEF3C7;color:#92400E;font-size:8px;font-weight:700;padding:1px 5px;border-radius:2px;margin-left:4px;vertical-align:middle}
.pass{display:inline-block;background:#D1FAE5;color:#065F46;font-size:8px;font-weight:700;padding:1px 5px;border-radius:2px;margin-left:4px;vertical-align:middle}
/* ── Browser chrome ── */
.chrome{border:1.5px solid #C4C0BA;border-radius:8px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.1)}
.chrome.dark{background:#010e1e;border-color:#0d3358}
.chrome-bar{height:20px;background:#E8E6E0;border-bottom:1px solid #C4C0BA;display:flex;align-items:center;padding:0 8px;gap:4px;flex-shrink:0}
.chrome.dark .chrome-bar{background:#010a18;border-bottom-color:#0d3358}
.chrome-dot{width:6px;height:6px;border-radius:50%;background:#BDB8B1}
.chrome.dark .chrome-dot{background:#1a2a3a}
.chrome-url{flex:1;height:9px;background:#CCC8C2;border-radius:5px;margin-left:6px}
.chrome.dark .chrome-url{background:#1a2a3a}
/* ── App nav ── */
.app-nav{height:30px;background:#012851;display:flex;align-items:center;padding:0 12px;gap:10px;flex-shrink:0}
.app-logo{font-family:'Tinos',Georgia,serif;font-size:7px;font-weight:700;color:#fff;border-bottom:2px solid #A1DCD8;padding-bottom:1px}
.app-link{font-size:5.5px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:rgba(255,255,255,.4);white-space:nowrap}
.app-link.on{color:rgba(255,255,255,.9)}
.app-nav-r{margin-left:auto;display:flex;gap:6px;align-items:center}
.app-av{width:16px;height:16px;border-radius:50%;background:rgba(255,255,255,.12);display:flex;align-items:center;justify-content:center;font-size:5px;font-weight:800;color:rgba(255,255,255,.5)}
/* ── Side-by-side layout ── */
.split-screens{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-bottom:16px}
.screen-lbl{font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:1.2px;color:#888;margin-bottom:8px;display:flex;align-items:center;gap:5px}
.lbl-dot{width:8px;height:8px;border-radius:50%;display:inline-block}
.cap{font-size:10px;color:#999;font-style:italic;line-height:1.6;margin-top:10px;max-width:520px}
/* ── Rules / impl ref table ── */
.rules{background:#fff;border:1px solid #E0DDD6;border-radius:6px;overflow:hidden}
.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.6}
.rules tr:last-child td{border-bottom:none}
.rules td:first-child{font-size:9px;font-weight:700;color:#012851;white-space:nowrap;width:200px}
.rules td code{font-size:9px;background:#F0EFE9;padding:1px 4px;border-radius:2px;color:#555;white-space:nowrap}
/* ══ PERSON EDIT PAGE COMPONENTS ══ */
/* Page wrapper inside chrome */
.pe-page{background:#f0efe9;padding:20px 18px 40px;display:flex;flex-direction:column;align-items:center;gap:0}
.chrome.dark .pe-page{background:#010e1e}
/* Page heading */
.pe-h1{font-family:'Tinos',Georgia,serif;font-size:16px;font-weight:700;color:#012851;letter-spacing:-.3px;margin-bottom:14px;align-self:flex-start;width:100%;max-width:520px}
.chrome.dark .pe-h1{color:#f0efe9}
/* Generic edit card */
.pe-card{background:#fff;border:1px solid #e4e2d7;border-radius:2px;padding:16px 18px;width:100%;max-width:520px;margin-bottom:10px}
.chrome.dark .pe-card{background:#011526;border-color:#0d3358}
/* Card section label */
.pe-sec-lbl{font-size:7px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:#6b7280;margin-bottom:10px}
.chrome.dark .pe-sec-lbl{color:#8b97a5}
/* Card header row (label + toggle) */
.pe-card-hdr{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.pe-card-hdr-right{display:flex;align-items:center;gap:6px}
.pe-toggle-lbl{font-size:7px;font-weight:700;color:#012851}
.chrome.dark .pe-toggle-lbl{color:#a1dcd8}
/* Toggle switch */
.toggle{width:32px;height:17px;border-radius:999px;background:#e4e2d7;position:relative;flex-shrink:0}
.toggle.on{background:#012851}
.chrome.dark .toggle.on{background:#a1dcd8}
.toggle-thumb{width:13px;height:13px;border-radius:50%;background:#fff;position:absolute;top:2px;left:2px;transition:left .15s}
.toggle.on .toggle-thumb{left:17px}
.chrome.dark .toggle.on .toggle-thumb{background:#012851}
/* In-tree indicator */
.intree{display:flex;align-items:center;justify-content:space-between;background:rgba(161,220,216,.1);border:1px solid #a1dcd8;border-radius:2px;padding:6px 9px;margin-bottom:12px}
.chrome.dark .intree{background:rgba(0,199,177,.08);border-color:#00c7b1}
.intree-left{display:flex;align-items:center;gap:6px}
.intree-dot{width:7px;height:7px;border-radius:50%;background:#012851;flex-shrink:0}
.chrome.dark .intree-dot{background:#00c7b1}
.intree-lbl{font-size:7px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:#012851}
.chrome.dark .intree-lbl{color:#00c7b1}
.intree-link{font-size:7px;font-weight:600;color:#012851;opacity:.6;white-space:nowrap}
.chrome.dark .intree-link{color:#a1dcd8;opacity:.7}
/* Relationship rows */
.rel-rows{display:flex;flex-direction:column;gap:0;margin-bottom:6px}
.rel-row{display:flex;align-items:center;gap:7px;padding:6px 0;border-bottom:1px solid #f5f4ef}
.chrome.dark .rel-row{border-bottom-color:#011a30}
.rel-row:last-child{border-bottom:none}
.rel-pill{font-size:7px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:#012851;background:rgba(161,220,216,.2);border:1px solid #a1dcd8;border-radius:999px;padding:2px 7px;white-space:nowrap;flex-shrink:0}
.chrome.dark .rel-pill{background:rgba(0,199,177,.12);border-color:#00c7b1;color:#f0efe9}
.rel-pill.spouse{background:rgba(161,220,216,.35)}
.chrome.dark .rel-pill.spouse{background:rgba(0,199,177,.22)}
.rel-name{font-family:'Tinos',Georgia,serif;font-size:10px;color:#012851;flex:1;min-width:0}
.chrome.dark .rel-name{color:#f0efe9}
.rel-years{font-size:8px;color:#6b7280;white-space:nowrap;margin-right:2px}
.chrome.dark .rel-years{color:#8b97a5}
.rel-del{font-size:9px;color:#6b7280;line-height:1;padding:2px;margin-left:2px;cursor:pointer;flex-shrink:0}
/* Add-rel button */
.add-rel-btn{font-size:8px;font-weight:700;color:#012851;opacity:.6;display:flex;align-items:center;gap:4px;margin-top:4px;cursor:pointer}
.chrome.dark .add-rel-btn{color:#a1dcd8;opacity:.7}
/* Inline add form */
.add-form{background:#f5f4ef;border:1px solid #e4e2d7;border-radius:2px;padding:12px;margin-top:8px}
.chrome.dark .add-form{background:#011a30;border-color:#0d3358}
.add-form-lbl{font-size:7px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:#6b7280;margin-bottom:8px}
.chrome.dark .add-form-lbl{color:#8b97a5}
.add-form-row{display:flex;gap:8px;margin-bottom:7px}
.add-form-field{flex:1;display:flex;flex-direction:column;gap:3px}
.add-form-field label{font-size:7px;font-weight:700;color:#6b7280;text-transform:uppercase;letter-spacing:.06em}
.chrome.dark .add-form-field label{color:#8b97a5}
.add-form-field select,
.add-form-field input{height:27px;border:1px solid #e4e2d7;border-radius:2px;padding:0 7px;font-family:'Montserrat',sans-serif;font-size:8px;color:#012851;background:#fff;width:100%}
.chrome.dark .add-form-field select,
.chrome.dark .add-form-field input{background:#011526;border-color:#0d3358;color:#f0efe9}
.add-form-field input::placeholder{color:#aaa}
.chrome.dark .add-form-field input::placeholder{color:#4E6070}
.add-form-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:4px}
.btn-cancel{height:24px;padding:0 10px;border:1px solid #e4e2d7;border-radius:2px;background:#fff;font-size:7.5px;font-weight:700;color:#4b5563;cursor:pointer}
.chrome.dark .btn-cancel{background:#011526;border-color:#0d3358;color:#8b97a5}
.btn-add{height:24px;padding:0 10px;border-radius:2px;background:#012851;border:none;font-size:7.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:#fff;cursor:pointer}
.chrome.dark .btn-add{background:#a1dcd8;color:#012851}
/* Derived relationships collapsed section */
.derived-hdr{display:flex;align-items:center;justify-content:space-between;padding:7px 0;cursor:pointer;border-top:1px solid #f0efe9;margin-top:10px}
.chrome.dark .derived-hdr{border-top-color:#0d3358}
.derived-hdr-lbl{font-size:8px;font-weight:700;color:#6b7280}
.chrome.dark .derived-hdr-lbl{color:#8b97a5}
.derived-hdr-count{font-size:7px;font-weight:700;color:#6b7280;background:#f5f4ef;border:1px solid #e4e2d7;border-radius:999px;padding:1px 6px;margin-left:4px}
.chrome.dark .derived-hdr-count{background:#011a30;border-color:#0d3358;color:#8b97a5}
.derived-chevron{font-size:8px;color:#6b7280}
.chrome.dark .derived-chevron{color:#8b97a5}
.derived-rows{display:flex;flex-direction:column;gap:5px;margin-top:8px;padding-bottom:4px}
.derived-row{display:flex;align-items:center;gap:7px}
.derived-pill{font-size:6.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:#4b5563;background:#f5f4ef;border:1px solid #e4e2d7;border-radius:999px;padding:2px 7px;white-space:nowrap;flex-shrink:0}
.chrome.dark .derived-pill{background:#011a30;border-color:#0d3358;color:#9ca3af}
.derived-name{font-family:'Tinos',Georgia,serif;font-size:10px;color:#6b7280}
.chrome.dark .derived-name{color:#8b97a5}
.derived-note{font-family:'Tinos',Georgia,serif;font-size:10px;color:#9ca3af;font-style:italic}
.chrome.dark .derived-note{color:#4E6070}
/* Angaben card placeholder (above the new card) */
.stub-card{background:#fff;border:1px solid #e4e2d7;border-radius:2px;padding:12px 14px;width:100%;max-width:520px;margin-bottom:10px;opacity:.6}
.chrome.dark .stub-card{background:#011526;border-color:#0d3358}
.stub-field{height:8px;background:#f0efe9;border-radius:2px;margin-bottom:6px}
.chrome.dark .stub-field{background:#0d1c2c}
.stub-lbl{font-size:7px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#aaa;margin-bottom:5px}
.chrome.dark .stub-lbl{color:#4E6070}
.stub-row{display:flex;gap:8px;margin-bottom:8px}
.stub-segmented{display:flex;gap:3px;margin-bottom:8px}
.stub-seg{height:18px;width:38px;background:#f5f4ef;border:1px solid #e4e2d7;border-radius:2px}
.stub-seg.active{background:#012851}
.chrome.dark .stub-seg{background:#011a30;border-color:#0d3358}
.chrome.dark .stub-seg.active{background:#a1dcd8}
/* Save bar (stub) */
.pe-savebar{background:#fff;border-top:1px solid #e4e2d7;padding:8px 18px;display:flex;align-items:center;justify-content:flex-end;gap:6px;width:100%;max-width:520px;margin-top:2px;box-shadow:0 -2px 6px rgba(0,0,0,.04)}
.chrome.dark .pe-savebar{background:#011526;border-top-color:#0d3358}
/* Narrow viewport helpers */
.narrow .pe-page{padding:14px 10px 30px}
.narrow .pe-card{padding:12px 12px}
.narrow .pe-h1{font-size:13px;margin-bottom:10px}
.narrow .add-form-row{flex-direction:column;gap:6px}
/* Mobile helpers */
.mobile .pe-page{padding:10px 7px 24px}
.mobile .pe-card{padding:10px 10px}
.mobile .pe-h1{font-size:12px;margin-bottom:8px}
.mobile .add-form-row{flex-direction:column;gap:5px}
.mobile .rel-pill{font-size:6px;padding:1px 5px}
.mobile .rel-name{font-size:9px}
</style>
</head>
<body>
<div class="doc">
<!-- ══ MASTHEAD ══════════════════════════════════════════════════════════════ -->
<div class="mh">
<h1>Stammbaum — Person Edit · Stammbaum &amp; Beziehungen Card</h1>
<p>
Spec for the new <strong>Stammbaum &amp; Beziehungen</strong> card appended at the bottom of
<code>/persons/{id}/edit</code>. The card lets editors toggle a person's family-tree membership
and manage their direct relationships (parents-of, spouse, siblings, etc.). Inferred transitive
relationships are shown in a collapsible derived section.
</p>
<div class="byline">Familienarchiv · 2026-04-27 · Leonie Voss, UX Lead</div>
<div class="tag-row">
<span class="tag">Stammbaum Feature</span>
<span class="tag">View 3 of 3 — Person Edit</span>
<span class="tag">Desktop / Tablet / Mobile</span>
<span class="tag">Light + Dark</span>
</div>
</div>
<!-- ══ SECTION 1 — DESIGN TOKENS ════════════════════════════════════════════ -->
<div class="section">
<div class="sh">
<h2>1 · Design tokens</h2>
<p>All colour values used by the new card. Components use Tailwind semantic tokens; exact hex values are provided here for reference only.</p>
</div>
<div class="token-grid">
<!-- Light -->
<div class="token-table light">
<div class="token-head">Light theme — page bg #f0efe9 · card bg #ffffff</div>
<table>
<tr>
<td>Page bg</td>
<td><span class="swatch" style="background:#f0efe9;border:1px solid #ddd"></span>#f0efe9 — sand</td>
</tr>
<tr>
<td>Card bg / border</td>
<td><span class="swatch" style="background:#fff;border:1px solid #e4e2d7"></span>#ffffff / 1px #e4e2d7</td>
</tr>
<tr>
<td>Section label</td>
<td><span class="swatch" style="background:#6b7280"></span>#6b7280 — Montserrat 9px 700 uppercase<span class="pass">4.8:1 AA ✓</span></td>
</tr>
<tr>
<td>In-tree indicator bg</td>
<td><span class="swatch" style="background:rgba(161,220,216,.1);border:1px solid #a1dcd8"></span>rgba(161,220,216,.1) bg / 1px #a1dcd8 border</td>
</tr>
<tr>
<td>In-tree label</td>
<td><span class="swatch" style="background:#012851"></span>#012851<span class="pass">14.5:1 AAA ✓</span></td>
</tr>
<tr>
<td>Toggle ON track</td>
<td><span class="swatch" style="background:#012851"></span>#012851</td>
</tr>
<tr>
<td>Toggle OFF track</td>
<td><span class="swatch" style="background:#e4e2d7;border:1px solid #ccc"></span>#e4e2d7</td>
</tr>
<tr>
<td>Toggle thumb</td>
<td><span class="swatch" style="background:#fff;border:1px solid #ccc"></span>#ffffff</td>
</tr>
<tr>
<td>Direct rel pill bg/border</td>
<td><span class="swatch" style="background:rgba(161,220,216,.2);border:1px solid #a1dcd8"></span>rgba(161,220,216,.2) / 1px #a1dcd8</td>
</tr>
<tr>
<td>Direct rel name</td>
<td><span class="swatch" style="background:#012851"></span>#012851 — Tinos 10px</td>
</tr>
<tr>
<td>Rel years</td>
<td><span class="swatch" style="background:#6b7280"></span>#6b7280 — Montserrat 8px</td>
</tr>
<tr>
<td>Delete btn / hover</td>
<td><span class="swatch" style="background:#6b7280"></span>#6b7280 normal / <span class="swatch" style="background:#c0392b"></span>#c0392b hover</td>
</tr>
<tr>
<td>Add-form bg / border</td>
<td><span class="swatch" style="background:#f5f4ef;border:1px solid #e4e2d7"></span>#f5f4ef / #e4e2d7</td>
</tr>
<tr>
<td>Derived pill bg/border</td>
<td><span class="swatch" style="background:#f5f4ef;border:1px solid #e4e2d7"></span>#f5f4ef / #e4e2d7</td>
</tr>
<tr>
<td>+ Hinzufügen btn</td>
<td><span class="swatch" style="background:#012851"></span>#012851 bg / #fff text</td>
</tr>
</table>
</div>
<!-- Dark -->
<div class="token-table dark">
<div class="token-head">Dark theme — page bg #010e1e · card bg #011526</div>
<table>
<tr>
<td>Page bg</td>
<td><span class="swatch" style="background:#010e1e;border:1px solid #0d3358"></span>#010e1e</td>
</tr>
<tr>
<td>Card bg / border</td>
<td><span class="swatch" style="background:#011526;border:1px solid #0d3358"></span>#011526 / 1px #0d3358</td>
</tr>
<tr>
<td>Section label</td>
<td><span class="swatch" style="background:#8b97a5"></span>#8b97a5<span class="pass" style="background:rgba(209,250,229,.15);color:#6EE7B7;border:none">7.1:1 AAA ✓</span></td>
</tr>
<tr>
<td>In-tree indicator bg</td>
<td><span class="swatch" style="background:rgba(0,199,177,.08);border:1px solid #00c7b1"></span>rgba(0,199,177,.08) bg / 1px #00c7b1 border</td>
</tr>
<tr>
<td>In-tree label</td>
<td><span class="swatch" style="background:#00c7b1"></span>#00c7b1</td>
</tr>
<tr>
<td>Toggle ON track</td>
<td><span class="swatch" style="background:#a1dcd8"></span>#a1dcd8 (mint)</td>
</tr>
<tr>
<td>Toggle thumb (ON)</td>
<td><span class="swatch" style="background:#012851;border:1px solid #0d3358"></span>#012851</td>
</tr>
<tr>
<td>Direct rel pill bg/border</td>
<td><span class="swatch" style="background:rgba(0,199,177,.12);border:1px solid #00c7b1"></span>rgba(0,199,177,.12) / 1px #00c7b1</td>
</tr>
<tr>
<td>Direct rel name</td>
<td><span class="swatch" style="background:#f0efe9"></span>#f0efe9</td>
</tr>
<tr>
<td>Rel years</td>
<td><span class="swatch" style="background:#8b97a5"></span>#8b97a5</td>
</tr>
<tr>
<td>Add-form bg / border</td>
<td><span class="swatch" style="background:#011a30;border:1px solid #0d3358"></span>#011a30 / #0d3358</td>
</tr>
<tr>
<td>Derived pill bg/border</td>
<td><span class="swatch" style="background:#011a30;border:1px solid #0d3358"></span>#011a30 / #0d3358 / text #9ca3af</td>
</tr>
<tr>
<td>+ Hinzufügen btn</td>
<td><span class="swatch" style="background:#a1dcd8"></span>#a1dcd8 bg / #012851 text</td>
</tr>
</table>
</div>
</div>
</div>
<!-- ══ SECTION 2 — DESKTOP 1280px LIGHT + DARK ══════════════════════════════ -->
<div class="section">
<div class="sh">
<h2>2 · Desktop (1280 px) — light &amp; dark</h2>
<p>
Full person-edit page at desktop width. Light mockup shows the
<strong>add-form expanded</strong>; dark mockup shows the <strong>resting state</strong>
(form collapsed, toggle ON, no derived section open). Shown at ~40% scale.
</p>
</div>
<div class="split-screens">
<!-- ── LIGHT ── -->
<div>
<div class="screen-lbl"><span class="lbl-dot" style="background:#A1DCD8;border:1px solid #ccc"></span>Light theme · add form expanded</div>
<div class="chrome">
<div class="chrome-bar"><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-url"></div></div>
<div class="app-nav">
<div class="app-logo">Familienarchiv</div>
<div class="app-link">Dokumente</div>
<div class="app-link on">Personen</div>
<div class="app-link">Chronik</div>
<div class="app-link">Admin</div>
<div class="app-nav-r"><div class="app-av">M</div></div>
</div>
<div class="pe-page">
<!-- Back link -->
<div style="width:100%;max-width:520px;margin-bottom:8px">
<span style="font-size:7.5px;font-weight:700;color:#012851;opacity:.5;display:flex;align-items:center;gap:3px">
<svg width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"/></svg>
Zurück
</span>
</div>
<div class="pe-h1">Person bearbeiten</div>
<!-- Card 1: Angaben stub -->
<div class="stub-card">
<div class="pe-sec-lbl">Angaben zur Person</div>
<div class="stub-segmented">
<div class="stub-seg active"></div>
<div class="stub-seg"></div>
<div class="stub-seg"></div>
<div class="stub-seg"></div>
</div>
<div class="stub-row">
<div style="flex:1"><div class="stub-lbl">Titel + Vorname</div><div class="stub-field"></div></div>
<div style="flex:1.5"><div class="stub-lbl">Nachname</div><div class="stub-field"></div></div>
</div>
<div class="stub-row">
<div style="flex:1"><div class="stub-lbl">Rufname</div><div class="stub-field"></div></div>
<div style="flex:1"><div class="stub-lbl">Geburtsjahr</div><div class="stub-field"></div></div>
<div style="flex:1"><div class="stub-lbl">Todesjahr</div><div class="stub-field"></div></div>
</div>
<div class="stub-field" style="height:30px;opacity:.5"></div>
</div>
<!-- Card 2: Namensverlauf stub -->
<div class="stub-card" style="padding:10px 14px">
<div class="pe-sec-lbl">Namensverlauf</div>
<div style="font-family:'Tinos',serif;font-size:8px;color:#aaa;font-style:italic;margin-bottom:8px">Noch keine Namensänderungen erfasst</div>
<div class="stub-row">
<div style="flex:1"><div class="stub-lbl">Art</div><div class="stub-field"></div></div>
<div style="flex:2"><div class="stub-lbl">Nachname</div><div class="stub-field"></div></div>
</div>
</div>
<!-- Card 3: Stammbaum & Beziehungen — NEW, add form EXPANDED -->
<div class="pe-card">
<!-- Header row -->
<div class="pe-card-hdr">
<div class="pe-sec-lbl" style="margin-bottom:0">Stammbaum &amp; Beziehungen</div>
<div class="pe-card-hdr-right">
<span class="pe-toggle-lbl">Als Familienmitglied</span>
<div class="toggle on"><div class="toggle-thumb"></div></div>
</div>
</div>
<!-- In-tree indicator -->
<div class="intree">
<div class="intree-left">
<div class="intree-dot"></div>
<span class="intree-lbl">Erscheint im Stammbaum</span>
</div>
<span class="intree-link">Ansehen →</span>
</div>
<!-- Direkte Beziehungen -->
<div class="pe-sec-lbl" style="margin-bottom:6px">Direkte Beziehungen</div>
<div class="rel-rows">
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Hans Raddatz</span>
<span class="rel-years">ab 1905</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Lotte Berger</span>
<span class="rel-years">ab 1908</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Werner Raddatz</span>
<span class="rel-years">ab 1912</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill spouse">Ehegatte</span>
<span class="rel-name">Frieda Raddatz</span>
<span class="rel-years">19021944</span>
<span class="rel-del"></span>
</div>
</div>
<!-- Add-rel button (dimmed — form is open) -->
<div class="add-rel-btn" style="opacity:.3;margin-bottom:4px">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 5v14M5 12h14"/></svg>
Beziehung hinzufügen
</div>
<!-- INLINE ADD FORM — expanded -->
<div class="add-form">
<div class="add-form-lbl">Beziehung hinzufügen</div>
<div class="add-form-row">
<div class="add-form-field" style="flex:1.2">
<label>Typ</label>
<select><option>Elternteil von ▾</option></select>
</div>
<div class="add-form-field" style="flex:2">
<label>Person</label>
<input type="text" placeholder="z.B. Oma Frieda…">
</div>
</div>
<div class="add-form-row">
<div class="add-form-field">
<label>Von Jahr</label>
<input type="text" placeholder="z.B. 1920">
</div>
<div class="add-form-field">
<label>Bis Jahr</label>
<input type="text" placeholder="z.B. 1944">
</div>
<div style="display:flex;align-items:flex-end;padding-bottom:0">
<button class="btn-add">+ Hinzufügen</button>
</div>
</div>
</div>
<!-- Derived section — collapsed -->
<div class="derived-hdr">
<div style="display:flex;align-items:center">
<span class="derived-hdr-lbl">Abgeleitete Beziehungen</span>
<span class="derived-hdr-count">5</span>
</div>
<span class="derived-chevron"></span>
</div>
</div>
<!-- Save bar stub -->
<div class="pe-savebar">
<button class="btn-cancel">Abbrechen</button>
<button class="btn-add">Speichern</button>
</div>
</div><!-- /pe-page -->
</div><!-- /chrome -->
<p class="cap">Desktop, light. Toggle is ON → in-tree indicator visible. "Beziehung hinzufügen" form is expanded, showing Typ dropdown, Person typeahead, Von/Bis year inputs, and "+ Hinzufügen" button. Derived section is collapsed with count badge (5).</p>
</div>
<!-- ── DARK ── -->
<div>
<div class="screen-lbl"><span class="lbl-dot" style="background:#1a2a3a"></span>Dark theme · resting state</div>
<div class="chrome dark">
<div class="chrome-bar"><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-url"></div></div>
<div class="app-nav">
<div class="app-logo">Familienarchiv</div>
<div class="app-link">Dokumente</div>
<div class="app-link on">Personen</div>
<div class="app-link">Chronik</div>
<div class="app-link">Admin</div>
<div class="app-nav-r"><div class="app-av">M</div></div>
</div>
<div class="pe-page">
<div style="width:100%;max-width:520px;margin-bottom:8px">
<span style="font-size:7.5px;font-weight:700;color:#a1dcd8;opacity:.5;display:flex;align-items:center;gap:3px">
<svg width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"/></svg>
Zurück
</span>
</div>
<div class="pe-h1">Person bearbeiten</div>
<!-- Card 1 stub dark -->
<div class="stub-card">
<div class="pe-sec-lbl">Angaben zur Person</div>
<div class="stub-segmented">
<div class="stub-seg active"></div>
<div class="stub-seg"></div>
<div class="stub-seg"></div>
<div class="stub-seg"></div>
</div>
<div class="stub-row">
<div style="flex:1"><div class="stub-lbl">Vorname</div><div class="stub-field"></div></div>
<div style="flex:1.5"><div class="stub-lbl">Nachname</div><div class="stub-field"></div></div>
</div>
<div class="stub-field" style="height:24px;opacity:.5"></div>
</div>
<!-- Card 2 stub dark -->
<div class="stub-card" style="padding:10px 14px">
<div class="pe-sec-lbl">Namensverlauf</div>
<div style="font-family:'Tinos',serif;font-size:8px;color:#4E6070;font-style:italic;margin-bottom:8px">Noch keine Namensänderungen erfasst</div>
<div class="stub-row">
<div style="flex:1"><div class="stub-lbl">Art</div><div class="stub-field"></div></div>
<div style="flex:2"><div class="stub-lbl">Nachname</div><div class="stub-field"></div></div>
</div>
</div>
<!-- Card 3 dark — resting -->
<div class="pe-card">
<div class="pe-card-hdr">
<div class="pe-sec-lbl" style="margin-bottom:0">Stammbaum &amp; Beziehungen</div>
<div class="pe-card-hdr-right">
<span class="pe-toggle-lbl">Als Familienmitglied</span>
<div class="toggle on"><div class="toggle-thumb"></div></div>
</div>
</div>
<div class="intree">
<div class="intree-left">
<div class="intree-dot"></div>
<span class="intree-lbl">Erscheint im Stammbaum</span>
</div>
<span class="intree-link">Ansehen →</span>
</div>
<div class="pe-sec-lbl" style="margin-bottom:6px">Direkte Beziehungen</div>
<div class="rel-rows">
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Hans Raddatz</span>
<span class="rel-years">ab 1905</span>
<span class="rel-del" style="color:#4E6070"></span>
</div>
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Lotte Berger</span>
<span class="rel-years">ab 1908</span>
<span class="rel-del" style="color:#4E6070"></span>
</div>
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Werner Raddatz</span>
<span class="rel-years">ab 1912</span>
<span class="rel-del" style="color:#4E6070"></span>
</div>
<div class="rel-row">
<span class="rel-pill spouse">Ehegatte</span>
<span class="rel-name">Frieda Raddatz</span>
<span class="rel-years">19021944</span>
<span class="rel-del" style="color:#4E6070"></span>
</div>
</div>
<div class="add-rel-btn" style="margin-top:8px">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 5v14M5 12h14"/></svg>
Beziehung hinzufügen
</div>
<div class="derived-hdr">
<div style="display:flex;align-items:center">
<span class="derived-hdr-lbl">Abgeleitete Beziehungen</span>
<span class="derived-hdr-count">5</span>
</div>
<span class="derived-chevron"></span>
</div>
</div>
<div class="pe-savebar">
<button class="btn-cancel">Abbrechen</button>
<button class="btn-add">Speichern</button>
</div>
</div>
</div>
<p class="cap">Desktop, dark. Resting state — add form hidden, "+ Beziehung hinzufügen" button visible. Toggle track is mint (#a1dcd8), thumb is navy (#012851). In-tree indicator border shifts to turquoise #00c7b1.</p>
</div>
</div>
</div>
<!-- ══ SECTION 3 — TABLET 768px ═════════════════════════════════════════════ -->
<div class="section">
<div class="sh">
<h2>3 · Tablet (768 px)</h2>
<p>
Narrower viewport — card fills the single center column, paddings tighten. Same component
structure as desktop. Shown at ~50% scale.
</p>
</div>
<div style="max-width:520px;margin-bottom:16px">
<div class="screen-lbl"><span class="lbl-dot" style="background:#A1DCD8;border:1px solid #ccc"></span>Tablet · light · resting state</div>
<div class="chrome narrow">
<div class="chrome-bar"><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-url"></div></div>
<div class="app-nav">
<div class="app-logo">Familienarchiv</div>
<div class="app-link on">Personen</div>
<div class="app-nav-r"><div class="app-av">M</div></div>
</div>
<div class="pe-page">
<div class="pe-h1">Person bearbeiten</div>
<!-- Card 1 stub narrow -->
<div class="stub-card">
<div class="pe-sec-lbl">Angaben zur Person</div>
<div class="stub-segmented"><div class="stub-seg active"></div><div class="stub-seg"></div><div class="stub-seg"></div><div class="stub-seg"></div></div>
<div class="stub-row"><div style="flex:1"><div class="stub-field"></div></div><div style="flex:1"><div class="stub-field"></div></div></div>
<div class="stub-field" style="height:22px;opacity:.5"></div>
</div>
<!-- Card 2 stub narrow -->
<div class="stub-card" style="padding:10px 12px">
<div class="pe-sec-lbl">Namensverlauf</div>
<div style="font-family:'Tinos',serif;font-size:7px;color:#aaa;font-style:italic;margin-bottom:6px">Noch keine Namensänderungen erfasst</div>
<div class="stub-row"><div style="flex:1"><div class="stub-field"></div></div><div style="flex:2"><div class="stub-field"></div></div></div>
</div>
<!-- Card 3 Stammbaum narrow -->
<div class="pe-card">
<div class="pe-card-hdr">
<div class="pe-sec-lbl" style="margin-bottom:0">Stammbaum &amp; Beziehungen</div>
<div class="pe-card-hdr-right">
<span class="pe-toggle-lbl">Als Familienmitglied</span>
<div class="toggle on"><div class="toggle-thumb"></div></div>
</div>
</div>
<div class="intree">
<div class="intree-left">
<div class="intree-dot"></div>
<span class="intree-lbl">Erscheint im Stammbaum</span>
</div>
<span class="intree-link">Ansehen →</span>
</div>
<div class="pe-sec-lbl" style="margin-bottom:6px">Direkte Beziehungen</div>
<div class="rel-rows">
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Hans Raddatz</span>
<span class="rel-years">ab 1905</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill spouse">Ehegatte</span>
<span class="rel-name">Frieda Raddatz</span>
<span class="rel-years">19021944</span>
<span class="rel-del"></span>
</div>
</div>
<div class="add-rel-btn" style="margin-top:8px">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 5v14M5 12h14"/></svg>
Beziehung hinzufügen
</div>
<div class="derived-hdr">
<div style="display:flex;align-items:center">
<span class="derived-hdr-lbl">Abgeleitete Beziehungen</span>
<span class="derived-hdr-count">5</span>
</div>
<span class="derived-chevron"></span>
</div>
</div>
<div class="pe-savebar">
<button class="btn-cancel">Abbrechen</button>
<button class="btn-add">Speichern</button>
</div>
</div>
</div>
<p class="cap">Tablet. Card fills single column. Two relationship rows shown (trimmed for space). All controls remain the same size — no stacking yet at 768 px.</p>
</div>
</div>
<!-- ══ SECTION 4 — MOBILE 375px ═════════════════════════════════════════════ -->
<div class="section">
<div class="sh">
<h2>4 · Mobile (375 px)</h2>
<p>
Phone viewport. Card is full-width. Add-form fields stack vertically (single column).
Pill labels truncate to first word on very small screens if needed. Shown at ~65% scale.
</p>
</div>
<div style="max-width:300px;margin-bottom:16px">
<div class="screen-lbl"><span class="lbl-dot" style="background:#A1DCD8;border:1px solid #ccc"></span>Mobile 375px · light · add form expanded</div>
<div class="chrome mobile">
<div class="chrome-bar"><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-url"></div></div>
<div class="app-nav">
<div class="app-logo">Familienarchiv</div>
<div class="app-nav-r"><div class="app-av">M</div></div>
</div>
<div class="pe-page">
<div class="pe-h1">Person bearbeiten</div>
<!-- Card 1 mobile stub -->
<div class="stub-card" style="padding:10px;margin-bottom:8px">
<div class="pe-sec-lbl">Angaben zur Person</div>
<div class="stub-field" style="margin-bottom:5px"></div>
<div class="stub-field" style="margin-bottom:5px"></div>
<div class="stub-field" style="height:20px;opacity:.4"></div>
</div>
<!-- Card 3 mobile — Stammbaum with expanded form -->
<div class="pe-card" style="padding:10px">
<!-- Header — toggle label may wrap on very small screens -->
<div class="pe-card-hdr" style="flex-wrap:wrap;gap:6px">
<div class="pe-sec-lbl" style="margin-bottom:0">Stammbaum &amp; Beziehungen</div>
<div class="pe-card-hdr-right">
<span class="pe-toggle-lbl">Als Familienmitglied</span>
<div class="toggle on"><div class="toggle-thumb"></div></div>
</div>
</div>
<div class="intree" style="margin-top:4px">
<div class="intree-left">
<div class="intree-dot"></div>
<span class="intree-lbl">Erscheint im Stammbaum</span>
</div>
<span class="intree-link">Ansehen →</span>
</div>
<div class="pe-sec-lbl" style="margin-bottom:5px;margin-top:10px">Direkte Beziehungen</div>
<div class="rel-rows">
<div class="rel-row">
<span class="rel-pill" style="font-size:6px;padding:1px 5px">Elternteil von</span>
<span class="rel-name" style="font-size:9px">Hans Raddatz</span>
<span class="rel-years" style="font-size:7px">ab 1905</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill spouse" style="font-size:6px;padding:1px 5px">Ehegatte</span>
<span class="rel-name" style="font-size:9px">Frieda Raddatz</span>
<span class="rel-years" style="font-size:7px">19021944</span>
<span class="rel-del"></span>
</div>
</div>
<!-- Add form stacked (mobile) -->
<div class="add-form" style="margin-top:8px">
<div class="add-form-lbl">Beziehung hinzufügen</div>
<!-- Stacked fields on mobile -->
<div style="display:flex;flex-direction:column;gap:6px;margin-bottom:6px">
<div class="add-form-field">
<label>Typ</label>
<select><option>Elternteil von ▾</option></select>
</div>
<div class="add-form-field">
<label>Person</label>
<input type="text" placeholder="z.B. Oma Frieda…">
</div>
<div style="display:flex;gap:6px">
<div class="add-form-field">
<label>Von Jahr</label>
<input type="text" placeholder="z.B. 1920">
</div>
<div class="add-form-field">
<label>Bis Jahr</label>
<input type="text" placeholder="z.B. 1944">
</div>
</div>
</div>
<div class="add-form-actions">
<button class="btn-cancel">Abbrechen</button>
<button class="btn-add">+ Hinzufügen</button>
</div>
</div>
<div class="derived-hdr">
<div style="display:flex;align-items:center">
<span class="derived-hdr-lbl">Abgeleitete Beziehungen</span>
<span class="derived-hdr-count">5</span>
</div>
<span class="derived-chevron"></span>
</div>
</div>
<div class="pe-savebar" style="padding:8px 10px">
<button class="btn-cancel">Abbrechen</button>
<button class="btn-add">Speichern</button>
</div>
</div>
</div>
<p class="cap">Mobile. "Typ" and "Person" fields are stacked vertically. Year inputs remain side-by-side. Pill labels shrink to 6 px. Card fills the full width with 7 px side padding.</p>
</div>
</div>
<!-- ══ SECTION 5 — DERIVED RELATIONSHIPS EXPANDED ═══════════════════════════ -->
<div class="section">
<div class="sh">
<h2>5 · Derived relationships — expanded state</h2>
<p>
Clicking the "Abgeleitete Beziehungen" row expands the section. Items are computed
server-side from the direct-relationship graph — the frontend renders them read-only.
Grey pills and muted italic text for entries that cannot be resolved.
</p>
</div>
<div style="max-width:560px;margin-bottom:16px">
<div class="screen-lbl"><span class="lbl-dot" style="background:#A1DCD8;border:1px solid #ccc"></span>Derived relationships — expanded · light</div>
<div class="chrome">
<div class="chrome-bar"><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-dot"></div><div class="chrome-url"></div></div>
<div class="app-nav">
<div class="app-logo">Familienarchiv</div>
<div class="app-link on">Personen</div>
<div class="app-nav-r"><div class="app-av">M</div></div>
</div>
<div class="pe-page">
<div class="pe-card" style="max-width:480px">
<div class="pe-card-hdr">
<div class="pe-sec-lbl" style="margin-bottom:0">Stammbaum &amp; Beziehungen</div>
<div class="pe-card-hdr-right">
<span class="pe-toggle-lbl">Als Familienmitglied</span>
<div class="toggle on"><div class="toggle-thumb"></div></div>
</div>
</div>
<div class="intree">
<div class="intree-left">
<div class="intree-dot"></div>
<span class="intree-lbl">Erscheint im Stammbaum</span>
</div>
<span class="intree-link">Ansehen →</span>
</div>
<div class="pe-sec-lbl" style="margin-bottom:6px">Direkte Beziehungen</div>
<div class="rel-rows">
<div class="rel-row">
<span class="rel-pill">Elternteil von</span>
<span class="rel-name">Hans Raddatz</span>
<span class="rel-years">ab 1905</span>
<span class="rel-del"></span>
</div>
<div class="rel-row">
<span class="rel-pill spouse">Ehegatte</span>
<span class="rel-name">Frieda Raddatz</span>
<span class="rel-years">19021944</span>
<span class="rel-del"></span>
</div>
</div>
<div class="add-rel-btn" style="margin-top:8px;margin-bottom:4px">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 5v14M5 12h14"/></svg>
Beziehung hinzufügen
</div>
<!-- Derived section — EXPANDED (chevron up) -->
<div class="derived-hdr">
<div style="display:flex;align-items:center">
<span class="derived-hdr-lbl">Abgeleitete Beziehungen</span>
<span class="derived-hdr-count">5</span>
</div>
<span class="derived-chevron"></span>
</div>
<div class="derived-rows">
<div class="derived-row">
<span class="derived-pill">Kind von</span>
<span class="derived-name">Heinrich Raddatz</span>
</div>
<div class="derived-row">
<span class="derived-pill">Kind von</span>
<span class="derived-name">Maria Raddatz</span>
</div>
<div class="derived-row">
<span class="derived-pill">Geschwister von</span>
<span class="derived-name">Ernst Raddatz</span>
</div>
<div class="derived-row">
<span class="derived-pill">Schwiegereltern</span>
<span class="derived-note">Eltern von Frieda, nicht im Archiv</span>
</div>
<div class="derived-row">
<span class="derived-pill">Onkel/Tante von</span>
<span class="derived-note">— keine Geschwisterkinder erfasst</span>
</div>
</div>
</div>
</div>
</div>
<p class="cap">Derived section expanded. Chevron rotates to ▴. Items use grey pills and Tinos italic for unresolvable entries. Section is read-only — no edit or delete controls. Computed by the backend graph traversal.</p>
</div>
</div>
<!-- ══ SECTION 6 — IMPLEMENTATION REFERENCE ══════════════════════════════════ -->
<div class="section">
<div class="sh">
<h2>6 · Implementation reference</h2>
</div>
<div class="rules">
<table>
<thead>
<tr>
<th>Element</th>
<th>Tailwind / CSS</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Card wrapper</td>
<td><code>bg-white border border-line rounded-sm p-6</code></td>
<td>Matches existing Angaben and Namensverlauf cards on same page</td>
</tr>
<tr>
<td>Section label</td>
<td><code>text-xs font-bold uppercase tracking-widest text-gray-400 mb-4</code></td>
<td>Montserrat 9px 700; identical to all other cards on the page</td>
</tr>
<tr>
<td>Card header row</td>
<td><code>flex items-center justify-between mb-3</code></td>
<td>Section label on left; toggle label + toggle on right</td>
</tr>
<tr>
<td>Toggle track ON</td>
<td><code>w-[38px] h-5 rounded-full bg-primary transition-colors</code></td>
<td>dark: <code>bg-accent</code> (#a1dcd8)</td>
</tr>
<tr>
<td>Toggle track OFF</td>
<td><code>w-[38px] h-5 rounded-full bg-line</code></td>
<td><code>bg-line</code> = #e4e2d7</td>
</tr>
<tr>
<td>Toggle thumb</td>
<td><code>absolute top-0.5 w-4 h-4 rounded-full bg-white transition-all</code></td>
<td>ON: <code>left-[19px]</code>; OFF: <code>left-0.5</code>; dark ON thumb: <code>bg-primary</code></td>
</tr>
<tr>
<td>In-tree banner</td>
<td><code>flex items-center justify-between px-2.5 py-1.5 bg-accent/10 border border-accent rounded-sm mb-3</code></td>
<td>Hidden when toggle is OFF. dark: <code>bg-[rgba(0,199,177,.08)] border-[#00c7b1]</code></td>
</tr>
<tr>
<td>In-tree dot</td>
<td><code>w-[7px] h-[7px] rounded-full bg-primary shrink-0</code></td>
<td>dark: <code>bg-[#00c7b1]</code></td>
</tr>
<tr>
<td>In-tree label</td>
<td><code>text-[9px] font-bold uppercase tracking-widest text-primary</code></td>
<td>dark: <code>text-[#00c7b1]</code></td>
</tr>
<tr>
<td>In-tree link</td>
<td><code>text-[9px] font-semibold text-primary/60</code></td>
<td>Navigates to <code>/stammbaum?focus={personId}</code></td>
</tr>
<tr>
<td>Rel row wrapper</td>
<td><code>flex items-center gap-2 py-1.5 border-b border-muted last:border-b-0</code></td>
<td>Padding 7px top/bottom; bottom border except last row</td>
</tr>
<tr>
<td>Direct rel pill</td>
<td><code>rounded-full border border-accent bg-accent/20 px-2 py-0.5 text-[9px] font-bold uppercase tracking-wider text-ink shrink-0</code></td>
<td>dark: <code>bg-[rgba(0,199,177,.12)] border-[#00c7b1] text-sand</code></td>
</tr>
<tr>
<td>Rel person name</td>
<td><code>font-serif text-[13px] text-ink flex-1 min-w-0 truncate</code></td>
<td>Tinos; truncate prevents overflow on narrow viewports</td>
</tr>
<tr>
<td>Rel year range</td>
<td><code>font-sans text-[10px] text-ink-3 whitespace-nowrap</code></td>
<td>Format: <code>ab {year}</code> or <code>{from}{to}</code></td>
</tr>
<tr>
<td>Delete button</td>
<td><code>text-ink-3 hover:text-danger p-0.5 ml-auto shrink-0</code></td>
<td>✕ icon button; hover color <code>#c0392b</code>; min touch 44px via padding wrapper</td>
</tr>
<tr>
<td>Add-rel quiet button</td>
<td><code>flex items-center gap-1 text-[8px] font-bold text-primary/60 hover:text-primary/90 mt-1</code></td>
<td>+ icon (heroicons plus-mini); hidden when add form is open</td>
</tr>
<tr>
<td>Add-form card</td>
<td><code>mt-3 bg-muted border border-line rounded-sm p-3.5</code></td>
<td><code>bg-muted</code> = #f5f4ef; dark: <code>bg-[#011a30] border-[#0d3358]</code></td>
</tr>
<tr>
<td>Type select</td>
<td><code>w-full border border-line rounded-sm px-2.5 py-2 text-xs font-sans text-ink bg-white</code></td>
<td>Options: Elternteil von / Ehegatte / Geschwister von / Kollege / Freund / Arbeitgeber / Arzt / Nachbar / Sonstiges</td>
</tr>
<tr>
<td>Person input</td>
<td><code>w-full border border-line rounded-sm px-2.5 py-2 font-serif text-sm text-ink bg-white</code></td>
<td>Drives <code>PersonTypeahead</code> component; placeholder "z.B. Oma Frieda…"</td>
</tr>
<tr>
<td>Year inputs</td>
<td><code>flex-1 border border-line rounded-sm px-2.5 py-2 font-serif text-sm text-ink bg-white</code></td>
<td>Side-by-side via <code>flex gap-2</code>; on mobile remain side-by-side (they're short)</td>
</tr>
<tr>
<td>+ Hinzufügen button</td>
<td><code>bg-primary text-white px-3.5 py-2 text-[10px] font-bold uppercase tracking-wider rounded-sm shrink-0</code></td>
<td>dark: <code>bg-accent text-primary</code></td>
</tr>
<tr>
<td>Cancel button</td>
<td><code>bg-white border border-line rounded-sm px-3 py-1.5 text-[10px] font-bold text-ink-2</code></td>
<td>Collapses add form without saving</td>
</tr>
<tr>
<td>Derived section header</td>
<td><code>flex items-center justify-between py-2 border-t border-muted cursor-pointer mt-2.5 select-none</code></td>
<td>Click toggles <code>derivedExpanded</code> boolean in component state</td>
</tr>
<tr>
<td>Derived count badge</td>
<td><code>ml-1.5 rounded-full border border-line bg-muted px-1.5 py-0 text-[7px] font-bold text-ink-3</code></td>
<td>Shows total inferred relationship count from backend</td>
</tr>
<tr>
<td>Derived rel pill</td>
<td><code>rounded-full border border-line bg-muted px-2 py-0.5 text-[9px] font-bold uppercase tracking-wider text-ink-2 shrink-0</code></td>
<td>Grey, no accent border; read-only only</td>
</tr>
<tr>
<td>Derived rel name</td>
<td><code>font-serif text-[13px] text-ink-3</code></td>
<td>Muted; unresolvable entries use <code>italic text-ink-4</code></td>
</tr>
<tr>
<td>Mobile form stacking</td>
<td><code>sm:flex-row flex-col</code> on add-form top row</td>
<td>Below 640 px Typ and Person stack; year inputs stay side-by-side</td>
</tr>
</tbody>
</table>
</div>
</div>
</div><!-- /doc -->
</body>
</html>