docs: T5 Bewegungs-Sprache (Spec §17) und Plan-Review 2026-10-16

Spec: Zweck, Stufen Voll/Dezent/Aus über useEffectiveMotionLevel,
Tokens aus dem, was Beute und CSS heute nutzen (eine Quelle in
lib/motion/tokens.ts), Regeln je Muster, was nie animiert,
Performance-Regeln, Abnahme; neue Inhaber-Frage 4.
Plan: 22 Korrekturen gegen den aktuellen Code (u. a. 31 statt 17
Checkbox-Stellen, fehlende AREAS, Lebenslinie unter der Beute-Karte,
Fokusring auf der Holo-Bühne), neue Tasks A11 (Bewegungs-Sprache
durchsetzen) und A12 (Beute-Bühne und Sonne-Modus).

Refs #26

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-16 14:17:03 +02:00
1 parent 362ae7466b
commit 1806255211
2 files changed
+394 -8

No files matched your search

+233 -5
View File
@@ -1,6 +1,103 @@
# T5 Optik mit eigener Handschrift Implementation Plan
**Status (2026-10-16):** Noch nicht begonnen. Vorher Plan-Review und die Bewegungs-Sprache aus Beute-Spec §12.4 ergänzen; Inhaber-Fragen der Spec §16 vorläufig mit A/A/A. Issue: [#26](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/26).
**Status (2026-10-16):** Noch nicht begonnen. Plan-Review erledigt (Abschnitt „Review 2026-10-16“ direkt unten), Bewegungs-Sprache steht in Spec §17 und ist als Task A11 eingeplant. Offen beim Inhaber: Spec §16 Fragen 1–3 (vorläufig A/A/A) und die neue Frage 4 (Bewegungs-Sprache, Empfehlung A). Issue: [#26](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/26).
## Review 2026-10-16
Geprüft gegen den Code nach Beute L1–L5, T4a/T4b, T6 und T7 L1/L2/L3/L5. Die Korrekturen gelten vor dem jeweiligen Task-Text. Wo sie ihm widersprechen, gilt die Korrektur.
**Allgemein**
- G1 (Voraussetzungen): T4a **und T4b** sind gemergt (TASKS.md). T5b läuft damit ohne Kalender-Rückfall.
- `PHASE_SOURCE_LABELS` liegt in `src/lib/phenology/labels.ts`; die lokale Ersatzdefinition entfällt.
- `SeasonChip` liegt in `src/components/autopilot/season-chip.tsx`, `fetchAutopilotToday` in `src/lib/autopilot/api.ts`, `INTENT_ICONS` in `src/components/autopilot/next-steps-card.tsx`.
- G2 (Global Constraints, Zeile „Bewegung“): ersetzt durch Spec §17. Ab sofort gilt: `motion-full:` statt `motion-safe:` für jede Verschiebung, Tokens aus `src/lib/motion/tokens.ts`, nichts Datenhaftes bewegt sich. Rad, Lebenslinie und Waben bleiben ohne Animation.
- G3 (Bestand `motion`): Installiert ist `motion` **13.4.6**, nicht 12.x. `maath` ist da, `framer-motion` nur transitiv. Kein Quelltext importiert `motion/react` (Beute §9.8 sah es für die DOM-Teile vor, gebaut wurde CSS). Task A11 bringt die ersten DOM-Nutzer. Ohne A11 wäre die Abhängigkeit ungenutzt.
- G4 (Aufwand): T5a wächst von ≈ 4,75 auf ≈ 6,4 PT. Gründe: A7 +0,4 (31 statt 17 Checkbox-Stellen), neue Tasks A11 (0,75) und A12 (0,5). T5b bleibt bei ≈ 5,25 PT.
- G5 (Wellen T5a): A11 läuft in Welle 9 nach A8. Sie teilt `globals.css` mit A1/A4/A5, `today-panel.tsx` mit A7 und `ui/*` mit A5. A12 läuft in Welle 9 parallel; sie fasst nur `components/hive/**` an, `globals.css` nicht, weil die Holo-Sonne-Werte schon in A1 kommen. A10 rückt in Welle 10 und wartet auf A8, A9, A11 und A12.
**Je Task**
- A1:
- `--holo-*` (in `:root`/`.dark` seit Beute L3) bekommt Werte in beiden Sonne-Sätzen: Bühne `oklch(0 0 0)`, Kanten und Etikett-Text `oklch(1 0 0)`, Etikett-Fläche `oklch(0.12 0 0)`.
- Neu ist der Rahmen `.holo-stage { --ring: var(--holo-edge-strong) }` (Spec §17.8).
- `contrast.spec.ts` bekommt zwei Zeilen: `holo-label-fg`/`holo-label-bg` ≥ 7 und `holo-edge-strong`/`holo-bg` ≥ 3, in allen vier Sätzen.
- Grund: `--primary-ink` auf `--holo-bg` ≈ 2,8:1.
- A2:
- `motion-preference.ts` hat seit der Beute `useEffectiveMotionLevel` und `MOTION_EVENT`. Nutzer sind `hive-canvas.tsx`, `hive-visual-slot.tsx` und `today/use-task-actions.ts`. Die API bleibt; `useAppearance().setMotion` löst `MOTION_EVENT` aus.
- Neu ist das Ereignis `apicore:appearance` bei jedem Wechsel von Schema oder Kontrast; A12 hört darauf.
- Test dazu: `it('a motion change from the appearance section reaches useEffectiveMotionLevel in the same tab', ...)`.
- Die Stufe heißt in der Oberfläche „Dezent“.
- A3:
- Verlauf-Verbraucher sind **33 Dateien**, nicht 31. `text-white` steht zusätzlich in `components/hive/editor/editor-stage-overlay.tsx` (auf der Bühne → `text-holo-label-fg`).
- `AREAS` fehlen Bereiche aus T6/T7/Beute, die in `nav-config.ts`/`quick-actions.ts` stehen. Neue Schlüssel:
- `compliance` (`ShieldCheck`, betrieb)
- `medicines` (`Pill`, erfassung)
- `voice` (`Mic`, erfassung)
- `hive-systems` (`Box`, neutral)
- `system` (`Activity`, neutral)
- `areas.spec` prüft danach wieder jeden Nav- und Quick-Action-Eintrag.
- Neue Icon-Abweichungen, die korrigiert werden müssen:
- Arzneimittel-Packungen nutzen `Package` (= Abfüllungen) in `medicines/[id]/page.tsx` und `medicines/lots/[id]/page.tsx`.
- Beutensysteme nutzen `Boxes` (= Rohstoffe) in `settings/hive-systems/page.tsx`, die Navigation dagegen `Box`.
- `settings/voice/page.tsx` nutzt `ShieldCheck` (= Prüfbereitschaft).
- Das Dashboard trägt seit T6 `ComplianceLine` und `StandNote`; beide bleiben unverändert.
- A4:
- Die Codemod-Trefferzahlen vor dem Lauf neu zählen (`grep`), die Zahlen im Task sind vom 14.10.
- `dark:` steht weiter in genau 8 `ui/*`-Dateien.
- Die Beute-Bühne (`bg-holo-*`) bleibt unberührt: Sie ist in hell und dunkel absichtlich dunkel.
- A5:
- `sm:h-`/`sm:min-h-` stehen in **11 Dateien**, nicht in 4.
- Der Fokus-Codemod trifft 5 Stellen in `components/hive/**`. Dort entfällt der eigene Ring, und der Ring kommt aus `.holo-stage` (A1).
- `.honey-check` hat `outline: none` plus eigenen Schatten-Ring in `globals.css`. Er nimmt die globale Regel, die Ausnahme entfällt.
- A6:
- `NumberStepper` hat seit Beute L2 `step` mit Dezimalschritten; die Umstellungen nutzen nur ganze Schritte.
- Neue Radio-Eigenbauten → `ChoiceGroup`: `compliance/notices/create-notice-dialog.tsx` (`type="radio"`) und `components/phenology/phenology-report-sheet.tsx` (`type="radio"`).
- Neues `aria-pressed` in `components/hive/hive-card.tsx` („Aufbau als Liste“) → `Button pressed`.
- Ergänze die Dateien in der Files-Liste und im Testbefehl (`"src/app/(app)/compliance" src/components/phenology src/components/hive`).
- A7: Heute sind es **31 Stellen in 27 Dateien** (13 `ToggleChip`, 13 native, 4 Base UI, 1 `today-panel`).
- `ToggleChip`: 13 Stellen in 11 Dateien, neu dazugekommen:
- `compliance/notices/create-notice-dialog.tsx`
- `compliance/restrictions/create-restriction-dialog.tsx`
- `compliance/settings/page.tsx` ×3
- `medicines/medicine-form-dialog.tsx`
- `profile/telegram-link-card.tsx`
- `settings/automation/automation-rules-tab.tsx`
- `settings/automation/rule-forms/rule-form-parts.tsx`
- Natives `type="checkbox"`, neu: `settings/hive-systems/system-dialog.tsx`, `settings/voice/page.tsx`, `components/colonies/colony-takeover-section.tsx`.
- `components/form/switch-row.tsx` (`role="switch"`, Nutzer `profile/notification-settings-card.tsx`, `telegram-link-card.tsx`) geht in `CheckboxField` auf. Dafür bekommt `CheckboxField` das Prop `role?: "checkbox" | "switch"`, Umsetzung mit Base UI `Switch`. Danach wird `SwitchRow` gelöscht. Die Wächter-Regel erlaubt `role="switch"` nur in `ui/checkbox.tsx`/`ui/switch.tsx`.
- `today-panel.tsx` (`task`) kommt zuletzt, weil A11 dieselbe Datei danach anfasst.
- Aufwand 0,9 PT.
- A8:
- `ActiveHistoryTabs` hat jetzt **10 Nutzer**, neu ist `medicines/page.tsx`; sie kommt in die Files-Liste.
- `TabSwitcher` hat unverändert 2 Nutzer.
- A9:
- `SHELL_CACHE` ist weiter `apicore-shell-v4` → v5 gilt.
- `SW_ROUTES_VERSION` haben Beute L5 und T7 erhöht. „Bleibt unverändert“ heißt: A9 erhöht sie nicht noch einmal.
- `/inspections/new`, `/varroa/new`, `/voice/new` stehen in `SHELL_ROUTES`. Ein vierter Shortcut „Sprachnotiz“ (`/voice/new`) ist möglich, aber nicht Spec; nur nach Freigabe.
- A10:
- `src/app/(app)/dashboard/page.spec.tsx` gibt es schon → Modify, nicht Create.
- Die Screenshot-Matrix bekommt die Seiten aus T6, T7 und Beute:
- Volk mit Beute-Karte (Bühne, Fokus, Sheet)
- `/colonies/[id]/hive` (Umbauen)
- `/voice` und `/voice/new` (Aufnahme-Punkt)
- `/settings/voice`
- `/offline`, `/offline/apiary` und `/offline/colony`
- das Warteschlangen-Sheet (`components/offline/pending-queue-sheet.tsx`) und das Offline-Band
- `/compliance`, `/medicines`
- Die Matrix läuft je in Voll, Dezent und Aus, zusätzlich mit `prefers-reduced-motion: reduce` auf Start, Volk und `/voice/new`.
- A11 **neu**: Bewegungs-Sprache durchsetzen (Task-Text unten nach A10).
- A12 **neu**: Beute-Bühne an Sonne und Darstellungswechsel anschließen (Task-Text unten nach A11).
- B1: Die Offline-Standseite `src/app/(app)/offline/apiary/page.tsx` zeigt die Wabe aus dem Paket mit demselben `ApiaryComb` (Modify ergänzen, Test `it('the offline apiary page shows the comb from the pack', ...)`). `apiary-colonies-card.tsx` nutzt `inspectionDueOn` schon. Die Tests für den Zweig ohne T4 bleiben für alte Pakete.
- B3: Die Keys stimmen (`varroa-measurements`, `swarm-control-checks`, `next-steps`, `history`). `["colonies", id, "hive"]` gibt es neu. Beute-Änderungen als Ereignisse sind laut Beute §9.10 nicht Teil von T5; die Lebenslinie lässt sie aus.
- B4: Die Volksseite hat seit Beute L2 ein neues Raster:
- oben `NextStepsCard` über die volle Breite
- Zeile 1: Stammdaten und Beute, gleich hoch, ohne `items-start`
- Zeile 2: Aktionen | Karten
- „Desktop rechte Spalte oben“ ist jetzt die Beute. Die Lebenslinie kommt in Zeile 2 als erstes Kind der 2-Spalten-Fläche, über dem `xl:grid-cols-2`-Raster.
- Reihenfolge im DOM: Stammdaten, Beute, Aktionen, Lebenslinie, Karten.
- Test `it('the colony page puts the lifeline under „Als Nächstes“', ...)` → `it('the lifeline opens row 2 above the record cards and leaves row 1 to Stammdaten and Beute', ...)`.
- B5: Unverändert gültig. `AutopilotToday.seasons` hat weiter weder `segmentSince`, `reportedOn` und `note` noch `seasonCalendar`. Die Dateien sind `src/autopilot/next-steps.service.ts`, `src/autopilot/dto/next-steps-response.dto.ts` und `test/next-steps.e2e-spec.ts`.
- B6: `season-defaults.spec.ts` liest nicht `default-rules.ts`, sondern `ApiCore-Backend/src/automation/rule-config/phenology.config.ts` (`calendarFallback`, Schwarmzeit) und `season-autopilot.config.ts` (`winterVarroaWindow`).
- B7: Das Dashboard hat heute noch Honigbanner und `StatTile`; A3 und B7 sind also weiter nötig. `ComplianceLine` und `StandNote` bleiben über „Bienenjahr“ an ihrem Platz.
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
@@ -12,7 +109,7 @@
**Spec:** `docs/superpowers/specs/2026-10-13-t5-optik-design.md` (bindend). Bausteine aus `docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md` und `docs/superpowers/plans/2026-10-13-t4-logik-ketten.md`.
**Lieferungen:** T5a „Sonnentauglich und Baukasten“ (Tasks A1–A10, ≈ 4,75 PT, hängt nur an T3) und T5b „Handschrift“ (Tasks B1–B8, ≈ 5,25 PT, nach T4a; ohne T4 greift der Kalender-Rückfall).
**Lieferungen:** T5a „Sonnentauglich und Baukasten“ (Tasks A1–A12, ≈ 6,4 PT nach Review 2026-10-16, hängt nur an T3) und T5b „Handschrift“ (Tasks B1–B8, ≈ 5,25 PT, nach T4a; ohne T4 greift der Kalender-Rückfall).
**Vorläufige Inhaber-Entscheidungen (Empfehlungen, vor der Ausführung noch überstimmbar):** Hauptknopf = heller Honig mit dunkler Tinte (Offene Frage 1, A, 9,4:1). Zellen der Waben-Standkarte nach Volkscode (Frage 2, A). Standard-Farbschema auf neuem Gerät = Hell (Frage 3, A). Kippt eine Antwort, ändert sich nur das Token bzw. eine Konstante (`DEFAULT_THEME` in Task A2, `--primary*` in Task A4, `sortCells` in Task B1); `contrast.spec.ts` hält jede Variante.
@@ -33,7 +130,7 @@
- Grundschrift 16 px (`text-base`) für Fließtext, Labels, Auswahl-Knöpfe, Listentitel, Knopftext, Eingabe; Nebentext 14 px (`text-sm`); `text-xs` = 13 px nur für Achsen, Legenden, Fußzeilen; in Sonne 16/14 px. Überschriften Space Grotesk, nie in Knöpfen oder Labels.
- Ein Fokusstil: 2 px durchgehender Ring in `--ring`, 2 px Abstand (Sonne 3 px), als Basisregel auf `:where(:focus-visible)`. Einzige Ausnahme: `honeycomb-cell.tsx` (zweiter Sechseckpfad, Spec 6.6).
- Zustand nie nur über Farbe: Icon plus Wort, Rand-Stufen über Strichstärke und Strichelung. Jede Grafik hat `<title>`, `<desc>` und eine aufklappbare Tabelle aus demselben Modell.
- Bewegung: keine neue Animation. Rad, Lebenslinie, Waben erscheinen sofort. Erlaubt bleibt nur die `honey-check`-Bewegung beim Abhaken. `prefers-reduced-motion` und `data-motion` bleiben wirksam.
- Bewegung (geändert 2026-10-16): Spec §17 ist bindend. Stufen über `useEffectiveMotionLevel()` und die CSS-Variante `motion-full:` (nie `motion-safe:` für Verschiebung). Tokens kommen aus `src/lib/motion/tokens.ts` und `--motion-*`. Bewegt werden nur `transform` und `opacity`, Datenwerte, Fehlertexte und Eingaben nie. `motion` nur über `LazyMotion`/`m.*` im `(app)`-Layout. Rad, Lebenslinie und Waben erscheinen weiter sofort. Durchgesetzt wird das in Task A11, der Wächter prüft es.
- Deutsche Oberfläche, kurze Sätze, ein Hauptknopf (Honig) je Ansicht, ADHS-freundlich: wenig kognitive Last. Code-Bezeichner englisch.
- Verboten (Wächter prüft): Weiß auf Honig, `text-primary` als Schriftfarbe (nur `text-primary-ink`), `ring-ring/50`, `outline-none`, Farbverlauf als Hintergrund, `text-white`, `dark:`-Klassen, Text < 13 px, Zustand nur über Farbe, eigene `role="radio|checkbox|tab"`-Bauten außerhalb des Baukastens. Ein Bereichston ist nie eine Zustandsfarbe.
- Wiederverwenden statt kopieren: `StatusLightBadge`, `colonyStatusLight`, `ChoiceGroup`, `NumberStepper`, `Field`, `QueryState`, `PageHeader`/`DetailHeader`/`EntityCard`, `useColonyOverview`, Query-Keys der bestehenden Karten (keine Doppel-Requests).
@@ -165,7 +262,8 @@ Die Honigfläche hat gegen die Karte nur 1,87:1; das ist zulässig, weil ein Kno
| 6 | A6 | A5 |
| 7 | A7 | A6 (`winter-check-dialog`, `label-designer`, `swarm-control-edit-dialog` gemeinsam) |
| 8 | A8 | A7 (`tasks/page.tsx`, `settings/automation/*` gemeinsam) |
| 9 | A10 | A8, A9 |
| 9 | A11, A12 | A11 → A8 (`today-panel.tsx`, `ui/*`, `globals.css`); A12 → A1, A2 |
| 10 | A10 | A8, A9, A11, A12 |
**T5b** (nach T4a-Frontend; ohne T4 mit Kalender-Rückfall lauffähig, aber dieselben Dateien wie T4 Tasks 17/18/20, darum danach):
@@ -576,6 +674,135 @@ it('the dashboard shows no white text on honey', ...);
---
### Task A11: Bewegungs-Sprache durchsetzen (Spec §17, neu im Review 2026-10-16)
Vorher laden:
- `animate` bzw. `ecc:motion-foundations` für Konzept und Tokens
- `motion` (Docs „Reduce bundle size“, `LazyMotion`, `layout`, `AnimatePresence`)
- danach `fixing-motion-performance`
Skill-Routing: erst Konzept, dann CSS, dann `motion`. GSAP nicht.
**Files**
- Create:
- `src/lib/motion/tokens.ts` (+ `tokens.spec.ts`)
- `src/components/app-motion.tsx` (+ Spec): `LazyMotion` mit `strict`, Features asynchron, `MotionConfig` je Stufe
- `src/lib/motion/motion-features.ts`: `export default domMax`, nur per dynamischem Import
- `scripts/codemod-t5-motion.mjs` (+ Spec)
- Modify:
- `src/app/globals.css`:
- `--motion-fade`, `--motion-enter`, `--motion-settle`, `--motion-moment`, `--ease-in`, `--ease-spring`, `--motion-shift`
- `--animate-page-in` auf `--motion-enter`
- `next-step-in` ohne `filter: blur`
- `.today-row`-Faltung entfernen
- `src/app/(app)/layout.tsx` (`<AppMotion>` um den Inhalt)
- `src/app/(app)/page-transition.tsx`
- `src/components/ui/sheet.tsx`, `dialog.tsx`, `dropdown-menu.tsx`, `select.tsx` (Dauern und Kurven aus Tokens, Austritt `--ease-in`)
- `src/components/ui/button.tsx` (`motion-full:active:scale-[0.97]`, kein `transition-all`)
- `src/components/ui/badge.tsx`, `card.tsx`, `input.tsx`, `textarea.tsx`, `tabs.tsx` (`transition-all` raus; Karte ohne Hover-Heben)
- `src/app/(app)/sidebar.tsx` (ohne `group-hover:scale-110`, ohne `transition-all`)
- `src/components/stat-bar-list.tsx` (Balken ohne Übergang)
- `src/components/today/today-panel.tsx` und `today/use-task-actions.ts`: Wegfalten über `AnimatePresence` und `m.li layout` mit `SPRING_FLIGHT`; `EXIT_DELAY_MS` bleibt
- `src/components/offline/pending-queue-sheet.tsx` und `src/app/(app)/voice/page.tsx`: Entfernen über dasselbe Muster
- alle `motion-safe:`-Treffer mit Verschiebung, Drehung, `animate-pulse` oder `animate-spin` (Codemod → `motion-full:`). Heute betroffen:
- `rule-card-shell.tsx`, `suggestions/page.tsx`, `restriction-override.tsx`, `form-section.tsx`, `suggestion-group.tsx`
- `hive-card.tsx`, `colonies/[id]/hive/page.tsx`, `voice-capture-card.tsx`, `voice-recorder.tsx`
- `label-compliance-panel.tsx` (`motion-reduce:animate-none` → `motion-full:animate-spin`)
- Beute als Verbraucher derselben Quelle:
- `src/components/hive/hive-scene/quality.ts` (`SPRING_STIFFNESS`/`SPRING_DAMPING` aus `tokens.ts`)
- `use-hive-motion.ts` (`SUBTLE_FADE_SECONDS` aus `tokens.ts`)
- `hive-visual-slot.tsx` (`FADE_MS.subtle` = `--motion-fade`)
- `src/styles/baukasten-guard.spec.ts`: Regelgruppe „Bewegung“ (Spec §17.7)
- Unverändert: three.js-Szene (`use-animated-node.ts`, `model-rig.tsx`); `.honey-check` (nur Fokus-Ausnahme aus A5).
**Interfaces**
```ts
export const MOTION = { fadeMs: 150, enterMs: 200, settleMs: 350, momentMs: 420, shiftPx: 8 } as const;
export const SPRING_FLIGHT = { type: "spring", stiffness: 210, damping: 21, mass: 1 } as const; // = Beute-Feder
export const SUBTLE_FADE_SECONDS: number; // MOTION.fadeMs / 1000
export function springEasing(points?: number): string; // CSS linear(...) aus springStep; erzeugt --ease-spring
export function transitionFor(level: MotionLevel, kind: "enter" | "exit" | "fade" | "layout"): Transition; // off → { duration: 0 }
export function scrollBehaviorFor(level: MotionLevel, distancePx: number, viewportPx: number): ScrollBehavior; // smooth nur bei full und < 1 Bildschirm
export function AppMotion(props: { children: ReactNode }): JSX.Element; // full: reducedMotion "never"; subtle: "always"; off: transition duration 0
```
- [ ] **Schritt 1: Failing Tests**
```ts
// tokens.spec.ts
it('css motion variables equal the TS tokens', ...); // liest globals.css
it('the flight spring equals the hive spring in quality.ts', ...);
it('--ease-spring samples stay within 0.02 of springStep', ...);
it('transitionFor off has zero duration and subtle has no spatial part', ...);
it('scrollBehaviorFor is smooth only at full and below one viewport', ...);
// app-motion.spec.tsx
it('sets reducedMotion per level and follows a level change in the same tab', ...);
// today-panel.spec.tsx (neu, gibt es noch nicht)
it('a ticked task leaves via layout at full and instantly at off', ...);
it('a ticked task never collapses grid-template-rows', ...);
// guard (baukasten-guard.spec.ts, Gruppe Bewegung)
it('no motion-safe: on translate, scale, rotate, slide, zoom or animate classes', ...);
it('no transition-all and no duration above 420 ms outside components/hive', ...);
it('hover translate or scale only inside components/hive', ...);
it('motion/react is used only for LazyMotion, MotionConfig, AnimatePresence and hooks; elements come from motion/react-m', ...);
it('globals.css keyframes and transitions do not animate width, height, grid-template-rows, filter or box-shadow', ...);
it('stat bars and other data values have no transition', ...);
```
- [ ] **Schritt 2:** `npx vitest run src/lib/motion src/components/app-motion.spec.tsx src/components/today src/styles scripts` → FAIL.
- [ ] **Schritt 3: Implementieren.**
- Codemod (`motion-safe:` → `motion-full:` nur für Verschiebung, Pulsieren und Drehen; Farbübergänge bleiben ohne Variante) ausführen und den Diff prüfen.
- Dann die Tokens setzen, `AppMotion` einbauen und die Listen umstellen.
- Skelett-Verzögerung 150 ms und Spinner ab 300 ms mit Wort, wo `QueryState`/Knöpfe das heute nicht tun (Spec §17.4).
- Toast bei „Dezent“ ohne Gleiten (Sichtprüfung; falls nötig CSS an `[data-sonner-toaster]`).
- [ ] **Schritt 4:** → PASS.
- [ ] **Schritt 5: Verifikation** – V mit `src scripts`; Bundle-Messung `motion`-Chunk ≤ 30 kB gzip, nicht im First Load von Login und Herkunft (Build-Ausgabe).
- VB:
- jedes Muster aus Spec §17.4 auf Start (Abhaken), Aufgaben, Warteschlangen-Sheet, Volk (Sheet, Beute), `/voice` (Entfernen), `/voice/new` (Aufnahme-Punkt)
- je Voll, Dezent, Aus und `prefers-reduced-motion: reduce`, 390 px und 1366 px
- Performance-Trace bei 4-facher CPU-Drosselung (390 px):
- Sheet auf/zu, Abhaken mit Wegfalten, Seitenwechsel
- kein Frame > 32 ms, kein Layout-Eintrag während der Bewegung außer der `layout`-Messung
- Danach `review-animations` über den Diff.
- Kein Commit.
---
### Task A12: Beute-Bühne an Sonne und Darstellungswechsel anschließen (Spec §17.8, Beute-Spec §9.3, neu im Review 2026-10-16)
**Files**
- Modify:
- `src/components/hive/hive-scene/theme.ts` (Tokens bei `apicore:appearance` neu lesen statt einmalig)
- `hive-canvas.tsx` (Bloom aus in Sonne)
- `materials.ts` und `frame-textures.ts` (Sonne: Kanten 2 px reinweiß; Rähmchen-Arten als Schraffur je Art statt Tönung)
- `hive-labels.tsx` und `src/components/hive/hive-glass.ts` (Sonne: Etiketten 16 px, kein `backdrop-blur`)
- `src/components/hive/hive-card.tsx` und `src/app/(app)/colonies/[id]/hive/page.tsx` (Bühnen-Wurzel bekommt `.holo-stage`)
- Specs dazu (`hive-scene-content.spec.tsx`, `frame-textures.spec.ts`)
- Consumes: Holo-Sonne-Tokens und `.holo-stage` (A1), Ereignis `apicore:appearance` und `useAppearance().sunActive` (A2).
**Interfaces**
- `readHoloTheme(): HoloTheme` liest bei jedem Aufruf neu. `useHoloTheme()` abonniert `apicore:appearance` und ruft `invalidate()` auf.
- `frameLookFor(type, { sun }): { color: Color | null; hatch: HatchKind | null }`.
- [ ] **Schritt 1: Failing Tests**
```ts
it('the scene re-reads the holo tokens when the appearance changes', ...);
it('sun turns bloom off and draws white edges', ...);
it('in sun every frame type has its own hatch and no tint', ...);
it('labels are 16 px and without backdrop blur in sun', ...);
it('focus inside the stage uses the holo ring token', ...); // .holo-stage setzt --ring
```
- [ ] **Schritt 2:** `npx vitest run src/components/hive` → FAIL.
- [ ] **Schritt 3: Implementieren.**
- [ ] **Schritt 4:** → PASS.
- [ ] **Schritt 5: Verifikation** – V mit `src/components/hive`. VB:
- Volk und `/colonies/[id]/hive` in hell, dunkel, Sonne hell und Sonne dunkel
- Sonne live umschalten: Die Szene zieht ohne Neuladen mit
- Tastatur-Fokus auf Glas-Knöpfen sichtbar
- Budget des 3D-Chunks unverändert (CI-Prüfung)
Kein Commit.
---
## Lieferung T5b – Handschrift
### Task B1: Waben-Standkarte (Spec 6)
@@ -918,7 +1145,8 @@ it('the pointer is a fixed element without animation', ...);
| 13.4 Sichtprüfung, Lighthouse, Impeccable, Draußen-Test | A10, B8 |
| 14 Aufwand, Zwei Lieferungen | Kopf, Abhängigkeiten |
| 15 Rollout (Reihenfolge, Service Worker, Nutzerhinweis, Doku) | Abhängigkeiten, A9, A10, B8 |
| 16 Offene Fragen (vorläufig A/A/A) | Kopf |
| 16 Offene Fragen (vorläufig A/A/A, Frage 4 Bewegungs-Sprache neu, Empfehlung A) | Kopf, Status |
| 17 Bewegungs-Sprache (Stufen, Tokens, Muster, Nie-Liste, Leistung, Abnahme) | A11; Beute-Bühne 17.8: A1, A12 |
---