core/frontend/css/neu.css
enzo b851dc61af fix: couleurs icônes, boutons carrés, sidebar collapsée, langue, SW scope, LXC arrêté
Icônes :
- Sidebar navItems : couleur distincte par section (iconStyle via data-binding)
- Sidebar footer user : couleur primary
- Navbar : logout → danger, soleil → amber, lune → blue
- Panel widgets : œil visible → success, caché → muted

Boutons :
- `.neu-btn--sm:has(> i:only-child)` → carré 2rem×2rem automatiquement
  (theme, logout, mode édition) sans modifier le HTML

Sidebar :
- --sidebar-width-collapsed : 64px → 52px
- Sidebar réduite : icônes centrées (justify-content center)

Langue :
- Setter vide sur `lang` dans navbar() pour corriger x-model avec getter
  (le @change gère la vraie mise à jour du store)

Service Worker :
- Enregistrement depuis /ws.sw.js (scope /) au lieu de /js/ws.sw.js (scope /js/)
- build.mjs : copie ws.sw.js vers dist/ root en plus de dist/js/

LXC arrêté :
- checkTarget() : skip si target.status !== 'running' → évite les 502 SSH

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 19:50:58 +01:00

645 lines
16 KiB
CSS

/* =============================================================================
ProxmoxPanel — Système de design Neumorphism
Définit les classes utilitaires et les variables CSS du thème.
Utilisé par tous les composants et les modules.
============================================================================= */
/* ── Reset / Base ───────────────────────────────────────────────────────────── */
*, *::before, *::after {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif;
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
body {
min-height: 100vh;
background-color: var(--neu-bg);
color: var(--neu-text);
}
h1, h2, h3, h4, h5, h6 { margin: 0; }
p { margin: 0; }
a { color: inherit; }
button { font-family: inherit; font-size: inherit; }
input, select, textarea { font-family: inherit; font-size: inherit; }
/* ── Variables CSS (surchargées par dark.css et light.css) ─────────────────── */
:root {
/* Couleurs de base */
--neu-bg: #1e2130;
--neu-surface: #252838;
--neu-text: #e0e4f0;
--neu-text-muted: #7f8899;
--neu-border: #2e3348;
/* Ombres Neumorphism */
--neu-shadow-dark: #161823;
--neu-shadow-light: #2a2f48;
/* Couleurs d'accent */
--neu-primary: #6c8ef4;
--neu-primary-dim: #4a6bd4;
--neu-success: #4cbb8a;
--neu-warning: #f5a623;
--neu-danger: #f05c6b;
--neu-info: #3dbfcf;
/* Typographie */
--neu-font-xs: 11px;
--neu-font-sm: 12px;
--neu-font-md: 14px;
--neu-font-lg: 16px;
--neu-font-xl: 20px;
--neu-font-2xl: 24px;
/* Espacements */
--neu-space-xs: 4px;
--neu-space-sm: 8px;
--neu-space-md: 16px;
--neu-space-lg: 24px;
--neu-space-xl: 32px;
/* Rayons */
--neu-radius-sm: 8px;
--neu-radius-md: 12px;
--neu-radius-lg: 16px;
--neu-radius-xl: 24px;
--neu-radius-full: 9999px;
/* Transitions */
--neu-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
/* Sidebar */
--sidebar-width: 240px;
--sidebar-width-collapsed: 52px;
/* Z-index */
--z-sidebar: 100;
--z-navbar: 200;
--z-modal: 300;
--z-toast: 400;
}
/* ── Carte Neumorphism (élévation convexe) ─────────────────────────────────── */
.neu-card {
background: var(--neu-surface);
border-radius: var(--neu-radius-lg);
box-shadow:
6px 6px 12px var(--neu-shadow-dark),
-4px -4px 10px var(--neu-shadow-light);
border: 1px solid var(--neu-border);
padding: var(--neu-space-md);
color: var(--neu-text);
transition: var(--neu-transition);
}
.neu-card--flat {
box-shadow: none;
border: 1px solid var(--neu-border);
}
.neu-card--hover:hover {
box-shadow:
8px 8px 16px var(--neu-shadow-dark),
-6px -6px 14px var(--neu-shadow-light);
transform: translateY(-1px);
}
/* ── Surface enfoncée (inputs, zones de saisie) ────────────────────────────── */
.neu-inset {
background: var(--neu-bg);
border-radius: var(--neu-radius-md);
box-shadow:
inset 3px 3px 7px var(--neu-shadow-dark),
inset -2px -2px 5px var(--neu-shadow-light);
border: 1px solid var(--neu-border);
}
/* ── Boutons ────────────────────────────────────────────────────────────────── */
.neu-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--neu-space-xs);
padding: var(--neu-space-sm) var(--neu-space-md);
border-radius: var(--neu-radius-md);
font-size: var(--neu-font-md);
font-weight: 500;
cursor: pointer;
border: none;
outline: none;
transition: var(--neu-transition);
text-decoration: none;
white-space: nowrap;
user-select: none;
color: var(--neu-text);
background: var(--neu-surface);
box-shadow:
4px 4px 8px var(--neu-shadow-dark),
-3px -3px 6px var(--neu-shadow-light);
}
.neu-btn:hover:not(:disabled) {
box-shadow:
6px 6px 12px var(--neu-shadow-dark),
-4px -4px 8px var(--neu-shadow-light);
transform: translateY(-1px);
}
.neu-btn:active:not(:disabled) {
box-shadow:
inset 2px 2px 5px var(--neu-shadow-dark),
inset -1px -1px 3px var(--neu-shadow-light);
transform: translateY(0);
}
.neu-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Variantes de boutons */
.neu-btn--primary {
background: var(--neu-primary);
color: #fff;
box-shadow:
4px 4px 8px rgba(0,0,0,0.3),
-2px -2px 6px rgba(255,255,255,0.05);
}
.neu-btn--primary:hover:not(:disabled) {
background: var(--neu-primary-dim);
box-shadow:
6px 6px 12px rgba(0,0,0,0.4),
-3px -3px 8px rgba(255,255,255,0.06);
}
.neu-btn--success {
background: var(--neu-success);
color: #fff;
}
.neu-btn--danger {
background: var(--neu-danger);
color: #fff;
}
.neu-btn--warning {
background: var(--neu-warning);
color: #1a1a2e;
}
.neu-btn--sm {
padding: 4px 10px;
font-size: var(--neu-font-sm);
border-radius: var(--neu-radius-sm);
}
.neu-btn--lg {
padding: 12px 24px;
font-size: var(--neu-font-lg);
border-radius: var(--neu-radius-lg);
}
.neu-btn--icon {
width: 40px;
height: 40px;
padding: 0;
border-radius: var(--neu-radius-md);
}
/* Bouton icône carré taille sm — se déclenche automatiquement si le bouton
ne contient qu'un <i> (ex: theme, logout, edit mode) */
.neu-btn--sm:has(> i:only-child) {
width: 2rem;
height: 2rem;
padding: 0;
}
.neu-btn--ghost {
background: transparent;
box-shadow: none;
border: 1px solid var(--neu-border);
}
.neu-btn--ghost:hover:not(:disabled) {
background: var(--neu-surface);
box-shadow:
2px 2px 5px var(--neu-shadow-dark),
-1px -1px 3px var(--neu-shadow-light);
}
/* ── Inputs ─────────────────────────────────────────────────────────────────── */
.neu-input {
width: 100%;
padding: var(--neu-space-sm) var(--neu-space-md);
background: var(--neu-bg);
color: var(--neu-text);
border: 1px solid var(--neu-border);
border-radius: var(--neu-radius-md);
font-size: var(--neu-font-md);
outline: none;
transition: var(--neu-transition);
box-shadow:
inset 3px 3px 7px var(--neu-shadow-dark),
inset -2px -2px 5px var(--neu-shadow-light);
}
.neu-input:focus {
border-color: var(--neu-primary);
box-shadow:
inset 3px 3px 7px var(--neu-shadow-dark),
inset -2px -2px 5px var(--neu-shadow-light),
0 0 0 2px rgba(108, 142, 244, 0.25);
}
.neu-input::placeholder {
color: var(--neu-text-muted);
}
.neu-input--error {
border-color: var(--neu-danger) !important;
}
/* ── Toggle switch ───────────────────────────────────────────────────────────── */
.neu-toggle {
position: relative;
display: inline-block;
width: 44px;
height: 24px;
flex-shrink: 0;
}
.neu-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.neu-toggle__slider {
position: absolute;
inset: 0;
background: var(--neu-bg);
border-radius: var(--neu-radius-full);
cursor: pointer;
transition: var(--neu-transition);
box-shadow:
inset 2px 2px 5px var(--neu-shadow-dark),
inset -1px -1px 3px var(--neu-shadow-light);
}
.neu-toggle__slider::before {
content: '';
position: absolute;
width: 18px;
height: 18px;
left: 3px;
bottom: 3px;
background: var(--neu-text-muted);
border-radius: 50%;
transition: var(--neu-transition);
box-shadow: 2px 2px 4px var(--neu-shadow-dark);
}
.neu-toggle input:checked + .neu-toggle__slider {
background: var(--neu-primary);
box-shadow:
inset 2px 2px 5px rgba(0,0,0,0.3),
inset -1px -1px 3px rgba(255,255,255,0.1);
}
.neu-toggle input:checked + .neu-toggle__slider::before {
transform: translateX(20px);
background: #fff;
}
/* ── Badges / Tags ───────────────────────────────────────────────────────────── */
.neu-badge {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: var(--neu-radius-full);
font-size: var(--neu-font-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.neu-badge--success { background: rgba(76, 187, 138, 0.15); color: var(--neu-success); }
.neu-badge--danger { background: rgba(240, 92, 107, 0.15); color: var(--neu-danger); }
.neu-badge--warning { background: rgba(245, 166, 35, 0.15); color: var(--neu-warning); }
.neu-badge--info { background: rgba(61, 191, 207, 0.15); color: var(--neu-info); }
.neu-badge--primary { background: rgba(108, 142, 244, 0.15); color: var(--neu-primary); }
/* ── Séparateurs ────────────────────────────────────────────────────────────── */
.neu-divider {
height: 1px;
background: linear-gradient(90deg, transparent, var(--neu-border), transparent);
border: none;
margin: var(--neu-space-md) 0;
}
/* ── Utilitaires de layout ──────────────────────────────────────────────────── */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }
.gap-sm { gap: var(--neu-space-sm); }
.gap-md { gap: var(--neu-space-md); }
.gap-lg { gap: var(--neu-space-lg); }
.w-full { width: 100%; }
.h-full { height: 100%; }
/* ── Grid responsive ────────────────────────────────────────────────────────── */
.neu-grid {
display: grid;
gap: var(--neu-space-md);
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
/* ── Scrollbar personnalisée ────────────────────────────────────────────────── */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track { background: var(--neu-bg); }
::-webkit-scrollbar-thumb {
background: var(--neu-border);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover { background: var(--neu-text-muted); }
/* ── Animations ─────────────────────────────────────────────────────────────── */
@keyframes neu-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@keyframes neu-spin {
to { transform: rotate(360deg); }
}
.neu-loading {
animation: neu-spin 1s linear infinite;
}
.neu-pulse {
animation: neu-pulse 2s ease-in-out infinite;
}
/* ── Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
.neu-grid {
grid-template-columns: 1fr;
}
:root {
--sidebar-width: 100%;
}
}
/* ── Layout Alpine (sidebar + navbar + page-content) ───────────────────────── */
:root {
--navbar-height: 56px;
}
/* Sidebar (position:fixed, hors flux) */
.sidebar {
width: var(--sidebar-width);
height: 100vh;
background: var(--neu-surface);
border-right: 1px solid var(--neu-border);
display: flex;
flex-direction: column;
transition: width 0.2s ease;
position: fixed;
top: 0;
left: 0;
z-index: var(--z-sidebar);
overflow: hidden;
}
.sidebar.collapsed {
width: var(--sidebar-width-collapsed);
}
.sidebar.collapsed .sidebar-link {
justify-content: center;
padding-left: 0;
padding-right: 0;
}
.sidebar-header {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem;
border-bottom: 1px solid var(--neu-border);
min-height: var(--navbar-height);
flex-shrink: 0;
cursor: pointer;
user-select: none;
}
.sidebar-logo {
font-size: 1.5rem;
color: var(--neu-primary);
flex-shrink: 0;
}
.sidebar-title {
font-weight: 700;
font-size: 1rem;
white-space: nowrap;
overflow: hidden;
color: var(--neu-text);
}
.sidebar-nav {
flex: 1;
padding: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
overflow-y: auto;
overflow-x: hidden;
}
.sidebar-link {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.625rem 0.75rem;
border-radius: var(--neu-radius-sm);
text-decoration: none;
color: var(--neu-text-muted);
font-size: 0.875rem;
font-weight: 500;
transition: all 0.15s;
white-space: nowrap;
overflow: hidden;
}
.sidebar-link:hover {
background: rgba(108, 142, 244, 0.08);
color: var(--neu-text);
}
.sidebar-link.active {
background: rgba(108, 142, 244, 0.15);
color: var(--neu-primary);
}
.sidebar-icon {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
flex-shrink: 0;
width: 1.25rem;
line-height: 1;
}
.sidebar-label {
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-footer {
padding: 0.75rem;
border-top: 1px solid var(--neu-border);
display: flex;
align-items: center;
gap: 0.5rem;
flex-shrink: 0;
}
.sidebar-user {
flex: 1;
font-size: 0.8rem;
color: var(--neu-text-muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Main layout (marge pour compenser le sidebar fixe) */
.main-layout {
display: flex;
flex-direction: column;
min-height: 100vh;
margin-left: var(--sidebar-width);
transition: margin-left 0.2s ease;
}
.sidebar.collapsed ~ .main-layout {
margin-left: var(--sidebar-width-collapsed);
}
/* Navbar */
.navbar {
height: var(--navbar-height);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.5rem;
border-bottom: 1px solid var(--neu-border);
background: var(--neu-bg);
flex-shrink: 0;
position: sticky;
top: 0;
z-index: var(--z-navbar);
}
.navbar-title {
font-size: 1rem;
font-weight: 700;
margin: 0;
color: var(--neu-text);
}
.navbar-actions {
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Page content */
.page-content {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
background: var(--neu-bg);
color: var(--neu-text);
}
/* Auth layout (login, install) */
.auth-layout {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
background: var(--neu-bg);
}
/* Swup fade transition */
.transition-fade {
transition: opacity 0.2s ease;
}
html.is-animating .transition-fade {
opacity: 0;
}
/* Responsive */
@media (max-width: 768px) {
.sidebar { width: var(--sidebar-width-collapsed); }
.main-layout { margin-left: var(--sidebar-width-collapsed); }
}
[x-cloak] { display: none !important; }
/* ── Sidebar droite ─────────────────────────────────────────────────────────── */
[data-sidebar="right"] .sidebar {
left: auto;
right: 0;
border-right: none;
border-left: 1px solid var(--neu-border);
}
[data-sidebar="right"] .main-layout {
margin-left: 0;
margin-right: var(--sidebar-width);
transition: margin-right 0.2s ease;
}
[data-sidebar="right"] .sidebar.collapsed ~ .main-layout {
margin-right: var(--sidebar-width-collapsed);
}
@media (max-width: 768px) {
[data-sidebar="right"] .main-layout {
margin-right: var(--sidebar-width-collapsed);
}
}
/* ── Couleurs icônes contextuelles ─────────────────────────────────────────── */
/* Navbar : logout, thème, édition */
.navbar .lnid-power-button { color: var(--neu-danger); }
.navbar .lnid-sun-1 { color: #f59e0b; }
.navbar .lnid-moon-half-left-1 { color: #60a5fa; }
/* Sidebar footer : utilisateur */
.sidebar-footer .sidebar-icon { color: var(--neu-primary); }