710 lines
32 KiB
HTML
710 lines
32 KiB
HTML
|
|
<!doctype html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="utf-8" />
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
|
|
<title>System Status — T-Systems Regulation Hub</title>
|
||
|
|
<style>
|
||
|
|
/* ─── Design tokens ─────────────────────────────────────────────── */
|
||
|
|
:root {
|
||
|
|
/* Sidebar (light rail) */
|
||
|
|
--rail-bg: #ffffff;
|
||
|
|
--rail-surface: #f7f8fa;
|
||
|
|
--rail-fg: #111827;
|
||
|
|
--rail-muted: #8b929e;
|
||
|
|
--rail-border: #e8eaed;
|
||
|
|
--rail-hover: rgba(0,0,0,.04);
|
||
|
|
--rail-active: rgba(226,0,116,.07);
|
||
|
|
|
||
|
|
/* Canvas (content area) */
|
||
|
|
--bg: #f2f4f7;
|
||
|
|
--surface: #ffffff;
|
||
|
|
--fg: #111827;
|
||
|
|
--muted: #6b7280;
|
||
|
|
--border: #e5e7eb;
|
||
|
|
|
||
|
|
/* Brand */
|
||
|
|
--accent: #e20074;
|
||
|
|
--accent-dim: rgba(226,0,116,.10);
|
||
|
|
--accent-hover: #c8006a;
|
||
|
|
--success: #16a34a;
|
||
|
|
--warn: #d97706;
|
||
|
|
--danger: #dc2626;
|
||
|
|
|
||
|
|
/* Type */
|
||
|
|
--font-display: "TeleNeoWeb-Bold","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
|
||
|
|
--font-body: "TeleNeoWeb-Regular","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
|
||
|
|
--font-mono: ui-monospace,"JetBrains Mono",Menlo,monospace;
|
||
|
|
|
||
|
|
--radius-sm: 6px;
|
||
|
|
--radius-md: 10px;
|
||
|
|
--radius-pill: 9999px;
|
||
|
|
--sidebar-w: 232px;
|
||
|
|
--shadow-card: 0 1px 4px rgba(0,0,0,.06), 0 0 0 1px rgba(0,0,0,.04);
|
||
|
|
--shadow-sm: 0 1px 2px rgba(0,0,0,.05);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ─── Reset ────────────────────────────────────────────────────── */
|
||
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; }
|
||
|
|
html, body { height: 100%; }
|
||
|
|
body {
|
||
|
|
background: var(--bg);
|
||
|
|
color: var(--fg);
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: 14px;
|
||
|
|
line-height: 1.6;
|
||
|
|
-webkit-font-smoothing: antialiased;
|
||
|
|
}
|
||
|
|
h1,h2,h3,h4 { font-family: var(--font-display); line-height: 1.2; letter-spacing: -0.015em; text-wrap: balance; }
|
||
|
|
a { color: inherit; text-decoration: none; }
|
||
|
|
button, input, select { font: inherit; cursor: pointer; }
|
||
|
|
|
||
|
|
/* ─── App shell ─────────────────────────────────────────────────── */
|
||
|
|
.app-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }
|
||
|
|
|
||
|
|
/* ─── Sidebar ───────────────────────────────────────────────────── */
|
||
|
|
.sidebar {
|
||
|
|
position: sticky; top: 0; height: 100vh;
|
||
|
|
overflow-y: auto; overflow-x: hidden;
|
||
|
|
display: flex; flex-direction: column;
|
||
|
|
background: var(--rail-bg);
|
||
|
|
border-right: 1px solid var(--rail-border);
|
||
|
|
z-index: 20;
|
||
|
|
}
|
||
|
|
.sidebar-brand {
|
||
|
|
display: flex; align-items: center; gap: 10px;
|
||
|
|
height: 54px; padding: 0 16px;
|
||
|
|
border-bottom: 1px solid var(--rail-border);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.brand-logo {
|
||
|
|
width: 28px; height: 28px;
|
||
|
|
background: var(--accent);
|
||
|
|
border-radius: 7px;
|
||
|
|
display: flex; align-items: center; justify-content: center;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.brand-logo svg { color: #fff; }
|
||
|
|
.brand-name { font-family: var(--font-display); font-size: 13px; color: var(--rail-fg); line-height: 1.2; font-weight: 700; }
|
||
|
|
.brand-sub { font-size: 10px; color: var(--rail-muted); font-family: var(--font-mono); letter-spacing: .04em; margin-top: 2px; }
|
||
|
|
|
||
|
|
.sidebar-nav { flex: 1; padding: 10px 0; }
|
||
|
|
.nav-group { padding: 0 8px 4px; }
|
||
|
|
.nav-group + .nav-group { margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--rail-border); }
|
||
|
|
.nav-group-label {
|
||
|
|
display: block;
|
||
|
|
font-family: var(--font-mono); font-size: 10px;
|
||
|
|
text-transform: uppercase; letter-spacing: .12em;
|
||
|
|
color: var(--rail-muted);
|
||
|
|
padding: 0 8px 6px;
|
||
|
|
}
|
||
|
|
.nav-item {
|
||
|
|
display: flex; align-items: center; gap: 9px;
|
||
|
|
height: 34px; padding: 0 8px;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
color: #4b5563;
|
||
|
|
font-size: 13px;
|
||
|
|
transition: background 120ms, color 120ms;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
.nav-item:hover { background: var(--rail-hover); color: var(--rail-fg); text-decoration: none; }
|
||
|
|
.nav-item.active {
|
||
|
|
background: var(--rail-active);
|
||
|
|
color: var(--accent);
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
.nav-item.active::before {
|
||
|
|
content: "";
|
||
|
|
position: absolute; left: 0; top: 6px; bottom: 6px;
|
||
|
|
width: 3px; border-radius: 0 3px 3px 0;
|
||
|
|
background: var(--accent);
|
||
|
|
}
|
||
|
|
.nav-icon { width: 15px; height: 15px; flex-shrink: 0; opacity: .55; }
|
||
|
|
.nav-item:hover .nav-icon,
|
||
|
|
.nav-item.active .nav-icon { opacity: 1; }
|
||
|
|
.nav-badge {
|
||
|
|
margin-left: auto;
|
||
|
|
min-width: 18px; height: 17px; padding: 0 5px;
|
||
|
|
border-radius: var(--radius-pill);
|
||
|
|
background: var(--accent-dim); color: var(--accent);
|
||
|
|
font-size: 10px; font-family: var(--font-mono); font-weight: 700;
|
||
|
|
display: flex; align-items: center; justify-content: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-footer {
|
||
|
|
border-top: 1px solid var(--rail-border);
|
||
|
|
padding: 10px 8px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.sidebar-user {
|
||
|
|
display: flex; align-items: center; gap: 9px;
|
||
|
|
padding: 8px; border-radius: var(--radius-sm);
|
||
|
|
cursor: pointer;
|
||
|
|
transition: background 120ms;
|
||
|
|
}
|
||
|
|
.sidebar-user:hover { background: var(--rail-hover); }
|
||
|
|
.avatar {
|
||
|
|
width: 28px; height: 28px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--accent); color: #fff;
|
||
|
|
font-size: 11px; font-weight: 700;
|
||
|
|
display: flex; align-items: center; justify-content: center;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.user-name { font-size: 12px; font-weight: 600; color: var(--rail-fg); }
|
||
|
|
.user-role { font-size: 10px; color: var(--rail-muted); font-family: var(--font-mono); margin-top: 1px; }
|
||
|
|
.sidebar-action {
|
||
|
|
display: flex; align-items: center; gap: 9px;
|
||
|
|
height: 32px; padding: 0 8px;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
color: var(--rail-muted); font-size: 12px;
|
||
|
|
border: none; background: transparent; width: 100%;
|
||
|
|
text-align: left;
|
||
|
|
transition: background 120ms, color 120ms;
|
||
|
|
}
|
||
|
|
.sidebar-action:hover { background: var(--rail-hover); color: var(--rail-fg); }
|
||
|
|
|
||
|
|
/* ─── Content area ──────────────────────────────────────────────── */
|
||
|
|
.content-area { display: flex; flex-direction: column; min-width: 0; min-height: 100vh; }
|
||
|
|
|
||
|
|
.topbar {
|
||
|
|
position: sticky; top: 0; z-index: 10;
|
||
|
|
display: flex; align-items: center; gap: 10px;
|
||
|
|
height: 54px; padding: 0 24px;
|
||
|
|
border-bottom: 1px solid var(--border);
|
||
|
|
background: rgba(242,244,247,.9);
|
||
|
|
backdrop-filter: blur(16px);
|
||
|
|
-webkit-backdrop-filter: blur(16px);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.topbar-title { font-weight: 600; font-size: 14px; flex: 1; color: var(--fg); }
|
||
|
|
.search {
|
||
|
|
display: flex; align-items: center; gap: 8px;
|
||
|
|
border: 1px solid var(--border); border-radius: var(--radius-sm);
|
||
|
|
background: var(--surface);
|
||
|
|
padding: 0 10px; height: 32px; width: 240px;
|
||
|
|
transition: border-color 140ms;
|
||
|
|
}
|
||
|
|
.search:focus-within { border-color: color-mix(in oklab, var(--accent), transparent 60%); }
|
||
|
|
.search input { border: 0; outline: none; background: transparent; width: 100%; color: var(--fg); font-size: 13px; }
|
||
|
|
.search input::placeholder { color: var(--muted); }
|
||
|
|
|
||
|
|
.btn {
|
||
|
|
height: 32px; border-radius: var(--radius-sm);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
padding: 0 12px;
|
||
|
|
background: var(--surface); color: var(--fg);
|
||
|
|
font-size: 13px; font-weight: 500;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: background 120ms, border-color 120ms;
|
||
|
|
white-space: nowrap;
|
||
|
|
display: inline-flex; align-items: center; gap: 6px;
|
||
|
|
}
|
||
|
|
.btn:hover { background: var(--bg); border-color: #b0b7c0; }
|
||
|
|
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
|
||
|
|
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
|
||
|
|
|
||
|
|
/* ─── Page ──────────────────────────────────────────────────────── */
|
||
|
|
.page { padding: 20px; display: grid; gap: 18px; flex: 1; }
|
||
|
|
|
||
|
|
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
|
||
|
|
.eyebrow {
|
||
|
|
font-family: var(--font-mono); font-size: 10px;
|
||
|
|
text-transform: uppercase; letter-spacing: .1em;
|
||
|
|
color: var(--accent); margin-bottom: 6px;
|
||
|
|
}
|
||
|
|
.page-head h1 { font-size: clamp(20px, 2.4vw, 28px); }
|
||
|
|
.page-head-desc { margin-top: 4px; font-size: 13px; color: var(--muted); max-width: 520px; line-height: 1.55; }
|
||
|
|
|
||
|
|
/* ─── Cards ─────────────────────────────────────────────────────── */
|
||
|
|
.card {
|
||
|
|
background: var(--surface);
|
||
|
|
border-radius: var(--radius-md);
|
||
|
|
box-shadow: var(--shadow-card);
|
||
|
|
padding: 16px 18px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ─── Stats row ─────────────────────────────────────────────────── */
|
||
|
|
.stats-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px; }
|
||
|
|
.stat-card {
|
||
|
|
border-top: 2px solid var(--border);
|
||
|
|
transition: border-color 200ms;
|
||
|
|
}
|
||
|
|
.stat-card:hover { border-top-color: var(--accent); }
|
||
|
|
.stat-card .s-label {
|
||
|
|
font-family: var(--font-mono); font-size: 10px;
|
||
|
|
text-transform: uppercase; letter-spacing: .1em; color: var(--muted);
|
||
|
|
}
|
||
|
|
.stat-card .s-value {
|
||
|
|
margin-top: 10px;
|
||
|
|
font-size: 32px; line-height: 1;
|
||
|
|
font-family: var(--font-display);
|
||
|
|
font-variant-numeric: tabular-nums;
|
||
|
|
letter-spacing: -0.02em;
|
||
|
|
color: var(--fg);
|
||
|
|
}
|
||
|
|
.stat-card .s-sub { margin-top: 8px; font-size: 11px; color: var(--muted); line-height: 1.5; }
|
||
|
|
|
||
|
|
/* ─── Two-column panel grid ─────────────────────────────────────── */
|
||
|
|
.panel-grid { display: grid; grid-template-columns: 1.4fr 0.9fr; gap: 18px; }
|
||
|
|
.stack { display: grid; gap: 18px; }
|
||
|
|
|
||
|
|
/* ─── Section heads ─────────────────────────────────────────────── */
|
||
|
|
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
|
||
|
|
.section-head h2 { font-size: 16px; }
|
||
|
|
.ghost-link {
|
||
|
|
color: var(--muted); font-size: 12px;
|
||
|
|
padding: 2px 0; border-radius: 4px;
|
||
|
|
transition: color 120ms;
|
||
|
|
}
|
||
|
|
.ghost-link:hover { color: var(--fg); text-decoration: none; }
|
||
|
|
|
||
|
|
/* ─── Task rows ─────────────────────────────────────────────────── */
|
||
|
|
.task-list, .program-list, .event-list { display: grid; gap: 8px; }
|
||
|
|
.task-row, .program-row, .event-row {
|
||
|
|
display: grid; gap: 10px;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
padding: 10px 12px;
|
||
|
|
background: var(--surface);
|
||
|
|
transition: border-color 120ms, box-shadow 120ms;
|
||
|
|
}
|
||
|
|
.task-row:hover, .program-row:hover {
|
||
|
|
border-color: #c8cdd8;
|
||
|
|
box-shadow: var(--shadow-sm);
|
||
|
|
}
|
||
|
|
.task-row { grid-template-columns: 1.6fr 0.8fr 0.8fr 0.6fr; align-items: center; }
|
||
|
|
.program-row{ grid-template-columns: 1fr auto; align-items: start; }
|
||
|
|
.event-row { grid-template-columns: 76px 1fr; align-items: start; }
|
||
|
|
|
||
|
|
/* ─── KPI strip ─────────────────────────────────────────────────── */
|
||
|
|
.kpi-strip { display: grid; grid-template-columns: repeat(3,1fr); gap: 8px; margin-top: 12px; }
|
||
|
|
.kpi {
|
||
|
|
border: 1px solid var(--border); border-radius: var(--radius-sm);
|
||
|
|
padding: 10px 12px; background: #f8f9fb;
|
||
|
|
}
|
||
|
|
.kpi strong { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 17px; color: var(--fg); }
|
||
|
|
.kpi-label { font-size: 11px; color: var(--muted); margin-bottom: 4px; }
|
||
|
|
.meter { height: 3px; border-radius: 999px; background: #e5e7eb; overflow: hidden; margin-top: 8px; }
|
||
|
|
.meter > span { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
|
||
|
|
|
||
|
|
/* ─── Dark mode ────────────────────────────────────────────────── */
|
||
|
|
[data-theme="dark"] {
|
||
|
|
--rail-bg: #1a1c22;
|
||
|
|
--rail-surface: #22242c;
|
||
|
|
--rail-fg: #f0f2f5;
|
||
|
|
--rail-muted: #7a8390;
|
||
|
|
--rail-border: #2d3038;
|
||
|
|
--rail-hover: rgba(255,255,255,.05);
|
||
|
|
--rail-active: rgba(226,0,116,.12);
|
||
|
|
--bg: #111318;
|
||
|
|
--surface: #1a1c22;
|
||
|
|
--fg: #f0f2f5;
|
||
|
|
--muted: #7a8390;
|
||
|
|
--border: #2d3038;
|
||
|
|
}
|
||
|
|
[data-theme="dark"] body { color-scheme: dark; }
|
||
|
|
[data-theme="dark"] .topbar { background: rgba(17,19,24,.9); }
|
||
|
|
[data-theme="dark"] .kpi { background: #1e2028; }
|
||
|
|
[data-theme="dark"] .task-row, [data-theme="dark"] .program-row, [data-theme="dark"] .event-row { background: #1e2028; }
|
||
|
|
|
||
|
|
/* ─── Status pills ──────────────────────────────────────────────── */
|
||
|
|
.status {
|
||
|
|
display: inline-flex; align-items: center; gap: 5px;
|
||
|
|
padding: 2px 8px; border-radius: var(--radius-pill);
|
||
|
|
font-size: 11px; font-family: var(--font-mono); font-weight: 600;
|
||
|
|
width: fit-content; white-space: nowrap;
|
||
|
|
}
|
||
|
|
.status::before {
|
||
|
|
content: ""; width: 5px; height: 5px;
|
||
|
|
border-radius: 50%; background: currentColor; flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.status.ok { color: var(--success); background: color-mix(in oklab,var(--success),transparent 90%); }
|
||
|
|
.status.warn { color: var(--warn); background: color-mix(in oklab,var(--warn),transparent 90%); }
|
||
|
|
.status.risk { color: var(--danger); background: color-mix(in oklab,var(--danger),transparent 90%); }
|
||
|
|
|
||
|
|
/* ─── Pill (version tag) ────────────────────────────────────────── */
|
||
|
|
.pill {
|
||
|
|
display: inline-flex; align-items: center;
|
||
|
|
height: 20px; padding: 0 8px;
|
||
|
|
border-radius: var(--radius-pill);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
color: var(--muted); font-size: 10px;
|
||
|
|
font-family: var(--font-mono); font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ─── Task CTA buttons ──────────────────────────────────────────── */
|
||
|
|
.task-cta {
|
||
|
|
display: inline-flex; align-items: center; gap: 4px;
|
||
|
|
height: 26px; padding: 0 10px;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
background: transparent; color: var(--muted);
|
||
|
|
font-size: 11px; font-family: var(--font-body);
|
||
|
|
white-space: nowrap; cursor: pointer;
|
||
|
|
transition: border-color 120ms, color 120ms, background 120ms;
|
||
|
|
}
|
||
|
|
.task-cta:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); text-decoration: none; }
|
||
|
|
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 12px; }
|
||
|
|
.note { font-size: 12px; color: var(--muted); line-height: 1.5; }
|
||
|
|
|
||
|
|
/* ─── Footer ────────────────────────────────────────────────────── */
|
||
|
|
.footer {
|
||
|
|
display: flex; align-items: center; justify-content: space-between; gap: 16px;
|
||
|
|
min-height: 34px; padding: 0 20px;
|
||
|
|
border-top: 1px solid var(--border);
|
||
|
|
color: var(--muted);
|
||
|
|
font-size: 10px; font-family: var(--font-mono);
|
||
|
|
letter-spacing: .1em; text-transform: uppercase;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.footer-live { display: inline-flex; align-items: center; gap: 7px; }
|
||
|
|
.footer-dot {
|
||
|
|
width: 6px; height: 6px; border-radius: 50%;
|
||
|
|
background: #22c55e;
|
||
|
|
box-shadow: 0 0 0 3px rgba(34,197,94,.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ─── Responsive ────────────────────────────────────────────────── */
|
||
|
|
@media (max-width: 1200px) {
|
||
|
|
.stats-grid { grid-template-columns: repeat(2,1fr); }
|
||
|
|
.panel-grid { grid-template-columns: 1fr; }
|
||
|
|
.kpi-strip { grid-template-columns: 1fr 1fr; }
|
||
|
|
.task-row { grid-template-columns: 1fr auto; }
|
||
|
|
}
|
||
|
|
@media (max-width: 700px) {
|
||
|
|
.app-shell { grid-template-columns: 1fr; }
|
||
|
|
.sidebar { display: none; }
|
||
|
|
.stats-grid, .kpi-strip { grid-template-columns: 1fr 1fr; }
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="app-shell">
|
||
|
|
|
||
|
|
<!-- ─── Sidebar ─────────────────────────────────────────────────────── -->
|
||
|
|
<aside class="sidebar" aria-label="Primary navigation">
|
||
|
|
<div class="sidebar-brand">
|
||
|
|
<div class="brand-logo">
|
||
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||
|
|
<path d="M2 3.5h12v1.5H2zm5.25 1.5h1.5v8h-1.5zm-3 2h2.25v1.5H4.25zm5.25 0h2.25v1.5H9.5zm-3 3h2.5v1.5H6.5z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<div class="brand-name">T-Systems</div>
|
||
|
|
<div class="brand-sub">Regulation Hub</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<nav class="sidebar-nav" aria-label="Primary">
|
||
|
|
<div class="nav-group">
|
||
|
|
<span class="nav-group-label">Main</span>
|
||
|
|
<a class="nav-item" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/index.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M2 2h5v5H2zm7 0h5v5H9zM2 9h5v5H2zm7 0h5v5H9z" fill="currentColor" opacity=".6"/>
|
||
|
|
</svg>
|
||
|
|
Overview
|
||
|
|
</a>
|
||
|
|
<a class="nav-item" href="perception.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<circle cx="8" cy="8" r="2.5" fill="currentColor"/>
|
||
|
|
<path d="M8 2.5C4.91 2.5 2.5 5.42 2.5 8S4.91 13.5 8 13.5 13.5 10.58 13.5 8 11.09 2.5 8 2.5zm0 9.5C5.52 12 3.5 10.24 3.5 8S5.52 4 8 4s4.5 1.76 4.5 4-2.02 4-4.5 4z" fill="currentColor" opacity=".45"/>
|
||
|
|
</svg>
|
||
|
|
Regulatory Signals
|
||
|
|
<span class="nav-badge">6</span>
|
||
|
|
</a>
|
||
|
|
<a class="nav-item active" href="dashboard-sidebar.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M1.5 2.5h13v1H1.5zm0 3h13v1H1.5zm0 3h8v1h-8zm0 3h6v1h-6z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
System Status
|
||
|
|
<span class="nav-badge">3</span>
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="nav-group">
|
||
|
|
<span class="nav-group-label">Workbench</span>
|
||
|
|
<a class="nav-item" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/document-management.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M3 1h7l3 3v11H3V1zm1 1v12h8V5h-3V2H4zm5 .5V4h1.5L9 1.5zM6 7h4v1H6zm0 2h4v1H6zm0 2h3v1H6z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
Documents
|
||
|
|
</a>
|
||
|
|
<a class="nav-item" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/compliance-analysis.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M8 1l7 3-1 6a7 7 0 01-6 5A7 7 0 011 10L0 4l8-3zm0 1.2L1.3 4.8l.8 5.1A6 6 0 008 14.8a6 6 0 005.9-4.9l.8-5.1L8 2.2zM7.5 5h1v4.5h-1V5zm0 5.5h1v1h-1v-1z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
Compliance Analysis
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="nav-group">
|
||
|
|
<span class="nav-group-label">Chat</span>
|
||
|
|
<a class="nav-item" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/regulation-chat.html">
|
||
|
|
<svg class="nav-icon" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M2 2h12a1 1 0 011 1v8a1 1 0 01-1 1H5l-3 2.5V3a1 1 0 011-1zm0 1v9.5L4.5 11H14V3H2zm2 2h8v1H4zm0 2h6v1H4z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
Regulation Q&A
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</nav>
|
||
|
|
|
||
|
|
<div class="sidebar-footer">
|
||
|
|
<div class="sidebar-user">
|
||
|
|
<div class="avatar">TS</div>
|
||
|
|
<div>
|
||
|
|
<div class="user-name">T-Systems User</div>
|
||
|
|
<div class="user-role">Compliance Analyst</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<button class="sidebar-action" type="button" onclick="toggleTheme()">
|
||
|
|
<svg width="14" height="14" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M8 3a5 5 0 100 10A5 5 0 008 3zM2 8a6 6 0 1112 0A6 6 0 012 8z" fill="currentColor"/>
|
||
|
|
</svg>
|
||
|
|
<span>Dark mode</span>
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
<!-- ─── Content ──────────────────────────────────────────────────────── -->
|
||
|
|
<div class="content-area">
|
||
|
|
<header class="topbar">
|
||
|
|
<span class="topbar-title">System Status</span>
|
||
|
|
<div class="search">
|
||
|
|
<svg width="13" height="13" viewBox="0 0 16 16" fill="none">
|
||
|
|
<path d="M6.5 1a5.5 5.5 0 014.23 9.02l3.62 3.62-.7.71-3.63-3.63A5.5 5.5 0 116.5 1zm0 1a4.5 4.5 0 100 9 4.5 4.5 0 000-9z" fill="currentColor" opacity=".4"/>
|
||
|
|
</svg>
|
||
|
|
<input type="search" placeholder="Search regulations, documents…" aria-label="Search" />
|
||
|
|
</div>
|
||
|
|
<button class="btn">Export status</button>
|
||
|
|
<a class="btn btn-primary" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/upload-modal.html">New upload</a>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<main class="page">
|
||
|
|
<!-- Page head -->
|
||
|
|
<section class="page-head">
|
||
|
|
<div>
|
||
|
|
<div class="eyebrow">System Status</div>
|
||
|
|
<h1>System Status</h1>
|
||
|
|
<p class="page-head-desc">Ingestion pipeline, active compliance programs, and regulatory watch — all in one place.</p>
|
||
|
|
</div>
|
||
|
|
<span class="pill">v1.0.0</span>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Stats -->
|
||
|
|
<section class="stats-grid">
|
||
|
|
<article class="card stat-card">
|
||
|
|
<div class="s-label">Documents total</div>
|
||
|
|
<div class="s-value mono" id="ds-docs">—</div>
|
||
|
|
<div class="s-sub">Ingested into the knowledge base</div>
|
||
|
|
</article>
|
||
|
|
<article class="card stat-card">
|
||
|
|
<div class="s-label">Vector chunks</div>
|
||
|
|
<div class="s-value mono" id="ds-chunks">—</div>
|
||
|
|
<div class="s-sub">regulations_dense_1024_v2 serving retrieval</div>
|
||
|
|
</article>
|
||
|
|
<article class="card stat-card">
|
||
|
|
<div class="s-label">High-impact signals</div>
|
||
|
|
<div class="s-value mono" id="ds-high">—</div>
|
||
|
|
<div class="s-sub">Regulatory signals requiring immediate review</div>
|
||
|
|
</article>
|
||
|
|
<article class="card stat-card">
|
||
|
|
<div class="s-label">Last 90 days</div>
|
||
|
|
<div class="s-value mono" id="ds-90d">—</div>
|
||
|
|
<div class="s-sub">Recent regulatory publications</div>
|
||
|
|
</article>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Two-column panels -->
|
||
|
|
<section class="panel-grid">
|
||
|
|
<!-- Left column -->
|
||
|
|
<div class="stack">
|
||
|
|
<article class="card">
|
||
|
|
<div class="section-head">
|
||
|
|
<h2>Workflow queue</h2>
|
||
|
|
<a class="ghost-link" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/document-management.html">Open documents →</a>
|
||
|
|
</div>
|
||
|
|
<div class="task-list">
|
||
|
|
<div class="task-row">
|
||
|
|
<div>
|
||
|
|
<strong>GB/T 31484-2015 battery density revision</strong>
|
||
|
|
<div class="note">Uploaded by EV Safety Team · version 2026-04 addendum</div>
|
||
|
|
</div>
|
||
|
|
<span class="status warn">Embedding</span>
|
||
|
|
<span class="mono">chunk build active</span>
|
||
|
|
<a class="task-cta" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/document-detail.html">Inspect →</a>
|
||
|
|
</div>
|
||
|
|
<div class="task-row">
|
||
|
|
<div>
|
||
|
|
<strong>UNECE R155 annex interpretation note</strong>
|
||
|
|
<div class="note">Parser artifacts ready · waiting for analyst assignment</div>
|
||
|
|
</div>
|
||
|
|
<span class="status ok">Ready</span>
|
||
|
|
<span class="mono">19 clauses linked</span>
|
||
|
|
<a class="task-cta" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/compliance-analysis.html">Analyze →</a>
|
||
|
|
</div>
|
||
|
|
<div class="task-row">
|
||
|
|
<div>
|
||
|
|
<strong>GB 26112-2010 roof strength scan</strong>
|
||
|
|
<div class="note">OCR confidence dropped below threshold on 6 pages</div>
|
||
|
|
</div>
|
||
|
|
<span class="status risk">Failed</span>
|
||
|
|
<span class="mono">Retry #2</span>
|
||
|
|
<a class="task-cta" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/document-management.html">Resolve →</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</article>
|
||
|
|
|
||
|
|
<article class="card">
|
||
|
|
<div class="section-head">
|
||
|
|
<h2>Active compliance programs</h2>
|
||
|
|
<a class="ghost-link" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/compliance-analysis.html">Review findings →</a>
|
||
|
|
</div>
|
||
|
|
<div class="program-list">
|
||
|
|
<div class="program-row">
|
||
|
|
<div>
|
||
|
|
<strong>Intelligent cockpit homologation</strong>
|
||
|
|
<p class="note">42 related standards across driver monitoring, EMC, and child safety. Four findings still open for MY27 platform.</p>
|
||
|
|
</div>
|
||
|
|
<span class="status risk">High risk</span>
|
||
|
|
</div>
|
||
|
|
<div class="program-row">
|
||
|
|
<div>
|
||
|
|
<strong>Battery swap certification dossier</strong>
|
||
|
|
<p class="note">Clause mapping complete. Thermal event test evidence package awaiting supplier document refresh.</p>
|
||
|
|
</div>
|
||
|
|
<span class="status warn">Pending</span>
|
||
|
|
</div>
|
||
|
|
<div class="program-row">
|
||
|
|
<div>
|
||
|
|
<strong>Connected fleet cybersecurity</strong>
|
||
|
|
<p class="note">RAG checks aligned with UNECE R155. Chat follow-up requested on remote key rotation obligations.</p>
|
||
|
|
</div>
|
||
|
|
<span class="status ok">On track</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="kpi-strip">
|
||
|
|
<div class="kpi">
|
||
|
|
<div class="kpi-label">Retrieval hit rate</div>
|
||
|
|
<strong>87%</strong>
|
||
|
|
<div class="meter"><span style="width:87%"></span></div>
|
||
|
|
</div>
|
||
|
|
<div class="kpi">
|
||
|
|
<div class="kpi-label">Evidence coverage</div>
|
||
|
|
<strong>72%</strong>
|
||
|
|
<div class="meter"><span style="width:72%"></span></div>
|
||
|
|
</div>
|
||
|
|
<div class="kpi">
|
||
|
|
<div class="kpi-label">Reviewer SLA</div>
|
||
|
|
<strong>18h</strong>
|
||
|
|
<div class="meter"><span style="width:64%"></span></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</article>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Right column -->
|
||
|
|
<div class="stack">
|
||
|
|
<article class="card">
|
||
|
|
<div class="section-head"><h2>System health</h2><a class="ghost-link" href="#">Refresh</a></div>
|
||
|
|
<div class="task-list">
|
||
|
|
<div class="task-row" style="grid-template-columns:1fr auto">
|
||
|
|
<div>
|
||
|
|
<strong>Aliyun parser backend</strong>
|
||
|
|
<div class="note">Poll interval 5 s · timeout 900 s</div>
|
||
|
|
</div>
|
||
|
|
<span class="status warn">Queue depth 7</span>
|
||
|
|
</div>
|
||
|
|
<div class="task-row" style="grid-template-columns:1fr auto">
|
||
|
|
<div>
|
||
|
|
<strong>Embedding model</strong>
|
||
|
|
<div class="note">text-embedding-v3 · dimension 1024</div>
|
||
|
|
</div>
|
||
|
|
<span class="status ok">Healthy</span>
|
||
|
|
</div>
|
||
|
|
<div class="task-row" style="grid-template-columns:1fr auto">
|
||
|
|
<div>
|
||
|
|
<strong>Vector store</strong>
|
||
|
|
<div class="note">Milvus regulations_dense_1024_v2</div>
|
||
|
|
</div>
|
||
|
|
<span class="status ok">Serving</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</article>
|
||
|
|
|
||
|
|
<article class="card">
|
||
|
|
<div class="section-head">
|
||
|
|
<h2>Regulatory watch</h2>
|
||
|
|
<a class="ghost-link" href="cc29bcb0-df2d-4d50-9428-7caa406ecb29/regulation-chat.html">Ask chat →</a>
|
||
|
|
</div>
|
||
|
|
<div class="event-list">
|
||
|
|
<div class="event-row">
|
||
|
|
<span class="mono note">2d ago</span>
|
||
|
|
<div>
|
||
|
|
<strong>GB 38031 thermal propagation draft updated</strong>
|
||
|
|
<p class="note" style="-webkit-line-clamp:2;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden">Potential impact on current battery enclosure narrative. Evidence gap flagged in two supplier submissions.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="event-row">
|
||
|
|
<span class="mono note">5d ago</span>
|
||
|
|
<div>
|
||
|
|
<strong>UNECE R155 Q&A added note on incident response logs</strong>
|
||
|
|
<p class="note" style="-webkit-line-clamp:2;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden">Connected fleet program must confirm retention windows and ownership controls.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="event-row">
|
||
|
|
<span class="mono note">12d ago</span>
|
||
|
|
<div>
|
||
|
|
<strong>GB/T 18487 charging interface interpretation circulated</strong>
|
||
|
|
<p class="note" style="-webkit-line-clamp:2;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden">No blocker yet, but three documents should be re-run against the new clause wording.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</article>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
</main>
|
||
|
|
|
||
|
|
<footer class="footer">
|
||
|
|
<span>T-Systems Regulation Hub</span>
|
||
|
|
<div class="footer-live">
|
||
|
|
<span class="footer-dot" aria-hidden="true"></span>
|
||
|
|
<span>Online</span>
|
||
|
|
</div>
|
||
|
|
</footer>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// ─── Theme toggle (P0 fix: reads data-theme attribute) ───────────────
|
||
|
|
function toggleTheme() {
|
||
|
|
const html = document.documentElement;
|
||
|
|
const next = html.dataset.theme === 'dark' ? 'light' : 'dark';
|
||
|
|
html.dataset.theme = next;
|
||
|
|
localStorage.setItem('theme', next);
|
||
|
|
const btn = document.querySelector('.sidebar-action');
|
||
|
|
if (btn) btn.querySelector('span') && (btn.querySelector('span').textContent = next === 'dark' ? 'Light mode' : 'Dark mode');
|
||
|
|
}
|
||
|
|
// Restore saved theme
|
||
|
|
(function() {
|
||
|
|
const saved = localStorage.getItem('theme');
|
||
|
|
if (saved) document.documentElement.dataset.theme = saved;
|
||
|
|
})();
|
||
|
|
|
||
|
|
// ─── Live stats from perception API ──────────────────────────────────
|
||
|
|
async function loadDashboardStats() {
|
||
|
|
try {
|
||
|
|
const r = await fetch('http://6.86.80.9:5173/api/v1/perception/stats');
|
||
|
|
if (!r.ok) return;
|
||
|
|
const s = await r.json();
|
||
|
|
const set = (id, val) => { const el = document.getElementById(id); if (el && val != null) el.textContent = val; };
|
||
|
|
set('ds-high', s.high_impact);
|
||
|
|
set('ds-90d', s.recent_90d);
|
||
|
|
set('ds-docs', s.total);
|
||
|
|
} catch(e) { /* silent — fallback to — */ }
|
||
|
|
}
|
||
|
|
loadDashboardStats();
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|