diff --git a/bin/SHA256SUMS b/bin/SHA256SUMS index 26fa81c..57483c0 100644 --- a/bin/SHA256SUMS +++ b/bin/SHA256SUMS @@ -1,4 +1,4 @@ 118e09f98944ac59593af603c04a1d5f0e7cafb6549b5a562300bc31d9c769da control-api 48c9b99fa88be751d9badfba8b7d80f894e326a743a90e85478f1d2251ce4ab6 validator-agent 8877cf7c6d2bdd58faf70865be602b3db5f18508f4607c8942bc8899ce0fb1e6 prober -8d18a72276cdb1a7c14c919c9243446f467bdf9aa99f26d856aa954546031731 admin-dashboard +4c7cf560b4a7b87f8de0fcc5a4fe6200c45eadf5ae04b022d67c8a8e196f39cc admin-dashboard diff --git a/bin/admin-dashboard b/bin/admin-dashboard index 67fd51c..3ba780c 100755 Binary files a/bin/admin-dashboard and b/bin/admin-dashboard differ diff --git a/internal/dashboard/static/dashboard.css b/internal/dashboard/static/dashboard.css index 520b097..a6ce8c5 100644 --- a/internal/dashboard/static/dashboard.css +++ b/internal/dashboard/static/dashboard.css @@ -10,8 +10,11 @@ (IBM Plex Mono, already vendored) carries headings/nav/labels/table heads — an operations-console register — while --font-ui (Manrope) stays on body copy and form microcopy for readability at length. - Both a light and a dark palette are defined; the dark one activates - automatically from the OS/browser color-scheme (no in-app toggle). */ + Both a light and a dark palette are defined. The bare :root (no + data-theme attribute) follows the OS/browser color-scheme; the sidebar + toggle (see layout.html) stamps documentElement with + data-theme="light"/"dark" to override that, storing the choice in + localStorage so it survives page navigation. */ :root { --bg: #EEF1F5; @@ -58,7 +61,7 @@ } @media (prefers-color-scheme: dark) { - :root { + :root:not([data-theme="light"]) { --bg: #0A0D13; --surface: #10141C; --surface-alt: #161B25; @@ -89,6 +92,37 @@ } } +/* Explicit dark choice (toggle) wins even when the OS/browser is light. */ +:root[data-theme="dark"] { + --bg: #0A0D13; + --surface: #10141C; + --surface-alt: #161B25; + --border: #262E3B; + --border-soft: #1D2430; + --text: #E7ECF5; + --text-muted: #8D97AC; + --text-faint: #626D82; + + --accent: #5C8CFF; + --accent-strong: #82A6FF; + --accent-soft: #182140; + --accent-contrast: #071022; + + --success: #3DDC8A; --success-soft: #10261C; + --warning: #F0B429; --warning-soft: #2B2210; --warning-border: #4A3B14; + --danger: #FF6B5E; --danger-soft: #2C1613; --danger-border: #5A2620; + --info: #5AC0FF; --info-soft: #10222E; + --neutral: #A3ACBE; --neutral-soft: #1B212B; + --cancel: #B79CFF; --cancel-soft: #221B3A; + + --overlay: rgba(0, 0, 0, .55); + + --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4); + --shadow-md: 0 16px 40px rgba(0, 0, 0, .5); + + color-scheme: dark; +} + * { box-sizing: border-box; } html, body { height: 100%; } @@ -177,8 +211,9 @@ nav.nav-groups { display: flex; flex-direction: column; gap: 1px; } font-family: var(--font-display); font-size: 11px; color: var(--text-muted); - display: flex; align-items: center; gap: 7px; + display: flex; align-items: center; justify-content: space-between; gap: 7px; } +.sidebar-foot-status { display: flex; align-items: center; gap: 7px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pulse-dot { width: 6px; height: 6px; border-radius: 1px; background: var(--success); @@ -186,6 +221,30 @@ nav.nav-groups { display: flex; flex-direction: column; gap: 1px; } flex-shrink: 0; } +.theme-toggle { + display: grid; place-items: center; + width: 22px; height: 22px; flex-shrink: 0; + border-radius: var(--radius-xs); + border: 1px solid var(--border); + background: var(--surface); + color: var(--text-muted); + cursor: pointer; + padding: 0; +} +.theme-toggle:hover { border-color: var(--accent); color: var(--accent); } +.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } +.theme-toggle svg { width: 13px; height: 13px; } +.theme-toggle .icon-moon { display: none; } +/* Icon reflects the *effective* theme (OS default, unless the toggle has + stamped an explicit choice) — same three-state precedence as the color + tokens above. */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: none; } + :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; } +} +:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; } +:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; } + .main { padding: 22px 26px 60px; max-width: 1180px; } .topbar { display: flex; align-items: baseline; justify-content: space-between; diff --git a/internal/dashboard/templates/layout.html b/internal/dashboard/templates/layout.html index 94cd0dd..fd08793 100644 --- a/internal/dashboard/templates/layout.html +++ b/internal/dashboard/templates/layout.html @@ -14,6 +14,21 @@