Files
orchestra/web/src/styles/ethos.tokens.css
T
kami 34f3c2888f Rebuild the operator console on the ethos shell
Nine screens against orchestra-ui-spec.md and the accepted mockups, on
the ethos design system: signal violet #8F7AE5, the routing fork motif,
the 64px rail and 56px top bar, mono for every machine value and sans
for every human one.

Each screen was built by its own agent against a fixed foundation, so
the shell, tokens and primitives have one author and the screens cannot
drift into nine dialects.

Real data only. Where no endpoint exists the screen says which one it
needs instead of inventing a value. That is most of what was learned
here: Steer / Correct is disabled because nothing records a human
decision from the web, take-control is disabled because nothing
forwards keystrokes to a pane, context occupancy is missing from three
screens, and projects can show no repo, remote, quality gate or
verification policy because those live only in config.jsonc.

Three bugs the render caught that no computed value would have:

The previous stylesheet fought every shared class name and leaked
properties the new rules never mention, which is how position:fixed
survived on .topbar. It is now scoped under .legacy and applies only to
the login route, which also stops its green accent and its
backdrop-filter from reaching the console.

Go marshals a zero time.Time as "0001-01-01T00:00:00Z" and omitempty
does not omit a struct, so absent timestamps arrived populated-looking
and rendered as "739855d ago". Stripped once at the API boundary every
screen reads through, with a test.

Long machine ids overflowed their cards and painted under the next one.

Verified by rendering: chromium screenshots of the dashboard, tasks,
task detail, terminal, workers and review at 1440px, and the dashboard
at 390px. Geist is still not on disk, so both stacks fall back to the
system faces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVbaKucEYBjMqVeUgJUsc1
2026-08-29 02:44:43 +04:00

137 lines
5.5 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ═══════════════════════════════════════════════════════════════
ETHOS — tokens
Shared design language for the kvmx.ru apps.
The neutral system (ramp, type, motion, radii, shadow) is shared by
every app and does not change. The only per-app difference is the
accent (one hue) and the motif (one geometric signature).
NEW APP: do not invent the accent silently. Ask the operator for the
accent name + hex and the motif, then add one [data-app] block at the
bottom using the TEMPLATE. Fonts are self-hosted (subset + woff2,
immutable caching) — no font CDN.
═══════════════════════════════════════════════════════════════ */
@font-face {
font-family: 'Geist';
src: url('/fonts/Geist-Variable.woff2') format('woff2');
font-weight: 100 900; font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('/fonts/GeistMono-Variable.woff2') format('woff2');
font-weight: 100 900; font-display: swap;
}
:root {
/* ── neutral ramp — warm, brown-tinted (dark, default) ── */
--bg-0: #14110D; /* deepest room */
--bg-1: #1B1712; /* surface */
--bg-2: #221D17; /* raised */
--bg-3: #2C261D; /* hover / raised */
--bg-4: #372F24; /* pressed / high */
--line: rgba(244, 234, 220, 0.09); /* hairline */
--line-hi: rgba(244, 234, 220, 0.16); /* hairline emphasized */
--text-hi: #F4EEE4; /* human primary (sans) */
--text-mid: #B4AA98; /* human secondary (sans) */
--text-lo: #756C5C; /* human tertiary / idle */
--text-machine: #9C917D; /* machine default (mono) */
/* ── type ── */
--sans: 'Geist', -apple-system, system-ui, sans-serif;
--mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;
/* mono numerics: apply on any element using --mono */
/* font-feature-settings: "tnum" 1, "zero" 1; letter-spacing: -0.01em; */
/* ── motion — mechanical, no bounce ── */
--ease: cubic-bezier(0.2, 0, 0, 1);
--fast: 130ms;
--med: 170ms;
/* ── radii ── */
--r-sm: 8px;
--r-md: 12px;
--r-lg: 18px;
--r-xl: 24px;
/* ── elevation: depth from light, never blur ── */
--shadow-soft: 0 2px 8px rgba(0,0,0,0.35), 0 12px 32px rgba(0,0,0,0.28);
--shadow-lift: 0 4px 14px rgba(0,0,0,0.40), 0 20px 48px rgba(0,0,0,0.34);
/* ── accent slot ──
Neutral fallback so an app with no [data-app] is never unstyled.
Real values come from the per-app block below. Accent is a SIGNAL
(active state, focus ring, primary action, one lit detail) — never a
fill-everything wash. */
--accent: var(--text-mid);
--accent-hi: var(--text-hi);
--accent-dim: rgba(244, 234, 220, 0.10);
--accent-line: rgba(244, 234, 220, 0.24);
--accent-glow: rgba(244, 234, 220, 0.14);
}
/* ── light theme — warm, off-white (kept off cream to dodge the AI-cream tell) ── */
[data-theme="light"] {
--bg-0: #F1ECE3;
--bg-1: #EAE4D8;
--bg-2: #E2DACB;
--bg-3: #D7CDBB;
--bg-4: #C9BDA7;
--line: rgba(28, 22, 14, 0.10);
--line-hi: rgba(28, 22, 14, 0.18);
--text-hi: #1B1712;
--text-mid: #544C3E;
--text-lo: #877E6C;
--text-machine: #6B6252;
--shadow-soft: 0 2px 8px rgba(60,45,25,0.10), 0 12px 32px rgba(60,45,25,0.08);
--shadow-lift: 0 4px 14px rgba(60,45,25,0.12), 0 20px 48px rgba(60,45,25,0.10);
}
/* ═══════════════════════════════════════════════════════════════
PER-APP OVERRIDES — one small block each. Accent + optional motif
hooks only; never touch the neutral ramp.
═══════════════════════════════════════════════════════════════ */
/* muzick — reference app · honey amber · waveform */
[data-app="muzick"] {
--accent: #EDA24E;
--accent-hi: #F5B667;
--accent-dim: rgba(237, 162, 78, 0.14);
--accent-line: rgba(237, 162, 78, 0.32);
--accent-glow: rgba(237, 162, 78, 0.22);
/* motif hook: cool content-art gradient so art carries color, amber stays signal */
--np-art: radial-gradient(120% 120% at 22% 14%, #7FB3BC 0%, #2F6E7A 42%, #1C4552 78%, #14262E 100%);
}
/* ── TEMPLATE — copy for a new app AFTER intake with the operator ──
[data-app="APPNAME"] {
--accent: #RRGGBB; // the operator's chosen hue
--accent-hi: #RRGGBB; // ~ +1014% lightness
--accent-dim: rgba(R, G, B, 0.14); // active-state backgrounds
--accent-line: rgba(R, G, B, 0.32); // accent hairlines
--accent-glow: rgba(R, G, B, 0.22); // restrained ambient pool
// optional motif hooks (gradients / seeds) go here, app-specific
}
*/
/* orchestra — signal violet · routing fork
Accent and motif come from orchestra-ui-spec.md, chosen by the operator. */
[data-app="orchestra"] {
--accent: #8F7AE5;
--accent-hi: #A291EC;
--accent-dim: rgba(143, 122, 229, 0.14);
--accent-line: rgba(143, 122, 229, 0.32);
--accent-glow: rgba(143, 122, 229, 0.22);
/* motif hook: the routing fork, one path splitting and rejoining. Used by
the app mark, phase transitions and empty states. */
--fork-line: rgba(143, 122, 229, 0.55);
}