From a60c466d8221052da59c085633777df6a416f248 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Mon, 24 Aug 2026 14:20:26 +0200 Subject: [PATCH] fix: Linie zum einzigen Kind riss ab (D29-Nachtrag 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Stiel aus dem Elternknoten sitzt bei 50 % der Gruppe, der Stiel zum Kind bei `--stem-x` (der gemessenen Knotenmitte, Nachtrag 2). Für `li:only-child` ist die waagerechte Sammelleiste abgeschaltet — richtig, solange beide zusammenfallen, und das tun sie nur, solange der Knoten in seiner Zelle zentriert steht. Bei einer Treppe darunter sind es gemessen 8,5 px Versatz, bei einem `li.has-or` als einzigem Kind 41,8 px. Jetzt verbindet ein Leiterstück genau zwischen 50 % und `--stem-x` die beiden — dieselbe L-Form wie bei einem äußeren Kind einer größeren Gruppe; ohne `--stem-x` ist es 0 px breit und unsichtbar. Dabei aufgefallen: `:only-child::after{border-left}` stand vor `:last-child::after{border:0 none}` und war bei gleicher Spezifität seit jeher wirkungslos. Der ganze Block steht nun dahinter. Kein Rückschritt von D61 — mit ausgeschaltetem Pfad derselbe Versatz; die Zugabe steht seither nur in voller Farbe statt blass da. Der Grafikexport war nie betroffen (die Leiste schließt dort die Elternmitte ein). Co-Authored-By: Claude Opus 5 --- docs/CHANGELOG.md | 1 + docs/DECISIONS.md | 51 ++++++++++++++++++++++++++++++++++++++++++ frontend/CLAUDE.md | 7 ++++++ frontend/src/style.css | 25 ++++++++++++++++++--- 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8026ef4..f0aa761 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -19,6 +19,7 @@ reverse. ## 2026-08-24 +- Fix: the line to an only child was torn where the child does not sit centred in its cell - An optional node (`+`) joins the cheapest path while it is being worked on — started work is the open front - Fix: a started alternative lost its `|`/`=` group to an untouched cheaper one, although the choice was already made - A node written as an id alone (`- #US-123`) is now titled by that id, instead of being ignored diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 70d0610..fe002f8 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -1304,6 +1304,57 @@ Geprüft wurde im Browser — auch der Moduswechsel hin und zurück, mehrfach: D Gruppe entsteht und löst sich rückstandsfrei auf, Knotenzahl und Dokumentordnung bleiben in allen drei Modi gleich. +**Nachtrag 4 — beim einzigen Kind riss die Linie ab: `--stem-x` ohne +Sammelleiste.** Gemeldet als „die Linie zwischen `#fe` und `#fe.rel` ist +abgerissen" an einem Baum mit genau einem Zerlegungsknoten und einer Treppe +darunter. Nachgemessen sind es zwei Stiele an **verschiedenen** Stellen: + +- `ul.and::before` — der Stiel aus dem Elternknoten — sitzt bei **50 % der + Gruppe** (gemessen `left: 136,2px`); +- der Stiel zum Kind sitzt bei **`--stem-x`** (gemessen `127,7px`), also auf der + Knotenmitte, die Nachtrag 2 eigens misst. + +Dazwischen lag nichts: Für `li:only-child` wird die waagerechte Sammelleiste +ausdrücklich abgeschaltet (`border-top:none`) — richtig, solange beide Stiele +zusammenfallen, und das tun sie, solange der Knoten in seiner Zelle **zentriert** +steht. Genau diese Voraussetzung hebt Nachtrag 2 auf, und der `:only-child`-Fall +ist dabei übersehen worden: Er stammt aus der Zeit, als es `--stem-x` noch nicht +gab. + +**Es ist nicht auf die Treppe beschränkt** — an einem `li.has-or` als einzigem +Kind (Knoten linksbündig, Zelle so breit wie der any-of-Teilbaum) sind es +gemessen **41,8 px** Versatz. Dass es bisher niemandem auffiel, liegt daran, +dass der Fall selten ist: Ein Elternknoten hat meist mehrere Kinder, und dann +trägt die Leiste. Aufgefallen ist er jetzt, weil eine angefangene Zugabe seit +D61 in voller Farbe dasteht statt blass. + +**Behoben mit einem kurzen Leiterstück genau zwischen den beiden** — +`left:min(50%, var(--stem-x))` bis `right:calc(100% - max(50%, var(--stem-x)))`, +darunter der Abgang bei `--stem-x`. Also dieselbe L-Form, mit der ein äußeres +Kind einer größeren Gruppe angeschlossen ist; ohne `--stem-x` ist das Stück null +Pixel breit und damit unsichtbar (nachgemessen: `0.0`, gerade Linie wie bisher). + +Erwogen und verworfen: **den Stiel des Elternknotens auf `--stem-x` zu ziehen.** +Eine Zeile weniger, aber er träte dann nicht mehr aus der Mitte des +Elternknotens aus — bei 8 px unauffällig, bei den gemessenen 42 px nicht mehr, +und bei einem schmalen Elternknoten käme er neben ihm heraus. + +**Dabei aufgefallen: `ul.and>li:only-child::after{border-left:…}` war seit jeher +wirkungslos.** Die Regel stand **vor** `ul.and>li:last-child::after{border:0 +none}`, und bei gleicher Spezifität gewinnt die spätere — ein einziges Kind ist +auch das letzte. Gezeichnet wurde der Abgang stattdessen von der +`border-right`-Kante des `::before` (aus `:last-child::before`), 16 px lang bei +14 px Innenabstand, also 2 px über den Knoten hinaus. Der ganze `:only-child`- +Block steht jetzt **hinter** den first/last-Regeln, und die Absicht der Zeile +gilt endlich. + +**Der Grafikexport hatte den Fehler nie:** `diagramToSvg()` spannt die +Sammelleiste über `kids.map(cx).concat(p.cx)` — die Elternmitte ist immer +Teil der Strecke. Betroffen war allein das CSS. Nicht durch Tests gedeckt (wie +der Rest dieser Geometrie), geprüft im Browser an allen drei Fällen: einziges +Kind mit Versatz (Stück 41,8 px breit, Linie durchgehend), gewöhnliches +einziges Kind (0 px, gerade), zwei Kinder (unverändert). + ## D30 — `[x]` → `[^]` per Beförderungs-Commit vor dem Deploy Der mitgelieferte Werkbaum-Plan (D27) behauptete `[^]` („in Produktion") für Funktionen, die nur auf der automatisch deployten Pages-Instanz lagen, nicht auf diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md index bc996b4..c419022 100644 --- a/frontend/CLAUDE.md +++ b/frontend/CLAUDE.md @@ -458,6 +458,13 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der der any-of-Teilbaum. `alignStems()` misst deshalb nach jedem `render()` (und in `applyLayout`) die Knotenmitte und setzt `--stem-x`; Fallback im CSS ist `50%`. Messwerte durch `zoom` zurückrechnen, sonst stimmt es nur bei 100 %. + **Beim einzigen Kind trägt keine Sammelleiste** (`:only-child` schaltet sie + ab): Der Stiel aus dem Elternknoten sitzt bei 50 % der Gruppe, der zum Kind + bei `--stem-x` — fallen die auseinander, riss die Linie ab (D29-Nachtrag 4). + Die `:only-child`-Regeln ziehen deshalb ein Leiterstück zwischen beide und + müssen **hinter** den first/last-Regeln stehen: Ein einziges Kind ist auch + das letzte, und bei gleicher Spezifität gewinnt die spätere Regel — genau + daran war `:only-child::after` jahrelang wirkungslos. - Kleiner Bildschirm: `body.mobile` (per `matchMedia`, ≤ 640 px) zeigt **genau einen** Bereich — `body.pane-diagram` bzw. `body.pane-text`, umgeschaltet über je einen festen Knopf pro Titelzeile (`#paneToText`/`#paneToDiagram`, diff --git a/frontend/src/style.css b/frontend/src/style.css index fd06af5..b30f2e3 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -1021,13 +1021,32 @@ border-top:2px solid var(--line);height:16px; } ul.and>li::after{left:var(--stem-x, 50%);right:0;border-left:2px solid var(--line)} - ul.and>li:only-child{padding-top:14px} - ul.and>li:only-child::before,ul.and>li:only-child::after{border-top:none} - ul.and>li:only-child::after{border-left:2px solid var(--line);height:14px} ul.and>li:first-child::before, ul.and>li:last-child::after{border:0 none} ul.and>li:last-child::before{border-right:2px solid var(--line);border-radius:0 6px 0 0} ul.and>li:first-child::after{border-radius:6px 0 0 0} + /* Einziges Kind: Normalerweise fallen der Stiel aus dem Elternknoten + (`ul.and::before`, 50 % der Gruppe) und der Stiel zum Kind (`--stem-x`) + zusammen — eine gerade Linie, keine Leiste nötig. Steht der Knoten aber + nicht mittig in seiner Zelle (`li.has-or`, Treppe — dort misst + `alignStems()` die Knotenmitte, D29-Nachtrag 2), liegen die beiden + auseinander, und ohne Geschwister gibt es keine Sammelleiste, die sie + verbände: die Linie riss ab (gemessen: 8,5 px). Deshalb hier ein kurzes + Leiterstück genau zwischen den beiden — dieselbe L-Form, mit der ein + äußeres Kind einer größeren Gruppe angeschlossen ist. Ohne `--stem-x` ist + es null Pixel breit und damit unsichtbar. Diese Regeln müssen NACH den + first/last-Regeln stehen: `li:only-child` ist beides, und bei gleicher + Spezifität gewinnt die spätere. */ + ul.and>li:only-child{padding-top:14px} + ul.and>li:only-child::before{ + border:0 none;border-top:2px solid var(--line);border-radius:0;height:14px; + left:min(50%, var(--stem-x, 50%)); + right:calc(100% - max(50%, var(--stem-x, 50%))); + } + ul.and>li:only-child::after{ + border:0 none;border-left:2px solid var(--line);border-radius:0;height:14px; + left:var(--stem-x, 50%);right:0; + } /* --- ANY OF: durchgehend gestrichelte graue Linien (Haupt- + Abzweige) --- */ li.has-or{align-items:flex-start}