# UI Theme (layout / tokens / components) Second normalized component. **Goal: path to shared code** — converge the three sister projects onto a common "Technical-Light" design system, realized as the `ZB.MOM.WW.Theme` Razor Class Library. - The one target: [`spec/SPEC.md`](spec/SPEC.md) - Design tokens reference: [`spec/DESIGN-TOKENS.md`](spec/DESIGN-TOKENS.md) - The shared library: [`shared-contract/ZB.MOM.WW.Theme.md`](shared-contract/ZB.MOM.WW.Theme.md) - Divergences + backlog: [`GAPS.md`](GAPS.md) - Current state, per project: [`current-state/`](current-state/) ## Why UI theme is a strong candidate All three sister apps share a Blazor SSR + Bootstrap 5 UI stack and each ships a hand-copied **379-line `theme.css`** (the "Technical-Light" design system: IBM Plex `@font-face`, `:root` design tokens, status palette, typography helpers). **The three copies are byte-for-byte identical except for three lines** — the `@font-face` `src:` URL prefix differs per app deployment convention. IBM Plex `.woff2` fonts are likewise vendored three times into each app's `wwwroot/fonts/`. This is the textbook drift situation: a shared design system already beginning to diverge, with a latent font-path bug in one app (OtOpcUa) that goes unnoticed because browsers fall back to system fonts. ## Status by project | Project | Surface | Layout today | Adoption status | |---|---|---|---| | **OtOpcUa** | `ZB.MOM.WW.OtOpcUa.AdminUI` | Side rail (`NavSidebar.razor`) + `theme.css` + IBM Plex | Not started | | **MxAccessGateway** | `ZB.MOM.WW.MxGateway.Server` Dashboard | Sidebar (`nav.sidebar`) + `theme.css` + IBM Plex | Not started | | **ScadaBridge** | `ZB.MOM.WW.ScadaBridge.Host` + `.CentralUI` (RCL) | Own `MainLayout` + `NavMenu` (`nav.sidebar`) + `theme.css` + IBM Plex | Not started | See each project's [`current-state//CURRENT-STATE.md`](current-state/) for the code-verified detail and its adoption plan. ## Normalized vs. left per-project **Normalized (extracted into the RCL `ZB.MOM.WW.Theme`):** design tokens + IBM Plex fonts, the canonical side-rail shell (`ThemeShell` + `BrandBar` + `NavRailItem` + `NavRailSection`), and the four widgets (`StatusPill`, `LoginCard`, `TechButton`, `TechCard`, `TechField`). One RCL, one package, one version. **Left per-project (NOT extracted):** each app's `site.css` residual page layout, its page/route content, and app-specific scoped `.razor.css` (e.g. ScadaBridge's `MultiSelectDropdown`, `TreeView`, `Audit/*`). The kit owns the *chrome and tokens*, not the app's domain screens.