TASKS Phase 1. Baum-/Kostenlogik -> model.js (gateOf, needsBreakdown,
visibleChildren, computeCheapSet, cheapCls), HTML-Erzeugung -> render.js
(renderTreeHtml). Beide sind headless: UI-State (verworfene einblenden,
günstigster Pfad) kommt als Parameter herein statt aus Globals; nur cheapPathOn
bleibt UI-State in app.js. render() in app.js ist jetzt die dünne DOM-Anbindung.
Snapshot-Tests (tests/render.test.js): Grundzustand, günstigster Pfad,
verworfene einblenden, Geister-Knoten („Untergliederung fehlt"), plus die
Zusicherung, dass der Renderer nie eine Modus-Klasse erzeugt (Modus =
CSS-Container-Klasse in app.js -> ein Snapshot deckt alle drei Modi). 24 Tests
grün. Byte-identisches Rendering im Browser verifiziert (18 Knoten, 6 Blätter,
3 Geister, Toggles ok, keine Konsolenfehler).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Erster Schritt der Modularisierung (ROADMAP „tragfähige Codebasis",
TASKS Phase 1). Der bisher einzelne index.html-Prototyp wird zur Vite-App:
- CSS -> src/style.css, gesamtes JS -> src/app.js (noch als ein Modul;
Parser/Renderer werden in den folgenden Checkboxen herausgelöst).
- index.html ist der Vite-Entry (<script type="module" src="/src/app.js">).
- npm run build (vite + vite-plugin-singlefile) inlint JS+CSS+Favicon (als
data:-URI) in EINE self-contained dist/index.html -> bleibt file://-tauglich.
- Vitest als Testrunner eingerichtet (tests/, passWithNoTests bis Schritt 2/3).
- Pages-Workflow: Node + npm ci + npm test + npm run build, deployt dist/;
Favicon-sed entfällt (inline), nur ../LICENSE + Footer-Version bleiben.
- .claude/launch.json auf Vite-Dev-Server (Port 8137) umgestellt.
Entscheidung als D19 dokumentiert (weicht D11 „kein Build-Zwang" bewusst auf,
hält aber D16 file://-Versprechen über die gebündelte Datei). README (de/en)
und frontend/CLAUDE.md um Dev-/Build-/Test-Workflow ergänzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auf dem Smartphone hatte der Splitter zwei Fehler: nach dem ersten Ziehen
rastete er in eine feste Aufteilung und ließ sich nicht mehr bewegen (die
Titelzeile im Snap-Rand fing jeden weiteren Zug ab), und das Tippen auf eine
Titelzeile klappte das Panel nicht mehr aus (der Handler verlangte den
collapsed-Zustand, den ein freier Zug aufhob).
Mobil jetzt kontinuierlich statt diskret:
- Grid-Zeilen-Minima --pmin-d/--pmin-e = gemessene Kopfhöhen (syncPanelMins),
dadurch bleiben beide Titelzeilen immer stehen (kein Snap/Collapse).
- Gutter-Drag ruft setMobileDrow() (klemmt --drow frei) — jederzeit beweglich.
- Tipp auf eine Titelzeile maximiert dieses Panel (das andere = Titelzeile).
- applyLayout ruft auf Mobil kein applySplit (behält --drow bei Moduswechsel);
seg-Klick stoppt Propagation, damit er die Titelzeile nicht mit-maximiert.
- Default: Diagramm maximiert. Desktop behält das diskrete Modell + Buttons.
SPEC §9, DECISIONS D17 und frontend/CLAUDE.md nachgeführt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- gestrichelte, geschwungene Petrol-Linie (Katmull-Rom) durch die Endknoten
des Pfads; kräftig hinter den Knoten, abgetönte Kopie davor
- blasse, große Stationspunkte nur an echten Blättern (U-Bahn-Plan) — macht
durchquerte Fremd-/Zwischenknoten eindeutig als "nicht Endknoten" erkennbar
- Linie + Punkte auch im SVG/PNG-Export (hinten/vorne-Schichtung)
- Overlays liegen in #out, erben dessen CSS-zoom (Punkte /zoom umgerechnet);
Neuzeichnung nach render() und applyLayout()
- Beispiel erweitert: Frontend (M) -> PWA | Web+Nativ (Web[/]+Android+iOS)
- Layout-Fix: all-of unter einer any-of-Alternative wird nur horizontal schmal
transponiert gestapelt (ul.or>li.has-and>ul.and), sonst schob der breite
Fächer Alternativknoten und Elternbaum weit nach rechts
- Geist-Knoten-Label "Untergliederung fehlt" -> "…" (alle 9 Sprachen), die
Erklärung bleibt im Tooltip; der lange Text verbreiterte gestapelte Zellen
- SPEC §5/§9 und DECISIONS D18 nachgeführt, Notiz in frontend/CLAUDE.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Umschalter im Diagramm-Kopf (Default an, Zustand in werkbaum-ui persistiert)
- nötige Knoten: all-of ⇒ alle Kinder, any-of ⇒ günstigste Alternative
(kleinste rekursive Kosten; Gleichstand ⇒ erste); verworfene zählen nie mit
- Darstellung per Inversion: nicht benötigte Knoten treten blass/entsättigt
zurück (kein Zusatzrahmen an den ohnehin dichten Knoten-Ecken)
- fehlende T-Shirt-Größe wird für die Kostenschätzung als M gewertet;
invertiertes M-Badge (weiß mit Petrol-Rand) macht die Annahme sichtbar
- neue Tooltips i18n (DE-Quelle + 8 Übersetzungen, 50 Keys × 9)
- SPEC §9 (Günstigster Pfad) und DECISIONS D18 mitgeführt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auf kleinem Bildschirm (body.mobile per matchMedia, <=640px):
- Immer nur ein Bereich gross (Diagramm ODER Editor); der andere schrumpft
auf seine Titelzeile und dient als Umschalter (Antippen holt ihn nach
vorn). Splitter und Min/Normal/Max-Buttons entfallen.
- Legende von der Bereichs-Umschaltung entkoppelt: eigener Umschalter
(#legendBtn) im Editor-Kopf statt der dauerhaften "AGENDA"-Zeile, damit
sie zugeklappt keinen Platz kostet (neuer i18n-Key legendTooltip, 9 Spr.).
- Sprachwahl schlank: nur EN + aktive Sprache + "…" (klappt alle auf); die
aktive Sprache wird auch als "extra" eingeblendet, Auto-Aufklappen entfaellt.
- Default Vollbild auf Mobil (nur ohne gespeicherte Nutzerwahl).
Verifiziert (headless, 375px): body.mobile gesetzt, Diagramm-Default +
Editor als Titelzeile, Umschalten per Tap, Legenden-Toggle, Sprachleiste
DE+EN+…/Aufklappen zeigt alle 9/aktives Extra bleibt sichtbar, Vollbild an,
keine Konsolenfehler; Desktop unveraendert (beide Panels, 4 Sprachen,
Legendenbutton verborgen). i18n konsistent (47 Keys x 9).
SPEC §9 (Kleiner Bildschirm) + DECISIONS D17 + frontend/CLAUDE.md ergaenzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ohne Backend bleiben Einstellungen und Text ueber ein Neuladen erhalten
(localStorage). Gespeichert: Editortext (werkbaum-src) und GUI-Zustand
(werkbaum-ui: Modus, verworfene, Split-Zustand inkl. freier Drag-Groesse
--col/--drow, Zoom, Vollbild); Sprache bleibt in werkbaum-lang.
saveUI()/saveSrc() haengen an allen Zustandsaenderungen (Layout, Toggle,
Fenster-Buttons, Splitter-Drag, Zoom, Vollbild, Texteingabe);
restoreState() stellt beim Laden alles wieder her und unterdrueckt
waehrenddessen ueber restoring=true das Zurueckschreiben. Fehlender Text
faellt auf das Beispiel (INITIAL) zurueck, ein leerer bleibt leer.
Verifiziert (headless): Text, Modus, verworfene, Zoom, Vollbild,
Custom-Split (--col) und Minimier-Zustand ueberstehen ein Reload;
keine Konsolenfehler. Keine SPEC-Aenderung (Notation unberuehrt);
localStorage-Schluessel in frontend/CLAUDE.md dokumentiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der bisherige „vertikal"-Toggle wird zur dreistufigen Auswahl
„horizontal / vertikal / kompakt", die zugleich das Seitenlayout wählt:
- horizontal: Diagramm oben, Editor unten (je volle Breite), Agenda
rechts im Editor aufklappbar.
- vertikal: Editor links, Diagramm rechts; „all of" tritt rechts aus.
- kompakt: wie vertikal, aber „all of" läuft nach unten (spart Breite);
Gate nur noch über den Linienstil codiert.
Zusätzlich wird das Petrol im Diagramm aufgegeben: any-of-Linien
(Sammelleiste und Abzweige) sowie der Rahmen der Alternative-Knoten sind
in allen Modi durchgehend gestrichelt bzw. grau (#6B7A8C). all-of bleibt
durchgezogen in Tinte. Petrol nur noch für UI-Akzente und das Logo.
Doku nachgezogen: SPEC §9 (Linienführung, drei Modi), DECISIONS D15,
frontend/CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>