Files
tickte-system/docs/superpowers/plans/2026-10-05-weisses-design-p1-tote-klassen.md
T

179 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P1 Task 4: tote Klassen und Übergangsschicht KOMPAT
Ergebnis des Klassen-Abgleichs mit `css-klassen.mjs` (Werkzeug-Repo `$W`). Zeilenangaben beziehen sich auf `global.css` im Stand `a6877aa` (vor diesem Commit). Spec: Abschnitt „Übergangsschicht KOMPAT“.
## Werkzeug
`node "$W/css-klassen.mjs" "$WT" [--ohne-ausnahmen] [--mit-neu]` gibt JSON aus: `{ defined, used, dead, undefinedUsed }` und dazu `definedAt` (Name → Datei:Zeile), `prefixes`, `ausnahmen`, `laufzeit`, `neuOhneBenutzer`, `counts`.
- **Definiert:** Klasse in einem Selektor in `global.css`, `chat.css`, `serverpuls.css`, `admin-areas.css` oder `pages/AdminPage.css` (Regeln in `@media` und `@container` zählen, `@keyframes` nicht). Geparst mit `postcss`.
- **Benutzt:** Wort in einem `className`-Ausdruck in `src/**/*.jsx` (Literale, Template-Strings, Zweige von `?:`, rechte Seite von `&&`, Teile einer `+`-Kette; Bedingungen und Vergleiche wie `filter === 'all'` zählen nicht; ein Ergebnis, das an Text klebt wie `fin-todo-${x || 'info'}`, ist nur ein Namensteil). Dazu Wörter aus Zeichenketten in `src/lib/*.js` und `src/hooks/*.js`, die eine definierte Klasse sind. Geparst mit `@babel/parser`.
- **Präfixe:** `xxx-${…}` oder `'xxx-' + …` deckt `xxx-*`.
- **Ausnahmeliste** (entfällt mit `--ohne-ausnahmen`): `fin-neg`, `fin-fixed-off`, `legal-tone-*`, `legal-version-*`, `badge-*`, `status-*`, `ticket-tab-active`, `ui-btn-*`, `side-dot-*`, `woms-chat`, `chat-*`.
- **NEU-Bereiche:** Regeln zwischen den Kommentaren `NEU-ANFANG` und `NEU-ENDE` in `global.css` (Basis, Hilfsklassen und Bausteine aus Task 2 und 3) sind das neue System; ihre Benutzer entstehen in P1 Task 5 bis 8 und in P2 bis P9. Eine Klasse mit einer Regel dort gilt nie als tot und steht in `neuOhneBenutzer` (mit `--mit-neu` zählt sie normal, so findet P10 unbenutzt gebliebene neue Klassen). Ohne diese Trennung stünden 77 neue Klassen als „tot“ in der Liste.
- **Laufzeit-Klassen** (gelten immer als benutzt): `u-*` (uPlot erzeugt `u-legend` im DOM) und `mine` (Modifikator der Sprechblasen des Chat-Bausteins aus dem Kundenportal, gesetzt über `renderMessage(…, { mine })` in `ChatThread.jsx`).
## Ergebnis
| Lauf | definiert | tot |
|---|---|---|
| Vor P1 (`bd84d22`, ohne NEU-Bereiche) | 514 | **67** |
| Vor diesem Task (`a6877aa`), roh | 594 | 144 |
| davon Laufzeit-Klassen (`mine`, `u-legend`) | | 2 |
| davon NEU-Bereiche (Task 2 und 3, noch ohne Benutzer) | | 77 |
| **Kandidaten (Altlast)** | | **65** |
| Nach diesem Task | 524 | 3 (siehe Gegenprobe) |
Erwartet waren etwa 66 Namen (Grenzen 40 und 90). Der Lauf auf dem Stand vor P1 ergibt 67, die Altlast-Kandidaten im aktuellen Stand 65: Die Differenz sind `link-danger`, `num`, `nowrap`, `small`, `strong` und `xs` (jetzt NEU) sowie `mine` und `u-legend` (Laufzeit), dazu kommen `stat-label` und `stat-value` wie unten.
## Gegenprobe
Für jeden der 65 Kandidaten: `rg -w <name> src --glob '!*.css'`. Bei Treffern zusätzlich mit genauer Wortgrenze (`rg -e '(^|[^A-Za-z0-9_-])<name>($|[^A-Za-z0-9_-])' --glob '!*.css' src`), weil `-w` den Bindestrich als Wortgrenze behandelt und `stat-value` in `fin-stat-value` „findet“.
- 62 Kandidaten: 0 Treffer.
- `stat-label`, `stat-value`: je 3 Treffer, alle in `fin-stat-label` und `fin-stat-value` (`AboCard.jsx`); mit genauer Wortgrenze 0, also tot.
- `success`: 71 Treffer, wirklich benutzt: `AdminPage.jsx` Zeile 25 setzt `admin-notice ${notice.type}` (`success` oder `error`). Bleibt.
- `admin-status`, `admin-empty-line`: 0 Treffer, tot, aber in `pages/AdminPage.css`, das nicht zu diesem Paket gehört (Task 9 und P8 fassen die Datei an). Bleiben vorerst.
Gelöscht sind damit 62 Namen aus `global.css`.
| Klasse | Definition (Stand `a6877aa`) | `rg -w` Treffer | Ergebnis |
|---|---|---|---|
| `admin-empty-line` | pages/AdminPage.css:361, pages/AdminPage.css:372 | 0 | tot, bleibt vorerst: Datei liegt ausserhalb dieses Pakets (P8 baut die Admin-Seite um) |
| `admin-status` | pages/AdminPage.css:280, pages/AdminPage.css:293 | 0 | tot, bleibt vorerst: Datei liegt ausserhalb dieses Pakets (P8 baut die Admin-Seite um) |
| `bg-amber` | global.css:494 | 0 | gelöscht |
| `bg-black` | global.css:487 | 0 | gelöscht |
| `bg-blue` | global.css:490 | 0 | gelöscht |
| `bg-blue-grey` | global.css:491 | 0 | gelöscht |
| `bg-dark-grey` | global.css:484, global.css:748, global.css:761 | 0 | gelöscht |
| `bg-green` | global.css:488 | 0 | gelöscht |
| `bg-light-grey` | global.css:485 | 0 | gelöscht |
| `bg-orange` | global.css:495 | 0 | gelöscht |
| `bg-teal` | global.css:489 | 0 | gelöscht |
| `bg-white` | global.css:486 | 0 | gelöscht |
| `bg-yellow` | global.css:493 | 0 | gelöscht |
| `btn-secondary` | global.css:593 | 0 | gelöscht |
| `col-12` | global.css:695 | 0 | gelöscht |
| `container` | global.css:504 | 0 | gelöscht |
| `control-panel-section` | global.css:1009, global.css:1014 | 0 | gelöscht |
| `dashboard-section` | global.css:1238 | 0 | gelöscht |
| `drop-zone` | global.css:963, global.css:972 | 0 | gelöscht |
| `fade-in` | global.css:1041 | 0 | gelöscht |
| `flex-col` | global.css:1321 | 0 | gelöscht |
| `form-select` | global.css:638, global.css:654, global.css:1308, global.css:1309 | 0 | gelöscht |
| `gap-1` | global.css:1324 | 0 | gelöscht |
| `gap-4` | global.css:1324 | 0 | gelöscht |
| `mb-1` | global.css:707 | 0 | gelöscht |
| `modal-content` | global.css:904 | 0 | gelöscht |
| `modern-card` | global.css:993, global.css:1003, global.css:1306, global.css:1307 | 0 | gelöscht |
| `mt-1` | global.css:704 | 0 | gelöscht |
| `nav-link` | global.css:545, global.css:553 | 0 | gelöscht |
| `nav-right` | global.css:558 | 0 | gelöscht |
| `navbar` | global.css:518 | 0 | gelöscht |
| `navbar-brand` | global.css:531 | 0 | gelöscht |
| `navbar-nav` | global.css:540, global.css:1095 | 0 | gelöscht |
| `priority-high` | global.css:838 | 0 | gelöscht |
| `priority-low` | global.css:836 | 0 | gelöscht |
| `priority-medium` | global.css:837 | 0 | gelöscht |
| `priority-none` | global.css:835 | 0 | gelöscht |
| `quick-actions` | global.css:1239 | 0 | gelöscht |
| `side-group-label` | global.css:1134, global.css:1138 | 0 | gelöscht |
| `slide-in` | global.css:1045 | 0 | gelöscht |
| `slider` | global.css:916, global.css:926, global.css:930, global.css:941, global.css:946, global.css:957 | 0 | gelöscht |
| `slider-container` | global.css:911 | 0 | gelöscht |
| `spacer` | global.css:609 | 0 | gelöscht |
| `stat-card` | global.css:1234 | 0 | gelöscht |
| `stat-info` | global.css:1235 | 0 | gelöscht |
| `stat-label` | global.css:1237 | 3, alle nur Teil von `fin-stat-label` | gelöscht |
| `stat-value` | global.css:1236 | 3, alle nur Teil von `fin-stat-value` | gelöscht |
| `stats-grid` | global.css:1233 | 0 | gelöscht |
| `success` | pages/AdminPage.css:99 | 71 | bleibt: dynamischer Modifikator `admin-notice ${notice.type}` (AdminPage.jsx:25, Typen `success`/`error`) |
| `table-hover` | global.css:600, global.css:604 | 0 | gelöscht |
| `text-black` | global.css:498 | 0 | gelöscht |
| `text-green` | global.css:500 | 0 | gelöscht |
| `text-large` | global.css:701 | 0 | gelöscht |
| `text-right` | global.css:699 | 0 | gelöscht |
| `text-small` | global.css:700 | 0 | gelöscht |
| `text-xlarge` | global.css:702 | 0 | gelöscht |
| `ticket-collapsed` | global.css:742, global.css:748 | 0 | gelöscht |
| `ticket-expanded` | global.css:755, global.css:761 | 0 | gelöscht |
| `ticket-id` | global.css:742, global.css:755, global.css:794, global.css:807 | 0 | gelöscht |
| `ticket-id-expanded` | global.css:807, global.css:811 | 0 | gelöscht |
| `ticket-info` | global.css:820 | 0 | gelöscht |
| `ticket-row` | global.css:715, global.css:720, global.css:727, global.css:731, global.css:735 | 0 | gelöscht |
| `ticket-time` | global.css:815 | 0 | gelöscht |
| `worksheet-cell` | global.css:771, global.css:777 | 0 | gelöscht |
| `worksheet-expansion` | global.css:767 | 0 | gelöscht |
## Nicht gelöscht, obwohl der Abgleich sie roh nennt
- **NEU (77, Task 2 und 3, Benutzer folgen):** `actions`, `brand`, `btn-block`, `btn-primary`, `btn-quiet`, `cell-sub`, `cell-title`, `check`, `code-input`, `count`, `critical`, `crumb`, `dialog`, `dialog-body`, `dialog-close`, `dialog-foot`, `dialog-head`, `dialog-wide`, `err`, `eyebrow`, `fact`, `facts`, `field-row`, `field-row-3`, `hide-md`, `hide-sm`, `hint`, `hot`, `input`, `is-invalid`, `k`, `kv`, `link-danger`, `loading`, `login`, `login-box`, `login-foot`, `login-links`, `main`, `menu-open`, `mobile-bar`, `msg`, `nav`, `nav-count`, `nav-dot`, `nav-item`, `neg`, `nowrap`, `num`, `page-head`, `paused`, `prose`, `right`, `scrim`, `search`, `section`, `select`, `select-quiet`, `shell`, `sidebar`, `sidebar-foot`, `small`, `stat`, `stats`, `strong`, `sub`, `sw`, `tab`, `table`, `table-foot`, `tabs`, `textarea`, `toast`, `two-col`, `v`, `who`, `xs`
- **Laufzeit (2):** `mine`, `u-legend`.
- **Nur durch die Ausnahmeliste am Leben** (Lauf mit `--ohne-ausnahmen`, 6 Namen): `chat-bubble`, `chat-input-row`, `chat-meta` (Sprechblasen und Eingabezeile kommen zur Laufzeit aus dem Chat-Baustein des Portals), `ui-btn-danger`, `ui-btn-sm` (`Button.jsx` setzt sie über die Tabelle `VARIANTS` und `size`; beide stehen in KOMPAT). `status-occupied` hat keinen Benutzer: `statusClass()` in `lib/ticketStatus.js` liefert nur `status-open`, `-working`, `-awaiting`, `-assigned` und `-closed`. Es ist gelöscht, die übrigen fünf stehen in KOMPAT.
## Zusätzlich gelöscht (nicht tot, laut Plan)
- Alle `!important` in `global.css`: 77 vorher, 0 nachher. Offen bleiben 6 in `pages/AdminPage.css` und 2 in `admin-areas.css` (beide Dateien gehören nicht zu diesem Paket; Task 9 und P8).
- `.btn-green, .btn-primary { … !important }` samt Hover und `.btn-secondary`; `.btn-dark`, `.btn-teal`, `.btn-green` stehen neu in KOMPAT.
- `.footer` (zweimal), `.navbar*`, `.nav-link`, `.nav-right`, `.ticket-row*`, `.ticket-collapsed`, `.ticket-expanded`, `.ticket-id*`, `.ticket-time`, `.ticket-info`, `.worksheet-expansion`, `.worksheet-cell`, `.slider*`, `.drop-zone`, `.modern-card`.
- Die Legacy-Responsive-Regeln (`@media (max-width: 768px)` mit `.col-6`, `.navbar-nav`, `.ticket-tab`); `.col-6 { width: 100% }` unter 768 px steht neu in KOMPAT.
- Die Keyframes `slideDown`, `fadeIn` und `slideIn` (`WorksheetList.jsx` bringt eigene in einem `<style>`-Block mit).
- `.kpi*` einschließlich `.kpi-grid`: `Kpi` rendert ab Task 6 `Stat`; bis dahin hat `Kpi` kein Styling. `.fin-stack .kpi-grid` und `.fin-head .kpi-value` im Finanz-Teil bleiben (Task 9).
- `.priority-none`, `-low`, `-medium`, `-high` (tot); `.priority-critical` und `.status-*` stehen in KOMPAT.
- `.ui-card*`, `.ui-btn*`, `.badge-*`, `.form-group`, `.form-label`, `.form-control` (und `.form-select`, tot), `.card*`, `.row`, `.col`, `.col-6`, `.dropdown*`, `.spinner`, `.overlay-content`, `.ticket-tab*` und die Regeln „Soften legacy“: durch KOMPAT-Zeilen ersetzt.
- `.fin-form-field .form-control[aria-invalid="true"] { border-color: … !important }`: ersetzt durch die roten Ringe aus Task 3 (`.form-control[aria-invalid="true"]`).
- Die Aliasvariable `--sidebar-w-collapsed` (Task 2).
- Die toten Hilfsklassen `.flex-col`, `.gap-1`, `.gap-4`, `.container`, `.mt-1`, `.mb-1`, `.text-right`, `.text-small`, `.text-large`, `.text-xlarge`, `.col-12`, `.bg-*` außer `.bg-red`, `.text-black`, `.text-green` (stehen in der Tabelle oben).
### Abweichung: `.side*` bleibt bis Task 5
Der Plan nennt `.side*` zum Löschen. Das alte Menü (`Navbar.jsx`) benutzt sie aber bis Task 5. Ohne sie fällt das Alt-Gerüst `.app-shell` zusammen: Der Lauf `shots.sh --gate p1` brach auf fast allen Ansichten mit `step-failed` ab, weil das ungebremste Menü den Inhalt verdrängte (auf dem Handy auch ohne die Regel für `.collapsed`). Die Regeln stehen deshalb unverändert in einem eigenen Teil des KOMPAT-Blocks („Altes Menü“). Geändert sind nur `--sidebar-w-collapsed` (jetzt `72px`) und das tote `.side-group-label` (entfernt). **Task 5 löscht diesen Teil**; dafür muss `global.css` in die Dateiliste von Task 5. `.side-count` und `.side-logo` stehen wie im Plan als eigene KOMPAT-Zeilen.
## KOMPAT-Zeilen (Selektor → Look)
| Selektor | Look |
|---|---|
| `.ui-card`, `.ui-card.pad`, `.ui-card-head`, `.ui-card-head h3`, `.ui-card-body` | Abschnitt ohne Kasten, Kopf wie `h2.section` (16/24, 600) |
| `.ui-btn`, `.ui-btn-primary`, `.ui-btn-danger` | wie `.btn` (weiß, Ring, 32 px), `.btn-primary` (schwarz), `.link-danger` (roter Textlink); `-ghost` und `-sm` ohne eigene Regel (wirken wie `.ui-btn`) |
| `.btn-dark`, `.btn-teal`, `.btn-green` | wie `.btn-primary` |
| `.form-group`, `.form-label`, `.form-control` (mit `textarea`, `select`, `:focus`, `[readonly]`, Platzhalter) | wie `.field`, Beschriftung 500, `.input`/`.select`/`.textarea` |
| `.badge-muted`, `-info`, `-warn`, `-ok`, `-danger` | Badge-Töne grau, blau, orange, grün, rot |
| `.status-open`, `-working`, `-awaiting`, `-assigned`, `-closed`, `.priority-critical` | grau, blau, orange, violett, „plain“ (geschlossen und storniert teilen sich die Klasse), rot |
| `.overlay:has(> .overlay-content)` | `overflow-y: auto`, `align-items: flex-start`, Abstand 24/16, Hintergrund `--overlay`, ohne Einblend-Animation |
| `.overlay-content` (und `.overlay-content.fin-dialog`) | weiße Box: 100 %, max. 520 px (760 px bei `.fin-dialog`), Radius 12, `--shadow-pop`, Abstand 24, Schrift `--text` |
| `.overlay-close` | fest oben rechts, 32×32, weißer runder Knopf, „ד in `--text-2` |
| `.seg button.active` | wie `.seg button.on` |
| `.bg-red` (mit `.text-white` oder ohne), `.text-grey`, `.text-red` | kein Hintergrund, `--red-fg`, 13 px; `--text-2`; `--red-fg`. `.text-white` allein hat keine Regel |
| `.side-count`, `.side-logo` | kleine graue Zahl; Initiale ohne Verlauf |
| `.card`, `.card-header`, `.card-body` | neutral: ohne Kasten, Kopf mit Haarlinie |
| `div.row`, `.col`, `.col-6` (unter 768 px 100 %) | Raster ohne Look; `div.row`, damit `tr.row` unberührt bleibt |
| `.dropdown`, `.dropdown-content`, `.dropdown-item` | weißes Popover mit `--shadow-pop` |
| `.spinner` | grauer Ring |
| `.page .page`, `.page .main-content` | Abstand und Breite aufgehoben |
| `.fin-link`, `.legal-files a`, `.credit-cols a`, `.area-rows a` | feiner Unterstrich (`--line-strong`, beim Überfahren `currentColor`) |
| `.ticket-tabs`, `.ticket-tab`, `.ticket-tab-active`, `.ticket-tab-content` | wie `.tabs` und `.tab` (Unterstrich statt Kasten); nicht in der Spec-Tabelle, aber `Tabs.jsx` bleibt bis Task 6 |
| `.side*` („Altes Menü“) | siehe Abweichung oben; Task 5 löscht den Teil |
Das `:has()` der Alt-Dialoge ist nötig, damit `^\.overlay *\{` genau einmal trifft (Grundregel des neuen `.overlay > .dialog`).
Die Einblend-Animation des neuen `.overlay` (`fade`, Deckkraft 0 → 1) ließ `submitReachable` mit „kein offener Dialog gefunden“ scheitern, wenn der Dialog im ersten Bild geprüft wurde (`checkVisibility` mit `checkOpacity`). Alt-Dialoge hatten nie eine Animation, deshalb `animation: none` in KOMPAT. Task 7 muss dasselbe für `Dialog` lösen, z. B. mit `@media (prefers-reduced-motion: reduce) { .overlay, .dialog { animation: none; } }` (der Lauf setzt `reducedMotion: 'reduce'`).
Zusätzlich: `.datetime-pair input[type="date"]` bekommt `flex: 1.3`, weil das Datum im 520-px-Dialog sonst das Jahr abschneidet.
## Benutzt, aber ohne Regel (`undefinedUsed`)
Der Lauf nach diesem Task nennt 67 Namen. Der Lauf auf dem Stand vor P1 (`bd84d22`) nannte 58 davon schon; neu sind 9, alle gewollt:
| Name | Grund |
|---|---|
| `dot`, `empty-icon` | Task 3 hat die Regeln mit dem neuen `.badge` und `.empty` ersetzt; Task 6 baut `Badge` und `EmptyState` um (Prop `dot` und `icon` entfallen) |
| `footer` | Regel nach Plan gelöscht; Task 5 löscht `Footer.jsx` |
| `kpi`, `kpi-accent`, `kpi-label`, `kpi-sub` | Regeln nach Plan gelöscht; Task 6 lässt `Kpi` das neue `Stat` rendern |
| `text-white` | Spec: allein keine Regel |
| `ui-btn-ghost` | gleicher Look wie `.ui-btn`, braucht keine eigene Regel |
Die übrigen 58 hatten schon vor P1 keine Regel:
- die Bootstrap-Namen aus `WorksheetList.jsx` (wirkungslos): `alert`, `alert-info`, `align-items-center`, `border-0`, `col-md-6`, `d-flex`, `fs-5`, `fs-6`, `justify-content-between`, `justify-content-md-end`, `mb-3`, `mb-4`, `me-1`, `me-2`, `ms-2`, `ms-3`, `mx-2`, `overflow-hidden`, `p-3`, `px-3`, `py-2`, `py-3`, `rounded-3`, `shadow-sm`, `spinner-border`, `text-dark`, `text-md-end`, `text-muted`, `visually-hidden`, `timeline`, `timeline-item`;
- die Namen aus dem Plan: `p-4`, `btn-sm`, `status-filter`, `supporters-editor` (und `timeline` oben);
- reine Haken ohne Styling: `credits-view`, `fin-abo-amount`, `fin-abo-main`, `fin-abo-next`, `fin-abo-product`, `fin-assign`, `fin-days`, `fin-inv-abo`, `fin-memo`, `fin-tax-card`, `fin-tax-note`, `fin-todo-main`, `fin-total-value`, `fin-tx-out`, `fin-wrap`, `legal-doc`, `offer-form`, `sp-ampel`, `sp-apps`, `sp-cleanup-body`, `status-filter-actions`, `worksheet-list`, `worksheet-supporters`.