mirror of
https://github.com/PegaProx/project-pegaprox.git
synced 2026-08-12 15:27:47 +08:00
The corporate/modern sidebar rendered every VM in the tree and re-filtered on each keystroke — janky at 100 nodes / 1000+ VMs. Two changes, no behaviour lost: - Debounce (250ms) the term used for FILTERING, name highlighting and the cross-cluster 'N found' match counter, so typing no longer re-filters and re-counts across all clusters/VMs on every keystroke. The <input>, clear-X and its visibility stay bound to the immediate value for instant echo; empty clears synchronously (no lag when wiping the box). - content-visibility:auto on the tree rows = native windowing: the browser skips layout + paint for rows scrolled out of the sidebar's scrollport while keeping them in the DOM, so keyboard nav (querySelectorAll+focus), tooltips, selection and the #vmid ::after all keep working. Moved the one-shot expand fade from each row to the tree container so it no longer replays per row on scroll re-entry (and runs once, not ~1000x). Degrades gracefully where content-visibility is unsupported. Adversarially reviewed across 4 dimensions (debounce correctness, CSS interaction, completeness, regression); coverage unchanged, every VM stays searchable.
3536 lines
208 KiB
Plaintext
3536 lines
208 KiB
Plaintext
<!DOCTYPE html>
|
|
<!--
|
|
PegaProx - Cluster Management for Proxmox VE
|
|
Version: 0.9.0.1 Beta
|
|
Website: https://pegaprox.com
|
|
GitHub: https://github.com/PegaProx/project-pegaprox
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
Copyright (C) 2025-2026 PegaProx Team
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
Development Team:
|
|
- Nico Schmidt (NS) - Lead Developer & Founder
|
|
- Marcus Kellermann (MK) - Backend Developer
|
|
- Laura Weber (LW) - Frontend Developer
|
|
|
|
Contributors:
|
|
- Florian Paul Azim Hoberg @gyptazy
|
|
- Alexandre Derumier @aderumier (Performance chart styling)
|
|
|
|
Started: September 2025
|
|
Last major refactor: January 2026
|
|
License: AGPL-3.0
|
|
|
|
Tech Stack: React 18 + Tailwind CSS (single-file SPA)
|
|
Yeah I know, single file is weird but it actually works great
|
|
for our deployment scenario. Makes updates super easy. - NS
|
|
|
|
Credits:
|
|
- ProxLB by gyptazy (https://github.com/gyptazy/ProxLB)
|
|
Load balancing logic is based on this project. Thanks!
|
|
- ProxSnap by gyptazy (https://github.com/gyptazy/ProxSnap)
|
|
Inspiration for the snapshot overview feature. Great tool!
|
|
|
|
Some parts were optimized with AI assistance (Claude/ChatGPT).
|
|
We've marked those sections. Most of the core logic is hand-written.
|
|
|
|
Contact: sponsor@pegaprox.com (for sponsorship inquiries)
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
TODO (NS): Split into proper components when we have time
|
|
TODO (MK): The API could use some cleanup too tbh
|
|
TODO (LW): Dark mode is the only mode rn, maybe add light theme?
|
|
FIXME (NS): Memory leak somewhere in the console component, low prio
|
|
FIXED (LW): mobile layout works now (Jan 2026)
|
|
|
|
git log --oneline (for reference):
|
|
- b3f7a1d feat(MK): disk bus type editing
|
|
- a2c8e4f feat(LW): EFI disk and TPM management
|
|
- 9e4f3c2 feat: rolling update manager
|
|
- 8f3a2b1 fix: ISO detection in migrate modal
|
|
- 7c91ef4 feat: cross-cluster migration
|
|
- 6d82ab3 fix: websocket reconnect issue (#247)
|
|
- 5e73cd2 refactor: auth system
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
-->
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>PegaProx • Cluster Management for Proxmox VE</title>
|
|
<meta name="google" content="notranslate">
|
|
|
|
<!-- LW May 2026 — preconnect removed. We're local-first now (libs are bundled
|
|
in /static), so the CDN preconnect just stalls DNS on air-gapped networks. -->
|
|
|
|
|
|
<!-- NS: Preload removed - was causing credential mode mismatch warnings -->
|
|
<!-- Scripts are loaded via loadScriptWithFallback which handles this better -->
|
|
|
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
|
|
|
|
<!-- MK May 2026: PWA manifest + theme color for installable web app -->
|
|
<link rel="manifest" href="/manifest.webmanifest">
|
|
<meta name="theme-color" content="#E57000">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<meta name="apple-mobile-web-app-title" content="PegaProx">
|
|
<script>
|
|
// Register service worker as soon as possible. SW handles offline shell + push.
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', function () {
|
|
navigator.serviceWorker.register('/sw.js', { scope: '/' })
|
|
.then(function (reg) { console.log('[PWA] SW registered, scope:', reg.scope); })
|
|
.catch(function (err) { console.warn('[PWA] SW registration failed:', err); });
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<!--
|
|
OFFLINE MODE: For jumphosts / Docker without internet:
|
|
1. Tailwind CSS is now a static build (no CDN needed)
|
|
2. Run: python3 pegaprox_server.py --download-static (downloads React, Babel, fonts, etc.)
|
|
3. Copy 'static' folder to target machine
|
|
|
|
MK: Mar 2026 - reworked for #118, Tailwind is always local now
|
|
-->
|
|
|
|
<!-- Smart Script Loader - CDN first, local fallback for offline -->
|
|
<!-- SRI Hashes for supply chain security - verify these match official releases -->
|
|
<script>
|
|
// NS: Global flag to know when libs are ready
|
|
window.pegaproxLibsReady = false;
|
|
|
|
// SRI Hashes for supply chain security - verify CDN scripts haven't been tampered with
|
|
// IMPORTANT: Update these hashes when upgrading library versions!
|
|
// Generate hashes at: https://www.srihash.org/ or use jsDelivr's ?integrity query
|
|
// Example: curl -s https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js | openssl dgst -sha384 -binary | openssl base64 -A
|
|
// Empty string = skip SRI check (use during development, fill in for production)
|
|
// NS: Mar 2026 - populated SRI hashes for supply chain protection
|
|
// NS: pinned to exact versions so SRI hashes stay stable
|
|
const SRI_HASHES = {
|
|
'react@18.3.1': 'sha384-DGyLxAyjq0f9SPpVevD6IgztCFlnMF6oW/XQGmfe+IsZ8TqEiDrcHkMLKI6fiB/Z',
|
|
'react-dom@18.3.1': 'sha384-gTGxhz21lVGYNMcdJOyq01Edg0jhn/c22nsx0kyqP0TxaV5WVdsSH1fSDUf5YJj1',
|
|
'babel@7.29.2': 'sha384-dqDn4UOhYWNxmtwnMX6yC3WtZZ6Li8rF6rLB7cu0i/R7btvb+p+kObgEHto7VsJK',
|
|
'chart.js@4.5.1': 'sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ',
|
|
'novnc@1.4.0': '', // loaded as ES module, SRI not supported for dynamic import
|
|
'xterm@5.3.0': 'sha384-xjfWUeCWdMtvpAb/SmM6lMzS6pQGcQa0loOl1d97j6Odw0vjK9nW3+dTb/bn/mwH',
|
|
'xterm-addon-fit@0.8.0': 'sha384-dpjGwSSISUTz2taP54Bor7qkyMR20sSO9oe11UVYnGs2/YdUBf7HW30XKQx9PCzn',
|
|
'marked@15.0.7': 'sha384-H+hy9ULve6xfxRkWIh/YOtvDdpXgV2fmAGQkIDTxIgZwNoaoBal14Di2YTMR6MzR',
|
|
'dompurify@3.2.4': 'sha384-eEu5CTj3qGvu9PdJuS+YlkNi7d2XxQROAFYOr59zgObtlcux1ae1Il3u7jvdCSWu'
|
|
};
|
|
|
|
// LW May 2026 — local-first. Air-gapped customers were watching the
|
|
// browser hang on CDN timeouts before the offline fallback kicked in,
|
|
// because navigator.onLine returns true on isolated LANs. Now we
|
|
// always try /static first; CDN only fires if local 404s AND the
|
|
// air-gap flag isn't set. The flag is persisted to localStorage by
|
|
// the auth-check handler in contexts.js.
|
|
var _isAirGapped = function() {
|
|
// NS Jul 2026 (offline): also honour a SESSION-only auto-latch set when
|
|
// the browser turns out to have no internet (navigator.onLine lies on
|
|
// isolated LANs). The backend still injects the persisted flag when
|
|
// air_gap_mode is enabled; this window flag catches "no internet but
|
|
// air-gap not enabled" so lazy modal loaders skip dead CDN fallbacks.
|
|
try { if (window.__pegaproxAirGap === true) return true; } catch (_) {}
|
|
try { return localStorage.getItem('pegaprox-air-gap') === '1'; }
|
|
catch (_) { return false; }
|
|
};
|
|
function loadScriptWithFallback(cdnUrl, localUrl, integrityKey) {
|
|
return new Promise(function(resolve) {
|
|
var local = document.createElement('script');
|
|
local.src = localUrl;
|
|
local.onload = resolve;
|
|
local.onerror = function() {
|
|
if (_isAirGapped()) {
|
|
console.error('[air-gap] local asset missing, refusing CDN fetch:', localUrl);
|
|
resolve();
|
|
return;
|
|
}
|
|
console.warn('Local asset missing, falling back to CDN:', cdnUrl);
|
|
var cdn = document.createElement('script');
|
|
cdn.src = cdnUrl;
|
|
if (integrityKey && SRI_HASHES[integrityKey]) {
|
|
cdn.integrity = SRI_HASHES[integrityKey];
|
|
cdn.crossOrigin = 'anonymous';
|
|
}
|
|
cdn.onload = resolve;
|
|
cdn.onerror = function() {
|
|
console.error('Both local and CDN failed for', localUrl);
|
|
resolve();
|
|
};
|
|
document.head.appendChild(cdn);
|
|
};
|
|
document.head.appendChild(local);
|
|
});
|
|
}
|
|
|
|
// Load in sequence - using jsdelivr instead of unpkg (faster + better caching)
|
|
loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/react@18.3.1/umd/react.production.min.js',
|
|
'/static/js/react.production.min.js',
|
|
'react@18.3.1'
|
|
).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/react-dom@18.3.1/umd/react-dom.production.min.js',
|
|
'/static/js/react-dom.production.min.js',
|
|
'react-dom@18.3.1'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/@babel/standalone@7.29.2/babel.min.js',
|
|
'/static/js/babel.min.js',
|
|
'babel@7.29.2'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js',
|
|
'/static/js/chart.umd.min.js',
|
|
'chart.js@4.5.1'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/marked@15.0.7/marked.min.js',
|
|
'/static/js/marked.min.js',
|
|
'marked@15.0.7'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/dompurify@3.2.4/dist/purify.min.js',
|
|
'/static/js/purify.min.js',
|
|
'dompurify@3.2.4'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js',
|
|
'/static/js/jspdf.umd.min.js',
|
|
'jspdf@2.5.2'
|
|
);
|
|
}).then(function() {
|
|
return loadScriptWithFallback(
|
|
'https://cdn.jsdelivr.net/npm/jspdf-autotable@3.8.4/dist/jspdf.plugin.autotable.min.js',
|
|
'/static/js/jspdf.plugin.autotable.min.js',
|
|
'jspdf-autotable@3.8.4'
|
|
);
|
|
}).then(function() {
|
|
// All libs loaded - transform babel scripts
|
|
window.pegaproxLibsReady = true;
|
|
if (window.Babel) {
|
|
Babel.transformScriptTags();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<!-- LW: Mar 2026 - switched to static Tailwind build (#118), CDN JIT broke offline -->
|
|
<link rel="stylesheet" href="/static/css/tailwind.min.css">
|
|
|
|
<!-- noVNC - lazy loaded when needed (local-first, CDN fallback skipped on air-gap) -->
|
|
<script>
|
|
window.loadNoVNC = function() {
|
|
return new Promise((resolve, reject) => {
|
|
if (window.RFB) { resolve(); return; }
|
|
var script = document.createElement('script');
|
|
script.type = 'module';
|
|
script.src = '/static/js/rfb.js';
|
|
script.onerror = function() {
|
|
if (_isAirGapped && _isAirGapped()) {
|
|
console.error('[air-gap] /static/js/rfb.js missing; not falling back to CDN');
|
|
resolve();
|
|
return;
|
|
}
|
|
this.src = 'https://cdn.jsdelivr.net/npm/@novnc/novnc@1.4.0/core/rfb.js';
|
|
if (SRI_HASHES['novnc@1.4.0']) {
|
|
this.integrity = SRI_HASHES['novnc@1.4.0'];
|
|
this.crossOrigin = 'anonymous';
|
|
}
|
|
};
|
|
script.onload = resolve;
|
|
document.head.appendChild(script);
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<!-- Fonts -->
|
|
<style>
|
|
:root {
|
|
--font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
--font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Fira Mono', 'Roboto Mono', monospace;
|
|
/* MK: Mar 2026 - RGB channel defaults for Tailwind opacity modifiers (#118) */
|
|
--color-primary-rgb: 229, 112, 0;
|
|
--color-dark-rgb: 15, 20, 25;
|
|
--color-darker-rgb: 8, 11, 14;
|
|
--color-card-rgb: 22, 27, 34;
|
|
--color-border-rgb: 48, 54, 61;
|
|
--color-hover-rgb: 28, 33, 40;
|
|
--color-secondary-rgb: 22, 27, 34; /* NS 2026-04-24: was green (35,134,54); caused bg-proxmox-secondary inputs (tokens, LDAP, OIDC) to render on a grass-coloured background. Now matches --color-card-rgb for a consistent sunken input look. */
|
|
--color-success-rgb: 63, 185, 80;
|
|
--color-warning-rgb: 210, 153, 34;
|
|
--color-error-rgb: 248, 81, 73;
|
|
--color-info-rgb: 88, 166, 255;
|
|
}
|
|
</style>
|
|
<!-- LW May 2026 — Google Fonts only attempted when localStorage flag isn't
|
|
set to air-gap. We persist that flag the moment Settings → Air-gap
|
|
toggles, so subsequent loads stay 100% local. system-ui fallback in
|
|
--font-sans handles missing fonts gracefully. -->
|
|
<script>
|
|
(function() {
|
|
try {
|
|
if (localStorage.getItem('pegaprox-air-gap') === '1') return;
|
|
} catch (_) {}
|
|
var fontHref = 'https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap';
|
|
var l = document.createElement('link');
|
|
l.rel = 'stylesheet';
|
|
l.href = fontHref;
|
|
l.media = 'print';
|
|
// NS Jul 2026 (offline): Google Fonts is the one external-only asset (no
|
|
// bundled woff2). If it fails or hasn't loaded within 3s, assume there's
|
|
// no internet and latch a SESSION-only air-gap flag so every later lazy
|
|
// modal loader (xterm/noVNC/html2canvas) skips its CDN fallback and uses
|
|
// the bundled local asset instead of hanging ~30s on a dead connect. Not
|
|
// persisted → a reload with internet back re-evaluates. Harmless if wrong:
|
|
// the CDN branch is only a fallback, locals are always present.
|
|
var _latchOffline = function() { try { window.__pegaproxAirGap = true; } catch (_) {} };
|
|
l.onload = function() { this.media = 'all'; };
|
|
l.onerror = function() { this.remove(); _latchOffline(); };
|
|
setTimeout(function() { if (l.media !== 'all') _latchOffline(); }, 3000);
|
|
document.head.appendChild(l);
|
|
})();
|
|
</script>
|
|
|
|
<script>
|
|
// ============================================
|
|
// THEME SYSTEM - NS Jan 2026
|
|
// ============================================
|
|
// Available themes with full color definitions
|
|
// To add a new theme: add entry here + it auto-appears in Settings
|
|
|
|
const PEGAPROX_THEMES = {
|
|
proxmoxDark: {
|
|
name: 'Proxmox Dark',
|
|
icon: '🌙',
|
|
description: 'Official Proxmox inspired dark theme',
|
|
colors: {
|
|
primary: '#E57000', // Official Proxmox orange
|
|
primaryHover: '#FF8C00',
|
|
dark: '#0F1419',
|
|
darker: '#080B0E',
|
|
card: '#161B22',
|
|
border: '#30363D',
|
|
hover: '#1C2128',
|
|
text: '#FFFFFF',
|
|
textMuted: '#8B949E',
|
|
success: '#3FB950',
|
|
warning: '#D29922',
|
|
error: '#F85149',
|
|
info: '#58A6FF'
|
|
}
|
|
},
|
|
midnight: {
|
|
name: 'Midnight Blue',
|
|
icon: '🌌',
|
|
description: 'Deep blue for night owls',
|
|
colors: {
|
|
primary: '#6366F1',
|
|
primaryHover: '#818CF8',
|
|
dark: '#0F172A',
|
|
darker: '#020617',
|
|
card: '#1E293B',
|
|
border: '#334155',
|
|
hover: '#1E3A5F',
|
|
text: '#F1F5F9',
|
|
textMuted: '#94A3B8',
|
|
success: '#22C55E',
|
|
warning: '#EAB308',
|
|
error: '#EF4444',
|
|
info: '#3B82F6'
|
|
}
|
|
},
|
|
forest: {
|
|
name: 'Forest',
|
|
icon: '🌲',
|
|
description: 'Nature-inspired green theme',
|
|
colors: {
|
|
primary: '#10B981',
|
|
primaryHover: '#34D399',
|
|
dark: '#0D1117',
|
|
darker: '#010409',
|
|
card: '#161B22',
|
|
border: '#21262D',
|
|
hover: '#1C2128',
|
|
text: '#C9D1D9',
|
|
textMuted: '#8B949E',
|
|
success: '#3FB950',
|
|
warning: '#D29922',
|
|
error: '#F85149',
|
|
info: '#58A6FF'
|
|
}
|
|
},
|
|
rose: {
|
|
name: 'Rose',
|
|
icon: '🌸',
|
|
description: 'Soft pink accent theme',
|
|
colors: {
|
|
primary: '#F43F5E',
|
|
primaryHover: '#FB7185',
|
|
dark: '#18181B',
|
|
darker: '#09090B',
|
|
card: '#27272A',
|
|
border: '#3F3F46',
|
|
hover: '#2D2D33',
|
|
text: '#FAFAFA',
|
|
textMuted: '#A1A1AA',
|
|
success: '#22C55E',
|
|
warning: '#EAB308',
|
|
error: '#EF4444',
|
|
info: '#3B82F6'
|
|
}
|
|
},
|
|
ocean: {
|
|
name: 'Ocean',
|
|
icon: '🌊',
|
|
description: 'Cool blue ocean vibes',
|
|
colors: {
|
|
primary: '#0EA5E9',
|
|
primaryHover: '#38BDF8',
|
|
dark: '#0C1222',
|
|
darker: '#060A10',
|
|
card: '#132337',
|
|
border: '#1E3A5F',
|
|
hover: '#1A3550',
|
|
text: '#E2E8F0',
|
|
textMuted: '#94A3B8',
|
|
success: '#22C55E',
|
|
warning: '#F59E0B',
|
|
error: '#EF4444',
|
|
info: '#3B82F6'
|
|
}
|
|
},
|
|
highContrast: {
|
|
name: 'High Contrast',
|
|
icon: '◐',
|
|
description: 'Maximum visibility for accessibility',
|
|
colors: {
|
|
primary: '#FFD700',
|
|
primaryHover: '#FFED4A',
|
|
dark: '#000000',
|
|
darker: '#000000',
|
|
card: '#0A0A0A',
|
|
border: '#FFFFFF',
|
|
hover: '#1A1A1A',
|
|
text: '#FFFFFF',
|
|
textMuted: '#CCCCCC',
|
|
success: '#00FF00',
|
|
warning: '#FFFF00',
|
|
error: '#FF0000',
|
|
info: '#00FFFF'
|
|
}
|
|
},
|
|
// extra skins - LW wanted more variety
|
|
dracula: {
|
|
name: 'Dracula',
|
|
icon: '🧛',
|
|
description: 'Popular Dracula color scheme',
|
|
colors: {
|
|
primary: '#BD93F9',
|
|
primaryHover: '#D4B8FF',
|
|
dark: '#282A36',
|
|
darker: '#1E1F29',
|
|
card: '#343746',
|
|
border: '#44475A',
|
|
hover: '#3D4051',
|
|
text: '#F8F8F2',
|
|
textMuted: '#6272A4',
|
|
success: '#50FA7B',
|
|
warning: '#F1FA8C',
|
|
error: '#FF5555',
|
|
info: '#8BE9FD'
|
|
}
|
|
},
|
|
nord: {
|
|
name: 'Nord',
|
|
icon: '❄️',
|
|
description: 'Arctic, north-bluish color palette',
|
|
colors: {
|
|
primary: '#88C0D0',
|
|
primaryHover: '#8FBCBB',
|
|
dark: '#2E3440',
|
|
darker: '#242933',
|
|
card: '#3B4252',
|
|
border: '#4C566A',
|
|
hover: '#434C5E',
|
|
text: '#ECEFF4',
|
|
textMuted: '#D8DEE9',
|
|
success: '#A3BE8C',
|
|
warning: '#EBCB8B',
|
|
error: '#BF616A',
|
|
info: '#81A1C1'
|
|
}
|
|
},
|
|
monokai: {
|
|
name: 'Monokai',
|
|
icon: '🎨',
|
|
description: 'Classic code editor theme',
|
|
colors: {
|
|
primary: '#F92672',
|
|
primaryHover: '#FF79C6',
|
|
dark: '#272822',
|
|
darker: '#1E1F1C',
|
|
card: '#3E3D32',
|
|
border: '#49483E',
|
|
hover: '#3E3D32',
|
|
text: '#F8F8F2',
|
|
textMuted: '#75715E',
|
|
success: '#A6E22E',
|
|
warning: '#E6DB74',
|
|
error: '#F92672',
|
|
info: '#66D9EF'
|
|
}
|
|
},
|
|
matrix: {
|
|
name: 'Matrix',
|
|
icon: '💊',
|
|
description: 'Enter the Matrix',
|
|
colors: {
|
|
primary: '#00FF41',
|
|
primaryHover: '#00CC33',
|
|
dark: '#0D0208',
|
|
darker: '#000000',
|
|
card: '#0D0D0D',
|
|
border: '#003B00',
|
|
hover: '#001A00',
|
|
text: '#00FF41',
|
|
textMuted: '#008F11',
|
|
success: '#00FF41',
|
|
warning: '#ADFF2F',
|
|
error: '#FF0000',
|
|
info: '#39FF14'
|
|
}
|
|
},
|
|
sunset: {
|
|
name: 'Sunset',
|
|
icon: '🌅',
|
|
description: 'Warm orange and purple gradients',
|
|
colors: {
|
|
primary: '#FF6B35',
|
|
primaryHover: '#FF8C5A',
|
|
dark: '#1A1423',
|
|
darker: '#0F0A14',
|
|
card: '#2D2137',
|
|
border: '#4A3B5C',
|
|
hover: '#3D2F4A',
|
|
text: '#FFF4E6',
|
|
textMuted: '#B8A9C9',
|
|
success: '#7CB518',
|
|
warning: '#FFB627',
|
|
error: '#E63946',
|
|
info: '#A855F7'
|
|
}
|
|
},
|
|
cyberpunk: {
|
|
name: 'Cyberpunk',
|
|
icon: '🤖',
|
|
description: 'Neon lights of Night City',
|
|
colors: {
|
|
primary: '#00D9FF',
|
|
primaryHover: '#00FFFF',
|
|
dark: '#0A0A0F',
|
|
darker: '#050508',
|
|
card: '#12121A',
|
|
border: '#FF00FF',
|
|
hover: '#1A1A25',
|
|
text: '#FFFFFF',
|
|
textMuted: '#8888AA',
|
|
success: '#00FF9F',
|
|
warning: '#FFFF00',
|
|
error: '#FF0055',
|
|
info: '#00D9FF'
|
|
}
|
|
},
|
|
github: {
|
|
name: 'GitHub Dark',
|
|
icon: '🐙',
|
|
description: 'GitHub dark mode colors',
|
|
colors: {
|
|
primary: '#238636',
|
|
primaryHover: '#2EA043',
|
|
dark: '#0D1117',
|
|
darker: '#010409',
|
|
card: '#161B22',
|
|
border: '#30363D',
|
|
hover: '#1F2428',
|
|
text: '#C9D1D9',
|
|
textMuted: '#8B949E',
|
|
success: '#238636',
|
|
warning: '#D29922',
|
|
error: '#F85149',
|
|
info: '#58A6FF'
|
|
}
|
|
},
|
|
solarizedDark: {
|
|
name: 'Solarized Dark',
|
|
icon: '🔆',
|
|
description: 'Precision colors for machines and people',
|
|
colors: {
|
|
primary: '#B58900',
|
|
primaryHover: '#CB4B16',
|
|
dark: '#002B36',
|
|
darker: '#001F27',
|
|
card: '#073642',
|
|
border: '#586E75',
|
|
hover: '#094552',
|
|
text: '#FDF6E3',
|
|
textMuted: '#93A1A1',
|
|
success: '#859900',
|
|
warning: '#B58900',
|
|
error: '#DC322F',
|
|
info: '#268BD2'
|
|
}
|
|
},
|
|
gruvbox: {
|
|
name: 'Gruvbox',
|
|
icon: '📦',
|
|
description: 'Retro groove color scheme',
|
|
colors: {
|
|
primary: '#FE8019',
|
|
primaryHover: '#FABD2F',
|
|
dark: '#1D2021',
|
|
darker: '#0D1011',
|
|
card: '#282828',
|
|
border: '#3C3836',
|
|
hover: '#32302F',
|
|
text: '#EBDBB2',
|
|
textMuted: '#A89984',
|
|
success: '#B8BB26',
|
|
warning: '#FABD2F',
|
|
error: '#FB4934',
|
|
info: '#83A598'
|
|
}
|
|
},
|
|
// Corporate/Enterprise style themes
|
|
corporateDark: {
|
|
name: 'Corporate Dark',
|
|
icon: '🖥️',
|
|
description: 'Modern corporate dark theme',
|
|
colors: {
|
|
primary: '#49afd9', // Clarity Skyline blue
|
|
primaryHover: '#3d9bc2',
|
|
dark: '#1b2a32', // Clarity dark sidebar
|
|
darker: '#111a21', // Clarity darkest bg
|
|
card: '#243542', // Clarity card surface
|
|
border: '#344955', // Clarity borders
|
|
hover: '#29414e', // Clarity hover
|
|
text: '#e9ecef',
|
|
textMuted: '#728b9a',
|
|
success: '#60b515', warning: '#efc006', error: '#f54f47', info: '#49afd9'
|
|
}
|
|
},
|
|
corporateLight: {
|
|
name: 'Corporate Light',
|
|
icon: '💻',
|
|
description: 'Modern corporate light theme',
|
|
colors: {
|
|
primary: '#0079b8',
|
|
primaryHover: '#005e91',
|
|
dark: '#fafafa',
|
|
darker: '#ffffff',
|
|
card: '#ffffff',
|
|
border: '#ccc',
|
|
hover: '#eee',
|
|
text: '#313131',
|
|
textMuted: '#666',
|
|
success: '#60b515', warning: '#efc006', error: '#f54f47', info: '#0079b8'
|
|
}
|
|
},
|
|
enterpriseBlue: {
|
|
name: 'Enterprise Blue',
|
|
icon: '🔷',
|
|
description: 'Classic enterprise blue theme',
|
|
colors: {
|
|
primary: '#005EB8', // Classic enterprise blue
|
|
primaryHover: '#0073D1',
|
|
dark: '#2C3E50', // Dark blue-gray
|
|
darker: '#1A252F',
|
|
card: '#34495E',
|
|
border: '#4A6278',
|
|
hover: '#3D5266',
|
|
text: '#ECF0F1',
|
|
textMuted: '#95A5A6',
|
|
success: '#27AE60',
|
|
warning: '#F39C12',
|
|
error: '#E74C3C',
|
|
info: '#3498DB'
|
|
}
|
|
},
|
|
cloud: {
|
|
name: 'Cloud (Preview)', icon: '☁️', description: 'Resource-first cloud layout (Preview)',
|
|
colors: {
|
|
primary: '#22d3ee', primaryHover: '#67e8f9',
|
|
dark: '#0a1628', darker: '#060f1e', card: '#102338', border: '#1e3a52', hover: '#14304a',
|
|
text: '#e6f1f8', textMuted: '#8aa4b8',
|
|
success: '#2dd4a7', warning: '#f5b945', error: '#f87171', info: '#38bdf8'
|
|
}
|
|
}
|
|
};
|
|
|
|
// MK: Mar 2026 - hex to RGB channels for Tailwind opacity modifiers (#118)
|
|
function hexToRgb(hex) {
|
|
hex = hex.replace('#', '');
|
|
if (hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
|
|
var n = parseInt(hex, 16);
|
|
return ((n >> 16) & 255) + ', ' + ((n >> 8) & 255) + ', ' + (n & 255);
|
|
}
|
|
|
|
// Apply theme by setting CSS variables
|
|
function applyTheme(themeName) {
|
|
const theme = PEGAPROX_THEMES[themeName] || PEGAPROX_THEMES.proxmoxDark;
|
|
const root = document.documentElement;
|
|
|
|
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
root.style.setProperty(`--color-${key}`, value);
|
|
// RGB channels for Tailwind opacity modifiers (bg-proxmox-orange/20 etc)
|
|
if (value && value.startsWith('#')) {
|
|
root.style.setProperty(`--color-${key}-rgb`, hexToRgb(value));
|
|
}
|
|
});
|
|
|
|
// Special handling for light theme - only if body exists
|
|
if (document.body) {
|
|
const lightThemes = ['corporateLight'];
|
|
if (lightThemes.includes(themeName)) {
|
|
document.body.classList.add('light-theme');
|
|
document.body.classList.remove('dark-theme');
|
|
} else {
|
|
document.body.classList.add('dark-theme');
|
|
document.body.classList.remove('light-theme');
|
|
}
|
|
}
|
|
|
|
localStorage.setItem('pegaprox-theme', themeName);
|
|
console.log(`Theme applied: ${theme.name}`);
|
|
}
|
|
|
|
// Load saved theme on page load - apply CSS vars immediately, body classes after DOM ready
|
|
(function() {
|
|
const saved = localStorage.getItem('pegaprox-theme') || 'proxmoxDark';
|
|
console.log('[Theme] Initial load from localStorage:', saved);
|
|
// Apply CSS variables immediately (works on documentElement)
|
|
const theme = PEGAPROX_THEMES[saved] || PEGAPROX_THEMES.proxmoxDark;
|
|
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
document.documentElement.style.setProperty(`--color-${key}`, value);
|
|
if (value && value.startsWith('#')) {
|
|
document.documentElement.style.setProperty(`--color-${key}-rgb`, hexToRgb(value));
|
|
}
|
|
});
|
|
// Apply body classes after DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => applyTheme(saved));
|
|
} else {
|
|
applyTheme(saved);
|
|
}
|
|
})();
|
|
|
|
// ============================================
|
|
// TAILWIND CONFIG
|
|
// ============================================
|
|
// LW: Custom Proxmox-inspired color palette
|
|
// Now uses CSS variables for dynamic theming
|
|
if (typeof tailwind !== 'undefined') {
|
|
tailwind.config = {
|
|
darkMode: 'class',
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
sans: ['Plus Jakarta Sans', 'sans-serif'],
|
|
mono: ['JetBrains Mono', 'monospace'],
|
|
},
|
|
colors: {
|
|
proxmox: {
|
|
// These now reference CSS variables for theme support
|
|
orange: 'var(--color-primary, #E57000)',
|
|
dark: 'var(--color-dark, #0F1419)',
|
|
darker: 'var(--color-darker, #080B0E)',
|
|
card: 'var(--color-card, #161B22)',
|
|
border: 'var(--color-border, #30363D)',
|
|
hover: 'var(--color-hover, #1C2128)',
|
|
},
|
|
// Semantic colors
|
|
theme: {
|
|
primary: 'var(--color-primary, #E57000)',
|
|
success: 'var(--color-success, #3FB950)',
|
|
warning: 'var(--color-warning, #D29922)',
|
|
error: 'var(--color-error, #F85149)',
|
|
info: 'var(--color-info, #58A6FF)',
|
|
}
|
|
},
|
|
animation: {
|
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
'gradient': 'gradient 8s ease infinite',
|
|
'slide-up': 'slideUp 0.5s ease-out',
|
|
'slide-in': 'slideIn 0.3s ease-out',
|
|
'fade-in': 'fadeIn 0.4s ease-out',
|
|
'scale-in': 'scaleIn 0.3s ease-out',
|
|
'glow': 'glow 2s ease-in-out infinite alternate',
|
|
},
|
|
keyframes: {
|
|
gradient: {
|
|
'0%, 100%': { backgroundPosition: '0% 50%' },
|
|
'50%': { backgroundPosition: '100% 50%' },
|
|
},
|
|
slideUp: {
|
|
'0%': { opacity: '0', transform: 'translateY(20px)' },
|
|
'100%': { opacity: '1', transform: 'translateY(0)' },
|
|
},
|
|
slideIn: {
|
|
'0%': { opacity: '0', transform: 'translateX(-10px)' },
|
|
'100%': { opacity: '1', transform: 'translateX(0)' },
|
|
},
|
|
fadeIn: {
|
|
'0%': { opacity: '0' },
|
|
'100%': { opacity: '1' },
|
|
},
|
|
scaleIn: {
|
|
'0%': { opacity: '0', transform: 'scale(0.95)' },
|
|
'100%': { opacity: '1', transform: 'scale(1)' },
|
|
},
|
|
glow: {
|
|
'0%': { boxShadow: '0 0 20px var(--color-primary, rgba(229, 112, 0, 0.3))' },
|
|
'100%': { boxShadow: '0 0 40px var(--color-primary, rgba(229, 112, 0, 0.6))' },
|
|
},
|
|
}
|
|
}
|
|
}
|
|
};
|
|
} // end if (typeof tailwind !== 'undefined')
|
|
</script>
|
|
<style>
|
|
* {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: #30363D #161B22;
|
|
}
|
|
*::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
*::-webkit-scrollbar-track {
|
|
background: #161B22;
|
|
}
|
|
*::-webkit-scrollbar-thumb {
|
|
background: #30363D;
|
|
border-radius: 4px;
|
|
}
|
|
*::-webkit-scrollbar-thumb:hover {
|
|
background: #484F58;
|
|
}
|
|
|
|
/* Global dark mode for form elements */
|
|
input, select, textarea {
|
|
background-color: var(--color-dark, #0F1419);
|
|
color: var(--color-text, #E6EDF3);
|
|
border-color: var(--color-border, #30363D);
|
|
}
|
|
input::placeholder, textarea::placeholder {
|
|
color: #9CA3AF;
|
|
}
|
|
input[type="checkbox"], input[type="radio"] {
|
|
accent-color: var(--color-primary, #E57000);
|
|
}
|
|
input[type="range"] {
|
|
background: transparent;
|
|
}
|
|
select option {
|
|
background-color: var(--color-dark, #0F1419);
|
|
color: var(--color-text, #E6EDF3);
|
|
}
|
|
/* Fix focus outline */
|
|
*:focus {
|
|
outline-color: var(--color-primary, #E57000);
|
|
}
|
|
/* Reset potential white backgrounds */
|
|
button, fieldset, legend {
|
|
background-color: transparent;
|
|
}
|
|
hr {
|
|
border-color: var(--color-border, #30363D);
|
|
}
|
|
/* GLOBAL BORDER FIX - prevent white borders from Tailwind default */
|
|
*, *::before, *::after {
|
|
border-color: var(--color-border, #30363D);
|
|
}
|
|
/* Fix table borders */
|
|
table {
|
|
border-collapse: collapse;
|
|
border-spacing: 0;
|
|
border-color: var(--color-border, #30363D);
|
|
background-color: transparent;
|
|
}
|
|
tbody {
|
|
background-color: var(--color-card, #161B22);
|
|
}
|
|
tr, td, th {
|
|
border-color: var(--color-border, #30363D) !important;
|
|
background-color: inherit;
|
|
}
|
|
tbody tr {
|
|
border-color: rgba(48, 54, 61, 0.5) !important;
|
|
}
|
|
/* Force dark borders on all elements */
|
|
.border-gray-700\/50 {
|
|
border-color: rgba(55, 65, 81, 0.5) !important;
|
|
}
|
|
|
|
/* Gradient backgrounds */
|
|
.gradient-mesh {
|
|
background:
|
|
radial-gradient(at 40% 20%, rgba(229, 112, 0, 0.15) 0px, transparent 50%),
|
|
radial-gradient(at 80% 0%, rgba(229, 112, 0, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 0% 50%, rgba(229, 112, 0, 0.08) 0px, transparent 50%),
|
|
radial-gradient(at 80% 100%, rgba(229, 112, 0, 0.05) 0px, transparent 50%);
|
|
}
|
|
|
|
/* Gauge styles */
|
|
.gauge-container {
|
|
position: relative;
|
|
width: 120px;
|
|
height: 120px;
|
|
}
|
|
.gauge-bg {
|
|
fill: none;
|
|
stroke: #30363D;
|
|
stroke-width: 10;
|
|
}
|
|
.gauge-fill {
|
|
fill: none;
|
|
stroke-width: 10;
|
|
stroke-linecap: round;
|
|
transform: rotate(-90deg);
|
|
transform-origin: center;
|
|
transition: stroke-dashoffset 0.8s cubic-bezier(0.4, 0, 0.2, 1), stroke 0.3s ease;
|
|
}
|
|
.gauge-text {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-weight: 600;
|
|
fill: currentColor;
|
|
}
|
|
|
|
/* Card hover effects */
|
|
/* NS: removed transform because it breaks fixed modal positioning */
|
|
.card-hover {
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
.card-hover:hover {
|
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(229, 112, 0, 0.2);
|
|
}
|
|
|
|
/* Slider styles */
|
|
.custom-slider {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
height: 8px;
|
|
border-radius: 4px;
|
|
outline: none;
|
|
transition: all 0.2s;
|
|
background: transparent;
|
|
}
|
|
.custom-slider::-webkit-slider-runnable-track {
|
|
height: 8px;
|
|
border-radius: 4px;
|
|
background: transparent;
|
|
}
|
|
.custom-slider::-moz-range-track {
|
|
height: 8px;
|
|
border-radius: 4px;
|
|
background: transparent;
|
|
}
|
|
.custom-slider::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background: #E57000;
|
|
cursor: grab;
|
|
box-shadow: 0 2px 10px rgba(229, 112, 0, 0.5);
|
|
transition: all 0.2s;
|
|
}
|
|
.custom-slider::-webkit-slider-thumb:hover {
|
|
transform: scale(1.1);
|
|
box-shadow: 0 4px 20px rgba(229, 112, 0, 0.7);
|
|
}
|
|
.custom-slider::-webkit-slider-thumb:active {
|
|
cursor: grabbing;
|
|
}
|
|
.custom-slider::-moz-range-thumb {
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background: #E57000;
|
|
cursor: grab;
|
|
border: none;
|
|
box-shadow: 0 2px 10px rgba(229, 112, 0, 0.5);
|
|
}
|
|
|
|
/* Status indicator pulse */
|
|
.status-online {
|
|
animation: pulse-online 2s ease-in-out infinite;
|
|
}
|
|
@keyframes pulse-online {
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7); }
|
|
50% { box-shadow: 0 0 0 8px rgba(34, 197, 94, 0); }
|
|
}
|
|
|
|
.topo-status-glow { box-shadow: 0 0 6px rgba(96,181,21,0.4); }
|
|
|
|
/* Noise texture overlay */
|
|
.noise-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
pointer-events: none;
|
|
opacity: 0.03;
|
|
z-index: 1000;
|
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
|
}
|
|
|
|
/* Modal backdrop blur */
|
|
.modal-backdrop {
|
|
backdrop-filter: blur(8px);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
}
|
|
|
|
/* Timeline styles */
|
|
.timeline-line {
|
|
position: absolute;
|
|
left: 19px;
|
|
top: 40px;
|
|
bottom: 0;
|
|
width: 2px;
|
|
background: linear-gradient(to bottom, #E57000, transparent);
|
|
}
|
|
|
|
/* Toggle switch */
|
|
.toggle-switch {
|
|
position: relative;
|
|
width: 48px;
|
|
height: 26px;
|
|
background: #30363D;
|
|
border-radius: 13px;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
}
|
|
.toggle-switch.active {
|
|
background: #E57000;
|
|
}
|
|
.toggle-switch::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 3px;
|
|
left: 3px;
|
|
width: 20px;
|
|
height: 20px;
|
|
background: white;
|
|
border-radius: 50%;
|
|
transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
}
|
|
.toggle-switch.active::after {
|
|
left: 25px;
|
|
}
|
|
|
|
/* Glow effect for active elements */
|
|
.glow-orange {
|
|
box-shadow: 0 0 30px rgba(229, 112, 0, 0.4);
|
|
}
|
|
|
|
/* Table row hover */
|
|
.table-row-hover {
|
|
transition: all 0.2s;
|
|
}
|
|
.table-row-hover:hover {
|
|
background: rgba(229, 112, 0, 0.1);
|
|
}
|
|
|
|
/* Notification toast */
|
|
.toast-enter {
|
|
animation: toastEnter 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
}
|
|
@keyframes toastEnter {
|
|
0% { opacity: 0; transform: translateX(100%); }
|
|
100% { opacity: 1; transform: translateX(0); }
|
|
}
|
|
|
|
/* Sparkline */
|
|
.sparkline-path {
|
|
fill: none;
|
|
stroke: #E57000;
|
|
stroke-width: 2;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
.sparkline-area {
|
|
fill: url(#sparklineGradient);
|
|
}
|
|
|
|
/* LW: Feb 2026 - Corporate layout overrides (experimental) */
|
|
/* Override CSS variables to Clarity dark theme palette */
|
|
body[data-layout="corporate"] {
|
|
--color-dark: #1b2a32;
|
|
--color-darker: #111a21;
|
|
--color-card: #243542;
|
|
--color-border: #344955;
|
|
--color-hover: #29414e;
|
|
--color-primary: #49afd9;
|
|
--color-text: #e9ecef;
|
|
--color-success: #60b515;
|
|
--color-warning: #efc006;
|
|
--color-error: #f54f47;
|
|
--color-info: #49afd9;
|
|
--corp-accent: #49afd9;
|
|
--corp-accent-hover: #6cc6e8;
|
|
--corp-selection: #324f61;
|
|
--corp-radius-sm: 4px;
|
|
--corp-radius-md: 6px;
|
|
--corp-radius-lg: 8px;
|
|
--corp-text-secondary: #adbbc4;
|
|
--corp-text-muted: #728b9a;
|
|
--corp-divider: #37474f;
|
|
/* MK: Mar 2026 - surface layers for depth hierarchy */
|
|
--corp-surface-0: #0e161b;
|
|
--corp-surface-1: #111a21;
|
|
--corp-surface-2: #1a2730;
|
|
--corp-surface-3: #243542;
|
|
--corp-surface-raised: #2c4050;
|
|
--corp-border-subtle: #283844;
|
|
--corp-border-medium: #344955;
|
|
--corp-border-strong: #4a6070;
|
|
--corp-header-bg: #1a2730;
|
|
--corp-bar-track: #1a2e38;
|
|
/* MK: Mar 2026 - elevation tokens */
|
|
--corp-shadow-sm: 0 1px 2px rgba(6,12,18,0.15), 0 1px 3px rgba(6,12,18,0.1);
|
|
--corp-shadow-md: 0 3px 8px rgba(6,12,18,0.2), 0 1px 3px rgba(6,12,18,0.1);
|
|
--corp-shadow-lg: 0 6px 16px rgba(6,12,18,0.3), 0 2px 4px rgba(6,12,18,0.15);
|
|
--corp-shadow-xl: 0 8px 24px rgba(6,12,18,0.4), 0 2px 8px rgba(6,12,18,0.2);
|
|
/* NS 2026-06-05 (UI polish): semantic metric + threshold colors so the
|
|
corporate detail views stop hardcoding hex inline (theme-aware now). */
|
|
--corp-metric-cpu: #49afd9;
|
|
--corp-metric-ram: #9b59b6;
|
|
--corp-metric-disk: #60b515;
|
|
--corp-metric-net: #efc006;
|
|
--corp-thresh-ok: #60b515;
|
|
--corp-thresh-warn: #efc006;
|
|
--corp-thresh-crit: #f54f47;
|
|
}
|
|
|
|
/* NS Jul 2026 (scale) — opt-in "show VM IDs" in the corporate sidebar tree.
|
|
Rendered as a CSS ::after on each guest row (a trailing flex item, so it
|
|
stays visible even when the name truncates) instead of an extra <span>
|
|
per VM. Gated on the body flag set from the user pref, so toggling it is
|
|
free at 1000+ VMs — no per-row React re-render, no added DOM nodes.
|
|
Only rows WITH a name carry data-vmid (nameless rows already show the id
|
|
in their fallback label), so there is no duplicate id. */
|
|
body[data-sidebar-vmid="1"] .corp-tree-child[data-vmid]::after {
|
|
content: "#" attr(data-vmid);
|
|
flex-shrink: 0;
|
|
margin-left: 6px;
|
|
font-size: 11px;
|
|
color: var(--corp-text-muted);
|
|
opacity: 0.85;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* NS Jul 2026 (scale) — native windowing for the sidebar tree. content-visibility:auto
|
|
lets the browser skip layout + paint for rows scrolled out of the sidebar's
|
|
scrollport, so a 100-node / 1000+-VM tree stays smooth while scrolling. Unlike JS
|
|
windowing the rows STAY in the DOM, so keyboard nav (querySelectorAll+focus),
|
|
tooltips, selection and the #vmid ::after all keep working unchanged — a
|
|
content-visibility:auto row is still focusable and in the a11y tree, and renders
|
|
the moment it's focused or scrolled near. contain-intrinsic-size keeps the
|
|
scrollbar honest before a row first paints (`auto` remembers the real height after
|
|
first render; ~20px is only the initial estimate). Degrades gracefully: browsers
|
|
without content-visibility just render every row normally. */
|
|
.corp-tree-child {
|
|
content-visibility: auto;
|
|
contain-intrinsic-size: auto 24px; /* real row height: leading-5 (20px) + py-0.5 (4px); `auto` self-corrects per row (network rows are ~20px) */
|
|
}
|
|
|
|
/* LW: Mar 2026 — corporate light mode tokens. NS 2026-05-10 retuned:
|
|
bumped text contrast (was #555/#888 → too washed), darker accent for
|
|
AA on white, slightly cooler surface base, sharper border on the
|
|
"subtle" tier so dense tables don't read as a flat block. */
|
|
body[data-corp-theme="light"] {
|
|
/* override base Tailwind color system */
|
|
--color-dark: #eef1f4;
|
|
--color-darker: #e2e7ec;
|
|
--color-dark-rgb: 238, 241, 244;
|
|
--color-darker-rgb: 226, 231, 236;
|
|
--color-card: #ffffff;
|
|
--color-border: #c0ccd4;
|
|
--color-text: #1c2733;
|
|
--color-hover: #e6eef4;
|
|
--color-orange: #c2610a;
|
|
/* corporate variables */
|
|
--corp-accent: #0072a3;
|
|
--corp-accent-hover: #005a85;
|
|
--corp-selection: #d6ebf6;
|
|
--corp-radius-sm: 4px;
|
|
--corp-radius-md: 6px;
|
|
--corp-radius-lg: 8px;
|
|
--corp-text: #1c2733;
|
|
--corp-text-secondary: #44525e;
|
|
--corp-text-muted: #6a7782;
|
|
--corp-divider: #d8dee3;
|
|
--corp-surface-0: #ffffff;
|
|
--corp-surface-1: #f6f8fa;
|
|
--corp-surface-2: #ecf1f4;
|
|
--corp-surface-3: #e0e6ea;
|
|
--corp-surface-raised: #ffffff;
|
|
--corp-border-subtle: #dde3e8;
|
|
--corp-border-medium: #c0ccd4;
|
|
--corp-border-strong: #97a5b0;
|
|
--corp-header-bg: #f6f8fa;
|
|
--corp-bar-track: #e6ebef;
|
|
--corp-shadow-sm: 0 1px 1px rgba(15,30,50,0.04), 0 1px 2px rgba(15,30,50,0.06);
|
|
--corp-shadow-md: 0 1px 3px rgba(15,30,50,0.06), 0 2px 6px rgba(15,30,50,0.08);
|
|
--corp-shadow-lg: 0 2px 6px rgba(15,30,50,0.08), 0 6px 14px rgba(15,30,50,0.10);
|
|
--corp-shadow-xl: 0 4px 12px rgba(15,30,50,0.10), 0 12px 32px rgba(15,30,50,0.12);
|
|
/* NS 2026-06-05 (UI polish): metric/threshold colors darkened for AA on white */
|
|
--corp-metric-cpu: #0079b8;
|
|
--corp-metric-ram: #8e44ad;
|
|
--corp-metric-disk: #4e9a06;
|
|
--corp-metric-net: #b7950b;
|
|
--corp-thresh-ok: #4e9a06;
|
|
--corp-thresh-warn: #b7950b;
|
|
--corp-thresh-crit: #d64541;
|
|
background-color: #eef1f4 !important;
|
|
color: #1c2733 !important;
|
|
}
|
|
/* component-level overrides */
|
|
body[data-corp-theme="light"] .corp-tab-strip button { color: #555; }
|
|
body[data-corp-theme="light"] .corp-tab-strip button.active { color: #0072a3; border-color: #0072a3; }
|
|
body[data-corp-theme="light"] .corp-sidebar-search { background: #fff; border-color: #cfd8dc; color: #333; }
|
|
body[data-corp-theme="light"] .corp-sidebar-search::placeholder { color: #999; }
|
|
body[data-corp-theme="light"] .corp-datagrid th { background: #f6f8fa !important; color: #44525e !important; border-bottom-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-datagrid td { border-color: #ecf1f4 !important; color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .corp-datagrid tr:hover td { background: rgba(0,114,163,0.04) !important; }
|
|
body[data-corp-theme="light"] .corp-datagrid tr.corp-row-selected td { background: rgba(0,114,163,0.10) !important; }
|
|
body[data-corp-theme="light"] .corp-datagrid tr.corp-row-selected td:first-child { box-shadow: inset 3px 0 0 #0072a3 !important; }
|
|
/* MK May 2026 (#296): the dark-mode `.corp-datagrid td` rule sits later
|
|
in the cascade with equal specificity, so without !important the
|
|
inventory overview rows ended up #e9ecef on white = invisible. */
|
|
body[data-corp-theme="light"] .corp-context-menu { background: #ffffff; border-color: #c0ccd4; box-shadow: 0 6px 20px rgba(15,30,50,0.12); }
|
|
body[data-corp-theme="light"] .corp-ctx-item { color: #1c2733; }
|
|
body[data-corp-theme="light"] .corp-ctx-item:hover { background: #ecf1f4; color: #1c2733; }
|
|
body[data-corp-theme="light"] .corp-dropdown { background: #ffffff !important; border-color: #c0ccd4 !important; box-shadow: 0 6px 20px rgba(15,30,50,0.12) !important; }
|
|
body[data-corp-theme="light"] .corp-dropdown button { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .corp-dropdown button:hover { background: #ecf1f4 !important; }
|
|
body[data-corp-theme="light"] .corp-node-row:hover { background: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] .corp-subnav-item:hover { background: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar button:hover { background: rgba(0,0,0,0.06) !important; }
|
|
body[data-corp-theme="light"] .corp-type-filter-btn { color: #555; }
|
|
body[data-corp-theme="light"] .corp-type-filter-btn.active { color: #0072a3; background: rgba(0,114,163,0.1); }
|
|
/* tailwind bg/text class overrides */
|
|
body[data-corp-theme="light"] .bg-proxmox-dark { background: #eef1f4 !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-darker { background: #e4e8ec !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-card { background: #fff !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-secondary { background: #fff !important; color: #222 !important; border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-hover { background: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] .border-proxmox-border { border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .border-gray-700\/50,
|
|
body[data-corp-theme="light"] .border-gray-700 { border-color: #ddd !important; }
|
|
/* NS 2026-05-10 — text contrast bumped (AA on white). Old values were
|
|
too washed (#555 secondary, #888 muted) — checked AA: failed. */
|
|
body[data-corp-theme="light"] .text-white { color: #1c2733 !important; }
|
|
/* MK May 2026 (#451 thefiredragon) — Modern UI's corporateLight theme sets
|
|
`body.light-theme` instead of `data-corp-theme="light"`. The existing
|
|
rule above only catches Corporate Layout's light mode, so login inputs
|
|
(which carry .text-white) stayed white on a near-white (#fafafa) bg →
|
|
invisible typed text. Surgical fix: target input/textarea only, so the
|
|
orange submit-button's `text-white` stays white. */
|
|
body.light-theme input.text-white,
|
|
body.light-theme textarea.text-white { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .text-gray-200 { color: #2a3744 !important; }
|
|
body[data-corp-theme="light"] .text-gray-300 { color: #3a4754 !important; }
|
|
body[data-corp-theme="light"] .text-gray-400 { color: #5a6772 !important; }
|
|
body[data-corp-theme="light"] .text-gray-500 { color: #6a7782 !important; }
|
|
body[data-corp-theme="light"] .text-gray-600 { color: #818b94 !important; }
|
|
/* override inline style colors — React renders as rgb() not hex */
|
|
body[data-corp-theme="light"] [style*="color: rgb(233, 236, 239)"],
|
|
body[data-corp-theme="light"] [style*="color: #e9ecef"] { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] [style*="color: rgb(114, 139, 154)"],
|
|
body[data-corp-theme="light"] [style*="color: #728b9a"] { color: #5a6772 !important; }
|
|
body[data-corp-theme="light"] [style*="color: rgb(90, 122, 138)"],
|
|
body[data-corp-theme="light"] [style*="color: #5a7a8a"] { color: #6a7782 !important; }
|
|
body[data-corp-theme="light"] [style*="color: rgb(173, 187, 196)"],
|
|
body[data-corp-theme="light"] [style*="color: #adbbc4"] { color: #3a4754 !important; }
|
|
/* NS 2026-05-10 — also handle white text inline (some component-internal
|
|
styles use color: #fff or rgb(255,255,255) for emphasis on dark — flip
|
|
to dark text on light bg). Skip explicit white-on-coloured-bg which
|
|
is intentional on accent buttons (handled by .corp-vm-btn-primary). */
|
|
body[data-corp-theme="light"] .corp-vm-modal-body [style*="color: #fff"],
|
|
body[data-corp-theme="light"] .corp-vm-modal-body [style*="color: rgb(255, 255, 255)"],
|
|
body[data-corp-theme="light"] .corp-vm-modal-body [style*="color: #ffffff"] { color: #1c2733 !important; }
|
|
/* override inline backgrounds — both hex AND rgb() forms */
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(14, 22, 27)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(17, 26, 33)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(26, 39, 48)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(26, 39, 51)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(27, 42, 50)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(36, 53, 66)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(23, 36, 43)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(15, 20, 25)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(14, 22, 27)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(17, 26, 33)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(26, 39, 48)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(26, 39, 51)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(27, 42, 50)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(36, 53, 66)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(23, 36, 43)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(15, 20, 25)"],
|
|
body[data-corp-theme="light"] [style*="background: #0e161b"],
|
|
body[data-corp-theme="light"] [style*="background: #111a21"],
|
|
body[data-corp-theme="light"] [style*="background: #1a2730"],
|
|
body[data-corp-theme="light"] [style*="background: #1a2733"],
|
|
body[data-corp-theme="light"] [style*="background: #1b2a32"],
|
|
body[data-corp-theme="light"] [style*="background: #243542"],
|
|
body[data-corp-theme="light"] [style*="background: #17242b"] { background: #f5f7f9 !important; background-color: #f5f7f9 !important; }
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(44, 64, 80)"],
|
|
body[data-corp-theme="light"] [style*="background-color: rgb(50, 79, 97)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(44, 64, 80)"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(50, 79, 97)"],
|
|
body[data-corp-theme="light"] [style*="background: #2c4050"],
|
|
body[data-corp-theme="light"] [style*="background: #324f61"] { background: #e3f2fd !important; background-color: #e3f2fd !important; }
|
|
/* inline borders — NS 2026-05-10 added #485764 / #3a5060 / #3a5565 +
|
|
variants. Most legacy code in node_modals.js uses these as 1-px frame
|
|
borders; without overrides they show as dark grey on light bg = ugly. */
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(40, 56, 68)"],
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(52, 73, 85)"],
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(55, 71, 79)"],
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(72, 87, 100)"],
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(58, 80, 96)"],
|
|
body[data-corp-theme="light"] [style*="border-color: rgb(58, 85, 101)"],
|
|
body[data-corp-theme="light"] [style*="border-color: #283844"],
|
|
body[data-corp-theme="light"] [style*="border-color: #344955"],
|
|
body[data-corp-theme="light"] [style*="border-color: #37474f"],
|
|
body[data-corp-theme="light"] [style*="border-color: #485764"],
|
|
body[data-corp-theme="light"] [style*="border-color: #3a5060"],
|
|
body[data-corp-theme="light"] [style*="border-color: #3a5565"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid rgb(40, 56, 68)"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid rgb(52, 73, 85)"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid rgb(72, 87, 100)"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #485764"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #283844"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #344955"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #3a5060"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #3a5565"],
|
|
body[data-corp-theme="light"] [style*="borderBottom: 1px solid #485764"],
|
|
body[data-corp-theme="light"] [style*="border-bottom: 1px solid #485764"] { border-color: var(--corp-border-medium, #c0ccd4) !important; }
|
|
/* Tailwind arbitrary bg classes — MK May 2026 (#296) substring matchers
|
|
on class= attribute hold the LITERAL class string, so brackets/hash
|
|
don't get escaped. Earlier version had \\[ \\# \\] in the string which
|
|
CSS parsed as backslash-bracket etc. → never matched the actual
|
|
"bg-[#17242b]" class → light-mode searchbar etc. stayed dark. */
|
|
body[data-corp-theme="light"] [class*="bg-[#17242b]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#1a2730]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#1a2e38]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#1e3340]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#111a21]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#141e24]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#1e2b33]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#0e161b]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#243542]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#22343c]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#12181f]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#0f161a]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#1c2733]"] { background-color: #f6f8fa !important; }
|
|
body[data-corp-theme="light"] [class*="bg-[#324f61]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#29414e]"],
|
|
body[data-corp-theme="light"] [class*="bg-[#2c4050]"] { background-color: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] [class*="hover:bg-[#324f61]"]:hover,
|
|
body[data-corp-theme="light"] [class*="hover:bg-[#29414e]"]:hover { background-color: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] [class*="border-[#3a5565]"],
|
|
body[data-corp-theme="light"] [class*="border-[#3a5060]"],
|
|
body[data-corp-theme="light"] [class*="border-[#344955]"],
|
|
body[data-corp-theme="light"] [class*="border-[#283844]"],
|
|
body[data-corp-theme="light"] [class*="border-[#37474f]"] { border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] [class*="text-[#5a7a8a]"],
|
|
body[data-corp-theme="light"] [class*="text-[#728b9a]"],
|
|
body[data-corp-theme="light"] [class*="text-[#adbbc4]"] { color: #666 !important; }
|
|
body[data-corp-theme="light"] [class*="text-[#e9ecef]"],
|
|
body[data-corp-theme="light"] [class*="!text-[#e9ecef]"],
|
|
body[data-corp-theme="light"] [class*="text-[#fff]"]:not(button):not(.corp-view-switcher button.active) { color: #333 !important; }
|
|
/* forms */
|
|
body[data-corp-theme="light"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
|
|
body[data-corp-theme="light"] select,
|
|
body[data-corp-theme="light"] textarea { background: #fff !important; color: #333 !important; border-color: #cfd8dc !important; }
|
|
/* sidebar tree */
|
|
body[data-corp-theme="light"] .corp-inline-tree { background: #f6f8fa !important; }
|
|
body[data-corp-theme="light"] .corp-tree-item { color: #1c2733; }
|
|
body[data-corp-theme="light"] .corp-tree-item:hover { background: #ecf1f4 !important; }
|
|
body[data-corp-theme="light"] .corp-tree-item.selected,
|
|
body[data-corp-theme="light"] .corp-tree-item[style*="background: var(--corp-selection)"] {
|
|
background: #d6ebf6 !important;
|
|
box-shadow: inset 2px 0 0 #0072a3;
|
|
}
|
|
/* header */
|
|
body[data-corp-theme="light"] header { background: #ffffff !important; border-bottom: 1px solid #c0ccd4 !important; box-shadow: 0 1px 0 rgba(15,30,50,0.04); }
|
|
/* scrollbar */
|
|
body[data-corp-theme="light"] ::-webkit-scrollbar-track { background: #f0f2f5; }
|
|
body[data-corp-theme="light"] ::-webkit-scrollbar-thumb { background: #bbb; }
|
|
body[data-corp-theme="light"] ::-webkit-scrollbar-thumb:hover { background: #999; }
|
|
|
|
/* NS: Mar 2026 - comprehensive light mode overrides for all corp-* classes */
|
|
/* modals */
|
|
body[data-corp-theme="light"] .corp-modal-header { background: #f6f8fa !important; border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-modal-title { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .corp-modal-close { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-modal-close:hover { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-modal-footer { background: #f5f7f9 !important; border-color: #ddd !important; }
|
|
/* cards */
|
|
body[data-corp-theme="light"] .corp-card { background: #fff !important; border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .corp-card-header { color: #555 !important; background: #f0f2f5 !important; }
|
|
/* badges */
|
|
body[data-corp-theme="light"] .corp-badge { border-color: transparent !important; }
|
|
body[data-corp-theme="light"] .corp-badge-stopped { color: #888 !important; }
|
|
/* navigation & subnav */
|
|
body[data-corp-theme="light"] .corp-subnav { border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-subnav-item { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-subnav-item.active { background: #e3f2fd !important; color: #0072a3 !important; border-left-color: #0072a3 !important; }
|
|
body[data-corp-theme="light"] .corp-subnav-item:hover { background: #e8f0f4 !important; color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-subnav-header { color: #888 !important; }
|
|
/* content header & title */
|
|
body[data-corp-theme="light"] .corp-content-header { background: #ffffff !important; border-color: #c0ccd4 !important; box-shadow: 0 1px 0 rgba(15,30,50,0.04); }
|
|
body[data-corp-theme="light"] .corp-content-header .corp-header-title { color: #1c2733 !important; font-weight: 500; }
|
|
/* status bar */
|
|
body[data-corp-theme="light"] .corp-status-bar { background: #f6f8fa !important; color: #6a7782 !important; border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-status-bar-item { border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-status-bar-item strong { color: #1c2733 !important; }
|
|
/* overview cards */
|
|
body[data-corp-theme="light"] .corp-overview-card { background: #ffffff !important; border-color: #c0ccd4 !important; box-shadow: 0 1px 0 rgba(15,30,50,0.04); }
|
|
body[data-corp-theme="light"] .corp-overview-card:hover { border-color: #97a5b0 !important; box-shadow: 0 1px 4px rgba(15,30,50,0.08); }
|
|
body[data-corp-theme="light"] .corp-overview-label { color: #6a7782 !important; font-weight: 500; }
|
|
body[data-corp-theme="light"] .corp-overview-value { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .corp-overview-sub { color: #6a7782 !important; }
|
|
/* LW: Apr 2026 — improved light mode polish */
|
|
body[data-corp-theme="light"] .corp-capacity-bar { background: #e8ecef !important; }
|
|
body[data-corp-theme="light"] .corp-donut-track { stroke: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-task-panel { background: #fff !important; border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-desc { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-date { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-name { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-node { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar { background: #ffffff !important; border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar button { color: #44525e !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar button:hover { color: #1c2733 !important; background: #f6f8fa !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar-group { background: #ecf1f4 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher { background: #f6f8fa !important; border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button { color: #5a6772 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button:hover { color: #1c2733 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button.active { background: #0072a3 !important; color: #ffffff !important; }
|
|
body[data-corp-theme="light"] .corp-event-log { background: #f5f7f9 !important; border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .bg-green-500\/10 { background: rgba(34,197,94,0.08) !important; }
|
|
body[data-corp-theme="light"] .bg-red-500\/10 { background: rgba(239,68,68,0.06) !important; }
|
|
body[data-corp-theme="light"] .bg-yellow-500\/10 { background: rgba(234,179,8,0.08) !important; }
|
|
body[data-corp-theme="light"] .bg-amber-500\/5,
|
|
body[data-corp-theme="light"] .bg-amber-500\/10,
|
|
body[data-corp-theme="light"] .bg-amber-500\/20 { background: rgba(245,158,11,0.10) !important; }
|
|
body[data-corp-theme="light"] .border-amber-500\/20,
|
|
body[data-corp-theme="light"] .border-amber-500\/30,
|
|
body[data-corp-theme="light"] .border-amber-500\/50 { border-color: rgba(245,158,11,0.40) !important; }
|
|
body[data-corp-theme="light"] .bg-blue-500\/10 { background: rgba(59,130,246,0.06) !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-orange\/10 { background: rgba(229,112,0,0.08) !important; }
|
|
body[data-corp-theme="light"] .bg-proxmox-orange\/20 { background: rgba(229,112,0,0.12) !important; }
|
|
body[data-corp-theme="light"] select option { background: #fff; color: #333; }
|
|
body[data-corp-theme="light"] ::placeholder { color: #aaa !important; }
|
|
body[data-corp-theme="light"] canvas { filter: saturate(0.85); }
|
|
body[data-corp-theme="light"] .text-green-400,
|
|
body[data-corp-theme="light"] .text-green-400\/80,
|
|
body[data-corp-theme="light"] .text-green-300 { color: #16a34a !important; }
|
|
body[data-corp-theme="light"] .text-red-400,
|
|
body[data-corp-theme="light"] .text-red-400\/80,
|
|
body[data-corp-theme="light"] .text-red-300 { color: #dc2626 !important; }
|
|
body[data-corp-theme="light"] .text-yellow-400,
|
|
body[data-corp-theme="light"] .text-yellow-400\/80,
|
|
body[data-corp-theme="light"] .text-yellow-300,
|
|
body[data-corp-theme="light"] .text-yellow-300\/80,
|
|
body[data-corp-theme="light"] .text-yellow-200,
|
|
body[data-corp-theme="light"] .text-amber-400,
|
|
body[data-corp-theme="light"] .text-amber-400\/80,
|
|
body[data-corp-theme="light"] .text-amber-300 { color: #b45309 !important; }
|
|
body[data-corp-theme="light"] .text-blue-400,
|
|
body[data-corp-theme="light"] .text-blue-400\/80,
|
|
body[data-corp-theme="light"] .text-blue-300,
|
|
body[data-corp-theme="light"] .text-cyan-400,
|
|
body[data-corp-theme="light"] .text-cyan-300 { color: #2563eb !important; }
|
|
body[data-corp-theme="light"] .text-orange-400,
|
|
body[data-corp-theme="light"] .text-orange-300 { color: #c2410c !important; }
|
|
body[data-corp-theme="light"] .text-purple-400,
|
|
body[data-corp-theme="light"] .text-purple-300 { color: #7c3aed !important; }
|
|
body[data-corp-theme="light"] .text-pink-400,
|
|
body[data-corp-theme="light"] .text-pink-300 { color: #db2777 !important; }
|
|
body[data-corp-theme="light"] .text-proxmox-orange { color: #c2610a !important; }
|
|
body[data-corp-theme="light"] .bg-black\/50 { background: rgba(0,0,0,0.25) !important; }
|
|
body[data-corp-theme="light"] .bg-black\/60 { background: rgba(0,0,0,0.3) !important; }
|
|
body[data-corp-theme="light"] .bg-black\/70 { background: rgba(0,0,0,0.35) !important; }
|
|
/* badges */
|
|
body[data-corp-theme="light"] .corp-badge-running { background: rgba(34,197,94,0.12) !important; color: #16a34a !important; border-color: rgba(34,197,94,0.3) !important; }
|
|
body[data-corp-theme="light"] .corp-badge-stopped { background: #f0f0f0 !important; color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-badge-online { background: rgba(34,197,94,0.1) !important; color: #16a34a !important; }
|
|
body[data-corp-theme="light"] .corp-badge-offline { background: rgba(239,68,68,0.1) !important; color: #dc2626 !important; }
|
|
body[data-corp-theme="light"] .corp-badge-maintenance { background: rgba(234,179,8,0.1) !important; color: #ca8a04 !important; }
|
|
body[data-corp-theme="light"] .corp-badge-ha { background: rgba(59,130,246,0.1) !important; color: #2563eb !important; }
|
|
body[data-corp-theme="light"] .corp-badge-locked { background: #f5f5f5 !important; color: #888 !important; }
|
|
/* rows + selections */
|
|
body[data-corp-theme="light"] .corp-consumer-row { border-color: #e8ecef !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-row:hover { background: #f0f5fa !important; }
|
|
body[data-corp-theme="light"] .corp-row-selected { background: #e3f2fd !important; }
|
|
body[data-corp-theme="light"] .corp-selected { background: #e3f2fd !important; }
|
|
body[data-corp-theme="light"] .corp-hover-tip-row { background: #f5f7f9 !important; }
|
|
/* consumers list + bars */
|
|
body[data-corp-theme="light"] .corp-consumers-list { border-color: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-bar-fill { opacity: 0.8; }
|
|
/* datacenter section headers */
|
|
body[data-corp-theme="light"] .corp-dc-section-header { background: #f0f2f5 !important; color: #555 !important; border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-dc-section-icon { color: #0072a3 !important; }
|
|
/* storage cards */
|
|
body[data-corp-theme="light"] .corp-storage-card { background: #ffffff !important; border-color: #c0ccd4 !important; }
|
|
body[data-corp-theme="light"] .corp-storage-card:hover { border-color: #0072a3 !important; box-shadow: 0 0 0 1px rgba(0,114,163,0.15); }
|
|
/* node detail grid */
|
|
body[data-corp-theme="light"] .corp-node-detail-grid { background: #f5f7f9 !important; }
|
|
/* skeleton loaders */
|
|
body[data-corp-theme="light"] .corp-skeleton-text,
|
|
body[data-corp-theme="light"] .corp-skeleton-bar,
|
|
body[data-corp-theme="light"] .corp-skeleton-badge { background: #e8ecef !important; }
|
|
/* warning banner */
|
|
body[data-corp-theme="light"] .corp-warning-banner { background: #fff3cd !important; color: #856404 !important; border-color: #ffc107 !important; }
|
|
body[data-corp-theme="light"] .corp-warning-dismiss { color: #856404 !important; }
|
|
/* context menu separator */
|
|
body[data-corp-theme="light"] .corp-ctx-separator { border-color: #e0e0e0 !important; }
|
|
/* sort icon */
|
|
body[data-corp-theme="light"] .corp-sort-icon { color: #aaa !important; }
|
|
/* tree */
|
|
body[data-corp-theme="light"] .corp-tree-child { border-color: #ddd !important; }
|
|
/* type filters */
|
|
body[data-corp-theme="light"] .corp-type-filters { background: #f5f7f9 !important; border-color: #ddd !important; }
|
|
/* tasks status indicator */
|
|
body[data-corp-theme="light"] .corp-tasks-status { color: #555 !important; }
|
|
/* rename btn */
|
|
body[data-corp-theme="light"] .corp-rename-btn { color: #777 !important; }
|
|
body[data-corp-theme="light"] .corp-rename-btn:hover { color: #0072a3 !important; }
|
|
/* action group */
|
|
body[data-corp-theme="light"] .corp-action-group button { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-action-group button:hover { color: #0072a3 !important; background: rgba(0,114,163,0.06) !important; }
|
|
/* resize handle */
|
|
body[data-corp-theme="light"] .corp-resize-handle { background: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-resize-handle:hover { background: #0072a3 !important; }
|
|
/* event types */
|
|
body[data-corp-theme="light"] .corp-event-type-success { color: #16a34a !important; }
|
|
body[data-corp-theme="light"] .corp-event-type-error { color: #dc2626 !important; }
|
|
body[data-corp-theme="light"] .corp-event-type-action { color: #0072a3 !important; }
|
|
/* sparklines */
|
|
body[data-corp-theme="light"] .corp-sparkline-inline { opacity: 0.7; }
|
|
body[data-corp-theme="light"] .corp-vm-sparkline { opacity: 0.7; }
|
|
/* overview lower section */
|
|
body[data-corp-theme="light"] .corp-overview-lower { background: #f5f7f9 !important; border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-overview-grid { gap: 12px; }
|
|
/* flash offline animation */
|
|
body[data-corp-theme="light"] .corp-flash-offline { background: rgba(239,68,68,0.06) !important; }
|
|
/* progress scan bar */
|
|
body[data-corp-theme="light"] .corp-progress-scan { background: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-donut-track { stroke: #e0e4e8 !important; }
|
|
/* breadcrumbs */
|
|
body[data-corp-theme="light"] .corp-breadcrumb-segment { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-breadcrumb-segment:hover { color: #333 !important; background: rgba(0,114,163,0.06) !important; }
|
|
body[data-corp-theme="light"] .corp-breadcrumb-current { color: #333 !important; }
|
|
/* view switcher */
|
|
body[data-corp-theme="light"] .corp-view-switcher { background: #f0f2f5 !important; border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button:hover { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-view-switcher button.active { color: #0072a3 !important; background: rgba(0,114,163,0.1) !important; }
|
|
/* tooltips */
|
|
body[data-corp-theme="light"] .corp-hover-tip { background: #fff !important; border-color: #cfd8dc !important; box-shadow: 0 4px 12px rgba(0,0,0,0.12) !important; }
|
|
body[data-corp-theme="light"] .corp-hover-tip-header { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-hover-tip-label { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-hover-tip-value { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-hover-tip-bar { background: #e0e4e8 !important; }
|
|
/* action buttons */
|
|
body[data-corp-theme="light"] .corp-action-btn { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-action-btn:hover { color: #333 !important; background: #e8f0f4 !important; }
|
|
/* toolbar */
|
|
body[data-corp-theme="light"] .corp-toolbar button { color: #555 !important; border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar button:hover { background: rgba(0,114,163,0.08) !important; color: #0072a3 !important; }
|
|
body[data-corp-theme="light"] .corp-vm-toolbar { border-color: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar-divider { background: #ddd !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar-filter { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar-filter:hover { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-toolbar-filter.active { color: #0072a3 !important; }
|
|
/* consumers / detail panels */
|
|
body[data-corp-theme="light"] .corp-consumer-rank { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-name { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-node { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-bar { background: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-consumer-val { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-item { border-color: #e8ecef !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-desc { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-node { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-tasks-time { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-node-detail-label { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-node-detail-value { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-node-detail-sub { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-node-detail-card { background: #f5f7f9 !important; border-color: #cfd8dc !important; }
|
|
/* datacenter / storage */
|
|
body[data-corp-theme="light"] .corp-dc-section-desc { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-dc-section-title { color: #333 !important; }
|
|
body[data-corp-theme="light"] .corp-storage-cap-bar { background: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-storage-type-badge { border-color: #cfd8dc !important; }
|
|
/* services bar */
|
|
body[data-corp-theme="light"] .corp-services-bar { background: #f5f7f9 !important; border-color: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-svc-item { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-svc-label { color: #888 !important; }
|
|
/* recent items */
|
|
body[data-corp-theme="light"] .corp-recent-item { color: #555 !important; }
|
|
body[data-corp-theme="light"] .corp-recent-item:hover { background: #e8f0f4 !important; color: #333 !important; }
|
|
/* event log */
|
|
body[data-corp-theme="light"] .corp-event-item:hover { background: #f5f7f9 !important; }
|
|
body[data-corp-theme="light"] .corp-event-time { color: #888 !important; }
|
|
/* skeleton loading */
|
|
body[data-corp-theme="light"] .corp-skeleton { background: linear-gradient(90deg, #e8ecef 0%, #f5f7f9 50%, #e8ecef 100%) !important; background-size: 200% 100% !important; }
|
|
/* section header */
|
|
body[data-corp-theme="light"] .corp-section-header { color: #888 !important; }
|
|
/* datagrid striped */
|
|
body[data-corp-theme="light"] .corp-datagrid-striped tbody tr:nth-child(even) { background: rgba(0,0,0,0.02) !important; }
|
|
/* node row */
|
|
body[data-corp-theme="light"] .corp-node-row { border-color: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] .corp-node-row:hover { background: #e8f0f4 !important; }
|
|
/* progress bar */
|
|
body[data-corp-theme="light"] .corp-progress-indeterminate { background: #e0e4e8 !important; }
|
|
/* sort icons */
|
|
body[data-corp-theme="light"] .corp-sort-hint path { fill: #bbb !important; }
|
|
/* property grid */
|
|
body[data-corp-theme="light"] .corp-property-grid td:first-child { color: #888 !important; }
|
|
body[data-corp-theme="light"] .corp-property-grid td { color: #333 !important; border-color: #e8ecef !important; }
|
|
/* dropdown */
|
|
body[data-corp-theme="light"] .corp-dropdown { background: #fff !important; border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .corp-dropdown button:hover { background: #e8f0f4 !important; }
|
|
|
|
/* additional inline style overrides for backgrounds not yet covered */
|
|
body[data-corp-theme="light"] [style*="background: #1a2e38"],
|
|
body[data-corp-theme="light"] [style*="background-color: #1a2e38"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(26, 46, 56)"] { background: #e0e4e8 !important; background-color: #e0e4e8 !important; }
|
|
body[data-corp-theme="light"] [style*="background: #29414e"],
|
|
body[data-corp-theme="light"] [style*="background-color: #29414e"],
|
|
body[data-corp-theme="light"] [style*="background: rgb(41, 65, 78)"] { background: #e8f0f4 !important; background-color: #e8f0f4 !important; }
|
|
body[data-corp-theme="light"] [style*="background: #1b2a32"],
|
|
body[data-corp-theme="light"] [style*="background-color: #1b2a32"] { background: #e0e4e8 !important; background-color: #e0e4e8 !important; }
|
|
/* muted text colors not yet covered */
|
|
body[data-corp-theme="light"] [style*="color: #3d5a6a"],
|
|
body[data-corp-theme="light"] [style*="color: rgb(61, 90, 106)"] { color: #999 !important; }
|
|
body[data-corp-theme="light"] [style*="color: #6a8a9a"],
|
|
body[data-corp-theme="light"] [style*="color: rgb(106, 138, 154)"] { color: #888 !important; }
|
|
body[data-corp-theme="light"] [style*="color: #4a6070"],
|
|
body[data-corp-theme="light"] [style*="color: rgb(74, 96, 112)"] { color: #999 !important; }
|
|
/* border color overrides */
|
|
body[data-corp-theme="light"] [style*="border-color: #485764"],
|
|
body[data-corp-theme="light"] [style*="border: 1px solid #485764"] { border-color: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] [style*="border-bottom: 1px solid #37474f"],
|
|
body[data-corp-theme="light"] [style*="border-top: 1px solid #37474f"],
|
|
body[data-corp-theme="light"] [style*="border-bottom: 2px solid #283844"] { border-color: #ddd !important; }
|
|
/* rgba() dark backgrounds (tooltip overlays etc) */
|
|
body[data-corp-theme="light"] [style*="rgba(20,25,35"],
|
|
body[data-corp-theme="light"] [style*="rgba(20, 25, 35"] { background: rgba(255,255,255,0.95) !important; border-color: #cfd8dc !important; }
|
|
/* toggle switch */
|
|
body[data-corp-theme="light"] .toggle-switch { background: #cfd8dc !important; }
|
|
body[data-corp-theme="light"] .toggle-switch.active { background: var(--corp-accent) !important; }
|
|
|
|
/* LW Apr 2026 (#296) — light-mode polish for the spots proxforge flagged.
|
|
The aggressive light-mode overrides above caught 90% of elements, but three
|
|
concrete patterns were still dark-on-light or bleached grey on white:
|
|
search inputs rendered inline, secondary-text grays too weak for WCAG AA,
|
|
and "card-style" buttons with text-gray-400 on white card bg. */
|
|
|
|
/* (1) search bars — inline styles on the filter/search inputs didn't get
|
|
caught by the generic input override because they set explicit rgba()
|
|
backgrounds via inline style. Force white + dark text + visible border. */
|
|
body[data-corp-theme="light"] input[type="text"][placeholder],
|
|
body[data-corp-theme="light"] input[type="search"],
|
|
body[data-corp-theme="light"] input[placeholder*="Filter"],
|
|
body[data-corp-theme="light"] input[placeholder*="filter"],
|
|
body[data-corp-theme="light"] input[placeholder*="Suchen"],
|
|
body[data-corp-theme="light"] input[placeholder*="Search"],
|
|
body[data-corp-theme="light"] input[placeholder*="search"] {
|
|
background: #fff !important;
|
|
color: #222 !important;
|
|
border-color: #b0bec5 !important;
|
|
}
|
|
body[data-corp-theme="light"] input::placeholder { color: #8a99a5 !important; }
|
|
|
|
/* (2) darker text for low-importance labels — #777 / #888 bleached against
|
|
white cards. Push toward AA. Keep .text-gray-500 slightly lighter than
|
|
.text-gray-400 so hierarchy survives. */
|
|
body[data-corp-theme="light"] .text-gray-400 { color: #4a5561 !important; }
|
|
body[data-corp-theme="light"] .text-gray-500 { color: #5e6a75 !important; }
|
|
/* and the inline-style twins that React sometimes emits as hex/rgb */
|
|
body[data-corp-theme="light"] [style*="color: #728b9a"],
|
|
body[data-corp-theme="light"] [style*="color: rgb(114, 139, 154)"],
|
|
body[data-corp-theme="light"] [style*="color: #adbbc4"],
|
|
body[data-corp-theme="light"] [style*="color: rgb(173, 187, 196)"] { color: #5e6a75 !important; }
|
|
|
|
/* (3) buttons that use bg-proxmox-card + text-gray-400 (e.g. the Storage tab
|
|
buttons incl. ISO-Sync tab). In dark mode they read fine; in light mode
|
|
the card bg is white and the text-gray-400 barely shows. Treat them like
|
|
inactive tabs: light-grey surface, mid-tone text, accent on hover/active. */
|
|
body[data-corp-theme="light"] button.bg-proxmox-card { background: #f0f2f5 !important; border: 1px solid #cfd8dc !important; }
|
|
body[data-corp-theme="light"] button.bg-proxmox-card.text-gray-400 { color: #455560 !important; }
|
|
body[data-corp-theme="light"] button.bg-proxmox-card:hover { color: #0072a3 !important; background: #e8f0f4 !important; }
|
|
/* active tab styling already lands via bg-proxmox-orange → leave it */
|
|
|
|
/* NS: xterm.js terminal must not inherit corporate spacing/font overrides */
|
|
body[data-layout="corporate"] .xterm,
|
|
body[data-layout="corporate"] .xterm * {
|
|
letter-spacing: normal !important;
|
|
text-transform: none !important;
|
|
font-variant: normal !important;
|
|
}
|
|
body[data-layout="corporate"] .xterm .xterm-rows span {
|
|
letter-spacing: 0 !important;
|
|
}
|
|
|
|
/* Kill all decorative effects */
|
|
body[data-layout="corporate"] .gradient-mesh,
|
|
body[data-layout="corporate"] .noise-overlay { display: none !important; }
|
|
/* User-toggle (#342): kill noise overlay in modern layout too if user opted out */
|
|
body[data-noise="off"] .noise-overlay { display: none !important; }
|
|
body[data-layout="corporate"] .glow-orange { box-shadow: none !important; }
|
|
body[data-layout="corporate"] .backdrop-blur-xl,
|
|
body[data-layout="corporate"] .backdrop-blur-sm,
|
|
body[data-layout="corporate"] .backdrop-blur { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
|
|
|
|
/* Kill all animations except spin (loading spinners need it) */
|
|
body[data-layout="corporate"] .animate-slide-up,
|
|
body[data-layout="corporate"] .animate-fade-in,
|
|
body[data-layout="corporate"] .animate-scale-in,
|
|
body[data-layout="corporate"] .animate-pulse,
|
|
body[data-layout="corporate"] .animate-bounce { animation: none !important; }
|
|
body[data-layout="corporate"] .status-online { animation: none !important; }
|
|
body[data-layout="corporate"] .card-hover { transform: none !important; }
|
|
/* MK: Mar 2026 - targeted transitions instead of blanket duration override */
|
|
body[data-layout="corporate"] button,
|
|
body[data-layout="corporate"] a,
|
|
body[data-layout="corporate"] .corp-action-btn,
|
|
body[data-layout="corporate"] input,
|
|
body[data-layout="corporate"] select { transition: background 0.15s ease, color 0.12s ease, border-color 0.15s ease, box-shadow 0.15s ease; }
|
|
|
|
/* Sharp corners everywhere - corporate has no rounded corners */
|
|
body[data-layout="corporate"] .rounded,
|
|
body[data-layout="corporate"] .rounded-md,
|
|
body[data-layout="corporate"] .rounded-lg,
|
|
body[data-layout="corporate"] .rounded-xl,
|
|
body[data-layout="corporate"] .rounded-2xl,
|
|
body[data-layout="corporate"] .rounded-3xl,
|
|
body[data-layout="corporate"] .rounded-full:not(.w-2):not(.w-1\.5):not(.h-2):not(.h-1\.5):not(.w-1):not(.h-1) { border-radius: 3px !important; }
|
|
|
|
/* Kill all gradients - flat solid colors only */
|
|
body[data-layout="corporate"] [class*="bg-gradient"],
|
|
body[data-layout="corporate"] [class*="from-"],
|
|
body[data-layout="corporate"] .bg-gradient-to-r,
|
|
body[data-layout="corporate"] .bg-gradient-to-br,
|
|
body[data-layout="corporate"] .bg-gradient-to-b { background-image: none !important; }
|
|
|
|
/* Kill all box shadows - flat corporate look */
|
|
body[data-layout="corporate"] .shadow-lg,
|
|
body[data-layout="corporate"] .shadow-xl,
|
|
body[data-layout="corporate"] .shadow-2xl { box-shadow: none !important; }
|
|
body[data-layout="corporate"] [class*="hover:shadow"] { box-shadow: none !important; }
|
|
|
|
/* Corporate sidebar - tree-view with border separator */
|
|
body[data-layout="corporate"] .corporate-sidebar {
|
|
border-right: 1px solid var(--corp-border-medium);
|
|
background: var(--corp-surface-1);
|
|
box-shadow: var(--corp-shadow-md);
|
|
}
|
|
|
|
/* Override orange accent to Clarity blue in corporate */
|
|
body[data-layout="corporate"] .text-proxmox-orange { color: var(--corp-accent) !important; }
|
|
body[data-layout="corporate"] .bg-proxmox-orange { background-color: var(--corp-accent) !important; }
|
|
body[data-layout="corporate"] .border-proxmox-orange\/30 { border-color: rgba(73, 175, 217, 0.3) !important; }
|
|
body[data-layout="corporate"] .hover\:bg-proxmox-orange:hover { background-color: #3d9bc2 !important; }
|
|
body[data-layout="corporate"] .hover\:bg-orange-600:hover { background-color: #3d9bc2 !important; }
|
|
body[data-layout="corporate"] .bg-proxmox-orange\/20 { background-color: rgba(73, 175, 217, 0.2) !important; }
|
|
body[data-layout="corporate"] .bg-proxmox-orange\/30 { background-color: rgba(73, 175, 217, 0.3) !important; }
|
|
body[data-layout="corporate"] .ring-proxmox-orange\/50 { --tw-ring-color: rgba(73, 175, 217, 0.5) !important; }
|
|
body[data-layout="corporate"] .focus-within\:border-proxmox-orange\/50:focus-within { border-color: rgba(73, 175, 217, 0.5) !important; }
|
|
|
|
/* Dense corporate tables */
|
|
body[data-layout="corporate"] table td,
|
|
body[data-layout="corporate"] table th { padding: 6px 12px !important; font-size: 13px !important; }
|
|
|
|
/* Kill hover scale effects */
|
|
body[data-layout="corporate"] .hover\:scale-105:hover,
|
|
body[data-layout="corporate"] .hover\:scale-110:hover { transform: none !important; }
|
|
|
|
/* Compact form inputs */
|
|
body[data-layout="corporate"] input,
|
|
body[data-layout="corporate"] select,
|
|
body[data-layout="corporate"] textarea { border-radius: 3px !important; }
|
|
|
|
/* Modal overrides - LW: subtle blur instead of flat */
|
|
body[data-layout="corporate"] .modal-backdrop { backdrop-filter: blur(3px) !important; -webkit-backdrop-filter: blur(3px) !important; }
|
|
|
|
/* Scrollbar styling for corporate */
|
|
body[data-layout="corporate"] ::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
body[data-layout="corporate"] ::-webkit-scrollbar-track { background: transparent; }
|
|
body[data-layout="corporate"] ::-webkit-scrollbar-thumb { background: rgba(73,175,217,0.15); border-radius: 4px; }
|
|
body[data-layout="corporate"] ::-webkit-scrollbar-thumb:hover { background: rgba(73,175,217,0.3); }
|
|
|
|
/* LW: Feb 2026 - Corporate VM Detail property grid (Clarity dark theme) */
|
|
.corp-property-grid { width: 100%; border-collapse: collapse; }
|
|
.corp-property-grid td { padding: 6px 14px; font-size: 13px; border-bottom: 1px solid var(--corp-divider, #37474f); }
|
|
.corp-property-grid td:first-child { color: var(--corp-text-secondary, #adbbc4); white-space: nowrap; width: 150px; }
|
|
.corp-property-grid td:last-child { color: var(--color-text, #e9ecef); }
|
|
.corp-property-grid tr:last-child td { border-bottom: none; }
|
|
|
|
/* Corporate toolbar buttons (Clarity flat buttons) */
|
|
.corp-toolbar button {
|
|
padding: 4px 10px; font-size: 13px; border: 1px solid var(--color-border, #485764);
|
|
background: transparent; color: var(--corp-text-secondary, #adbbc4); cursor: pointer; display: inline-flex;
|
|
align-items: center; gap: 4px; border-radius: 3px !important;
|
|
}
|
|
.corp-toolbar button:hover { background: rgba(73, 175, 217, 0.12); border-color: var(--corp-accent, #49afd9); color: #fff; }
|
|
/* NS 2026-06-05 (UI polish, a11y): keyboard focus ring — the tab strip already
|
|
had one, the toolbar buttons didn't. */
|
|
.corp-toolbar button:focus-visible { outline: 2px solid var(--corp-accent, #49afd9); outline-offset: 1px; }
|
|
.corp-toolbar button:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
.corp-toolbar button:disabled:hover { background: transparent; border-color: var(--color-border, #485764); color: var(--corp-text-secondary, #adbbc4); }
|
|
|
|
@keyframes corp-content-fade { from { opacity: 0.6; } to { opacity: 1; } }
|
|
.corp-content-fade { animation: corp-content-fade 0.15s ease-out; }
|
|
|
|
/* Corporate node compact row */
|
|
.corp-node-row { border-bottom: 1px solid var(--corp-divider, #37474f); border-left: 3px solid transparent; }
|
|
.corp-node-row:hover { background: rgba(73,175,217,0.04); }
|
|
.corp-node-row:last-child { border-bottom: none; }
|
|
.corp-node-row.node-online { border-left-color: #60b515; }
|
|
.corp-node-row.node-maintenance { border-left-color: #efc006; }
|
|
.corp-node-row.node-offline { border-left-color: #f54f47; }
|
|
|
|
/* Corporate tab strip (flat tabs) - transparent bg, underline active.
|
|
NS 2026-05-10: tighter padding (8/14), focus-visible ring, light-mode
|
|
hover that doesn't tint the bg cyan. */
|
|
.corp-tab-strip { border-bottom: 1px solid var(--corp-border-medium, #344955); display: flex; gap: 0; padding: 0 8px; background: transparent; }
|
|
.corp-tab-strip button { padding: 8px 14px; font-size: 12.5px; color: var(--corp-text-secondary, #adbbc4); border: none; background: none;
|
|
cursor: pointer; margin-bottom: -1px; border-bottom: 2px solid transparent; white-space: nowrap; display: flex; align-items: center; gap: 6px;
|
|
font-family: inherit; transition: color .12s, border-color .12s, background .12s; }
|
|
.corp-tab-strip button:hover { color: var(--color-text, #e9ecef); background: rgba(73,175,217,0.05); }
|
|
.corp-tab-strip button.active { color: var(--color-text, #e9ecef); font-weight: 500; background: rgba(73,175,217,0.08); border-bottom-color: var(--corp-accent); }
|
|
.corp-tab-strip button:focus-visible { outline: 2px solid var(--corp-accent, #49afd9); outline-offset: -2px; }
|
|
[data-corp-theme="light"] .corp-tab-strip { border-bottom-color: #c0ccd4; }
|
|
[data-corp-theme="light"] .corp-tab-strip button { color: #44525e; }
|
|
[data-corp-theme="light"] .corp-tab-strip button:hover { color: #1c2733; background: rgba(0,114,163,0.05); }
|
|
[data-corp-theme="light"] .corp-tab-strip button.active { color: #1c2733; background: rgba(0,114,163,0.07); border-bottom-color: #0072a3; }
|
|
|
|
/* Corporate section headers */
|
|
.corp-section-header { font-size: 11px; font-weight: 600; color: var(--corp-text-muted, #728b9a); text-transform: uppercase;
|
|
letter-spacing: 0.08em; padding: 12px 0 8px; border-bottom: 2px solid var(--corp-border-subtle, #283844); margin-bottom: 8px; }
|
|
|
|
/* Corporate action dropdown */
|
|
.corp-dropdown { background: var(--color-card, #22343c); border: 1px solid var(--color-border, #485764); border-radius: var(--corp-radius-md); box-shadow: var(--corp-shadow-lg, 0 4px 12px rgba(0,0,0,0.3));
|
|
animation: corp-dropdown-in 0.12s ease-out; transform-origin: top; }
|
|
.corp-dropdown button:hover { background: var(--color-hover, #29414e); }
|
|
/* NS 2026-06-05 (UI polish): subtle fade/scale-in so menus don't pop abruptly */
|
|
@keyframes corp-dropdown-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }
|
|
|
|
/* LW: Mar 2026 - Right-click context menu for sidebar tree */
|
|
.corp-context-menu { background: var(--corp-surface-3); border: 1px solid var(--corp-border-medium); border-radius: var(--corp-radius-md); box-shadow: var(--corp-shadow-lg, 0 4px 12px rgba(0,0,0,0.3)); min-width: 200px; max-width: 280px; padding: 4px 0; font-size: 13px; z-index: 999; }
|
|
.corp-ctx-item { display: flex; align-items: center; gap: 8px; width: 100%; padding: 5px 12px; color: var(--corp-text-secondary); background: none; border: none; cursor: pointer; text-align: left; white-space: nowrap; font-size: 13px; font-family: inherit; }
|
|
.corp-ctx-item:hover:not(:disabled) { background: var(--color-hover); color: var(--color-text); }
|
|
.corp-ctx-item:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
.corp-ctx-item.ctx-danger { color: var(--color-error); }
|
|
.corp-ctx-item.ctx-danger:hover:not(:disabled) { background: rgba(245,79,71,0.12); color: var(--color-error); }
|
|
.corp-ctx-separator { height: 1px; background: var(--corp-divider); margin: 4px 8px; }
|
|
.corp-ctx-submenu-arrow { margin-left: auto; opacity: 0.5; }
|
|
|
|
/* Corporate selection highlight (sidebar tree items) */
|
|
.corp-selected { background: rgba(73,175,217,0.10) !important; color: #fff !important; border-left: 2px solid #49afd9; }
|
|
|
|
/* Corporate status badges */
|
|
.corp-badge { padding: 1px 6px; font-size: 11px; font-weight: 500; border-radius: 3px; border: 1px solid transparent; }
|
|
.corp-badge::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 5px; vertical-align: middle; }
|
|
.corp-badge-running { background: rgba(96, 181, 21, 0.12); color: #60b515; }
|
|
.corp-badge-stopped { background: rgba(114, 139, 154, 0.12); color: #728b9a; }
|
|
.corp-badge-ha { background: rgba(73, 175, 217, 0.12); color: #49afd9; }
|
|
.corp-badge-locked { background: rgba(239, 192, 6, 0.12); color: #efc006; }
|
|
|
|
/* LW: Feb 2026 - Corporate Node Detail sub-navigation */
|
|
.corp-subnav { min-width: 200px; width: auto; border-right: 1px solid var(--corp-divider, #37474f); flex-shrink: 0; }
|
|
.corp-subnav-item { padding: 5px 12px; font-size: 13px; color: var(--corp-text-secondary, #adbbc4); cursor: pointer; display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; border: none; background: none; border-left: 2px solid transparent; white-space: nowrap; }
|
|
.corp-subnav-item:hover { color: var(--color-text, #e9ecef); background: rgba(73, 175, 217, 0.06); }
|
|
.corp-subnav-item.active { background: var(--corp-selection, #324f61); border-left-color: var(--corp-accent, #49afd9); color: var(--color-text, #e9ecef); }
|
|
.corp-subnav-header { padding: 8px 12px 4px; font-size: 11px; font-weight: 600; color: var(--corp-text-muted, #728b9a); text-transform: uppercase; letter-spacing: 0.05em; }
|
|
|
|
/* ============================================================
|
|
NS May 2026 — VM Configure modal (Corporate layout, corporate flat style)
|
|
============================================================
|
|
Drives the redesigned Configure modal. Goals: flat surfaces,
|
|
thin dividers, light-weight title typography, narrow sidebar
|
|
tab tree (where applicable), property-list rows. Avoids the
|
|
Modern dark-pill tab look that felt foreign in Corporate. */
|
|
.corp-vm-modal-overlay {
|
|
position: fixed; inset: 0; z-index: 50;
|
|
display: flex; align-items: stretch; justify-content: center;
|
|
background: rgba(0, 0, 0, 0.55);
|
|
backdrop-filter: saturate(120%) blur(2px);
|
|
-webkit-backdrop-filter: saturate(120%) blur(2px);
|
|
padding: 16px;
|
|
}
|
|
.corp-vm-modal {
|
|
width: 100%;
|
|
max-width: 1400px;
|
|
max-height: 100%;
|
|
display: flex; flex-direction: column;
|
|
background: var(--corp-surface-1, #111a21);
|
|
border: 1px solid var(--corp-border-medium, #344955);
|
|
border-radius: 4px;
|
|
box-shadow: var(--corp-shadow-xl, 0 8px 24px rgba(0,0,0,0.4));
|
|
overflow: hidden;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal {
|
|
background: #ffffff;
|
|
border-color: #c0ccd4;
|
|
}
|
|
|
|
/* Top header bar — VM identity + actions. NS 2026-05-10: subtle
|
|
inset shadow on light mode adds depth without breaking flat style. */
|
|
.corp-vm-modal-header {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 14px 20px 12px;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
background: var(--corp-header-bg, #1a2730);
|
|
min-height: 60px;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-header {
|
|
background: #f6f8fa;
|
|
border-bottom-color: #c0ccd4;
|
|
}
|
|
.corp-vm-modal-header-left {
|
|
display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1;
|
|
}
|
|
.corp-vm-type-pill {
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
min-width: 36px; height: 22px; padding: 0 8px;
|
|
font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
|
|
font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;
|
|
color: #fff;
|
|
background: var(--corp-accent, #49afd9);
|
|
border-radius: 3px;
|
|
flex-shrink: 0;
|
|
}
|
|
.corp-vm-type-pill.lxc { background: #8b5cf6; }
|
|
.corp-vm-modal-title-block { min-width: 0; flex: 1; }
|
|
.corp-vm-modal-title {
|
|
font-size: 17px;
|
|
font-weight: 400;
|
|
letter-spacing: -0.01em;
|
|
color: var(--color-text, #e9ecef);
|
|
line-height: 1.25;
|
|
margin: 0;
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-title { color: #1c2733; font-weight: 500; }
|
|
.corp-vm-modal-meta {
|
|
display: flex; align-items: center; gap: 8px;
|
|
font-size: 11.5px;
|
|
color: var(--corp-text-muted, #728b9a);
|
|
margin-top: 3px;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-meta { color: #6a7782; }
|
|
.corp-vm-modal-meta .corp-meta-sep { opacity: 0.5; }
|
|
.corp-vm-modal-actions {
|
|
display: flex; align-items: center; gap: 8px;
|
|
flex-shrink: 0;
|
|
}
|
|
.corp-unsaved-pill {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 3px 10px; font-size: 11px; font-weight: 500;
|
|
background: rgba(239, 192, 6, 0.12);
|
|
color: #efc006;
|
|
border: 1px solid rgba(239, 192, 6, 0.32);
|
|
border-radius: 3px;
|
|
}
|
|
.corp-unsaved-pill::before {
|
|
content: ''; width: 6px; height: 6px; border-radius: 50%;
|
|
background: #efc006;
|
|
animation: corp-pulse 1.6s ease-in-out infinite;
|
|
}
|
|
@keyframes corp-pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.4; }
|
|
}
|
|
|
|
/* Action buttons inside the modal header. NS 2026-05-10: tighter
|
|
padding (5/12), explicit focus-visible ring, light-mode hover that
|
|
uses surface tint instead of accent-tint (reads cleaner on white). */
|
|
.corp-vm-btn {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 5px 12px;
|
|
font-size: 12.5px; font-weight: 500;
|
|
border-radius: 3px;
|
|
border: 1px solid transparent;
|
|
cursor: pointer;
|
|
transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
|
|
font-family: inherit;
|
|
line-height: 1.2;
|
|
}
|
|
.corp-vm-btn:focus-visible {
|
|
outline: none;
|
|
box-shadow: 0 0 0 2px var(--corp-accent, #49afd9);
|
|
}
|
|
.corp-vm-btn-primary {
|
|
background: var(--corp-accent, #49afd9);
|
|
color: #fff;
|
|
border-color: var(--corp-accent, #49afd9);
|
|
}
|
|
.corp-vm-btn-primary:hover { filter: brightness(1.08); }
|
|
[data-corp-theme="light"] .corp-vm-btn-primary {
|
|
background: #0072a3;
|
|
border-color: #0072a3;
|
|
color: #fff;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-btn-primary:hover {
|
|
background: #005a85;
|
|
border-color: #005a85;
|
|
filter: none;
|
|
}
|
|
.corp-vm-btn-primary:disabled {
|
|
opacity: 0.45; cursor: not-allowed;
|
|
filter: none;
|
|
}
|
|
.corp-vm-btn-ghost {
|
|
background: transparent;
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
border-color: var(--corp-border-medium, #344955);
|
|
}
|
|
.corp-vm-btn-ghost:hover {
|
|
background: rgba(73, 175, 217, 0.06);
|
|
color: var(--color-text, #e9ecef);
|
|
border-color: var(--corp-accent, #49afd9);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-btn-ghost {
|
|
color: #44525e;
|
|
border-color: #c0ccd4;
|
|
background: #ffffff;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-btn-ghost:hover {
|
|
background: #f6f8fa;
|
|
color: #1c2733;
|
|
border-color: #97a5b0;
|
|
}
|
|
.corp-vm-btn-danger-ghost {
|
|
background: transparent;
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
border-color: var(--corp-border-medium, #344955);
|
|
}
|
|
.corp-vm-btn-danger-ghost:hover {
|
|
background: rgba(245, 79, 71, 0.08);
|
|
color: #f54f47;
|
|
border-color: rgba(245, 79, 71, 0.4);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-btn-danger-ghost {
|
|
color: #44525e;
|
|
border-color: #c0ccd4;
|
|
background: #ffffff;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-btn-danger-ghost:hover {
|
|
background: rgba(220, 38, 38, 0.06);
|
|
color: #c8262a;
|
|
border-color: rgba(220, 38, 38, 0.40);
|
|
}
|
|
|
|
/* Tab strip — sits below the header. NS 2026-05-10: tighter rhythm
|
|
(10/14 padding), 12.5px font for denser feel, shadow-inset bottom
|
|
border on light mode for cleaner separation, and a focus-visible
|
|
ring for keyboard nav. */
|
|
.corp-vm-modal-tabs {
|
|
display: flex; align-items: center;
|
|
gap: 0;
|
|
padding: 0 10px;
|
|
background: var(--corp-surface-2, #1a2730);
|
|
border-bottom: 1px solid var(--corp-border-medium, #344955);
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-tabs {
|
|
background: #f6f8fa;
|
|
border-bottom-color: #c0ccd4;
|
|
box-shadow: inset 0 -1px 0 rgba(15,30,50,0.04);
|
|
}
|
|
.corp-vm-modal-tabs::-webkit-scrollbar { display: none; }
|
|
.corp-vm-modal-tab {
|
|
display: inline-flex; align-items: center; gap: 7px;
|
|
padding: 10px 14px;
|
|
font-size: 12.5px; font-weight: 400;
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
background: none; border: none;
|
|
border-bottom: 2px solid transparent;
|
|
cursor: pointer; white-space: nowrap;
|
|
margin-bottom: -1px;
|
|
font-family: inherit;
|
|
letter-spacing: -0.005em;
|
|
transition: color 0.12s, border-color 0.12s, background 0.12s;
|
|
}
|
|
.corp-vm-modal-tab:hover {
|
|
color: var(--color-text, #e9ecef);
|
|
background: rgba(73, 175, 217, 0.04);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-tab:hover {
|
|
color: #1c2733;
|
|
background: rgba(0, 114, 163, 0.05);
|
|
}
|
|
.corp-vm-modal-tab:focus-visible {
|
|
outline: 2px solid var(--corp-accent, #49afd9);
|
|
outline-offset: -2px;
|
|
}
|
|
.corp-vm-modal-tab.active {
|
|
color: var(--corp-accent, #49afd9);
|
|
border-bottom-color: var(--corp-accent, #49afd9);
|
|
font-weight: 500;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-tab.active {
|
|
color: var(--corp-accent, #0072a3);
|
|
border-bottom-color: var(--corp-accent, #0072a3);
|
|
}
|
|
|
|
/* Body — the form area. NS 2026-05-10: explicit text colour so labels
|
|
inherit cleanly in light mode without relying on the global override
|
|
cascade. */
|
|
.corp-vm-modal-body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
background: var(--corp-surface-1, #111a21);
|
|
color: var(--color-text, #e9ecef);
|
|
padding: 20px 24px;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-body {
|
|
background: #ffffff;
|
|
color: #1c2733;
|
|
}
|
|
/* Inputs inside the modal body — explicit light-mode polish so they
|
|
match the surrounding chrome (the global form override misses some
|
|
because Tailwind utilities outrank it on specificity). */
|
|
[data-corp-theme="light"] .corp-vm-modal-body input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
|
|
[data-corp-theme="light"] .corp-vm-modal-body select,
|
|
[data-corp-theme="light"] .corp-vm-modal-body textarea {
|
|
background: #ffffff !important;
|
|
color: #1c2733 !important;
|
|
border: 1px solid #c0ccd4 !important;
|
|
border-radius: 3px !important;
|
|
padding: 6px 8px !important;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-body input:focus,
|
|
[data-corp-theme="light"] .corp-vm-modal-body select:focus,
|
|
[data-corp-theme="light"] .corp-vm-modal-body textarea:focus {
|
|
border-color: #0072a3 !important;
|
|
outline: none !important;
|
|
box-shadow: 0 0 0 3px rgba(0,114,163,0.15) !important;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-body label {
|
|
color: #1c2733;
|
|
}
|
|
|
|
/* Property list — corporate flat style key/value */
|
|
.corp-prop-list {
|
|
display: grid;
|
|
grid-template-columns: minmax(160px, 220px) 1fr;
|
|
row-gap: 0;
|
|
column-gap: 24px;
|
|
}
|
|
.corp-prop-list .corp-prop-row {
|
|
display: contents;
|
|
}
|
|
.corp-prop-list .corp-prop-label,
|
|
.corp-prop-list .corp-prop-value {
|
|
padding: 9px 0;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
font-size: 13px;
|
|
min-height: 38px;
|
|
display: flex; align-items: center;
|
|
}
|
|
[data-corp-theme="light"] .corp-prop-list .corp-prop-label,
|
|
[data-corp-theme="light"] .corp-prop-list .corp-prop-value {
|
|
border-bottom-color: #e9ecef;
|
|
}
|
|
.corp-prop-list .corp-prop-label {
|
|
color: var(--corp-text-muted, #728b9a);
|
|
font-weight: 400;
|
|
}
|
|
.corp-prop-list .corp-prop-value {
|
|
color: var(--color-text, #e9ecef);
|
|
}
|
|
.corp-prop-list .corp-prop-row:last-child .corp-prop-label,
|
|
.corp-prop-list .corp-prop-row:last-child .corp-prop-value {
|
|
border-bottom: none;
|
|
}
|
|
|
|
/* Section header inside the modal body */
|
|
.corp-vm-section-title {
|
|
font-size: 12px; font-weight: 600;
|
|
color: var(--corp-text-muted, #728b9a);
|
|
text-transform: uppercase; letter-spacing: 0.08em;
|
|
padding: 16px 0 10px;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
margin-bottom: 12px;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-section-title {
|
|
border-bottom-color: #c0ccd4;
|
|
color: #6a7782;
|
|
}
|
|
.corp-vm-section-title:first-child {
|
|
padding-top: 0;
|
|
}
|
|
|
|
/* Loading / error states inside the modal body */
|
|
.corp-vm-modal-state {
|
|
display: flex; flex-direction: column;
|
|
align-items: center; justify-content: center;
|
|
min-height: 320px;
|
|
text-align: center;
|
|
}
|
|
.corp-vm-spinner {
|
|
width: 32px; height: 32px;
|
|
border: 2px solid var(--corp-border-medium, #344955);
|
|
border-top-color: var(--corp-accent, #49afd9);
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
}
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
|
|
/* ============================================================
|
|
NS May 2026 — VM/CT Create wizard chrome (Corporate)
|
|
============================================================
|
|
Reuses corp-vm-modal-overlay/corp-vm-modal/corp-vm-modal-header
|
|
but adds a numbered stepper, footer bar, and a small warning row. */
|
|
|
|
/* Warning strip between header and stepper (e.g. no nodes available) */
|
|
.corp-vm-modal-warning {
|
|
display: flex; align-items: center; gap: 8px;
|
|
padding: 8px 20px;
|
|
font-size: 12px;
|
|
color: #efc006;
|
|
background: rgba(239, 192, 6, 0.10);
|
|
border-bottom: 1px solid rgba(239, 192, 6, 0.30);
|
|
}
|
|
|
|
/* Numbered stepper (numbered "1 — Edit settings — 2 — …" wizard pattern) */
|
|
.corp-vm-stepper {
|
|
display: flex; align-items: stretch;
|
|
padding: 14px 20px 14px;
|
|
background: var(--corp-surface-2, #1a2730);
|
|
border-bottom: 1px solid var(--corp-border-medium, #344955);
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-stepper {
|
|
background: #fafbfc;
|
|
border-bottom-color: #e0e4e8;
|
|
}
|
|
.corp-vm-stepper::-webkit-scrollbar { display: none; }
|
|
|
|
.corp-vm-step {
|
|
display: inline-flex; align-items: center; gap: 8px;
|
|
padding: 4px 8px 4px 4px;
|
|
background: none; border: none;
|
|
color: var(--corp-text-muted, #728b9a);
|
|
font-size: 12.5px; font-weight: 400;
|
|
cursor: pointer;
|
|
position: relative;
|
|
white-space: nowrap;
|
|
font-family: inherit;
|
|
transition: color 0.15s;
|
|
}
|
|
.corp-vm-step:disabled { cursor: not-allowed; }
|
|
.corp-vm-step-num {
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
width: 22px; height: 22px;
|
|
border-radius: 50%;
|
|
background: var(--corp-surface-3, #243542);
|
|
border: 1px solid var(--corp-border-medium, #344955);
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
font-size: 11px; font-weight: 600;
|
|
flex-shrink: 0;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step-num {
|
|
background: #f0f2f5;
|
|
border-color: #cfd8dc;
|
|
color: #555;
|
|
}
|
|
.corp-vm-step-label {
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
font-size: 12.5px;
|
|
}
|
|
.corp-vm-step-line {
|
|
width: 28px; height: 1px;
|
|
background: var(--corp-border-medium, #344955);
|
|
margin: 0 4px;
|
|
flex-shrink: 0;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step-line {
|
|
background: #cfd8dc;
|
|
}
|
|
|
|
.corp-vm-step.active .corp-vm-step-num {
|
|
background: var(--corp-accent, #49afd9);
|
|
border-color: var(--corp-accent, #49afd9);
|
|
color: #fff;
|
|
box-shadow: 0 0 0 3px rgba(73, 175, 217, 0.16);
|
|
}
|
|
.corp-vm-step.active .corp-vm-step-label {
|
|
color: var(--corp-accent, #49afd9);
|
|
font-weight: 500;
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step.active .corp-vm-step-num {
|
|
background: var(--corp-accent, #0072a3);
|
|
border-color: var(--corp-accent, #0072a3);
|
|
box-shadow: 0 0 0 3px rgba(0, 114, 163, 0.16);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step.active .corp-vm-step-label {
|
|
color: var(--corp-accent, #0072a3);
|
|
}
|
|
|
|
.corp-vm-step.done .corp-vm-step-num {
|
|
background: var(--corp-accent, #49afd9);
|
|
border-color: var(--corp-accent, #49afd9);
|
|
color: #fff;
|
|
}
|
|
.corp-vm-step.done .corp-vm-step-label {
|
|
color: var(--color-text, #e9ecef);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step.done .corp-vm-step-label {
|
|
color: #1a1a1a;
|
|
}
|
|
.corp-vm-step.done + .corp-vm-step .corp-vm-step-line,
|
|
.corp-vm-step.done .corp-vm-step-line {
|
|
background: var(--corp-accent, #49afd9);
|
|
}
|
|
|
|
.corp-vm-step:hover:not(:disabled) .corp-vm-step-label {
|
|
color: var(--color-text, #e9ecef);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-step:hover:not(:disabled) .corp-vm-step-label {
|
|
color: #1a1a1a;
|
|
}
|
|
|
|
/* Footer bar with Back / Cancel / Next / Create buttons */
|
|
.corp-vm-modal-footer {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 12px 20px;
|
|
border-top: 1px solid var(--corp-border-subtle, #283844);
|
|
background: var(--corp-header-bg, #1a2730);
|
|
}
|
|
[data-corp-theme="light"] .corp-vm-modal-footer {
|
|
background: #f6f8fa;
|
|
border-top-color: #c0ccd4;
|
|
box-shadow: inset 0 1px 0 rgba(15,30,50,0.04);
|
|
}
|
|
|
|
/* Create-button uses the success/green palette to set it apart from Next */
|
|
.corp-vm-btn-create {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 6px 16px;
|
|
font-size: 12.5px; font-weight: 500;
|
|
background: #60b515;
|
|
color: #fff;
|
|
border: 1px solid #60b515;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
font-family: inherit;
|
|
transition: filter 0.15s;
|
|
}
|
|
.corp-vm-btn-create:hover:not(:disabled) { filter: brightness(1.08); }
|
|
.corp-vm-btn-create:disabled {
|
|
opacity: 0.45; cursor: not-allowed;
|
|
}
|
|
|
|
/* LW: Snapshot Overview tab — flat corporate table */
|
|
.corp-snap-overview {
|
|
background: var(--corp-surface-1, #111a21);
|
|
border: 1px solid var(--corp-border-medium, #344955);
|
|
display: flex; flex-direction: column;
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-overview {
|
|
background: #ffffff; border-color: #d4dae0;
|
|
}
|
|
.corp-snap-overview-header {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 14px 20px 12px;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
background: var(--corp-header-bg, #1a2730);
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-overview-header {
|
|
background: #f7f9fa; border-bottom-color: #e0e4e8;
|
|
}
|
|
.corp-snap-empty {
|
|
padding: 48px 20px; text-align: center;
|
|
background: var(--corp-surface-1);
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-empty { background: #ffffff; }
|
|
.corp-snap-table-wrap {
|
|
overflow-x: auto;
|
|
background: var(--corp-surface-1);
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-table-wrap { background: #ffffff; }
|
|
.corp-snap-table {
|
|
width: 100%; border-collapse: collapse;
|
|
}
|
|
.corp-snap-table thead th {
|
|
background: var(--corp-surface-0, #0e161b);
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
|
|
font-weight: 600;
|
|
padding: 8px 14px;
|
|
border-bottom: 2px solid var(--corp-border-medium, #344955);
|
|
text-align: left; cursor: pointer; white-space: nowrap;
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-table thead th {
|
|
background: #f0f3f5; color: #455560; border-bottom-color: #cfd8dc;
|
|
}
|
|
.corp-snap-table thead th:hover { color: var(--color-text, #e9ecef); }
|
|
.corp-snap-table tbody td {
|
|
padding: 8px 14px; font-size: 13px;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
color: var(--color-text, #e9ecef);
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-table tbody td {
|
|
color: #1c2733; border-bottom-color: #ebeef1;
|
|
}
|
|
.corp-snap-table tbody tr:hover td { background: rgba(73,175,217,0.04); }
|
|
[data-corp-theme="light"] .corp-snap-table tbody tr:hover td { background: rgba(0,114,163,0.04); }
|
|
.corp-snap-mono {
|
|
font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;
|
|
font-size: 12px;
|
|
}
|
|
.corp-snap-age { color: #efc006; }
|
|
[data-corp-theme="light"] .corp-snap-age { color: #b78b00; }
|
|
.corp-snap-action { text-align: right; width: 60px; }
|
|
.corp-snap-type-pill {
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
min-width: 32px; padding: 1px 8px;
|
|
font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em;
|
|
border: 1px solid; border-radius: 3px;
|
|
}
|
|
.corp-snap-delete {
|
|
background: none; border: none; cursor: pointer;
|
|
color: #f54f47; padding: 4px;
|
|
opacity: 0; transition: opacity 0.15s, color 0.15s;
|
|
}
|
|
.corp-snap-table tr:hover .corp-snap-delete { opacity: 1; }
|
|
.corp-snap-delete:hover { color: #ff7a73; }
|
|
[data-corp-theme="light"] .corp-snap-delete { color: #c8262a; }
|
|
[data-corp-theme="light"] .corp-snap-delete:hover { color: #ff5a52; }
|
|
|
|
/* LW: Topology view chrome (corporate) */
|
|
.corp-topo-frame {
|
|
background: var(--corp-surface-1, #111a21);
|
|
border: 1px solid var(--corp-border-medium, #344955);
|
|
display: flex; flex-direction: column;
|
|
}
|
|
[data-corp-theme="light"] .corp-topo-frame {
|
|
background: #ffffff; border-color: #d4dae0;
|
|
}
|
|
.corp-topo-header {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 12px 16px 10px;
|
|
border-bottom: 1px solid var(--corp-border-subtle, #283844);
|
|
background: var(--corp-header-bg, #1a2730);
|
|
}
|
|
[data-corp-theme="light"] .corp-topo-header {
|
|
background: #f7f9fa; border-bottom-color: #e0e4e8;
|
|
}
|
|
/* underline-tab toggle, similar to corp-vm-modal-tab */
|
|
.corp-topo-toggle { display: inline-flex; align-items: center; }
|
|
.corp-topo-toggle > button {
|
|
display: inline-flex; align-items: center;
|
|
padding: 6px 12px;
|
|
font-size: 12px; font-weight: 400;
|
|
color: var(--corp-text-secondary, #adbbc4);
|
|
background: none; border: none;
|
|
border-bottom: 2px solid transparent;
|
|
cursor: pointer;
|
|
transition: color 0.12s, border-color 0.12s, background 0.12s;
|
|
}
|
|
.corp-topo-toggle > button:hover {
|
|
color: var(--color-text, #e9ecef);
|
|
background: rgba(73,175,217,0.04);
|
|
}
|
|
.corp-topo-toggle > button.active {
|
|
color: var(--corp-accent, #49afd9);
|
|
border-bottom-color: var(--corp-accent, #49afd9);
|
|
font-weight: 500;
|
|
}
|
|
[data-corp-theme="light"] .corp-topo-toggle > button.active {
|
|
color: var(--corp-accent, #0072a3);
|
|
border-bottom-color: var(--corp-accent, #0072a3);
|
|
}
|
|
.corp-topo-frame > div:not(.corp-topo-header) {
|
|
padding: 14px 16px;
|
|
}
|
|
|
|
/* LW: per-VM snapshot rows (tree view) */
|
|
.corp-snap-row {
|
|
padding: 8px 12px;
|
|
background: var(--corp-surface-2, #1a2733);
|
|
border: 1px solid var(--corp-border-subtle, #283844);
|
|
margin-bottom: 4px;
|
|
transition: border-color 0.15s, background 0.15s;
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-row {
|
|
background: #fafbfc; border-color: #e0e4e8;
|
|
}
|
|
.corp-snap-row:hover {
|
|
border-color: rgba(73,175,217,0.35);
|
|
background: rgba(73,175,217,0.04);
|
|
}
|
|
[data-corp-theme="light"] .corp-snap-row:hover {
|
|
border-color: rgba(0,114,163,0.35);
|
|
background: rgba(0,114,163,0.03);
|
|
}
|
|
.corp-snap-pill {
|
|
display: inline-flex; align-items: center;
|
|
padding: 1px 7px; font-size: 10px; font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
border: 1px solid; border-radius: 2px;
|
|
}
|
|
|
|
/* LW: pill + a bit of air under the value, matches the storage bars */
|
|
.corp-capacity-bar { height: 6px; margin-top: 3px; background: var(--corp-bar-track); overflow: hidden; border-radius: 999px; }
|
|
.corp-capacity-bar > div { height: 100%; transition: width 0.3s ease; border-radius: 999px; }
|
|
.corp-badge-online { background: rgba(96, 181, 21, 0.12); color: #60b515; }
|
|
.corp-badge-offline { background: rgba(245, 79, 71, 0.12); color: #f54f47; }
|
|
.corp-badge-maintenance { background: rgba(239, 192, 6, 0.12); color: #efc006; }
|
|
|
|
/* LW: Feb 2026 - Corporate data-grid (dense table) */
|
|
body[data-layout="corporate"] .corp-datagrid { border-collapse: collapse; width: 100%; }
|
|
body[data-layout="corporate"] .corp-datagrid th { background: var(--corp-surface-0, #0e161b); color: #adbbc4; font-size: 11px; text-transform: uppercase;
|
|
letter-spacing: 0.05em; font-weight: 600; padding: 6px 12px; border-bottom: 2px solid var(--corp-border-medium, #344955); position: sticky; top: 0; z-index: 2; }
|
|
body[data-layout="corporate"] .corp-datagrid th:hover { color: #c8d8e4; cursor: pointer; }
|
|
body[data-layout="corporate"] .corp-datagrid td { padding: 6px 12px; font-size: 13px; border-bottom: 1px solid var(--corp-border-subtle, #283844); color: #e9ecef; }
|
|
body[data-layout="corporate"] .corp-datagrid tr:hover td { background: rgba(73,175,217,0.04); transition: background 0.15s ease; }
|
|
body[data-layout="corporate"] .corp-datagrid tr.corp-row-selected td { background: rgba(73,175,217,0.16); }
|
|
body[data-layout="corporate"] .corp-datagrid tr.corp-row-selected td:first-child { box-shadow: inset 3px 0 0 var(--corp-accent); }
|
|
body[data-layout="corporate"] .corp-datagrid .sort-indicator { color: #49afd9; }
|
|
|
|
/* LW: Feb 2026 - Corporate modal overrides (Clarity flat inputs) */
|
|
body[data-layout="corporate"] .fixed.inset-0 > div > div { border-radius: 3px !important; box-shadow: none !important; }
|
|
body[data-layout="corporate"] input:focus, body[data-layout="corporate"] select:focus,
|
|
body[data-layout="corporate"] textarea:focus { border-color: #49afd9 !important; outline-color: #49afd9 !important; }
|
|
|
|
/* MK: Mar 2026 - robust modal overrides, covers all modal structures */
|
|
body[data-layout="corporate"] .fixed.inset-0 [class*="bg-proxmox-card"] {
|
|
background: var(--corp-surface-3) !important;
|
|
border: 1px solid var(--corp-border-strong) !important;
|
|
border-radius: 3px !important;
|
|
box-shadow: none !important;
|
|
}
|
|
body[data-layout="corporate"] .fixed.inset-0.bg-black\/50,
|
|
body[data-layout="corporate"] .fixed.inset-0.bg-black\/60,
|
|
body[data-layout="corporate"] .fixed.inset-0.bg-black\/70,
|
|
body[data-layout="corporate"] .fixed.inset-0.bg-black\/80 {
|
|
background: rgba(0,0,0,0.6) !important;
|
|
backdrop-filter: blur(2px) !important;
|
|
}
|
|
/* modal header/footer bars */
|
|
body[data-layout="corporate"] .fixed.inset-0 [class*="border-b"][class*="border-proxmox"] {
|
|
background: var(--corp-surface-0) !important;
|
|
border-color: var(--corp-border-medium) !important;
|
|
}
|
|
/* bordered-box inputs inside modals — matches the modal-body fields */
|
|
body[data-layout="corporate"] .fixed.inset-0 input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
|
|
body[data-layout="corporate"] .fixed.inset-0 select,
|
|
body[data-layout="corporate"] .fixed.inset-0 textarea {
|
|
border: 1px solid var(--corp-border-medium) !important;
|
|
border-radius: 3px !important;
|
|
background: var(--corp-surface-2) !important;
|
|
padding: 6px 8px !important;
|
|
color: var(--color-text) !important;
|
|
}
|
|
body[data-layout="corporate"] .fixed.inset-0 input:focus,
|
|
body[data-layout="corporate"] .fixed.inset-0 select:focus,
|
|
body[data-layout="corporate"] .fixed.inset-0 textarea:focus {
|
|
border-color: var(--corp-accent) !important;
|
|
box-shadow: 0 0 0 3px rgba(73,175,217,0.15) !important;
|
|
outline: none !important;
|
|
}
|
|
/* primary action buttons in modals */
|
|
body[data-layout="corporate"] .fixed.inset-0 button[class*="bg-proxmox-orange"] {
|
|
background: var(--corp-accent) !important;
|
|
border-color: var(--corp-accent) !important;
|
|
}
|
|
body[data-layout="corporate"] .fixed.inset-0 button[class*="bg-proxmox-orange"]:hover {
|
|
background: #3d9bc2 !important;
|
|
}
|
|
/* rounded-xl → sharp in modals */
|
|
body[data-layout="corporate"] .fixed.inset-0 .rounded-xl {
|
|
border-radius: 3px !important;
|
|
}
|
|
|
|
/* LW: Feb 2026 - Corporate badge color overrides (Clarity palette) */
|
|
body[data-layout="corporate"] .bg-blue-500\/20 { background: rgba(73,175,217,0.12) !important; }
|
|
body[data-layout="corporate"] .text-blue-400 { color: #49afd9 !important; }
|
|
body[data-layout="corporate"] .text-blue-300 { color: #6dc0e0 !important; }
|
|
body[data-layout="corporate"] .bg-blue-500 { background: #49afd9 !important; }
|
|
body[data-layout="corporate"] .bg-blue-600 { background: #3d9bc2 !important; }
|
|
body[data-layout="corporate"] .bg-purple-500\/20 { background: rgba(161,120,217,0.12) !important; }
|
|
body[data-layout="corporate"] .text-purple-400 { color: #a178d9 !important; }
|
|
body[data-layout="corporate"] .bg-emerald-500 { background: #49afd9 !important; }
|
|
body[data-layout="corporate"] .bg-emerald-600 { background: #3d9bc2 !important; }
|
|
body[data-layout="corporate"] .hover\:bg-emerald-600:hover { background: #3d9bc2 !important; }
|
|
body[data-layout="corporate"] .text-emerald-400 { color: #60b515 !important; }
|
|
body[data-layout="corporate"] .bg-green-500\/20 { background: rgba(96,181,21,0.12) !important; }
|
|
body[data-layout="corporate"] .text-green-400 { color: #60b515 !important; }
|
|
body[data-layout="corporate"] .bg-red-500\/20 { background: rgba(245,79,71,0.12) !important; }
|
|
body[data-layout="corporate"] .bg-yellow-500\/20 { background: rgba(239,192,6,0.12) !important; }
|
|
|
|
/* LW: Feb 2026 - Corporate sidebar tree (indentation only, no connector lines) */
|
|
|
|
/* LW: Feb 2026 - Corporate header darker */
|
|
body[data-layout="corporate"] header.sticky { background: var(--corp-surface-0) !important; border-bottom: 1px solid var(--corp-border-medium); box-shadow: var(--corp-shadow-sm); }
|
|
|
|
/* LW: Feb 2026 - Corporate table row hover override */
|
|
body[data-layout="corporate"] .table-row-hover:hover { background: rgba(73,175,217,0.04) !important; }
|
|
body[data-layout="corporate"] .table-row-hover.corp-row-selected { background: rgba(73,175,217,0.10) !important; }
|
|
|
|
|
|
|
|
/* LW: Feb 2026 - Corporate sidebar resize handle */
|
|
.corp-resize-handle { width: 4px; cursor: col-resize; background: transparent; flex-shrink: 0;
|
|
border-left: 1px solid var(--corp-border-medium); transition: background 0.15s, width 0.1s; }
|
|
.corp-resize-handle:hover, .corp-resize-handle.active { width: 5px; background: rgba(73,175,217,0.3); border-left-color: var(--corp-accent); }
|
|
|
|
/* NS: Mar 2026 - utility classes so JS can drop inline hex colors */
|
|
.corp-bg-header { background: var(--corp-header-bg); }
|
|
.corp-bg-surface { background: var(--corp-surface-3); }
|
|
.corp-text-secondary { color: var(--corp-text-secondary); }
|
|
.corp-text-muted { color: var(--corp-text-muted); }
|
|
.corp-text-accent { color: var(--corp-accent); }
|
|
.corp-text-primary { color: var(--color-text); }
|
|
.corp-border { border: 1px solid var(--corp-border-medium); }
|
|
.corp-border-b { border-bottom: 1px solid var(--corp-border-medium); }
|
|
.corp-divider { border-top: 1px solid var(--corp-divider); }
|
|
.corp-bar-track { background: var(--corp-bar-track); }
|
|
|
|
/* LW: Feb 2026 - System fonts for corporate layout */
|
|
body[data-layout="corporate"] {
|
|
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif !important;
|
|
}
|
|
body[data-layout="corporate"] * {
|
|
font-family: inherit !important;
|
|
}
|
|
body[data-layout="corporate"] code, body[data-layout="corporate"] .font-mono,
|
|
body[data-layout="corporate"] pre, body[data-layout="corporate"] kbd {
|
|
font-family: 'Consolas', 'JetBrains Mono', monospace !important;
|
|
}
|
|
|
|
/* LW: Feb 2026 - Tree items (indentation only) */
|
|
body[data-layout="corporate"] .corp-tree-child { padding-left: 4px; }
|
|
/* LW: Feb 2026 - Keyboard focus for sidebar tree items */
|
|
body[data-layout="corporate"] .corp-tree-child:focus-visible,
|
|
body[data-layout="corporate"] .corp-tree-item:focus-visible {
|
|
outline: 1px solid #49afd9; outline-offset: -1px;
|
|
}
|
|
|
|
/* LW: Feb 2026 - Warning banner (yellow bar) */
|
|
.corp-warning-banner {
|
|
background: rgba(239,192,6,0.12); color: #efc006; border: 1px solid rgba(239,192,6,0.3);
|
|
padding: 6px 16px; font-size: 13px; display: flex; align-items: center; justify-content: space-between;
|
|
}
|
|
.corp-warning-banner .corp-warning-dismiss {
|
|
background: none; border: 1px solid rgba(239,192,6,0.3); color: #efc006; padding: 2px 8px;
|
|
font-size: 11px; cursor: pointer; text-transform: uppercase; letter-spacing: 0.05em;
|
|
}
|
|
.corp-warning-banner .corp-warning-dismiss:hover { background: rgba(239,192,6,0.2); }
|
|
|
|
/* LW: Feb 2026 - Thinner scrollbars */
|
|
body[data-layout="corporate"] * { scrollbar-width: thin; }
|
|
body[data-layout="corporate"] ::-webkit-scrollbar { width: 6px !important; height: 6px !important; }
|
|
|
|
/* LW: Feb 2026 - No rounded-full for status badges (exclude small dots) */
|
|
body[data-layout="corporate"] .rounded-full:not(.w-2):not(.w-1\.5):not(.h-2):not(.h-1\.5):not(.w-1):not(.h-1) {
|
|
border-radius: 3px !important;
|
|
}
|
|
|
|
/* LW: Mar 2026 - Content header strip (between tabs and content body) */
|
|
.corp-content-header {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
padding: 6px 16px; background: var(--corp-surface-3, #243542); border-bottom: 1px solid var(--corp-border-medium, #344955);
|
|
font-size: 13px; min-height: 32px; box-shadow: 0 1px 2px rgba(0,0,0,0.08);
|
|
}
|
|
.corp-content-header .corp-header-title { color: #e9ecef; font-weight: 500; font-size: 14px; }
|
|
.corp-rename-btn { opacity: 0; transition: opacity 0.15s; }
|
|
.corp-content-header:hover .corp-rename-btn { opacity: 1; }
|
|
.corp-rename-btn:hover { color: #49afd9 !important; }
|
|
|
|
/* Corporate VM/resource table toolbar */
|
|
.corp-vm-toolbar {
|
|
display: flex; align-items: center; padding: 4px 8px;
|
|
border-bottom: 1px solid #37474f; gap: 4px; background: transparent;
|
|
}
|
|
.corp-toolbar-divider { display: inline-block; width: 1px; height: 16px; background: #485764; margin: 0 4px; flex-shrink: 0; }
|
|
.corp-toolbar-filter { padding: 2px 8px; font-size: 12px; color: #728b9a; background: none; border: none; cursor: pointer; font-family: inherit; }
|
|
.corp-toolbar-filter:hover { color: #adbbc4; }
|
|
.corp-toolbar-filter.active { color: #e9ecef; border-bottom: 2px solid #49afd9; }
|
|
|
|
/* NS: Status bar - bottom of page */
|
|
.corp-status-bar {
|
|
position: fixed; bottom: 0; left: 0; right: 0; height: 26px; z-index: 40;
|
|
background: var(--corp-surface-0, #0e161b); border-top: 1px solid var(--corp-border-medium, #344955);
|
|
display: flex; align-items: center; padding: 0 12px;
|
|
font-size: 11px; color: #728b9a;
|
|
}
|
|
.corp-status-bar-item {
|
|
display: inline-flex; align-items: center; gap: 4px;
|
|
padding: 0 8px; border-right: 1px solid var(--corp-divider); height: 100%;
|
|
}
|
|
.corp-status-bar-item:last-child { border-right: none; }
|
|
|
|
/* Recent items in sidebar */
|
|
.corp-recent-item {
|
|
display: flex; align-items: center; gap: 6px;
|
|
padding: 3px 8px; font-size: 12px; color: #adbbc4;
|
|
cursor: pointer; border: none; background: none; width: 100%; text-align: left;
|
|
}
|
|
.corp-recent-item:hover { background: #29414e; color: #e9ecef; }
|
|
|
|
/* Striped datagrid variant */
|
|
body[data-layout="corporate"] .corp-datagrid-striped tbody tr:nth-child(even) td { background: rgba(14,22,27,0.3); }
|
|
body[data-layout="corporate"] .corp-datagrid-striped tbody tr:nth-child(even):hover td { background: rgba(73,175,217,0.04); }
|
|
|
|
/* Tab strip background */
|
|
body[data-layout="corporate"] .corp-tab-strip { background: var(--corp-surface-1, #111a21); }
|
|
|
|
/* subtle depth on card panels */
|
|
body[data-layout="corporate"] .bg-proxmox-card { box-shadow: 0 1px 2px rgba(0,0,0,0.12); }
|
|
|
|
/* LW: Mar 2026 - Card component (reusable content block) */
|
|
.corp-card { background: var(--corp-surface-3, #243542); border: 1px solid var(--corp-border-medium, #344955); border-radius: var(--corp-radius-md); }
|
|
.corp-card-header { padding: 8px 12px; background: var(--corp-surface-2, #1a2730); border-bottom: 1px solid var(--corp-border-medium, #344955);
|
|
font-size: 12px; font-weight: 600; color: #adbbc4; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
.corp-card-body { padding: 12px; }
|
|
|
|
/* Toolbar button group */
|
|
.corp-toolbar-group { display: inline-flex; gap: 1px; background: #485764; border-radius: 3px; overflow: hidden; }
|
|
.corp-toolbar-group button { border-radius: 0 !important; border: none !important; }
|
|
|
|
/* Status bar item strong text */
|
|
.corp-status-bar-item strong { color: var(--corp-text-secondary); font-weight: 500; }
|
|
|
|
/* LW: Mar 2026 - Sidebar quick-filter */
|
|
.corp-sidebar-search { width: 100%; padding: 5px 8px 5px 28px; font-size: 12px; background: var(--corp-surface-0, #0e161b); border: 1px solid var(--corp-border-subtle, #283844);
|
|
color: #e9ecef; outline: none; }
|
|
.corp-sidebar-search:focus { border-color: #49afd9; }
|
|
.corp-sidebar-search::placeholder { color: #5a7a8a; }
|
|
|
|
/* NS: Mar 2026 - Event feed mini-panel above status bar */
|
|
.corp-event-log {
|
|
position: fixed; bottom: 26px; left: 0; right: 0; z-index: 39;
|
|
background: var(--corp-surface-1, #111a21); border-top: 1px solid var(--corp-border-medium, #344955);
|
|
max-height: 200px; overflow-y: auto; scrollbar-width: thin;
|
|
}
|
|
.corp-event-item {
|
|
display: flex; align-items: center; gap: 8px; padding: 4px 12px;
|
|
font-size: 12px; color: #adbbc4; border-bottom: 1px solid #1e3340;
|
|
}
|
|
.corp-event-item:hover { background: #1b2a32; }
|
|
.corp-event-time { color: #5a7a8a; font-size: 11px; white-space: nowrap; min-width: 40px; }
|
|
.corp-event-type-error { color: #f54f47; }
|
|
.corp-event-type-success { color: #60b515; }
|
|
.corp-event-type-action { color: #49afd9; }
|
|
|
|
/* Status flash for node offline */
|
|
@keyframes corp-flash-offline { 0% { background: transparent; } 50% { background: rgba(245,79,71,0.08); } 100% { background: transparent; } }
|
|
.corp-flash-offline { animation: corp-flash-offline 0.3s ease; }
|
|
|
|
/* MK: Mar 2026 - focus-visible ring for keyboard nav */
|
|
body[data-layout="corporate"] button:focus-visible,
|
|
body[data-layout="corporate"] input:focus-visible,
|
|
body[data-layout="corporate"] select:focus-visible,
|
|
body[data-layout="corporate"] [tabindex]:focus-visible { outline: 1px solid #49afd9 !important; outline-offset: -1px; }
|
|
|
|
/* loading skeleton animation */
|
|
.corp-skeleton { background: linear-gradient(90deg, var(--corp-surface-1,#111a21) 0%, var(--corp-surface-3,#243542) 50%, var(--corp-surface-1,#111a21) 100%); background-size: 200% 100%; animation: corp-skeleton-pulse 1.5s ease-in-out infinite; border-radius: 2px; }
|
|
@keyframes corp-skeleton-pulse { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
|
|
|
|
/* NS: Mar 2026 - type filter chips for sidebar */
|
|
.corp-type-filters { display: flex; gap: 0; padding: 2px 8px 4px; }
|
|
.corp-type-filter-btn { padding: 2px 8px; font-size: 11px; color: #728b9a; background: none; border: 1px solid transparent; border-radius: 3px; cursor: pointer; font-family: inherit; transition: all 0.15s; }
|
|
.corp-type-filter-btn:hover { color: #adbbc4; background: rgba(73,175,217,0.04); }
|
|
.corp-type-filter-btn.active { color: #49afd9; background: rgba(73,175,217,0.08); border-color: rgba(73,175,217,0.2); }
|
|
|
|
/* view switcher (horizontal icon toggle) */
|
|
.corp-view-switcher { display: flex; gap: 0; background: var(--corp-surface-0, #0e161b); border: 1px solid var(--corp-border-subtle, #283844); border-radius: 3px; overflow: hidden; margin: 4px 8px; }
|
|
.corp-view-switcher button { flex: 1; padding: 6px 0; border: none; background: none; color: #5a7a8a; cursor: pointer; display: flex; align-items: center; justify-content: center; }
|
|
.corp-view-switcher button:hover { color: #adbbc4; background: rgba(73,175,217,0.04); }
|
|
.corp-view-switcher button.active { color: #49afd9; background: rgba(73,175,217,0.10); box-shadow: inset 0 -2px 0 #49afd9; }
|
|
|
|
/* LW: Mar 2026 - breadcrumb segments */
|
|
.corp-breadcrumb-segment { color: #728b9a; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px; border-radius: 3px; transition: all 0.15s; }
|
|
.corp-breadcrumb-segment:hover { color: #e9ecef; background: rgba(73,175,217,0.06); }
|
|
.corp-breadcrumb-current { color: #e9ecef; font-weight: 500; cursor: default; display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px; }
|
|
|
|
/* Phase 9: cluster overview summary cards - NS */
|
|
.corp-overview-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 12px; }
|
|
.corp-overview-card { background: linear-gradient(135deg, color-mix(in srgb, var(--corp-accent) 12%, var(--corp-surface-3)), var(--corp-surface-3) 75%); border: 1px solid color-mix(in srgb, var(--corp-accent) 18%, var(--corp-border-medium)); border-radius: var(--corp-radius-lg); padding: 12px 16px; display: flex; align-items: center; gap: 14px; }
|
|
.corp-overview-card:hover { border-color: var(--corp-border-strong); }
|
|
/* LW: accent-tinted icon chip for the overview cards */
|
|
.corp-stat-icon { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; background: rgba(73,175,217,0.12); border-radius: var(--corp-radius-md); color: var(--corp-accent); flex-shrink: 0; }
|
|
.corp-donut-track { stroke: #1b2a32; }
|
|
.corp-donut-fill { transition: stroke-dashoffset 0.5s ease; }
|
|
.corp-overview-label { font-size: 11px; color: #728b9a; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 2px; }
|
|
.corp-overview-value { font-size: 18px; font-weight: 600; color: #e9ecef; }
|
|
.corp-overview-sub { font-size: 11px; color: #5a7a8a; margin-top: 2px; }
|
|
@media (max-width: 1200px) { .corp-overview-grid { grid-template-columns: repeat(2, 1fr); } }
|
|
|
|
/* Phase 10: content area surface depth - LW */
|
|
body[data-layout="corporate"] .bg-proxmox-darker { background: var(--corp-surface-2) !important; }
|
|
body[data-layout="corporate"] .bg-proxmox-dark { background: var(--corp-surface-1) !important; }
|
|
body[data-layout="corporate"] .bg-proxmox-card { background: var(--corp-surface-3) !important; box-shadow: 0 1px 2px rgba(0,0,0,0.12); }
|
|
body[data-layout="corporate"] .border-proxmox-border { border-color: var(--corp-border-medium) !important; }
|
|
|
|
/* Phase 11: sidebar hover tooltip popover */
|
|
.corp-hover-tip { position: fixed; z-index: 100; background: var(--corp-surface-3); border: 1px solid var(--corp-border-strong);
|
|
box-shadow: var(--corp-shadow-lg, 0 4px 12px rgba(0,0,0,0.3)); border-radius: var(--corp-radius-md); padding: 8px 12px; max-width: 260px; font-size: 12px; pointer-events: none; }
|
|
.corp-hover-tip-header { font-weight: 600; color: #e9ecef; margin-bottom: 4px; display: flex; align-items: center; gap: 6px; }
|
|
.corp-hover-tip-row { display: flex; justify-content: space-between; gap: 12px; padding: 1px 0; }
|
|
.corp-hover-tip-label { color: #728b9a; }
|
|
.corp-hover-tip-value { color: #adbbc4; font-weight: 500; }
|
|
.corp-hover-tip-bar { height: 6px; background: var(--corp-bar-track); border-radius: 999px; margin-top: 2px; }
|
|
.corp-hover-tip-bar > div { height: 100%; border-radius: 1px; }
|
|
|
|
/* LW: Apr 2026 - fix gray-on-gray in advanced sections (#303) */
|
|
body[data-layout="corporate"] .fixed.inset-0 details label { color: #adbbc4 !important; }
|
|
body[data-layout="corporate"] .fixed.inset-0 details input:not([type="checkbox"]):not([type="radio"]),
|
|
body[data-layout="corporate"] .fixed.inset-0 details select {
|
|
background: var(--corp-surface-3) !important; color: #e9ecef !important;
|
|
border-color: var(--corp-border-medium) !important;
|
|
}
|
|
|
|
/* MK: Mar 2026 - corporate modal refinement */
|
|
.corp-modal-header { background: var(--corp-surface-0); border-bottom: 1px solid var(--corp-border-medium);
|
|
padding: 10px 16px; display: flex; align-items: center; justify-content: space-between; }
|
|
.corp-modal-title { font-size: 14px; font-weight: 600; color: #e9ecef; }
|
|
.corp-modal-close { background: none; border: none; color: #728b9a; cursor: pointer; padding: 4px;
|
|
border-radius: 3px; display: flex; align-items: center; }
|
|
.corp-modal-close:hover { background: rgba(73,175,217,0.12); color: #e9ecef; }
|
|
.corp-modal-footer { background: var(--corp-surface-1); border-top: 1px solid var(--corp-border-medium);
|
|
padding: 8px 16px; display: flex; justify-content: flex-end; gap: 8px; }
|
|
|
|
/* bordered-box inputs in corporate modals */
|
|
body[data-layout="corporate"] .fixed.inset-0 input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(.corp-sidebar-search) {
|
|
border: 1px solid var(--corp-border-medium) !important; border-radius: 3px !important;
|
|
background: var(--corp-surface-2) !important; padding: 6px 8px !important;
|
|
}
|
|
body[data-layout="corporate"] .fixed.inset-0 input:focus:not([type="checkbox"]):not([type="radio"]):not([type="range"]) {
|
|
border-color: #49afd9 !important; box-shadow: 0 0 0 3px rgba(73,175,217,0.15) !important;
|
|
}
|
|
body[data-layout="corporate"] .fixed.inset-0 select {
|
|
border: 1px solid var(--corp-border-medium) !important; background: var(--corp-surface-2) !important;
|
|
border-radius: 3px !important; padding: 6px 8px !important;
|
|
}
|
|
|
|
/* Phase 13: icon-only action buttons - LW */
|
|
.corp-action-btn { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
|
|
background: none; border: 1px solid transparent; border-radius: 3px; color: #728b9a; cursor: pointer; }
|
|
.corp-action-btn:hover { background: rgba(73,175,217,0.12); color: #e9ecef; border-color: var(--corp-border-subtle); }
|
|
.corp-action-btn:disabled { opacity: 0.3; cursor: not-allowed; }
|
|
/* MK 2026-06-09: unify the hover/active feel across corporate controls — most
|
|
had no transition, so they snapped while datagrid rows faded. One light touch. */
|
|
body[data-layout="corporate"] .corp-action-btn,
|
|
body[data-layout="corporate"] .corp-toolbar button,
|
|
body[data-layout="corporate"] .corp-subnav-item,
|
|
body[data-layout="corporate"] .corp-ctx-item,
|
|
body[data-layout="corporate"] .corp-tab-strip button,
|
|
body[data-layout="corporate"] .corp-dropdown button {
|
|
transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
}
|
|
.corp-action-btn.danger:hover { background: rgba(245,79,71,0.12); color: #f54f47; }
|
|
.corp-action-group { display: inline-flex; gap: 1px; }
|
|
|
|
/* Phase 14: sort indicator SVGs */
|
|
.corp-sort-icon { display: inline-block; width: 8px; height: 8px; margin-left: 4px; vertical-align: middle; }
|
|
.corp-sort-icon path { fill: #49afd9; }
|
|
.corp-sort-hint { opacity: 0; transition: opacity 0.15s; }
|
|
body[data-layout="corporate"] .corp-datagrid th:hover .corp-sort-hint { opacity: 1; }
|
|
.corp-sort-hint path { fill: #4a6070; }
|
|
|
|
/* Phase 15: overview enrichment widgets - NS Mar 2026 */
|
|
.corp-overview-lower { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
|
|
@media (max-width: 900px) { .corp-overview-lower { grid-template-columns: 1fr; } }
|
|
.corp-consumers-list { padding: 4px 0; }
|
|
.corp-consumer-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 12px; }
|
|
.corp-consumer-rank { width: 16px; color: #728b9a; text-align: right; font-variant-numeric: tabular-nums; }
|
|
.corp-consumer-name { flex: 1; color: #e9ecef; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.corp-consumer-name:hover { color: #49afd9; }
|
|
.corp-consumer-node { color: #5a7a8a; font-size: 11px; width: 70px; text-align: right; overflow: hidden; text-overflow: ellipsis; }
|
|
.corp-consumer-bar { width: 50px; height: 4px; background: var(--corp-bar-track); border-radius: 2px; flex-shrink: 0; }
|
|
.corp-consumer-bar-fill { height: 100%; border-radius: 2px; transition: width 0.3s ease; }
|
|
.corp-consumer-val { width: 52px; text-align: right; color: #adbbc4; font-variant-numeric: tabular-nums; }
|
|
.corp-tasks-item { display: flex; align-items: center; gap: 8px; padding: 5px 0; font-size: 12px; border-bottom: 1px solid var(--corp-border-subtle, #283844); }
|
|
.corp-tasks-item:last-child { border-bottom: none; }
|
|
.corp-tasks-status { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
|
|
.corp-tasks-desc { flex: 1; color: #e9ecef; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.corp-tasks-node { color: #5a7a8a; font-size: 11px; }
|
|
.corp-tasks-time { color: #5a7a8a; font-size: 11px; white-space: nowrap; }
|
|
.corp-services-bar { display: flex; gap: 12px; padding: 6px 12px; background: var(--corp-surface-2, #1a2730); border: 1px solid var(--corp-border-subtle, #283844); border-radius: 3px; margin-bottom: 8px; flex-wrap: wrap; align-items: center; }
|
|
.corp-services-bar .corp-svc-item { display: flex; align-items: center; gap: 5px; font-size: 12px; color: #adbbc4; }
|
|
.corp-services-bar .corp-svc-label { color: #728b9a; text-transform: uppercase; font-size: 10px; letter-spacing: 0.04em; }
|
|
|
|
/* Phase 16: node sparklines + detail cards */
|
|
.corp-sparkline-inline { display: inline-block; vertical-align: middle; margin-left: 4px; }
|
|
.corp-node-detail-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 8px 0; }
|
|
@media (max-width: 768px) { .corp-node-detail-grid { grid-template-columns: repeat(2, 1fr); } }
|
|
.corp-node-detail-card { background: var(--corp-surface-2, #1a2730); border: 1px solid var(--corp-border-subtle, #283844); border-radius: 3px; padding: 8px 10px; }
|
|
.corp-node-detail-label { font-size: 10px; color: #728b9a; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 2px; }
|
|
.corp-node-detail-value { font-size: 15px; font-weight: 600; color: #e9ecef; }
|
|
.corp-node-detail-sub { font-size: 11px; color: #5a7a8a; margin-top: 1px; }
|
|
|
|
/* Phase 17: vm table sparklines */
|
|
.corp-vm-sparkline { display: inline-block; vertical-align: middle; margin-left: 3px; }
|
|
|
|
/* Phase 18: datacenter section headers + storage */
|
|
.corp-dc-section-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 2px solid var(--corp-border-subtle, #283844); }
|
|
.corp-dc-section-icon { color: #49afd9; flex-shrink: 0; }
|
|
.corp-dc-section-title { font-size: 13px; font-weight: 600; color: #e9ecef; }
|
|
.corp-dc-section-desc { font-size: 11px; color: #728b9a; margin-left: auto; }
|
|
.corp-storage-card { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border-bottom: 1px solid var(--corp-border-subtle, #283844); }
|
|
.corp-storage-card:last-child { border-bottom: none; }
|
|
.corp-storage-card:hover { background: rgba(73,175,217,0.04); }
|
|
.corp-storage-type-badge { font-size: 10px; padding: 1px 6px; border-radius: 2px; text-transform: uppercase; letter-spacing: 0.03em; }
|
|
.corp-storage-cap-bar { width: 80px; height: 6px; background: var(--corp-bar-track); border-radius: 999px; flex-shrink: 0; }
|
|
|
|
/* NS: Mar 2026 - card elevation + hover lift */
|
|
body[data-layout="corporate"] .corp-card { box-shadow: var(--corp-shadow-sm); transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease; }
|
|
body[data-layout="corporate"] .corp-card:hover { box-shadow: var(--corp-shadow-md); transform: translateY(-2px); border-color: var(--corp-border-strong); }
|
|
|
|
/* input focus glow */
|
|
body[data-layout="corporate"] input:focus,
|
|
body[data-layout="corporate"] select:focus,
|
|
body[data-layout="corporate"] textarea:focus { box-shadow: 0 0 0 2px rgba(73,175,217,0.15) !important; }
|
|
body[data-layout="corporate"] input[type="checkbox"],
|
|
body[data-layout="corporate"] input[type="radio"] { accent-color: #49afd9; }
|
|
|
|
/* tab underline slide - pseudo element instead of border toggle */
|
|
.corp-tab-strip button { position: relative; border-bottom: none !important; }
|
|
.corp-tab-strip button::after { content: ''; position: absolute; bottom: 0; left: 50%; width: 0; height: 3px; background: var(--corp-accent, #49afd9); transition: width 0.18s ease, left 0.18s ease; }
|
|
.corp-tab-strip button:hover::after { width: 60%; left: 20%; background: rgba(73,175,217,0.3); }
|
|
.corp-tab-strip button.active::after { width: 100%; left: 0; background: var(--corp-accent, #49afd9); }
|
|
|
|
/* modal entrance */
|
|
@keyframes corp-modal-in { from { opacity: 0; transform: scale(0.97) translateY(4px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
body[data-layout="corporate"] .fixed.inset-0 > div > div { animation: corp-modal-in 0.15s ease-out; }
|
|
|
|
/* button press feedback */
|
|
body[data-layout="corporate"] button:active:not(:disabled) { transform: scale(0.97); }
|
|
|
|
/* overview card left-accent stripe — inset so it stacks with the tinted border above */
|
|
.corp-overview-card { transition: border-color 0.15s ease, box-shadow 0.15s ease; box-shadow: var(--corp-shadow-sm); }
|
|
.corp-overview-card:hover { box-shadow: inset 3px 0 0 var(--corp-accent, #49afd9), var(--corp-shadow-md); }
|
|
|
|
/* datagrid row left indicator — inset shadow so the cell text doesn't shift */
|
|
body[data-layout="corporate"] .corp-datagrid tr:hover td:first-child { box-shadow: inset 3px 0 0 rgba(73,175,217,0.4); }
|
|
body[data-layout="corporate"] .corp-datagrid tr.corp-row-selected td:first-child { box-shadow: inset 3px 0 0 var(--corp-accent); }
|
|
|
|
/* LW: typography hierarchy polish — reserve 10px/700/tracked uppercase for the
|
|
section header only; datagrid th + card-header step down to 11px/600 */
|
|
.corp-section-header { font-size: 10px !important; font-weight: 700 !important; letter-spacing: 0.1em !important; }
|
|
.corp-overview-value { font-size: 20px !important; font-weight: 700 !important; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
|
|
body[data-layout="corporate"] .corp-datagrid th { font-size: 11px; letter-spacing: 0.05em; font-weight: 600; }
|
|
.corp-card-header { font-size: 11px !important; font-weight: 600 !important; text-transform: none !important; letter-spacing: normal !important; }
|
|
.corp-status-bar { font-variant-numeric: tabular-nums; }
|
|
|
|
/* toast slide-in */
|
|
@keyframes corp-toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
|
|
body[data-layout="corporate"] .toast-enter, body[data-layout="corporate"] [class*="animate-slide"] { animation: corp-toast-in 0.2s ease-out !important; }
|
|
|
|
/* indeterminate progress bar */
|
|
.corp-progress-indeterminate { height: 2px; background: var(--corp-surface-0, #0e161b); overflow: hidden; position: relative; }
|
|
.corp-progress-indeterminate::after { content: ''; position: absolute; left: -40%; width: 40%; height: 100%; background: var(--corp-accent, #49afd9); animation: corp-progress-scan 1.4s ease-in-out infinite; }
|
|
@keyframes corp-progress-scan { 0% { left: -40%; } 100% { left: 100%; } }
|
|
|
|
/* skeleton variants */
|
|
.corp-skeleton-text { height: 12px; width: 70%; margin: 4px 0; }
|
|
.corp-skeleton-badge { height: 18px; width: 48px; display: inline-block; }
|
|
.corp-skeleton-bar { height: 3px; width: 100%; }
|
|
|
|
/* sidebar tree expand animation */
|
|
@keyframes corp-tree-expand { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
|
|
/* NS Jul 2026 (scale) — animate the tree CONTAINER once on expand, not each
|
|
.corp-tree-child row. The per-row entry animation collided with the new
|
|
content-visibility:auto (a row re-ran its fade every time it scrolled back into
|
|
view = jank on exactly the big trees this targets) and meant ~1000 simultaneous
|
|
animations on expand. One container fade is smoother and far cheaper. Both view
|
|
roots (network + datastore reuse .corp-inline-tree; pools use .corp-pool-tree). */
|
|
body[data-layout="corporate"] .corp-inline-tree,
|
|
body[data-layout="corporate"] .corp-pool-tree { animation: corp-tree-expand 0.12s ease-out; }
|
|
|
|
/* empty state placeholder */
|
|
.corp-empty-state { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px 20px; text-align: center; }
|
|
.corp-empty-title { font-size: 13px; color: var(--corp-text-secondary); }
|
|
.corp-empty-text { font-size: 12px; color: var(--corp-text-muted); }
|
|
|
|
/* console preview tile */
|
|
.corp-console-tile { background: var(--corp-surface-2); border: 1px solid var(--corp-border-medium); border-radius: 4px; box-shadow: var(--corp-shadow-sm); transition: border-color 0.15s, box-shadow 0.15s; cursor: pointer; }
|
|
.corp-console-tile:hover { border-color: var(--corp-accent); box-shadow: var(--corp-shadow-md); }
|
|
|
|
/* ── Cloud skin (Preview): deep navy + teal, airy resource-first card-grid — NS 2026-06-05 ──
|
|
Base colors are also regenerated by applyTheme('cloud') from PEGAPROX_THEMES.cloud;
|
|
restated here for cascade determinism (same pattern as the corporate block above).
|
|
The --cloud, --space and --radius tokens are inert for Modern/Corporate (they use
|
|
Tailwind utils + hardcoded px), so this block is zero-regression — it only goes
|
|
load-bearing for the Cloud-specific card-grid components. */
|
|
body[data-layout="cloud"] {
|
|
--color-darker: #060f1e;
|
|
--color-dark: #0a1628;
|
|
--color-card: #102338;
|
|
--color-border: #1e3a52;
|
|
--color-hover: #14304a;
|
|
--color-primary:#22d3ee;
|
|
--color-text: #e6f1f8;
|
|
--color-text-muted: #8aa4b8;
|
|
--color-success:#2dd4a7;
|
|
--color-warning:#f5b945;
|
|
--color-error: #f87171;
|
|
--color-info: #38bdf8;
|
|
/* layered surfaces (darkest → raised) */
|
|
--cloud-surface-0: #060f1e;
|
|
--cloud-surface-1: #0a1628;
|
|
--cloud-surface-2: #102338;
|
|
--cloud-surface-3: #16304a;
|
|
--cloud-surface-raised: #1d3b59;
|
|
/* accent */
|
|
--cloud-accent: #22d3ee;
|
|
--cloud-accent-hover: #67e8f9;
|
|
--cloud-selection: #0e3a4a;
|
|
/* semantic status tokens (were referenced by cloud.js but never defined — NS 2026-06) */
|
|
--cloud-success: #2dd4a7;
|
|
--cloud-warning: #f5b945;
|
|
--cloud-info: #38bdf8;
|
|
--cloud-error: #f87171;
|
|
--cloud-gauge-track: #1b3148;
|
|
/* text + dividers */
|
|
--cloud-text-secondary: #b3c6d4;
|
|
--cloud-text-muted: #8aa4b8;
|
|
--cloud-divider: #1a3147;
|
|
/* borders */
|
|
--cloud-border-subtle: #16293c;
|
|
--cloud-border-medium: #1e3a52;
|
|
--cloud-border-strong: #2f5775;
|
|
/* elevation — softer/larger than corporate for the airy card look */
|
|
--cloud-shadow-sm: 0 1px 2px rgba(2,8,20,0.35);
|
|
--cloud-shadow-md: 0 4px 12px rgba(2,8,20,0.40), 0 1px 3px rgba(2,8,20,0.30);
|
|
--cloud-shadow-lg: 0 10px 28px rgba(2,8,20,0.45), 0 2px 6px rgba(2,8,20,0.30);
|
|
--cloud-shadow-xl: 0 20px 48px rgba(2,8,20,0.50), 0 4px 10px rgba(2,8,20,0.30);
|
|
/* airy spacing scale (vs corporate's dense 4/6/8) */
|
|
--space-xs: 6px; --space-sm: 10px; --space-md: 14px;
|
|
--space-lg: 20px; --space-xl: 28px; --space-2xl: 40px;
|
|
/* radius scale (card-forward, rounder than corporate's 3px) */
|
|
--radius-sm: 6px; --radius-md: 10px; --radius-lg: 14px; --radius-pill: 999px;
|
|
/* component tokens for the resource card-grid */
|
|
--cloud-card-radius: var(--radius-lg);
|
|
--cloud-card-shadow: var(--cloud-shadow-md);
|
|
--cloud-card-padding: var(--space-lg);
|
|
--cloud-card-gap: var(--space-lg);
|
|
/* scrollbar (mirrors the corporate-light override precedent) */
|
|
--scrollbar-track: #0a1628;
|
|
--scrollbar-thumb: #1e3a52;
|
|
--scrollbar-thumb-hover: #2f5775;
|
|
}
|
|
body[data-layout="cloud"] ::-webkit-scrollbar-track { background: var(--scrollbar-track); }
|
|
body[data-layout="cloud"] ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: var(--radius-sm); }
|
|
body[data-layout="cloud"] ::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }
|
|
/* Cloud resource card-grid (consumed by CloudOverviewGrid + airier VM cards) */
|
|
body[data-layout="cloud"] .cloud-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--cloud-card-gap, 20px); }
|
|
body[data-layout="cloud"] .cloud-card { background: var(--cloud-surface-3); border: 1px solid var(--cloud-border-medium); border-radius: var(--cloud-card-radius, 14px); padding: var(--cloud-card-padding, 20px); box-shadow: var(--cloud-card-shadow); transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
|
|
body[data-layout="cloud"] .cloud-card:hover { transform: translateY(-2px); box-shadow: var(--cloud-shadow-lg); border-color: var(--cloud-border-strong); }
|
|
body[data-layout="cloud"] .cloud-meter { height: 6px; background: var(--cloud-surface-1); border-radius: var(--radius-pill); overflow: hidden; }
|
|
body[data-layout="cloud"] .cloud-meter > div { height: 100%; border-radius: var(--radius-pill); transition: width .3s ease; }
|
|
/* at-a-glance summary stat tiles */
|
|
body[data-layout="cloud"] .cloud-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); gap: var(--space-md, 14px); }
|
|
body[data-layout="cloud"] .cloud-stat { position: relative; overflow: hidden; background: var(--cloud-surface-3); border: 1px solid var(--cloud-border-medium); border-radius: var(--radius-lg, 14px); padding: var(--space-lg, 20px); display: flex; align-items: center; gap: var(--space-md, 14px); box-shadow: var(--cloud-shadow-sm); transition: border-color .12s ease, box-shadow .12s ease; }
|
|
body[data-layout="cloud"] .cloud-stat:hover { border-color: var(--cloud-border-strong); box-shadow: var(--cloud-shadow-md); }
|
|
body[data-layout="cloud"] .cloud-stat-icon { width: 46px; height: 46px; border-radius: var(--radius-md, 10px); display: flex; align-items: center; justify-content: center; background: rgba(34,211,238,0.13); color: var(--cloud-accent); flex-shrink: 0; }
|
|
body[data-layout="cloud"] .cloud-stat-icon svg { width: 22px; height: 22px; }
|
|
body[data-layout="cloud"] .cloud-stat-num { font-size: 28px; font-weight: 700; line-height: 1.05; color: var(--color-text); letter-spacing: -0.01em; }
|
|
body[data-layout="cloud"] .cloud-stat-label { font-size: 11px; color: var(--cloud-text-muted); text-transform: uppercase; letter-spacing: 0.07em; margin-top: 4px; }
|
|
/* circular usage gauges */
|
|
body[data-layout="cloud"] .cloud-gauge { width: 116px; height: 116px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background .3s ease; }
|
|
body[data-layout="cloud"] .cloud-gauge-inner { width: 86px; height: 86px; border-radius: 50%; background: var(--cloud-surface-2); display: flex; align-items: center; justify-content: center; }
|
|
|
|
/* ── Cloud console: shell / nav / topbar / table / detail-panel (CloudShell, cloud.js) ── */
|
|
.cloud-shell { display:flex; flex-direction:row; height:100vh; min-height:0; background:var(--cloud-surface-0, #060f1e); color:var(--color-text, #e6f1f8); }
|
|
.cloud-nav { background:var(--cloud-surface-1, #0a1628); }
|
|
.cloud-content-scroll { background:var(--cloud-surface-0, #060f1e); }
|
|
.cloud-content { flex:1 1 auto; display:flex; flex-direction:column; min-width:0; min-height:0; }
|
|
.cloud-content-main { position:relative; flex:1 1 auto; min-height:0; min-width:0; display:flex; }
|
|
.cloud-content-scroll { flex:1 1 auto; min-width:0; overflow-y:auto; padding:var(--space-lg); }
|
|
.cloud-body { display:flex; flex-direction:column; gap:var(--space-lg); }
|
|
.cloud-nav { width:220px; flex:0 0 220px; background:var(--cloud-surface-1); border-right:1px solid var(--cloud-border-subtle); padding:var(--space-md) 0; overflow-y:auto; }
|
|
.cloud-nav-brand { display:flex; align-items:center; gap:var(--space-sm); padding:0 var(--space-md) var(--space-md); border-bottom:1px solid var(--cloud-divider); margin-bottom:var(--space-md); }
|
|
.cloud-nav-brand-mark { color:var(--cloud-accent); display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; }
|
|
.cloud-nav-brand-mark svg { width:20px; height:20px; }
|
|
.cloud-nav-brand-mark img { width:30px; height:30px; object-fit:contain; display:block; }
|
|
.cloud-nav-brand-text { font-weight:700; font-size:0.98rem; letter-spacing:0.01em; color:var(--color-text); }
|
|
.cloud-nav-group { margin-bottom:var(--space-sm); }
|
|
.cloud-nav-group-label { font-size:0.65rem; letter-spacing:0.08em; font-weight:600; color:var(--cloud-text-muted); padding:var(--space-sm) var(--space-md) var(--space-xs); }
|
|
.cloud-nav-item { display:flex; align-items:center; gap:var(--space-sm); width:100%; border:none; background:transparent; color:var(--cloud-text-secondary); padding:var(--space-sm) var(--space-md); font-size:0.85rem; cursor:pointer; border-left:3px solid transparent; text-align:left; transition:background .12s, color .12s; }
|
|
.cloud-nav-item:hover { background:var(--cloud-surface-2); color:var(--color-text); }
|
|
.cloud-nav-item-icon { display:inline-flex; }
|
|
.cloud-nav-item-icon svg { width:18px; height:18px; }
|
|
.cloud-nav-item-active { background:var(--cloud-surface-2); color:var(--cloud-accent); border-left-color:var(--cloud-accent); font-weight:600; }
|
|
.cloud-topbar { display:flex; align-items:center; justify-content:space-between; padding:var(--space-md) var(--space-lg); border-bottom:1px solid var(--cloud-border-subtle); background:var(--cloud-surface-1); flex:0 0 auto; }
|
|
.cloud-breadcrumb { display:flex; align-items:center; gap:var(--space-xs); font-size:0.85rem; color:var(--cloud-text-secondary); }
|
|
.cloud-breadcrumb svg { width:16px; height:16px; }
|
|
.cloud-breadcrumb-root { color:var(--cloud-text-muted); }
|
|
.cloud-breadcrumb-sep { display:inline-flex; color:var(--cloud-text-muted); }
|
|
.cloud-breadcrumb-leaf { color:var(--color-text); font-weight:600; }
|
|
.cloud-topbar-actions { display:flex; align-items:center; gap:var(--space-sm); }
|
|
.cloud-cluster-select { background:var(--cloud-surface-2); color:var(--color-text); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:var(--space-xs) var(--space-sm); font-size:0.85rem; }
|
|
.cloud-btn { display:inline-flex; align-items:center; justify-content:center; gap:var(--space-xs); background:var(--cloud-surface-2); color:var(--color-text); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:var(--space-xs) var(--space-sm); font-size:0.85rem; cursor:pointer; }
|
|
.cloud-btn:hover { background:var(--cloud-surface-3); }
|
|
.cloud-btn-icon { padding:var(--space-xs); }
|
|
.cloud-btn-icon svg { width:16px; height:16px; }
|
|
.cloud-chip { display:inline-flex; align-items:center; gap:4px; font-size:0.72rem; font-weight:600; padding:2px 8px; border-radius:var(--radius-pill); background:var(--cloud-surface-2); border:1px solid var(--cloud-border-subtle); }
|
|
.cloud-chip-preview { color:var(--cloud-accent); background:transparent; border-color:var(--cloud-accent); margin-left:auto; letter-spacing:0.06em; }
|
|
.cloud-chip-tag { color:var(--cloud-text-secondary); }
|
|
.cloud-chip-tag svg { width:11px; height:11px; }
|
|
.cloud-gauge-row { display:flex; gap:var(--space-lg); flex-wrap:wrap; }
|
|
.cloud-gauge-card { display:flex; align-items:center; justify-content:center; flex:0 0 auto; min-width:200px; }
|
|
.cloud-gauge-wrap { display:flex; flex-direction:column; align-items:center; gap:var(--space-sm); }
|
|
.cloud-gauge-num { font-size:1.1rem; font-weight:700; color:var(--color-text); }
|
|
.cloud-gauge-label { font-size:0.78rem; color:var(--cloud-text-secondary); text-align:center; }
|
|
.cloud-section-title { font-size:0.95rem; font-weight:600; color:var(--color-text); margin-top:var(--space-sm); }
|
|
.cloud-empty { color:var(--cloud-text-muted); text-align:center; padding:var(--space-xl); }
|
|
.cloud-cluster-card { display:flex; flex-direction:column; gap:var(--space-xs); }
|
|
.cloud-cluster-head { display:flex; align-items:center; justify-content:space-between; gap:var(--space-sm); }
|
|
.cloud-cluster-name { font-weight:600; color:var(--color-text); }
|
|
.cloud-cluster-host { font-size:0.8rem; color:var(--cloud-text-muted); font-family:ui-monospace,monospace; }
|
|
.cloud-cluster-meta { font-size:0.78rem; color:var(--cloud-text-secondary); }
|
|
.cloud-table-card { padding:0; overflow:hidden; }
|
|
.cloud-table { width:100%; border-collapse:collapse; font-size:0.85rem; }
|
|
.cloud-table thead th { text-align:left; font-size:0.7rem; letter-spacing:0.05em; text-transform:uppercase; color:var(--cloud-text-muted); font-weight:600; padding:var(--space-sm) var(--space-md); border-bottom:1px solid var(--cloud-divider); background:var(--cloud-surface-1); }
|
|
.cloud-table td { padding:var(--space-sm) var(--space-md); border-bottom:1px solid var(--cloud-border-subtle); color:var(--color-text); vertical-align:middle; }
|
|
.cloud-table-row { cursor:pointer; transition:background .1s; }
|
|
.cloud-table-row:hover { background:var(--cloud-surface-2); }
|
|
.cloud-table-row-active { background:var(--cloud-surface-2); box-shadow:inset 3px 0 0 var(--cloud-accent); }
|
|
.cloud-table-name { display:inline-flex; align-items:center; gap:var(--space-sm); font-weight:500; }
|
|
.cloud-table-name-icon { color:var(--cloud-text-secondary); display:inline-flex; }
|
|
.cloud-table-name-icon svg { width:16px; height:16px; }
|
|
.cloud-table-mono { font-family:ui-monospace,monospace; color:var(--cloud-text-secondary); }
|
|
.cloud-table-note { padding:var(--space-sm) var(--space-md); font-size:0.78rem; color:var(--cloud-text-muted); border-top:1px solid var(--cloud-divider); }
|
|
.cloud-cell-meter { display:flex; align-items:center; gap:var(--space-sm); min-width:120px; }
|
|
.cloud-cell-meter .cloud-meter { flex:1 1 auto; }
|
|
.cloud-cell-meter-num { font-size:0.75rem; color:var(--cloud-text-secondary); width:34px; text-align:right; }
|
|
.cloud-placeholder { display:flex; flex-direction:column; align-items:center; gap:var(--space-sm); text-align:center; padding:var(--space-2xl); }
|
|
.cloud-placeholder-icon { color:var(--cloud-text-muted); }
|
|
.cloud-placeholder-icon svg { width:40px; height:40px; }
|
|
.cloud-placeholder-title { font-size:1rem; font-weight:600; color:var(--color-text); }
|
|
.cloud-placeholder-text { font-size:0.85rem; color:var(--cloud-text-secondary); max-width:380px; }
|
|
.cloud-panel { position:absolute; top:0; right:0; bottom:0; width:420px; max-width:92vw; background:var(--cloud-surface-raised); border-left:1px solid var(--cloud-border-medium); box-shadow:var(--cloud-shadow-xl); display:flex; flex-direction:column; z-index:40; animation:cloudPanelIn .18s ease-out; }
|
|
@keyframes cloudPanelIn { from { transform:translateX(100%); } to { transform:translateX(0); } }
|
|
.cloud-panel-header { display:flex; align-items:center; justify-content:space-between; padding:var(--space-md); border-bottom:1px solid var(--cloud-divider); }
|
|
.cloud-panel-title { display:flex; align-items:center; gap:var(--space-sm); min-width:0; }
|
|
.cloud-panel-title-icon { color:var(--cloud-accent); display:inline-flex; }
|
|
.cloud-panel-title-text { font-weight:600; color:var(--color-text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
.cloud-panel-close { background:transparent; border:none; color:var(--cloud-text-secondary); cursor:pointer; padding:var(--space-xs); border-radius:var(--radius-sm); }
|
|
.cloud-panel-close:hover { background:var(--cloud-surface-2); color:var(--color-text); }
|
|
.cloud-panel-close svg { width:18px; height:18px; }
|
|
.cloud-panel-tabs { display:flex; gap:var(--space-xs); padding:0 var(--space-md); border-bottom:1px solid var(--cloud-divider); }
|
|
.cloud-panel-tab { background:transparent; border:none; border-bottom:2px solid transparent; color:var(--cloud-text-secondary); padding:var(--space-sm) var(--space-sm); font-size:0.82rem; cursor:pointer; }
|
|
.cloud-panel-tab:hover { color:var(--color-text); }
|
|
.cloud-panel-tab-active { color:var(--cloud-accent); border-bottom-color:var(--cloud-accent); font-weight:600; }
|
|
.cloud-panel-body { flex:1 1 auto; overflow-y:auto; padding:var(--space-md); }
|
|
.cloud-panel-row { display:flex; align-items:center; justify-content:space-between; gap:var(--space-md); padding:var(--space-sm) 0; border-bottom:1px solid var(--cloud-border-subtle); font-size:0.85rem; }
|
|
.cloud-panel-row-key { color:var(--cloud-text-muted); }
|
|
.cloud-panel-row-val { color:var(--color-text); text-align:right; word-break:break-word; }
|
|
.cloud-panel-row-tags { align-items:flex-start; }
|
|
.cloud-panel-tags { display:flex; flex-wrap:wrap; gap:4px; justify-content:flex-end; }
|
|
.cloud-panel-meter-block { margin-bottom:var(--space-md); }
|
|
.cloud-panel-meter-label { font-size:0.82rem; color:var(--color-text); margin-bottom:var(--space-xs); }
|
|
.cloud-panel-meter-sub { font-size:0.75rem; color:var(--cloud-text-muted); margin-top:var(--space-xs); }
|
|
.cloud-panel-hint { font-size:0.78rem; color:var(--cloud-text-muted); margin-top:var(--space-md); }
|
|
|
|
/* ── Cloud console pass-2 polish: page header / utilization / toolbar / search / filled chips / select ── */
|
|
.cloud-page-header { display:flex; align-items:flex-end; justify-content:space-between; gap:var(--space-md); margin-bottom:var(--space-xs); }
|
|
.cloud-page-title { font-size:1.6rem; font-weight:700; color:var(--color-text); margin:0; letter-spacing:-0.01em; }
|
|
.cloud-page-sub { font-size:0.85rem; color:var(--cloud-text-muted); margin-top:4px; }
|
|
|
|
/* utilization card: gauges + numeric breakdown side by side, fills width */
|
|
.cloud-util-card { display:flex; align-items:center; gap:var(--space-2xl); flex-wrap:wrap; }
|
|
.cloud-util-gauges { display:flex; gap:var(--space-2xl); }
|
|
.cloud-util-breakdown { flex:1 1 260px; min-width:220px; display:flex; flex-direction:column; }
|
|
.cloud-util-row { display:flex; align-items:center; justify-content:space-between; gap:var(--space-md); padding:var(--space-sm) 0; border-bottom:1px solid var(--cloud-border-subtle); font-size:0.88rem; }
|
|
.cloud-util-row:last-child { border-bottom:none; }
|
|
.cloud-util-row > span:first-child { color:var(--cloud-text-muted); }
|
|
.cloud-util-row > span:last-child { color:var(--color-text); font-weight:600; font-variant-numeric:tabular-nums; }
|
|
|
|
/* table toolbar (title + count + selection note | search) */
|
|
.cloud-toolbar { display:flex; align-items:center; justify-content:space-between; gap:var(--space-md); padding:var(--space-md); border-bottom:1px solid var(--cloud-divider); flex-wrap:wrap; }
|
|
.cloud-toolbar-left { display:flex; align-items:center; gap:var(--space-sm); min-width:0; }
|
|
.cloud-toolbar-right { display:flex; align-items:center; gap:var(--space-sm); }
|
|
.cloud-toolbar-icon { color:var(--cloud-accent); display:inline-flex; }
|
|
.cloud-toolbar-icon svg { width:18px; height:18px; }
|
|
.cloud-toolbar-title { font-size:1rem; font-weight:600; color:var(--color-text); }
|
|
.cloud-count-chip { font-size:0.72rem; font-weight:600; color:var(--cloud-text-secondary); background:var(--cloud-surface-1); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-pill); padding:1px 9px; font-variant-numeric:tabular-nums; }
|
|
.cloud-sel-note { display:inline-flex; align-items:center; gap:var(--space-sm); margin-left:var(--space-sm); font-size:0.78rem; color:var(--cloud-accent); }
|
|
.cloud-sel-clear { background:transparent; border:none; color:var(--cloud-text-secondary); cursor:pointer; font-size:0.78rem; text-decoration:underline; padding:0; }
|
|
.cloud-sel-clear:hover { color:var(--color-text); }
|
|
|
|
/* search box */
|
|
.cloud-search { display:flex; align-items:center; gap:var(--space-xs); background:var(--cloud-surface-1); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:0 var(--space-sm); min-width:230px; transition:border-color .12s; }
|
|
.cloud-search:focus-within { border-color:var(--cloud-accent); }
|
|
.cloud-search-icon { display:inline-flex; color:var(--cloud-text-muted); }
|
|
.cloud-search-icon svg { width:15px; height:15px; }
|
|
.cloud-search input { flex:1 1 auto; background:transparent; border:none; outline:none; color:var(--color-text); font-size:0.85rem; padding:7px 0; min-width:0; }
|
|
.cloud-search input::placeholder { color:var(--cloud-text-muted); }
|
|
.cloud-search-clear { background:transparent; border:none; color:var(--cloud-text-muted); cursor:pointer; display:inline-flex; padding:2px; border-radius:var(--radius-sm); }
|
|
.cloud-search-clear:hover { color:var(--color-text); }
|
|
.cloud-search-clear svg { width:13px; height:13px; }
|
|
|
|
/* filled status pill + dot (gives tables the console look) */
|
|
.cloud-chip-status { border-style:solid; border-width:1px; }
|
|
.cloud-status-dot { width:7px; height:7px; border-radius:50%; flex:0 0 auto; }
|
|
|
|
/* selectable table: checkbox column + roomier rows */
|
|
.cloud-table-scroll { width:100%; overflow-x:auto; }
|
|
.cloud-table td { padding:13px var(--space-md); }
|
|
.cloud-th-check, .cloud-td-check { width:42px; text-align:center; padding-left:var(--space-md); padding-right:0; }
|
|
.cloud-table input[type="checkbox"] { width:15px; height:15px; accent-color:var(--cloud-accent); cursor:pointer; vertical-align:middle; }
|
|
.cloud-table-row-checked, .cloud-table-row-checked:hover { background:var(--cloud-selection); }
|
|
|
|
/* ══ Cloud console buildout (v2): KPI / detail / nodes / menus / buttons / light theme ══ */
|
|
/* buttons */
|
|
.cloud-btn svg { width:15px; height:15px; }
|
|
.cloud-btn-primary { background:var(--cloud-accent); color:#04141c; border-color:transparent; font-weight:600; }
|
|
.cloud-btn-primary:hover { background:var(--cloud-accent-hover); }
|
|
.cloud-btn-ghost { background:transparent; }
|
|
.cloud-btn-danger { color:#f4868a; border-color:rgba(248,113,113,0.4); background:transparent; }
|
|
.cloud-btn-danger:hover { background:rgba(248,113,113,0.12); color:#fca5a5; }
|
|
.cloud-btn-sm { padding:5px 10px; font-size:0.8rem; }
|
|
.cloud-link-btn { background:none; border:none; color:var(--cloud-accent); cursor:pointer; font-size:0.82rem; padding:0; display:inline-flex; align-items:center; gap:4px; }
|
|
.cloud-link-btn:hover { color:var(--cloud-accent-hover); text-decoration:underline; }
|
|
.cloud-link-btn svg { width:14px; height:14px; }
|
|
.cloud-input { width:100%; background:var(--cloud-surface-2); border:1px solid var(--cloud-border-medium, var(--cloud-divider)); border-radius:6px; color:var(--color-text); padding:8px 10px; font-size:0.85rem; }
|
|
.cloud-input:focus { outline:none; border-color:var(--cloud-accent); }
|
|
/* NS 2026-07 — harmonize the mounted Corporate/modern components with the cloud
|
|
theme. They render with the default proxmox-dark palette + proxmox-orange accent;
|
|
remap their surfaces/borders/accent to cloud tokens, the same trick the corporate
|
|
layout uses at data-layout=corporate. Scoped to .cloud-mounted so cloud-native
|
|
views are untouched. */
|
|
body[data-layout="cloud"] .cloud-mounted { --color-card: var(--cloud-surface-2); --color-border: var(--cloud-border-subtle); --color-bg: var(--cloud-surface-0); --color-secondary: var(--cloud-surface-2); }
|
|
body[data-layout="cloud"] .cloud-mounted .bg-proxmox-dark { background: var(--cloud-surface-1) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .bg-proxmox-darker { background: var(--cloud-surface-0) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .bg-proxmox-card { background: var(--cloud-surface-2) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .bg-proxmox-secondary { background: var(--cloud-surface-2) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .border-proxmox-border { border-color: var(--cloud-border-subtle) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .text-proxmox-orange { color: var(--cloud-accent) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .bg-proxmox-orange { background: var(--cloud-accent) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .border-proxmox-orange { border-color: var(--cloud-accent) !important; }
|
|
/* recolour the common blue "primary" accents used by the modern components to the cloud accent */
|
|
body[data-layout="cloud"] .cloud-mounted .bg-blue-600, body[data-layout="cloud"] .cloud-mounted .bg-blue-500 { background: var(--cloud-accent) !important; color: #04121a !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .text-blue-400, body[data-layout="cloud"] .cloud-mounted .text-blue-500 { color: var(--cloud-accent) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .border-blue-500, body[data-layout="cloud"] .cloud-mounted .border-blue-600 { border-color: var(--cloud-accent) !important; }
|
|
body[data-layout="cloud"] .cloud-mounted .hover\:bg-blue-700:hover { background: var(--cloud-accent-hover) !important; }
|
|
|
|
/* icon button */
|
|
.cloud-icon-btn { display:inline-flex; align-items:center; justify-content:center; width:32px; height:32px; border-radius:var(--radius-md); background:transparent; border:1px solid transparent; color:var(--cloud-text-secondary); cursor:pointer; flex:0 0 auto; transition:background .12s, color .12s; }
|
|
.cloud-icon-btn:hover { background:var(--cloud-surface-2); color:var(--color-text); }
|
|
.cloud-icon-btn:disabled { opacity:0.35; cursor:default; }
|
|
.cloud-icon-btn svg { width:17px; height:17px; }
|
|
.cloud-icon-btn-danger:hover { color:#f4868a; }
|
|
|
|
/* KPI tiles */
|
|
.cloud-kpi-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(186px, 1fr)); gap:var(--space-md); }
|
|
.cloud-kpi { position:relative; overflow:hidden; display:flex; align-items:center; gap:var(--space-md); padding:var(--space-lg); border-radius:var(--radius-lg); border:1px solid color-mix(in srgb, var(--kpi-accent) 28%, var(--cloud-border-medium)); background:linear-gradient(135deg, color-mix(in srgb, var(--kpi-accent) 20%, var(--cloud-surface-3)), var(--cloud-surface-3) 72%); box-shadow:var(--cloud-shadow-sm); transition:transform .12s ease, box-shadow .12s ease; }
|
|
.cloud-kpi-click { cursor:pointer; }
|
|
.cloud-kpi-click:hover { transform:translateY(-2px); box-shadow:var(--cloud-shadow-md); }
|
|
.cloud-kpi-icon { width:48px; height:48px; border-radius:13px; display:flex; align-items:center; justify-content:center; background:color-mix(in srgb, var(--kpi-accent) 24%, transparent); color:var(--kpi-accent); flex:0 0 auto; }
|
|
.cloud-kpi-icon svg { width:24px; height:24px; }
|
|
.cloud-kpi-value { font-size:1.7rem; font-weight:700; line-height:1.05; color:var(--color-text); letter-spacing:-0.01em; }
|
|
.cloud-kpi-label { font-size:0.78rem; color:var(--cloud-text-secondary); margin-top:2px; }
|
|
.cloud-kpi-sub { font-size:0.72rem; color:var(--cloud-text-muted); margin-top:3px; }
|
|
|
|
/* dashboard layout */
|
|
.cloud-dash-grid { display:grid; grid-template-columns:1.25fr 1fr; gap:var(--space-lg); align-items:start; }
|
|
@media (max-width:1100px) { .cloud-dash-grid { grid-template-columns:1fr; } }
|
|
.cloud-section-row { display:flex; align-items:center; justify-content:space-between; gap:var(--space-md); margin-bottom:var(--space-xs); }
|
|
.cloud-util-card { display:block; }
|
|
.cloud-util-body { display:flex; align-items:center; gap:var(--space-xl); flex-wrap:wrap; margin-top:var(--space-md); }
|
|
.cloud-util-gauges { display:flex; gap:var(--space-xl); }
|
|
.cloud-util-breakdown { flex:1 1 220px; min-width:200px; display:flex; flex-direction:column; }
|
|
.cloud-gauge-sub { font-size:0.72rem; color:var(--cloud-text-muted); text-align:center; }
|
|
|
|
/* bar chart */
|
|
.cloud-barchart { display:flex; flex-direction:column; gap:10px; margin-top:var(--space-md); }
|
|
.cloud-bar-row { display:flex; align-items:center; gap:10px; font-size:0.82rem; }
|
|
.cloud-bar-label { width:120px; flex:0 0 120px; color:var(--cloud-text-secondary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
.cloud-bar-track { flex:1 1 auto; height:8px; background:var(--cloud-surface-1); border-radius:var(--radius-pill); overflow:hidden; }
|
|
.cloud-bar-fill { height:100%; border-radius:var(--radius-pill); transition:width .3s ease; }
|
|
.cloud-bar-val { width:74px; flex:0 0 74px; text-align:right; color:var(--cloud-text-muted); font-variant-numeric:tabular-nums; }
|
|
|
|
/* task list */
|
|
.cloud-tasklist { display:flex; flex-direction:column; margin-top:var(--space-sm); }
|
|
.cloud-task-row { display:flex; align-items:center; gap:10px; padding:9px 0; border-bottom:1px solid var(--cloud-border-subtle); font-size:0.84rem; }
|
|
.cloud-task-row:last-child { border-bottom:none; }
|
|
.cloud-task-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
|
|
.cloud-task-dot.is-run { background:#38bdf8; } .cloud-task-dot.is-ok { background:#2dd4a7; } .cloud-task-dot.is-err { background:#f87171; }
|
|
.cloud-task-type { font-weight:600; color:var(--color-text); min-width:96px; }
|
|
.cloud-task-target { color:var(--cloud-text-secondary); font-family:ui-monospace,monospace; }
|
|
.cloud-task-node { color:var(--cloud-text-muted); }
|
|
.cloud-task-time { margin-left:auto; color:var(--cloud-text-muted); white-space:nowrap; }
|
|
|
|
/* usage bars */
|
|
.cloud-usage { display:flex; flex-direction:column; gap:5px; }
|
|
.cloud-usage-head { display:flex; justify-content:space-between; font-size:0.78rem; color:var(--cloud-text-secondary); }
|
|
.cloud-usage-right { color:var(--cloud-text-muted); font-variant-numeric:tabular-nums; }
|
|
.cloud-meter-lg { height:9px; }
|
|
|
|
/* segmented filter */
|
|
.cloud-segment { display:inline-flex; background:var(--cloud-surface-1); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:2px; gap:2px; }
|
|
.cloud-segment-btn { background:transparent; border:none; color:var(--cloud-text-secondary); padding:4px 12px; font-size:0.8rem; border-radius:var(--radius-sm); cursor:pointer; }
|
|
.cloud-segment-btn:hover { color:var(--color-text); }
|
|
.cloud-segment-btn.is-active { background:var(--cloud-surface-3); color:var(--cloud-accent); font-weight:600; box-shadow:var(--cloud-shadow-sm); }
|
|
.cloud-bulkbar { display:flex; align-items:center; gap:var(--space-sm); flex-wrap:wrap; }
|
|
|
|
/* dropdown menu */
|
|
.cloud-menu { background:var(--cloud-surface-raised); border:1px solid var(--cloud-border-strong); border-radius:var(--radius-md); box-shadow:var(--cloud-shadow-lg); padding:6px; min-width:200px; display:flex; flex-direction:column; gap:1px; }
|
|
.cloud-menu-fixed { position:fixed; z-index:80; }
|
|
.cloud-menu-item { display:flex; align-items:center; gap:10px; width:100%; background:transparent; border:none; color:var(--cloud-text-secondary); padding:8px 10px; font-size:0.84rem; text-align:left; border-radius:var(--radius-sm); cursor:pointer; }
|
|
.cloud-menu-item:hover { background:var(--cloud-surface-2); color:var(--color-text); }
|
|
.cloud-menu-item:disabled { opacity:0.4; cursor:default; }
|
|
.cloud-menu-item-danger { color:#f4868a; }
|
|
.cloud-menu-item-danger:hover { background:rgba(248,113,113,0.12); color:#fca5a5; }
|
|
.cloud-menu-icon { display:inline-flex; } .cloud-menu-icon svg { width:15px; height:15px; }
|
|
.cloud-menu-sep { height:1px; background:var(--cloud-divider); margin:4px 2px; }
|
|
|
|
/* pager + table foot */
|
|
.cloud-table-foot:empty { display:none; }
|
|
.cloud-table-foot { display:flex; justify-content:flex-end; padding:var(--space-sm) var(--space-md); border-top:1px solid var(--cloud-divider); }
|
|
.cloud-pager { display:flex; align-items:center; gap:6px; }
|
|
.cloud-pager-text { font-size:0.8rem; color:var(--cloud-text-muted); margin-right:4px; font-variant-numeric:tabular-nums; }
|
|
|
|
/* empty state */
|
|
.cloud-empty-state { display:flex; flex-direction:column; align-items:center; gap:10px; padding:var(--space-2xl); text-align:center; }
|
|
.cloud-empty-icon { color:var(--cloud-text-muted); } .cloud-empty-icon svg { width:36px; height:36px; }
|
|
.cloud-empty-title { font-size:0.95rem; font-weight:600; color:var(--color-text); }
|
|
.cloud-empty-text { font-size:0.84rem; color:var(--cloud-text-muted); max-width:380px; }
|
|
|
|
/* page header actions + table extras */
|
|
.cloud-page-header-actions { display:flex; align-items:center; gap:var(--space-sm); }
|
|
.cloud-th-actions, .cloud-td-actions { width:48px; text-align:right; }
|
|
.cloud-table-row-static { cursor:default; }
|
|
.cloud-table-row-static:hover { background:transparent; }
|
|
.cloud-sort-arrow { color:var(--cloud-accent); font-size:0.7rem; }
|
|
.cloud-table-name-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:300px; }
|
|
.cloud-cell-muted { color:var(--cloud-text-muted); font-size:0.8rem; }
|
|
|
|
/* detail view */
|
|
.cloud-detail-head { display:flex; align-items:center; gap:var(--space-md); margin-bottom:var(--space-md); flex-wrap:wrap; }
|
|
.cloud-detail-icon { width:44px; height:44px; border-radius:12px; display:flex; align-items:center; justify-content:center; background:rgba(34,211,238,0.13); color:var(--cloud-accent); flex:0 0 auto; }
|
|
.cloud-detail-icon svg { width:22px; height:22px; }
|
|
.cloud-detail-titlewrap { flex:1 1 auto; min-width:160px; }
|
|
.cloud-detail-title { font-size:1.4rem; font-weight:700; margin:0; color:var(--color-text); }
|
|
.cloud-detail-meta { display:flex; align-items:center; gap:10px; margin-top:5px; flex-wrap:wrap; }
|
|
.cloud-detail-id { font-size:0.82rem; color:var(--cloud-text-muted); }
|
|
.cloud-detail-actions { display:flex; align-items:center; gap:var(--space-sm); flex-wrap:wrap; }
|
|
|
|
/* tabs */
|
|
.cloud-tabs { display:flex; gap:4px; border-bottom:1px solid var(--cloud-divider); margin-bottom:var(--space-lg); flex-wrap:wrap; }
|
|
.cloud-tab { background:transparent; border:none; border-bottom:2px solid transparent; color:var(--cloud-text-secondary); padding:10px 14px; font-size:0.86rem; cursor:pointer; }
|
|
.cloud-tab:hover { color:var(--color-text); }
|
|
.cloud-tab-active { color:var(--cloud-accent); border-bottom-color:var(--cloud-accent); font-weight:600; }
|
|
|
|
/* key-value panels */
|
|
.cloud-kv-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(320px, 1fr)); gap:var(--space-lg); }
|
|
.cloud-kv-panel { background:var(--cloud-surface-3); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-lg); padding:var(--space-lg); box-shadow:var(--cloud-shadow-sm); }
|
|
.cloud-kv-title { font-size:0.78rem; font-weight:600; text-transform:uppercase; letter-spacing:0.05em; color:var(--cloud-text-muted); margin-bottom:var(--space-sm); }
|
|
.cloud-kv-row { display:flex; align-items:center; justify-content:space-between; gap:var(--space-md); padding:7px 0; border-bottom:1px solid var(--cloud-border-subtle); font-size:0.86rem; }
|
|
.cloud-kv-row:last-child { border-bottom:none; }
|
|
.cloud-kv-key { color:var(--cloud-text-muted); }
|
|
.cloud-kv-val { color:var(--color-text); text-align:right; word-break:break-word; font-weight:500; }
|
|
.cloud-tag-wrap { display:flex; flex-wrap:wrap; gap:6px; }
|
|
|
|
/* large meter blocks (capacity tab) */
|
|
.cloud-meter-block { margin-bottom:var(--space-lg); }
|
|
.cloud-meter-block:last-child { margin-bottom:0; }
|
|
.cloud-meter-label { font-size:0.86rem; color:var(--color-text); margin-bottom:6px; font-weight:500; }
|
|
.cloud-meter-sub { font-size:0.78rem; color:var(--cloud-text-muted); margin-top:6px; }
|
|
|
|
/* soft / warn chips */
|
|
.cloud-chip-soft { color:var(--cloud-text-secondary); background:var(--cloud-surface-2); border:1px solid var(--cloud-border-medium); }
|
|
.cloud-chip-warn { color:#e0a82e; background:rgba(245,185,69,0.14); border:1px solid rgba(245,185,69,0.4); }
|
|
|
|
/* cluster / pool cards */
|
|
.cloud-cluster-card, .cloud-pool-card { display:flex; flex-direction:column; gap:var(--space-sm); }
|
|
.cloud-cluster-name { display:flex; align-items:center; gap:8px; font-weight:600; color:var(--color-text); }
|
|
.cloud-cluster-name svg { width:16px; height:16px; color:var(--cloud-accent); }
|
|
.cloud-cluster-badges { display:flex; flex-wrap:wrap; gap:6px; }
|
|
.cloud-cluster-stats { display:flex; gap:var(--space-lg); margin-top:auto; padding-top:var(--space-sm); border-top:1px solid var(--cloud-border-subtle); }
|
|
.cloud-cluster-stats > div { display:flex; flex-direction:column; }
|
|
.cloud-cluster-stat-num { font-size:1.2rem; font-weight:700; color:var(--color-text); font-variant-numeric:tabular-nums; }
|
|
.cloud-cluster-stat-lbl { font-size:0.7rem; color:var(--cloud-text-muted); text-transform:uppercase; letter-spacing:0.05em; }
|
|
|
|
/* node / host cards */
|
|
.cloud-card-grid-wide { grid-template-columns:repeat(auto-fill, minmax(360px, 1fr)); }
|
|
.cloud-node-card { display:flex; flex-direction:column; gap:var(--space-md); }
|
|
.cloud-node-head { display:flex; align-items:center; justify-content:space-between; gap:var(--space-sm); }
|
|
.cloud-node-name { display:flex; align-items:center; gap:8px; font-weight:600; color:var(--color-text); }
|
|
.cloud-node-name svg { width:16px; height:16px; color:var(--cloud-accent); }
|
|
.cloud-node-head-right { display:flex; align-items:center; gap:8px; }
|
|
.cloud-node-meters { display:flex; flex-direction:column; gap:11px; }
|
|
.cloud-node-foot { display:flex; gap:var(--space-md); flex-wrap:wrap; font-size:0.78rem; color:var(--cloud-text-muted); padding-top:var(--space-sm); border-top:1px solid var(--cloud-border-subtle); }
|
|
.cloud-node-foot span { display:inline-flex; align-items:center; gap:5px; }
|
|
.cloud-node-foot svg { width:13px; height:13px; }
|
|
|
|
/* classic launcher */
|
|
.cloud-launcher { display:flex; flex-direction:column; align-items:center; gap:var(--space-md); text-align:center; padding:var(--space-2xl); }
|
|
.cloud-launcher-icon { color:var(--cloud-text-muted); } .cloud-launcher-icon svg { width:44px; height:44px; }
|
|
.cloud-launcher-text { font-size:0.9rem; color:var(--cloud-text-secondary); max-width:440px; }
|
|
|
|
/* collapsible nav */
|
|
.cloud-nav { transition:width .15s ease; }
|
|
.cloud-nav-collapsed { width:64px; flex:0 0 64px; }
|
|
.cloud-nav-scroll { flex:1 1 auto; overflow-y:auto; overflow-x:hidden; }
|
|
.cloud-nav-collapse { margin:var(--space-sm); border:1px solid var(--cloud-border-medium); background:var(--cloud-surface-2); color:var(--cloud-text-secondary); border-radius:var(--radius-md); padding:7px; cursor:pointer; display:flex; align-items:center; justify-content:center; }
|
|
.cloud-nav-collapse:hover { color:var(--color-text); }
|
|
.cloud-nav-collapse svg { width:16px; height:16px; }
|
|
.cloud-nav-collapsed .cloud-nav-item { justify-content:center; padding-left:0; padding-right:0; }
|
|
.cloud-nav-collapsed .cloud-nav-brand { justify-content:center; padding:0 0 var(--space-md); }
|
|
|
|
/* topbar cluster picker wrapper */
|
|
.cloud-cluster-pick { display:flex; align-items:center; gap:6px; background:var(--cloud-surface-2); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:0 8px; }
|
|
.cloud-cluster-pick svg { width:15px; height:15px; color:var(--cloud-text-muted); }
|
|
.cloud-cluster-pick .cloud-cluster-select { background:transparent; border:none; padding:7px 4px; }
|
|
.cloud-btn-ghost svg { width:15px; height:15px; }
|
|
|
|
/* ── Cloud LIGHT theme (toggle in topbar) ── */
|
|
body[data-layout="cloud"][data-cloud-theme="light"] {
|
|
--color-darker:#eef1f6; --color-dark:#ffffff; --color-card:#ffffff;
|
|
--color-text:#16222e; --color-text-muted:#5d6b79;
|
|
--cloud-surface-0:#eef1f6; --cloud-surface-1:#ffffff; --cloud-surface-2:#f3f6fa;
|
|
--cloud-surface-3:#ffffff; --cloud-surface-raised:#ffffff;
|
|
--cloud-text-secondary:#3f4d5a; --cloud-text-muted:#6a7a89;
|
|
--cloud-divider:#e4e9ef; --cloud-border-subtle:#edf1f5; --cloud-border-medium:#dde3ea; --cloud-border-strong:#c6d0da;
|
|
--cloud-selection:#e1f3f8; --cloud-gauge-track:#e4e9ef;
|
|
--cloud-accent:#0098c3; --cloud-accent-hover:#007ba0;
|
|
--cloud-shadow-sm:0 1px 2px rgba(20,40,70,0.06);
|
|
--cloud-shadow-md:0 4px 12px rgba(20,40,70,0.08), 0 1px 3px rgba(20,40,70,0.05);
|
|
--cloud-shadow-lg:0 10px 28px rgba(20,40,70,0.13), 0 2px 6px rgba(20,40,70,0.06);
|
|
--cloud-shadow-xl:0 20px 48px rgba(20,40,70,0.16);
|
|
--scrollbar-track:#eef1f6; --scrollbar-thumb:#d2dae2; --scrollbar-thumb-hover:#bcc7d1;
|
|
}
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-shell { background:var(--cloud-surface-0); color:var(--color-text); }
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-nav { background:var(--cloud-surface-1); }
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-content-scroll { background:var(--cloud-surface-0); }
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-btn-primary { color:#ffffff; }
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-detail-icon,
|
|
body[data-layout="cloud"][data-cloud-theme="light"] .cloud-stat-icon { background:rgba(0,152,195,0.12); }
|
|
|
|
/* ── masthead user menu + labelled Actions trigger + language ── */
|
|
.cloud-menu-trigger-plain { background:transparent; border:none; padding:0; cursor:pointer; display:inline-flex; }
|
|
.cloud-user-btn { display:inline-flex; align-items:center; gap:8px; padding:4px 9px 4px 4px; border-radius:var(--radius-pill); background:var(--cloud-surface-2); border:1px solid var(--cloud-border-medium); color:var(--cloud-text-secondary); transition:border-color .12s, color .12s; }
|
|
.cloud-user-btn:hover { color:var(--color-text); border-color:var(--cloud-border-strong); }
|
|
.cloud-user-avatar { width:26px; height:26px; border-radius:50%; background:var(--cloud-accent); color:#04141c; font-weight:700; font-size:0.8rem; display:flex; align-items:center; justify-content:center; flex:0 0 auto; }
|
|
.cloud-user-name { font-size:0.84rem; font-weight:500; max-width:140px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
.cloud-user-btn svg { width:14px; height:14px; }
|
|
.cloud-lang { display:inline-flex; align-items:center; font-size:0.8rem; }
|
|
.cloud-lang select { background:var(--cloud-surface-2); color:var(--color-text); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-md); padding:5px 6px; font-size:0.8rem; }
|
|
.cloud-lang button { color:var(--cloud-text-muted); }
|
|
|
|
/* filter chips row (list toolbar) */
|
|
.cloud-filterchips { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:0 var(--space-md) var(--space-sm); }
|
|
.cloud-filterchip { display:inline-flex; align-items:center; gap:6px; font-size:0.76rem; color:var(--cloud-text-secondary); background:var(--cloud-surface-1); border:1px solid var(--cloud-border-medium); border-radius:var(--radius-pill); padding:3px 6px 3px 10px; }
|
|
.cloud-filterchip button { background:transparent; border:none; color:var(--cloud-text-muted); cursor:pointer; display:inline-flex; padding:1px; border-radius:50%; }
|
|
.cloud-filterchip button:hover { color:var(--color-text); background:var(--cloud-surface-3); }
|
|
.cloud-filterchip svg { width:12px; height:12px; }
|
|
.cloud-clearfilters { background:none; border:none; color:var(--cloud-accent); cursor:pointer; font-size:0.78rem; }
|
|
.cloud-clearfilters:hover { text-decoration:underline; }
|
|
.cloud-empty-action { margin-top:var(--space-sm); }
|
|
</style>
|
|
</head>
|
|
<body class="dark notranslate">
|
|
<script>
|
|
// NS Apr 2026 (#342) — apply noise-off attribute as early as possible to
|
|
// avoid a brief flash of the overlay on page load. localStorage flag set
|
|
// by the toggle in user prefs.
|
|
try { if (localStorage.getItem('pegaprox-noise') === 'off') document.body.setAttribute('data-noise', 'off'); } catch(_) {}
|
|
</script>
|
|
<div class="noise-overlay"></div>
|
|
|
|
<!-- NS: Loading screen - shows immediately while Babel compiles -->
|
|
<div id="loading-screen" style="
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: linear-gradient(135deg, #1a1a2e 0%, #0f0f1a 100%);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 9999;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
">
|
|
<div style="
|
|
width: 80px;
|
|
height: 80px;
|
|
border: 3px solid rgba(226, 109, 65, 0.2);
|
|
border-top-color: #e26d41;
|
|
border-radius: 50%;
|
|
animation: spin 1s linear infinite;
|
|
"></div>
|
|
<div style="color: #e26d41; font-size: 24px; font-weight: 600; margin-top: 24px;">
|
|
PegaProx
|
|
</div>
|
|
<div style="color: #888; font-size: 14px; margin-top: 8px;">
|
|
Loading...
|
|
</div>
|
|
</div>
|
|
<style>
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
@keyframes sponsorNagPopIn {
|
|
from { opacity: 0; transform: scale(0.85) translateY(20px); }
|
|
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
}
|
|
</style>
|
|
|
|
<div id="root"></div>
|
|
|
|
|
|
<!-- PEGAPROX_JSX_INSERT -->
|
|
<!-- Build: cd web/Dev && ./build.sh -->
|
|
|
|
</body>
|
|
</html>
|