# Spezifikation: UI-Refresh — Werkator-Optik und mobile Bedienbarkeit Status: geplant, nicht begonnen. Werkbaum-Knoten `#ui-refresh` unter `#experience`. Entwürfe: [mockups/ui-refresh.html](mockups/ui-refresh.html) (im Browser öffnen; Umschalter für Hell/Dunkel oben rechts). Nachfolger: [auth-flow-refresh.md](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](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](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 `RouterLink`s 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.