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.
119 lines
5 KiB
CSS
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;
|
|
}
|