The project shipped a black-and-white theme that was only half converted: the login page looked right, the message page was halfway, and the settings page had not been started. This finishes the move to the CYBER reference in prototype_reference/. Colors now come from a single token source (styles/variables.scss), where every semantic color is declared twice: once as OKLCH for the CSS, and once as an RGB triple so translucent variants can be built as rgba(var(--*-rgb), alpha). Cyan is the system itself, amber means the user has to intervene, green means the machine is working, and red only ever means something broke. The RGB triples are derived from the OKLCH values so the two declarations cannot drift apart. Pages adopt the .cy-* shell classes from the reference (view, panel, kpis, tabs, grid, table, field) instead of ad-hoc markup, which is what makes 19 of 26 views consistent. The remaining seven are deliberately bespoke: chat streams, the kanban board, the workflow canvas, the terminal, and the missing-agent screen. The chart palette and the kanban column colors move into single-source modules so they cannot drift either. A new guard test rejects raw hex colors, named colors, and literal RGB triples anywhere in the client source, with an explicit exemption list for the places that genuinely cannot read a CSS variable. The existing chat semantics spec keeps the chat chain honest. No behavior changes: no logic, no i18n keys, no data structures, and the /chat-run event contract is untouched.
4.2 KiB
date, pr, feature, impact
| date | pr | feature | impact |
|---|---|---|---|
| 2026-10-19 | pending | Chat view CYBER pass — single-colour live ring, send-key neon tube, status LED, responsive outline | The chat chain's "machine is working" indicator is now a single lime pulse instead of a six-colour cycle, the send key renders as a neon tube with the standard sweep instead of a flat grey block, the header carries a connection LED and a cyan press-light, and the Outline panel becomes an overlay at ≤1180px. Rendering-layer only — no store logic, no `/chat-run` payload, no markup semantics beyond one decorative status span, no event wiring changed. |
Chat view CYBER pass
Follow-up to 2026-10-19-three-colour-semantics.md. That change split the
palette by meaning but left several call sites hardcoded, and the chat view was
still missing the page-level treatment the rest of the app had.
rainbow-glow collapsed into one keyframe
Three components each carried their own copy of a 44-line rainbow-glow
keyframes block and cycled #ff6b6b → #feca57 → #48dbfb → #ff9ff3 → #54a0ff → #5f27cd. Four semantic hues flashing in one animation means the indicator
carries no meaning at all — which is exactly what the three-colour rule exists
to prevent.
live-ring is now defined once in global.scss and pulses --success
(lime) between a dim and a bright ring. All three call sites use it:
MessageItem.vue—.speech-playingon the message bubbleSessionListItem.vue—.streamingring on the agent logoGroupMessageItem.vue—.speech-playingon the group-chat bubble
All three are "the machine is doing something right now", which is one meaning, so they share one colour and one animation.
Send key
ChatInput.vue had border: 0 !important and box-shadow: none !important
on .send-button, which erased the neon tube that global.scss gives every
.arco-btn-primary. The disabled state was also a solid #9f9f9f block —
a hardcoded grey outside the palette. Both are gone; the button now inherits
the global tube + neon-sheen sweep and uses the standard dimmed-tube disabled
treatment.
Added .send-button--stop: while a run is streaming, the same button becomes
the stop control, which is a "needs you" action rather than a "system" action,
so it turns amber — the same semantic the approval card uses.
Status LED
New .cy-led in global.scss: a 7px dot, lime with a glow and a slow
breathe when connected, red and static when not. A dead connection should not
look like it is still doing work, so the breathe animation only runs in the
connected state. Bound to appStore.connected in the chat header, reusing the
existing sidebar.connected / sidebar.disconnected strings.
Session list current item
.session-item.active already had the soft cyan fill; the prototype's defining
feature is the 2px glowing left bar. Added via inset box-shadow rather than
border-left, which would have shifted the row's content by 2px.
Header press-light
.chat-header gets a radial-gradient cyan wash from the top edge. Radial,
not linear — a linear gradient lights the whole strip evenly and loses the
"pressed from above" quality.
Responsive
Verified the real implementation had only the 768px tier. Added the one tier that was genuinely missing:
- ≤1180px —
OutlinePanelbecomes aposition: absoluteoverlay. Below this width the message stream, Outline and tool panel cannot coexist as three columns; the header's Outline button already toggles it, so no extra close control is needed. Below 768px it keeps its existing narrower width. - ≤900px — the workspace badge hides. The session sidebar deliberately does not hide at this width: it is controlled by the header toggle, and removing the column would leave no way to open it.
Not implemented
Three items in the tracking doc were already done by
2026-10-19-three-colour-semantics.md and are recorded there, not repeated
here: bubble role colours (cyan right edge on user, lime left edge on
assistant), the approval card's amber zone, and the three-segment context meter.
Verification
npm run harness:check, npm run test and npm run build pass. The LED,
the send key's enabled/disabled/stop states, the active session row, and both
new breakpoints were checked in a browser.