# T5 Optik mit eigener Handschrift — Design
Stand: 2026-10-14, Nachtrag 2026-10-16 (§17 Bewegungs-Sprache, Frage 4 in §16; Anlass Beute-Spec §12.4, Issue #26) · Betrifft: ApiCore-Frontend (plus ein kleiner Zusatz am Backend-Endpunkt `GET /autopilot/today`) · Teilprojekt T5 aus `docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md` §10
## 1. Ziel
ApiCore soll man draußen am Stand lesen können: in der Mittagssonne, mit Handschuhen, mit einer Hand. Und man soll es auf den ersten Blick als Imker-App erkennen, nicht als Verwaltungsvorlage.
- Jeder Text und jedes Bedienelement erfüllt WCAG 2.2 AA. Die wichtigen Stellen liegen deutlich darüber, damit noch genug Kontrast übrig bleibt, wenn die Sonne auf dem Display spiegelt.
- Es gibt hell, dunkel und einen Kontrastmodus „Sonne“. Der Wechsel geht mit einem Tipp und flackert nicht.
- Ein Motiv trägt die Handschrift: **die Wabenzelle**. Sie zeigt den Zustand der Völker (Waben-Standkarte, Kartenmarker), sitzt am Zeiger des Bienenjahr-Rads, rahmt die Bereichs-Icons und bildet das Markenzeichen. Verläufe, Glas-Effekte und Zierbewegung fallen weg.
- Der Baukasten wird durchgesetzt. Jede Auswahlgruppe, jede Checkbox, jede Tab-Leiste und jedes Plus/Minus-Feld kommt aus genau einem Baustein, mit einem gemeinsamen Fokusstil.
Technisch heißt das:
- Farben stehen nur noch als Tokens in `globals.css`. Es gibt vier geprüfte Sätze: hell, dunkel, Sonne hell, Sonne dunkel. Ein Wächter-Test misst jedes Paar aus Abschnitt 4.4. Ein Token, das einem Satz fehlt, lässt den Test scheitern.
- Neue Grafiken sind handgeschriebenes SVG, wie heute das Varroa-Diagramm. Keine neue Laufzeit-Bibliothek. `next-themes` fliegt raus.
- Wo T4-Daten (Saison, nächste Schritte, Varroa-Bänder) schon da sind, zeigen Rad und Lebenslinie sie an. Fehlen sie, greift ein Kalender-Rückfall. Die Oberfläche funktioniert vor T4 und bricht nach T4 nicht.
**Voraussetzungen:**
- T3-Plan `docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md`: Tasks 7 (Navigation, `nav-config.ts`, Sheets), 8 (`NumberStepper`, `RatingScale` mit Richtung und Tönen, Kontrast-Wächter), 11 (Varroa-Trend) und 14 (Stand-Seite mit Ampel, `colonyStatusLight`, `StatusLightBadge`) sind gemergt. T5 baut darauf auf und nichts davon neu.
- Für T5b: T4-Plan `docs/superpowers/plans/2026-10-13-t4-logik-ketten.md`, Lieferung T4a mit den Tasks 13, 15, 17, 18 und 19, ist gemergt. T4b (Tasks 25, 26, 31) ist optional; ohne T4b gilt die Saison nach Kalender.
### Bindende Vorgaben (Inhaber, aus Fahrplan, T3 und T4)
- ADHS-freundlich: wenig kognitive Last, ein Hauptknopf je Ansicht, kurze deutsche Sätze, Zustand nie nur über Farbe (immer Icon plus Wort).
- Sicherheit hat Priorität 1, Konsistenz ist oberstes Gesetz: ein Muster, gemeinsame Bausteine, keine Kopien.
- Touch-Ziele mindestens 44 px, Sheet-Zeilen 56 px. WCAG 2.2 AA.
- Dark Mode wird angeschlossen, sonst fliegen die Tokens raus (Fahrplan §10). Diese Spec schließt ihn an.
- Vor jedem Next.js-Code die passende Anleitung unter `ApiCore-Frontend/node_modules/next/dist/docs/` lesen (`AGENTS.md`). Für T5 sind das vor allem `01-app/02-guides/preventing-flash-before-hydration.md`, `progressive-web-apps.md` und `01-app/03-api-reference/03-file-conventions/01-metadata/manifest.md` sowie `app-icons.md`.
### Entscheidungen
| Frage | Entscheidung |
|---|---|
| Wie wird der Hauptknopf lesbar? | **Honig als Fläche, dunkle Tinte als Text** (9,4:1). Das ersetzt Weiß auf Honigverlauf (2,3:1). Für Text, Links, Icons und den Fokusring auf hellen Flächen gibt es ein eigenes Token `--primary-ink` (dunkler Bernstein, 6,5:1). `text-primary` ist verboten, weil heller Honig als Schrift nicht lesbar ist. Abweichung zur Wahl: Offene Frage 1. |
| Wie unterscheidet sich ein gewählter Zustand? | Honigfläche **plus** 2 px Rahmen in Tinte **plus** Haken-Icon. Die Fläche allein hätte gegen die Karte nur 1,9:1. Rahmen und Haken tragen den Zustand, auch für Farbenblinde und in der Sonne. |
| Ampel-Abzeichen im Dunkelmodus | Heute steht dort dunkle Schrift auf dunkler Tönung (1,4:1). Darum bekommt jede Zustandsfarbe drei Tokens: Fläche (`--condition-x`), Text auf der Fläche (`-foreground`) und Text oder Icon auf normalen Flächen und Tönungen (`-ink`). |
| Kontrastmodus | **„Sonne“** als eigener Tokensatz (`html[data-contrast="sun"]`): reinweiße Fläche, fast schwarze Tinte, Rahmen in Tinte, keine Tönungen, Schatten oder Unschärfe, 3-px-Fokus, Nebentext 16 px. Sonne funktioniert hell und dunkel. Schaltbar im Profil und mit einem Tipp im Benutzermenü; `prefers-contrast: more` schaltet Sonne vor, solange der Nutzer nichts gewählt hat. |
| Wie wird umgeschaltet, ohne zu flackern? | Ein kleines Inline-Skript im `
` setzt vor dem ersten Bild `class="dark"`, `data-contrast` und `data-motion` auf `` (Muster aus der Next-Anleitung „Preventing Flash“). Die Werte liegen je Gerät in `localStorage`, wie heute die Bewegungsstufe. `next-themes` wird entfernt. Ein Mechanismus für alle drei Einstellungen. |
| Standard-Farbschema | **Hell**, nicht „Wie Gerät“. Viele Handys stehen dauerhaft auf dunkel; draußen bei Tag ist eine helle Oberfläche besser lesbar. Wahl: Offene Frage 3. |
| Grundschrift | Fließtext, Formular-Beschriftungen, Auswahl-Knöpfe, Listentitel und Hauptknöpfe haben 16 px. Nebentext 14 px. `text-xs` wird 13 px und ist nur für Achsen, Legenden und Fußzeilen erlaubt. In Sonne 16 bzw. 14 px. |
| Kompakte Größen | Kompakt darf nur ein Gerät mit feinem Zeiger (`@media (pointer: fine)`) sein, nicht jeder Bildschirm ab `sm`. Heute bekommt ein Tablet am Stand 32-px-Knöpfe und 36-px-Felder. |
| Fokusstil | **Einer für alles:** 2 px durchgehender Ring in `--ring` mit 2 px Abstand (Sonne: 3 px). Er sitzt als Basisregel auf `:focus-visible`. Komponenten löschen ihn nicht mehr (`outline-none`, `ring-ring/50` werden entfernt). Der Abstand sorgt dafür, dass der Ring gegen den Hintergrund gemessen wird, nicht gegen den Knopf. |
| Ein Motiv | Die Wabenzelle (Sechseck mit spitzer Oberseite) ist das einzige grafische Motiv. Verläufe (`--gradient-honey/-sage/-sky`) werden entfernt, ebenso der Glas-Effekt in Sonne. Das Wabenmuster `HoneycombPattern` bleibt nur auf Login und Herkunftsseite. |
| Waben-Standkarte: Datenquelle | Der bestehende Endpunkt `GET /apiaries/:id/colony-overview` (T3, mit T4-Feldern) je Stand über `useQueries`. Cache und Offline-Paket-Rückfall der Stand-Seite gelten damit mit. Kein neuer Sammel-Endpunkt. |
| Randstärke der Zelle | Wie im Fahrplan zeigt die Randstärke die Tage seit der letzten Durchsicht, aber in **drei Stufen** statt stufenlos: dünn = frisch, mittel = bald fällig, dick und gestrichelt = fällig oder nie durchgesehen. Stufenlose Strichstärken sind draußen nicht unterscheidbar. Die genaue Zahl steht im Namen der Zelle und in der Liste. |
| Lebenslinie und Rad: Daten | Nur vorhandene Endpunkte (Volk, Durchsichten, Varroa, Behandlungen, Fütterungen, Schwarmkontrollen, Historie, Königin; ab T4 `next-steps` und Varroa-Bewertung). Einzige Backend-Änderung: `GET /autopilot/today` bekommt **additiv** den Saisonkalender und `segmentSince` je Stand (9.1). |
| Diagramm-Bibliothek | Keine. Handgeschriebenes SVG wie `colony-varroa.tsx`. Beim Bau den `dataviz`-Skill laden (wie T3/T4). |
| Bewegung | **Geändert 2026-10-16, siehe §17.** Eine Bewegungs-Sprache für die ganze App, abgeleitet aus der Beute: Bewegung nur, wo sie Orientierung gibt (woher kommt das Sheet, was ist weg, was hat geklappt), mit wenigen Tokens und den drei Stufen „Voll“, „Dezent“, „Aus“. Rad, Lebenslinie und Waben bleiben Daten und erscheinen weiter sofort (6.8, 8.5, 9.5). `motion` ist seit der Beute installiert und wird nur dort genutzt, wo CSS es nicht kann. |
| Icons | Lucide wie bisher. Eine Tabelle `AREAS` (Abschnitt 11) ist die einzige Quelle für Icon und Farbton je Bereich. Navigation, Kopfzeilen, „+ Neu“ und T4-Vorschläge lesen daraus. |
| App-Icons | Ein Master-SVG, daraus erzeugte PNGs (192/512 „any“, 192/512 „maskable“, 512 „monochrome“, 180 Apple, Favicon). Die erzeugten Dateien liegen im Repo; das Skript nutzt `sharp` als neue devDependency. |
## 2. Umfang
### 2.1 Im Umfang (§10 T5 → Lösung)
| Punkt aus §10 T5 | Lösung | Abschnitt |
|---|---|---|
| Waben-Standkarte: Stand = Wabe, Volk = Zelle, Füllung über `condition-*` plus Icon, Randstärke = Tage seit Durchsicht | `ApiaryComb` auf der Stand-Seite und der Bienenstände-Liste | 6 |
| Mini-Waben ersetzen die Leaflet-Marker | `L.divIcon` mit SVG-Rosette, Listen-Rückfall | 7 |
| Lebenslinie: senkrechte Zeitleiste, Stärkekurve, Band für Milben pro Tag, Königin als Punkt in Zeichenfarbe | `ColonyLifeline` auf der Volksseite | 8 |
| Bienenjahr-Rad auf dem Dashboard, ersetzt die Zählkacheln | `YearWheel` mit Saison, Fenstern, Zeiger, Aufgabenpunkten | 9 |
| Text auf Hauptknopf ≥ 4,5:1, Rahmen ≥ 3:1, Grundschrift 16 px | neue Tokens, `-ink`-Tokens, Schriftregeln | 4 |
| Optional ein Kontrastmodus | „Sonne“ | 4.3, 5 |
| Dark Mode anschließen oder Tokens raus | angeschlossen, Tokens repariert | 4, 5 |
| Manifest in Markenfarben mit PNG und maskable Icons | neues Markenzeichen, Icon-Satz, Shortcuts | 12 |
| Je ein Baustein für Auswahlgruppe, Checkbox, Tabs, Plus/Minus | `ChoiceGroup`, `Checkbox`/`CheckboxField`, `Tabs`, `NumberStepper` | 10 |
| Feste Icon- und Farbzuordnung pro Bereich | `AREAS`, `AreaIcon` | 11 |
| Fokusstil für alle eigenen Bedienelemente | globale Fokusregel | 4.6, 10.6 |
| Nachtrag 2026-10-16: eine Bewegungs-Sprache für die App, passend zur Beute (Beute-Spec §12.4) | Stufen, Tokens, Regeln je Muster, Wächter | 17 |
| §11 T5-Befunde: Weiß auf Honig 2,3:1, Eingaberahmen 1,56:1, Dark Mode unerreichbar, Auswahlgruppen von Hand, Checkboxen in 4, Tabs in 3 Varianten | alle behoben | 4.4, 5, 10 |
### 2.2 Befunde aus dem Code, die T5 zusätzlich behebt
Gemessen mit derselben OKLCH-Rechnung wie `src/lib/forms/rating-contrast.spec.ts`.
| Befund | Wert heute | Lösung | Abschnitt |
|---|---|---|---|
| Links und Icons in `text-primary` auf dem Seitenhintergrund | 3,66:1 | `--primary-ink`, Codemod für 32 Stellen | 4.2 |
| Fokusring `ring-ring/50` auf der Karte | 1,94:1 (dunkel 2,59) | durchgehender Ring mit Abstand | 4.6 |
| Ampel-Abzeichen (Text auf 15-%-Tönung) im Dunkelmodus | 1,36–1,43:1 | `-ink`-Tokens | 4.2 |
| Warn-Badge im Dunkelmodus | 1,49:1 | `--warning-ink` | 4.2 |
| Aktiver Navigationseintrag (`bg-primary text-primary-foreground`) | 4,04:1 | Honig plus Tinte, 9,38:1 | 4.2 |
| Weiße Icons auf Honigverlauf (Seitenkopf, Karten, Markenzeichen) | 2,39:1 | `AreaIcon`, `BrandMark` | 11, 12 |
| Warn-Icons `text-warning` auf der Karte | 2,90:1 | `text-warning-ink`, 6,09:1 | 4.2 |
| Diagrammfarbe `chart-3` | 2,90:1 | 3,93:1 | 4.2 |
| Ampelfläche „mittel“ als gewählte Skalenstufe | 2,65:1 | 3,03:1, dazu Rahmen und Haken | 4.2, 10.2 |
| Ab `sm` (640 px) Knöpfe 32 px und Felder 36 px, auch auf Tablets mit Touch | – | Kompaktmaß nur bei `pointer: fine` | 4.5 |
| `Toaster` nutzt `useTheme` aus `next-themes` ohne Provider und folgt damit dem System, die App aber nicht | – | eigener Appearance-Hook | 5 |
| `data-motion` wird erst in `useEffect` gesetzt | erster Seitenübergang läuft ungebremst | Inline-Skript setzt es vor dem ersten Bild | 5 |
| `TabSwitcher` und `ActiveHistoryTabs` haben `role="tablist"` ohne Tabpanel und ohne Pfeiltasten | – | ein `Tabs`-Baustein auf Base UI | 10.4 |
| Farbverläufe je Seite von Hand gewählt (Königinnen Salbei, Kalender Himmel, Inventar mal Salbei, mal Himmel) | – | Farbe aus `AREAS` | 11 |
| Abweichende Icons: Ernte-Detail `Boxes` statt `Scissors`, Schleuderung neu `Droplet` statt `FlaskConical`, Lager zusätzlich `Package` (= Abfüllung) | – | eine Quelle `AREAS` | 11 |
| Manifest: `theme_color #0a0a0a`, `background_color #ffffff`, nur `icon.svg`; das Icon zeigt drei gelbe Balken statt des Markenzeichens | – | neuer Icon-Satz | 12 |
| Leaflet-Popups sind immer weiß, auch im Dunkelmodus | – | Popup-Stil aus Tokens | 7 |
| `ui/*` hat eigene `dark:`-Klassen, die das Token-System umgehen | – | entfernt, Tokens tragen den Modus | 4.1 |
### 2.3 Nicht im Umfang
- Neue Fachlogik. Ampelregeln, Saison, Fälligkeit und Varroa-Bänder kommen aus T3 und T4.
- Echte Aufstellung der Völker am Stand (Position in der Reihe). Die Zellen stehen nach Volkscode, siehe Offene Frage 2.
- Neue Diagramme in der Statistik. Die Statistik bekommt nur die neuen Tokens und den Tabs-Baustein.
- Etiketten-Designer und PDF-Ausgaben. Sie bekommen nur Tokens und Bausteine, wo sie Bedienelemente der App nutzen; Druck bleibt immer hell.
- Native App, Umgebungslicht-Sensor (zu wenig Browserunterstützung), Haptik.
- Ein E2E-Framework (Playwright) im Frontend. Die Sichtprüfung läuft per Screenshot-Matrix (13.4).
### 2.4 Abgrenzung zu T3 und T4
| Baustein | Liefert | T5 ändert |
|---|---|---|
| T3 Task 8 `RatingScale`, `RATING_TONE_CLASS`, `rating-contrast.spec.ts` | Töne je Stufe, Kontrast-Wächter für Ampelflächen | Wächter geht in `src/styles/contrast.spec.ts` auf (alle Paare, vier Sätze). Gewählte Stufe bekommt Rahmen und Haken wie jede Auswahl. |
| T3 Task 8 `NumberStepper` | Plus/Minus-Feld | API bleibt. Weitere Zählfelder stellen darauf um (10.5). |
| T3 Task 14 `colonyStatusLight`, `StatusLightBadge`, `ApiaryColoniesCard` | Ampel je Volk, Zeilenliste | Die Ampel füllt die Zellen. Die Zeilenliste bleibt als Rückfall unter der Wabe. |
| T3 Task 7 `nav-config.ts`, `quick-actions.ts`, Sheets | eine Navigationsquelle | Icons kommen aus `AREAS`. |
| T3 Task 11 Varroa-Trend (SVG) | Muster für handgeschriebene Diagramme | Vorlage für Lebenslinie und Rad. |
| T4 Task 15 `ColonyOverviewRow.inspectionDueOn`, `ColonyNextSteps`, `AutopilotToday` | Fälligkeit, nächste Schritte, Saison je Stand | Randstufen der Zelle, Zukunftszone der Lebenslinie, Rad. `AutopilotToday` bekommt zwei Felder (9.1). |
| T4 Task 18 `SeasonChip`, `SEGMENT_LABELS`, Heute-Karten | Saison-Chips auf dem Dashboard | Die Saison je Stand zieht in die Rad-Karte. Die Chip-Zeile entfällt dort, um Doppelanzeige zu vermeiden. `SeasonChip` bleibt auf der Stand-Seite. |
| T4 Task 17 `INTENT_ICONS` | Icon je Absicht | Werte aus `AREAS` (Durchsicht, Varroa, Fütterung …). |
| T4 Task 19 Varroa-Bänder, `rating` je Messung | Ampel je Messung | Lebenslinie färbt mit `rating.light` und markiert `band.redAbove`. |
| T4 Task 31 `PHASE_SOURCE_LABELS` | „gemeldet“, „geschätzt“, „Kalender“ | Rad zeigt die Quelle damit. |
## 3. Gestaltungsgrundsätze für diese App
1. **Sonne zuerst.** Draußen spiegelt das Display, und Spiegelung frisst Kontrast. Darum liegen Fließtext und Hauptknopf über 7:1, nicht knapp über 4,5:1. Flächen sind hell und ruhig, Text ist dunkel. Unterschiede zeigen sich über Helligkeit, Form und Strichstärke, nicht über Sättigung.
2. **Handschuhe.** Jedes Ziel mindestens 44 × 44 px, Zeilen in Sheets 56 px. Kein Ziel, das nur durch Hover oder einen langen Druck erreichbar ist. Benachbarte Ziele haben mindestens 4 px Abstand.
3. **Ein Blick, eine Sache.** Jede Ansicht hat einen Hauptknopf in Honig. Alles andere ist umrandet oder Text. Eine Grafik beantwortet genau eine Frage:
- Waben: Welches Volk braucht mich?
- Lebenslinie: Wie hat sich das Volk entwickelt?
- Rad: Wo stehen wir im Bienenjahr, was kommt?
4. **Nie nur Farbe.** Jeder Zustand hat ein Icon und ein Wort, jede Grafik einen Text und eine Tabelle. Die Zellen tragen den Volkscode und ein Zustands-Icon. Gestrichelte Ränder und Schraffuren unterscheiden auch ohne Farbsehen.
5. **Vertraute Bedienung, eigene Handschrift im Detail.** Knöpfe, Felder, Tabs und Sheets verhalten sich wie überall im Web. Die Handschrift sitzt in Material (Wachs und Honig), Tinte und dem einen Motiv Wabenzelle, nicht in erfundenen Bedienelementen.
6. **Ruhe.** Keine Verläufe, kein Glas, keine Zierbewegung, keine Großbuchstaben-Laufschrift. Schatten sind leise und entfallen in Sonne. Die Farbtöne der Bereiche erscheinen nur als Icon-Kachel, nicht als Fläche. Bewegung folgt §17. Glas, Leuchten und Ruhebewegung gibt es nur auf der Beute-Bühne (§17.8).
**Verboten** (der Wächter-Test prüft, was sich prüfen lässt):
- Weiß auf Honig
- `text-primary` als Schriftfarbe
- `ring-ring/50` und `outline-none` ohne Ersatz
- Farbverlauf als Hintergrund
- Text unter 13 px
- Zustand nur über Farbe
- eigene `role="radio|checkbox|tab"`-Bauten außerhalb des Baukastens
- Bewegung gegen §17: `motion-safe:` für Verschiebung, `transition-all`, animierte Breite, Höhe oder Unschärfe, bewegte Datenwerte
## 4. Tokens
### 4.1 Grundregeln
- Jede Farbe hat eine Rolle. **Fläche** (`--primary`, `--condition-good`, …) trägt ihren **Text auf der Fläche** (`--primary-foreground`, `--condition-good-foreground`). Für Text und Icons auf normalen Flächen gibt es **Tinte** (`--primary-ink`, `--warning-ink`, `--condition-good-ink`).
- Vier Sätze in dieser Reihenfolge in `globals.css`:
1. `:root` (hell)
2. `.dark` (dunkel)
3. `:root[data-contrast="sun"]` (Sonne hell)
4. `.dark[data-contrast="sun"]` (Sonne dunkel)
Die Sonne-Sätze überschreiben nur die Tokens aus 4.3.
- `@custom-variant dark (&:where(.dark, .dark *));` statt heute `(&:is(.dark *))`, damit die Klasse direkt auf `` greift. Dazu kommen die Varianten `sun`, `pointer-fine` und `pointer-coarse`.
- `ui/*` und `components/*` enthalten keine `dark:`-Klassen mehr. Ein Modus ist nur ein anderer Tokensatz. Einzige Ausnahme: Leaflet-Kacheln (7.4).
- Entfernt: `--gradient-honey`, `--gradient-sage`, `--gradient-sky`. Die Komponente `PageHeader`/`EntityCard` verliert den Prop `gradient`.
- `@media print` setzt immer den hellen Satz.
- `@media (forced-colors: active)`:
- Zellen, Ränder, Ringe und Rad-Segmente bekommen `CanvasText`-Striche.
- Zustände bleiben über Icon, Muster und Strichstärke erkennbar.
- SVG-Flächen nutzen `forced-color-adjust: auto`.
### 4.2 Werte hell und dunkel
OKLCH ist die Quelle, Hex dient nur zur Orientierung. Alle Werte liegen im sRGB-Farbraum (vom Skript geprüft).
| Token | Hell | Dunkel | Verwendung |
|---|---|---|---|
| `--background` | `oklch(0.968 0.014 85)` #f9f4ea | `oklch(0.19 0.016 55)` #1a120d | Seite („Wachs“) |
| `--foreground` | `oklch(0.21 0.03 55)` #23140a | `oklch(0.95 0.018 80)` #f5ede1 | Text („Tinte“) |
| `--card`, `--popover`, `--sidebar` | `oklch(0.995 0.004 90)` #fefdfa | `oklch(0.235 0.018 55)` #251c16 | Karten, Sheets |
| `--muted` | `oklch(0.925 0.018 82)` #ece5d9 | `oklch(0.28 0.018 55)` #302720 | ruhige Flächen, Rad-Segmente |
| `--muted-foreground` | `oklch(0.44 0.03 60)` #5f4f42 | `oklch(0.76 0.025 75)` #bbafa0 | Nebentext |
| `--primary` | `oklch(0.80 0.145 78)` #f0b13f | `oklch(0.80 0.14 78)` #efb146 | Honig: Hauptknopf, Auswahl, aktiver Eintrag |
| `--primary-foreground` | `oklch(0.21 0.035 55)` #251408 | `oklch(0.19 0.03 55)` #1e1006 | Text auf Honig |
| `--primary-ink` **neu** | `oklch(0.47 0.115 55)` #8a4603 | `oklch(0.82 0.13 80)` #f0ba59 | Links, Akzent-Icons, aktiver Tab-Strich |
| `--ring` | = `--primary-ink` | = `--primary-ink` | Fokusring |
| `--secondary` / `-foreground` | `oklch(0.44 0.07 145)` / `oklch(0.98 0.015 100)` | `oklch(0.66 0.08 145)` / `oklch(0.16 0.02 145)` | Salbei, Zweitknopf |
| `--accent` / `-foreground` | `oklch(0.935 0.03 78)` / `oklch(0.25 0.045 50)` | `oklch(0.31 0.03 60)` / `oklch(0.95 0.018 80)` | Hover, Menüs |
| `--destructive` | `oklch(0.50 0.17 28)` #af2b25 | `oklch(0.70 0.15 28)` #ed7668 | Text, Icon, Rahmen |
| `--destructive-foreground` **neu** | `oklch(0.985 0.005 30)` | `oklch(0.17 0.03 30)` | Text auf voller Fläche (Bestätigen-Dialog) |
| `--border` | `oklch(0.86 0.022 78)` #d9d0c1 | `oklch(0.34 0.02 60)` #40362e | nur Trennlinien und Kartenkanten (Deko) |
| `--input` | `oklch(0.60 0.035 65)` #8f7c6b | `oklch(0.56 0.025 70)` #7e7265 | Rahmen jedes Bedienelements |
| `--warning` / `-foreground` | `oklch(0.79 0.15 80)` / `oklch(0.23 0.04 60)` | `oklch(0.80 0.14 80)` / `oklch(0.20 0.03 60)` | Warnfläche |
| `--warning-ink` **neu** | `oklch(0.50 0.11 65)` #8d5406 | `oklch(0.82 0.13 82)` #eebb58 | Warn-Icon und -Text |
| `--success` / `-foreground` | `oklch(0.46 0.08 145)` / `oklch(0.98 0.015 100)` | `oklch(0.70 0.09 145)` / `oklch(0.16 0.02 145)` | Erfolg |
| `--condition-excellent` / `-foreground` / `-ink` | `0.62 0.13 150` / `0.15 0.04 150` / `0.40 0.09 150` | `0.68 0.12 150` / `0.17 0.04 150` / `0.80 0.11 150` | Ampel „sehr gut“ |
| `--condition-good` / … | `0.645 0.13 125` / `0.17 0.04 125` / `0.41 0.09 125` | `0.72 0.12 125` / `0.18 0.04 125` / `0.83 0.11 125` | Ampel „gut“, Zelle grün |
| `--condition-average` / … | `0.665 0.125 88` / `0.19 0.04 90` / `0.44 0.09 85` | `0.77 0.13 90` / `0.20 0.04 90` / `0.86 0.11 90` | Ampel „Achtung“, Zelle gelb |
| `--condition-weak` / … | `0.665 0.14 58` / `0.18 0.04 55` / `0.46 0.12 52` | `0.74 0.13 60` / `0.19 0.04 55` / `0.82 0.11 60` | Ampel „schwach“ |
| `--condition-critical` / … | `0.62 0.17 30` / `0.15 0.04 30` / `0.47 0.16 28` | `0.68 0.16 28` / `0.16 0.04 30` / `0.78 0.11 28` | Ampel „kritisch“, Zelle rot |
| `--chart-1` … `--chart-5` | `0.56 0.13 55`, `0.46 0.08 145`, `0.60 0.12 85`, `0.50 0.17 28`, `0.52 0.08 250` | `0.78 0.13 70`, `0.70 0.09 145`, `0.82 0.12 90`, `0.70 0.15 28`, `0.72 0.08 250` | Diagramme; Rad-Fenster: Tracht = 3, Varroa = 4, Einwinterung = 5 |
| `--area-betrieb` **neu** | `oklch(0.46 0.08 150)` | `oklch(0.74 0.09 150)` | Bereichston (Abschnitt 11) |
| `--area-erfassung` **neu** | `oklch(0.50 0.12 60)` | `oklch(0.80 0.12 70)` | |
| `--area-arbeit` **neu** | `oklch(0.48 0.08 250)` | `oklch(0.76 0.07 250)` | |
| `--area-ernte` **neu** | `oklch(0.52 0.11 75)` | `oklch(0.80 0.10 80)` | |
| `--area-neutral` **neu** | `oklch(0.45 0.02 60)` | `oklch(0.76 0.02 70)` | |
| `--queen-white/-yellow/-red/-green/-blue` **neu** | `0.97 0.005 90`, `0.86 0.17 95`, `0.58 0.20 27`, `0.58 0.15 145`, `0.52 0.15 255` | gleich, außer rot `0.62 0.20 27`, grün `0.66 0.15 145`, blau `0.62 0.15 255` | Zeichenfarbe der Königin, immer mit 2-px-Ring in `--foreground` |
| `--radius` | `0.75rem` | gleich | unverändert |
| `--shadow-soft`, `--shadow-elevated` | unverändert | unverändert | in Sonne `none` |
Bestehende Klassen werden so umgestellt (Codemod, Abschnitt 10.8):
- `text-primary` → `text-primary-ink`
- `text-warning` → `text-warning-ink`
- `text-condition-x-foreground` in Abzeichen → `text-condition-x-ink` (`COLONY_CONDITION_TONE_CLASS`, `StatusLightBadge`)
- `border-primary` bei Auswahlzuständen → `border-foreground`
### 4.3 Kontrastmodus „Sonne“
Ziel: draußen bei voller Sonne alles mit maximaler Helligkeitsdifferenz lesbar, ohne dass sich Bedienung oder Anordnung ändern.
| Token | Sonne hell | Sonne dunkel |
|---|---|---|
| `--background`, `--card`, `--popover`, `--sidebar` | `oklch(1 0 0)` #ffffff | `oklch(0.10 0.005 55)` #040302 |
| `--foreground`, `--primary-foreground`, `--ring` | `oklch(0.13 0.02 55)` #0d0602 | `--foreground`/`--ring` `oklch(0.99 0.005 85)` |
| `--muted` | `oklch(0.95 0.01 80)` | `oklch(0.20 0.01 55)` |
| `--muted-foreground` | `oklch(0.32 0.03 60)` | `oklch(0.88 0.02 80)` |
| `--border` | `oklch(0.40 0.03 60)` | `oklch(0.70 0.02 70)` |
| `--input` | `oklch(0.20 0.03 55)` | `oklch(0.92 0.01 80)` |
| `--primary-ink` | `oklch(0.38 0.10 52)` | wie dunkel |
Dazu kommen Regeln unter `[data-contrast="sun"]`:
- **Schrift:** `--text-sm: 1rem`, `--text-xs: 0.875rem`. Tailwind 4 liest die Größen aus diesen Variablen, deshalb wirkt das ohne Klassenänderung.
- **Fokus:** `--focus-width: 3px`.
- **Rahmen:** Rahmen von Bedienelementen 2 px (`--control-border-width: 2px`).
- **Flächen:** keine Schatten (`--shadow-*: none`). Kopfzeile undurchsichtig (`backdrop-filter: none`, `bg-card`). Tönungen `bg-*/15` werden zu `bg-card` mit 2-px-Rahmen in der jeweiligen Tinte (Hilfsklasse `.tint` statt `/15`).
- **Grafik:** Wabenränder 3/5/7 px statt 2/4/6 px. Keine Honig-Tönung unter der Stärkekurve.
### 4.4 Gemessene Kontraste (Ist → Soll)
Grenzen: Text 4,5:1, Bedienrahmen, Fokus und Grafik 3:1. Für Fließtext und Hauptknopf ist das Ziel 7:1. Die Werte unten sind die Sollwerte, die der Wächter-Test prüft.
| Paar | Ist hell | Soll hell | Ist dunkel | Soll dunkel | Sonne hell | Sonne dunkel | Grenze |
|---|---|---|---|---|---|---|---|
| Text auf Hauptknopf | 2,31 (Verlaufsanfang) / 4,04 | **9,38** | 1,72 (Verlaufsende) | **9,77** | 10,61 | 9,77 | 7 |
| Grundtext / Seite | 15,25 | 16,23 | 15,21 | 15,98 | 20,15 | 20,01 | 7 |
| Grundtext / Karte | 17,15 | 17,56 | 13,46 | 14,45 | 20,15 | 20,01 | 7 |
| Nebentext / Seite | 5,77 | 7,13 | 6,78 | 8,60 | 12,77 | 14,33 | 4,5 |
| Nebentext / `--muted` | 4,88 | 6,27 | 5,29 | 6,81 | 11,03 | 12,62 | 4,5 |
| Link (`--primary-ink`) / Seite | 3,66 | **6,48** | 7,05 | 10,48 | 10,37 | 11,66 | 4,5 |
| Eingaberahmen / Karte | **1,56** | **3,92** | 1,66 | 3,58 | 18,19 | 16,25 | 3 |
| Eingaberahmen / Seite | – | 3,62 | – | 3,96 | 18,19 | 16,25 | 3 |
| Fokusring / Karte (mit Abstand) | 1,94 | 7,01 | 2,59 | 9,47 | 20,15 | 20,01 | 3 |
| Fokusring / Seite | – | 6,48 | – | 10,48 | 20,15 | 20,01 | 3 |
| Warn-Icon/-Text / Karte | 2,90 | 6,09 | 6,84 | 9,49 | 6,18 | 11,68 | 4,5 |
| Warn-Text / Warn-Tönung | 14,14 | 5,53 | 1,49 | 6,92 | 5,60 | 9,37 | 4,5 |
| Fehlertext / Karte | 6,41 | 6,45 | 4,10 | 5,87 | 6,54 | 7,23 | 4,5 |
| Fehlertext / Fehler-Tönung | 5,48 | 5,50 | 3,66 | 5,06 | 5,57 | 6,58 | 4,5 |
| Salbei-Knopf | 7,11 | 7,11 | 5,56 | 6,43 | 7,11 | 6,43 | 4,5 |
| Ampel-Abzeichen (Tinte / Tönung), schlechteste Stufe | 12,61 | 6,06 | **1,36** | 6,45 | 6,14 | 8,49 | 4,5 |
| Text auf Ampelfläche, schlechteste Stufe | 4,71 | 5,02 | 4,66 | 6,32 | 5,02 | 6,32 | 4,5 |
| Ampelfläche / Karte (Zelle, gewählte Stufe), schlechteste | 2,65 | 3,03 | 4,10 | 5,41 | 3,07 | 6,66 | 3 |
| Diagramm `chart-1…5` / Karte, schlechteste | 2,90 (`chart-3`) | 3,93 | 4,10 | 5,87 | 3,99 | 7,23 | 3 |
| Bereichston / Karte, schlechtester | – | 5,54 | – | 7,52 | 5,54 | 7,52 | 3 |
| Königinnenfarbe mit Tinten-Ring / Karte | – | 17,56 (Ring) | – | 14,45 (Ring) | 20,15 | 20,01 | 3 |
Abzeichen im hellen Modus fallen bewusst von 12–16:1 auf 6–7,4:1. Statt fast schwarzer Schrift zeigen sie nun den Farbton als Tinte, damit „Kritisch“ und „Gut“ auch ohne Icon verschieden aussehen. Sie bleiben deutlich über 4,5:1.
Die Honigfläche hat gegen die Karte nur 1,87:1. Das ist zulässig: Ein Knopf wird über seinen Text erkannt, und gewählte Zustände tragen Rahmen und Haken (Entscheidungen). Im Rad bekommt das aktuelle Segment einen 2-px-Rahmen in Tinte (9.3).
### 4.5 Schrift und Größen
| Rolle | Größe | Klasse | Familie |
|---|---|---|---|
| Fließtext, Formular-Beschriftung, Auswahl-Knöpfe, Listentitel, Knopftext, Eingabe | 16 px | `text-base` | Inter |
| Nebentext (Datum, Hinweis, Begründung) | 14 px (Sonne 16) | `text-sm` | Inter |
| Achsen, Legenden, Fußzeilen | 13 px (Sonne 14) | `text-xs` (`--text-xs: 0.8125rem`) | Inter |
| Überschriften h1–h4 | 20 / 24 / 30 px | wie heute | Space Grotesk, nie in Knöpfen oder Labels |
| Codes, Losnummern | wie Umgebung | `font-mono` | IBM Plex Mono |
- Diese Bausteine stellen Inhaltstext von `text-sm` auf `text-base` um:
- `Field`-Label
- `ChoiceGroup`-Option
- `CheckboxField`-Label
- Button-Größe `touch` (heute `text-[0.95rem]`)
- `Input`/`Textarea` (`md:text-sm` entfällt; 16 px verhindert auch das Zoomen in iOS)
- Zeilentitel in Listen, `DetailHeader`-Untertitel
- `EmptyState`-Beschreibung
- Größen: `size="default"` bei Button und `Input` hat 44 px Höhe. 32 bzw. 36 px gibt es nur mit `pointer-fine:` statt `sm:`. `size="touch"` bleibt 44 px. In `ui/button.tsx`, `ui/input.tsx`, `ui/select.tsx`, `ui/textarea.tsx` und `ui/tabs.tsx` wird `sm:h-*` zu `pointer-fine:h-*`.
- Ziele: Icon-Knöpfe ohne Text (`icon`, `icon-sm`) bekommen bei `pointer-coarse` eine Trefferfläche von 44 px über ein `::after`-Element, ohne optisch zu wachsen.
### 4.6 Fokusstil
In `@layer base`:
```css
:root { --focus-width: 2px; --focus-offset: 2px; }
:where(:focus-visible) { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }
```
- Alle `outline-none`, `focus-visible:ring-3 focus-visible:ring-ring/50` und `has-[:focus-visible]:outline-*` in `ui/*`, `components/*` und `app/*` entfallen (18 Stellen `ring-ring/50` in 17 Dateien, 22 `outline-none`).
- Wo der Fokus auf einem inneren Element liegt (Label-Zeile mit verstecktem Input, Wabenzelle), zeigt der Baustein den Ring am äußeren Element über `:has(:focus-visible)`. Bei der Wabenzelle ist das ein zweiter Sechseckpfad (6.6).
- Fehlerzustand (`aria-invalid`): Rahmen in `--destructive`, 2 px, dazu der Fehlertext am Feld. Der Fokusring bleibt in `--ring`.
- Fokus wird nicht verdeckt (WCAG 2.4.11): Das bestehende `scroll-padding` bleibt.
## 5. Darstellung umschalten
### 5.1 Einstellungen
| Einstellung | Werte | Standard | Attribut auf `` | Speicher (je Gerät) |
|---|---|---|---|---|
| Farbschema | „Hell“, „Dunkel“, „Wie Gerät“ | Hell (Offene Frage 3) | `class="dark"` oder nichts | `localStorage` `apicore.theme` |
| Kontrast | „Normal“, „Sonne“ | Normal; ohne gespeicherten Wert Sonne bei `prefers-contrast: more` | `data-contrast="sun"` | `apicore.contrast` |
| Bewegung | „Voll“, „Dezent“, „Aus“ | Voll (wie heute) | `data-motion` | `apicore.motion` (heute schon) |
Alles wird je Gerät gespeichert, nicht am Konto. Draußen am Handy will man Sonne, am Schreibtisch nicht. Das folgt dem bestehenden Muster der Bewegungsstufe.
### 5.2 Ablauf
1. **Vor dem ersten Bild:** `src/components/appearance-script.tsx` rendert im `` von `app/layout.tsx` ein Inline-Skript nach dem Muster `InlineScript` der Next-Anleitung „Preventing Flash“.
- Es liest die drei Schlüssel in `try/catch` und setzt Klasse und Attribute.
- Es setzt den Inhalt von `` auf die Seitenfarbe des aktiven Satzes.
- `` bekommt `suppressHydrationWarning`.
- Das Skript kommt aus derselben Konstante wie der Hook (`APPEARANCE_KEYS`), damit Schlüssel und Werte nie auseinanderlaufen.
- CSP: `script-src 'self' 'unsafe-inline'` (`proxy.ts`) erlaubt das schon. Wird die CSP später verschärft, kommt der SHA-256-Hash des Skripts in die Liste. Das Skript enthält keine Nutzerdaten.
2. **Zur Laufzeit:** `useAppearance()` (`src/lib/appearance/appearance.ts`) liefert die Werte und Setter.
- Ein Setter schreibt `localStorage` und das Attribut.
- Er hört auf `matchMedia('(prefers-color-scheme: dark)')`, solange „Wie Gerät“ gewählt ist, und auf `prefers-contrast`, solange nichts gewählt ist.
- Er hört auf das `storage`-Ereignis, damit ein zweiter Tab mitzieht.
- `motion-preference.ts` behält seine API; `applyMotionLevel` wird vom Skript übernommen, der `useEffect` in `providers.tsx` entfällt.
3. **Toaster:** `components/ui/sonner.tsx` liest `useAppearance().resolvedTheme` statt `next-themes`. `next-themes` wird aus `package.json` entfernt.
4. **Metadaten:** `viewport.themeColor` in `app/layout.tsx`:
- `[{ media: '(prefers-color-scheme: light)', color: '#f9f4ea' }, { media: '(prefers-color-scheme: dark)', color: '#1a120d' }]`
- Das Skript überschreibt den Wert bei manueller Wahl.
### 5.3 Bedienung
- **Profil → Karte „Darstellung“** (ersetzt die Karte „Bewegung & Effekte“, `appearance-section.tsx` statt `motion-section.tsx`). Drei `ChoiceGroup`-Felder (Aussehen „Karten“ mit Beschreibung, 10.2):
- **Farbschema:** „Hell – am besten bei Tageslicht“, „Dunkel – für abends“, „Wie Gerät“.
- **Kontrast:** „Normal“, „Sonne – maximaler Kontrast, größere Schrift, für draußen“.
- **Bewegung:** Texte wie heute.
- Darunter steht: „Gilt nur für dieses Gerät.“ Die Änderung wirkt sofort und ohne Übergang.
- **Schnellschalter:** Im Benutzermenü (Avatar) steht oben ein Eintrag „Sonnenmodus“ als `DropdownMenuCheckboxItem` (`role="menuitemcheckbox"`, 44 px), mit Sonnen-Icon und Haken. Vom Stand aus sind das zwei Tipps, ohne Seitenwechsel. Nach dem Umschalten erscheint der Toast „Sonnenmodus an“ bzw. „aus“.
- **Abmelden** löscht diese Einstellungen nicht. Sie sind Gerätevorlieben, keine Daten.
### 5.4 Seiten außerhalb der App
- Login und `/herkunft/[lot]` folgen denselben Tokens und Einstellungen. Ein Kunde ohne gespeicherten Wert sieht „Hell“.
- Druck (`@media print`) und PDF-Vorschau bleiben hell.
## 6. Waben-Standkarte
**Frage, die sie beantwortet:** Welches Volk an diesem Stand braucht mich, und wann war ich zuletzt dran?
### 6.1 Daten
- Je Stand `ColonyOverview` aus `GET /apiaries/:id/colony-overview`, Query-Key `["apiaries", apiaryId, "colony-overview"]` (wie T3 Task 14). Offline greift `withPackFallback` (T3 Task 15).
- Je Zeile: `code`, `status`, Bedingungen, `lastInspectionDate`, `openWarnings`, `openCritical`. Ab T4 zusätzlich `inspectionDueOn`, `segment`, `nextStepTitle`.
- Zustand der Zelle = `colonyStatusLight(row, { today, inspectionsVisible })`, unverändert aus T3/T4.
- Auf der Bienenstände-Liste lädt `useQueries` die Übersicht aller aktiven Stände, höchstens 20. Bei mehr Ständen zeigen die übrigen Karten nur die Zusammenfassung, ohne Wabe; das ist im Betrieb nicht zu erwarten.
### 6.2 Aufbau
Stand-Seite, Karte „Völker“ (Handy, 328 px Inhaltsbreite):
```
┌ Völker (7) ─────────────────────────────────────────┐
│ 5 Gut · 1 Achtung · 1 Kritisch · 2 Durchsichten fällig│
│ │
│ ⬡B1 ⬡B2 ⬡B3 ⬡B4 ⬡ = Zelle 64 px │
│ ⬡B5 ⬡B6 ⬡B7 versetzte Reihe │
│ │
│ ⬡ Gut ⬡ Achtung ⬡ Kritisch · Rand: dünn = frisch, │
│ dick = Durchsicht fällig │
│ ──────────────────────────────────────────────────── │
│ Braucht Blick │
│ B3 ▲ Achtung Futter schwach · 16 Tage ohne Durchs.│
│ B6 ✕ Kritisch Weisellos │
│ [ Alle 7 Völker als Liste ▾ ] │
└──────────────────────────────────────────────────────┘
```
- Zusammenfassung oben: ein Satz mit Icons, nach Ampel gezählt, dazu fällige Durchsichten (ab T4 aus `inspectionDueOn`, vorher Stufe 3 der Randregel).
- Wabe: die Zellen.
- Legende: immer sichtbar, eine Zeile, 13 px. Sie erklärt die drei Füllungen mit Wort und Icon und den Rand.
- „Braucht Blick“: nur Völker mit Gelb oder Rot, mit Gründen. Das ist die Arbeitsliste. Bei null Völkern steht dort „Alle Völker sind in Ordnung.“
- „Alle 7 Völker als Liste“: ein Knopf mit `aria-expanded`, der die T3-Zeilenliste aufklappt. Das ist der Tabellen-Rückfall für alle, die die Wabe nicht lesen können oder wollen. Ab T4 zeigt die Liste auch „Durchsicht fällig in 2 Tagen“ und den nächsten Schritt (T4 Task 18).
- Der Hauptknopf der Seite bleibt „Runde starten“ (T3).
Bienenstände-Liste (`/apiaries`, Tab „Aktiv“): Jeder aktive Stand ist eine Karte.
```
┌ ⬡ Nordhang ──────────────── Schwarmzeit · alle 7 Tage ┐ ← AreaIcon, Name (Link), SeasonChip (T4)
│ 7 Völker · 1 Achtung · 1 Kritisch │
│ ⬡ ⬡ ⬡ ⬡ │ Zellen 56 px, verlinken zum Volk
│ ⬡ ⬡ ⬡ │
└───────────────────────────────────────────────────────┘
```
- Die Liste behält ihren Hauptknopf „+ Neuer Bienenstand“. Die Karten haben keine eigenen Knöpfe. Der Name führt zum Stand, die Zellen führen zu den Völkern.
- Der Tab „Historie“ bleibt eine `EntityCard`-Liste ohne Wabe.
- Die Legende steht einmal oben über allen Karten.
### 6.3 Zelle
- **Form:** Sechseck mit spitzer Oberseite. Breite (Abstand der senkrechten Seiten) 64 px bei `pointer-coarse`, 56 px bei `pointer-fine`, auf der Liste 56 bzw. 48 px. Höhe = Breite × 2/√3. Der Innenkreis (= Breite) ist immer mindestens 48 px, also mindestens 44 px Trefferfläche.
- **Anordnung:**
- Reihen mit `n` Zellen. `n = floor((Breite_Container − (b + 4)/2) / (b + 4))`, mindestens 3, höchstens 10.
- Jede zweite Reihe ist um `(b + 4)/2` nach rechts versetzt und um ein Viertel der Höhe nach oben verzahnt. Abstand 4 px.
- `n` misst ein `ResizeObserver` (`useContainerWidth`).
- Reihenfolge nach Volkscode, natürlich sortiert, wie Liste und Runde (Offene Frage 2).
- **Füllung** nach Ampel: Grün `--condition-good`, Gelb `--condition-average`, Rot `--condition-critical`. Text und Icon in `--condition-*-foreground`. Alle drei Flächen haben mindestens 3:1 gegen die Karte (4.4).
- **Inhalt:**
- oben das Zustands-Icon (16 px; `CheckCircle2`, `AlertTriangle`, `XCircle` wie `StatusLightBadge`)
- darunter der Volkscode (16 px halbfett; bis 6 Zeichen, länger mit Auslassung, voller Code im Namen)
- Bei mehr als einem Grund steht ein kleiner Zähler „2“ unten rechts in der Zelle (13 px).
- **Rand = Tage seit der letzten Durchsicht**, in Tinte (`--foreground`), innen gezeichnet, damit die Zelle gleich groß bleibt:
| Stufe | Bedeutung | ab T4 (mit `inspectionDueOn`) | vor T4 (`INSPECTION_STALE_DAYS = 14`) | Strich | Sonne |
|---|---|---|---|---|---|
| 1 frisch | alles gut | Fälligkeit mehr als 3 Tage entfernt, oder Winterruhe (`inspectionDueOn = null`) | höchstens 10 Tage her | 2 px durchgehend | 3 px |
| 2 bald fällig | bald hin | fällig heute bis in 3 Tagen | 11–14 Tage her | 4 px durchgehend | 5 px |
| 3 fällig | jetzt hin | Fälligkeit überschritten oder nie durchgesehen | mehr als 14 Tage oder nie | 6 px gestrichelt (6 4), kleines Uhr-Icon oben rechts | 7 px |
- Ohne `inspections:read` (`inspectionsVisible = false`) gibt es einen 1-px-Rand in `--input` und keine Aussage zur Durchsicht.
- Die 3-Tage-Grenze ist dieselbe wie „SOON“ in der T4-Rangfolge.
- Die Funktion `rimStepOf(row, today, inspectionsVisible)` liegt in `src/lib/honeycomb/cell-state.ts`.
- **Zustand „Winterruhe“:** Ab T4 heißt die Rand-Erklärung im Namen „Winterruhe – keine Durchsicht nötig“.
### 6.4 Bedienung
- Jede Zelle ist ein Link zur Volksseite. Tippen öffnet das Volk; es gibt kein Menü und keinen langen Druck.
- Hover (nur `pointer-fine`) hebt die Zelle mit einem 2-px-Rahmen in `--primary-ink` hervor, ohne Bewegung und ohne Größenänderung.
- Kein Ziehen, kein Zoomen. Bei vielen Völkern wächst die Wabe in die Höhe.
### 6.5 Barrierefreiheit
- Semantik: `