frontend: „Was ist neu?" — neu in Produktion mit gelbem Strahlenkranz

Dokumente von außen (mitgeliefert D27, ?sourceUrl= D23) ändern sich, ohne dass
der Betrachter es merkt. Sie zeigen jetzt, was sich seit seinem letzten Besuch
getan hat.

- „Neu" heißt bewusst NICHT „Zeile hinzugefügt", sondern **neu in Produktion**:
  ein Knoten trägt jetzt [^] und tat es in der zuletzt gesehenen Fassung nicht.
  Ein Zeilendiff meldete vor allem Rauschen; die Nachricht, die zählt, ist was
  live gegangen ist. Nebeneffekt: es leuchtet eine Handvoll Knoten, nicht dreißig.
- Basis ist die zuletzt GESEHENE Fassung je Dokument (`werkbaum-seen`), nicht
  die letzte Auslieferung — wer Fassungen überspringt, sieht alles seither.
  Fortgeschrieben wird erst beim Bestätigen, sonst wäre die Meldung nach einem
  Neuladen weg, bevor sie jemand bemerkt. Beim Erstkontakt leuchtet nichts.
- Knoten-Identität ist der Label-Pfad, nicht die Zeilennummer: Umeinrücken und
  Umsortieren erzeugen keine Falschmeldungen; gleichnamige Geschwister per
  Index; Umbenennen gilt als neuer Knoten (der Text ist der Vertrag, D14).
- Darstellung: gelber Strahlenkranz nach außen, kein Blinken (WCAG 2.2.2/2.3.1;
  Blinken zöge dauerhaft den Blick statt einmal zu melden). Außen, weil die
  Füllung dem Status gehört (SPEC §4). Zusammen mit der Cursor-Zeile: Tinte
  innen, Gelb außen. Nicht im Druck und nicht im Grafikexport — die Markierung
  hängt am persönlichen Besuchsstand.
- Knopf im Diagramm-Kopf nur, wenn es etwas gibt; nennt die Anzahl, Klick
  bestätigt. Kein Dauer-Umschalter.
- Bei selbst bearbeitetem mitgeliefertem Dokument wird nichts hervorgehoben —
  dort fehlt die saubere Vergleichsbasis (D27).

Fehler beim Bauen, der zuerst durchrutschte: Die Menge wurde beim Laden aus
einem eigenen Parse-Durchlauf berechnet. Der Zähler stimmte, aber kein Knoten
leuchtete — `Set.has()` prüft Objektidentität, und die gerenderten Knoten kamen
aus einem anderen Parse. `render()` bildet die Menge jetzt bei jedem Durchlauf
aus den gerade geparsten Wurzeln; vorgehalten wird nur der geparste Basisbaum.

Verifiziert: 9 neue Modelltests (Statuswechsel, neuer [^]-Knoten, nicht-[^]
ignoriert, unverändert ignoriert, Erstkontakt leer, Umsortieren/Tabs ohne
Falschmeldung, gleiches Label unter verschiedenen Eltern, gleichnamige
Geschwister, verworfene). Im Browser: Erstkontakt setzt nur die Basis (Knopf
versteckt); zurückgedrehte Basis lässt genau die erwarteten Knoten leuchten
(Zähler 3, dann 1); Bestätigen räumt auf und überlebt das Neuladen; ohne
Bestätigen bleibt die Meldung über ein Neuladen stehen. Vitest 46/46.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-07-27 15:18:20 +02:00
co-authored by Claude Opus 4.8
parent 68abdc6625
commit 7a52277b84
9 changed files with 293 additions and 5 deletions
+17
View File
@@ -237,6 +237,15 @@
.agenda .hint{border-top:0;flex:1 1 auto;min-height:0;overflow:auto}
/* Splitter zwischen Editor und Legende — dieselbe Sprache wie der große
Splitter, nur schmaler. Ohne offene Legende gibt es nichts zu teilen. */
/* Neuheiten-Knopf im Diagramm-Kopf (D28): Sternchen + Anzahl, nur sichtbar,
wenn es etwas gibt. Gelb wie der Strahlenkranz am Knoten. */
.freshbtn{position:relative;color:#A16207;border-color:#FACC15;background:#FEFCE8}
.freshbtn:hover{color:#854D0E;border-color:#EAB308}
.freshbtn[hidden]{display:none}
.freshcount{
font-family:'IBM Plex Mono',monospace;font-size:.62rem;font-weight:600;
margin-left:3px;vertical-align:2px;
}
.hint-gutter{
flex:0 0 10px;align-self:stretch;
cursor:col-resize;touch-action:none;
@@ -463,6 +472,13 @@
(weiter unten) ist spezifischer als `.node.current` und schluckte den Ring
sonst überall unterhalb einer any-of-Gruppe. */
#out .node.current{box-shadow:0 0 0 2px var(--card),0 0 0 4px var(--ink)}
/* Neu in Produktion seit dem letzten Besuch (D28): gelber Strahlenkranz um den
Knoten. Bewusst ein Schein nach AUSSEN statt Farbe im Knoten — die Füllung
gehört dem Status (SPEC §4) und bleibt lesbar. Kein Blinken: WCAG 2.2.2/2.3.1
und es zöge dauerhaft den Blick. `#out`-Präfix wegen `ul.or .node`. */
#out .node.fresh{box-shadow:0 0 0 2px #FACC15,0 0 16px 5px rgba(234,179,8,.65)}
/* Beides zugleich: Cursor-Zeile innen (Tinte), Neuheit außen (gelb). */
#out .node.fresh.current{box-shadow:0 0 0 2px var(--card),0 0 0 4px var(--ink),0 0 18px 6px rgba(234,179,8,.65)}
/* Alt gedrückt = Sprung-Geste scharf: Cursor an allen Knoten, Petrol-Ring am
Knoten unter dem Zeiger. Auf verlinkten Knoten ist das die einzige
Rückmeldung, weil dort der einfache Klick dem Link gehört (D25). */
@@ -792,5 +808,6 @@
/* Knoten nicht über den Seitenrand zerschneiden */
#out li{break-inside:avoid}
.node.current{box-shadow:none!important} /* Editierhilfe, nicht drucken (D25) */
.node.fresh{box-shadow:none!important} /* „neu seit dem letzten Besuch" ist persönlich (D28) */
@page{margin:12mm}
}