Kestrel Neon theme family, a shared theme-effects layer, and the Core Assembly CoS avatar - #6250
Merged
Merged
Conversation
…no WebGL dependency The Kestrel Neon concept's telemetry widget becomes an avatar style (`core`). Geometry and the frame renderer are pure (client/src/lib/wireframeCore.js) so the projection math is pinned without a canvas; the component drives them with requestAnimationFrame. Edges take the agent-state color so all seven states stay distinguishable, rings and vertices follow the theme's --port-accent-2 and re-resolve on theme switch, speaking bursts spin and glow, drag rotates, and prefers-reduced-motion holds one static frame. It skips CoSCanvasGuard because it needs no WebGL, so it also works where the three.js avatars fall back to the failure panel.
Kestrel Neon (night) and Kestrel Dawn (day) bring the CRT boot-terminal concept: cyan and magenta on a scanlined void, a perspective grid floor, IBM Plex Mono throughout, uppercase glitching titles at night. Full-screen effects are now theme features instead of per-theme CSS: a theme lists them in its manifest (scanlines, vignette, sweep, grid-floor, glitch — registry THEME_EFFECTS), useTheme publishes the list as data-port-theme-effects on <html>, and index.css keys one block per effect on that attribute, parameterized by --port-fx-* tokens. Black ICE Terminal's scanlines (both modes) move onto the shared layer with identical values. theme:check fails on an unknown effect or a registered effect with no block. Fixes a latent applyTheme defect: it only ever set custom properties, so a token one theme declares and the next does not stayed inline on <html> after a switch. It now removes the stale ones (pinned in useTheme.test.jsx).
…ecomes tokens Review follow-ups on the Kestrel/effects work: - The effects layer no longer borrows body::after and #root::before. main.jsx renders <div class="port-fx-layer"> and the grid floor (::before), the static scanline+vignette overlay (::after), and the sweep band (.port-fx-sweep child) all live there, so a theme's own body pseudo-element rules (Lumen Glass Day's drift) can never collide with the shared layer. - The sweep and the grid floor animate transform only, so they stay on the compositor instead of repainting a blended full-screen layer every frame. - Heading treatment is four tokens (--port-heading-tracking, --port-heading-glow, --port-title-tracking, --port-title-transform) read by the shared h1-h3 rule; the glitch effect rests on --port-heading-glow so listing it never dictates a theme's title look. Kestrel's per-id CSS collapses to a family block. - theme:check rejects a --port-fx-* token declared for an effect the theme does not list; themes declare only the tokens where they diverge from :root. - applyTheme clears stale --port-* properties by walking the inline style rather than remembering what it wrote. - The Core Assembly avatar sizes through useCanvasDprSize (now following the container height), resolves theme tokens through useCanvasRollPalette (now taking the resolver), parses triples with chipContrast's parseTriple, and reads reduced motion from a new usePrefersReducedMotion hook that BrainGraph adopts too. Edge colors are parsed once at import, not per frame.
…ICE headings keep their glow useCanvasDprSize resizes on mount before the avatar's own effect installs drawRef, so a real (non-zero) layout hit `drawRef.current is not a function`. The hook now tolerates a not-yet-installed draw (the rAF loop paints a tick later), and a test with a sized layout pins it. The shared heading rule sets text-shadow explicitly, which dropped the glow Black ICE headings inherited from body — both Black ICE manifests restate it in --port-heading-glow.
… reduced motion With prefers-reduced-motion the rAF loop stops after one frame, so a new agent state never reached the canvas. An effect now requests the single frame explicitly; the reduced-motion test pins it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
kestrel: Kestrel Neon (night) and Kestrel Dawn (day), from a CRT boot-terminal concept — cyan/magenta on a scanlined void, a perspective grid floor, IBM Plex Mono throughout, uppercase tracked titles that glitch at night. Palettes graded by the existing contrast contract; docs indocs/themes/kestrel-neon.md.effects(scanlines,vignette,sweep,grid-floor,glitch— registryTHEME_EFFECTS),useThemepublishes them asdata-port-theme-effects, and one shared block per effect paints on a dedicated.port-fx-layerelement rendered bymain.jsx, tuned by--port-fx-*tokens. Sweep and floor animatetransformonly (compositor, no full-screen repaint). Black ICE's scanlines moved onto the layer with identical values.--port-heading-tracking,--port-heading-glow,--port-title-tracking,--port-title-transform) read by the shared h1–h3 rule.applyThemedefect: inline--port-*properties from the previous theme leaked into the next when a theme declared an optional token. It now clears undeclared ones from the DOM.core(Core Assembly): the concept's rotating wireframe icosahedron on a plain 2D canvas (no WebGL). Edges follow the agent-state color, rings follow--port-accent-2, drag rotates, reduced motion holds one frame. Pure geometry/renderer inclient/src/lib/wireframeCore.js.useCanvasRollPalettetakes a resolver,useCanvasDprSizecan follow the container height, newusePrefersReducedMotion(BrainGraph adopts it).Test plan
npm run theme:check(now also rejects a--port-fx-*token for an unlisted effect)portosThemes,chipContrast,useTheme,wireframeCore,CoreCoSAvatar,ConfigTab,ChiefOfStaff, piano-roll, BrainGraph, barrel suites; full client and server suites (only known load flakes, all green in isolation)cosStatusRoutesAvatarschema test acceptscorecd client && npm run build