diff --git a/frontend/packages/dashboard/build.mjs b/frontend/packages/dashboard/build.mjs index 63c6f6b5..b0d79747 100644 --- a/frontend/packages/dashboard/build.mjs +++ b/frontend/packages/dashboard/build.mjs @@ -52,7 +52,7 @@ mkdirSync(staticDir(''), { recursive: true }); // follow-up once asset sizes warrant it). esbuild writes each entry // to `static/.js` based on the entryPoint basename. await build({ - entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js')], + entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js'), src('stats.js')], outdir: staticDir(''), bundle: true, format: 'esm', @@ -91,7 +91,7 @@ await build({ // so a swap replaces only it) + theme.css (the semantic derivation // layer) + common.css (shared typography, badges, buttons, inbox, side // panel) plus its own page-specific bundle. -for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css']) { +for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css', 'stats.css']) { await build({ entryPoints: [src(entry)], outfile: staticDir(entry), @@ -101,7 +101,7 @@ for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', ' }); } -for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html']) { +for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html', 'stats.html']) { copyFileSync(src(html), dist(html)); } diff --git a/frontend/packages/dashboard/src/common.css b/frontend/packages/dashboard/src/common.css index 22c6fb37..305d68d5 100644 --- a/frontend/packages/dashboard/src/common.css +++ b/frontend/packages/dashboard/src/common.css @@ -519,6 +519,16 @@ body.side-panel-resizing * { cursor: ew-resize !important; } padding: 0.2em 0.5em; } +/* ─── page-content gutter ───────────────────────────────────────────── + Inverted-gutter layout: the dashboard + H0M3 keep `` full-bleed + and wrap their padded content in a single `.page-content` div that + carries the horizontal gutter. Full-width chrome (the tab strip, the + server-warnings banner, the footer) then spans edge-to-edge for free, + with no negative-margin breakout hacks. Only matches on pages that opt + in by adding the wrapper (dashboard.html, index.html); FL0W / L0GS / + ST4TS / S3TT1NGS are full-bleed with their own `.-main` padding. */ +.page-content { padding: 0 1.5em; } + /* ─── server warnings banner ────────────────────────────────────────── Generic top-of-page strip, injected at the top of by common.js (renderServerWarnings) on every page. One row per warning; @@ -530,16 +540,11 @@ body.side-panel-resizing * { cursor: ew-resize !important; } top: 0; z-index: 50; } -/* The bar is prepended as a direct child of . On pages that pad - the body gutter (the dashboard + H0M3 use a 1.5em horizontal gutter), - break out of that padding so the warning spans the full width - edge-to-edge — the same trick `.dashboard-chrome` uses. FL0W + L0GS - are already full-bleed (no body padding), so they need no override. */ -body.dashboard-shell #server-warnings, -body.home-shell #server-warnings { - margin-left: -1.5em; - margin-right: -1.5em; -} +/* The bar is prepended as a direct child of and spans the full + width edge-to-edge. The dashboard + H0M3 are full-bleed at the body + level — their 1.5em horizontal gutter lives on an inner `.page-content` + wrapper (see below), so the banner is full-width for free with no + breakout. FL0W + L0GS are full-bleed too. */ .server-warnings[hidden] { display: none; } .server-warn { text-align: center; @@ -558,3 +563,31 @@ body.home-shell #server-warnings { background: color-mix(in srgb, var(--red) 18%, transparent); border-bottom: 1px solid var(--red); } + +/* ─── stats table ───────────────────────────────────────────────── + Shared right-aligned numeric table. Used by /stats.html (busiest + agents) and the dashboard SYST3M › C0NT41N3R L04D table — moved here + from dashboard.css when ST4TS became its own page. */ +.hive-stats-table { + width: 100%; + border-collapse: collapse; + font-size: 0.85rem; + margin-bottom: 8px; +} +.hive-stats-table th, +.hive-stats-table td { + border-bottom: 1px solid var(--border); + padding: 5px 8px; + text-align: right; +} +.hive-stats-table th:first-child, +.hive-stats-table td:first-child { + text-align: left; +} +.hive-stats-table th { + color: var(--muted); + font-weight: normal; +} +.hive-stats-table td.num { + font-variant-numeric: tabular-nums; +} diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index 3b1f0229..dfd2eeb0 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -9,14 +9,15 @@ routing model. */ body.dashboard-shell { - /* Full-width layout — no max-width cap so wide screens don't - waste real estate on empty side margins. `padding: 0 1.5em - 1.5em` keeps a small gutter on the left/right so cards don't - kiss the viewport edge; `.dashboard-chrome { margin: 0 -1.5em - ... }` still pulls the chrome bar edge-to-edge through that - gutter. */ + /* Full-bleed body (no horizontal gutter). The 1.5em side gutter lives + on the inner `.page-content` wrapper (see common.css), so the sticky + chrome bar, the server-warnings banner, and the footer span the full + width edge-to-edge with no negative-margin breakout. `padding-bottom` + keeps a little breathing room above the viewport edge (overridden to + clear the selection bar via `.has-selection` below). No max-width cap + — wide screens use the full width rather than empty side margins. */ margin: 0; - padding: 0 1.5em 1.5em; + padding-bottom: 1.5em; } .dashboard-chrome { @@ -28,7 +29,7 @@ body.dashboard-shell { backdrop-filter: blur(8px) saturate(120%); border-bottom: 1px solid var(--purple-dim); padding: 0.4em 0 0; - margin: 0 -1.5em 1em; + margin: 0 0 1em; } /* ← home back-link to the H0M3 hub. Small purple link top-left of the chrome, mirroring the .logs-back treatment the sub-pages use so the @@ -1392,97 +1393,14 @@ body.dashboard-shell.has-selection { padding-bottom: 4.5em; } cursor: default; } -/* ─── ST4TS tab: hive-wide turn-stats rollup ────────────────────────────── - Plain tables + CSS bars (no chart lib in the dashboard bundle). */ -.hive-stats-windows { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin: 12px 0; -} -.hive-stats-windows .btn.active { - border-color: var(--amber); - color: var(--amber); -} -.hive-stats-chips { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 16px; -} -.hive-stats-chip { - display: inline-flex; - flex-direction: column; - padding: 6px 10px; - background: var(--bg-elev); - border: 1px solid var(--border); - border-radius: 4px; - min-width: 7em; -} -.hive-stats-chip .k { - font-size: 0.72rem; - color: var(--muted); - text-transform: lowercase; -} -.hive-stats-chip .v { - font-size: 1.05rem; - color: var(--fg); -} -.hive-stats-chip.est .v { - color: var(--amber); -} -.hive-stats-table { - width: 100%; - border-collapse: collapse; - font-size: 0.85rem; - margin-bottom: 8px; -} -.hive-stats-table th, -.hive-stats-table td { - border-bottom: 1px solid var(--border); - padding: 5px 8px; - text-align: right; -} -.hive-stats-table th:first-child, -.hive-stats-table td:first-child { - text-align: left; -} -.hive-stats-table th { - color: var(--muted); - font-weight: normal; -} -.hive-stats-table td.num { - font-variant-numeric: tabular-nums; -} -.hive-stats-bar { - display: grid; - grid-template-columns: 12em 1fr 4em; - align-items: center; - gap: 8px; - margin: 3px 0; - font-size: 0.85rem; -} -.hive-stats-bar .track { - background: var(--bg-elev); - border: 1px solid var(--border); - border-radius: 3px; - height: 14px; - overflow: hidden; -} -.hive-stats-bar .fill { - display: block; - height: 100%; - background: var(--purple); -} -.hive-stats-bar .cnt { - text-align: right; - color: var(--muted); - font-variant-numeric: tabular-nums; -} +/* ST4TS moved to its own page (`/stats.html`): the + window selector / summary chips / bars live in stats.css, and the + shared `.hive-stats-table` moved to common.css (the SYST3M › + C0NT41N3R L04D table below still uses it). */ /* ─── SYST3M › C0NT41N3R L04D: live cgroup cpu/mem ───────────────────────────── - Reuses the `.hive-stats-table` styling from the ST4TS tab; only the - inline meter bar is new. */ + Reuses the shared `.hive-stats-table` styling (now in common.css); + only the inline meter bar is new. */ .cload-meter { display: inline-block; width: 6em; diff --git a/frontend/packages/dashboard/src/dashboard.html b/frontend/packages/dashboard/src/dashboard.html index e1f20160..676cac03 100644 --- a/frontend/packages/dashboard/src/dashboard.html +++ b/frontend/packages/dashboard/src/dashboard.html @@ -60,14 +60,9 @@ - - - ◆ ST4TS ◆ - + @@ -88,6 +83,10 @@ visible by toggling the `hidden` attribute, resolved from the URL hash (default SW4RM). Panes start `hidden` to avoid a flash before the script runs. --> + +
- +
+