Blueforce-Linux/web/static/tokens.css
emirhanmamak-blueforce 4ad20452e7 feat(design): add the operator design system the two surfaces share
The device console is a default-grey tkinter window with no hierarchy: no
grouping, no state colour, no type scale, the privilege warning buried in a
monospace paragraph, "Çık" duplicated at two sizes, and an output area that
looks editable. Every measurement is in the delivered work; the point here is
that the fix is a system, not a repaint.

Adds PRODUCT.md (product truth: who uses this, from where, under what
constraints), docs/DESIGN.md (the direction contract and the shared status
vocabulary) and web/static/tokens.css (the values both surfaces read).

The vocabulary is the load-bearing part. Four severities -- ok / warn / danger /
info -- plus one action accent, and one Turkish word per device stage
(KURULDU / KAYITLI / HAZIR / HATA / YOK) used identically on the device and in
the central panel. A fifth hue is a bug, and colour is never the only carrier:
every badge ships its word, so the fleet list stays readable in greyscale.

The ground is light on purpose. The console runs in workshops and dealer service
areas in daylight; a near-black ops console loses its own body text there and its
state colours collapse into equal-brightness smudges.

No webfont: the fleet installs offline from a committed pool, so a font CDN is a
broken page on every device.
2026-09-16 22:20:15 +03:00

119 lines
5 KiB
CSS

/*
* Blueforce Field OS — design tokens
* ---------------------------------------------------------------------------
* One source for both operator surfaces:
* - the device console (Python/tkinter, bfos/ui_theme.py reads these values)
* - the central panel (stdlib http.server, web/templates/*)
*
* The surfaces share a status vocabulary because they describe the same fleet
* from two ends. A colour here means one thing everywhere: a device state, a
* severity, or an action weight. It never decorates.
*
* WHY LIGHT, NOT DARK
* The console is used in workshops, dealer service areas and customer sites --
* bright overhead light, daylight from a roller door, a 14" laptop panel. A
* near-black console loses its own body text there and its state colours
* collapse into equal-brightness smudges. So the ground is light, the text is
* dark, and saturation is spent only where it carries meaning: state.
*
* WHAT THE COLOURS HAVE TO CARRY
* The catalogue is 48 operations, 13 of which write. The state machine has
* three stages and a device can also be failed or absent. That is four
* severities plus one action colour, and no more -- a fifth hue would make the
* distinction something an operator has to read instead of see.
*/
:root {
/* -- Ground and structure -------------------------------------------- */
--bg-app: #f6f7f8; /* window ground */
--bg-panel: #ffffff; /* raised surfaces, cards, table body */
--bg-sunken: #eef0f2; /* wells: log output, code, inactive rows */
--bg-header: #1d2530; /* app header; the one dark region */
--border: #d5d9de; /* hairline between regions */
--border-strong: #b6bcc4; /* input borders, table rules */
/* -- Text ------------------------------------------------------------- */
--text: #1a1f26; /* body */
--text-muted: #5c6570; /* secondary lines, labels */
--text-faint: #8b939c; /* timestamps, hints, placeholders */
--text-on-dark: #e8ebee; /* header text */
--text-on-accent: #ffffff;
/* -- Action ----------------------------------------------------------- */
/* One accent. It marks the action the operator came to take and the
selection in a list; nothing else. */
--accent: #1d4ed8;
--accent-hover: #1a43bd;
--accent-active: #16389e;
--accent-soft: #e8eeff; /* selected row, focus ring fill */
--focus-ring: #1d4ed8;
/* -- State: the fleet vocabulary -------------------------------------- */
/* Four severities. Each has a strong form for text and a soft form for
fills, so a badge can be built from either without a second palette. */
--ok: #15803d;
--ok-soft: #e6f4ea;
--warn: #b45309;
--warn-soft: #fdf3e3;
--danger: #b91c1c;
--danger-soft: #fdecec;
--info: #1d4ed8;
--info-soft: #e8eeff;
--idle: #5c6570; /* not yet acted on: not a failure */
--idle-soft: #eef0f2;
/* -- Device state machine --------------------------------------------- */
/* PROVISIONED_OFFLINE -> ENROLLED -> READY, and the failure/absence that
sit outside the sequence. Kept as named tokens so no surface invents a
fifth stage or repaints a stage by accident. */
--state-provisioned: var(--info);
--state-enrolled: var(--warn);
--state-ready: var(--ok);
--state-failed: var(--danger);
--state-absent: var(--idle);
/* -- Type ------------------------------------------------------------- */
/* Workhorse faces only: this is an Operate surface, and the value of a
webfont here is negative -- the fleet installs offline from a committed
pool, so a font CDN is a broken page on every device. The UI face is
whatever the platform ships; the data face is monospace so device ids,
counts and exit codes line up in a column. */
--font-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans",
"DejaVu Sans", sans-serif;
--font-data: ui-monospace, "Cascadia Mono", "JetBrains Mono", Menlo,
Consolas, "DejaVu Sans Mono", monospace;
--size-xs: 12px; /* timestamps, table meta */
--size-sm: 13px; /* labels, table body */
--size-md: 15px; /* body, inputs, buttons */
--size-lg: 18px; /* card titles */
--size-xl: 22px; /* view titles */
--size-2xl: 30px; /* the one headline figure per view */
--leading-tight: 1.25;
--leading-normal: 1.5;
/* -- Space ------------------------------------------------------------ */
/* A 4px rhythm. Named, so a component never hand-picks 7px. */
--sp-1: 4px;
--sp-2: 8px;
--sp-3: 12px;
--sp-4: 16px;
--sp-5: 24px;
--sp-6: 32px;
--sp-7: 48px;
--radius: 6px;
--radius-lg: 10px;
/* -- Elevation -------------------------------------------------------- */
/* Two levels. More would separate regions that are not separate. */
--shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);
--shadow-md: 0 4px 12px rgba(16, 24, 40, .10);
/* -- Metrics ---------------------------------------------------------- */
--row-h: 44px; /* fleet table row: comfortable at arm's length */
--control-h: 36px; /* buttons and inputs share one height */
--header-h: 56px;
--sidebar-w: 220px;
}