Files
nano_metrics/.superpowers/brainstorm/599687-1779425985/content/layout-v4.html
T
Gilles Soulier a0f47bf966 feat: add plans, design system, CONSIGNE and brainstorm assets
Ajoute les trois plans d'implémentation (agent Rust, serveur Go, dashboard),
les consignes de design, les fichiers de brainstorming et le .gitignore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:13:53 +02:00

542 lines
33 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nanometrics — Layout v4</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Share+Tech+Mono:wght@400&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<script src="/helper.js"></script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root[data-theme="dark"] {
--accent:#fe8019; --accent-soft:#d65d0e; --accent-glow:rgba(254,128,25,0.3);
--bg-0:#1d1813; --bg-1:#2a231d; --bg-2:#32291f; --bg-3:#3c332a; --bg-4:#4a3f33; --bg-5:#57493c;
--ink-1:#f2e5c7; --ink-2:#d5c4a1; --ink-3:#a89984; --ink-4:#7c6f64;
--ok:#4dbb26; --warn:#fabd2f; --err:#fb4934; --info:#83a598; --blue:#3db0d1; --purple:#c882c8;
--border-1:rgba(255,255,255,0.06); --border-2:rgba(255,255,255,0.12); --border-3:rgba(255,255,255,0.22);
--tile-3d:0 1px 0 rgba(255,255,255,0.08) inset,0 -1px 0 rgba(0,0,0,0.3) inset,0 4px 16px rgba(0,0,0,0.5);
--font-ui:'Inter',system-ui,sans-serif; --font-mono:'JetBrains Mono',monospace; --font-terminal:'Share Tech Mono',monospace;
}
:root[data-theme="light"] {
--accent:#af3a03; --accent-soft:#d65d0e; --accent-glow:rgba(175,58,3,0.2);
--bg-0:#d5c4a1; --bg-1:#ebdbb2; --bg-2:#d5c4a1; --bg-3:#bdae93; --bg-4:#a89984; --bg-5:#928374;
--ink-1:#3c3836; --ink-2:#504945; --ink-3:#665c54; --ink-4:#7c6f64;
--ok:#3c911c; --warn:#b57614; --err:#9d0006; --blue:#2d82a3; --purple:#8c468c;
--border-1:rgba(0,0,0,0.08); --border-2:rgba(0,0,0,0.15); --border-3:rgba(0,0,0,0.25);
--tile-3d:0 1px 0 rgba(255,255,255,0.5) inset,0 -1px 0 rgba(0,0,0,0.1) inset,0 4px 16px rgba(0,0,0,0.12);
--font-ui:'Inter',system-ui,sans-serif; --font-mono:'JetBrains Mono',monospace; --font-terminal:'Share Tech Mono',monospace;
}
body { background:var(--bg-1); color:var(--ink-1); font-family:var(--font-ui); font-size:13px; height:100vh; display:flex; flex-direction:column; overflow:hidden; transition:background .2s,color .2s; }
/* HEADER */
.header { background:var(--bg-2); border-bottom:1px solid var(--border-2); padding:0 20px; height:48px; display:flex; align-items:center; gap:14px; flex-shrink:0; }
.logo { display:flex; align-items:center; gap:8px; }
.logo-led { width:9px; height:9px; border-radius:50%; background:var(--accent); box-shadow:0 0 8px var(--accent-glow); animation:blink 2s infinite; }
@keyframes blink{0%,100%{opacity:1}50%{opacity:.4}}
.logo-name { font-weight:700; font-size:14px; letter-spacing:.05em; font-family:var(--font-terminal); }
.logo-ver { font-size:10px; color:var(--ink-4); font-family:var(--font-terminal); }
.h-sep { width:1px; height:24px; background:var(--border-2); }
.h-spacer { flex:1; }
.h-stats { display:flex; gap:14px; }
.h-stat { display:flex; align-items:center; gap:5px; }
.h-stat .lbl { font-size:9px; color:var(--ink-4); font-family:var(--font-terminal); letter-spacing:.06em; }
.h-stat .val { font-family:var(--font-mono); font-weight:700; font-size:13px; }
.c-ok{color:var(--ok)}.c-warn{color:var(--warn)}.c-err{color:var(--err)}.c-n{color:var(--ink-2)}
.hbtn { width:34px; height:34px; border-radius:8px; border:1px solid var(--border-2); background:var(--bg-3); color:var(--ink-2); font-size:14px; display:flex; align-items:center; justify-content:center; cursor:pointer; position:relative; transition:background .12s,color .12s; }
.hbtn:hover { background:var(--bg-4); color:var(--accent); }
.hbtn .tip { position:absolute; top:calc(100%+6px); right:0; z-index:50; background:var(--bg-0); color:var(--ink-1); font-size:11px; padding:4px 8px; border-radius:5px; border:1px solid var(--border-2); white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .12s; font-family:var(--font-ui); }
.hbtn:hover .tip { opacity:1; }
/* GRID */
.main { flex:1; padding:14px 16px; overflow-y:auto; }
.agents-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:10px; }
/* TILE */
.tile { background:var(--bg-3); border-radius:10px; padding:12px 14px; border:1px solid var(--border-1); box-shadow:var(--tile-3d); cursor:pointer; transition:border-color .15s; display:flex; flex-direction:column; gap:9px; }
.tile:hover { border-color:var(--border-3); }
.tile.t-warn { border-color:rgba(250,189,47,.28); }
.tile.t-err { border-color:rgba(251,73,52,.32); box-shadow:var(--tile-3d),0 0 16px rgba(251,73,52,.1); }
.tile.t-off { opacity:.5; cursor:default; }
.tile-head { display:flex; align-items:center; gap:8px; }
.t-icon { width:28px; height:28px; border-radius:7px; background:var(--bg-4); display:flex; align-items:center; justify-content:center; color:var(--accent); font-size:13px; flex-shrink:0; overflow:hidden; }
.t-icon img { width:100%; height:100%; object-fit:cover; border-radius:7px; }
.t-names { flex:1; min-width:0; }
.t-host { font-weight:600; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.t-ip { font-family:var(--font-mono); font-size:10px; color:var(--ink-4); }
.t-led { width:8px; height:8px; border-radius:50%; flex-shrink:0; }
.s-ok{background:var(--ok);box-shadow:0 0 6px var(--ok)}.s-warn{background:var(--warn);box-shadow:0 0 6px var(--warn);animation:blink 1.5s infinite}.s-err{background:var(--err);box-shadow:0 0 8px var(--err);animation:blink 1s infinite}.s-off{background:var(--ink-4)}
.tile-gauges { display:flex; flex-direction:column; gap:5px; }
.g-row { display:flex; align-items:center; gap:7px; }
.g-ico { width:18px; height:18px; display:flex; align-items:center; justify-content:center; font-size:11px; color:var(--ink-3); flex-shrink:0; position:relative; cursor:help; }
.g-ico .g-tip { position:absolute; bottom:calc(100%+5px); left:50%; transform:translateX(-50%); background:var(--bg-0); color:var(--ink-1); font-size:10px; padding:3px 7px; border-radius:4px; border:1px solid var(--border-2); white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .12s; z-index:10; font-family:var(--font-ui); }
.g-ico:hover .g-tip { opacity:1; }
.g-bar { flex:1; height:5px; border-radius:3px; background:var(--bg-1); overflow:hidden; }
.g-fill { height:100%; border-radius:3px; background:var(--ok); transition:width .4s; }
.g-fill.w{background:var(--warn)}.g-fill.e{background:var(--err)}
.g-val { font-family:var(--font-mono); font-size:11px; color:var(--ink-2); width:34px; text-align:right; flex-shrink:0; }
.tile-foot { font-family:var(--font-terminal); font-size:10px; color:var(--ink-4); display:flex; align-items:center; gap:5px; }
.tile-foot i { font-size:9px; }
.tile-foot.offline { color:var(--err); }
/* FOOTER */
.footer { background:var(--bg-0); border-top:1px solid var(--border-2); height:26px; display:flex; align-items:center; font-family:var(--font-terminal); font-size:11px; color:var(--ink-4); flex-shrink:0; }
.f-mode { background:var(--accent); color:var(--bg-0); padding:0 12px; height:100%; display:flex; align-items:center; font-weight:700; letter-spacing:.04em; }
.f-cell { padding:0 12px; border-right:1px solid var(--border-1); display:flex; align-items:center; gap:5px; height:100%; }
.f-val { font-family:var(--font-mono); color:var(--ink-2); }
.f-val.w { color:var(--warn); }
.f-minibar { width:36px; height:4px; border-radius:2px; background:var(--bg-3); overflow:hidden; }
.f-minifill { height:100%; border-radius:2px; background:var(--ok); }
.f-minifill.w { background:var(--warn); }
.f-spacer { flex:1; }
.f-right { padding:0 12px; display:flex; align-items:center; gap:6px; color:var(--ink-3); }
.f-time { font-family:var(--font-mono); color:var(--ink-2); }
/* ══ POPUP ══ */
.overlay { position:fixed; inset:0; background:rgba(0,0,0,.65); z-index:100; display:flex; align-items:center; justify-content:center; backdrop-filter:blur(2px); }
.popup { background:var(--bg-2); border:1px solid var(--border-3); border-radius:12px; width:540px; max-width:96vw; max-height:92vh; box-shadow:0 24px 64px rgba(0,0,0,.7); display:flex; flex-direction:column; overflow:hidden; }
/* popup header */
.pop-head { background:var(--bg-3); padding:14px 18px; border-bottom:1px solid var(--border-2); display:flex; align-items:center; gap:12px; }
/* agent icon — cliquable pour upload */
.agent-icon-wrap {
position:relative; width:44px; height:44px; border-radius:10px; flex-shrink:0;
cursor:pointer; overflow:hidden;
background:var(--bg-4); display:flex; align-items:center; justify-content:center;
color:var(--accent); font-size:18px;
border:2px solid var(--border-2); transition:border-color .15s;
}
.agent-icon-wrap:hover { border-color:var(--accent); }
.agent-icon-wrap img { width:100%; height:100%; object-fit:cover; }
.agent-icon-overlay {
position:absolute; inset:0; background:rgba(0,0,0,.6);
display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
opacity:0; transition:opacity .15s;
font-size:10px; color:#fff; font-family:var(--font-ui);
}
.agent-icon-overlay i { font-size:14px; }
.agent-icon-wrap:hover .agent-icon-overlay { opacity:1; }
#icon-upload { display:none; }
.pop-head-info { flex:1; }
.pop-host { font-weight:700; font-size:15px; }
.pop-ip { font-family:var(--font-mono); font-size:11px; color:var(--ink-4); }
.pop-led { width:10px; height:10px; border-radius:50%; background:var(--ok); box-shadow:0 0 8px var(--ok); flex-shrink:0; }
.pop-close { width:28px; height:28px; border-radius:6px; background:var(--bg-5); color:var(--ink-3); display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:12px; transition:background .12s,color .12s; }
.pop-close:hover { background:var(--err); color:#fff; }
/* upload feedback */
.upload-hint { font-size:10px; color:var(--ink-4); font-family:var(--font-terminal); margin-top:3px; }
/* popup body */
.pop-body { padding:16px 18px; display:flex; flex-direction:column; gap:14px; overflow-y:auto; }
.sec-title { font-size:9px; color:var(--ink-4); font-family:var(--font-terminal); letter-spacing:.08em; margin-bottom:8px; }
/* KPI row */
.kpi-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:7px; }
.kpi { background:var(--bg-3); border-radius:8px; padding:10px 12px; border:1px solid var(--border-1); box-shadow:var(--tile-3d); }
.kpi-lbl { font-size:9px; color:var(--ink-4); font-family:var(--font-terminal); letter-spacing:.06em; }
.kpi-val { font-family:var(--font-mono); font-size:20px; font-weight:700; line-height:1.1; margin-top:2px; }
.kpi-val .u { font-size:10px; color:var(--ink-3); font-weight:400; }
.kpi-sub { font-size:10px; color:var(--ink-4); font-family:var(--font-mono); margin-top:2px; }
/* ── COURBES HISTORIQUES ── */
.charts-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.chart-card { background:var(--bg-3); border-radius:8px; padding:10px 12px; border:1px solid var(--border-1); box-shadow:var(--tile-3d); }
.chart-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; }
.chart-label { display:flex; align-items:center; gap:6px; font-size:10px; font-family:var(--font-terminal); letter-spacing:.06em; color:var(--ink-3); }
.chart-label i { font-size:11px; }
.chart-cur { font-family:var(--font-mono); font-size:16px; font-weight:700; }
.chart-svg { width:100%; height:56px; display:block; }
.chart-axis { display:flex; justify-content:space-between; margin-top:3px; font-family:var(--font-terminal); font-size:9px; color:var(--ink-4); }
/* disk jauge conservée */
.det-gauges { display:flex; flex-direction:column; gap:7px; }
.dg-row { display:flex; align-items:center; gap:10px; }
.dg-ico { width:22px; text-align:center; font-size:13px; position:relative; cursor:help; }
.dg-ico .dg-tip { position:absolute; bottom:calc(100%+5px); left:50%; transform:translateX(-50%); background:var(--bg-0); color:var(--ink-1); font-size:10px; padding:3px 8px; border-radius:4px; border:1px solid var(--border-2); white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .1s; z-index:10; font-family:var(--font-ui); }
.dg-ico:hover .dg-tip { opacity:1; }
.dg-bar { flex:1; height:7px; border-radius:4px; background:var(--bg-1); overflow:hidden; }
.dg-fill { height:100%; border-radius:4px; background:var(--ok); }
.dg-fill.w{background:var(--warn)}.dg-fill.e{background:var(--err)}
.dg-val { font-family:var(--font-mono); font-size:12px; color:var(--ink-2); width:90px; text-align:right; }
/* meta */
.meta-grid { display:grid; grid-template-columns:1fr 1fr; gap:6px; }
.meta { background:var(--bg-3); border-radius:6px; padding:8px 10px; border:1px solid var(--border-1); }
.meta-lbl { font-size:9px; color:var(--ink-4); font-family:var(--font-terminal); letter-spacing:.06em; }
.meta-val { font-family:var(--font-mono); font-size:12px; color:var(--ink-2); margin-top:2px; }
/* popup footer — pas de bouton Fermer */
.pop-foot { padding:10px 18px; border-top:1px solid var(--border-2); background:var(--bg-3); display:flex; align-items:center; gap:8px; }
.pop-uptime { font-family:var(--font-terminal); font-size:11px; color:var(--ink-4); flex:1; }
.btn { padding:6px 14px; border-radius:8px; border:1px solid var(--border-2); background:var(--bg-4); color:var(--ink-2); font-size:12px; font-family:var(--font-ui); cursor:pointer; display:flex; align-items:center; gap:6px; transition:background .1s; }
.btn:hover { background:var(--bg-5); }
.btn.primary { background:var(--accent); color:var(--bg-0); border-color:var(--accent-soft); font-weight:600; }
.btn.primary:hover { background:var(--accent-soft); }
/* scrollbar */
::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:var(--bg-1)}::-webkit-scrollbar-thumb{background:var(--bg-4);border-radius:3px}
</style>
</head>
<body>
<!-- HEADER -->
<div class="header">
<div class="logo">
<div class="logo-led"></div>
<span class="logo-name">NANOMETRICS</span>
<span class="logo-ver">v1.0</span>
</div>
<div class="h-sep"></div>
<div class="h-stats">
<div class="h-stat"><span class="lbl">AGENTS</span><span class="val c-n">8</span></div>
<div class="h-stat"><span class="lbl">OK</span><span class="val c-ok">5</span></div>
<div class="h-stat"><span class="lbl">WARN</span><span class="val c-warn">2</span></div>
<div class="h-stat"><span class="lbl">ERR</span><span class="val c-err">1</span></div>
</div>
<div class="h-spacer"></div>
<div class="hbtn" onclick="toggleTheme()">
<i class="fa-solid fa-moon" id="theme-icon"></i>
<span class="tip">Thème clair / sombre</span>
</div>
<div class="hbtn" onclick="alert('Config panel')">
<i class="fa-solid fa-sliders"></i>
<span class="tip">Configuration interface</span>
</div>
</div>
<!-- GRID -->
<div class="main">
<div class="agents-grid">
<div class="tile" onclick="showPopup()">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-server"></i></div>
<div class="t-names"><div class="t-host">srv-prod-01</div><div class="t-ip">10.0.0.11</div></div>
<div class="t-led s-ok"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i><span class="g-tip">Processeur (CPU)</span></div><div class="g-bar"><div class="g-fill" style="width:42%"></div></div><span class="g-val">42%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">Mémoire RAM</span></div><div class="g-bar"><div class="g-fill" style="width:58%"></div></div><span class="g-val">58%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Espace disque</span></div><div class="g-bar"><div class="g-fill" style="width:31%"></div></div><span class="g-val">31%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>14j 6h</div>
</div>
<div class="tile t-warn">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-server"></i></div>
<div class="t-names"><div class="t-host">srv-backup-02</div><div class="t-ip">10.0.0.12</div></div>
<div class="t-led s-warn"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico" style="color:var(--warn)"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU — élevé</span></div><div class="g-bar"><div class="g-fill w" style="width:78%"></div></div><span class="g-val" style="color:var(--warn)">78%</span></div>
<div class="g-row"><div class="g-ico" style="color:var(--warn)"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM — élevée</span></div><div class="g-bar"><div class="g-fill w" style="width:72%"></div></div><span class="g-val" style="color:var(--warn)">72%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Espace disque</span></div><div class="g-bar"><div class="g-fill" style="width:20%"></div></div><span class="g-val">20%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>3j 14h</div>
</div>
<div class="tile t-err">
<div class="tile-head">
<div class="t-icon" style="color:var(--err)"><i class="fa-solid fa-microchip"></i></div>
<div class="t-names"><div class="t-host">rpi-sensor-03</div><div class="t-ip">10.0.0.23</div></div>
<div class="t-led s-err"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU</span></div><div class="g-bar"><div class="g-fill" style="width:12%"></div></div><span class="g-val">12%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM</span></div><div class="g-bar"><div class="g-fill" style="width:38%"></div></div><span class="g-val">38%</span></div>
<div class="g-row"><div class="g-ico" style="color:var(--err)"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Disque critique !</span></div><div class="g-bar"><div class="g-fill e" style="width:94%"></div></div><span class="g-val" style="color:var(--err)">94%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>62j 1h</div>
</div>
<div class="tile">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-hard-drive"></i></div>
<div class="t-names"><div class="t-host">nas-storage-04</div><div class="t-ip">10.0.0.30</div></div>
<div class="t-led s-ok"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU</span></div><div class="g-bar"><div class="g-fill" style="width:8%"></div></div><span class="g-val">8%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM</span></div><div class="g-bar"><div class="g-fill" style="width:45%"></div></div><span class="g-val">45%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Disque</span></div><div class="g-bar"><div class="g-fill" style="width:66%"></div></div><span class="g-val">66%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>128j 3h</div>
</div>
<div class="tile">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-database"></i></div>
<div class="t-names"><div class="t-host">db-primary-05</div><div class="t-ip">10.0.0.40</div></div>
<div class="t-led s-ok"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU</span></div><div class="g-bar"><div class="g-fill" style="width:25%"></div></div><span class="g-val">25%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM</span></div><div class="g-bar"><div class="g-fill" style="width:61%"></div></div><span class="g-val">61%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Disque</span></div><div class="g-bar"><div class="g-fill" style="width:48%"></div></div><span class="g-val">48%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>7j 22h</div>
</div>
<div class="tile t-warn">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-globe"></i></div>
<div class="t-names"><div class="t-host">web-front-06</div><div class="t-ip">10.0.0.51</div></div>
<div class="t-led s-warn"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico" style="color:var(--warn)"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU — élevé</span></div><div class="g-bar"><div class="g-fill w" style="width:71%"></div></div><span class="g-val" style="color:var(--warn)">71%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM</span></div><div class="g-bar"><div class="g-fill" style="width:55%"></div></div><span class="g-val">55%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Disque</span></div><div class="g-bar"><div class="g-fill" style="width:28%"></div></div><span class="g-val">28%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>21j 8h</div>
</div>
<div class="tile t-off">
<div class="tile-head">
<div class="t-icon" style="color:var(--ink-4)"><i class="fa-solid fa-server"></i></div>
<div class="t-names"><div class="t-host">srv-dev-07</div><div class="t-ip">10.0.0.60</div></div>
<div class="t-led s-off"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i></div><div class="g-bar"></div><span class="g-val" style="color:var(--ink-4)"></span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i></div><div class="g-bar"></div><span class="g-val" style="color:var(--ink-4)"></span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i></div><div class="g-bar"></div><span class="g-val" style="color:var(--ink-4)"></span></div>
</div>
<div class="tile-foot offline"><i class="fa-solid fa-circle-xmark"></i>Hors ligne · vu il y a 2h</div>
</div>
<div class="tile">
<div class="tile-head">
<div class="t-icon"><i class="fa-solid fa-network-wired"></i></div>
<div class="t-names"><div class="t-host">gateway-08</div><div class="t-ip">10.0.0.1</div></div>
<div class="t-led s-ok"></div>
</div>
<div class="tile-gauges">
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-microchip"></i><span class="g-tip">CPU</span></div><div class="g-bar"><div class="g-fill" style="width:5%"></div></div><span class="g-val">5%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-memory"></i><span class="g-tip">RAM</span></div><div class="g-bar"><div class="g-fill" style="width:22%"></div></div><span class="g-val">22%</span></div>
<div class="g-row"><div class="g-ico"><i class="fa-solid fa-hard-drive"></i><span class="g-tip">Disque</span></div><div class="g-bar"><div class="g-fill" style="width:15%"></div></div><span class="g-val">15%</span></div>
</div>
<div class="tile-foot"><i class="fa-solid fa-clock"></i>365j 0h</div>
</div>
</div>
</div>
<!-- FOOTER -->
<div class="footer">
<div class="f-mode">LIVE</div>
<div class="f-cell"><i class="fa-solid fa-server" style="font-size:10px"></i><span>SERVEUR</span></div>
<div class="f-cell"><i class="fa-solid fa-microchip" style="font-size:10px"></i><span class="f-val">18%</span><div class="f-minibar"><div class="f-minifill" style="width:18%"></div></div></div>
<div class="f-cell"><i class="fa-solid fa-memory" style="font-size:10px"></i><span class="f-val w">71%</span><div class="f-minibar"><div class="f-minifill w" style="width:71%"></div></div></div>
<div class="f-spacer"></div>
<div class="f-right"><i class="fa-solid fa-rotate"></i><span>Actualisation : <span class="f-time">22:14:07</span></span></div>
</div>
<!-- ══ POPUP ══ -->
<div class="overlay" id="popup-overlay" style="display:flex" onclick="if(event.target===this)this.style.display='none'">
<div class="popup" onclick="event.stopPropagation()">
<!-- HEADER POPUP -->
<div class="pop-head">
<!-- Icône agent — cliquer pour uploader -->
<div class="agent-icon-wrap" onclick="document.getElementById('icon-upload').click()" title="Changer l'icône">
<i class="fa-solid fa-server" id="agent-icon-fa"></i>
<img id="agent-icon-img" src="" style="display:none">
<div class="agent-icon-overlay">
<i class="fa-solid fa-camera"></i>
<span>Changer</span>
</div>
</div>
<input type="file" id="icon-upload" accept=".svg,.jpg,.jpeg,.png,.webp" onchange="handleIconUpload(event)">
<div class="pop-head-info">
<div class="pop-host">srv-prod-01</div>
<div class="pop-ip">10.0.0.11</div>
<div class="upload-hint" id="upload-hint">Cliquer sur l'icône pour personnaliser · SVG, JPG, PNG, WEBP · max 128×128 px</div>
</div>
<div class="pop-led"></div>
<div class="pop-close" onclick="document.getElementById('popup-overlay').style.display='none'">
<i class="fa-solid fa-xmark"></i>
</div>
</div>
<!-- BODY -->
<div class="pop-body">
<!-- KPIs actuels -->
<div>
<div class="sec-title">MÉTRIQUES ACTUELLES</div>
<div class="kpi-grid">
<div class="kpi"><div class="kpi-lbl">CPU</div><div class="kpi-val c-ok">42<span class="u">%</span></div><div class="kpi-sub">4 cœurs</div></div>
<div class="kpi"><div class="kpi-lbl">MÉMOIRE</div><div class="kpi-val">3.7<span class="u">Go</span></div><div class="kpi-sub">/ 8 Go · 46%</div></div>
<div class="kpi"><div class="kpi-lbl">DISQUE</div><div class="kpi-val">62<span class="u">Go</span></div><div class="kpi-sub">/ 200 Go · 31%</div></div>
<div class="kpi"><div class="kpi-lbl">UPTIME</div><div class="kpi-val" style="font-size:15px;color:var(--ink-1)">14j 6h</div><div class="kpi-sub">depuis boot</div></div>
</div>
</div>
<!-- COURBES HISTORIQUES CPU + RAM -->
<div>
<div class="sec-title">HISTORIQUE — 30 DERNIÈRES MINUTES</div>
<div class="charts-grid">
<!-- CPU chart -->
<div class="chart-card">
<div class="chart-header">
<div class="chart-label" style="color:var(--accent)"><i class="fa-solid fa-microchip"></i>CPU</div>
<span class="chart-cur c-ok">42%</span>
</div>
<svg class="chart-svg" viewBox="0 0 200 56" preserveAspectRatio="none" id="cpu-chart"></svg>
<div class="chart-axis"><span>-30min</span><span>-15min</span><span>maintenant</span></div>
</div>
<!-- RAM chart -->
<div class="chart-card">
<div class="chart-header">
<div class="chart-label" style="color:var(--blue)"><i class="fa-solid fa-memory"></i>RAM</div>
<span class="chart-cur" style="color:var(--blue)">46%</span>
</div>
<svg class="chart-svg" viewBox="0 0 200 56" preserveAspectRatio="none" id="ram-chart"></svg>
<div class="chart-axis"><span>-30min</span><span>-15min</span><span>maintenant</span></div>
</div>
</div>
</div>
<!-- DISQUE — jauge barre conservée (pas de série temporelle pertinente) -->
<div>
<div class="sec-title">STOCKAGE</div>
<div class="det-gauges">
<div class="dg-row">
<div class="dg-ico"><i class="fa-solid fa-hard-drive"></i><span class="dg-tip">Disque utilisé</span></div>
<div class="dg-bar"><div class="dg-fill" style="width:31%"></div></div>
<span class="dg-val">62 / 200 Go</span>
</div>
<div class="dg-row">
<div class="dg-ico" style="color:var(--blue)"><i class="fa-solid fa-floppy-disk"></i><span class="dg-tip">Espace libre</span></div>
<div class="dg-bar"><div class="dg-fill" style="width:69%;background:var(--blue)"></div></div>
<span class="dg-val">138 Go libre</span>
</div>
</div>
</div>
<!-- INFOS -->
<div>
<div class="sec-title">INFORMATIONS</div>
<div class="meta-grid">
<div class="meta"><div class="meta-lbl">HOSTNAME</div><div class="meta-val">srv-prod-01</div></div>
<div class="meta"><div class="meta-lbl">ADRESSE IP</div><div class="meta-val">10.0.0.11</div></div>
<div class="meta"><div class="meta-lbl">DERNIER CONTACT</div><div class="meta-val">22:14:07</div></div>
<div class="meta"><div class="meta-lbl">FRÉQUENCE</div><div class="meta-val">CPU 2s · Disk 60s</div></div>
</div>
</div>
</div>
<!-- FOOTER popup — pas de bouton Fermer -->
<div class="pop-foot">
<span class="pop-uptime"><i class="fa-solid fa-clock" style="margin-right:4px"></i>En ligne depuis 14 jours 6 heures</span>
<button class="btn"><i class="fa-solid fa-chart-line"></i> Historique complet</button>
</div>
</div>
</div>
<script>
/* ── thème ── */
function toggleTheme() {
const h = document.documentElement;
const i = document.getElementById('theme-icon');
h.dataset.theme = h.dataset.theme === 'dark' ? 'light' : 'dark';
i.className = h.dataset.theme === 'dark' ? 'fa-solid fa-moon' : 'fa-solid fa-sun';
drawCharts();
}
/* ── upload icône ── */
function handleIconUpload(e) {
const file = e.target.files[0];
if (!file) return;
const allowed = ['image/svg+xml','image/jpeg','image/png','image/webp'];
if (!allowed.includes(file.type)) { alert('Format non supporté'); return; }
const reader = new FileReader();
reader.onload = function(ev) {
if (file.type === 'image/svg+xml') {
// SVG : afficher directement
showAgentIcon(ev.target.result, true);
} else {
// Raster : redimensionner canvas max 128×128 en respectant le ratio
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
const ratio = Math.min(128 / img.width, 128 / img.height, 1);
canvas.width = Math.round(img.width * ratio);
canvas.height = Math.round(img.height * ratio);
canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
showAgentIcon(canvas.toDataURL(file.type === 'image/png' ? 'image/png' : 'image/jpeg', 0.9), false);
};
img.src = ev.target.result;
}
document.getElementById('upload-hint').textContent = '✓ Icône mise à jour — sauvegardée sur le serveur';
document.getElementById('upload-hint').style.color = 'var(--ok)';
};
reader.readAsDataURL(file);
}
function showAgentIcon(src, isSvg) {
document.getElementById('agent-icon-fa').style.display = 'none';
const img = document.getElementById('agent-icon-img');
img.src = src;
img.style.display = 'block';
}
/* ── courbes historiques ── */
function makeCurve(pts, color, fillColor, w, h) {
if (!pts.length) return '';
const maxV = 100, minV = 0;
const xs = pts.map((_, i) => (i / (pts.length - 1)) * w);
const ys = pts.map(v => h - ((v - minV) / (maxV - minV)) * (h - 4) - 2);
// zone de seuil warn (70%) — ligne pointillée
const warnY = h - ((70 - minV) / (maxV - minV)) * (h - 4) - 2;
let d = `M ${xs[0]} ${ys[0]}`;
for (let i = 1; i < pts.length; i++) {
const cx = (xs[i-1] + xs[i]) / 2;
d += ` C ${cx} ${ys[i-1]}, ${cx} ${ys[i]}, ${xs[i]} ${ys[i]}`;
}
const fillD = d + ` L ${xs[xs.length-1]} ${h} L ${xs[0]} ${h} Z`;
return `
<defs>
<linearGradient id="grad-${color.replace('#','')}" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="${fillColor}" stop-opacity="0.35"/>
<stop offset="100%" stop-color="${fillColor}" stop-opacity="0.02"/>
</linearGradient>
</defs>
<line x1="0" y1="${warnY}" x2="${w}" y2="${warnY}"
stroke="var(--warn)" stroke-width="0.8" stroke-dasharray="3,3" opacity="0.5"/>
<path d="${fillD}" fill="url(#grad-${color.replace('#','')})" />
<path d="${d}" fill="none" stroke="${color}" stroke-width="1.5" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="${xs[xs.length-1]}" cy="${ys[ys.length-1]}" r="2.5" fill="${color}"/>
`;
}
function drawCharts() {
const cpuPts = [38,41,35,40,44,42,39,45,50,48,43,42,44,41,40,43,47,45,42,44,41,43,42,40,43,41,44,43,41,42];
const ramPts = [44,44,45,45,46,46,47,47,46,46,45,46,46,47,47,46,46,45,46,46,46,46,46,46,46,46,46,46,46,46];
const accent = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
const blue = getComputedStyle(document.documentElement).getPropertyValue('--blue').trim();
document.getElementById('cpu-chart').innerHTML = makeCurve(cpuPts, accent, accent, 200, 56);
document.getElementById('ram-chart').innerHTML = makeCurve(ramPts, blue, blue, 200, 56);
}
window.addEventListener('load', drawCharts);
function showPopup() {
document.getElementById('popup-overlay').style.display = 'flex';
}
</script>
</body>
</html>