Files
mhoennigandClaude Fable 5.1 6471608aa4 Start UI refresh: shared Werkator tokens and selector inventory (0.1.100)
Mark #ui-refresh as in progress. Rewrite styles.css around one token set
(light-dark, Lumo derived from it) including the classes for the target
structure of docs/plans/ui-refresh.md; move login.css and offline.html to
the same tokens. Add the test selector inventory (step 1) and a handover
section so a goal run can continue with steps 3 to 8. Views unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 10:53:05 +02:00

24 KiB
Raw Permalink Blame History

Spezifikation: UI-Refresh — Werkator-Optik und mobile Bedienbarkeit

Status: geplant, nicht begonnen. Werkbaum-Knoten #ui-refresh unter #experience. Entwürfe: mockups/ui-refresh.html (im Browser öffnen; Umschalter für Hell/Dunkel oben rechts). Nachfolger: auth-flow-refresh.md baut auf diesem Stand auf.

0. Übergabestand für den Goal-Lauf (2026-09-12)

Vorbereitet und committet, hier weitermachen, nichts davon wiederholen:

  • Branch ui-refresh existiert lokal (von main bei 7bfed1a), #ui-refresh steht im Werkbaum auf [~]. Der Branch ist noch nicht gepusht; git push -u origin ui-refresh beim ersten Push.
  • Schritt 1 (Selektor-Inventar) liegt in ui-refresh-selectors.md. Schritt 2 (Tokens) ist umgesetzt: styles.css ist komplett neu geschrieben (ein Token-Set, Lumo-Ableitung, Klassen für die Zielstruktur aus Abschnitt 5 sind bereits enthalten, u. a. wj-tiles, wj-tile, wj-stepper, journal-entry-row, wj-day-nav, wj-hours-pills, wj-sheet, wj-calendar-kpis), login.css und offline.html nutzen dieselben Tokens. Die Kotlin-Views sind noch unverändert; die Schritte 3 bis 8 stehen aus. Wo die CSS-Klassen nicht zur gebauten Struktur passen, gilt die Spezifikation, und das CSS wird angepasst.
  • Lokale Toolchain: export JAVA_HOME=$HOME/opt/jdk25 (gepinntes Temurin 25 aus packaging/jdk.properties, geprüft installiert). Playwright-Browser liegen unter ~/.cache/ms-playwright. Vollständiger Lauf: ./gradlew --no-daemon --console=plain test -Pproduction=true, danach ./tools/test-frontend und ./gradlew --no-daemon firefoxAcceptance productionAcceptance -Pproduction=true -x test.
  • CI (Werkator) baut und deployt nur main: https://werkator.javagil.de/repos/werkjournal/latest (ein Lauf dauert etwa zehn Minuten). Feature-Branches laufen nicht in CI; deshalb vor dem Merge lokal die vollständige Pipeline grün haben.
  • Abschluss dieses Pakets: git checkout main && git merge --no-ff ui-refresh, Micro-Version erhöhen, pushen, dann den CI-Lauf auf der Werkator-Seite bis zum Ende beobachten (Status success und Deployment). Bei Fehlschlag auf main beheben und erneut pushen; kein Force-Push. Danach mit auth-flow-refresh.md fortfahren (eigener Goal-Lauf).
  • .claude/launch.json ist lokal und nicht Teil des Repos (dient nur der Mockup-Vorschau).

1. Ziel

Die PWA soll auf dem Smartphone leicht, schnell und „schick“ wirken und auf dem Desktop ruhig und aufgeräumt. Farbwelt und Tonalität orientieren sich an https://werkator.javagil.de (Petrol-Akzent auf neutralem, leicht grünstichigem Grau, Clay und Amber als Nebenfarben, hell und dunkel). Home (Today), Arbeitszeit-Erfassung und Habits sind die Kernscreens und bekommen den größten Anteil der Arbeit. Verhalten, Datenmodell und Anmeldung bleiben unverändert; das ist eine Gestaltungs- und Bedienbarkeitsarbeit.

2. Ausgangslage

  • Vaadin Flow mit Lumo. Gestaltung liegt in src/main/resources/META-INF/resources/styles.css (zwei historische Schichten mit unterschiedlichen Petrol-Tönen #086b78 und #0c4654) und in src/main/resources/static/login.css (eigener Ton #17677b, eigene Variablen). Es gibt keine gemeinsamen Design-Tokens.
  • Shell: ui/MainLayout.kt mit Navbar (Logo, Titel, Quick-Nav, Drawer-Toggle) und mobiler Bottom-Nav mit drei Icons ohne Beschriftung plus Drawer-Toggle.
  • Today: ui/TodayView.kt, dunkle Arbeitskarte mit 52–70 px Stundenzahl, Wochen-/Monatssumme, Details-Element mit Einträgen, Habit-Karten mit Zähler und Details.
  • Arbeit: work/WorkView.kt, Datumsauswahl, Summenkarte, „Freier Tag“-Karte, Einträge als Karten mit vier Aktionsbuttons in einer Reihe, Formular in einem 600 px-Dialog.
  • Habits: habits/HabitView.kt (Auswahlbuttons, Monatskalender, Konfigurationsdialog) und habits/HabitCounter (Karte mit Zähler ±, Grenzen als Textzeilen).
  • Weitere Seiten: work/ReportsView.kt, catalog/CatalogView.kt, ui/SettingsView.kt, identity/AdminView.kt, offline.html, Wartungsseite.
  • Wahrgenommene Probleme: große Paddings und Radien wirken klobig; Stundenzahl dominiert; Aktionsreihen mit gleichwertigen Icon-Buttons; Bottom-Nav ohne Labels; Details-Elemente verstecken Inhalt; Dialoge statt Bottom-Sheets; Habit-Grenzen als Fließtext statt Anzeige; Kalenderzellen ohne Zielbezug.

3. Nicht-Ziele

  • Keine Änderung an Anmeldung, Einladungen, Sessions oder E-Mails (siehe Nachfolgespezifikation). Die Login-Seite wird nur farblich und typografisch nachgezogen, ihre Struktur bleibt.
  • Keine Schema-Änderung, keine Migration, keine neuen Fachfunktionen.
  • Keine Offline-Erfassung, keine Timer, keine Swipe-Gesten mit versteckten Aktionen.
  • Kein Wechsel weg von Vaadin Flow, keine kostenpflichtigen Komponenten, keine neuen npm-Abhängigkeiten ohne begründete Notwendigkeit.

4. Verbindliche Vorgaben

4.1 Arbeitsweise

  • Branch ui-refresh von main. Vor Beginn #ui-refresh im Werkbaum auf [~] setzen, committen, pushen. Vor jedem Push die Micro-Version in build.gradle.kts erhöhen.
  • Kleine, thematisch geschlossene Commits in der Reihenfolge aus Abschnitt 7. Jeder Commit lässt ./gradlew test -Pproduction=true grün.
  • Ergebnisdokument docs/implementation/ui-refresh.md im Stil der vorhandenen Implementierungsdokumente (Was wurde gebaut, welche Entscheidungen, Abschnitt „Verification on “ mit tatsächlichen Testläufen und geprüften Screenshots). Kein Erfolg behaupten, der nicht geprüft wurde.
  • Nach Abschluss #ui-refresh auf [x], Werkbaum-Notiz mit Datum, README-Absatz zur Gestaltung aktualisieren.
  • Bei Rückfragen, die die Gestaltung wesentlich ändern würden, anhalten. Kleine Entscheidungen selbst treffen und im Ergebnisdokument festhalten.

4.2 Stabilitätsregeln

  • Alle data-*-Attribute, role-Attribute, aria-label-Texte und Klassennamen, die Tests verwenden, bleiben bestehen (data-work-entry, data-work-field, data-work-submit, data-work-discard, data-work-recovery, aria-pressed, role=alert, role=status, .journal-entry, .summary-card, .habit-indicator, .habit-warning, .calendar-day, .calendar-today, .work-entry-selected u. a.). Vor dem Umbau die Browser-Schritte unter src/test/kotlin/.../acceptance nach verwendeten Selektoren durchsuchen und diese Liste im Ergebnisdokument aufführen.
  • i18n-Schlüssel dürfen ergänzt werden; bestehende Schlüssel bleiben. Neue Texte immer in messages_de.properties und messages_en.properties.
  • Alle Chromium- und Firefox-Szenarien laufen weiterhin durch. Wo ein Szenario nur wegen eines geänderten Layouts scheitert, wird der Test-Schritt angepasst, nicht das Szenario gestrichen.
  • Draft-Handling (work-drafts.js), Push-Einstellungen, Zeitzonen-Erkennung und Theme-Wahl (device-settings.js) bleiben funktional unverändert.

4.3 Design-Tokens (Werkator)

Ein gemeinsames Token-Set wird in styles.css (auf html) und login.css (auf :root) identisch definiert. Lumo-Variablen werden daraus abgeleitet, nicht doppelt gepflegt. Die dunkle Variante folgt der bestehenden Theme-Wahl der App (Attribut/Klasse, die device-settings.js setzt) und prefers-color-scheme; light-dark() bleibt zulässig, solange die Theme-Wahl der Einstellungen weiter greift.

Token Hell Dunkel Verwendung
--wj-bg #ffffff #242928 Seitengrund
--wj-panel #fafafa #2a302f Karten, Navbar, Bottom-Nav
--wj-panel-2 #f4f5f5 #313837 Eingebettete Flächen, Chips, Stepper
--wj-line #e4e7e7 #3e4645 Trennlinien, Kartenrahmen
--wj-line-2 #d1d6d5 #545f5d Betonte Rahmen, Fokus-Hintergrund
--wj-text #141616 #f4f5f5 Haupttext
--wj-text-2 #3e4645 #d1d6d5 Sekundärtext
--wj-muted #6e7c7a #9ea9a7 Labels, Eyebrows, Hinweise
--wj-ghost #9ea9a7 #6e7c7a Deaktiviertes, Platzhalter
--wj-accent #0e6b7d #63bccb Primäraktion, aktive Navigation, Zahlen
--wj-accent-2 #0a5262 #8ed0db Hover/Pressed der Primäraktion
--wj-accent-soft #e3f0f3 #1f3b41 Aktiv-Hintergrund, Fortschrittsspur, Chips aktiv
--wj-accent-soft-2 #c6e0e6 #27505a Stärkere Akzentfläche
--wj-clay #b0563b #e09070 Warnhinweise (Grenze verfehlt), Löschen
--wj-clay-soft #f6e9e4 #3e2a22 Hintergrund von Warnhinweisen
--wj-amber #b8860b #e3b341 Aufmerksamkeit (Entwurf vorhanden, Konflikt)
--wj-amber-soft #f9f0d2 #3d3418 Hintergrund dazu
--wj-crit #b3261e #ef6f66 Fehler
--wj-crit-soft #f8e2df #45201d Hintergrund von Fehlern
--wj-shadow 0 1px 2px rgb(20 22 22 / .06), 0 4px 16px rgb(20 22 22 / .06) 0 2px 6px rgb(0 0 0 / .25) Schwebende Flächen (Sheet, Dialog)

Lumo-Ableitung mindestens: --lumo-primary-color: var(--wj-accent), --lumo-primary-text-color: var(--wj-accent), --lumo-primary-color-10pct: var(--wj-accent-soft), --lumo-base-color: var(--wj-panel), --lumo-body-text-color: var(--wj-text), --lumo-secondary-text-color: var(--wj-muted), --lumo-tertiary-text-color: var(--wj-ghost), --lumo-contrast-10pct und -20pct aus --wj-line/--wj-line-2, --lumo-error-color: var(--wj-crit), --lumo-error-text-color: var(--wj-crit), --lumo-error-color-10pct: var(--wj-crit-soft), --lumo-success-color: var(--wj-accent). Die alten Journal-Variablen (--journal-*) werden auf die neuen Tokens umgestellt oder entfernt; am Ende gibt es nur ein Token-Set.

4.4 Typografie, Rhythmus, Formen

  • Schrift: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif, Grundgröße 16 px, Zeilenhöhe 1.45. Tabellarische Ziffern (font-variant-numeric: tabular-nums) für alle Zahlen.
  • Skala (Mobil / Desktop): Eyebrow 12/12 px Versalien, Buchstabenabstand 0.06em; Seitentitel 24/32 px, Gewicht 600, Buchstabenabstand −0.02em; Kartentitel 15/16 px, Gewicht 600; Hero-Zahl 40/56 px, Gewicht 600; Sekundärzahl 20/24 px; Fließtext 15/16 px; Hinweise 13 px.
  • Radien: Karten 14 px, Buttons und Felder 10 px, Chips und Pills 999 px, Bottom-Sheet oben 20 px. Keine 20–28 px-Radien mehr.
  • Abstände: 8-px-Raster. Seitenrand 16 px mobil, 32 px Desktop. Kartenpadding 16 px mobil, 20 px Desktop. Abstand zwischen Karten 12 px mobil, 16 px Desktop. Maximale Inhaltsbreite 1100 px, Zwei-Spalten-Layout ab 800 px (bestehendes Verhältnis 1.15 : 1).
  • Flächen: Karten mit 1 px --wj-line auf --wj-panel, kein Schatten. Nur Bottom-Sheet und Dialoge haben --wj-shadow. Die dunkle Petrol-Arbeitskarte entfällt; die Hero-Karte auf Today ist eine helle Panel-Karte mit Akzentzahl (siehe Entwurf).
  • Bewegung: Übergänge 150 ms ease-out für Hover/Fokus, 220 ms für Sheet-Öffnen. Bei prefers-reduced-motion: reduce keine Bewegung.

4.5 Interaktion und Touch

  • Mindesttrefferfläche 44 × 44 px für alle Aktionen; Stepper-Buttons 48 × 48 px.
  • Genau eine Primäraktion pro Screen als gefüllter Akzent-Button; alle übrigen Aktionen als leise Buttons (Text in --wj-text-2, transparent, Hover --wj-panel-2) oder als Icon-Buttons mit Tooltip und aria-label.
  • Auf Bildschirmen ≤ 600 px öffnen Formulare als Bottom-Sheet (Vaadin Dialog mit Thema/Klasse wj-sheet: unten angedockt, volle Breite, Radius oben 20 px, Griffleiste, Inhalt scrollt im Sheet, Aktionen fest am unteren Rand mit Safe-Area). Ab 601 px als zentrierter Dialog mit 560 px Breite.
  • Leseabstand zur Bottom-Nav: Seiteninhalt endet mindestens 96 px plus env(safe-area-inset-bottom) über dem unteren Rand.
  • Fokus: 2 px Umriss in --wj-accent mit 2 px Versatz, sichtbar auf allen Flächen.

4.6 Barrierefreiheit

  • Kontrast mindestens WCAG AA (4.5 : 1 Text, 3 : 1 große Zahlen und Icons) in beiden Themes. Kombinationen im Ergebnisdokument mit gemessenen Werten belegen (z. B. --wj-accent auf --wj-panel, --wj-muted auf --wj-panel, --wj-clay auf --wj-clay-soft).
  • Alle Icon-Buttons behalten sichtbaren Tooltip und aria-label. Bottom-Nav-Links bekommen sichtbare Labels.
  • Zustände (aktiv, Warnung, Fehler) nie nur über Farbe: zusätzlich Text, Icon oder Form.

5. Screens

Die Entwürfe in mockups/ui-refresh.html sind maßgeblich für Anordnung und Gewichtung; Pixelgleichheit ist nicht gefordert. Der Abschnitt „Voller Zustand, kompakt“ ist die Zielvorgabe; die „erste Fassung“ darunter zeigt nur die Herleitung und gilt dort nicht, wo sie abweicht.

5.1 Shell

  • Navbar (alle Breiten): Logo 28 px, Wortmarke „werkjournal“ 18 px Gewicht 600, rechts Quick-Nav (Desktop) und Menü-Button. Höhe 56 px, Hintergrund --wj-panel, 1 px Linie unten. Gast-Badge als Pill in --wj-accent-soft bleibt (Desktop) und wandert mobil in den Drawer-Kopf.
  • Bottom-Nav (≤ 600 px): vier Ziele „Heute“, „Arbeit“, „Habits“, „Mehr“ (Drawer) mit Icon 22 px über Label 11 px. Aktives Ziel: Icon und Label in --wj-accent, Pill-Hintergrund --wj-accent-soft hinter dem Icon. Höhe 64 px plus Safe-Area. aria-current="page" auf dem aktiven Link.
  • Drawer: gleiche Einträge wie heute (Heute, Arbeit, Berichte, Habits, Kunden & Projekte, Einstellungen, Admin falls berechtigt) als Liste mit Icon, 48 px Zeilen, aktiver Eintrag mit --wj-accent-soft. Footer mit Version bleibt.
  • Seitenkopf: Eyebrow (Datum oder Bereich) über Titel, darunter optional eine Zeile Sekundärtext. Kein 38 px-Titel mehr.

5.2 Today (Home)

Maßgeblich ist der Entwurf „Heute · voll, Kacheln“ mit vier Einträgen über drei Kunden und drei Habits; die Seite muss in diesem Zustand bei 390 × 812 ohne Scrollen vollständig sichtbar sein. Reihenfolge mobil von oben: Seitenkopf mit vollem Datum als Eyebrow und Titel „Heute“. Dann:

  1. Arbeitskarte (kompakt): links Kartentitel „Arbeit heute“ und direkt darunter die Tageszahl 34 px in --wj-accent mit Einheit in --wj-muted; rechts vertikal zentriert der Primär-Button „Erfassen“ (Plus-Icon, Text ab 360 px sichtbar), 44 px hoch, Pill-Form. Darunter eine Chip-Zeile mit den Tagessummen je Kunde („Hostsharing 4 h“), Chips in --wj-panel-2, Zahl in --wj-accent, bei mehr als vier Kunden horizontal scrollbar; bei nur einem Kunden entfällt die Zeile. Darunter zwei Kennzahlen „Diese Woche 23 h“ und „September 71 h“ (Label 12 px, Wert 16 px) mit je einer 4-px-Fortschrittsspur relativ zum Maximum der letzten zwölf Wochen bzw. Monate (Abfrage im WorkService, ohne Schemaänderung; ohne Vergleichswert bleibt die Spur leer). Freier Tag: statt der Spuren eine Pill „Freier Tag“ in --wj-amber-soft. Kartenpadding 14 × 16 px.
  2. Heutige Einträge: keine Details-Klappe, keine Karten. Liste direkt unter der Arbeitskarte, jede Zeile 52 px mit 1 px Trennlinie: links „Kunde · Projekt“ (Kunde 600, Projekt in --wj-muted) und darunter Beschreibung 12 px in --wj-muted, einzeilig mit Ellipsis; rechts Inline-Stepper „− 3 h +“ (Buttons 34 px rund, Zahl in --wj-accent) und ein Pfeil in --wj-ghost. Stepper ändert die Stunden direkt (bestehende Regeln: max. 12 h/Tag, min. 1 h, Konflikt als Notification); Tippen auf den Textbereich öffnet den Eintrag auf der Arbeit-Seite (bestehender Link mit entry-Parameter, Klasse journal-entry bleibt). Leerzustand: eine Zeile „Noch nichts erfasst“ mit sekundärem Link „Jetzt erfassen“.
  3. Habits als Kacheln: Abschnittstitel „Habits“ mit leisem Link „Kalender“ rechts. Habits stehen nebeneinander in einem Raster mit drei Spalten (Gap 8 px), jede Kachel in sich vertikal: Name 13 px (600, einzeilig mit Ellipsis, voller Name als title), Zähler 28 px, Statuszeile 11 px mit Punkt in Statusfarbe (z. B. „Ziel · Wo 4/5“ in --wj-accent mit Häkchen; „noch 1 · Wo 3/5“ in --wj-clay; „max 3 · noch 1“ in --wj-muted), darunter das große Plus (44 px rund, gefüllt Akzent) und darunter das kleine Minus (34 × 30 px Pill, leise). Erreichtes Tagesziel färbt den Zähler in --wj-accent. Mehr als drei Habits brechen in weitere Dreierzeilen um; bei zwei Habits bleiben zwei Spalten mit gleicher Kachelbreite, bei einem Habit eine Zeilenkarte wie in der Alternative. Tippen auf Name oder Zähler öffnet mobil ein Bottom-Sheet mit dem vollständigen HabitCounter (Grenzen, Wochenwert, Neu laden), Desktop ein Popover. Der Zähler bleibt in HabitCounter; aria-label, role=status/alert, .habit-indicator und .habit-warning bleiben erhalten. Alternative (im Entwurf „Zeilen“ dokumentiert, nicht Standard): verdichtete Zeilenkarten 56 px mit Stepper rechts. Sie wird nur verwendet, wenn genau ein Habit aktiv ist.
  4. Desktop (≥ 800 px): links Arbeitskarte und Eintragszeilen, rechts Habit-Kacheln, drei pro Zeile, Kachelpadding 14 px.

5.3 Arbeit (WorkView)

  • Seitenkopf: Eyebrow „Arbeit“, Titel ist das gewählte Datum (z. B. „Freitag, 12. September“), darunter Tagesnavigation als drei Pills: „‹ Vortag“, „Heute“, „Folgetag ›“ (Folgetag deaktiviert, wenn Datum = heute) und ein Kalender-Icon-Button, der den bestehenden DatePicker öffnet. Der DatePicker bleibt als Komponente vorhanden (Tests), darf aber visuell hinter dem Icon liegen.
  • Tageskarte (kompakt wie auf Today): Titel „Tag“, Tageszahl 34 px, rechts Primär-Button „Erfassen“ (deaktiviert für Zukunftstage, mit Tooltip-Begründung), Chip-Zeile mit Kundensummen, darunter in derselben Karte die Zeile „Freier Tag“ mit Schalter (Toggle mit Icon); Konfliktmeldung als role=alert-Zeile darunter. „Neu laden“ als leiser Icon-Button rechts im Kartentitel.
  • Einträge: keine Karten mit Aktionsreihe mehr. Abschnittstitel „Einträge“ mit Hinweis „Tippen zum Bearbeiten“ in 12 px. Zeilen wie auf Today (52 px, Kunde · Projekt, Beschreibung einzeilig, Inline-Stepper, Pfeil); die ganze Zeile außer dem Stepper öffnet das Bearbeiten-Sheet. Attribut data-work-entry bleibt auf der Zeile; der per Link fokussierte Eintrag (work-entry-selected) bekommt Hintergrund --wj-accent-soft mit 10 px Radius statt eines Rahmens. Bestehende Aktivierungsregeln bleiben.
  • Formular (Bottom-Sheet mobil, Dialog Desktop), kompakt: Kopf mit Titel „Erfassen“ / „Bearbeiten“; rechts im Kopf beim Bearbeiten ein Löschen-Icon (öffnet die bestehende Bestätigung) und der leise „Schließen (Entwurf behalten)“-Button. Felder: Kunde und Projekt nebeneinander in zwei Spalten (bestehender CatalogPicker, ab 360 px zweispaltig), Stunden als Pills 1–8 in einer Reihe plus „mehr“-Chip, der das IntegerField (1–12) einblendet (das Feld bleibt das Datenfeld mit data-work-field="hours", die Pills setzen nur seinen Wert), Beschreibung als TextArea mit 56 px Mindesthöhe und Zeichenanzeige ab 1800/2000, zuletzt das Datum als Nur-Lesen-Zeile 40 px, die beim Tippen den DatePicker öffnet. Fußzeile fest am unteren Rand: Primär „Speichern“, leise „Verwerfen“. Entwurfs-Wiederherstellung (data-work-recovery) erscheint als Amber-Hinweiskarte oberhalb der Felder mit Buttons je Entwurf; Konfliktansicht als Amber-Karte mit „Aktueller Stand“ und Button „Meinen Entwurf übernehmen“.

5.4 Habits

  • Seitenkopf: Eyebrow „Habits“, Titel „Kalender“.
  • Habit-Auswahl: horizontal scrollbare Pill-Leiste (aria-pressed bleibt), aktive Pill gefüllt in --wj-accent-soft mit Akzenttext. Rechts davon (Desktop) bzw. darunter (mobil) drei leise Icon-Buttons: Anlegen, Bearbeiten, Löschen.
  • Monatskopf: „‹“ Monatsname Jahr „›“ zentriert, Monatsname ist Button für die bestehende Monatswahl. Darunter Kennzahlen-Zeile: „Diesen Monat 21“, „Diese Woche 3 / 5“, „Serie 4 Tage“ (Serie = aufeinanderfolgende Tage mit Zähler ≥ Tagesminimum bzw. ≥ 1 ohne Minimum, endend heute oder gestern; im HabitService berechnen, keine Schemaänderung).
  • Kalender: 7 Spalten, Zellen quadratisch (mobil ≈ 44 px, Desktop 56 px), Radius 10 px. Zelle zeigt Tagesnummer 12 px oben links und Zählwert 16 px zentriert; Hintergrund abgestuft: 0 → --wj-panel-2, unter Tagesminimum → --wj-clay-soft, im Ziel → --wj-accent-soft, über Tagesmaximum → --wj-amber-soft; ohne Grenzen: 0 → --wj-panel-2, > 0 → --wj-accent-soft. Heute mit 2 px Akzentrahmen (calendar-today), Nachbarmonat 45 % Deckkraft, Zukunft nicht klickbar. Wochenzeile rechts mit Wochensumme (bestehende Wochensummen-Anzeige bleibt, kompakter).
  • Tages-Detail: Tippen auf eine Zelle öffnet mobil ein Bottom-Sheet mit dem HabitCounter für diesen Tag (Desktop: Popover-Dialog), inklusive Grenzen und Neu laden.
  • Konfigurationsdialog (Name, Aktiv, vier Grenzen): als Sheet/Dialog mit Feldern in zwei Spalten (Tag min/max, Woche min/max) ab 400 px Breite, Hilfetext habit.limitHelp als kleiner Absatz.

5.5 Übrige Seiten

Berichte, Kunden & Projekte, Einstellungen und Admin übernehmen nur Tokens, Rhythmus, Kartenstil, Button-Hierarchie und Seitenkopf. Keine Neuanordnung. Balken in Berichten nutzen --wj-accent auf --wj-accent-soft. Die Admin-Seite wird in der Nachfolgespezifikation neu geschnitten.

5.6 Login-Seite, Offline- und Wartungsseite

login.css, offline.html und die Wartungsseite übernehmen dasselbe Token-Set, Schrift, Radien 14/10 px, Button-Hierarchie und Fokusstil. Die Karte der Login-Seite bekommt 24 px Padding mobil, Radius 14 px, keinen 80 px-Schatten. Struktur, Formulare, IDs und Texte bleiben unverändert; alle Workflow-Änderungen kommen mit auth-flow-refresh.md.

6. Technische Umsetzungshinweise

  • CSS ausschließlich in styles.css und login.css; Kotlin-Views setzen Klassen und Struktur. Keine Inline-Styles außer für berechnete Fortschrittsbreiten (style="--wj-progress: 62%").
  • Bottom-Sheet: Vaadin Dialog mit addClassName("wj-sheet") und ::part(overlay)-Styling (position: fixed; inset: auto 0 0 0; border-radius: 20px 20px 0 0; max-height: 92dvh), Klasse nur ≤ 600 px wirksam. Header und Footer des Dialogs verwenden.
  • Stunden-Pills: Div mit Buttons aria-pressed, die den Wert des IntegerField setzen; Wert-Änderungen am Feld (auch durch Draft-Wiederherstellung) synchronisieren die Pills.
  • Bottom-Nav-Labels: bestehende RouterLinks um Span mit Text erweitern; aria-label beibehalten.
  • Mockups sind statische HTML-Dateien und werden nicht ausgeliefert; nichts aus docs/plans/mockups in src kopieren, nur die Werte übernehmen.
  • Vaadin-Komponenten, bei denen Lumo-Styling nicht ausreicht, über ::part(...) stylen; kein Shadow-DOM-Piercing über Skripte.

7. Umsetzungsreihenfolge

  1. Selektor-Inventar der Browser-Tests erstellen und im Ergebnisdokument festhalten. Werkbaum [~], Version, Push.
  2. Tokens: gemeinsames Token-Set in styles.css und login.css, Lumo-Ableitung, alte Variablen umstellen. Screenshots hell/dunkel als Referenz.
  3. Shell: Navbar, Bottom-Nav mit Labels, Drawer, Seitenkopf, Sheet-Basisstil.
  4. Today: Hero-Karte mit Kennzahlen und Spuren (Service-Abfrage), Eintragsliste, kompakte Habit-Karten.
  5. Arbeit: Tagesnavigation, Tageskarte mit Freier-Tag-Toggle, Eintragskarten, Formular als Sheet mit Stunden-Pills, Entwurfs-/Konfliktkarten.
  6. Habits: Pill-Leiste, Monatskopf mit Kennzahlen (Serie im Service), Kalenderzellen mit Zielabstufung, Tages-Sheet, Konfigurationsdialog.
  7. Übrige Seiten, Login/Offline/Wartung nur Tokens.
  8. Abnahme nach Abschnitt 8, Ergebnisdokument, Werkbaum [x], README.

8. Abnahme

  • ./gradlew test -Pproduction=true und ./gradlew firefoxAcceptance (mit JAVA_HOME auf das gepinnte JDK) ohne Fehler; Anzahl Szenarien im Ergebnisdokument.
  • tools/test-frontend (Frontend-JavaScript-Tests) ohne Fehler.
  • Screenshots aus dem laufenden Produktions-JAR bei 360 × 780, 390 × 844 und 1280 × 900, jeweils hell und dunkel: Today, Arbeit mit geöffnetem Sheet, Habits-Kalender, Login. Testdaten dafür: vier Arbeitseinträge über drei Kunden am selben Tag und drei aktive Habits mit Grenzen. Kein horizontales Scrollen; alle Texte lesbar; Bottom-Nav verdeckt keinen Inhalt; Today bei 390 × 844 vollständig ohne Scrollen sichtbar.
  • Manuelle Prüfung im Chromium-Gerätemodus: Erfassen über Today → Sheet → Speichern → zurück auf Today; Habit hochzählen; Kalenderzelle öffnen und zählen; Theme in Einstellungen umschalten; Sprache umschalten.
  • Kontrastwerte der in 4.6 genannten Kombinationen im Ergebnisdokument.
  • Keine Fehler in der Browserkonsole während der manuellen Prüfung.