Files
peardock/ui/modern.css
T
Raven Scott b720e7e68f Wire PearDock branding into app, Electron icons, and README
Copy runtime logos/favicons into assets/ and package icons into build/, then use them for the titlebar, favicons, dock/window icons, and docs so packaging and the UI no longer rely on placeholder marks.
2026-07-11 14:16:28 -04:00

2893 lines
60 KiB
CSS

/**
* peardock modern UI layer
* Overrides / extends ui/styles.css with a refined design system.
*/
:root {
/* Surfaces */
--bg-primary: #0a0c10;
--bg-secondary: #0f131a;
--bg-tertiary: #151b24;
--bg-elevated: #1a222e;
--bg-hover: #232d3b;
--bg-glass: rgba(15, 19, 26, 0.72);
/* Brand — pear green + teal */
--accent-primary: #34d399;
--accent-secondary: #2dd4bf;
--accent-glow: rgba(52, 211, 153, 0.35);
--accent-success: #4ade80;
--accent-warning: #fbbf24;
--accent-danger: #f87171;
--accent-info: #38bdf8;
/* Text — tuned for WCAG-ish contrast on near-black surfaces */
--text-primary: #f4f7fb;
--text-secondary: #c8d1df;
--text-muted: #9aa8bc;
--text-faint: #7d8b9f;
--border-color: rgba(255, 255, 255, 0.1);
--border-strong: rgba(255, 255, 255, 0.18);
--border-radius: 14px;
--border-radius-sm: 10px;
--border-radius-lg: 18px;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
--shadow-md: 0 8px 24px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.45);
--shadow-glow: 0 0 0 1px rgba(52, 211, 153, 0.15), 0 8px 32px rgba(52, 211, 153, 0.12);
--titlebar-h: 42px;
--sidebar-w: 288px;
--sidebar-collapsed-w: 68px;
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}
html {
color-scheme: dark;
}
body {
font-family: var(--font-sans);
background:
radial-gradient(1200px 600px at 10% -10%, rgba(52, 211, 153, 0.08), transparent 55%),
radial-gradient(900px 500px at 100% 0%, rgba(45, 212, 191, 0.06), transparent 50%),
var(--bg-primary);
letter-spacing: -0.01em;
-webkit-font-smoothing: antialiased;
}
/* ─── Titlebar ─── */
#titlebar {
height: var(--titlebar-h);
background: var(--bg-glass);
border-bottom: 1px solid var(--border-color);
backdrop-filter: blur(16px) saturate(1.4);
-webkit-backdrop-filter: blur(16px) saturate(1.4);
padding: 0 12px 0 8px;
gap: 0;
display: flex;
align-items: center;
justify-content: space-between;
-webkit-app-region: drag;
overflow: visible;
z-index: 1100;
}
#titlebar > * {
-webkit-app-region: no-drag;
}
/* Left cluster: window controls + brand (never overlap) */
#titlebar .titlebar-left {
display: flex;
align-items: center;
gap: 10px;
flex: 0 1 auto;
min-width: 0;
max-width: 55%;
z-index: 2;
}
/* Pear window controls — reserve space so brand never sits under traffic lights */
#titlebar pear-ctrl {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: flex-start;
position: relative;
z-index: 5;
line-height: 0;
min-width: 54px;
min-height: 28px;
margin: 0;
padding: 0 4px;
overflow: visible;
-webkit-app-region: no-drag;
}
#titlebar pear-ctrl[data-platform='darwin'] {
min-width: 78px;
margin: 0 8px 0 8px;
margin-top: 0 !important;
margin-left: 8px !important;
}
#titlebar pear-ctrl[data-platform='linux'],
#titlebar pear-ctrl[data-platform='win32'] {
min-width: 110px;
}
#titlebar .app-brand {
display: flex;
align-items: center;
gap: 8px;
pointer-events: none;
-webkit-app-region: no-drag;
margin-left: 4px;
min-width: 0;
flex-shrink: 1;
position: relative;
z-index: 1;
}
#titlebar .titlebar-right {
display: flex;
align-items: center;
gap: 10px;
flex: 0 0 auto;
margin-left: auto;
max-width: 50%;
z-index: 2;
}
#titlebar .notification-tray {
margin-left: 0;
position: relative;
flex-shrink: 0;
}
#titlebar .connection-health-badge,
#titlebar #active-peer-chip {
flex-shrink: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#titlebar .app-brand-mark {
width: 22px;
height: 22px;
border-radius: 6px;
display: grid;
place-items: center;
overflow: hidden;
flex-shrink: 0;
background: transparent;
box-shadow: none;
}
#titlebar .app-brand-mark img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
}
#titlebar .app-brand-text {
font-size: 13px;
font-weight: 650;
color: var(--text-primary);
letter-spacing: -0.02em;
}
#titlebar .app-brand-text span {
color: var(--text-secondary);
font-weight: 500;
margin-left: 6px;
font-size: 12px;
}
/* ─── Sidebar ─── */
#sidebar {
position: fixed;
top: var(--titlebar-h);
left: 0;
height: calc(100vh - var(--titlebar-h));
width: var(--sidebar-w);
background: linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
border-right: 1px solid var(--border-color);
box-shadow: none;
display: flex;
flex-direction: column;
/* Never scroll the whole sidebar — nav and peer list scroll independently */
overflow: hidden;
z-index: 1000;
}
/* ─── Collapsed sidebar = clean icon rail ─── */
#sidebar.collapsed {
width: var(--sidebar-collapsed-w);
}
#sidebar.collapsed .content {
padding: 48px 6px 10px;
align-items: stretch;
}
/* Expand control sits centered at top of the rail */
#sidebar.collapsed #collapse-sidebar-btn {
top: 10px;
left: 50%;
right: auto;
transform: translateX(-50%);
width: 40px;
height: 32px;
border-radius: 10px;
z-index: 12;
}
#sidebar.collapsed #collapse-sidebar-btn:hover {
transform: translateX(-50%);
color: var(--accent-primary);
border-color: rgba(52, 211, 153, 0.35);
}
/* Hide every text label / section chrome in the rail */
#sidebar.collapsed .sidebar-section-label,
#sidebar.collapsed .nav-group-label,
#sidebar.collapsed .nav-label,
#sidebar.collapsed .sidebar-nav-scroll > .sidebar-section-label,
#sidebar.collapsed .sidebar-nav-scroll kbd,
#sidebar.collapsed .connection-name,
#sidebar.collapsed .connection-item small,
#sidebar.collapsed .connection-meta,
#sidebar.collapsed .open-add-connection-label,
#sidebar.collapsed .sidebar-divider,
#sidebar.collapsed .sidebar-footer .sidebar-divider,
#sidebar.collapsed .docker-terminal-btn,
#sidebar.collapsed .disconnect-btn,
#sidebar.collapsed .connection-actions {
display: none !important;
}
#sidebar.collapsed .sidebar-nav-scroll {
width: 100%;
padding: 0;
padding-right: 0;
scrollbar-gutter: auto;
display: flex;
flex-direction: column;
align-items: stretch;
overflow-x: hidden;
}
#sidebar.collapsed .nav-menu {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
margin: 0;
width: 100%;
padding: 0;
}
#sidebar.collapsed .nav-item {
margin: 0;
width: 100%;
display: flex;
justify-content: center;
}
/* Square icon buttons */
#sidebar.collapsed .nav-link {
width: 44px;
height: 40px;
min-width: 44px;
padding: 0;
margin: 0 auto;
justify-content: center;
align-items: center;
gap: 0;
border-radius: 11px;
box-sizing: border-box;
}
#sidebar.collapsed .nav-link i {
width: auto;
margin: 0;
font-size: 1.05rem;
line-height: 1;
opacity: 0.95;
}
#sidebar.collapsed .nav-link:hover {
background: var(--bg-hover);
color: var(--text-primary);
transform: none;
}
#sidebar.collapsed .nav-link.active {
background: rgba(52, 211, 153, 0.14);
color: var(--accent-primary);
box-shadow: inset 0 0 0 1px rgba(52, 211, 153, 0.32);
border-left: none;
}
/* Footer: quick-add + peers shortcut (list is on Peers view) */
#sidebar.collapsed .sidebar-footer {
width: 100%;
margin-top: auto;
padding: 8px 0 4px;
background: linear-gradient(180deg, transparent 0%, rgba(15, 19, 26, 0.9) 40%);
display: flex;
flex-direction: column;
align-items: center;
overflow: visible;
}
#sidebar.collapsed .connections-panel {
width: 100%;
align-items: center;
overflow: visible;
padding: 0;
gap: 6px;
}
#sidebar.collapsed .connections-panel--compact {
padding: 0;
}
#sidebar.collapsed .open-add-connection-btn {
width: 40px;
height: 36px;
min-width: 40px;
padding: 0;
border-radius: 10px;
justify-content: center;
gap: 0;
font-size: 14px;
}
#sidebar.collapsed .open-add-connection-label {
display: none;
}
#sidebar.collapsed .connection-item {
width: 100%;
height: 100%;
padding: 0 !important;
justify-content: center;
align-items: center;
gap: 0;
}
#sidebar.collapsed .connection-info {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
flex: none;
overflow: visible;
cursor: pointer;
}
#sidebar.collapsed .connection-title-row {
justify-content: center;
align-items: center;
gap: 0;
width: auto;
}
#sidebar.collapsed .connection-status {
margin: 0 !important;
width: 11px;
height: 11px;
flex-shrink: 0;
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.04), 0 0 10px currentColor;
}
#content {
margin-left: var(--sidebar-w);
margin-top: var(--titlebar-h);
height: calc(100vh - var(--titlebar-h));
background: transparent;
overflow: hidden;
display: flex;
flex-direction: column;
position: relative;
}
#content > #welcome-page {
margin: auto;
}
#content > #dashboard,
#content > .view {
flex: 1;
min-height: 0;
}
#sidebar.collapsed ~ #content {
margin-left: var(--sidebar-collapsed-w);
}
#collapse-sidebar-btn {
top: 12px;
right: 12px;
width: 30px;
height: 30px;
border-radius: 8px;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
color: var(--text-secondary);
font-size: 12px;
}
#collapse-sidebar-btn:hover {
color: var(--accent-primary);
border-color: rgba(52, 211, 153, 0.35);
transform: none;
}
#sidebar .content {
flex: 1 1 auto;
padding: 16px 14px 10px;
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
max-height: 100%;
overflow: hidden;
}
/* Only the nav region scrolls — peers stay docked at the bottom */
.sidebar-nav-scroll {
flex: 1 1 auto;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
padding-right: 2px;
padding-bottom: 8px;
scrollbar-gutter: stable;
}
.sidebar-section-label {
font-size: 11px;
font-weight: 650;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin: 8px 8px 10px;
}
.nav-menu {
margin-bottom: 8px;
}
.nav-link {
gap: 12px;
padding: 10px 12px;
border-radius: 10px;
color: var(--text-secondary);
font-weight: 500;
font-size: 13.5px;
}
.nav-link i {
width: 18px;
opacity: 0.9;
}
.nav-link:hover {
background: var(--bg-hover);
color: var(--text-primary);
transform: none;
}
.nav-link.active {
background: linear-gradient(90deg, rgba(52, 211, 153, 0.16), rgba(52, 211, 153, 0.04));
color: var(--accent-primary);
border-left: none;
box-shadow: inset 0 0 0 1px rgba(52, 211, 153, 0.18);
}
.sidebar-divider {
border: none;
height: 1px;
background: var(--border-color);
margin: 8px 4px 10px;
opacity: 1;
flex: 0 0 auto;
}
/*
* Footer docked to the bottom of the sidebar (not in the nav scroll).
* Peer list grows upward until 4 rows, then scrolls inside the footer.
*/
.sidebar-footer {
flex: 0 0 auto;
margin-top: auto;
padding-top: 4px;
background: linear-gradient(180deg, transparent 0%, var(--bg-secondary) 28%);
border-top: 0;
z-index: 2;
}
.connections-panel {
--peer-row-h: 54px;
--peer-row-gap: 8px;
--peer-list-max-visible: 4;
--peer-list-max-h: calc(
(var(--peer-list-max-visible) * var(--peer-row-h)) +
((var(--peer-list-max-visible) - 1) * var(--peer-row-gap))
);
flex: 0 0 auto;
display: flex;
flex-direction: column;
margin-top: 0;
padding-top: 0;
padding-bottom: 4px;
overflow: hidden;
max-height: none;
}
/* Compact sidebar footer: Add peer + open Peers view (list lives in Peers tab) */
.connections-panel--compact {
padding: 0 6px 6px;
gap: 6px;
overflow: visible;
}
.connections-panel--compact .open-add-connection-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 36px;
border-radius: 10px;
font-weight: 600;
}
/* Peers view full list */
#peers-view .peers-connection-list,
.peers-connection-list {
max-height: none !important;
overflow: visible !important;
display: flex;
flex-direction: column;
gap: 8px;
padding: 0;
margin: 0;
background: transparent;
}
#peers-view .peers-connection-list .list-group-item {
border-radius: 12px !important;
border: 1px solid var(--border-color) !important;
background: var(--bg-tertiary) !important;
margin: 0 !important;
padding: 12px 14px !important;
width: 100% !important;
max-width: none !important;
height: auto !important;
max-height: none !important;
}
#peers-view .peers-connection-list .list-group-item:hover {
background: var(--bg-hover) !important;
border-color: rgba(52, 211, 153, 0.35) !important;
}
#peers-view .peers-connection-list .list-group-item.active {
border-color: rgba(52, 211, 153, 0.55) !important;
box-shadow: 0 0 0 1px rgba(52, 211, 153, 0.25), 0 8px 24px rgba(0, 0, 0, 0.25);
background: rgba(52, 211, 153, 0.1) !important;
}
#peers-view .connection-item {
gap: 12px;
width: 100%;
}
#peers-view .connection-name {
max-width: none !important;
font-size: 0.95rem;
overflow: visible;
text-overflow: unset;
white-space: normal;
}
#peers-view .connection-meta {
display: block !important;
white-space: normal;
}
.connections-panel-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
padding: 0 2px;
flex: 0 0 auto;
}
.connections-panel-header .sidebar-section-label {
margin: 0;
}
.open-add-connection-btn {
display: inline-flex;
align-items: center;
gap: 6px;
border-radius: 8px;
font-weight: 600;
font-size: 12px;
padding: 4px 10px;
flex-shrink: 0;
}
#connection-list {
flex: 0 1 auto;
height: auto;
max-height: var(--peer-list-max-h);
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 0 2px 0;
margin-bottom: 0 !important;
list-style: none;
scrollbar-gutter: stable;
}
#connection-list .list-group-item {
display: flex;
align-items: stretch;
width: 100%;
max-width: 100%;
height: var(--peer-row-h);
max-height: var(--peer-row-h);
background: var(--bg-elevated);
border: 1px solid var(--border-color);
border-radius: 12px;
margin-bottom: var(--peer-row-gap);
padding: 0;
overflow: hidden;
min-width: 0;
box-sizing: border-box;
}
#connection-list .list-group-item:last-child {
margin-bottom: 0;
}
#connection-list .list-group-item:hover {
transform: none;
border-color: rgba(52, 211, 153, 0.35);
box-shadow: var(--shadow-glow);
}
#connection-list .list-group-item.active {
background: rgba(52, 211, 153, 0.1);
border-color: rgba(52, 211, 153, 0.4);
}
/* Peer row: name truncates; action buttons never overflow */
.connection-item {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
height: 100%;
min-width: 0;
max-width: 100%;
padding: 8px 10px !important;
border: none !important;
background: transparent !important;
box-sizing: border-box;
}
.connection-item .connection-info {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
cursor: pointer;
}
.connection-item .connection-title-row {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.connection-item .connection-name {
display: block;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 600;
font-size: 13px;
line-height: 1.25;
}
.connection-item .connection-meta {
display: block;
margin-left: 22px;
margin-top: 2px;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 10px;
line-height: 1.2;
color: var(--text-muted);
font-family: var(--font-mono);
}
.connection-item .connection-actions {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
gap: 4px;
}
.connection-item .connection-actions .btn {
width: 30px;
height: 30px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
}
#addConnectionModal .form-control {
font-size: 13px;
}
#addConnectionModal .font-monospace {
letter-spacing: -0.02em;
}
/* ─── Content / views ─── */
.view {
margin-top: 0 !important;
padding: 20px 24px 28px !important;
/* Flex child of #content: fill available height and scroll internally */
flex: 1 1 auto;
height: auto !important;
max-height: 100%;
min-height: 0;
width: 100%;
max-width: 100%;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
.view > .container-fluid {
width: 100%;
max-width: 100%;
min-width: 0;
/* Avoid Bootstrap gutters + padding stacking into horizontal scroll */
padding-left: 0;
padding-right: 0;
padding-bottom: 8px;
}
.view .row {
--bs-gutter-x: 0.9rem;
--bs-gutter-y: 0.9rem;
max-width: 100%;
margin-left: 0;
margin-right: 0;
}
.view .row > [class*='col'] {
min-width: 0;
max-width: 100%;
}
/* ═══════════════════════════════════════════════════════════
Dashboard redesign — modern fit-to-viewport shell
═══════════════════════════════════════════════════════════ */
#dashboard-view.view {
display: flex !important;
flex-direction: column;
overflow: hidden !important;
height: 100% !important;
max-height: 100%;
min-height: 0;
padding: 0 !important;
background:
radial-gradient(900px 420px at 8% -10%, rgba(52, 211, 153, 0.1), transparent 55%),
radial-gradient(700px 360px at 100% 0%, rgba(56, 189, 248, 0.07), transparent 50%),
transparent;
}
#dashboard-view.hidden {
display: none !important;
}
#dashboard-view .dashboard-layout.dash {
flex: 1 1 auto;
min-height: 0;
height: 100%;
max-height: 100%;
display: grid;
grid-template-rows: auto auto minmax(0, 1fr) auto;
gap: 14px;
width: 100%;
max-width: 100%;
overflow: hidden;
padding: 18px 22px 16px;
box-sizing: border-box;
}
/* Header */
.dash-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
min-width: 0;
}
.dash-kicker {
margin: 0 0 2px;
font-size: 11px;
font-weight: 650;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--accent-primary);
}
.dash-title {
margin: 0;
font-size: 1.55rem;
font-weight: 750;
letter-spacing: -0.03em;
color: var(--text-primary);
line-height: 1.15;
}
.dash-subtitle {
margin: 4px 0 0;
font-size: 13px;
color: var(--text-muted);
line-height: 1.4;
}
.dash-header-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.dash-icon-btn {
width: 36px;
height: 36px;
border-radius: 10px;
border: 1px solid var(--border-color);
background: rgba(26, 34, 46, 0.85);
color: var(--text-secondary);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.dash-icon-btn:hover {
color: var(--accent-primary);
border-color: rgba(52, 211, 153, 0.4);
background: rgba(52, 211, 153, 0.08);
}
.dash-icon-btn--sm {
width: 30px;
height: 30px;
border-radius: 8px;
font-size: 12px;
}
.dash-chip-btn {
display: inline-flex;
align-items: center;
gap: 8px;
height: 36px;
padding: 0 14px;
border-radius: 999px;
border: none;
cursor: pointer;
font-weight: 650;
font-size: 13px;
color: #052e1c;
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
box-shadow: 0 6px 20px rgba(52, 211, 153, 0.25);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.dash-chip-btn:hover {
transform: translateY(-1px);
box-shadow: 0 8px 24px rgba(52, 211, 153, 0.35);
}
/* KPI strip */
.dash-kpis {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
min-width: 0;
}
.dash-kpi {
position: relative;
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
padding: 14px 16px;
border-radius: 16px;
border: 1px solid var(--border-color);
background:
linear-gradient(145deg, rgba(26, 34, 46, 0.95), rgba(15, 19, 26, 0.9));
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
overflow: hidden;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.dash-kpi:hover {
border-color: rgba(52, 211, 153, 0.28);
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28), 0 0 0 1px rgba(52, 211, 153, 0.08);
}
.dash-kpi-icon {
width: 42px;
height: 42px;
border-radius: 12px;
display: grid;
place-items: center;
flex-shrink: 0;
font-size: 15px;
}
.dash-kpi--ok .dash-kpi-icon {
background: rgba(74, 222, 128, 0.14);
color: #4ade80;
}
.dash-kpi--stop .dash-kpi-icon {
background: rgba(248, 113, 113, 0.14);
color: #f87171;
}
.dash-kpi--info .dash-kpi-icon {
background: rgba(56, 189, 248, 0.14);
color: #38bdf8;
}
.dash-kpi--teal .dash-kpi-icon {
background: rgba(45, 212, 191, 0.14);
color: #2dd4bf;
}
.dash-kpi-meta {
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.dash-kpi-label {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-muted);
}
.dash-kpi-value {
font-size: 1.65rem;
font-weight: 750;
letter-spacing: -0.03em;
line-height: 1.05;
color: var(--text-primary);
font-variant-numeric: tabular-nums;
}
.dash-kpi-glow {
position: absolute;
right: -20%;
top: -40%;
width: 90px;
height: 90px;
border-radius: 50%;
opacity: 0.18;
pointer-events: none;
filter: blur(8px);
}
.dash-kpi--ok .dash-kpi-glow { background: #4ade80; }
.dash-kpi--stop .dash-kpi-glow { background: #f87171; }
.dash-kpi--info .dash-kpi-glow { background: #38bdf8; }
.dash-kpi--teal .dash-kpi-glow { background: #2dd4bf; }
/* Panels */
.dash-panels {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
gap: 12px;
min-height: 0;
overflow: hidden;
}
.dash-card {
min-width: 0;
min-height: 0;
height: 100%;
display: flex;
flex-direction: column;
border-radius: 16px;
border: 1px solid var(--border-color);
background:
linear-gradient(180deg, rgba(26, 34, 46, 0.92) 0%, rgba(15, 19, 26, 0.88) 100%);
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
overflow: hidden;
}
.dash-card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding: 12px 14px 8px;
flex: 0 0 auto;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.dash-card-title {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 12.5px;
font-weight: 650;
letter-spacing: 0.02em;
color: var(--text-primary);
}
.dash-card-title i {
color: var(--accent-primary);
font-size: 12px;
opacity: 0.95;
}
.dash-card-body {
flex: 1 1 auto;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 10px 14px 14px;
font-size: 13px;
}
.dash-empty {
color: var(--text-muted);
font-size: 12.5px;
padding: 18px 4px;
text-align: center;
}
/* Metric rows inside cards */
.dash-metric {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 7px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.045);
min-width: 0;
}
.dash-metric:last-child {
border-bottom: none;
}
.dash-metric-label {
color: var(--text-muted);
font-size: 12px;
flex: 0 1 auto;
min-width: 0;
}
.dash-metric-value {
color: var(--text-primary);
font-weight: 600;
font-size: 12.5px;
text-align: right;
min-width: 0;
overflow-wrap: anywhere;
word-break: break-word;
font-variant-numeric: tabular-nums;
}
/* Disk usage bars */
.dash-disk-row {
display: grid;
gap: 4px;
padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.045);
}
.dash-disk-row:last-child {
border-bottom: none;
}
.dash-disk-top {
display: flex;
justify-content: space-between;
gap: 10px;
font-size: 12px;
}
.dash-disk-top span {
color: var(--text-muted);
}
.dash-disk-top strong {
color: var(--text-primary);
font-weight: 650;
font-variant-numeric: tabular-nums;
}
.dash-disk-bar {
height: 6px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.06);
overflow: hidden;
}
.dash-disk-bar > i {
display: block;
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
min-width: 0;
max-width: 100%;
}
/* Events */
.dash-events.events-timeline {
max-height: none !important;
height: 100%;
min-height: 0;
font-size: 0.72rem;
}
#dashboard-view .events-timeline .event-row {
grid-template-columns: 58px minmax(48px, 64px) minmax(0, 1fr);
gap: 6px;
padding: 6px 4px;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 6px;
}
#dashboard-view .events-timeline .event-row:hover {
background: rgba(255, 255, 255, 0.03);
}
/* Skeleton */
.dash-skeleton {
display: grid;
gap: 10px;
padding: 6px 0;
}
.dash-skel-line {
height: 12px;
border-radius: 6px;
background: linear-gradient(
90deg,
rgba(255, 255, 255, 0.04),
rgba(255, 255, 255, 0.09),
rgba(255, 255, 255, 0.04)
);
background-size: 200% 100%;
animation: dashShimmer 1.2s ease-in-out infinite;
}
.dash-skel-line.short {
width: 55%;
}
@keyframes dashShimmer {
0% { background-position: 100% 0; }
100% { background-position: -100% 0; }
}
/* Actions dock */
.dash-actions {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
min-width: 0;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid var(--border-color);
background: rgba(15, 19, 26, 0.75);
backdrop-filter: blur(10px);
}
.dash-actions-label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11px;
font-weight: 650;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-muted);
flex-shrink: 0;
}
.dash-actions-label i {
color: var(--accent-primary);
}
.dash-actions-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
min-width: 0;
flex: 1 1 auto;
}
.dash-action {
display: inline-flex;
align-items: center;
gap: 7px;
height: 32px;
padding: 0 12px;
border-radius: 999px;
border: 1px solid var(--border-color);
background: rgba(26, 34, 46, 0.9);
color: var(--text-secondary);
font-size: 12.5px;
font-weight: 600;
cursor: pointer;
transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
white-space: nowrap;
}
.dash-action:hover {
color: var(--text-primary);
border-color: rgba(52, 211, 153, 0.4);
background: rgba(52, 211, 153, 0.1);
}
.dash-action--warn {
border-color: rgba(251, 191, 36, 0.25);
color: #fbbf24;
}
.dash-action--warn:hover {
border-color: rgba(251, 191, 36, 0.5);
background: rgba(251, 191, 36, 0.1);
color: #fcd34d;
}
.dash-action--danger {
border-color: rgba(248, 113, 113, 0.35);
color: #fca5a5;
}
.dash-action--danger:hover {
border-color: rgba(248, 113, 113, 0.55);
background: rgba(248, 113, 113, 0.12);
color: #fecaca;
}
/* Compat: key-value blocks injected by JS map to metric style */
#dashboard-view .key-value {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
padding: 7px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.045);
min-width: 0;
}
#dashboard-view .key-value:last-child {
border-bottom: none;
}
#dashboard-view .key-value .key,
#dashboard-view .key-value > span:first-child {
color: var(--text-muted);
font-size: 12px;
}
#dashboard-view .key-value .value,
#dashboard-view .key-value strong {
color: var(--text-primary);
font-weight: 600;
font-size: 12.5px;
text-align: right;
min-width: 0;
overflow-wrap: anywhere;
}
@media (max-width: 1100px) {
.dash-kpis {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 900px) {
#dashboard-view.view {
overflow-y: auto !important;
}
#dashboard-view .dashboard-layout.dash {
grid-template-rows: auto auto auto auto;
height: auto;
max-height: none;
overflow: visible;
}
.dash-panels {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: none;
overflow: visible;
}
.dash-card {
min-height: 180px;
}
}
@media (prefers-reduced-motion: reduce) {
.dash-skel-line {
animation: none;
}
.dash-chip-btn:hover {
transform: none;
}
}
.page-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
margin-bottom: 22px;
flex-wrap: wrap;
min-width: 0;
max-width: 100%;
}
.page-header h2 {
font-size: 1.5rem;
font-weight: 700;
letter-spacing: -0.03em;
margin: 0 0 4px;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 10px;
}
.page-header h2 i {
color: var(--accent-primary);
font-size: 1.15rem;
}
.page-header .page-subtitle {
margin: 0;
color: var(--text-muted);
font-size: 13px;
}
/* ─── Welcome ─── */
#welcome-page {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
position: relative;
top: auto;
left: auto;
transform: none;
max-width: 720px;
width: min(720px, 92%);
margin: auto;
padding: 40px 36px;
background:
linear-gradient(160deg, rgba(52, 211, 153, 0.1) 0%, rgba(15, 19, 26, 0.9) 45%),
var(--bg-elevated);
border: 1px solid var(--border-strong);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-lg), 0 0 80px rgba(52, 211, 153, 0.08);
animation: welcomeIn 0.55s ease-out;
}
/* Must beat base #welcome-page { display:flex } from styles.css */
#welcome-page.hidden,
#welcome-page[hidden],
#welcome-page.is-hidden {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
animation: none !important;
}
@keyframes welcomeIn {
from {
opacity: 0;
transform: translateY(12px) scale(0.98);
}
to {
opacity: 1;
transform: none;
}
}
#welcome-page h1 {
font-size: clamp(2rem, 4vw, 2.75rem);
font-weight: 800;
letter-spacing: -0.04em;
margin-bottom: 12px;
}
#welcome-page .welcome-lead {
font-size: 1.05rem;
color: var(--text-secondary);
margin-bottom: 28px;
line-height: 1.7;
}
.welcome-steps {
display: grid;
gap: 12px;
text-align: left;
margin-top: 8px;
}
.welcome-step {
display: flex;
gap: 14px;
align-items: flex-start;
padding: 14px 16px;
border-radius: 12px;
background: rgba(255, 255, 255, 0.03);
border: 1px solid var(--border-color);
}
.welcome-step-num {
flex-shrink: 0;
width: 28px;
height: 28px;
border-radius: 8px;
display: grid;
place-items: center;
font-size: 12px;
font-weight: 700;
color: #052e1c;
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
}
.welcome-step strong {
display: block;
color: var(--text-primary);
font-size: 13.5px;
margin-bottom: 2px;
}
.welcome-step span {
color: var(--text-muted);
font-size: 12.5px;
line-height: 1.5;
}
.welcome-mono {
font-family: var(--font-mono);
font-size: 11.5px;
color: var(--accent-secondary);
}
/* ─── Cards & stats ─── */
.stat-card,
.info-card {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, transparent 100%), var(--bg-elevated);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
box-shadow: var(--shadow-sm);
}
.stat-card:hover,
.info-card:hover {
border-color: rgba(52, 211, 153, 0.28);
box-shadow: var(--shadow-glow);
transform: translateY(-1px);
}
.stat-card-value {
font-variant-numeric: tabular-nums;
font-weight: 700;
letter-spacing: -0.03em;
}
/* ─── Bootstrap dark polish ─── */
.btn {
border-radius: 10px;
font-weight: 600;
font-size: 13px;
letter-spacing: -0.01em;
transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.btn-primary {
--bs-btn-bg: #10b981;
--bs-btn-border-color: #10b981;
--bs-btn-hover-bg: #059669;
--bs-btn-hover-border-color: #059669;
--bs-btn-active-bg: #047857;
--bs-btn-active-border-color: #047857;
--bs-btn-color: #042f1a;
--bs-btn-hover-color: #042f1a;
--bs-btn-active-color: #042f1a;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.12) inset, 0 6px 16px rgba(16, 185, 129, 0.25);
}
.btn-outline-primary {
--bs-btn-color: #6ee7b7;
--bs-btn-border-color: rgba(52, 211, 153, 0.55);
--bs-btn-hover-bg: rgba(52, 211, 153, 0.18);
--bs-btn-hover-border-color: var(--accent-primary);
--bs-btn-hover-color: #ecfdf5;
--bs-btn-active-bg: rgba(52, 211, 153, 0.28);
--bs-btn-active-border-color: var(--accent-primary);
--bs-btn-active-color: #ecfdf5;
--bs-btn-disabled-color: rgba(110, 231, 183, 0.4);
--bs-btn-disabled-border-color: rgba(52, 211, 153, 0.25);
background: transparent;
color: #6ee7b7;
border-color: rgba(52, 211, 153, 0.55);
}
.btn-outline-primary:hover,
.btn-outline-primary:focus {
background: rgba(52, 211, 153, 0.18) !important;
color: #ecfdf5 !important;
border-color: var(--accent-primary) !important;
}
.btn-secondary {
--bs-btn-bg: var(--bg-tertiary);
--bs-btn-border-color: var(--border-strong);
--bs-btn-color: var(--text-primary);
--bs-btn-hover-bg: var(--bg-hover);
--bs-btn-hover-border-color: var(--border-strong);
--bs-btn-hover-color: var(--text-primary);
--bs-btn-active-bg: var(--bg-hover);
--bs-btn-active-color: var(--text-primary);
color: var(--text-primary);
background: var(--bg-tertiary);
border-color: var(--border-strong);
}
.btn-outline-secondary {
--bs-btn-color: var(--text-secondary);
--bs-btn-border-color: rgba(148, 163, 184, 0.45);
--bs-btn-hover-bg: rgba(148, 163, 184, 0.12);
--bs-btn-hover-border-color: rgba(148, 163, 184, 0.65);
--bs-btn-hover-color: var(--text-primary);
--bs-btn-active-bg: rgba(148, 163, 184, 0.18);
--bs-btn-active-color: var(--text-primary);
--bs-btn-disabled-color: var(--text-faint);
background: transparent;
color: var(--text-secondary);
border-color: rgba(148, 163, 184, 0.45);
}
.btn-outline-secondary:hover,
.btn-outline-secondary:focus {
background: rgba(148, 163, 184, 0.12) !important;
color: var(--text-primary) !important;
border-color: rgba(148, 163, 184, 0.65) !important;
}
/* Semantic outline buttons — avoid Bootstrap light-on-dark defaults */
.btn-outline-success {
--bs-btn-color: #86efac;
--bs-btn-border-color: rgba(74, 222, 128, 0.5);
--bs-btn-hover-bg: rgba(74, 222, 128, 0.16);
--bs-btn-hover-border-color: #4ade80;
--bs-btn-hover-color: #ecfdf5;
--bs-btn-active-bg: rgba(74, 222, 128, 0.24);
--bs-btn-active-color: #ecfdf5;
background: transparent;
color: #86efac;
border-color: rgba(74, 222, 128, 0.5);
}
.btn-outline-success:hover,
.btn-outline-success:focus {
background: rgba(74, 222, 128, 0.16) !important;
color: #ecfdf5 !important;
border-color: #4ade80 !important;
}
.btn-outline-danger {
--bs-btn-color: #fca5a5;
--bs-btn-border-color: rgba(248, 113, 113, 0.55);
--bs-btn-hover-bg: rgba(248, 113, 113, 0.16);
--bs-btn-hover-border-color: #f87171;
--bs-btn-hover-color: #fef2f2;
--bs-btn-active-bg: rgba(248, 113, 113, 0.24);
--bs-btn-active-color: #fef2f2;
background: transparent;
color: #fca5a5;
border-color: rgba(248, 113, 113, 0.55);
}
.btn-outline-danger:hover,
.btn-outline-danger:focus {
background: rgba(248, 113, 113, 0.16) !important;
color: #fef2f2 !important;
border-color: #f87171 !important;
}
.btn-outline-warning {
--bs-btn-color: #fcd34d;
--bs-btn-border-color: rgba(251, 191, 36, 0.5);
--bs-btn-hover-bg: rgba(251, 191, 36, 0.14);
--bs-btn-hover-border-color: #fbbf24;
--bs-btn-hover-color: #fffbeb;
--bs-btn-active-bg: rgba(251, 191, 36, 0.22);
--bs-btn-active-color: #fffbeb;
background: transparent;
color: #fcd34d;
border-color: rgba(251, 191, 36, 0.5);
}
.btn-outline-warning:hover,
.btn-outline-warning:focus {
background: rgba(251, 191, 36, 0.14) !important;
color: #fffbeb !important;
border-color: #fbbf24 !important;
}
.btn-outline-info {
--bs-btn-color: #7dd3fc;
--bs-btn-border-color: rgba(56, 189, 248, 0.5);
--bs-btn-hover-bg: rgba(56, 189, 248, 0.14);
--bs-btn-hover-border-color: #38bdf8;
--bs-btn-hover-color: #f0f9ff;
--bs-btn-active-bg: rgba(56, 189, 248, 0.22);
--bs-btn-active-color: #f0f9ff;
background: transparent;
color: #7dd3fc;
border-color: rgba(56, 189, 248, 0.5);
}
.btn-outline-info:hover,
.btn-outline-info:focus {
background: rgba(56, 189, 248, 0.14) !important;
color: #f0f9ff !important;
border-color: #38bdf8 !important;
}
.btn-outline-light {
--bs-btn-color: var(--text-secondary);
--bs-btn-border-color: rgba(255, 255, 255, 0.22);
--bs-btn-hover-bg: rgba(255, 255, 255, 0.08);
--bs-btn-hover-border-color: rgba(255, 255, 255, 0.35);
--bs-btn-hover-color: var(--text-primary);
background: transparent;
color: var(--text-secondary);
border-color: rgba(255, 255, 255, 0.22);
}
.btn-outline-light:hover,
.btn-outline-light:focus {
background: rgba(255, 255, 255, 0.08) !important;
color: var(--text-primary) !important;
border-color: rgba(255, 255, 255, 0.35) !important;
}
.btn-success {
--bs-btn-bg: #059669;
--bs-btn-border-color: #059669;
--bs-btn-color: #ecfdf5;
--bs-btn-hover-bg: #047857;
--bs-btn-hover-border-color: #047857;
--bs-btn-hover-color: #ecfdf5;
color: #ecfdf5;
}
.btn-danger {
--bs-btn-bg: #dc2626;
--bs-btn-border-color: #dc2626;
--bs-btn-color: #fef2f2;
--bs-btn-hover-bg: #b91c1c;
--bs-btn-hover-border-color: #b91c1c;
--bs-btn-hover-color: #fef2f2;
color: #fef2f2;
}
.btn-warning {
--bs-btn-bg: #d97706;
--bs-btn-border-color: #d97706;
--bs-btn-color: #fffbeb;
--bs-btn-hover-bg: #b45309;
--bs-btn-hover-border-color: #b45309;
--bs-btn-hover-color: #fffbeb;
color: #fffbeb;
}
.btn-info {
--bs-btn-bg: #0284c7;
--bs-btn-border-color: #0284c7;
--bs-btn-color: #f0f9ff;
--bs-btn-hover-bg: #0369a1;
--bs-btn-hover-border-color: #0369a1;
--bs-btn-hover-color: #f0f9ff;
color: #f0f9ff;
}
/* Filter / pill toggles that use .active on outline buttons */
.btn-outline-primary.active,
.btn-check:checked + .btn-outline-primary,
.image-filter-btn.active {
background: rgba(52, 211, 153, 0.22) !important;
border-color: var(--accent-primary) !important;
color: #ecfdf5 !important;
box-shadow: 0 0 0 1px rgba(52, 211, 153, 0.25);
}
.form-control,
.form-select {
background: var(--bg-tertiary) !important;
border: 1px solid var(--border-color) !important;
color: var(--text-primary) !important;
border-radius: 10px !important;
font-size: 13.5px;
}
.form-control:focus,
.form-select:focus {
border-color: rgba(52, 211, 153, 0.5) !important;
box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.15) !important;
}
.form-control::placeholder,
.form-select::placeholder,
input::placeholder,
textarea::placeholder {
color: var(--text-faint) !important;
opacity: 1 !important;
}
.form-label {
color: var(--text-secondary);
font-weight: 550;
font-size: 12.5px;
margin-bottom: 6px;
}
.table {
--bs-table-bg: transparent;
--bs-table-color: var(--text-primary);
--bs-table-border-color: var(--border-color);
--bs-table-striped-bg: rgba(255, 255, 255, 0.03);
--bs-table-hover-bg: rgba(52, 211, 153, 0.08);
--bs-table-striped-color: var(--text-primary);
--bs-table-hover-color: var(--text-primary);
font-size: 13px;
}
.table thead th {
color: var(--text-secondary);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.06em;
font-weight: 650;
border-bottom-width: 1px;
white-space: nowrap;
}
.table-dark {
--bs-table-color: var(--text-primary);
--bs-table-bg: transparent;
--bs-table-border-color: var(--border-color);
--bs-table-striped-bg: rgba(255, 255, 255, 0.03);
--bs-table-striped-color: var(--text-primary);
--bs-table-hover-bg: rgba(52, 211, 153, 0.08);
--bs-table-hover-color: var(--text-primary);
color: var(--text-primary);
}
.table td,
.table th {
vertical-align: middle;
padding: 12px 14px;
}
.card,
.modal-content {
background: var(--bg-elevated) !important;
border: 1px solid var(--border-color) !important;
border-radius: var(--border-radius) !important;
color: var(--text-primary);
}
.modal-header {
border-bottom-color: var(--border-color) !important;
padding: 16px 20px;
}
.modal-footer {
border-top-color: var(--border-color) !important;
padding: 14px 20px;
}
.modal-title {
font-weight: 650;
letter-spacing: -0.02em;
}
.accordion-item {
background: var(--bg-tertiary) !important;
border-color: var(--border-color) !important;
}
.accordion-button {
background: var(--bg-elevated) !important;
color: var(--text-primary) !important;
font-weight: 550;
box-shadow: none !important;
}
.accordion-button:not(.collapsed) {
color: var(--accent-primary) !important;
background: rgba(52, 211, 153, 0.08) !important;
}
.accordion-button::after {
filter: invert(1) brightness(1.4);
}
.list-group-item {
background: var(--bg-elevated);
border-color: var(--border-color);
color: var(--text-primary);
}
.badge {
font-weight: 600;
letter-spacing: 0.02em;
border-radius: 6px;
}
/* Scrollbars */
* {
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.14);
border-radius: 8px;
}
*::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.24);
}
/* Toolbar / filter bars */
.toolbar,
.filter-bar,
.view-toolbar {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
margin-bottom: 16px;
padding: 12px 14px;
background: var(--bg-elevated);
border: 1px solid var(--border-color);
border-radius: var(--border-radius-sm);
}
/* Terminal */
#terminal-modal {
border-top: 1px solid var(--border-strong);
background: var(--bg-secondary);
box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
}
#terminal-modal .header {
background: var(--bg-elevated);
}
/* Legacy full-screen status spinner removed — activity uses #job-drawer */
/* ─── Toast stack (opt-in only; bottom job tray is primary feedback) ─── */
.toast-stack,
#toast-stack,
#alert-container.toast-stack {
position: fixed;
top: calc(var(--titlebar-h) + 12px);
left: 50%;
transform: translateX(-50%);
z-index: 2600;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
width: min(420px, calc(100vw - 24px));
max-width: 90vw;
pointer-events: none;
/* Hidden unless a toast child is present (forceToast path) */
}
.toast-stack:empty,
#toast-stack:empty {
display: none;
}
.pd-toast {
pointer-events: auto;
display: flex;
align-items: flex-start;
gap: 10px;
width: 100%;
padding: 12px 14px;
border-radius: 12px;
border: 1px solid var(--border-strong);
background: var(--bg-elevated);
box-shadow: var(--shadow-lg);
color: var(--text-primary);
animation: toastIn 0.22s ease-out;
}
.pd-toast--leaving {
opacity: 0;
transform: translateY(-6px);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.pd-toast-icon {
margin-top: 2px;
flex-shrink: 0;
}
.pd-toast--success {
border-color: rgba(74, 222, 128, 0.45);
}
.pd-toast--success .pd-toast-icon { color: var(--accent-success); }
.pd-toast--danger {
border-color: rgba(248, 113, 113, 0.45);
}
.pd-toast--danger .pd-toast-icon { color: var(--accent-danger); }
.pd-toast--warning {
border-color: rgba(251, 191, 36, 0.45);
}
.pd-toast--warning .pd-toast-icon { color: var(--accent-warning); }
.pd-toast--info {
border-color: rgba(56, 189, 248, 0.4);
}
.pd-toast--info .pd-toast-icon { color: var(--accent-info); }
.pd-toast-body {
flex: 1 1 auto;
min-width: 0;
font-size: 13px;
line-height: 1.4;
word-break: break-word;
}
.pd-toast-close {
appearance: none;
border: none;
background: transparent;
color: var(--text-muted);
cursor: pointer;
padding: 2px 4px;
line-height: 1;
border-radius: 6px;
}
.pd-toast-close:hover {
color: var(--text-primary);
background: var(--bg-hover);
}
@keyframes toastIn {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: none;
}
}
.alert {
border-radius: 12px;
border: 1px solid var(--border-strong);
background: var(--bg-elevated);
box-shadow: var(--shadow-md);
}
/* Role-gated controls */
.role-hidden {
display: none !important;
}
/* Container action overflow */
.container-actions {
display: flex;
align-items: center;
gap: 4px;
flex-wrap: nowrap;
justify-content: flex-end;
}
.container-actions-primary {
flex-wrap: nowrap;
}
.container-actions-cell {
white-space: nowrap;
width: 1%;
}
.container-actions .dropdown-menu {
min-width: 10rem;
font-size: 13px;
}
/* Activity history tray */
.activity-tray {
position: relative;
flex-shrink: 0;
}
.activity-panel {
position: absolute;
right: 0;
top: calc(100% + 8px);
width: min(320px, 90vw);
max-height: min(420px, 70vh);
overflow: hidden;
display: flex;
flex-direction: column;
background: var(--bg-elevated);
border: 1px solid var(--border-strong);
border-radius: 12px;
box-shadow: var(--shadow-lg);
z-index: 1200;
}
.activity-panel.hidden {
display: none !important;
}
.activity-panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
border-bottom: 1px solid var(--border-color);
}
.activity-panel-list {
overflow-y: auto;
flex: 1 1 auto;
min-height: 0;
}
.activity-item {
width: 100%;
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: auto auto;
gap: 2px 8px;
text-align: left;
padding: 10px 12px;
border: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
background: transparent;
color: var(--text-primary);
cursor: pointer;
}
.activity-item:hover {
background: var(--bg-hover);
}
.activity-item-kind {
font-weight: 600;
font-size: 13px;
}
.activity-item-meta {
grid-column: 1 / -1;
font-size: 11px;
}
/* First-connect checklist */
.first-connect-checklist {
position: fixed;
inset: 0;
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(5, 8, 12, 0.55);
backdrop-filter: blur(6px);
padding: 20px;
}
.first-connect-checklist.hidden {
display: none !important;
}
.first-connect-card {
width: min(420px, 100%);
background: var(--bg-elevated);
border: 1px solid var(--border-strong);
border-radius: 16px;
padding: 20px 22px;
box-shadow: var(--shadow-lg);
}
.first-connect-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 8px;
}
.first-connect-head h3 {
margin: 0;
font-size: 1.15rem;
font-weight: 700;
}
.first-connect-steps {
margin: 0 0 16px;
padding-left: 1.2rem;
color: var(--text-secondary);
font-size: 13.5px;
line-height: 1.55;
}
.first-connect-link {
appearance: none;
border: none;
background: none;
color: var(--accent-primary);
font-weight: 600;
padding: 0;
cursor: pointer;
text-decoration: underline;
text-underline-offset: 2px;
}
.invite-token-result.hidden {
display: none !important;
}
/* Template list URLs in Settings */
.settings-template-urls {
max-height: 200px;
overflow-y: auto;
border: 1px solid var(--border-color);
border-radius: 10px;
background: var(--bg-elevated);
}
.settings-template-urls .list-group-item {
background: transparent;
border-color: var(--border-color);
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 11.5px;
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
}
.settings-template-urls .list-group-item .url-text {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.settings-template-urls .btn-remove-url {
flex: 0 0 auto;
}
/* Density prefs */
body[data-density='compact'] .table > :not(caption) > * > * {
padding: 0.35rem 0.5rem;
font-size: 12.5px;
}
body[data-density='compact'] .stat-card,
body[data-density='compact'] .info-card {
padding: 8px 10px !important;
}
body[data-density='compact'] .page-header {
margin-bottom: 12px;
}
body[data-density='compact'] .nav-link {
padding: 8px 10px;
font-size: 12.5px;
}
body[data-density='compact'] .connection-item {
padding: 6px 8px !important;
}
/* List search */
.list-search-input {
max-width: 280px;
min-width: 160px;
}
/* Inline empty states inside tables */
.pd-empty--inline {
padding: 20px 12px;
}
.pd-empty--inline .pd-empty-icon {
font-size: 1.4rem;
opacity: 0.65;
margin-bottom: 6px;
color: var(--accent-primary);
}
.pd-empty--inline .pd-empty-title {
font-size: 0.95rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 4px;
}
/* Palette keyboard selection */
.pd-palette-item.is-active,
.pd-palette-item:hover {
background: rgba(52, 211, 153, 0.12);
color: var(--text-primary);
}
/* Focus rings */
:focus-visible {
outline: 2px solid rgba(52, 211, 153, 0.65);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.pd-toast,
.pd-toast--leaving,
.pd-skeleton-row,
.skeleton {
animation: none !important;
transition: none !important;
}
}
/* Notification tray */
.notification-tray-toggle {
border-radius: 10px !important;
}
/* Monospace helpers */
code,
.font-monospace,
pre {
font-family: var(--font-mono) !important;
}
/* Empty states */
.empty-state {
text-align: center;
padding: 48px 24px;
color: var(--text-muted);
}
.empty-state i {
font-size: 2rem;
margin-bottom: 12px;
color: var(--accent-primary);
opacity: 0.7;
}
/* Connection health badge (titlebar) */
.connection-health-badge {
display: flex;
align-items: center;
gap: 10px;
margin-left: auto;
margin-right: 12px;
padding: 4px 12px;
border-radius: 999px;
background: var(--bg-elevated);
border: 1px solid var(--border-color);
font-size: 0.75rem;
color: var(--text-secondary);
font-family: 'JetBrains Mono', ui-monospace, monospace;
max-width: 42vw;
overflow: hidden;
white-space: nowrap;
}
.health-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
background: var(--text-muted);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.06);
}
.health-dot--ok {
background: var(--accent-success);
box-shadow: 0 0 8px rgba(74, 222, 128, 0.55);
}
.health-dot--degraded {
background: var(--accent-warning);
box-shadow: 0 0 8px rgba(251, 191, 36, 0.45);
}
.health-dot--down,
.health-dot--unknown {
background: var(--text-muted);
}
.health-dot--error {
background: var(--accent-danger);
}
.health-role {
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--accent-secondary);
font-size: 0.68rem;
}
.events-timeline {
max-height: 220px;
overflow-x: hidden;
overflow-y: auto;
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 0.72rem;
min-width: 0;
}
.events-timeline .event-row {
display: grid;
grid-template-columns: 64px minmax(56px, 72px) minmax(0, 1fr);
gap: 8px;
padding: 4px 0;
border-bottom: 1px solid var(--border-color);
color: var(--text-secondary);
min-width: 0;
max-width: 100%;
}
.events-timeline .event-row > * {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.events-timeline .event-row .event-action {
color: var(--accent-info);
}
.events-timeline .event-row .event-type {
color: var(--text-muted);
}
/* ─── Readability / contrast fixes (dark theme) ─── */
/* Bootstrap muted utilities are too dim on near-black backgrounds */
.text-muted,
.form-text,
small.text-muted,
.small.text-muted,
.text-body-secondary,
.text-secondary {
color: var(--text-muted) !important;
}
/* Prefer secondary for “helper” copy so it stays scannable */
.page-subtitle,
.info-card-title + .text-muted,
.detail-info-label,
.stat-card-label {
color: var(--text-secondary) !important;
}
code,
pre,
.font-monospace,
kbd {
color: var(--text-primary);
}
kbd {
background: var(--bg-elevated);
border: 1px solid var(--border-strong);
color: var(--text-secondary);
}
/* List groups used for templates / peers */
.list-group-item,
.list-group-item-dark,
.list-group-item-action {
color: var(--text-primary) !important;
background-color: var(--bg-tertiary) !important;
border-color: var(--border-color) !important;
}
.list-group-item .text-muted,
.list-group-item small,
.list-group-item .small {
color: var(--text-muted) !important;
}
.list-group-item-action:hover,
.list-group-item-action:focus {
color: var(--text-primary) !important;
background-color: var(--bg-hover) !important;
}
/* Accordion / forms in modals */
.accordion-body,
.accordion-body .text-muted,
.modal-body,
.modal-body .text-muted,
.modal-content .form-text,
.modal-content small {
color: var(--text-muted);
}
.accordion-body,
.modal-body {
color: var(--text-primary);
}
.accordion-button.collapsed {
color: var(--text-primary) !important;
}
.accordion-button::after {
filter: invert(0.85);
}
/* Bootstrap dark inputs without bg-dark class */
.form-control:not(.bg-dark),
.form-select:not(.bg-dark) {
background: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
}
.form-control.bg-dark,
.form-select.bg-dark,
input.bg-dark,
textarea.bg-dark,
select.bg-dark {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
border-color: var(--border-color) !important;
}
.form-check-label {
color: var(--text-primary);
}
.form-check-input {
background-color: var(--bg-hover);
border-color: var(--border-strong);
}
.form-check-input:checked {
background-color: var(--accent-primary);
border-color: var(--accent-primary);
}
.form-range {
accent-color: var(--accent-primary);
}
/* Disabled controls: still legible, just softer */
.form-control:disabled,
.form-select:disabled,
.btn:disabled,
.form-check-input:disabled + .form-check-label {
color: var(--text-muted) !important;
opacity: 0.85;
}
/* Cards / info panels */
.info-card,
.stat-card,
.settings-section,
.card {
color: var(--text-primary);
}
.info-card-body,
.stat-card-value,
.detail-info-value {
color: var(--text-primary);
}
.page-header h2,
.page-header h1 {
color: var(--text-primary);
}
/* Sidebar labels — solid color instead of low opacity */
.sidebar-section-label,
.nav-group-label {
color: var(--text-muted) !important;
opacity: 1 !important;
}
#sidebar .nav-link {
color: var(--text-secondary);
}
#sidebar .nav-link:hover,
#sidebar .nav-link.active {
color: var(--text-primary);
}
#sidebar .connection-name,
#connection-list .list-group-item {
color: var(--text-primary) !important;
}
#connection-list .text-muted,
#connection-list small {
color: var(--text-muted) !important;
}
/* Health badge & peer chip */
.connection-health-badge,
#health-latency,
#health-docker,
#health-role,
#active-peer-chip,
#active-peer-label {
color: var(--text-secondary);
}
/* Alerts: ensure readable body text */
.alert {
color: var(--text-primary);
}
.alert-success { color: #d1fae5 !important; }
.alert-danger { color: #fee2e2 !important; }
.alert-warning { color: #fef3c7 !important; }
.alert-info { color: #e0f2fe !important; }
/* Badges that Bootstrap greys out */
.badge.bg-secondary {
background-color: #475569 !important;
color: #f8fafc !important;
}
.badge.bg-dark {
background-color: var(--bg-hover) !important;
color: var(--text-primary) !important;
}
/* Dropdown menus */
.dropdown-menu {
background: var(--bg-elevated);
border: 1px solid var(--border-color);
color: var(--text-primary);
}
.dropdown-item {
color: var(--text-primary);
}
.dropdown-item:hover,
.dropdown-item:focus {
background: var(--bg-hover);
color: var(--text-primary);
}
.dropdown-item-text,
.dropdown-header {
color: var(--text-muted);
}
/* Tabs — dark content tabs (not sidebar) */
.nav-tabs {
border-bottom-color: var(--border-color) !important;
gap: 4px;
}
.nav-tabs .nav-link {
color: var(--text-secondary) !important;
background: transparent !important;
border: 1px solid transparent !important;
border-bottom: none !important;
border-radius: 10px 10px 0 0 !important;
font-weight: 600;
font-size: 0.875rem;
padding: 0.5rem 0.95rem;
}
.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
color: var(--text-primary) !important;
background: rgba(255, 255, 255, 0.04) !important;
border-color: transparent !important;
isolation: isolate;
}
.nav-tabs .nav-link.active {
color: var(--text-primary) !important;
background: var(--bg-elevated) !important;
border-color: var(--border-color) var(--border-color) var(--bg-elevated) !important;
border-bottom-color: var(--bg-elevated) !important;
}
/* Pills (settings-style and generic) */
.nav-pills .nav-link {
color: var(--text-secondary) !important;
background: transparent !important;
border: 1px solid var(--border-color);
border-radius: 999px !important;
font-weight: 600;
}
.nav-pills .nav-link:hover {
color: var(--text-primary) !important;
background: rgba(255, 255, 255, 0.05) !important;
border-color: var(--border-strong);
}
.nav-pills .nav-link.active {
color: #042f1a !important;
background: linear-gradient(135deg, #34d399, #2dd4bf) !important;
border-color: transparent !important;
box-shadow: 0 4px 14px rgba(52, 211, 153, 0.28);
}
/* Modal footer buttons stay readable on dark modals */
.modal-content.bg-dark .btn-close-white {
filter: invert(1) grayscale(100%) brightness(200%);
opacity: 0.75;
}
.modal-content.bg-dark .btn-close-white:hover {
opacity: 1;
}
/* List-group dark actions used in Hub search / volume browser */
.list-group-item-dark,
.list-group-item-action.list-group-item-dark {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
border-color: var(--border-color) !important;
}
.list-group-item-action.list-group-item-dark:hover,
.list-group-item-action.list-group-item-dark:focus {
background-color: var(--bg-hover) !important;
color: var(--text-primary) !important;
}
/* Pagination / page links if used */
.page-link {
background-color: var(--bg-tertiary);
border-color: var(--border-color);
color: var(--text-secondary);
}
.page-link:hover {
background-color: var(--bg-hover);
border-color: var(--border-strong);
color: var(--text-primary);
}
.page-item.active .page-link {
background-color: #10b981;
border-color: #10b981;
color: #042f1a;
}
/* Empty / skeleton states */
.pd-empty-body,
.pd-empty {
color: var(--text-muted);
}
.pd-empty-title {
color: var(--text-primary);
}
/* Job panel */
.job-step-label {
color: var(--text-primary);
}
.job-step-detail {
color: var(--text-muted);
}
/* Deploy template list */
.deploy-template-list .fw-bold {
color: var(--text-primary) !important;
}
.deploy-template-list .text-muted {
color: var(--text-muted) !important;
}
/* Welcome / lead copy */
#welcome-page,
#welcome-page h1,
.welcome-lead {
color: var(--text-primary);
}
.welcome-step span,
.welcome-lead {
color: var(--text-secondary);
}
/* Links */
a {
color: var(--accent-secondary);
}
a:hover {
color: var(--accent-primary);
}
/* Select options (native dropdown) */
option {
background: var(--bg-elevated);
color: var(--text-primary);
}
/* Narrow viewports: force the same icon-rail layout as .collapsed */
@media (max-width: 900px) {
#sidebar {
width: var(--sidebar-collapsed-w);
}
#sidebar .content {
padding: 48px 6px 10px;
}
#sidebar #collapse-sidebar-btn {
top: 10px;
left: 50%;
right: auto;
transform: translateX(-50%);
width: 40px;
height: 32px;
}
#sidebar .sidebar-section-label,
#sidebar .nav-group-label,
#sidebar .nav-label,
#sidebar .sidebar-nav-scroll kbd,
#sidebar .connection-name,
#sidebar .connection-meta,
#sidebar .connection-item small,
#sidebar .open-add-connection-label,
#sidebar .sidebar-divider,
#sidebar .docker-terminal-btn,
#sidebar .disconnect-btn,
#sidebar .connection-actions {
display: none !important;
}
#sidebar .nav-menu {
align-items: center;
gap: 2px;
margin: 0;
}
#sidebar .nav-item {
margin: 0;
display: flex;
justify-content: center;
}
#sidebar .nav-link {
width: 44px;
height: 40px;
padding: 0;
justify-content: center;
gap: 0;
border-radius: 11px;
}
#sidebar .nav-link i {
width: auto;
font-size: 1.05rem;
}
#sidebar .connections-panel-header {
justify-content: center;
}
#sidebar .open-add-connection-btn {
width: 40px;
height: 36px;
padding: 0;
justify-content: center;
}
#sidebar #connection-list {
align-items: center;
display: flex;
flex-direction: column;
}
#sidebar #connection-list .list-group-item {
width: 44px;
height: 40px;
max-width: 44px;
padding: 0;
justify-content: center;
border-radius: 11px;
}
#sidebar .connection-item {
padding: 0 !important;
justify-content: center;
}
#sidebar .connection-status {
margin: 0 !important;
}
#content {
margin-left: var(--sidebar-collapsed-w);
}
.view {
padding: 16px !important;
}
.connection-health-badge {
display: none;
}
}