Files
nano_metrics/.superpowers/brainstorm/599687-1779425985/content/layout-v7.html
T
2026-05-31 14:01:28 +02:00

635 lines
50 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 — v7</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,.28);
--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;--blue:#3db0d1;--purple:#c882c8;
--border-1:rgba(255,255,255,.06);--border-2:rgba(255,255,255,.12);--border-3:rgba(255,255,255,.26);
--tile-3d:0 1px 0 rgba(255,255,255,.08) inset,0 -1px 0 rgba(0,0,0,.3) inset,0 6px 20px rgba(0,0,0,.5);
--tile-press:inset 0 2px 8px rgba(0,0,0,.5),inset 0 1px 3px rgba(0,0,0,.4);
--hover-glow:0 0 0 1px var(--accent-soft),0 0 24px var(--accent-glow),0 6px 20px rgba(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,.18);
--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,.08);--border-2:rgba(0,0,0,.15);--border-3:rgba(0,0,0,.3);
--tile-3d:0 1px 0 rgba(255,255,255,.55) inset,0 -1px 0 rgba(0,0,0,.08) inset,0 4px 14px rgba(0,0,0,.13);
--tile-press:inset 0 2px 6px rgba(0,0,0,.2);
--hover-glow:0 0 0 1px var(--accent-soft),0 0 18px var(--accent-glow),0 4px 14px rgba(0,0,0,.13);
--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}
/* TOOLTIP */
#tooltip{position:fixed;z-index:9999;pointer-events:none;background:var(--bg-0);color:var(--ink-1);border:1px solid var(--border-3);border-radius:5px;padding:4px 9px;font-size:11px;font-family:var(--font-ui);white-space:nowrap;opacity:0;transition:opacity .12s;box-shadow:0 4px 12px rgba(0,0,0,.4)}
#tooltip.show{opacity:1}
/* HEADER */
.header{background:var(--bg-2);border-bottom:1px solid var(--border-2);padding:0 20px;height:48px;display:flex;align-items:center;gap:12px;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;user-select:none;transition:background .12s,color .12s,transform .08s,box-shadow .08s}
.hbtn:hover{background:var(--bg-4);color:var(--accent)}
.hbtn:active{transform:translateY(1px) scale(.96);box-shadow:var(--tile-press)}
/* 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{background:var(--bg-3);border-radius:10px;padding:12px 14px;border:1px solid var(--border-1);box-shadow:var(--tile-3d);cursor:pointer;user-select:none;display:flex;flex-direction:column;gap:9px;transition:box-shadow .15s,transform .08s,border-color .15s}
.tile:hover{box-shadow:var(--hover-glow);border-color:var(--accent-soft)}
.tile:active{transform:translateY(2px) scale(.99);box-shadow:var(--tile-press)}
.tile.t-warn{border-color:rgba(250,189,47,.3)}.tile.t-warn:hover{border-color:var(--warn);box-shadow:0 0 0 1px var(--warn),0 0 22px rgba(250,189,47,.22),0 6px 20px rgba(0,0,0,.5)}
.tile.t-err{border-color:rgba(251,73,52,.35)}.tile.t-err:hover{border-color:var(--err);box-shadow:0 0 0 1px var(--err),0 0 22px rgba(251,73,52,.25),0 6px 20px rgba(0,0,0,.5)}
.tile.t-off{opacity:.5;cursor:default}.tile.t-off:hover,.tile.t-off:active{box-shadow:var(--tile-3d);border-color:var(--border-1);transform:none}
.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-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;cursor:help}
.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)}
.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}
.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}
/* 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)}
/* OVERLAY */
.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;box-shadow:0 24px 64px rgba(0,0,0,.7);display:flex;flex-direction:column;overflow:hidden}
/* POPUP DETAIL — redimensionnable */
#popup-detail{
width:540px;max-width:96vw;max-height:92vh;
/* redimensionnable par l'utilisateur */
resize:both;overflow:hidden;
min-width:380px;min-height:300px;
}
/* on met overflow:auto sur le body pour que resize fonctionne */
#popup-detail .pop-body{overflow-y:auto;flex:1}
.pop-head{background:var(--bg-3);padding:14px 18px;border-bottom:1px solid var(--border-2);display:flex;align-items:center;gap:12px;flex-shrink:0}
.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-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}
.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)}
.upload-hint{font-size:10px;color:var(--ink-4);font-family:var(--font-terminal);margin-top:2px}
.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;border:1px solid var(--border-1);transition:background .12s,color .12s,transform .08s;user-select:none}
.pop-close:hover{background:var(--err);color:#fff}
.pop-close:active{transform:translateY(1px) scale(.93);box-shadow:var(--tile-press)}
.pop-body{padding:16px 18px;display:flex;flex-direction:column;gap:14px}
.sec-title{font-size:9px;color:var(--ink-4);font-family:var(--font-terminal);letter-spacing:.08em;margin-bottom:8px}
.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}
.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-cur{font-family:var(--font-mono);font-size:16px;font-weight:700}
.chart-svg{width:100%;height:52px;display:block}
.chart-axis{display:flex;justify-content:space-between;margin-top:2px;font-family:var(--font-terminal);font-size:9px;color:var(--ink-4)}
/* STOCKAGE + SMART */
.storage-block{display:flex;flex-direction:column;gap:8px}
.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;cursor:help}
.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.b{background:var(--blue)}
.dg-val{font-family:var(--font-mono);font-size:12px;color:var(--ink-2);width:90px;text-align:right}
/* bouton SMART */
.smart-btn{
display:inline-flex;align-items:center;gap:8px;padding:7px 12px;border-radius:8px;
border:1px solid var(--border-2);background:var(--bg-3);cursor:pointer;user-select:none;
transition:background .12s,border-color .12s,transform .08s,box-shadow .08s;
font-family:var(--font-terminal);font-size:11px;
}
.smart-btn:hover{background:var(--bg-4);border-color:var(--border-3)}
.smart-btn:active{transform:translateY(1px);box-shadow:var(--tile-press)}
.smart-btn.ok{border-color:rgba(77,187,38,.3);color:var(--ok)}
.smart-btn.ok .smart-dot{background:var(--ok);box-shadow:0 0 5px var(--ok)}
.smart-btn.warn{border-color:rgba(250,189,47,.3);color:var(--warn)}
.smart-btn.warn .smart-dot{background:var(--warn);box-shadow:0 0 5px var(--warn)}
.smart-btn.err{border-color:rgba(251,73,52,.3);color:var(--err)}
.smart-btn.err .smart-dot{background:var(--err);box-shadow:0 0 5px var(--err)}
.smart-dot{width:7px;height:7px;border-radius:50%}
.smart-label{font-weight:600;letter-spacing:.04em}
.smart-temp{font-family:var(--font-mono);font-size:10px;color:var(--ink-3);margin-left:4px}
.smart-chevron{font-size:10px;color:var(--ink-4);margin-left:auto}
.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}
.proto-badges{display:flex;gap:5px;margin-top:4px;flex-wrap:wrap}
.proto-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border-radius:999px;font-size:10px;font-family:var(--font-terminal);font-weight:600}
.proto-badge.udp{background:rgba(61,176,209,.15);color:var(--blue);border:1px solid rgba(61,176,209,.3)}
.proto-badge.mqtt{background:rgba(200,130,200,.15);color:var(--purple);border:1px solid rgba(200,130,200,.3)}
.pop-foot{padding:10px 18px;border-top:1px solid var(--border-2);background:var(--bg-3);display:flex;align-items:center;gap:8px;flex-shrink:0}
.pop-uptime{font-family:var(--font-terminal);font-size:11px;color:var(--ink-4);flex:1}
.resize-hint{font-family:var(--font-terminal);font-size:9px;color:var(--ink-4);display:flex;align-items:center;gap:4px}
.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;user-select:none;transition:background .1s,transform .08s,box-shadow .08s}
.btn:hover{background:var(--bg-5)}.btn:active{transform:translateY(1px) scale(.97);box-shadow:var(--tile-press)}
.btn.primary{background:var(--accent);color:var(--bg-0);border-color:var(--accent-soft);font-weight:600}.btn.primary:hover{background:var(--accent-soft)}
.btn-agent-cfg{width:34px;height:34px;border-radius:8px;border:1px solid var(--border-2);background:var(--bg-4);color:var(--ink-3);font-size:15px;display:flex;align-items:center;justify-content:center;cursor:pointer;user-select:none;transition:background .12s,color .12s,transform .08s,box-shadow .08s}
.btn-agent-cfg:hover{background:var(--bg-5);color:var(--accent)}.btn-agent-cfg:active{transform:translateY(1px) scale(.93);box-shadow:var(--tile-press)}
/* ══ POPUP SMART ══ */
#overlay-smart{z-index:300}
#popup-smart{width:500px;max-width:96vw;max-height:88vh}
.smart-head{background:var(--bg-3);padding:14px 18px;border-bottom:1px solid var(--border-2);display:flex;align-items:center;gap:10px}
.smart-head-icon{width:32px;height:32px;border-radius:8px;background:var(--bg-4);display:flex;align-items:center;justify-content:center;color:var(--ok);font-size:15px}
.smart-head-info{flex:1}
.smart-head-title{font-weight:700;font-size:14px}
.smart-head-sub{font-size:11px;color:var(--ink-4);font-family:var(--font-terminal)}
.smart-body{padding:18px;display:flex;flex-direction:column;gap:16px;overflow-y:auto}
/* verdict global */
.smart-verdict{display:flex;align-items:center;gap:14px;background:rgba(77,187,38,.1);border:1px solid rgba(77,187,38,.3);border-radius:10px;padding:14px 18px}
.verdict-icon{font-size:28px;color:var(--ok)}
.verdict-text .v-title{font-size:16px;font-weight:700;color:var(--ok)}
.verdict-text .v-sub{font-size:12px;color:var(--ink-3);margin-top:3px}
/* indicateurs simplifiés */
.smart-indicators{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.smart-ind{background:var(--bg-3);border-radius:8px;padding:12px 14px;border:1px solid var(--border-1);box-shadow:var(--tile-3d)}
.si-header{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.si-icon{font-size:14px;width:22px;text-align:center}
.si-title{font-weight:600;font-size:12px;flex:1}
.si-status{font-size:10px;font-family:var(--font-terminal);font-weight:700;padding:1px 7px;border-radius:999px}
.si-status.ok{background:rgba(77,187,38,.15);color:var(--ok)}
.si-status.warn{background:rgba(250,189,47,.15);color:var(--warn)}
.si-val{font-family:var(--font-mono);font-size:18px;font-weight:700;color:var(--ink-1)}
.si-val .u{font-size:11px;color:var(--ink-3);font-weight:400}
.si-desc{font-size:11px;color:var(--ink-3);margin-top:4px;line-height:1.4}
/* attributs détail */
.smart-attrs{display:flex;flex-direction:column;gap:5px}
.attr-row{display:flex;align-items:center;gap:10px;padding:6px 10px;border-radius:6px;background:var(--bg-3);border:1px solid var(--border-1)}
.attr-id{font-family:var(--font-mono);font-size:10px;color:var(--ink-4);width:28px;flex-shrink:0}
.attr-name{flex:1;font-size:11px;color:var(--ink-2)}
.attr-val{font-family:var(--font-mono);font-size:11px;font-weight:600;width:40px;text-align:right}
.attr-explain{font-size:10px;color:var(--ink-4);width:130px;text-align:right;font-family:var(--font-terminal)}
.attr-ok{color:var(--ok)}.attr-warn{color:var(--warn)}.attr-err{color:var(--err)}
.smart-footer{padding:12px 18px;border-top:1px solid var(--border-2);background:var(--bg-3);display:flex;align-items:center;gap:8px}
.smart-footer-note{flex:1;font-size:10px;color:var(--ink-4);font-family:var(--font-terminal)}
/* CONFIG AGENT */
#overlay-agentcfg{z-index:200}
#popup-agentcfg{width:480px;max-width:96vw;max-height:90vh}
.cfg-head{background:var(--bg-3);padding:14px 18px;border-bottom:1px solid var(--border-2);display:flex;align-items:center;gap:10px}
.cfg-head-icon{width:32px;height:32px;border-radius:8px;background:var(--bg-4);display:flex;align-items:center;justify-content:center;color:var(--accent);font-size:15px}
.cfg-head-info{flex:1}.cfg-head-title{font-weight:700;font-size:14px}.cfg-head-sub{font-size:11px;color:var(--ink-4);font-family:var(--font-terminal)}
.cfg-body{padding:18px;display:flex;flex-direction:column;gap:16px;overflow-y:auto;max-height:58vh}
.cfg-section{display:flex;flex-direction:column;gap:8px}
.cfg-sec-title{font-size:9px;color:var(--ink-4);font-family:var(--font-terminal);letter-spacing:.08em;padding-bottom:6px;border-bottom:1px solid var(--border-1)}
.check-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;background:var(--bg-3);border:1px solid var(--border-1);cursor:pointer;transition:background .12s,border-color .12s}
.check-row.active{border-color:var(--accent-soft);background:rgba(254,128,25,.08)}
.check-row.mqtt-active{border-color:rgba(200,130,200,.4);background:rgba(200,130,200,.07)}
.chk-box{width:18px;height:18px;border-radius:4px;border:2px solid var(--border-3);background:var(--bg-1);display:flex;align-items:center;justify-content:center;font-size:11px;flex-shrink:0}
.check-row.active .chk-box{background:var(--accent);border-color:var(--accent);color:var(--bg-0)}
.check-row.mqtt-active .chk-box{background:var(--purple);border-color:var(--purple);color:var(--bg-0)}
.chk-label{flex:1}.chk-name{font-weight:600;font-size:13px}.chk-desc{font-size:11px;color:var(--ink-4);font-family:var(--font-terminal);margin-top:1px}
.chk-badge{font-size:10px;font-family:var(--font-terminal);font-weight:700;padding:1px 7px;border-radius:999px}
.chk-badge.udp{background:rgba(61,176,209,.15);color:var(--blue)}.chk-badge.mqtt{background:rgba(200,130,200,.15);color:var(--purple)}
.mqtt-opts{background:var(--bg-3);border-radius:8px;border:1px solid rgba(200,130,200,.2);padding:12px 14px;display:flex;flex-direction:column;gap:10px}
.mqtt-field{display:flex;align-items:center;gap:10px}
.mqtt-field label{font-size:11px;color:var(--ink-3);font-family:var(--font-terminal);width:90px;flex-shrink:0}
.mqtt-input{flex:1;background:var(--bg-1);border:1px solid var(--border-2);border-radius:6px;color:var(--ink-1);padding:6px 10px;font-size:12px;font-family:var(--font-mono)}
.mqtt-input:focus{outline:none;border-color:var(--purple)}
.mqtt-check-row{display:flex;align-items:center;justify-content:space-between;padding:4px 0}
.mqtt-check-row label{font-size:12px;color:var(--ink-2);display:flex;align-items:center;gap:7px;cursor:pointer}
.mqtt-check-row label i{color:var(--purple);font-size:11px}
.toggle{position:relative;width:34px;height:18px;flex-shrink:0}
.toggle input{opacity:0;width:0;height:0}
.toggle-slider{position:absolute;inset:0;border-radius:9px;background:var(--bg-4);border:1px solid var(--border-2);cursor:pointer;transition:background .2s}
.toggle-slider::before{content:'';position:absolute;width:12px;height:12px;border-radius:50%;background:var(--ink-4);top:2px;left:2px;transition:transform .2s,background .2s}
.toggle input:checked+.toggle-slider{background:rgba(200,130,200,.3);border-color:var(--purple)}
.toggle input:checked+.toggle-slider::before{transform:translateX(16px);background:var(--purple)}
.metrics-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.metric-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:7px;background:var(--bg-3);border:1px solid var(--border-1)}
.metric-ico{width:22px;text-align:center;font-size:12px;color:var(--ink-3)}
.metric-name{flex:1;font-size:12px;color:var(--ink-2);font-family:var(--font-terminal)}
.tog-ok input:checked+.toggle-slider{background:rgba(77,187,38,.3);border-color:var(--ok)}
.tog-ok input:checked+.toggle-slider::before{background:var(--ok)}
.cmds-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.cmd-btn{display:flex;flex-direction:column;align-items:center;gap:4px;padding:10px 8px;border-radius:8px;background:var(--bg-3);border:1px solid var(--border-1);cursor:not-allowed;opacity:.4}
.cmd-btn i{font-size:16px;color:var(--ink-3)}.cmd-btn span{font-size:10px;color:var(--ink-4);font-family:var(--font-terminal)}
.soon-tag{font-size:8px;color:var(--ink-4);font-family:var(--font-terminal)}
.cfg-foot{padding:12px 18px;border-top:1px solid var(--border-2);background:var(--bg-3);display:flex;align-items:center;gap:8px}
.cfg-status{flex:1;display:flex;align-items:center;gap:6px;font-family:var(--font-terminal);font-size:11px;color:var(--ink-4)}
.cfg-status .dot{width:6px;height:6px;border-radius:50%;background:var(--ok)}
::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{background:var(--bg-1)}::-webkit-scrollbar-thumb{background:var(--bg-4);border-radius:3px}
</style>
</head>
<body>
<div id="tooltip"></div>
<!-- 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()" data-tip="Thème clair / sombre"><i class="fa-solid fa-moon" id="theme-icon"></i></div>
<div class="hbtn" data-tip="Configuration interface"><i class="fa-solid fa-sliders"></i></div>
</div>
<!-- GRID -->
<div class="main">
<div class="agents-grid">
<div class="tile" onclick="showDetail()">
<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" data-tip="CPU"><i class="fa-solid fa-microchip"></i></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" data-tip="RAM"><i class="fa-solid fa-memory"></i></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" data-tip="Disque"><i class="fa-solid fa-hard-drive"></i></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" data-tip="CPU élevé" style="color:var(--warn)"><i class="fa-solid fa-microchip"></i></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" data-tip="RAM élevée" style="color:var(--warn)"><i class="fa-solid fa-memory"></i></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" data-tip="Disque"><i class="fa-solid fa-hard-drive"></i></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" data-tip="CPU"><i class="fa-solid fa-microchip"></i></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" data-tip="RAM"><i class="fa-solid fa-memory"></i></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" data-tip="Disque critique !" style="color:var(--err)"><i class="fa-solid fa-hard-drive"></i></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" data-tip="CPU"><i class="fa-solid fa-microchip"></i></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" data-tip="RAM"><i class="fa-solid fa-memory"></i></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" data-tip="Disque"><i class="fa-solid fa-hard-drive"></i></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 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" style="color:var(--err)"><i class="fa-solid fa-circle-xmark"></i>Hors ligne · vu il y a 2h</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 DÉTAIL — redimensionnable ══ -->
<div class="overlay" id="overlay-detail" style="display:flex" onclick="if(event.target===this)this.style.display='none'">
<div class="popup" id="popup-detail" onclick="event.stopPropagation()">
<div class="pop-head">
<div class="agent-icon-wrap" onclick="document.getElementById('icon-upload').click()" data-tip="Changer l'icône">
<i class="fa-solid fa-server"></i>
<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">
<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">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('overlay-detail').style.display='none'" data-tip="Fermer"><i class="fa-solid fa-xmark"></i></div>
</div>
<div class="pop-body">
<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>
<div>
<div class="sec-title">HISTORIQUE — 30 MIN</div>
<div class="charts-grid">
<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 52" preserveAspectRatio="none" id="cpu-chart"></svg>
<div class="chart-axis"><span>30min</span><span>15min</span><span>now</span></div>
</div>
<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 52" preserveAspectRatio="none" id="ram-chart"></svg>
<div class="chart-axis"><span>30min</span><span>15min</span><span>now</span></div>
</div>
</div>
</div>
<div>
<div class="sec-title">STOCKAGE</div>
<div class="storage-block">
<div class="det-gauges">
<div class="dg-row"><div class="dg-ico" data-tip="Utilisé"><i class="fa-solid fa-hard-drive"></i></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" data-tip="Libre" style="color:var(--blue)"><i class="fa-solid fa-floppy-disk"></i></div><div class="dg-bar"><div class="dg-fill b" style="width:69%"></div></div><span class="dg-val">138 Go libre</span></div>
</div>
<!-- Bouton SMART — affiché si smartctl disponible -->
<div class="smart-btn ok" onclick="showSmart();event.stopPropagation()" data-tip="Voir l'état de santé complet du disque">
<div class="smart-dot"></div>
<span class="smart-label">SMART</span>
<span style="font-size:10px;color:var(--ink-3)">·</span>
<span style="font-size:11px;color:var(--ok);font-family:var(--font-terminal)">PASSED</span>
<span class="smart-temp"><i class="fa-solid fa-temperature-half"></i> 34°C</span>
<i class="fa-solid fa-chevron-right smart-chevron"></i>
</div>
</div>
</div>
<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">PROTOCOLES ACTIFS</div><div class="proto-badges"><span class="proto-badge udp"><i class="fa-solid fa-arrow-up"></i>UDP</span><span class="proto-badge mqtt">M MQTT</span></div></div>
<div class="meta"><div class="meta-lbl">DERNIER CONTACT</div><div class="meta-val">22:14:07</div></div>
</div>
</div>
</div>
<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>
<span class="resize-hint"><i class="fa-solid fa-up-right-and-down-left-from-center"></i>Redimensionnable</span>
<div class="btn-agent-cfg" onclick="showAgentCfg()" data-tip="Configurer l'agent"><i class="fa-solid fa-gears"></i></div>
</div>
</div>
</div>
<!-- ══ POPUP SMART ══ -->
<div class="overlay" id="overlay-smart" style="display:none" onclick="if(event.target===this)this.style.display='none'">
<div class="popup" id="popup-smart" onclick="event.stopPropagation()">
<div class="smart-head">
<div class="smart-head-icon"><i class="fa-solid fa-shield-heart"></i></div>
<div class="smart-head-info">
<div class="smart-head-title">Santé du disque dur</div>
<div class="smart-head-sub">srv-prod-01 · /dev/sda · Samsung SSD 870 EVO 250GB</div>
</div>
<div class="pop-close" onclick="document.getElementById('overlay-smart').style.display='none'" data-tip="Fermer"><i class="fa-solid fa-xmark"></i></div>
</div>
<div class="smart-body">
<!-- Verdict global en français, compréhensible par tous -->
<div class="smart-verdict">
<div class="verdict-icon"><i class="fa-solid fa-circle-check"></i></div>
<div class="verdict-text">
<div class="v-title">Disque en bonne santé</div>
<div class="v-sub">Aucun problème détecté. Le disque fonctionne normalement et peut être utilisé en toute confiance.</div>
</div>
</div>
<!-- Indicateurs simplifiés -->
<div>
<div class="sec-title">POINTS DE CONTRÔLE PRINCIPAUX</div>
<div class="smart-indicators">
<div class="smart-ind">
<div class="si-header">
<div class="si-icon" style="color:var(--warn)"><i class="fa-solid fa-temperature-half"></i></div>
<span class="si-title">Température</span>
<span class="si-status ok">Normale</span>
</div>
<div class="si-val">34<span class="u">°C</span></div>
<div class="si-desc">La température idéale est entre 20°C et 50°C. Au-delà de 60°C le disque risque de s'abîmer prématurément.</div>
</div>
<div class="smart-ind">
<div class="si-header">
<div class="si-icon" style="color:var(--ok)"><i class="fa-solid fa-circle-check"></i></div>
<span class="si-title">Secteurs défectueux</span>
<span class="si-status ok">Aucun</span>
</div>
<div class="si-val">0<span class="u"> sect.</span></div>
<div class="si-desc">Les secteurs défectueux sont des zones endommagées sur le disque. S'ils apparaissent en grand nombre, une panne est imminente.</div>
</div>
<div class="smart-ind">
<div class="si-header">
<div class="si-icon" style="color:var(--blue)"><i class="fa-solid fa-clock-rotate-left"></i></div>
<span class="si-title">Heures de fonctionnement</span>
<span class="si-status ok">Jeune</span>
</div>
<div class="si-val">4<span class="u">213 h</span></div>
<div class="si-desc">Environ 175 jours de fonctionnement. Un disque dur de bureau dure en moyenne 3 à 5 ans (26 000 43 000 heures).</div>
</div>
<div class="smart-ind">
<div class="si-header">
<div class="si-icon" style="color:var(--ok)"><i class="fa-solid fa-battery-full"></i></div>
<span class="si-title">Durée de vie SSD</span>
<span class="si-status ok">Excellente</span>
</div>
<div class="si-val">98<span class="u">%</span></div>
<div class="si-desc">Indique la durée de vie restante des cellules flash (spécifique aux SSD). 100% = neuf, 0% = fin de vie recommandée.</div>
</div>
</div>
</div>
<!-- Attributs détaillés -->
<div>
<div class="sec-title">ATTRIBUTS SMART DÉTAILLÉS</div>
<div class="smart-attrs">
<div class="attr-row">
<span class="attr-id">001</span>
<span class="attr-name">Taux d'erreurs de lecture brutes</span>
<span class="attr-val attr-ok">0</span>
<span class="attr-explain attr-ok">✓ Parfait</span>
</div>
<div class="attr-row">
<span class="attr-id">005</span>
<span class="attr-name">Secteurs réalloués (remplacés)</span>
<span class="attr-val attr-ok">0</span>
<span class="attr-explain attr-ok">✓ Aucun dommage</span>
</div>
<div class="attr-row">
<span class="attr-id">009</span>
<span class="attr-name">Heures de fonctionnement</span>
<span class="attr-val attr-ok">4213</span>
<span class="attr-explain">175 jours</span>
</div>
<div class="attr-row">
<span class="attr-id">012</span>
<span class="attr-name">Nombre de démarrages</span>
<span class="attr-val attr-ok">312</span>
<span class="attr-explain">Normale</span>
</div>
<div class="attr-row">
<span class="attr-id">177</span>
<span class="attr-name">Usure des cellules d'écriture (SSD)</span>
<span class="attr-val attr-ok">2</span>
<span class="attr-explain attr-ok">✓ Très faible</span>
</div>
<div class="attr-row">
<span class="attr-id">190</span>
<span class="attr-name">Température du disque</span>
<span class="attr-val attr-ok">34°C</span>
<span class="attr-explain attr-ok">✓ Normale</span>
</div>
<div class="attr-row">
<span class="attr-id">197</span>
<span class="attr-name">Secteurs instables en attente</span>
<span class="attr-val attr-ok">0</span>
<span class="attr-explain attr-ok">✓ Aucun</span>
</div>
<div class="attr-row">
<span class="attr-id">198</span>
<span class="attr-name">Secteurs non corrigeables</span>
<span class="attr-val attr-ok">0</span>
<span class="attr-explain attr-ok">✓ Aucun</span>
</div>
</div>
</div>
</div>
<div class="smart-footer">
<span class="smart-footer-note"><i class="fa-solid fa-circle-info" style="margin-right:4px"></i>Données collectées via smartctl · mise à jour à chaque actualisation de l'agent</span>
<button class="btn primary" onclick="document.getElementById('overlay-smart').style.display='none'"><i class="fa-solid fa-xmark"></i> Fermer</button>
</div>
</div>
</div>
<!-- CONFIG AGENT (inchangé) -->
<div class="overlay" id="overlay-agentcfg" style="display:none;z-index:200" onclick="if(event.target===this)this.style.display='none'">
<div class="popup" id="popup-agentcfg" onclick="event.stopPropagation()">
<div class="cfg-head">
<div class="cfg-head-icon"><i class="fa-solid fa-gears"></i></div>
<div class="cfg-head-info"><div class="cfg-head-title">Configuration de l'agent</div><div class="cfg-head-sub">srv-prod-01 · 10.0.0.11 · config récupérée à 22:14:05</div></div>
<div class="pop-close" onclick="document.getElementById('overlay-agentcfg').style.display='none'" data-tip="Fermer"><i class="fa-solid fa-xmark"></i></div>
</div>
<div class="cfg-body">
<div class="cfg-section">
<div class="cfg-sec-title">PROTOCOLES DE TRANSPORT</div>
<div class="check-row active"><div class="chk-box"><i class="fa-solid fa-check"></i></div><div class="chk-label"><div class="chk-name">UDP <span class="chk-badge udp">UDP</span></div><div class="chk-desc">Fire-and-forget · serveur 10.0.0.82 · port 9999</div></div></div>
<div class="check-row mqtt-active"><div class="chk-box" style="background:var(--purple);border-color:var(--purple);color:var(--bg-0)"><i class="fa-solid fa-check"></i></div><div class="chk-label"><div class="chk-name">MQTT <span class="chk-badge mqtt">MQTT</span></div><div class="chk-desc">Bidirectionnel · broker 10.0.0.3 · port 1883</div></div></div>
<div class="mqtt-opts">
<div class="mqtt-field"><label>Broker</label><input class="mqtt-input" type="text" value="10.0.0.3"></div>
<div class="mqtt-field"><label>Port</label><input class="mqtt-input" type="number" value="1883" style="width:90px;flex:none"></div>
<div class="mqtt-field"><label>Topic base</label><input class="mqtt-input" type="text" value="nanometrics/agents"></div>
<div style="border-top:1px solid var(--border-1);padding-top:8px;display:flex;flex-direction:column;gap:6px">
<div class="mqtt-check-row"><label><i class="fa-solid fa-satellite-dish"></i> Auto-discovery (Home Assistant)</label><label class="toggle"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="mqtt-check-row"><label><i class="fa-solid fa-arrow-right-to-bracket"></i> Birth message (connexion)</label><label class="toggle"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="mqtt-check-row"><label><i class="fa-solid fa-skull"></i> Last Will message (déconnexion)</label><label class="toggle"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
</div>
</div>
</div>
<div class="cfg-section">
<div class="cfg-sec-title">MÉTRIQUES ACTIVES</div>
<div class="metrics-grid">
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-microchip"></i></div><span class="metric-name">cpu</span><label class="toggle tog-ok"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-memory"></i></div><span class="metric-name">memory</span><label class="toggle tog-ok"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-hard-drive"></i></div><span class="metric-name">disk</span><label class="toggle tog-ok"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-shield-heart"></i></div><span class="metric-name">smart</span><label class="toggle tog-ok"><input type="checkbox" checked><span class="toggle-slider"></span></label></div>
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-network-wired"></i></div><span class="metric-name">network</span><label class="toggle tog-ok"><input type="checkbox"><span class="toggle-slider"></span></label></div>
<div class="metric-row"><div class="metric-ico"><i class="fa-solid fa-thermometer-half"></i></div><span class="metric-name">temperature</span><label class="toggle tog-ok"><input type="checkbox"><span class="toggle-slider"></span></label></div>
</div>
</div>
<div class="cfg-section">
<div class="cfg-sec-title">COMMANDES DISTANTES <span style="color:var(--ink-4);font-size:8px;margin-left:6px">— BIENTÔT</span></div>
<div class="cmds-grid">
<div class="cmd-btn"><i class="fa-solid fa-rotate-right"></i><span>reboot</span><span class="soon-tag">bientôt</span></div>
<div class="cmd-btn"><i class="fa-solid fa-power-off"></i><span>shutdown</span><span class="soon-tag">bientôt</span></div>
<div class="cmd-btn"><i class="fa-solid fa-display"></i><span>screen off</span><span class="soon-tag">bientôt</span></div>
<div class="cmd-btn"><i class="fa-solid fa-arrow-up-from-bracket"></i><span>update</span><span class="soon-tag">bientôt</span></div>
<div class="cmd-btn"><i class="fa-solid fa-arrow-up-right-dots"></i><span>upgrade</span><span class="soon-tag">bientôt</span></div>
<div class="cmd-btn"><i class="fa-solid fa-terminal"></i><span>shell cmd</span><span class="soon-tag">bientôt</span></div>
</div>
</div>
</div>
<div class="cfg-foot">
<div class="cfg-status"><div class="dot"></div><span>Config synchronisée</span></div>
<button class="btn" onclick="document.getElementById('overlay-agentcfg').style.display='none'">Annuler</button>
<button class="btn primary"><i class="fa-solid fa-paper-plane"></i> Envoyer à l'agent</button>
</div>
</div>
</div>
<script>
const tip=document.getElementById('tooltip');let tt;
document.addEventListener('mouseover',e=>{const el=e.target.closest('[data-tip]');if(!el)return;clearTimeout(tt);tt=setTimeout(()=>{tip.textContent=el.dataset.tip;tip.classList.add('show');mv(e);},120);});
document.addEventListener('mousemove',e=>{if(tip.classList.contains('show'))mv(e);});
document.addEventListener('mouseout',e=>{const el=e.target.closest('[data-tip]');if(!el)return;clearTimeout(tt);tip.classList.remove('show');});
function mv(e){const w=tip.offsetWidth,h=tip.offsetHeight;let x=e.clientX-w/2,y=e.clientY-h-10;x=Math.max(6,Math.min(x,window.innerWidth-w-6));if(y<6)y=e.clientY+18;tip.style.left=x+'px';tip.style.top=y+'px';}
function toggleTheme(){const h=document.documentElement;h.dataset.theme=h.dataset.theme==='dark'?'light':'dark';document.getElementById('theme-icon').className=h.dataset.theme==='dark'?'fa-solid fa-moon':'fa-solid fa-sun';drawCharts();}
function showDetail(){document.getElementById('overlay-detail').style.display='flex';drawCharts();}
function showAgentCfg(){document.getElementById('overlay-agentcfg').style.display='flex';}
function showSmart(){document.getElementById('overlay-smart').style.display='flex';}
/* Sauvegarde taille popup au resize */
const pd=document.getElementById('popup-detail');
const ro=new ResizeObserver(()=>{
localStorage.setItem('popup-detail-size',JSON.stringify({w:pd.offsetWidth,h:pd.offsetHeight}));
});
ro.observe(pd);
const saved=JSON.parse(localStorage.getItem('popup-detail-size')||'null');
if(saved){pd.style.width=saved.w+'px';pd.style.height=saved.h+'px';}
function makeCurve(pts,stroke,fill,w,h){
const xs=pts.map((_,i)=>(i/(pts.length-1))*w);
const ys=pts.map(v=>h-(v/100)*(h-6)-3);
const wy=h-(70/100)*(h-6)-3;
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 uid=Math.random().toString(36).slice(2);
return `<defs><linearGradient id="g${uid}" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="${fill}" stop-opacity=".4"/><stop offset="100%" stop-color="${fill}" stop-opacity=".02"/></linearGradient></defs>
<line x1="0" y1="${wy}" x2="${w}" y2="${wy}" stroke="var(--warn)" stroke-width=".8" stroke-dasharray="3,3" opacity=".5"/>
<path d="${d} L${xs.at(-1)} ${h} L${xs[0]} ${h}Z" fill="url(#g${uid})"/>
<path d="${d}" fill="none" stroke="${stroke}" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="${xs.at(-1)}" cy="${ys.at(-1)}" r="2.5" fill="${stroke}"/>`;
}
function drawCharts(){
const cpu=[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 ram=[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 cs=getComputedStyle(document.documentElement);
const ac=cs.getPropertyValue('--accent').trim(),bl=cs.getPropertyValue('--blue').trim();
document.getElementById('cpu-chart').innerHTML=makeCurve(cpu,ac,ac,200,52);
document.getElementById('ram-chart').innerHTML=makeCurve(ram,bl,bl,200,52);
}
window.addEventListener('load',drawCharts);
</script>
</body>
</html>