Système
@@ -656,7 +427,12 @@ $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/
Espace disque
-
+ 85 ? '#e05555' : ($diskPct > 70 ? '#ffc107' : '#4caf50');
+ ?>
+
= humanBytes($diskUsed) ?> utilisé (= $diskPct ?>%)
= humanBytes($diskFree) ?> libre / = humanBytes($diskTotal) ?>
@@ -780,56 +556,5 @@ $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/
-
diff --git a/public/assets/css/system.css b/public/assets/css/system.css
new file mode 100644
index 0000000..e9da731
--- /dev/null
+++ b/public/assets/css/system.css
@@ -0,0 +1,282 @@
+/* ── System page tabs ──────────────────────────────────────────────────── */
+.sys-tabs {
+ display: flex;
+ gap: 0;
+ border-bottom: 1px solid var(--admin-border);
+ margin-bottom: 1.75rem;
+}
+.sys-tab {
+ display: inline-block;
+ padding: .55rem 1.1rem;
+ font-size: .84rem;
+ font-weight: 500;
+ color: var(--admin-text-muted);
+ text-decoration: none;
+ border-bottom: 2px solid transparent;
+ margin-bottom: -1px;
+ transition: color .15s, border-color .15s;
+}
+.sys-tab:hover {
+ color: var(--admin-text);
+}
+.sys-tab.active {
+ color: var(--admin-purple);
+ border-bottom-color: var(--admin-purple);
+}
+
+/* ── Status cards ──────────────────────────────────────────────────────── */
+.srv-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 1rem;
+ margin-bottom: 2.5rem;
+}
+.srv-card {
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ border-radius: 5px;
+ padding: 1rem 1.25rem;
+}
+.srv-card__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: .4rem;
+}
+.srv-card__name {
+ font-size: .82rem;
+ text-transform: uppercase;
+ letter-spacing: .07em;
+ color: var(--admin-text-muted);
+ font-weight: 500;
+}
+.srv-card__detail {
+ font-size: .8rem;
+ color: var(--admin-text-muted);
+ margin-top: .25rem;
+ font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
+}
+.status-ok { color: #4caf50; font-weight: 600; font-size: .85rem; }
+.status-warn { color: #ffc107; font-weight: 600; font-size: .85rem; }
+.status-err { color: #e05555; font-weight: 600; font-size: .85rem; }
+.status-unknown { color: #888; font-weight: 600; font-size: .85rem; }
+
+.srv-section-title {
+ font-size: .82rem;
+ text-transform: uppercase;
+ letter-spacing: .1em;
+ color: var(--admin-text-muted);
+ border-bottom: 1px solid var(--admin-border);
+ padding-bottom: .4rem;
+ margin: 0 0 1rem;
+ font-weight: 500;
+}
+
+/* ── PHP info grid ─────────────────────────────────────────────────────── */
+.php-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+ gap: .5rem .75rem;
+ margin-bottom: 2.5rem;
+}
+.php-item {
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ border-radius: 4px;
+ padding: .5rem .75rem;
+}
+.php-item__key {
+ font-size: .75rem;
+ text-transform: uppercase;
+ letter-spacing: .06em;
+ color: var(--admin-text-muted);
+}
+.php-item__val {
+ font-size: .92rem;
+ font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
+ color: var(--admin-text);
+ margin-top: .15rem;
+}
+
+/* ── Disk bar ──────────────────────────────────────────────────────────── */
+.disk-bar-wrap {
+ background: var(--admin-border);
+ border-radius: 3px;
+ height: 6px;
+ margin-top: .5rem;
+ overflow: hidden;
+}
+.disk-bar {
+ height: 100%;
+ border-radius: 3px;
+ /* width and background-color are set via inline style using --disk-pct and --disk-color */
+ width: var(--disk-pct, 0%);
+ background: var(--disk-color, #4caf50);
+ transition: width .3s;
+}
+.disk-stats {
+ display: flex;
+ justify-content: space-between;
+ font-size: .78rem;
+ color: var(--admin-text-muted);
+ margin-top: .25rem;
+}
+
+/* ── Log viewer ────────────────────────────────────────────────────────── */
+.log-toolbar {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: .6rem;
+ margin-bottom: 1.25rem;
+}
+.log-toolbar select {
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ color: var(--admin-text);
+ border-radius: 4px;
+ padding: .4rem .7rem;
+ font-size: .85rem;
+ font-family: inherit;
+}
+.log-toolbar select:focus { outline: 2px solid var(--admin-purple); }
+
+.log-meta {
+ font-size: .78rem;
+ color: var(--admin-text-muted);
+ font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
+ margin-bottom: .75rem;
+ display: flex;
+ gap: 1.5rem;
+ flex-wrap: wrap;
+}
+.log-meta span::before { content: attr(data-label) ": "; opacity: .6; }
+
+.log-unavailable {
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ border-radius: 4px;
+ padding: 1.5rem;
+ color: var(--admin-text-muted);
+ font-size: .88rem;
+}
+.log-unavail-path {
+ font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
+ font-size: .8rem;
+ margin-top: .4rem;
+ opacity: .7;
+}
+.log-unavail-dev {
+ margin-top: .6rem;
+ font-size: .8rem;
+ opacity: .7;
+}
+.log-empty {
+ color: var(--admin-text-muted);
+ font-size: .88rem;
+ padding: 1rem 0;
+}
+.log-output {
+ background: #0d0d0d;
+ border: 1px solid var(--admin-border);
+ border-radius: 4px;
+ padding: 1rem;
+ overflow-x: auto;
+ font-family: ui-monospace, "SFMono-Regular", Consolas, "Courier New", monospace;
+ font-size: .76rem;
+ line-height: 1.55;
+ max-height: 62vh;
+ overflow-y: auto;
+ position: relative;
+}
+.log-line {
+ display: block;
+ white-space: pre;
+ padding: .05rem .1rem;
+ border-radius: 2px;
+ color: #bbb;
+}
+.log-line + .log-line { border-top: 1px solid rgba(255,255,255,.03); }
+.log-crit { color: #ff7070; background: rgba(200,0,0,.12); }
+.log-error { color: #f08080; }
+.log-warn { color: #ffd080; }
+.log-notice { color: #a0c8ff; }
+.log-line::before {
+ content: attr(data-n);
+ display: inline-block;
+ min-width: 4ch;
+ margin-right: .75rem;
+ opacity: .3;
+ text-align: right;
+ user-select: none;
+}
+.log-count-badge {
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ border-radius: 3px;
+ font-size: .76rem;
+ padding: .15rem .5rem;
+ color: var(--admin-text-muted);
+ font-family: ui-monospace, monospace;
+}
+.log-copy-btn {
+ position: absolute;
+ top: .6rem;
+ right: .6rem;
+ background: var(--admin-bg-alt);
+ border: 1px solid var(--admin-border);
+ color: var(--admin-text-muted);
+ border-radius: 4px;
+ font-size: .76rem;
+ padding: .25rem .6rem;
+ cursor: pointer;
+ font-family: inherit;
+ transition: color .15s, border-color .15s;
+ z-index: 2;
+}
+.log-copy-btn:hover {
+ color: var(--admin-text);
+ border-color: var(--admin-purple);
+}
+.log-copy-btn.copied {
+ color: #4caf50;
+ border-color: #4caf50;
+}
+
+.sys-refresh-note {
+ font-size: .78rem;
+ color: var(--admin-text-muted);
+ margin-bottom: 1.25rem;
+}
+.sys-refresh-note a {
+ color: var(--admin-purple);
+ text-decoration: none;
+}
+.sys-refresh-note a:hover { text-decoration: underline; }
+
+/* ── Nginx config viewer ───────────────────────────────────────────────── */
+.nginx-source-badge {
+ display: inline-block;
+ font-size: .72rem;
+ font-family: ui-monospace, monospace;
+ padding: .15rem .55rem;
+ border-radius: 3px;
+ margin-left: .6rem;
+ vertical-align: middle;
+}
+.nginx-source-badge--live {
+ background: rgba(76,175,80,.15);
+ color: #4caf50;
+ border: 1px solid rgba(76,175,80,.35);
+}
+.nginx-source-badge--local {
+ background: rgba(255,193,7,.12);
+ color: #ffc107;
+ border: 1px solid rgba(255,193,7,.35);
+}
+/* Nginx syntax highlight layers inside .log-output */
+.nginx-comment { color: #666; font-style: italic; }
+.nginx-directive { color: #7eb8f7; }
+.nginx-block { color: #d4a0ff; font-weight: 600; }
+.nginx-value { color: #e2c08d; }
+.nginx-location { color: #79dac8; }