On a failed fetch the store keeps the last real payload (stale > fake) and flags `disconnected` instead of falling back to bundled demo carts — an operator must never book a reject against a fabricated entry. Sample data and sample reason codes are gated behind import.meta.env.DEV, so `vite build` tree-shakes them out entirely (verified: no sample strings in dist). - cold start / no data: centered reconnect spinner that keeps retrying - data present + drop: stale carts stay, header shows amber "reconnecting" - reasons no longer seed sample codes in production - polling retries faster (5s) while disconnected, recovers automatically Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
144 lines
3.5 KiB
CSS
144 lines
3.5 KiB
CSS
@import 'tailwindcss';
|
|
|
|
/* Class-based dark mode (index.html sets <html class="dark">). */
|
|
@variant dark (&:where(.dark, .dark *));
|
|
|
|
@theme {
|
|
--breakpoint-hmi-sm: 800px;
|
|
--breakpoint-hmi-md: 1024px;
|
|
--breakpoint-hmi-lg: 1280px;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
BOARD TOKENS
|
|
Neutral surfaces = the temper board palette (shared with the overview SPA).
|
|
FLOW ACCENTS match PressV's --c-* process colours + the reject colour so the
|
|
5-station belt reads the same across the fleet:
|
|
nicht gesendet=violet · Wagen=cyan · Unterwegs=amber · Ofen=orange ·
|
|
Fertig=emerald · Ausschuss=dark-red (Grafana "Ausschuss" #C4162A).
|
|
Fonts come from @sp-ui-kit/tokens (Inter Variable + mono).
|
|
========================================================================== */
|
|
:root {
|
|
--ground: #11151b;
|
|
--panel: #1a212a;
|
|
--panel-2: #222b36;
|
|
--panel-3: #2a3542;
|
|
--line: #2c3641;
|
|
--line-2: #3a4654;
|
|
|
|
--ink: #e8edf2;
|
|
--ink-dim: #97a3b1;
|
|
--ink-faint: #7f8b9a;
|
|
|
|
--press: #a78bfa; /* violet — Nicht gesendet */
|
|
--way: #22d3ee; /* cyan — Wagen */
|
|
--transit: #fbbf24; /* amber — Unterwegs */
|
|
--oven: #f97316; /* orange — Ofen */
|
|
--hot: #ef4444; /* red — Ofen (peak) */
|
|
--done: #34d399; /* emerald — Fertig */
|
|
--ausschuss: #983048; /* burgundy — Ausschuss */
|
|
|
|
--o1: #5794f2;
|
|
--o2: #e8825a;
|
|
--o3: #b57edc;
|
|
--o4: #4fb7a8;
|
|
|
|
--r: 2px;
|
|
--sans: var(--font-family-sans, 'Inter Variable', ui-sans-serif, system-ui, sans-serif);
|
|
--mono: var(--font-family-mono, ui-monospace, 'Cascadia Mono', 'SFMono-Regular', Menlo, Consolas, monospace);
|
|
}
|
|
|
|
/* Light theme (no .dark): cool slate surfaces + darker, still-legible accents. */
|
|
html:not(.dark) {
|
|
--ground: #f1f5f9;
|
|
--panel: #e2e8f0;
|
|
--panel-2: #cbd5e1;
|
|
--panel-3: #94a3b8;
|
|
--line: #cbd5e1;
|
|
--line-2: #94a3b8;
|
|
|
|
--ink: #0f172a;
|
|
--ink-dim: #475569;
|
|
--ink-faint: #4b586b;
|
|
|
|
--press: #6d28d9;
|
|
--way: #0e7490;
|
|
--transit: #b45309;
|
|
--oven: #c2410c;
|
|
--hot: #dc2626;
|
|
--done: #15803d;
|
|
--ausschuss: #86243c;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
html {
|
|
-webkit-text-size-adjust: 100%;
|
|
font-size: clamp(13px, 1.6vw, 16px);
|
|
font-family: var(--sans);
|
|
}
|
|
body {
|
|
margin: 0;
|
|
color: var(--ink);
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
background:
|
|
radial-gradient(1300px 700px at 72% -12%, #182230 0%, transparent 58%),
|
|
var(--ground);
|
|
}
|
|
html:not(.dark) body {
|
|
background:
|
|
radial-gradient(1300px 700px at 72% -12%, #e2e8f0 0%, transparent 58%),
|
|
var(--ground);
|
|
}
|
|
|
|
.num {
|
|
font-family: var(--mono);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* ── Global keyframes ─────────────────────────────────────────────────────── */
|
|
@keyframes blink {
|
|
0%,
|
|
100% {
|
|
opacity: 0.35;
|
|
}
|
|
50% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
/* horizontal conveyor for the 5-station belt (style C) */
|
|
@keyframes flowright {
|
|
to {
|
|
background-position: 11px 0;
|
|
}
|
|
}
|
|
@keyframes spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* Reconnect spinner (connection-loss states). `.sm` is the inline header variant. */
|
|
.spinner {
|
|
display: inline-block;
|
|
width: 30px;
|
|
height: 30px;
|
|
border: 3px solid var(--line-2);
|
|
border-top-color: var(--transit);
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
}
|
|
.spinner.sm {
|
|
width: 13px;
|
|
height: 13px;
|
|
border-width: 2px;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
* {
|
|
animation: none !important;
|
|
}
|
|
}
|