diff --git a/frontend/src/lib/person/genealogy/StammbaumConnectors.svelte b/frontend/src/lib/person/genealogy/StammbaumConnectors.svelte
new file mode 100644
index 00000000..0a647b70
--- /dev/null
+++ b/frontend/src/lib/person/genealogy/StammbaumConnectors.svelte
@@ -0,0 +1,189 @@
+
+
+
+{#each parentLinks.shared as group (group.key)}
+ {@const aCenter = nodeCenter(group.parentA)}
+ {@const bCenter = nodeCenter(group.parentB)}
+ {@const childCenters = group.childIds
+ .map((id) => nodeCenter(id))
+ .filter((c): c is { x: number; y: number } => c !== null)}
+ {#if aCenter && bCenter && childCenters.length > 0}
+ {@const midX = (aCenter.x + bCenter.x) / 2}
+ {@const parentBottomY = aCenter.y + NODE_H / 2}
+ {@const childTopY = childCenters[0].y - NODE_H / 2}
+ {@const barY = (parentBottomY + childTopY) / 2}
+ {@const xs = childCenters.map((c) => c.x)}
+ {@const minX = Math.min(midX, ...xs)}
+ {@const maxX = Math.max(midX, ...xs)}
+
+ {#if minX !== maxX}
+
+ {/if}
+ {#each childCenters as cc, i (group.childIds[i])}
+
+ {/each}
+ {/if}
+{/each}
+
+
+{#each parentLinks.single as link (link.key)}
+ {@const parentCenter = nodeCenter(link.parentId)}
+ {@const childCenter = nodeCenter(link.childId)}
+ {#if parentCenter && childCenter}
+ {@const parentBottomY = parentCenter.y + NODE_H / 2}
+ {@const childTopY = childCenter.y - NODE_H / 2}
+ {@const barY = (parentBottomY + childTopY) / 2}
+
+ {#if parentCenter.x !== childCenter.x}
+
+ {/if}
+
+ {/if}
+{/each}
+
+
+{#each spouseEdges as e (e.id)}
+ {@const aCenter = nodeCenter(e.personId)}
+ {@const bCenter = nodeCenter(e.relatedPersonId)}
+ {#if aCenter && bCenter}
+
+
+ {/if}
+{/each}
diff --git a/frontend/src/lib/person/genealogy/StammbaumNode.svelte b/frontend/src/lib/person/genealogy/StammbaumNode.svelte
new file mode 100644
index 00000000..f2877994
--- /dev/null
+++ b/frontend/src/lib/person/genealogy/StammbaumNode.svelte
@@ -0,0 +1,90 @@
+
+
+ onSelect(node.id)}
+ onkeydown={handleKey}
+ onfocus={() => (focused = true)}
+ onblur={() => (focused = false)}
+ class="cursor-pointer focus:outline-none"
+>
+ {#if focused}
+
+ {/if}
+
+ {#if selected}
+
+ {/if}
+
+ {node.displayName}
+
+ {#if node.birthYear || node.deathYear}
+
+ {node.birthYear ?? '?'}–{node.deathYear ?? ''}
+
+ {/if}
+
diff --git a/frontend/src/lib/person/genealogy/StammbaumTree.svelte b/frontend/src/lib/person/genealogy/StammbaumTree.svelte
index 711dc6f2..7d6caab8 100644
--- a/frontend/src/lib/person/genealogy/StammbaumTree.svelte
+++ b/frontend/src/lib/person/genealogy/StammbaumTree.svelte
@@ -1,6 +1,6 @@
@@ -364,180 +288,18 @@ const parentLinks = $derived.by(() => {
{/each}
{/if}
-
- {#each parentLinks.shared as group (group.key)}
- {@const aCenter = nodeCenter(group.parentA)}
- {@const bCenter = nodeCenter(group.parentB)}
- {@const childCenters = group.childIds
- .map((id) => nodeCenter(id))
- .filter((c): c is { x: number; y: number } => c !== null)}
- {#if aCenter && bCenter && childCenters.length > 0}
- {@const midX = (aCenter.x + bCenter.x) / 2}
- {@const parentBottomY = aCenter.y + NODE_H / 2}
- {@const childTopY = childCenters[0].y - NODE_H / 2}
- {@const barY = (parentBottomY + childTopY) / 2}
- {@const xs = childCenters.map((c) => c.x)}
- {@const minX = Math.min(midX, ...xs)}
- {@const maxX = Math.max(midX, ...xs)}
-
- {#if minX !== maxX}
-
- {/if}
- {#each childCenters as cc, i (group.childIds[i])}
-
- {/each}
- {/if}
- {/each}
-
-
- {#each parentLinks.single as link (link.key)}
- {@const parentCenter = nodeCenter(link.parentId)}
- {@const childCenter = nodeCenter(link.childId)}
- {#if parentCenter && childCenter}
- {@const parentBottomY = parentCenter.y + NODE_H / 2}
- {@const childTopY = childCenter.y - NODE_H / 2}
- {@const barY = (parentBottomY + childTopY) / 2}
-
- {#if parentCenter.x !== childCenter.x}
-
- {/if}
-
- {/if}
- {/each}
-
-
- {#each spouseEdges as e (e.id)}
- {@const aCenter = nodeCenter(e.personId)}
- {@const bCenter = nodeCenter(e.relatedPersonId)}
- {#if aCenter && bCenter}
-
-
- {/if}
- {/each}
+
{#each nodes as node (node.id)}
{@const pos = layout.positions.get(node.id)}
{#if pos}
- {@const isSelected = selectedId === node.id}
- {@const isFocused = focusedId === node.id}
- onSelect(node.id)}
- onkeydown={(e) => handleNodeKey(e, node.id)}
- onfocus={() => (focusedId = node.id)}
- onblur={() => (focusedId = null)}
- class="cursor-pointer focus:outline-none"
- >
- {#if isFocused}
-
- {/if}
-
- {#if isSelected}
-
- {/if}
-
- {node.displayName}
-
- {#if node.birthYear || node.deathYear}
-
- {node.birthYear ?? '?'}–{node.deathYear ?? ''}
-
- {/if}
-
+
{/if}
{/each}