Stilpakete: Architektur des neuen Design-Systems
Stand 15.10.2026, gemessen an 31a46db56 (beta). Vorgang E-261015-designsystem-neu, Entscheidung docs/kontext/entscheidungen/2026-10-15-designsystem-neuaufbau.md.
Christian am 15.10.2026: „Am besten von Anfang an modular arbeiten (sodass der Übergang nichts bricht und jederzeit aufs Legacy-Theme geschaltet werden kann um Nutzung zu ermöglichen (auch admin-Setting die zwischen neu und legacy toggled für alle), damit wir später noch ändern können. Da sollte unser Component/Widget-System praktisch sein als Vorarbeit.“
Dieses Papier beschreibt den Bau, nicht die Richtung. Welches neue Paket kommt, wählt Christian an den Musterbögen (docs/gestaltung/musterboegen/stilpakete/). Zahlen ohne Vermerk sind gezählt oder gemessen; Schätzungen heißen so. Gezählt wurde mit grep über packages/frontend/src und packages/plugins/src ohne Testdateien; das Hauptbündel wurde mit Vites Produktionsbau in einen eigenen Ordner gebaut (dieselbe Prüfsumme index-44m9sH9P.js wie build.blick/).
1. Bestand
1.1 Das Theme
- Ein Objekt für den ganzen Baum.
baueTheme(packages/frontend/src/theme/theme.ts) baut aus einer Wahl — Szene, Kontrast, Dichte, Bewegung, Abo-Stufe, Tageszeit, Wetter — einTheme.GestaltungProvider(theme/Gestaltung.tsx) baut es neu, sobald sich eine dieser Angaben ändert, und schiebt es überThemeContextnach oben;ThemeProvider(theme/ThemeProvider.tsx) setzt vor dem ersten Bild das Theme aus der Geräteschicht und reicht es an styled-components. Jedes neue Objekt lässt styled-components die Stile aller gezeichneten Bausteine neu rechnen, allein durch die Tageszeit viermal am Tag. - Wer es liest. 9 519 Zugriffe auf die fünf großen Bereiche (
spacing3 028,neutral2 688,typography2 094,colors1 087,borderRadius622) in 462 Dateien, dazubreakpoints157 undtransitions119. 149 Aufrufe vonuseTheme()in 119 Dateien lesen Werte in JavaScript, darunter Mermaid (components/text/Diagramm.tsxrechnet mithex(theme.neutral.schwach)), SVG-Attribute in sechs Dateien (formen/Ring.tsx,zeichen/Zeichen.tsx,LeitstandWeekCurve.tsx,Tagesbogen.tsx,Tagesbahnen.tsx,Interessengraph.tsx) und das Glas mit angehängter Deckkraft (${theme.neutral.karton}ccintheme/werkstoffe.ts). 225 Dateien importieren unmittelbar aus Modulen untertheme/, am häufigstenwerkstoffe(75),bewegung(56) undeingabeschrift(39). 361 Testdateien bauen ihr Theme mitbaueThemeoderdefaultTheme. - CSS-Variablen gibt es schon dreimal, jedes Mal als Insel.
:rootträgt die Dauern der Bewegung (GlobalStyles.tsx). Die Schaubühne der Startseite schreibt ihre Werte an die eigene Wurzel, ihr Stil nennt nurvar(--…)(theme/schaubuehne.ts,components/screens/startseite/). Der Musterbogen/stil/richtungsetzt die Werte jeder Richtung als Variablen an den Rahmen der Probe (components/stil/richtung/Musterbogen.tsx). Dessen Datenform (richtungen.ts: Farben je Schema, Schriften, Ecken, Dichte,linien,raender, Himmelsform, Begleiterform) ist schon fast die eines Stilpakets.color-mix()steht 120-mal im Quelltext und arbeitet mit Variablen. - Die Ecken greifen in jedes Stilblatt.
theme/ecken.tshängt als stylis-Plugin anStyleSheetManager, streckt jede Pixel-Rundung um 1,5 und setztcorner-shape. Das ist ein Merkmal des heutigen Aussehens, wirkt aber global, und eine Rundung ausvar()kann es nicht strecken. - Schriften. Drei Familien in sieben Dateien, 208,7 kB (
public/schrift/), angemeldet mit@font-faceinGlobalStyles.tsx. - Feste Größen hängen am Theme-Objekt.
hooks/useSchmal.ts,handlers/nutzungsprotokoll.tsundcomponents/widgets/general/navbar/topNavigationConfig.tsxlesen ihre Bruchstellen ausdefaultTheme; damit hängt das Hauptbündel am ganzenbaueTheme.theme.tsbaut beim Laden außerdemthemeDictionary,darkThemeundlightTheme, die außerhalb vontheme.tsniemand liest.
1.2 Die Bausteinschicht und wer sie nutzt
Gezählt sind Dateien, die den Baustein einführen. Die Bereiche führen über relative Pfade ein (../../../../frontend/src/components/…).
| Baustein | Ort | Dateien |
|---|---|---|
ActionButton, TextField, ControlRow, Panel | components/controls/Controls.tsx | 196 führen Controls ein; ActionButton steht in rund 180, TextField in 86 |
Button | components/ui/Button.tsx | 18, dazu 13 über ui/index.ts |
Segmentwahl | components/ui/Segmentwahl.tsx | 16 |
MenuScreen (Kopf, Abschnittsreiter, Ansichtssegmente, Suche, Anlegen) | components/menus/shell/MenuScreen.tsx, MenuShell.tsx | 27 |
EmptyState | components/dataview/EmptyState.tsx | 24 |
Liste | components/formen/Liste.tsx | 19 |
Modal | components/ui/Modal.tsx | 10 |
Badge | components/ui/Badge.tsx | 8 |
Werkstoffe papier, karton, glas, stein, korn | theme/werkstoffe.ts | 74 |
Tabs, Input, Checkbox, Tooltip, Divider | components/ui/ | je 0 bis 1 außerhalb von /stil |
Select | components/ui/Select.tsx | 0 |
Karte, Zeile, Blatt | components/formen/ | 1, 1, 3 |
Einstellungsgruppe | plugins/src/settings/client/Einstellungsgruppe.tsx | 1; liegt in einem Bereich und ist nach Grundsatz 43 für keinen anderen erreichbar |
Table, Tab, TextButton, VerticalDivider | components/widgets/general/ | 0, tot |
Was es gibt, reicht als Vorarbeit: Werkstoffe, MenuScreen, Segmentwahl und EmptyState sind schon Bausteine mit Regel und Test. Was fehlt, ist die Trennung zwischen dem, was ein Baustein ist (Aufbau, Verhalten, Zugänglichkeit), und dem, wie er aussieht (Werte und Gestalt). Heute steht beides in derselben Vorlage, mit den Werten des heutigen Aussehens darin.
1.3 Doppelt vorhanden
- Knopf:
ActionButtonundui/Button(mitui/steinschliff.ts, seit dem 18.10.2026theme/steinschliff.ts) nebeneinander, dazu der toteTextButton. - Reiter und Segment:
MenuTabBar/MenuTabundAnsichtsReiterinMenuShell.tsx,Segmentwahl,ui/Tabs(nur auf/stil), der toteTab, dazu eigene Reiter inplugins/src/calendar/client/Monatsblatt.tsx,study/client/Interessenbaum.tsx,wiki/client/Pfadleiste.tsx,admin/client/leitstand/LeitstandView.tsx,components/bearbeiten/reiterfolge.tsxundcomponents/menus/shell/Anlegefach.tsx. Die Befragung fand fünf Formen auf acht Schirmen. - Feld:
TextField,ui/Input,MenuSearchundFeld/Hakeninplugins/src/admin/client/pflegebausteine.ts; Auswahl alsSelectField(Radix),ui/Selectundui/Dropdown. - Fläche: zwei Bausteine namens
Panel(controls/Controls.tsxundui/Panel.tsx), dazuformen/Karteund die Werkstoffe. - Tabelle, Trenner:
DataTablegegen den totenTable,ui/Dividergegen den totenVerticalDivider. - Leerzustand:
EmptyStategegen 26 eigeneLeer…- undEmpty…-Definitionen in Schirmen. - Einstellungsgruppe:
study/client/Themengliederung.tsxbaut ihre Regel von Hand nach.
1.4 Was die Schirme selbst bauen
3 726 styled-Definitionen, davon 2 844 in den Bereichen und 206 in den Bausteinordnern (ui, controls, formen, dataview, layout, menus/shell). 284 lokale Knöpfe (styled.button: 211 in 135 Bereichsdateien, 73 in 50 Dateien des Frontends), 121 lokale Überschriften (styled.h1 bis h3). Zeilen mit einer rohen px-Zahl: rund 1 680 in plugins/*/client, rund 1 250 in frontend/src/components (ohne Kommentarzeilen; Haarlinien von 1 px zählen mit).
| Bereich | styled | lokale Knöpfe | lokale Überschriften | .tsx | mit gemeinsamem Knopf | mit EmptyState |
|---|---|---|---|---|---|---|
| admin | 478 | 27 | 23 | 48 | 23 | 0 |
| settings | 317 | 14 | 7 | 49 | 31 | 1 |
| begleiter | 292 | 12 | 2 | 40 | 24 | 0 |
| documents | 265 | 37 | 2 | 43 | 4 | 1 |
| study | 239 | 19 | 11 | 24 | 12 | 2 |
| wiki | 216 | 19 | 6 | 23 | 15 | 1 |
| calendar | 191 | 11 | 7 | 20 | 15 | 0 |
| latex | 189 | 5 | 15 | 16 | 15 | 5 |
| dashboard | 105 | 15 | 5 | 10 | 2 | 0 |
| tasks | 104 | 11 | 2 | 11 | 6 | 0 |
| stundenplan | 101 | 8 | 0 | 13 | 11 | 1 |
Kalender und Stundenplan zeichnen in zwei Rastern: calendar/client/Stundenraster.tsx (1 073 Zeilen) und Monatsblatt.tsx (1 579) gegen stundenplan/client/Wochenraster.tsx (1 242). Die Befunde 1 bis 4 der Befragung (uneinheitliche Bausteine, keine Hierarchie, zwei Raster, doppelte Navigation) sind zum größeren Teil Folgen dieser Zahlen.
1.5 Hauptbündel und Nachladen
- Gemessen: 1 964,3 kB roh, Grenze 1 434,0 kB (
HAUPTBUENDEL_GRENZEinpackages/backend/src/database/scripts/blick/verifyBuendel.ts), also 530 kB darüber.B-261015-glieder-gruennennt 1 960,6 kB. - Woraus es besteht (vor dem Verkleinern, zusammen 4 191,7 kB; verkleinert ist es das 0,466-Fache):
react-dom539,5 kB, Framer Motion mitmotion-dom374 kB, Krypto-Nachbildungen (bn.js,readable-stream,vite-plugin-node-polyfills,diffie-hellman,miller-rabin,ripemd160und weitere) rund 741 kB übersrc/handlers/startabruf.ts,plugins/src/begleiter255 kB,shared/src/config297 kB, styled-components mit stylis 54 kB. Das Theme sind 33 Module mit 138,9 kB, verkleinert geschätzt rund 65 kB. Die Überschreitung kommt nicht vom Theme. - Der Himmel lädt nach.
Himmel.tsx,gelaende.ts,Kopfband.tsxundhimmelsschrift.tsstehen im Stück der Übersicht (Dashboard-*.js), nicht im Hauptbündel. Im Hauptbündel stehenEule.tsxundHorizont.tsx. - Stile entstehen zur Laufzeit. Der Bau liefert drei CSS-Dateien:
index(0,6 kB),GeneralMenu(2,1 kB), KaTeX (30,3 kB). Alles andere schreibt styled-components beim Zeichnen. - Kommentare reisen mit. Kommentare in styled-Vorlagen sind Teil der Zeichenkette und überstehen das Verkleinern: 33,2 kB im Hauptbündel, 121,6 kB über alle Stücke; die Einrückung in den Vorlagen kostet im Hauptbündel noch einmal rund 11,5 kB.
- Wie Vite nachlädt. Schirme über
spaeterinplugins/src/register.client.tsx(React.lazyohne Suspense, wenn das Stück schon da ist). Vor dem ersten Bild wartetindex.tsxaufersterSchirm(App.tsx) undtabelleVorDemErstenBild(config/sprachtabellen.ts), beide mit Frist 2000 ms; die Sprachtabelle ist das Muster für ein Stück, das je Gerät verschieden ist und vor dem ersten Bild gebraucht wird. Ein Stück, das ein CSS mitbringt, hängt Vite beim Laden an. Scheitert ein Nachladen, lädthuelle/fehlendeStuecke.tseinmal neu. Die Hülle (public/sw.js,huelle/bauliste.ts) legt alle Stücke unterassets/und alle WOFF2 unterschrift/ab, auf jedem Gerät. vite.config.mtserklärt Module untercomponents/ui/undcomponents/controls/für frei von Wirkungen beim Laden; ein unbenutzter Baustein fällt so aus dem Bündel.
1.6 Einstellungen und Admin-Werte
- Schichten (docs/gestaltung/einstellungen.md §2): eingebaut, Instanz (
personal.preference_defaults, gesetzt mitsettings.global_default), Rolle (personal.preference_role_defaults), Nutzer (personal.preferences), Gerät (localStoragedenotato.geraet); oben gewinnt. Jeder Schlüssel inpackages/shared/src/config/preferenceKeys.tsträgt seine Reichweite (UEBLICH,MIT_GERAET,NUR_INSTANZ,NUR_NUTZER…), und der Server prüft sie beim Schreiben (schichtErlaubt). - Instanzwerte (
shared/src/config/instanzwerte.ts,admin.instance_values) sind Zahlen mit Einheit und Grenzen, gedacht für Bremsen und Fristen. Für die Wahl eines Pakets passen sie nicht. - Der Admin setzt Instanzvorgaben in
plugins/src/admin/client/Verwaltungsabschnitte.tsxübersetzeGlobal(Beispiele:PLUGINS_VERFUEGBAR,ERSTSTART_ZUSCHNITTE,BITTEN_GRENZEN). Rollenvorgaben setzt er auf der Einstellungsseite über „Ändern für“. - Laden:
handlers/startabruf.tsfragt Zugriff und Einstellungen, während der erste Schirm lädt. Einstellungen kommen je Sitzungsrunde und mitneuLaden; was ein anderer Admin oder ein anderes Gerät ändert, kommt beim nächsten Laden an. - Ohne Sitzung gibt es schon öffentliche Wege (
AUTH_GAST_ERLAUBT,AUTH_OIDC_PROVIDERSinshared/src/config/endpointPaths.ts).
2. Zielbild
2.1 Drei Schichten
Schirme ordnen an: Bausteine und Anordnung, keine eigenen Werte
│
Bausteine Aufbau, Verhalten, Zugänglichkeit; Aussehen nur aus
│ Tokens (CSS-Variablen) und dem Rezept des Pakets
│
Kern Tokenvertrag, tk, Tokenschreiber, Paketlader, Register;
│ Szenen, Tageszeit, Wetter, Himmelsgrund, Bewegung,
│ Geräteschicht, Gestaltung → im Hauptbündel
│
Stilpaket Werte, Rezepte, Bühne (Grund, Texturen, Schriften),
Himmelsauftritt, Eulenkostüm → je Paket ein Stück,
nur das aktive lädtSchirme kennen kein Paket, Bausteine kennen kein Paket, und ein Paket kennt keinen Schirm. Die einzige Stelle, die Pakete einführt, ist der Lader.
2.2 Was ein Stilpaket ist
Ein Ordner packages/frontend/src/theme/pakete/<name>/ mit einem Einstieg:
export interface Stilpaket {
readonly name: Stilpaketname;
/** Werte und Kompatibilität aus derselben Wahl wie heute baueTheme. */
readonly baue: (wahl: Themewahl) => { readonly theme: Theme; readonly tokens: Tokensatz };
/** Gestalt je Baustein; fehlt eine, gilt das Grundrezept des Kerns. */
readonly rezepte: Partial<Rezepte>;
/** Grund, Texturen, @font-face — ein createGlobalStyle des Pakets. */
readonly Buehne: React.ComponentType;
readonly himmel: Himmelsauftritt;
readonly eule: Eulenkostuem;
/** Welche Einstellungen das Paket versteht (Abo-Theme, eigene Szene, Zeichenstil, Serif). */
readonly kann: Paketfaehigkeiten;
}- Werte (Tokens) heißen
--dn-<gruppe>-<name>und stehen im Tokenvertrag (theme/vertrag/). Rund 80 davon kennt das heutige Theme schon:Gruppe Beispiele heute im Theme Fläche flaeche-grund,-stein,-papier,-karton,-glas,-ueberfahrenneutral.grund/stein/papier/karton,colors.glass.*,colors.ueberfahrenTinte tinte-text,-lese,-schwachneutral.text/lese/schwachLinie linie-rand,-kante,-trennerneutral.rand/kante,decoration.*Rolle handlung,handlung-hover,handlung-auf,handlung-schrift,fach,fach-schriftcolors.handlung.*,colors.fach.*Zustand erfolg,erfolg-leise,erfolg-auf, ebensowarnung,gefahr,hinweiscolors.status.*Form rundung-xsbis-xl,rundung-pille,ecke-form,ecke-streckungborderRadius.*,theme/ecken.tsTiefe schatten-sm/md/lg,schein-fokusshadows.*Textur textur-korn,textur-korn-deckkraft,textur-papier,textur-grundkorn.*Satz schrift-bedienen,-lesen,-aufmacher,-zahlen,-code,groesse-xsbis-aufmacher,gewicht-*typography.*Abstand abstand-xsbis-xxxl,dichte-zeile,dichte-innenspacing.*,dichte.*Die Bewegung (Federn je Anlass, Entscheidung 2026-10-07-bewegung) bleibt im Kern und ist kein Paketwert.
- Rezepte sind styled-
css-Fragmente je Baustein und Art (Knopf primär, sekundär, Geist, Gefahr; Reiter; Segment; Feld; Fläche je Werkstoff; Zeile; Leerzustand; Fenster). Sie tragen, was ein Wert nicht ausdrücken kann: Linien statt Flächen, Rand oder Helligkeitsstufe, Unterstrich statt Kapsel (die Schalterlinienundraenderder Richtungen). Ein Baustein setzt Aufbau und Zugänglichkeit selbst und bindet das Rezept ein:const Grund = styled.button<{ readonly $art: Knopfart }>` font: inherit; border-radius: var(--dn-rundung-knopf); ${({ theme, $art }) => theme.paket.rezepte.knopf[$art]} `; - Texturen sind Bilder, die das Paket als Vite-Asset einführt; die Variable trägt
url(…). Der Browser lädt ein Hintergrundbild erst, wenn eine Regel es braucht. - Schriften meldet die Bühne des Pakets mit
@font-facean; Dateien unterpublic/schrift/<paket>/. Eine Schrift lädt erst, wenn Text sie braucht; die Bedienschrift kann der Lader vorab anfordern. - Vorladen je Paket (Stand 19.10.2026). Die festen
<link rel="preload">inindex.htmlsind weg: Sie luden unter jedem Paket die Schriften von Legacy.VORLADENintheme/paket/vorladen.tsnennt je Paket die Schnitte des ersten Bildes (Bedienschrift und Titel, aufrecht; Fira Code und Kursive nicht), und der Lader setzt sie mitladeSchriftenVorzugleich mit demimport()des Paketstücks, beim Rückfall die von Legacy. Ein Skript inindex.htmlverbietet die CSP. Die Wege stehen ohneurl(, sonst gehörte die Schrift in der Bauliste dem Kern; anfordern muss jedes Paket seine Schriften weiter in seiner Bühne. Gemessen unter Legacy: Die Schriften beginnen gut 150 ms später als ausindex.html, sind aber vor dem ersten Bild da. Das Flaggschiff hat eigene Dateien unterschrift/flaggschiff/(Newsreader mit opsz, Source Sans 3 variabel), weil 500, 650 und opsz sonst nicht wirken. - Himmel und Eule bleiben in jedem Paket (Entscheidung). Szenen, Tageszeit und Wetter bleiben gemeinsamer Kern (
szenen.ts,tageszeit.ts,wetterszene.ts,grundbild.ts,Himmel.tsx). Das Paket bestimmt den Auftritt: Vollbild, Kopfband, Band oder Linie, welche Modi vontheme.himmeles anbietet, und wie der Grundton einer Szene in seine Flächen fällt. Die Eule zeichnetzeichnung.tsweiter; das Paket gibt ihr Kostüm. - Rezept
himmelund Himmel je Szene (Stand 19.10.2026).Rezepte.himmel(Himmelrezept) hat vier Teile:band(Verlauf, Tönung, Maske, ein eigenes Sternbild in&::before),stars,orb(Sonne oder Mond,data-gestirn) undland. Szene, Tageszeit, Wetter, Teilchen, Lage und Größe der Gestirne und die Form des Landes bleiben im Kern; das Rezept gibt nur den Auftritt, es zeichnet also kein Gestirn, das die Szene nicht hat. Ein Paket bringt Töne für einzelne Szenen mit:Himmelsauftritt.scenesje Szene und Tageszeit,Eulenkostuem.scenesje Szene mit Augen, Schnabel, Flügelkante undEulenton.colors. Der Kern setzt beides beim Bauen an die Stelle vonszene.himmelundszene.eule(fieldsFromChoiceintheme/geruest.ts); eine fehlende Szene und eine eigene Szene behalten ihre. Das Flaggschiff gibt Sonnentag und Nacht Himmel und Eule der Vorlage (Christian, Frage 1). Welche Tageszeiten den Himmel der Vorlage tragen, sagtTEMPLATE_SKY_TIMESinpakete/flaggschiff/zuordnung.ts: der Sonnentag nur mittags, die Nacht immer. Morgens und abends behält der Sonnentag seinen eigenen Himmel, denn der Himmel folgt dem Tagesabschnitt (Style-Guide §4.4). - Fähigkeiten. Abo-Theme (N132), eigene Szene (E04), Zeichenstil und Serif sind Begriffe des heutigen Aussehens. Ein Paket sagt, welche es versteht; die Einstellungsseite zeigt nur diese. Edelsteine und Ränge dürfen laut Entscheidung leiser werden oder entfallen.
- Was ein Paket nicht ändert: Anordnung, Verhalten, Texte, Zugänglichkeit, Bewegung (siehe Frage 3).
2.3 CSS-Variablen und Theme-Objekt: beide, mit getrennten Aufgaben
- CSS-Variablen tragen jeden Wert, der in einem Stil steht. Der Tokenschreiber des Kerns schreibt den
Tokensatzdes aktiven Pakets an:root;<html>trägtdata-stilpaket, nebendata-themeunddata-szene, die es schon gibt. Bausteine lesen sie übertkaus@/theme(tk.flaeche.papierergibt'var(--dn-flaeche-papier)');tkist aus dem Vertrag abgeleitet, nicht von Hand geschrieben (A44). Weil Variablen erben, kann ein Teilbaum ein anderes Paket zeigen: Musterbogen,/stilund eine Vorschau setzen den Satz an ihren Rahmen, wie esMusterbogen.tsxheute schon tut. - Der Tokensatz kommt aus
baue()(Stand 19.10.2026).baue(wahl)liefertGebautesmitthemeundtokens, und derThemeProviderschreibtgebaut.tokensmitschreibeTokensatzan:root, nicht mehrtokensAus(theme). So kommen Werte an, die sich aus dem Theme-Objekt nicht ablesen lassen, etwa die Streckung der Ecken oder die Form eines Pakets. Legacy und Prüfpaket bilden ihre Tokens weiter mittokensAusaus ihrem Theme, für sie steht also dasselbe an:rootwie vorher. Die Bühne der Startseite (theme/schaubuehne.ts) schreibt den Satz nicht mehr selbst, sondern erbt ihn von:root; vorher überdeckte sie unter einem anderen Paket dessen Tokens mit denen von Legacy. - Das Theme-Objekt bleibt aus drei Gründen: Es hält die alten Namen mit konkreten Werten für jeden Schirm, der noch nicht umgezogen ist; es liefert konkrete Werte an alles, was in JavaScript rechnet (Mermaid, Canvas, Kontrastrechnung, SVG-Attribute); und es trägt Rezepte und Paketangaben (
theme.paket). Ein neues Paket bekommt die alten Namen vom Kern geschenkt:themeFromTokensintheme/vertrag/themeFromTokens.tsbaut aus Tokensatz, Wahl und einem Zusatz (Paket, Rand und Schatten des Glases, Metalle, Hauptknopf) das ganze alte Theme-Objekt. Stand 19.10.2026: Die Funktion heißt englisch, nicht wie im EntwurfthemeAusTokens, weilverify:bezeichnerneue deutsche Namen sperrt. Was nicht vom Paket abhängt (Ebenen, Maße, Federn, Bruchstellen, die Auslegung der Wahl samt Serife, Verweilen, Mitgliedschaft und Abo), steht im Kern untertheme/geruest.ts; Legacy liest es von dort. Die Dichte folgt der Wahl, nichtabstand.dichte*, weiltheme.dichteauch Name und Chip-Form trägt; das Paket setzt die drei Tokens aus derselben Wahl. - Zwei Regeln aus dem Bestand. Eine Variable, deren Wert selbst
var()enthält, wird dort aufgelöst, wo sie steht, nicht dort, wo sie gelesen wird (Kopf vonschaubuehne.ts); Verläufe gehören deshalb ins Rezept, nicht in eine Variable. Deckkraft entsteht mitcolor-mix(), nicht durch angehängte Hex-Ziffern.
2.4 Das Legacy-Paket entsteht aus dem heutigen baueTheme
theme/pakete/legacy/übernimmtbaueThememit Zustands-, Fach- und Schattentafeln, Knopf und Steinen ausmetalle.ts,steinschliff.ts(seit dem 18.10.2026 im Kern, vorher untercomponents/ui/),lesefarbe.ts,kontrast.ts,vorspannfarbe.ts, das Korn ausmuster.ts, die Werkstoffrezepte und die heutigen@font-face.baueliefertthemewie heute undtokens = tokensAus(theme), eine Abbildung der alten Felder auf den Vertrag.- Die Legacy-Rezepte sind das heutige CSS von
ActionButton,TextField,MenuTab,Segmentwahl,MenuTitle,EmptyStateund der Werkstoffe. Ein Schirm, der auf die neuen Bausteine umzieht, sieht unter Legacy deshalb aus wie vorher; was sich ändert, ist gewollte Vereinheitlichung (aus fünf Reiterformen wird eine). - Das Eckenplugin wird vom Paket gesteuert: Es schreibt
corner-shape: var(--dn-ecke-form)undcalc(<px> * var(--dn-ecke-streckung)). Legacy setztsquircleund 1,5, ein anderes Paket seine eigenen Werte. - Beweis:
/ansehen allevor und nach dem Umbau ohne Unterschied, auf iPad, Telefon und Desktop, hell und dunkel. - Tests behalten ihre Pfade:
@/theme/themereichtbaueThemeunddefaultThemeaus dem Legacy-Paket weiter. Kein Laufzeitmodul außerhalb vontheme/darf diese Weiterleitung einführen (heute nur die drei Bruchstellen-Leser aus 1.1, die in eine Kerndatei umziehen).
2.5 Schirme gestalten nur noch über Bausteine
Neue Bausteine stehen unter packages/frontend/src/components/bausteine/. Die alten Exporte werden Weiterleitungen, bis niemand sie mehr einführt.
Stand 18.10.2026 (E-261016-bausteine-i-knopf-feld): Knopf, Feld, Reiter, Segment und Schirmkopf stehen, jeder mit data-baustein, einem Legacy-Rezept und dem Grundrezept aus dem Vertrag; ein Test zeichnet jeden mit leerem Rezept und findet keinen eigenen Farb-, Schrift-, Rand-, Rundungs- oder Schattenwert. Weiterleitungen sind ActionButton, ui/Button, TextField, MenuSearch, der Rahmen von ui/Input, Feld und Haken aus pflegebausteine.ts, MenuTabBar, ui/Tabs (mit dem Reitermuster aus ARIA), Segmentwahl, AnsichtsReiter, MenuTitle, MenuMotiv und Titelblock; MenuTab, MenuTabs, MenuHeader, MenuKopfende und MenuTitelblock sind entfernt. Offen aus der Tabelle bleiben die toten TextButton und Tab und die lokalen Nachbauten in den Schirmen.
Stand 18.10.2026 (E-261016-bausteine-ii-flaeche): Flaeche, Zeile mit Zeilenliste und Aufgabenzeile, Leerzustand, Einstellungsgruppe mit Klappe, Nebentext, Fenster und Unterblatt sowie Stapel, Reihe und Spalten stehen, jeder mit data-baustein. Das Rezept flaeche zeichnet die Flaeche je Stoff und ihren Kartenreiter, zeile die Linien der Zeilenliste und die Aufgabenzeile, leerzustand den Leerzustand, einstellungsgruppe die Gruppe mit Faltleiste, MehrHinweis und Klappe, nebentext den Nebentext und fenster das Fenster und das Unterblatt. Jedes dieser sechs Rezepte steht wie die der Bausteine I auch im Paket Legacy, weil seine Bausteine heutiges CSS ersetzen; erst Bausteine, die nach dem Einfrieren von Legacy entstehen, zeichnen unter Legacy mit dem Grundrezept (Kommentar in theme/pakete/legacy/rezepte.ts). Die Zeile selbst, deren Linie die Zeilenliste zieht, und die Anordnung haben kein Rezept. Weiterleitungen sind beide Panel auf Flaeche, formen/Karte auf Flaeche und Kartenreiter, Liste und Listenzeile aus formen/Liste auf Zeilenliste und Zeile, formen/Zeile auf Aufgabenzeile, EmptyState und Horizont auf Leerzustand, settings/client/Einstellungsgruppe.tsx auf Einstellungsgruppe, Faltleiste und MehrHinweis, ui/Klappe auf Klappe, Unterzeile und Hinweis aus pflegebausteine.ts auf Nebentext, ui/Modal auf Fenster sowie Knopfzeile und Felder aus pflegebausteine.ts auf Reihe und Spalten; Unterblatt und Stapel führt außer den Tests noch niemand ein. Die toten Table, Tab, TextButton und VerticalDivider sind gelöscht, auch die beiden, die Bausteine I offen ließ. Offen aus der Tabelle bleiben die Einbindungen der Werkstoffe, die Zellen, die 26 lokalen Leerzustände, der Nachbau in study/client/Themengliederung.tsx, Seitenblickblatt, die Schubladen und die lokalen styled.div für Abstände, dazu die Aufgabenzeile des Bereichs tasks.
| Baustein | ersetzt | Anmerkung |
|---|---|---|
Schirmkopf | MenuHeader, MenuTitle, MenuTitelblock, 121 lokale Überschriften | Titel, Ort, Aktionen, Platz für den Vorschlag der einen Suche (Befund 4); heißt nicht „Seitenkopf“, weil layout/Seitenkopf.tsx den Dokumentkopf hält |
Reiter | MenuTabBar/MenuTab, ui/Tabs, toter Tab, sechs lokale | Abschnitte, Navigation, aria-current |
Segment | Segmentwahl, AnsichtsReiter | wenige Stellungen, aria-pressed, Kapsel |
Knopf | ActionButton, ui/Button, toter TextButton, 284 lokale | primär, sekundär, Geist, Gefahr; xs, sm; als Verweis; Zielfläche 44 px unter pointer: coarse; Wegtun bleibt die Hülle darüber |
Feld | TextField, ui/Input, MenuSearch, Admin-Feld | Text; Auswahl, Datum, Haken und Schalter als Hüllen um SelectField, DateField, Checkbox |
Flaeche | beide Panel, formen/Karte, Werkstoff-Einbindungen | Papier, Karton, Stein und der Rahmen um ein Formular; Glas nur für Schwebendes (Liste in verifyEigenstil.ts) |
Zeile | formen/Zeile, formen/Liste, Zellen | Haarlinie, Fälligkeit kippt (Guide §7.6) |
Einstellungsgruppe | settings/client/Einstellungsgruppe.tsx, ui/Klappe, Nachbau in study/client/Themengliederung.tsx | zieht aus dem Bereich ins Gerüst; Klappe ist ihre Form am Telefon |
Nebentext | Unterzeile und Hinweis aus admin/client/pflegebausteine.ts | der kleine Satz unter einer Zeile oder neben einem Feld, leiser als der Lesetext |
Leerzustand | EmptyState, Horizont, 26 lokale | Fels und sitzende Eule zeichnet der Kern in jedem Paket; Tinte, Familie und wie leise das Band ist, sagt das Rezept |
Zeitraster | Stundenraster, Monatsblatt, Wochenraster | ein Raster mit Ebenen; der Stundenplan wird eine Ebene (Befund 3), die Daten bleiben getrennt |
Fenster, Unterblatt | ui/Modal, Seitenblickblatt, Schubladen | Fenster am Schreibtisch und iPad, Blatt von unten am Telefon; nicht „Blatt“, weil formen/Blatt das Dokument mit Eselsohr ist |
Stapel, Reihe, Spalten | lokale styled.div für Abstände, Knopfzeile und Felder aus admin/client/pflegebausteine.ts | Anordnung mit Token-Abständen, damit ein Schirm für Lücken keine eigene Vorlage braucht |
Ein Schirm darf danach noch anordnen (Raster, Spaltenbreiten, Reihenfolge), aber keinen Farb-, Schrift-, Rand-, Rundungs- oder Schattenwert setzen. verify:bausteine hält das fest (5.2).
3. Umschalten
3.1 Der Wert
- Ein Einstellungsschlüssel, kein Instanzwert:
theme.stilpaketinpreferenceKeys.ts, die ListeSTILPAKETEinshared/src/config/gestaltung.tsnebenSZENEN_NAMEN. Der Wert ist immer ein Paketname; „neu oder Legacy“ ist am Anfang die Wahl zwischen zwei Namen. Eingebaute Vorgabelegacy, bis Frage 4 entschieden ist. Der Server weist unbekannte Namen ab. - Reichweite: Instanz, Rolle, Gerät und Nutzer (gebaut mit E-261016-admin-schalter). Instanz ist „für alle“; die Rolle erlaubt eine Probegruppe (Christian und Ben zuerst) und Ausnahmen; das Gerät trägt die Vorschau für Admins und Entwickler und den Blick von
/ansehen. Die Nutzerschicht nimmt seit 2026-10-15-vier-themes nurklar,ruhigundmarkeran;legacyund das Prüfpaket setzt nur der Admin, und der Server weist sie dort mitSETTING_RESERVED_ERRORab, einen unbekannten Namen mitSETTING_INVALID_ERROR. - Wo der Admin schaltet: ein Abschnitt „Gestaltung“ in
Verwaltungsabschnitte.tsxmitsetzeGlobal, wie die Bereichsvorgaben; die Rolle über „Ändern für“. Es entsteht kein neuer Endpunkt (PREFERENCE_GLOBALundPREFERENCE_ROLEgibt es), also auch kein neues MCP-Werkzeug.
3.2 Beim Laden
index.tsx ──┬─ ersterSchirm(adresse, 2000)
├─ tabelleVorDemErstenBild(sprache, 2000)
└─ stilpaketVorDemErstenBild(paketVomGeraet(), 2000) neu
import('./theme/pakete/<name>') eigenes Stück
│
erstes Bild: Paket steht, Tokens an :root, data-stilpaket
│
startabruf → Einstellungen → GestaltungProvider löst
theme.stilpaket auf; anders als am Gerät → Lader holt das
andere Paket, wechselt einmal, merkt es am GerätpaketVomGeraet()liestdenotato.stilpaket, das zuletzt wirksame Paket dieses Geräts. Das ist ein Cache wie die Szene imThemeProvider, keine Einstellung.- Ohne Sitzung (Anmeldung, Rechtstexte) gilt das Gerät, sonst die Vorgabe. Soll die Anmeldung schon im Paket der Instanz stehen, genügt später ein öffentlicher Weg wie
AUTH_GAST_ERLAUBT. - Lädt das Stück nicht, greift das Neuladen aus
huelle/fehlendeStuecke.ts.
3.3 Ob ein Konto selbst zurückschalten kann
Gebaut ist nur „Ändern für: mein Konto“ (E-261016-admin-schalter): Die Einstellungsseite zeigt unter Darstellung die Gruppe „Aussehen“ (Stufe „erweitert“) mit „wie für alle (<Vorgabe>)“ und den gebauten wählbaren Themes. Unter „nur dieses Gerät“ steht sie nie (amGeraetEinstellbar); den Gerätewert schreiben nur /ansehen und die Vorschau im Abschnitt „Gestaltung“ der Verwaltung. Die Gruppe fehlt, solange keines von klar, ruhig und marker gebaut ist oder die Vorgabe legacy ist. „wie für alle“ nimmt den eigenen Wert zurück, statt den Namen der Vorgabe zu speichern: Wer so wählt, geht mit, wenn die Verwaltung die Vorgabe wechselt.
Seit 2026-10-15-vier-themes geöffnet: Es gibt vier Themes (flaggschiff, klar, ruhig, marker). Der Admin-Wert setzt das Haupttheme für alle, und die Nutzerschicht nimmt die drei anderen an; legacy bleibt dem Admin vorbehalten. /ansehen --pakete deckt damit alle vier ab, und der Lader holt nur das aktive Theme. Ergibt die Vorgabe aus eingebaut, Instanz und Rolle legacy, gilt legacy, gleich was das Konto gewählt hat (vorgabeUeberstimmt in preferenceKeys.ts). So bleibt „jederzeit aufs Legacy-Theme geschaltet … für alle“ (2026-10-15-designsystem-neuaufbau) wahr, und vor der Umstellung der Vorgabe sieht außerhalb der Probegruppe niemand ein neues Theme. Die Geräteschicht gewinnt weiter über alles.
3.4 Was beim Umschalten zur Laufzeit geschieht
- Paketwechsel (selten, der Admin): Der Lader holt das Stück einmal. Bis es da ist, bleibt das alte Paket stehen; dann wechseln in einem Schritt
data-stilpaket, die Variablen, das Theme-Objekt und die Bühne (dascreateGlobalStyledes alten Pakets wird abgebaut und nimmt seine Regeln mit). styled-components rechnet dabei einmal neu, so wie heute bei jedem Szenenwechsel. - Szene, Kontrast, Dichte (häufig): Solange Schirme das Theme-Objekt lesen, bleibt es wie heute. Umgezogene Bausteine lesen nur Variablen; für sie tauscht der Wechsel Werte, ohne Stile neu zu rechnen. Der Endzustand nach dem Umzug: Das Theme-Objekt bleibt je Paket stehen, und nur die Variablen wechseln (eigener Vorgang, Schritt 11 in 5.1).
- Andere Geräte bekommen den Wechsel beim nächsten Laden. Einmal je Gerät zeigt das erste Bild dann noch das alte Paket und wechselt nach Ankunft der Einstellungen.
- Gemischtes Bild: Unter einem neuen Paket zeigen nicht umgezogene Schirme dessen Farben über die Kompatibilität, aber ihre alte Gestalt. Deshalb wird das neue Paket erst Vorgabe, wenn die Schirme umgezogen sind (Frage 4).
3.5 /ansehen nimmt beide Pakete auf
- Gebaut (E-261016-admin-schalter):
--pakete legacy,pruefpaketneben--schemata. Er setzttheme.stilpaketin die Geräteschicht (denotato.geraet) und in den Cache des Laders (denotato.stilpaket), damit schon das erste Bild das Paket zeigt. Dateinamen tragen das Paket (<weg>--<gerät>-<schema>-<paket>), der Bogen stellt die Pakete nebeneinander,--vergleichvergleicht Legacy vorher mit Legacy nachher. verify:optik(zuletzt 33,8 s) läuft im vollen Lauf nur mit dem Vorgabepaket; das andere mit--affectedfür berührte Schirme. Sonst verdoppelt es seine Zeit, währendB-261015-glieder-gruendie Nachweise unter fünf Minuten bringen soll (zuletzt 9:59 min).- Als Befund, nicht als Prüfung, kann
/ansehenje Schirm zählen, wie vielebuttonkeindata-bausteintragen.
4. Bündel
Regel: Kein Modul aus theme/pakete/ steht im Hauptbündel. Der Kern wächst nur um Vertrag, tk, Tokenschreiber, Lader und Register. Jeder Vorgang misst vorher und nachher mit node betrieb/buendel.mjs --build (nicht mit dem Bau von /ansehen, siehe fallstricke.md, WI27) und schreibt beide Zahlen in den Commit.
Wie nur das aktive Paket lädt: Das Register ordnet jedem Namen ein import() zu; Vite macht daraus je Paket ein Stück. Schriften und Texturen sind eigene Dateien, angemeldet in der Bühne des Pakets; der Browser holt sie erst bei Gebrauch. Eine echte CSS-Datei je Paket ist möglich (ein .css, das der Einstieg des Pakets einführt, hängt Vite mit dem Stück an), aber nicht nötig: Die Werte schreibt der Tokenschreiber, die Gestalt tragen die Rezepte, und beides bleibt bei styled-components (Projektregel „nur Styled Components“).
| Teil | heute | mit Stilpaketen | Grundlage |
|---|---|---|---|
| Hauptbündel | 1 964,3 kB, Grenze 1 434,0 kB | wächst nicht, wird kleiner | gemessen |
| Theme im Hauptbündel | 33 Module, 138,9 kB vor dem Verkleinern, rund 65 kB danach | Kern bleibt: Szenen, Tageszeit, Wetter, Himmelsgrund, Bewegung, Geräteschicht, Gestaltung | gemessen; „danach“ geschätzt mit 0,466 |
| davon nur Legacy | theme.ts 18,9 · metalle 9,2 · steinschliff 4,4 · vorspannfarbe 2,9 · werkstoffe 2,4 · lesefarbe 2,1 · kontrast 1,5 · muster 1,2 = 42,6 kB vor dem Verkleinern | ins Legacy-Stück, bis rund 20 kB weniger im Hauptbündel | geschätzt; die Abo-Stufe aus metalle braucht Gestaltung.tsx, bis sie eine Fähigkeit des Pakets ist |
| neuer Kern | – | 3 bis 6 kB | geschätzt |
| Kommentare in styled-Vorlagen | 33,2 kB im Hauptbündel, 121,6 kB in allen Stücken | 0 | gemessen |
| Einrückung in styled-Vorlagen | rund 11,5 kB im Hauptbündel | nahe 0 | gemessen, grob |
| Legacy-Stück | – | 20 bis 35 kB, lädt neben dem ersten Schirm | geschätzt |
| neues Paket | – | 15 bis 35 kB Code; Schriften und Texturen eigene Dateien | Annahme |
| Schriften | 7 Dateien, 208,7 kB, alle angemeldet | je Paket nur die eigenen | gemessen |
Spielraum, den das Vorhaben braucht: Die Kommentare und die Einrückung in styled-Vorlagen kann ein Bauschritt entfernen (ein eigenes Plugin unter src/bau/ oder babel-plugin-styled-components mit minify, das wäre ein neues npm-Paket). Das gehört zu B-261015-glieder-gruen und ist mit ihm abzustimmen. Die Überschreitung selbst (Krypto über startabruf.ts, Begleiter) löst dieses Vorhaben nicht.
Hülle: Stand 18.10.2026 (E-261016-huelle-legt-nur-aktive): Die Bauliste in public/sw.js nennt je Datei ihre Pakete, eine leere Liste heißt Kern, und als fallbackPackage das Paket legacy. assignChunks in huelle/bauliste.ts ordnet die Stücke über ihre Erreichbarkeit im Bündel zu: Ein Paket beginnt mit dem Stück, dessen Einstieg theme/pakete/<name>/index.ts ist; Kern ist, was das Hauptbündel erreicht, ohne über ein import() in ein Paket zu gehen, ein Paket, was sein Stück erreicht, ohne durch den Kern zu gehen. Stile und Assets gehören wie ihr Stück; das Legacy-Stück trägt Legacy und das Prüfpaket, weil das Prüfpaket es einführt. Eine Schrift unter schrift/ gehört dem, der sie mit url(/schrift/….woff2) anfordert; eine Schrift zweier Pakete liegt einmal und trägt beide, eine, die niemand anfordert, gehört dem Paket ihres Ordners schrift/<name>/, wenn es eines gibt, sonst dem Kern. Der Worker legt beim Einrichten den Kern und das zuletzt gemeldete Paket ab, die Dateien eines später gemeldeten erst mit dessen Meldung, geprüft wie jede Datei. Den Namen merkt er sich in einem eigenen Speicher (denotato-huelle-meldung), der jede Fassung überdauert; wechselt das Paket, während eine neue Fassung wartet, nimmt diese beim Aktivieren die Dateien des gemeldeten Pakets aus den alten Ablagen mit, ohne das Netz zu fragen. Was ein früher gemeldetes Paket abgelegt hat, bleibt bis zur nächsten Fassung liegen. Der Lader meldet jedes Paket, das aktiv wird, vor dem ersten Bild und nach jedem Wechsel (onActivePackage); huelle/anmelden.ts reicht es nur im Bau per postMessage an den Worker weiter, sobald einer aktiv ist. Beim ersten Besuch richtet sich der Worker vor jeder Meldung ein und legt legacy ab; das gemeldete Paket folgt mit der Meldung. Ohne Netz startet das zuletzt gemeldete Paket, ein anderes fängt huelle/fehlendeStuecke.ts ab. Seit dem 19.10.2026 nimmt die Hülle auch Bilder auf: gehoertInDieHuelle lässt außer Stücken, Stilen und WOFF2 ein Bild unter assets/ zu, wenn ein Stück es einführt; assignChunks liest dazu die importedAssets jedes Stücks, also gehört ein Bild dem Paket, dessen Stück es einführt. Beim Flaggschiff ist das nur himmel-nacht.svg (eingeführt mit ?no-inline); die kleineren Texturen legt Vite als data:-Adresse ins Stück. Den Boden Legacy legt der Worker immer mit ab: Auf ihn fällt der Lader zurück, wenn das aktive Paket nicht lädt, und ohne Netz muss er dann liegen. Unter dem Prüfpaket kostet das keine Datei, weil sein Stück das Legacy-Stück einführt. Das Flaggschiff führt Legacy nicht ein; unter ihm legt der Worker dessen Dateien zusätzlich ab, rund 226 KB im Hintergrund (Empfehlung aus E-261016-huelle-legt-nur-aktive). Christian hat am 19.10.2026 entschieden („Erst später weg“): Der Boden bleibt vorerst und fällt weg, sobald das Flaggschiff Vorgabe für alle ist.
5. Übergang
5.1 Reihenfolge
| Schritt | Vorgang | setzt voraus | sichtbar |
|---|---|---|---|
| 1 | Token-Schicht aus dem heutigen Theme | – | nein |
| 2 | Legacy-Paket und Paketlader | 1 | nein |
| 3 | Admin-Schalter, Prüfpaket, /ansehen --pakete | 2 | nur in der Verwaltung |
| 4 | Bausteine I: Knopf, Feld, Reiter, Segment, Schirmkopf | 1, Rezepte aus 2 | unter Legacy nein |
| 5 | Prüfglieder verify:bausteine, verify:stilpakete | 4 | nein |
| 6 | Bausteine II: Fläche, Zeile, Leerzustand, Einstellungsgruppe, Fenster und Unterblatt, Anordnung | 4 | unter Legacy nein |
| 7 | Bausteine III: Zeitraster mit Ebenen | 6 | ja (Befund 3) |
| 8 | Erstes neues Paket nach Christians Wahl | 3, 4, 6 | nur mit Schalter |
| 9 | Schirme umziehen, je Bereich ein Vorgang | 5, 6 | unter Legacy nur gewollte Vereinheitlichung |
| 10 | Gerüst: schmale Leiste, eine Suche, weniger Reiter | Frage 2 | ja |
| 11 | Vorgabe umstellen, Legacy nach Frage 5 behandeln, Theme-Objekt je Paket festhalten | Fragen 4, 5 | ja |
Das Prüfpaket aus Schritt 3 ist Legacy mit wenigen anderen Werten (etwa Handlung in Kobalt, kleinere Rundung, Grotesk im Aufmacher), nur für Entwickler in der Liste. Es beweist den Wechsel und lässt jeden Baustein in zwei Paketen testen, bevor das neue Paket existiert.
Reihenfolge der Schirme in Schritt 9 nach der Befragung: Kalender und Stundenplan, Studium und Tutor, Verwaltung, Einstellungen, Leiste und Kopf, danach der Rest nach Nutzung; jeweils das iPad im Querformat zuerst.
5.2 Prüfglieder
Beide nach dem Muster von verifyEigenstil.ts mit eigenstilBestand.ts. verify:bausteine führt einen Bestand je Datei (bausteineBestand.ts): Er wurde einmal mit --schreiben --heben erzeugt; danach senkt --schreiben ihn nur, er darf nicht steigen, und jede Meldung nennt Datei, Zeile und den Baustein als Abhilfe (P9). verify:stilpakete braucht keinen Bestand: Es gibt keinen Fund, der bleiben dürfte; die Regeln 2 und 5 stehen als Vitest-Test in theme/paket/stilpakete.test.ts, den das Glied startet.
verify:bausteine in Schirmdateien (plugins/src/*/client/**, frontend/src/components/screens/**, frontend/src/components/pages/**):
- lokaler Knopf (
styled.button,styled(motion.button)) →Knopf - lokale Überschrift (
styled.h1bish3) →Schirmkopf - eigener Reiter (
role="tablist", Namen aufReiter,Tab,Segment) →ReiteroderSegment - eigener Leerzustand (
Leer…,Empty…) →Leerzustand - Gestaltungseigenschaft in einer styled-Vorlage (
color,background,border,border-radius,box-shadow,font-*) → Baustein oderFlaeche - rohe px-Zahl außerhalb von Anordnungseigenschaften → Token-Abstand
- Import aus
theme/werkstoffeodertheme/pakete/→Flaeche
verify:stilpakete:
STILPAKETEinshared, das Register und die Ordner untertheme/pakete/nennen dieselben Namen.- Jedes Paket liefert jeden Wert des Vertrags (die Typen erzwingen es) und jedes Rezept oder ausdrücklich das Grundrezept.
- Nur der Lader und Tests führen
theme/pakete/*ein; kein Paket führt ein anderes oder etwas auscomponents/ein. - Im Bündelbild des Hauptbündels (
packages/frontend/.buendel/) steht kein Modul austheme/pakete/. - Kontrast je Paket: Text-, Lese- und Nebentinte auf jeder Fläche mindestens 4,5 : 1, Tag und Nacht, alle zwölf Szenen (Test nach dem Muster von
theme/kontrast.test.ts).
verify:stil (Guide gegen Theme) liest künftig den Tokenvertrag; betrieb/designsystem/design-md.mjs erzeugt die Tokentabelle für DESIGN.md aus ihm.
5.3 Wie ein Schirm umzieht, ohne dass Legacy bricht
/ansehen <weg> --geraete ipad,telefon,desktop --pakete legacyvorher.- Lokale Nachbauten durch Bausteine ersetzen; was im Schirm bleibt, ist Anordnung.
/ansehennachher mit--pakete legacy,<neu>und Vergleich. Unter Legacy ändert sich nur gewollte Vereinheitlichung; sie steht im Commit-Rumpf.npx tsx src/database/scripts/verifyBausteine.ts --schreiben(inpackages/backend) senkt den Bestand.docs/seiten/<seite>.mdnachziehen.
Legacy bricht nicht, weil die Legacy-Rezepte das heutige Aussehen der Bausteine zeichnen und das Theme-Objekt für nicht umgezogene Teile gleich bleibt.
6. Risiken und offene Fragen
| Risiko | Wirkung | Gegenmittel |
|---|---|---|
verify:buendel ist schon rot | kein Vorgang kann „nicht gewachsen“ am Glied zeigen | Vorher-nachher-Zahl je Commit; Grenze zurück über B-261015-glieder-gruen |
| Erstes Bild wartet auf ein weiteres Stück | verify:schirmzeit ist schon rot (fünf Schirme über 1000 ms p90) | Paket parallel zum ersten Schirm laden; p90 je Schirm vorher und nachher vergleichen |
| JavaScript liest Farben | Mermaid, Canvas, SVG-Attribute und ${karton}cc vertragen kein var() | Theme-Objekt behält konkrete Werte; nur Bausteine lesen Variablen |
| Eckenplugin streckt nur px | Rundungen aus Variablen blieben ungestreckt | Plugin wird tokengesteuert (2.4) |
Variable mit var() im Wert | löst sich am falschen Element auf | Verläufe ins Rezept |
| Legacy-Rezepte doppeln die Gestaltungsarbeit | jeder Baustein zweimal | Frage 5: Legacy nach dem Umzug einfrieren |
| Gemischtes Bild unter dem neuen Paket | nicht umgezogene Schirme mit alter Gestalt | neues Paket erst Vorgabe nach dem Umzug (Frage 4), Probegruppe über Rolle |
| Einmaliger Wechsel nach dem ersten Bild | ein Gerät sieht nach dem Umschalten einmal das alte Paket | hinnehmen; später ein öffentlicher Weg für den Instanzwert |
| Hülle legt alle Pakete ab | Schriften und Texturen inaktiver Pakete auf jedem Gerät | Kern und gemeldetes Paket statt aller, gebaut am 18.10.2026 (E-261016-huelle-legt-nur-aktive, Abschnitt 4); Texturen erst mit dem Flaggschiff |
iPad quer misst 1194 px, breakpoints.desktop 1200 px | Teile, die an desktop hängen, zeigen auf dem Hauptgerät die Tabletform | Bruchstellen beim Umzug in den Kern neu schneiden; welche Schirme betroffen sind, ist nicht geprüft |
| Namensgleiche Bausteine | zwei Panel, Seitenkopf und Blatt schon vergeben | neue Namen (2.5), tote Widgets entfernen |
| Parallele Musterbögen | ihre Werte passen nicht zum Vertrag | Vertrag und Musterbögen benutzen die Gruppen aus 2.2 |
| Bausteine im Bereich | Einstellungsgruppe, pflegebausteine sind für andere Bereiche unerreichbar | ins Gerüst ziehen (Schritt 6) |
Die fünf Fragen aus Abschnitt 7 sind beantwortet: docs/kontext/entscheidungen/2026-10-15-stilpakete-bau.md. Christian entschied Frage 1 (kein Kontoschalter) und Frage 2 (Legacy bekommt die neue Anordnung); die Fragen 3 bis 5 laufen mit der Empfehlung weiter. Frage 1 ist für die vier Themes überholt: 2026-10-15-vier-themes öffnet die Nutzerschicht für klar, ruhig und marker (3.3); zurück auf legacy schaltet weiter nur der Admin.
7. Fragen an Christian (beantwortet am 15.10.2026)
- Darf ein Konto selbst auf das bisherige Aussehen zurückschalten? Empfehlung: nein. Der Admin schaltet für alle, eine Rolle trägt Probegruppe und Ausnahmen, Admins und Entwickler sehen je Gerät vor. Für die vier Themes überholt (2026-10-15-vier-themes): Ein Konto wählt
klar,ruhigodermarker; auf Legacy zurück schaltet weiter nur der Admin (3.3). - Bekommt Legacy die neue Anordnung mit (schmale Leiste, eine Suche, Kalender mit Stundenplan als Ebene, weniger Reiter)? Empfehlung: ja; Legacy bewahrt Farben, Werkstoffe, Schriften und Formen, nicht die Anordnung.
- Wie weit darf ein Stilpaket gestalten? Empfehlung: Werte, Rezepte je Baustein und Bühne (Grund, Texturen, Schriften, Himmelsauftritt, Eulenkostüm), nicht die Anordnung.
- Wann wird das neue Paket die Vorgabe für alle? Empfehlung: wenn alle Schirme auf Bausteinen stehen; bis dahin schaltet der Admin, erst für eine Probegruppe.
- Was geschieht danach mit Legacy? Empfehlung: Es bleibt wählbar, wird aber eingefroren; neue Bausteine bekommen dort nur das Grundrezept.
8. Erste Vorgänge
- Token-Schicht aus dem heutigen Theme — ohne sichtbare Änderung.
- Legacy-Paket auslagern, Paketlader vor dem ersten Bild.
- Admin-Schalter für das Stilpaket, mit Prüfpaket und
/ansehen --pakete. - Bausteine I: Knopf, Feld, Reiter, Segment, Schirmkopf.
- Prüfglieder
verify:bausteineundverify:stilpakete. - Bausteine II: Fläche, Zeile, Leerzustand, Einstellungsgruppe, Fenster und Unterblatt, Anordnung; tote Widgets entfernen.
Je Vorgang ein kurzer Branch (bash betrieb/bahn.sh claim <KENNUNG>), angelegt mit node betrieb/vorgang.mjs new 5-bereiche/gestaltung "<Titel>"; „Fertig, wenn“ steht im jeweiligen Vorgang.