From 82cf21085def44be9fefc6ebc387b7cc7c9aee46 Mon Sep 17 00:00:00 2001 From: fs Date: Mon, 27 Jul 2026 10:33:53 +0200 Subject: [PATCH] Design-System: Fokus vereinheitlichen, Formularfeld-Ring WCAG-fest machen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Letzter Teil. base.css hatte längst eine globale :focus-visible-Regel, trotzdem existierten 15 Fokus-Regeln — die meisten davon Ballast. Fünf Overrides wiederholten die Basisregel praktisch wortgleich (.back-to-top, .ad-banner__dot, .faq__q, .table-scroll, .btn) und sind ersatzlos entfallen; sie unterschieden sich höchstens um 1px Offset. Die Basisregel selbst läuft jetzt über --focus-ring/--focus-offset, .position-card__head wechselt von Akzentrot auf Weiß. Übrig bleiben zehn Regeln, davon deklarieren nur noch vier überhaupt eine outline — jede mit Grund (inset-Offset bei .tab und .position-card__head, geschichteter Ring beim Formularfeld). Die anderen sechs sind reine Zusatz- effekte (transform, Farbe, Fläche) und lassen den Basis-Ring durch. Der eigentliche Fund steckte im Formularfeld: es setzte outline: none und ersetzte den Ring durch einen roten Rahmen mit 30%-Glow. Akzentrot erreicht auf der Feldfläche aber nur 2,8:1 und verfehlt damit WCAG 1.4.11 (>=3:1) für Fokus-Indikatoren — Tastaturnutzer hatten dort also den schwächsten Fokus der ganzen Seite. Roter Rahmen und Glow bleiben als Marken-Signal, der weiße Standard-Ring kommt zurück; outline-offset entspricht der Glow-Breite, beide Ringe liegen bündig nebeneinander statt übereinander. CLAUDE.md dokumentiert die neuen Regeln: Token-Disziplin mit Tabelle (Spacing, Typo, Icons, Sperrung, Fokus, Trefferfläche) samt der bewussten em-Ausnahme, das Button- und Tab-System inklusive der (0,2,0)-Falle durch die CSS-Ladereihenfolge, und die Fokus-Regel. Dazu ein Punkt in der Checkliste. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01MSsVdooFLgPA8gPFp7HwZU --- CLAUDE.md | 45 +++++++++++++++++++++++++++++++- public/assets/css/base.css | 5 ++-- public/assets/css/components.css | 27 ++++++------------- public/assets/css/layout.css | 5 ---- public/assets/css/utilities.css | 5 ---- 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d409d74..b8e8611 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -138,10 +138,51 @@ Sichtbare FAQ + FAQPage-Schema aus derselben `data/*.json`-Quelle, damit Inhalt - Headings: Coolvetica, uppercase, line-height ~0.85. Body: Abel. Beide self-hosted als woff2. - **Coolvetica nie kleiner als `--fs-650` (28px)** — der schmale Condensed-Schnitt wird in Uppercase darunter unleserlich (mehrfach bestätigt: Footer-Headings, Timeline-Nav). Für kleinere Auszeichnungen - Abel verwenden, ggf. mit `letter-spacing` + uppercase. + Abel verwenden, ggf. mit `letter-spacing` + uppercase. `base.css` setzt das durch: `h1`–`h3` tragen + Coolvetica, **`h4`–`h6` laufen über `--ff-body` + uppercase + `--ls-caps`**. - Rot nie für Fließtext auf dunklem Grund (Kontrast!) — nur als Button-/Akzent-Fläche mit weißem Text. - Alle Werte als CSS Custom Properties in `tokens.css`; Breakpoints: 1249 (Burger) / 1024 / 992 / 768 / 600 / 500. +### Token-Disziplin (gilt für jede CSS-Änderung) + +Keine rohen Werte in `base/layout/components/utilities.css` — es gibt für alles eine Stufe: + +| Was | Token | Anmerkung | +|---|---|---| +| `padding` / `margin` / `gap` | `--space-4xs … --space-7xl` (14 Stufen, 4px-Raster) | `--space-4xs` (2px) **nur** für optische Korrekturen (Icon-/Baseline-Nudges), nie fürs Layout | +| `font-size` (Text) | `--fs-300 … --fs-1000` | `--fs-550`/`--fs-690` sind die fluiden Zwischenstufen (Lead, Karten-Überschrift) | +| `font-size` (Icons) | `--icon-s/m/l/xl` (rem), `--icon-inline-sm/--icon-inline/--icon-inline-lg` (em) | em-Stufen für Icons, die mit ihrer Textzeile mitwachsen sollen | +| `letter-spacing` | `--ls-tight/caps/wide/wider` | | +| Fokus | `--focus-ring` / `--focus-offset` | | +| Trefferfläche | `--tap-min` (44px) | | + +**Ausnahmen, bewusst roh:** `em`-Werte, die mit der `font-size` skalieren sollen (Button-Padding +`--btn-pad-*`, Badge-Innenabstände) — die gehören nicht auf ein festes px-Raster. + +### Buttons & Trefferflächen + +- Varianten in `utilities.css`: `.btn` (primary) · `.btn--outline` · `.btn--ghost` (tertiär, ohne Fläche) + · `.btn--icon` (quadratisch, nur Icon + `aria-label`) · `.btn--sm` / `.btn--lg`. + `.btn` ist `inline-flex` mit `gap` — Icon + Label brauchen **kein** Zusatz-Markup und keinen eigenen Abstand. +- Tabs (Filterleiste wie Panel-Tabs) laufen über die gemeinsame **`.tab`**-Basis in `components.css`; + aktiv wird über `aria-pressed` **oder** `aria-selected` erkannt. Nie eine dritte Tab-Optik bauen. +- **Jedes Control ≥ `--tap-min` (44px, WCAG 2.5.5).** Soll es optisch kleiner bleiben, streckt + `.tap-target` die Trefferfläche unsichtbar per `::after` (bei `.btn--sm` automatisch). Voraussetzung: + kein `overflow: hidden`, `::after` frei. In Reihen (Nav, Footer) stattdessen `min-height` verwenden — + überlappende Pseudo-Flächen würden sonst den Nachbarn verdecken. +- Ausnahme: die Formular-Checkbox bleibt bei 24px (WCAG 2.5.8). `` ist ein Replaced Element, + `::after` greift dort nicht zuverlässig; das klickbare `