diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 2d38038..41a4aa7 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -2009,6 +2009,11 @@ gekrümmten Ebene und begegnen den Rahmenkanten nie. Die **Hervorhebung** (fokussierter Knoten) bleibt durchgezogen in Tinte: Sie ist ausdrücklich angefordert und soll sich nach vorn drängen. Export identisch nachgezogen. +Zweiter Schritt derselben Rückmeldung: Auch die **Pfeilspitze** ist jetzt +**offen** (ein Winkel aus zwei dünnen grauen Strichen) statt eines gefüllten +Dreiecks — das Dreieck stach als einziger satter Fleck aus der gepunkteten +Linie heraus. Die Hervorhebung bekommt denselben Winkel in Tinte. + ## D42 — Closure-Pfad: erschöpfend über die gekoppelten Gruppen, gierig nur benannt Die letzte Baustelle aus D34: Mit Abhängigkeiten zählt der günstigste Pfad nicht mehr den gewählten Teilbaum, sondern die **Hülle** — jeder nötige Knoten diff --git a/docs/SPEC.md b/docs/SPEC.md index f0be00b..e9a5793 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -643,9 +643,9 @@ Abhängigkeiten werden als **optisch sekundäre** Kanten gezeichnet: dünn, blassgrau (`#6B7A8C`), **gepunktet** und **geschwungen** — Punktierung und Krümmung unterscheiden sie doppelt von den Baumlinien (durchgezogen bzw. gestrichelt, immer orthogonal) und halten sie zurückhaltend — auf einer -eigenen Zeichenebene **hinter** den Knoten, mit einer kleinen **Pfeilspitze -auf das Gebrauchte** („braucht“-Richtung). Der Baum trägt weiterhin die -Hauptaussage. +eigenen Zeichenebene **hinter** den Knoten, mit einer kleinen **offenen +Pfeilspitze auf das Gebrauchte** („braucht“-Richtung; ein Winkel aus zwei +Strichen, kein gefülltes Dreieck). Der Baum trägt weiterhin die Hauptaussage. - Die Kanten des **ausgewählten** Knotens — Tastaturfokus im Diagramm, sonst der Knoten der Cursor-Zeile — liegen hervorgehoben in Tinte auf einer diff --git a/frontend/src/app.js b/frontend/src/app.js index 968d584..d98d207 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -336,13 +336,15 @@ function depCurve(a, b){ return {d:`M${p1.x.toFixed(1)},${p1.y.toFixed(1)} Q${ctrl.x.toFixed(1)},${ctrl.y.toFixed(1)} ${p2.x.toFixed(1)},${p2.y.toFixed(1)}`, end:p2, ctrl}; } +/* Offene Pfeilspitze (Winkel aus zwei Strichen, D41-Nachtrag): ein gefülltes + Dreieck stach als einziger satter Fleck aus der gepunkteten Linie heraus. */ function depArrow(end, from){ const dx = end.x - from.x, dy = end.y - from.y; const l = Math.hypot(dx, dy) || 1; const ux = dx/l, uy = dy/l, s = 5; const a = {x: end.x - ux*s*1.8 - uy*s, y: end.y - uy*s*1.8 + ux*s}; const b = {x: end.x - ux*s*1.8 + uy*s, y: end.y - uy*s*1.8 - ux*s}; - return `M${end.x.toFixed(1)},${end.y.toFixed(1)} L${a.x.toFixed(1)},${a.y.toFixed(1)} L${b.x.toFixed(1)},${b.y.toFixed(1)} Z`; + return `M${a.x.toFixed(1)},${a.y.toFixed(1)} L${end.x.toFixed(1)},${end.y.toFixed(1)} L${b.x.toFixed(1)},${b.y.toFixed(1)}`; } /* „Ausgewählt" heißt: Tastaturfokus im Diagramm, sonst der Knoten der Cursor-Zeile (D25) — beide Lesarten von „ich schaue auf diesen Knoten". */ @@ -495,7 +497,7 @@ function diagramToSvg(){ depEdges().forEach(([from, to]) => { const c = depCurve(R(from), R(to)); parts.push(``); - parts.push(``); + parts.push(``); }); /* 1b) Günstigster-Pfad: kräftige Linie hinter den Knoten */ diff --git a/frontend/src/style.css b/frontend/src/style.css index a06be3d..f07f24b 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -710,9 +710,11 @@ .dep-overlay{position:absolute;left:0;top:0;overflow:visible;pointer-events:none} .dep-edge{fill:none;stroke:var(--muted);stroke-width:1.5;opacity:.4; stroke-linecap:round;stroke-dasharray:.1 5} - .dep-arrow{fill:var(--muted);opacity:.4} + /* Offene Pfeilspitze — grau und dünn wie die Linie, kein gefülltes Dreieck. */ + .dep-arrow{fill:none;stroke:var(--muted);stroke-width:1.5;opacity:.4; + stroke-linecap:round;stroke-linejoin:round} .dep-edge.hl{stroke:var(--line);stroke-width:2;opacity:.9;stroke-dasharray:none} - .dep-arrow.hl{fill:var(--line);opacity:.9} + .dep-arrow.hl{stroke:var(--line);stroke-width:2;opacity:.9} .cheap-path{fill:none;stroke:var(--or);stroke-width:2.5;stroke-linecap:round; stroke-dasharray:8 6;opacity:.9} .cheap-path.faint{opacity:.2} diff --git a/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json b/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json new file mode 100644 index 0000000..f8f1854 --- /dev/null +++ b/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json @@ -0,0 +1 @@ +{"version":"4.1.11","results":[[":frontend/tests/render.test.js",{"duration":98.47688799999997,"failed":false}],[":frontend/tests/focusmark.test.js",{"duration":35.79027499999995,"failed":false}],[":frontend/tests/fold.test.js",{"duration":41.154863999999975,"failed":false}],[":frontend/tests/optional.test.js",{"duration":35.42018200000001,"failed":false}],[":frontend/tests/parser.test.js",{"duration":33.422897999999975,"failed":false}],[":frontend/tests/xor.test.js",{"duration":52.44134100000002,"failed":false}],[":frontend/tests/desc.test.js",{"duration":31.248038000000008,"failed":false}],[":frontend/tests/deps.test.js",{"duration":31.736107000000004,"failed":false}],[":frontend/tests/closure.test.js",{"duration":24.077101999999968,"failed":false}],[":frontend/tests/effective.test.js",{"duration":27.93907200000001,"failed":false}],[":frontend/tests/ids.test.js",{"duration":25.51923499999998,"failed":false}],[":frontend/tests/remote.test.js",{"duration":20.999619999999993,"failed":false}],[":frontend/tests/warnings.test.js",{"duration":9.594386999999983,"failed":false}],[":frontend/tests/fresh.test.js",{"duration":22.15039999999999,"failed":false}]]} \ No newline at end of file