Files
awoooi/.playwright-mcp/sprint5-approved-design.html

583 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1440">
<title>AWOOOI 指令中心 — 最終版</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=VT323&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
/*
方案 2: Sidebar 品牌 + 內容區標題列 (Linear/Notion 風格)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- 無獨立 Header 橫條
- 品牌在 Sidebar 頂部
- 標題/Tab/操作在內容區頂部
- 所有元素嚴格對齊
*/
*{margin:0;padding:0;box-sizing:border-box}
:root{
--bg:#f5f4ed;--card:#fff;--surface:#faf9f3;--bdr:#e0ddd4;
--text:#141413;--text2:#555550;--text3:#87867f;
--accent:#d97757;--green:#22C55E;--red:#cc2200;--blue:#4A90D9;--orange:#F59E0B;--purple:#A855F7;
--sb-w:200px;--gap:14px;--radius:10px;--border:.5px solid #e0ddd4;
}
body{font-family:'DM Mono','Inter',system-ui,monospace;background:var(--bg);color:var(--text);font-size:13px;-webkit-font-smoothing:antialiased;overflow:hidden;height:100vh;line-height:1.5}
/* ═══ LAYOUT ═══ */
.layout{display:flex;height:100vh}
/* ═══ SIDEBAR (200px) ═══ */
.sidebar{width:var(--sb-w);flex-shrink:0;background:var(--surface);border-right:var(--border);display:flex;flex-direction:column;overflow:hidden}
/* Brand Area (品牌區, 72px 高) */
.brand{height:72px;padding:0 16px;display:flex;align-items:center;gap:10px;border-bottom:var(--border);flex-shrink:0}
.brand svg{flex-shrink:0}
.brand-text{display:inline-flex;align-items:baseline;gap:0}
.brand-text .a,.brand-text .i{font-family:'DM Mono',monospace;font-size:22px;font-weight:700;color:var(--text)}
.brand-text .w{font-family:'VT323',monospace;font-size:30px;color:var(--accent);letter-spacing:0;line-height:1}
/* Nav */
.nav{flex:1;overflow-y:auto;padding:8px}
.nav-item{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:6px;font-size:13px;color:var(--text2);cursor:pointer;transition:all .12s;margin-bottom:1px}
.nav-item:hover{background:rgba(0,0,0,.03)}
.nav-item.on{background:rgba(217,119,87,.08);color:var(--accent);font-weight:500}
.nav-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}
.nav-badge{margin-left:auto;background:var(--red);color:#fff;font-size:7px;padding:1px 5px;border-radius:6px;font-weight:700;min-width:14px;text-align:center}
.nav-sep{height:var(--border);background:var(--bdr);margin:8px 12px}
.nav-label{font-size:7px;text-transform:uppercase;letter-spacing:1.2px;color:var(--text3);padding:8px 12px 4px;font-weight:600}
/* Nav Bottom */
.nav-bottom{border-top:var(--border);padding:8px;flex-shrink:0}
/* ═══ CONTENT AREA ═══ */
.content{flex:1;display:flex;flex-direction:column;overflow:hidden}
/* Title Bar (內容區頂部, 48px) */
.title-bar{height:48px;padding:0 20px;display:flex;align-items:center;gap:16px;border-bottom:var(--border);background:var(--surface);flex-shrink:0}
.page-title{font-family:'Syne','Inter',sans-serif;font-size:20px;font-weight:800;color:var(--text);letter-spacing:-.3px}
.title-actions{margin-left:auto;display:flex;align-items:center;gap:10px}
.ai-status{display:flex;align-items:center;gap:5px;padding:4px 10px;border:var(--border);border-radius:20px;font-size:9px;color:var(--text2)}
.ai-dot{width:5px;height:5px;border-radius:50%;background:var(--green);animation:blink 2s infinite}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.3}}
.lang-btn{padding:4px 10px;font-family:'DM Mono',monospace;font-size:10px;border:var(--border);border-radius:16px;cursor:pointer;background:transparent;color:var(--text3)}
.lang-btn.on{background:var(--text);color:#fff;border-color:var(--text)}
.avatar{width:24px;height:24px;border-radius:50%;background:var(--accent);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:#fff}
/* Tab Bar (36px) */
.tab-bar{height:36px;padding:0 20px;display:flex;align-items:stretch;border-bottom:var(--border);background:var(--card);flex-shrink:0}
.tab{padding:0 14px;font-size:12px;font-weight:500;color:var(--text3);cursor:pointer;border-bottom:2px solid transparent;display:flex;align-items:center;gap:4px;transition:all .12s}
.tab:hover{color:var(--text2)}
.tab.on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.tab-badge{background:var(--red);color:#fff;font-size:7px;padding:0 4px;border-radius:4px;font-weight:700;min-width:14px;text-align:center}
/* ═══ KPI Strip (融入背景, 不反白) ═══ */
.kpi-strip{display:flex;padding:10px 20px;gap:12px;flex-shrink:0}
.kpi-card{flex:1;background:var(--card);border:var(--border);border-radius:8px;padding:8px 12px}
.kpi-label{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--text3);font-weight:500}
.kpi-row{display:flex;align-items:baseline;gap:4px;margin-top:2px}
.kpi-val{font-size:22px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1}
.kpi-sub{font-size:9px;color:var(--text2)}
.kpi-trend{font-size:9px;font-weight:500}
.kpi-bar{height:2px;border-radius:1px;background:#ebe8df;margin-top:4px;overflow:hidden}
.kpi-bar-f{height:100%;border-radius:1px}
/* ═══ MAIN BODY (2 欄) ═══ */
.main-body{flex:1;display:flex;gap:var(--gap);padding:0 20px var(--gap);overflow:hidden}
/* Left Column (60%) */
.col-left{flex:6;min-width:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--gap);padding-top:var(--gap);padding-bottom:40px}
.col-left .card{flex-shrink:0}
/* Right Column (40%) — 整欄可捲動,卡片自然撐開不截斷 */
.col-right{flex:4;min-width:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--gap);padding-top:var(--gap);padding-bottom:40px}
.col-right .card{flex-shrink:0}
/* ═══ SHARED CARD ═══ */
.card{background:var(--card);border:var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.04)}
.card-header{padding:10px 14px;border-bottom:var(--border);display:flex;align-items:center;gap:8px;background:var(--surface)}
.card-dot{width:5px;height:5px;border-radius:50%;background:var(--accent);flex-shrink:0}
.card-title{font-size:14px;font-weight:700;letter-spacing:.3px}
.card-action{margin-left:auto;font-size:11px;color:var(--blue);cursor:pointer;font-weight:500;white-space:nowrap}
.card-action:hover{text-decoration:underline}
.card-body{padding:14px}
/* ═══ INCIDENT CARD ═══ */
.inc{border:var(--border);border-radius:8px;overflow:hidden;margin-bottom:12px;box-shadow:0 1px 2px rgba(0,0,0,.03)}
.inc:last-child{margin-bottom:0}
.inc-bar{height:3px}
.inc-body{padding:10px 12px}
.inc-top{display:flex;align-items:center;gap:6px;margin-bottom:4px}
.inc-sev{font-size:9px;font-weight:700;padding:2px 6px;border-radius:3px}
.inc-name{font-size:13px;font-weight:600}
.inc-meta{font-size:11px;color:var(--text2);margin-bottom:6px}
/* FlowPipeline Animations */
@keyframes lobster-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
@keyframes card-glow-p2{0%,100%{box-shadow:0 0 0 0 rgba(74,144,217,.3)}50%{box-shadow:0 0 6px 2px rgba(74,144,217,.3)}}
/* AI 提案 */
.ai-proposal{background:rgba(217,119,87,.06);border:var(--border);border-color:rgba(217,119,87,.15);border-radius:6px;padding:6px 10px;font-size:10px;color:var(--accent);display:flex;align-items:center;gap:4px;margin-top:6px}
.inc-actions{display:flex;gap:6px;margin-top:8px}
.btn-approve{padding:5px 14px;border:none;border-radius:5px;font-size:10px;font-weight:600;cursor:pointer;background:var(--green);color:#fff}
.btn-reject{padding:5px 14px;border:var(--border);border-radius:5px;font-size:10px;cursor:pointer;background:var(--card);color:var(--text2)}
/* ═══ DISPOSITION MINI ═══ */
.disp-mini{display:flex;gap:10px;align-items:center}
.disp-ring{position:relative;width:56px;height:56px;flex-shrink:0}
.disp-ring svg{transform:rotate(-90deg)}
.disp-ring-center{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;color:var(--green)}
.disp-list{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:2px 12px}
.disp-item{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text2)}
.disp-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}
.disp-num{margin-left:auto;font-weight:700;font-variant-numeric:tabular-nums}
/* ═══ STREAM MINI ═══ */
.stream-item{display:flex;gap:8px;padding:6px 0;border-bottom:.5px solid #f0ede5;font-size:12px}
.stream-item:last-child{border-bottom:none}
.stream-time{font-size:10px;color:var(--text2);font-family:'JetBrains Mono',monospace;width:40px;flex-shrink:0}
.stream-dot{width:4px;height:4px;border-radius:50%;margin-top:5px;flex-shrink:0}
.stream-msg{flex:1;line-height:1.4}
.stream-msg b{font-weight:600}
.stream-msg code{background:rgba(0,0,0,.04);padding:0 2px;border-radius:2px;font-family:'JetBrains Mono',monospace;font-size:9px}
/* ═══ OPENCLAW PANEL ═══ */
.oc-body{display:flex;gap:12px;align-items:flex-start}
.oc-info{flex:1;min-width:0}
.oc-brand{display:inline-flex;align-items:baseline;gap:0;margin-bottom:2px}
.oc-brand .w,.oc-brand .c{font-family:'DM Mono',monospace;font-size:15px;font-weight:700;color:var(--text)}
.oc-brand .o{font-family:'VT323',monospace;font-size:24px;color:var(--accent);letter-spacing:0;line-height:1}
.oc-badge{display:inline-block;font-size:8px;padding:2px 6px;background:rgba(74,144,217,.1);color:var(--blue);border-radius:2px;text-transform:uppercase;letter-spacing:1.2px;margin-bottom:6px}
.oc-status{font-size:11px;color:var(--text2);display:flex;align-items:center;gap:4px}
.oc-pulse{display:inline-flex;gap:3px}
.oc-pulse span{width:4px;height:4px;border-radius:50%;background:var(--blue)}
.oc-pulse span:nth-child(1){animation:oc-p 1.4s 0s infinite}
.oc-pulse span:nth-child(2){animation:oc-p 1.4s .2s infinite}
.oc-pulse span:nth-child(3){animation:oc-p 1.4s .4s infinite}
@keyframes oc-p{0%,60%,100%{opacity:.2}30%{opacity:1}}
/* ═══ TOPO GROUPS ═══ */
.topo-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.topo-g{border:var(--border);border-radius:8px;padding:8px 10px;cursor:pointer;transition:all .12s}
.topo-g:hover{transform:translateY(-1px);box-shadow:0 2px 6px rgba(0,0,0,.05)}
.tg-name{font-size:12px;font-weight:600;margin-bottom:2px}
.tg-meta{font-size:10px;color:var(--text2)}
.tg-svcs{display:flex;flex-wrap:wrap;gap:2px;margin-top:4px}
.tg-svc{display:flex;align-items:center;gap:3px;padding:2px 7px;background:var(--card);border:var(--border);border-radius:4px;font-size:10px}
.tg-sdot{width:3px;height:3px;border-radius:50%}
.tg-infra{border-color:rgba(59,130,246,.2);background:rgba(59,130,246,.01)}
.tg-ai{border-color:rgba(249,115,22,.25);background:rgba(249,115,22,.01)}
.tg-k3s{border-color:rgba(168,85,247,.25);background:rgba(168,85,247,.01)}
.tg-ext{border-color:rgba(245,158,11,.2);background:rgba(245,158,11,.01)}
/* ═══ TOGGLE ═══ */
.toggle-bar{display:flex;background:var(--bg);border-radius:5px;padding:2px}
.toggle-opt{padding:3px 10px;border-radius:3px;font-size:8px;font-weight:500;cursor:pointer;color:var(--text3);transition:all .12s}
.toggle-opt.on{background:var(--card);color:var(--accent);box-shadow:0 1px 2px rgba(0,0,0,.06);font-weight:600}
/* ═══ HOST GRID ═══ */
.host-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.host-card{border:var(--border);border-radius:8px;padding:8px 10px;background:var(--surface)}
.host-name{font-size:12px;font-weight:600;margin-bottom:2px}
.host-ip{font-size:10px;color:var(--text2);font-family:'JetBrains Mono',monospace}
.host-bars{display:flex;gap:6px;margin-top:5px}
.host-bar-w{flex:1}
.host-bar-l{font-size:7px;color:var(--text3);margin-bottom:2px;display:flex;justify-content:space-between}
.host-bar{height:3px;border-radius:2px;background:#ebe8df;overflow:hidden}
.host-bar-f{height:100%;border-radius:2px}
/* ═══ TOOL GRID ═══ */
.tool-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px}
.tool{display:flex;overflow:hidden;border:var(--border);border-radius:6px;background:var(--surface);cursor:pointer;transition:all .1s}
.tool:hover{border-color:var(--blue)}
.tool-bar{width:3px;flex-shrink:0}
.tool-body{padding:5px 7px;flex:1;min-width:0}
.tool-name{font-size:11px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tool-meta{font-size:10px;color:var(--text2);margin-top:2px}
/* ═══ APPROVAL MINI ═══ */
.appr-item{background:var(--surface);border:var(--border);border-radius:6px;padding:8px 10px;margin-bottom:6px}
.appr-item:last-child{margin-bottom:0}
.appr-alert{font-size:13px;font-weight:600}
.appr-target{font-size:11px;color:var(--text2);margin-top:2px;font-family:'JetBrains Mono',monospace}
.appr-risk{display:inline-block;font-size:10px;padding:2px 8px;border-radius:3px;margin-top:3px;font-weight:600}
.risk-low{background:rgba(34,197,94,.08);color:var(--green)}
.risk-med{background:rgba(249,115,22,.08);color:var(--orange)}
.appr-btns{display:flex;gap:4px;margin-top:5px}
.btn-sm-ok{flex:1;padding:6px;border:none;border-radius:5px;font-size:11px;font-weight:600;cursor:pointer;background:var(--green);color:#fff}
.btn-sm-no{flex:1;padding:6px;border:var(--border);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);color:var(--text2)}
/* ═══ AI MODEL STATUS ═══ */
.model-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.model{border:var(--border);border-radius:6px;padding:6px 8px;display:flex;align-items:center;gap:6px}
.model-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}
.model-name{font-size:12px;font-weight:500}
.model-tag{font-size:10px;color:var(--text3);margin-left:auto}
/* ═══ TERMINAL FLOAT ═══ */
.terminal-float{position:fixed;bottom:14px;right:14px;display:flex;align-items:center;gap:5px;padding:6px 14px;background:var(--card);border:var(--border);border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.08);cursor:pointer;font-size:10px;color:var(--text2);z-index:40;transition:all .12s}
.terminal-float:hover{border-color:var(--accent);color:var(--accent)}
/* 龍蝦動畫 */
.chibi-strip{height:14px;position:relative;overflow:hidden;border-bottom:.5px dashed rgba(232,85,48,.06);flex-shrink:0}
@keyframes swim{0%{transform:translateX(0) scaleX(1)}47%{transform:translateX(900px) scaleX(1)}50%{transform:translateX(900px) scaleX(-1)}97%{transform:translateX(0) scaleX(-1)}100%{transform:translateX(0) scaleX(1)}}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-2px)}}
.chibi-swim{animation:swim 25s linear infinite;position:absolute;top:0;left:0}
.chibi-bob{animation:bob .7s ease-in-out infinite;display:inline-block}
</style>
</head>
<body>
<div class="layout">
<!-- ═══ SIDEBAR ═══ -->
<div class="sidebar">
<!-- Brand Area (72px) -->
<div class="brand">
<svg width="32" height="32" viewBox="0 0 140 140" fill="none">
<defs><linearGradient id="c1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#FFF"/><stop offset="40%" stop-color="#F8F8F8"/><stop offset="70%" stop-color="#E8E8E8"/><stop offset="100%" stop-color="#D8D8D8"/></linearGradient><radialGradient id="l1" cx="40%" cy="35%" r="60%"><stop offset="0%" stop-color="#7AB8F5"/><stop offset="100%" stop-color="#2B6CB0"/></radialGradient></defs>
<circle cx="70" cy="70" r="32" fill="url(#c1)" stroke="#E0E0E0" stroke-width="1"/>
<circle cx="70" cy="70" r="16" fill="url(#l1)"><animate attributeName="r" values="14;17;14" dur="2s" repeatCount="indefinite"/></circle>
<circle cx="70" cy="70" r="8" fill="white" opacity=".8"/>
<path d="M70 38L70 18L58 6M70 18L82 6" stroke="url(#c1)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M70 38L70 18L58 6M70 18L82 6" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M38 70L18 70L6 58M18 70L6 82" stroke="url(#c1)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M38 70L18 70L6 58M18 70L6 82" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M102 70L122 70L134 58M122 70L134 82" stroke="url(#c1)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M102 70L122 70L134 58M122 70L134 82" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M48 92L28 112L16 116" stroke="url(#c1)" stroke-width="6" stroke-linecap="round" fill="none"/>
<path d="M92 92L112 112L124 116" stroke="url(#c1)" stroke-width="6" stroke-linecap="round" fill="none"/>
<circle cx="70" cy="70" r="42" fill="none" stroke="#4A90D9" stroke-width="1" stroke-dasharray="6 6" opacity=".3"><animateTransform attributeName="transform" type="rotate" from="0 70 70" to="360 70 70" dur="8s" repeatCount="indefinite"/></circle>
</svg>
<div class="brand-text"><span class="a">A</span><span class="w">wooo</span><span class="i">I</span></div>
</div>
<!-- Nav -->
<div class="nav">
<div class="nav-item on"><span class="nav-dot" style="background:var(--accent)"></span>指令中心<span style="margin-left:auto;font-size:9px;color:var(--text3)">4 tab</span></div>
<div class="nav-item"><span class="nav-dot" style="background:var(--blue)"></span>可觀測性<span style="margin-left:auto;font-size:9px;color:var(--text3)">5 tab</span></div>
<div class="nav-item"><span class="nav-dot" style="background:var(--green)"></span>自動化<span style="margin-left:auto;font-size:9px;color:var(--text3)">3 tab</span></div>
<div class="nav-item"><span class="nav-dot" style="background:var(--purple)"></span>營運<span style="margin-left:auto;font-size:9px;color:var(--text3)">5 tab</span></div>
<div class="nav-item"><span class="nav-dot" style="background:var(--red)"></span>安全合規<span style="margin-left:auto;font-size:9px;color:var(--text3)">2 tab</span></div>
<div class="nav-item"><span class="nav-dot" style="background:var(--text3)"></span>知識</div>
<div class="nav-sep"></div>
<div class="nav-label">legacy</div>
<div class="nav-item" style="opacity:.5"><span class="nav-dot" style="background:var(--text3)"></span>經典 AI 中心</div>
</div>
<!-- Nav Bottom -->
<div class="nav-bottom">
<div class="nav-item"><span class="nav-dot" style="background:var(--text3)"></span>終端</div>
<div class="nav-item"><span class="nav-dot" style="background:var(--text3)"></span>設定</div>
</div>
</div>
<!-- ═══ CONTENT AREA ═══ -->
<div class="content">
<!-- Title Bar -->
<div class="title-bar">
<span class="page-title">AI中心</span>
<div class="title-actions">
<div class="ai-status"><span class="ai-dot"></span>OpenClaw · openclaw_nemo</div>
<button class="lang-btn on"></button>
<button class="lang-btn">EN</button>
<div class="avatar">OG</div>
</div>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<div class="tab on">戰情總覽</div>
<div class="tab">告警 & 授權 <span class="tab-badge">2</span></div>
<div class="tab">活動串流</div>
<div class="tab">處置統計</div>
</div>
<!-- 龍蝦游泳列 -->
<div class="chibi-strip">
<div class="chibi-swim"><div class="chibi-bob">
<svg width="16" height="12" viewBox="0 0 18 14" fill="none"><ellipse cx="9" cy="10" rx="5" ry="4" fill="#E85530" opacity=".9"/><circle cx="9" cy="6" r="3.5" fill="#E85530" opacity=".9"/><circle cx="7.5" cy="5.2" r=".9" fill="#fff" opacity=".8"/><circle cx="10.5" cy="5.2" r=".9" fill="#fff" opacity=".8"/><path d="M3 8.5Q.5 7.5 1 10Q1.5 11.5 3.5 11" stroke="#E85530" stroke-width="1.2" fill="none" stroke-linecap="round"/><ellipse cx="1" cy="10" rx="1.2" ry="1.5" fill="#E85530" opacity=".7" transform="rotate(-10 1 10)"/><path d="M15 8.5Q17.5 7.5 17 10Q16.5 11.5 14.5 11" stroke="#E85530" stroke-width="1.2" fill="none" stroke-linecap="round"/><ellipse cx="17" cy="10" rx="1.2" ry="1.5" fill="#E85530" opacity=".7" transform="rotate(10 17 10)"/><path d="M6.5 2.5Q5 .5 3.5 1" stroke="#b03a1a" stroke-width=".8" fill="none" stroke-linecap="round"/><path d="M11.5 2.5Q13 .5 14.5 1" stroke="#b03a1a" stroke-width=".8" fill="none" stroke-linecap="round"/></svg>
</div></div>
</div>
<!-- KPI Strip (卡片式,融入背景) -->
<div class="kpi-strip">
<div class="kpi-card"><div class="kpi-label">系統健康</div><div class="kpi-row"><span class="kpi-val" style="color:var(--green)">98.5%</span></div><div class="kpi-bar"><div class="kpi-bar-f" style="width:98.5%;background:var(--green)"></div></div></div>
<div class="kpi-card"><div class="kpi-label">活動事件</div><div class="kpi-row"><span class="kpi-val" style="color:var(--accent)">2</span><span class="kpi-sub">P1:1 P2:1</span></div></div>
<div class="kpi-card"><div class="kpi-label">自動修復率</div><div class="kpi-row"><span class="kpi-val" style="color:var(--green)">72%</span><span class="kpi-trend" style="color:var(--green)">↑5%</span></div><div class="kpi-bar"><div class="kpi-bar-f" style="width:72%;background:linear-gradient(90deg,var(--green),#4ade80)"></div></div></div>
<div class="kpi-card"><div class="kpi-label">待審批</div><div class="kpi-row"><span class="kpi-val" style="color:var(--orange)">3</span><span class="kpi-sub">等待決策</span></div></div>
<div class="kpi-card"><div class="kpi-label">本週操作</div><div class="kpi-row"><span class="kpi-val">1,245</span></div></div>
</div>
<!-- ═══ MAIN BODY ═══ -->
<div class="main-body">
<!-- ═══ LEFT COLUMN ═══ -->
<div class="col-left">
<!-- 活躍事件 -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">活躍事件</span>
<span style="font-size:11px;background:rgba(217,119,87,.1);color:#a04010;padding:2px 8px;font-weight:700;border:.5px solid rgba(217,119,87,.25);border-radius:10px">2</span>
<span class="card-action">查看全部告警 →</span>
</div>
<div class="card-body">
<!-- Incident 1: P1 進度條 -->
<div class="inc">
<div class="inc-bar" style="background:var(--orange)"></div>
<div class="inc-body">
<div class="inc-top">
<span class="inc-sev" style="background:rgba(245,158,11,.12);color:#d97000">P1</span>
<span class="inc-name">重新探測 #10exiconFast: 通過</span>
</div>
<div class="inc-meta">awoooi-api @ awoooi-prod · 3 alerts · investigating</div>
<!-- P1 FlowPipeline: 進度條 + 龍蝦 -->
<div style="position:relative;height:54px;margin:4px 0">
<div style="position:absolute;bottom:16px;left:0;right:0;height:4px;background:#e8e5dc;border-radius:2px"></div>
<div style="position:absolute;bottom:16px;left:0;height:4px;background:#F59E0B;border-radius:2px;width:43%"></div>
<div style="position:absolute;bottom:0;left:0%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#F59E0B;margin:0 auto"></div><div style="font-size:9px;color:#F59E0B;margin-top:2px">告警</div></div>
<div style="position:absolute;bottom:0;left:16.7%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#F59E0B;margin:0 auto"></div><div style="font-size:9px;color:#F59E0B;margin-top:2px">偵測</div></div>
<div style="position:absolute;bottom:0;left:33.3%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#F59E0B;margin:0 auto"></div><div style="font-size:9px;color:#F59E0B;margin-top:2px">分析</div></div>
<div style="position:absolute;bottom:0;left:50%;transform:translateX(-50%);text-align:center"><div style="animation:lobster-bob 1.5s ease-in-out infinite;margin-bottom:2px"><svg width="14" height="16" viewBox="0 0 18 20" fill="none"><ellipse cx="9" cy="13" rx="5.5" ry="6.5" fill="#F59E0B"/><circle cx="9" cy="7.5" r="4.5" fill="#F59E0B"/><circle cx="7" cy="6.5" r="1" fill="#b03a1a"/><circle cx="11" cy="6.5" r="1" fill="#b03a1a"/></svg></div><div style="width:8px;height:8px;border-radius:50%;background:#fff;border:2px solid #F59E0B;margin:0 auto"></div><div style="font-size:9px;color:var(--text);font-weight:700;margin-top:2px">提案</div></div>
<div style="position:absolute;bottom:0;left:66.7%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#f8f9fc;border:1.5px solid #e0ddd4;margin:0 auto"></div><div style="font-size:9px;color:var(--text3);margin-top:2px">授權</div></div>
<div style="position:absolute;bottom:0;left:83.3%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#f8f9fc;border:1.5px solid #e0ddd4;margin:0 auto"></div><div style="font-size:9px;color:var(--text3);margin-top:2px">執行</div></div>
<div style="position:absolute;bottom:0;left:100%;transform:translateX(-50%);text-align:center"><div style="height:20px"></div><div style="width:8px;height:8px;border-radius:50%;background:#f8f9fc;border:1.5px solid #e0ddd4;margin:0 auto"></div><div style="font-size:9px;color:var(--text3);margin-top:2px">完成</div></div>
</div>
<div class="ai-proposal">▶ AI 提案restart_deployment awoooi-api (信心度 91%)</div>
<div class="inc-actions">
<button class="btn-approve">批准執行</button>
<button class="btn-reject">拒絕</button>
</div>
</div>
</div>
<!-- Incident 2: P2 卡片步驟 -->
<div class="inc">
<div class="inc-bar" style="background:var(--blue)"></div>
<div class="inc-body">
<div class="inc-top">
<span class="inc-sev" style="background:rgba(74,144,217,.12);color:var(--blue)">P2</span>
<span class="inc-name">awoooi-api: 服務異常</span>
</div>
<div class="inc-meta">awoooi-api @ awoooi-prod · investigating</div>
<!-- P2 FlowPipeline: 卡片步驟 + 光暈 -->
<div style="display:flex;align-items:flex-end;gap:3px;margin:4px 0;overflow-x:auto">
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#4A90D9;border-radius:4px"><span style="font-size:9px;color:#fff;font-weight:700">告警</span></div></div>
<div style="width:6px;height:1.5px;background:#4A90D9;margin-bottom:10px"></div>
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#4A90D9;border-radius:4px"><span style="font-size:9px;color:#fff;font-weight:700">偵測</span></div></div>
<div style="width:6px;height:1.5px;background:#e0ddd4;margin-bottom:10px"></div>
<div style="text-align:center"><div style="animation:lobster-bob 1.5s ease-in-out infinite"><svg width="14" height="16" viewBox="0 0 18 20" fill="none"><ellipse cx="9" cy="13" rx="5.5" ry="6.5" fill="#4A90D9"/><circle cx="9" cy="7.5" r="4.5" fill="#4A90D9"/><circle cx="7" cy="6.5" r="1" fill="#1a4a7a"/><circle cx="11" cy="6.5" r="1" fill="#1a4a7a"/></svg></div><div style="padding:3px 5px;background:#fff;border:1.5px solid #4A90D9;border-radius:4px;animation:card-glow-p2 1.5s infinite"><span style="font-size:9px;color:#4A90D9;font-weight:700">分析</span></div></div>
<div style="width:6px;height:1.5px;background:#e0ddd4;margin-bottom:10px"></div>
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#f8f9fc;border:1px solid #e0ddd4;border-radius:4px"><span style="font-size:9px;color:#b0ad9f">提案</span></div></div>
<div style="width:6px;height:1.5px;background:#e0ddd4;margin-bottom:10px"></div>
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#f8f9fc;border:1px solid #e0ddd4;border-radius:4px"><span style="font-size:9px;color:#b0ad9f">授權</span></div></div>
<div style="width:6px;height:1.5px;background:#e0ddd4;margin-bottom:10px"></div>
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#f8f9fc;border:1px solid #e0ddd4;border-radius:4px"><span style="font-size:9px;color:#b0ad9f">執行</span></div></div>
<div style="width:6px;height:1.5px;background:#e0ddd4;margin-bottom:10px"></div>
<div style="text-align:center"><div style="height:20px"></div><div style="padding:3px 5px;background:#f8f9fc;border:1px solid #e0ddd4;border-radius:4px"><span style="font-size:9px;color:#b0ad9f">完成</span></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- 處置統計迷你版 -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">處置統計</span>
<span class="card-action">查看完整報表 →</span>
</div>
<div class="card-body">
<div class="disp-mini">
<!-- 環形圖 SVG -->
<div class="disp-ring">
<svg width="56" height="56" viewBox="0 0 56 56">
<circle cx="28" cy="28" r="22" fill="none" stroke="#ebe8df" stroke-width="5"/>
<circle cx="28" cy="28" r="22" fill="none" stroke="var(--green)" stroke-width="5" stroke-dasharray="96.6 41.7" stroke-linecap="round"/>
<circle cx="28" cy="28" r="22" fill="none" stroke="var(--blue)" stroke-width="5" stroke-dasharray="3.5 134.8" stroke-dashoffset="-96.6" stroke-linecap="round"/>
<circle cx="28" cy="28" r="22" fill="none" stroke="var(--orange)" stroke-width="5" stroke-dasharray="30.5 107.8" stroke-dashoffset="-100.1" stroke-linecap="round"/>
<circle cx="28" cy="28" r="22" fill="none" stroke="var(--purple)" stroke-width="5" stroke-dasharray="8.1 130.2" stroke-dashoffset="-130.6" stroke-linecap="round"/>
</svg>
<div class="disp-ring-center">72%</div>
</div>
<div class="disp-list">
<div class="disp-item"><span class="disp-dot" style="background:var(--green)"></span>自動修復<span class="disp-num" style="color:var(--green)">142</span></div>
<div class="disp-item"><span class="disp-dot" style="background:var(--orange)"></span>人工核准<span class="disp-num" style="color:var(--orange)">45</span></div>
<div class="disp-item"><span class="disp-dot" style="background:var(--purple)"></span>手動處理<span class="disp-num" style="color:var(--purple)">12</span></div>
<div class="disp-item"><span class="disp-dot" style="background:var(--blue)"></span>冷啟動<span class="disp-num" style="color:var(--blue)">5</span></div>
</div>
</div>
</div>
</div>
<!-- 最近活動 -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">最近活動</span>
<span class="card-action">查看活動串流 →</span>
</div>
<div class="card-body" style="padding:10px 14px">
<div class="stream-item"><span class="stream-time">18:05</span><span class="stream-dot" style="background:var(--green)"></span><span class="stream-msg">心跳確認 <code>mon/mon1</code> Ready</span></div>
<div class="stream-item"><span class="stream-time">18:04</span><span class="stream-dot" style="background:var(--blue)"></span><span class="stream-msg"><b>OpenClaw</b> 匹配 Playbook <code>restart_worker</code> (91%)</span></div>
<div class="stream-item"><span class="stream-time">18:02</span><span class="stream-dot" style="background:var(--red)"></span><span class="stream-msg"><b>Prometheus</b> Worker CPU 89%</span></div>
<div class="stream-item"><span class="stream-time">17:58</span><span class="stream-dot" style="background:var(--green)"></span><span class="stream-msg">自動修復完成 <code>restart: api</code> (12s)</span></div>
</div>
</div>
</div>
<!-- ═══ RIGHT COLUMN (480px) ═══ -->
<div class="col-right">
<!-- OpenClaw 認知引擎 (最上方,品牌錨點) -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">OPENCLAW 認知引擎</span>
</div>
<div class="card-body">
<div class="oc-body">
<svg width="68" height="68" viewBox="0 0 140 140" fill="none" style="flex-shrink:0">
<defs><linearGradient id="oc-c" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#FFF"/><stop offset="40%" stop-color="#F8F8F8"/><stop offset="70%" stop-color="#E8E8E8"/><stop offset="100%" stop-color="#D8D8D8"/></linearGradient><radialGradient id="oc-l" cx="40%" cy="35%" r="60%"><stop offset="0%" stop-color="#7AB8F5"/><stop offset="100%" stop-color="#2B6CB0"/></radialGradient></defs>
<circle cx="70" cy="70" r="32" fill="url(#oc-c)" stroke="#E0E0E0" stroke-width="1"/><circle cx="70" cy="70" r="16" fill="url(#oc-l)"><animate attributeName="r" values="14;17;14" dur="2s" repeatCount="indefinite"/></circle><circle cx="70" cy="70" r="8" fill="white" opacity=".8"/>
<path d="M70 38L70 18L58 6M70 18L82 6" stroke="url(#oc-c)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M70 38L70 18L58 6M70 18L82 6" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M38 70L18 70L6 58M18 70L6 82" stroke="url(#oc-c)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M38 70L18 70L6 58M18 70L6 82" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M102 70L122 70L134 58M122 70L134 82" stroke="url(#oc-c)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M102 70L122 70L134 58M122 70L134 82" stroke="#4A90D9" stroke-width="3" stroke-linecap="round" fill="none" opacity=".5"/>
<path d="M48 92L28 112L16 116" stroke="url(#oc-c)" stroke-width="6" stroke-linecap="round" fill="none"/><path d="M92 92L112 112L124 116" stroke="url(#oc-c)" stroke-width="6" stroke-linecap="round" fill="none"/>
<circle cx="70" cy="70" r="42" fill="none" stroke="#4A90D9" stroke-width="1" stroke-dasharray="6 6" opacity=".3"><animateTransform attributeName="transform" type="rotate" from="0 70 70" to="360 70 70" dur="8s" repeatCount="indefinite"/></circle>
</svg>
<div class="oc-info">
<div class="oc-brand"><span class="w">W</span><span class="o">ooo</span><span class="c">Claw</span></div>
<div><div class="oc-badge">WoooClaw Pipeline</div></div>
<div class="oc-status">[AGENT] patrolling... <span class="oc-pulse"><span></span><span></span><span></span></span></div>
<!-- 豐富內容: AI 即時狀態 -->
<div style="margin-top:8px;padding-top:8px;border-top:.5px solid var(--bdr)">
<div style="display:flex;gap:8px;margin-bottom:4px">
<div style="flex:1;font-size:10px;color:var(--text2)">模型: <span style="font-weight:600;color:var(--text)">openclaw_nemo</span></div>
<div style="font-size:10px;color:var(--green);font-weight:500">● 運行中</div>
</div>
<div style="display:flex;gap:12px;font-size:10px;color:var(--text2)">
<span>今日分析: <b style="color:var(--text)">23</b></span>
<span>成功率: <b style="color:var(--green)">91%</b></span>
<span>MTTR: <b style="color:var(--text)">8.2m</b></span>
</div>
<!-- AI 推理終端 -->
<div style="background:#141413;border-radius:6px;padding:8px 10px;margin-top:8px;font-family:'JetBrains Mono',monospace;font-size:10px;color:#a0e8a0;line-height:1.6;max-height:80px;overflow-y:auto">
<span style="color:#555">[18:03]</span> Analyzing worker CPU spike...
<span style="color:#555">[18:03]</span> Root cause: OOM pressure
<span style="color:#555">[18:03]</span> Matched: restart_worker (91%)
<span style="color:#ffd700">[18:03] Awaiting approval ▎</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 待審批任務 -->
<div class="card" style="border-color:rgba(249,115,22,.3)">
<div class="card-header" style="background:rgba(249,115,22,.04)">
<div class="card-dot" style="background:var(--orange)"></div>
<span class="card-title">待審批任務</span>
<span style="font-size:11px;background:rgba(249,115,22,.1);color:var(--orange);padding:2px 8px;font-weight:700;border-radius:10px">3</span>
<span class="card-action">查看全部授權 →</span>
</div>
<div class="card-body">
<div class="appr-item">
<div class="appr-alert" style="color:var(--red)">Worker 高負載警告</div>
<div class="appr-target">ssh://wooo@192.168.0.110/restart</div>
<span class="appr-risk risk-low">LOW RISK</span>
<div class="appr-btns"><button class="btn-sm-ok">批准</button><button class="btn-sm-no">拒絕</button></div>
</div>
<div class="appr-item">
<div class="appr-alert" style="color:var(--orange)">Redis 記憶體壓力</div>
<div class="appr-target">ansible://188/clear_redis_cache.yml</div>
<span class="appr-risk risk-med">MEDIUM</span>
<div class="appr-btns"><button class="btn-sm-ok">批准</button><button class="btn-sm-no">拒絕</button></div>
</div>
</div>
</div>
<!-- 拓撲 / 主機 Toggle -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">基礎架構</span>
<div style="margin-left:auto"><div class="toggle-bar"><div class="toggle-opt" id="t-host" onclick="switchView('host')">主機</div><div class="toggle-opt on" id="t-topo" onclick="switchView('topo')">拓撲</div></div></div>
<span class="card-action" style="margin-left:8px">展開全圖 →</span>
</div>
<div class="card-body" id="view-topo">
<div class="topo-grid">
<div class="topo-g tg-infra"><div class="tg-name">🏗️ 基礎設施 (.110)</div><div class="tg-meta">7 服務 · ✓ 全部健康</div><div class="tg-svcs"><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Gitea</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Harbor</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Sentry</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Prom</span></div></div>
<div class="topo-g tg-ai"><div class="tg-name">🧠 AI/數據 (.188)</div><div class="tg-meta">7 服務 · ⚡ OpenClaw 診斷中</div><div class="tg-svcs"><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>PG</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Redis</span><span class="tg-svc" style="border-color:var(--blue)"><span class="tg-sdot" style="background:var(--blue)"></span>OpenClaw⚡</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Ollama</span></div></div>
<div class="topo-g tg-k3s"><div class="tg-name">☸️ K3s 叢集</div><div class="tg-meta">5 服務 · ⚠️ Worker CPU 89%</div><div class="tg-svcs"><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>api×2</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>web×2</span><span class="tg-svc" style="border-color:var(--orange)"><span class="tg-sdot" style="background:var(--orange)"></span>worker⚠</span></div></div>
<div class="topo-g tg-ext"><div class="tg-name">🌐 外部服務</div><div class="tg-meta">3 服務 · ✓ 全部可達</div><div class="tg-svcs"><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>Gemini</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>NVIDIA</span><span class="tg-svc"><span class="tg-sdot" style="background:var(--green)"></span>CF</span></div></div>
</div>
</div>
<div class="card-body" id="view-host" style="display:none">
<div class="host-grid">
<div class="host-card"><div class="host-name">DevOps 金庫</div><div class="host-ip">192.168.0.110</div><div class="host-bars"><div class="host-bar-w"><div class="host-bar-l"><span>CPU</span><span>35%</span></div><div class="host-bar"><div class="host-bar-f" style="width:35%;background:var(--green)"></div></div></div><div class="host-bar-w"><div class="host-bar-l"><span>RAM</span><span>55%</span></div><div class="host-bar"><div class="host-bar-f" style="width:55%;background:var(--green)"></div></div></div></div></div>
<div class="host-card"><div class="host-name">AI+Web 中心</div><div class="host-ip">192.168.0.188</div><div class="host-bars"><div class="host-bar-w"><div class="host-bar-l"><span>CPU</span><span>67%</span></div><div class="host-bar"><div class="host-bar-f" style="width:67%;background:var(--orange)"></div></div></div><div class="host-bar-w"><div class="host-bar-l"><span>RAM</span><span>72%</span></div><div class="host-bar"><div class="host-bar-f" style="width:72%;background:var(--orange)"></div></div></div></div></div>
<div class="host-card"><div class="host-name">K3s Master</div><div class="host-ip">192.168.0.120</div><div class="host-bars"><div class="host-bar-w"><div class="host-bar-l"><span>CPU</span><span>45%</span></div><div class="host-bar"><div class="host-bar-f" style="width:45%;background:var(--green)"></div></div></div><div class="host-bar-w"><div class="host-bar-l"><span>RAM</span><span>60%</span></div><div class="host-bar"><div class="host-bar-f" style="width:60%;background:var(--green)"></div></div></div></div></div>
<div class="host-card"><div class="host-name">K3s Worker</div><div class="host-ip">192.168.0.121</div><div class="host-bars"><div class="host-bar-w"><div class="host-bar-l"><span>CPU</span><span>--</span></div><div class="host-bar"><div class="host-bar-f" style="width:0%"></div></div></div><div class="host-bar-w"><div class="host-bar-l"><span>RAM</span><span>--</span></div><div class="host-bar"><div class="host-bar-f" style="width:0%"></div></div></div></div></div>
</div>
</div>
</div>
<!-- AI 模型狀態 -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">AI 模型狀態</span>
</div>
<div class="card-body">
<div class="model-grid">
<div class="model"><span class="model-dot" style="background:var(--green)"></span><span class="model-name">OpenClaw Nemo</span><span class="model-tag">local</span></div>
<div class="model"><span class="model-dot" style="background:var(--green)"></span><span class="model-name">Ollama qwen2.5</span><span class="model-tag">local</span></div>
<div class="model"><span class="model-dot" style="background:var(--green)"></span><span class="model-name">Gemini Pro</span><span class="model-tag">cloud</span></div>
<div class="model"><span class="model-dot" style="background:var(--green)"></span><span class="model-name">NVIDIA NIM</span><span class="model-tag">cloud</span></div>
</div>
</div>
</div>
<!-- 監控工具 -->
<div class="card">
<div class="card-header">
<div class="card-dot"></div>
<span class="card-title">監控工具</span>
</div>
<div class="card-body">
<div class="tool-grid">
<div class="tool"><div class="tool-bar" style="background:#4A90D9"></div><div class="tool-body"><div class="tool-name">SigNoz</div><div class="tool-meta">Traces · Logs</div></div></div>
<div class="tool"><div class="tool-bar" style="background:#E85530"></div><div class="tool-body"><div class="tool-name">Grafana</div><div class="tool-meta">3 Dashboards</div></div></div>
<div class="tool"><div class="tool-bar" style="background:var(--green)"></div><div class="tool-body"><div class="tool-name">Prometheus</div><div class="tool-meta">22 targets</div></div></div>
<div class="tool"><div class="tool-bar" style="background:var(--orange)"></div><div class="tool-body"><div class="tool-name">Langfuse</div><div class="tool-meta">LLMOps</div></div></div>
<div class="tool"><div class="tool-bar" style="background:var(--red)"></div><div class="tool-body"><div class="tool-name">Sentry</div><div class="tool-meta">2 Projects</div></div></div>
<div class="tool"><div class="tool-bar" style="background:var(--purple)"></div><div class="tool-body"><div class="tool-name">Gitea</div><div class="tool-meta">CI/CD</div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Terminal Float -->
<div class="terminal-float">⌨ Omni-Terminal</div>
<script>
function switchView(v){
document.getElementById('view-host').style.display=v==='host'?'block':'none'
document.getElementById('view-topo').style.display=v==='topo'?'block':'none'
document.getElementById('t-host').classList.toggle('on',v==='host')
document.getElementById('t-topo').classList.toggle('on',v==='topo')
}
</script>
</body>
</html>