A lockup slot on a page or panel drew its title in the light
--design-primary with a --design-on-primary outline in both color schemes.
With an orange base that is about 3:1 on the light surface, and the SVG
never changed in dark mode; the Sphinx, Jenkins and Jellyfin passes
reported it.
sys-front-inj-design now passes --design-link with a --design-surface-1
outline for light and their dark values for dark. render_assets() hands
the dark pair to every slot without frame: true, and render_svg() adds a
style rule under prefers-color-scheme: dark that overrides the fill and
stroke attributes. Slots on brand chrome keep the frame colors, and the PNG
keeps the light pair. The design_assets action requires the two new
arguments; its two callers, assets.yml and Keycloak's theme task, pass
them.
A unit test asserts the dark rule on page slots and its absence on frame
and logo-only slots; it fails when the dark pair is not handed on. In
headless Chromium an <img> of the SVG renders the title #825200 on #fff5ea
in light and #ffa500 on #140e07 in dark.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A generated lockup drew its title in the primary color with an
on-primary outline. On a header or sidebar that a role maps onto the
frame token, that put primary-colored text on a primary-toned ground.
A slot now takes `frame: true` in the role's design entry. The asset
action receives a second color pair from the palette, the on-frame
color as fill and the frame color as outline, and the renderer picks
the pair per slot. Slots without the flag render as before.
Keycloak calls the asset action directly and already rendered its
brand slot in the on-frame color, so it passes that color for both
pairs and keeps its output.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
web-svc-css becomes web-svc-design and owns the configuration that lived in group_vars/all/13_design.yml. Consumers switch their css service key to design, and sys-front-inj-css becomes sys-front-inj-design. javascript stays an independent key; a role's optional design.js.j2 is injected together with the design and CSP-hashed like the functional script.
An in-repo OKLCH lookup replaces colorscheme_generator. From design.colors.base alone it derives surfaces, text, borders, the primary and status fills with their on-colors, hover and active states and a dedicated dark palette; a unit test proves WCAG AA, and AAA for body text, across six base colors in both modes. Semantic --design-* tokens replace --color-NN-SS in every role stylesheet. The shared element styles sit in the cascade layer infinito-design, so an app's own design system always wins and takes the palette through a variable mapping in its role stylesheet or through its own theming mechanism.
design.logo and design.title resolve globally from web-svc-design or per role from its design entry, and false or 0 disables the replacement. The design_assets action renders the logo lockup per slot as SVG, PNG and ICO, and the legacy title keys move into the design entries.
Three roles carry the design end to end. The dashboard takes logo, favicon and title from the generator and replaces the hard-coded port-ui colors. Gitea maps its theme variables onto the tokens and mounts the generated logo and a branded start page. Nextcloud receives primary color, logo, name and slogan through occ theming and ships no stylesheet.
make design-sync re-renders the static design files of a deployed app, make design-gallery captures before and after screenshots in light, dark, desktop and mobile, and make design-queue orders the roles that are due for a design pass. The i8-designer skill and docs/agents/action/design.md describe that loop.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>