:root { --bg:#f6f7f9; --card:#fff; --line:#e3e6ea; --text:#1f2328; --muted:#6b7280; --pri:#2563eb; --ok:#15803d; --bad:#b91c1c; --warn:#b45309; }
* { box-sizing:border-box; }
body { margin:0; background:var(--bg); color:var(--text); font:15px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,"PingFang SC","Noto Sans CJK SC",sans-serif; }
main { max-width:1180px; margin:16px auto; padding:0 16px; }
header.top { display:flex; align-items:center; gap:24px; padding:10px 20px; background:#111827; color:#fff; }
header .brand { color:#fff; font-weight:600; text-decoration:none; }
header nav a { color:#cbd5e1; text-decoration:none; margin-right:14px; padding:4px 0; }
header nav a.on, header nav a:hover { color:#fff; border-bottom:2px solid #60a5fa; }
header .me { margin-left:auto; color:#cbd5e1; display:flex; gap:12px; align-items:center; }
header .me a { color:#cbd5e1; }
footer { max-width:1180px; margin:24px auto; padding:8px 16px; color:var(--muted); font-size:13px; display:flex; gap:18px; border-top:1px solid var(--line); }
h2 { margin:8px 0 12px; font-size:22px; } h3 { margin:14px 0 8px; font-size:16px; }
a { color:var(--pri); }
.card { background:var(--card); border:1px solid var(--line); border-radius:8px; padding:16px 18px; margin:12px 0; }
.card.narrow { max-width:460px; margin:48px auto; }
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:10px 24px; } .grid3 { display:grid; grid-template-columns:repeat(3,1fr); gap:10px 24px; }
@media (max-width:800px) { .grid2,.grid3 { grid-template-columns:1fr; } }
label { display:block; margin:8px 0; font-size:14px; color:#374151; }
label.inline { display:inline-block; margin-right:12px; }
input:not([type=checkbox]), select, textarea { display:block; width:100%; margin-top:4px; padding:7px 9px; border:1px solid #cbd5e1; border-radius:6px; font:inherit; background:#fff; }
input.path { width:220px; display:inline-block; } input.wide { width:420px; display:inline-block; }
label.inline input[type=checkbox] { margin-right:6px; }
button, .btn { display:inline-block; padding:7px 14px; border:1px solid #cbd5e1; border-radius:6px; background:#fff; color:var(--text); font:inherit; cursor:pointer; text-decoration:none; }
button.primary { background:var(--pri); border-color:var(--pri); color:#fff; }
button.danger, .btn.danger { color:var(--bad); border-color:#fca5a5; }
button.small, .btn.small { padding:3px 9px; font-size:13px; }
button.link { border:0; background:none; color:#cbd5e1; padding:0; cursor:pointer; }
form.inline { display:inline; } details.inline { display:inline-block; }
details summary { list-style:none; cursor:pointer; } details form.confirm { margin-top:6px; }
table { width:100%; border-collapse:collapse; background:var(--card); border:1px solid var(--line); border-radius:8px; }
th, td { text-align:left; padding:8px 10px; border-bottom:1px solid var(--line); vertical-align:top; font-size:14px; }
thead th { background:#f3f4f6; font-weight:600; }
table.plain, table.plain td, table.plain th { border:0; background:none; }
table.kv th { width:90px; color:var(--muted); font-weight:500; }
td.actions form, td.actions details, td.actions a { margin-right:4px; }
pre { background:#0f172a; color:#e2e8f0; padding:10px 12px; border-radius:6px; overflow:auto; font-size:13px; }
pre.logs { max-height:480px; } pre.big { font-size:20px; text-align:center; }
code { background:#eef2f7; padding:1px 4px; border-radius:4px; font-size:13px; }
pre code { background:none; }
.row { display:flex; gap:12px; align-items:center; flex-wrap:wrap; } .row.between { justify-content:space-between; }
.muted { color:var(--muted); } .ok { color:var(--ok); } .bad { color:var(--bad); }
.note { background:#fffbeb; border:1px solid #fde68a; color:#78350f; padding:8px 12px; border-radius:6px; margin:10px 0; font-size:14px; }
.flash { padding:9px 14px; margin:10px auto; max-width:1148px; border-radius:6px; }
.flash.ok { background:#ecfdf5; border:1px solid #a7f3d0; color:#065f46; }
.flash.error { background:#fef2f2; border:1px solid #fecaca; color:#991b1b; }
.flash.info { background:#eff6ff; border:1px solid #bfdbfe; color:#1e3a8a; }
.banner.err { background:#7f1d1d; color:#fff; padding:8px 20px; } .banner span { margin-left:12px; }
.tag { display:inline-block; padding:1px 8px; border-radius:10px; font-size:12px; background:#e5e7eb; }
.tag.running { background:#dcfce7; color:#166534; } .tag.queued, .tag.scheduling, .tag.starting, .tag.installing, .tag.submitted { background:#fef3c7; color:#92400e; }
.tag.failed { background:#fee2e2; color:#991b1b; } .tag.succeeded { background:#dbeafe; color:#1e40af; } .tag.deleting { background:#e5e7eb; }
textarea { font-family:ui-monospace,Menlo,monospace; }
/* ---- 处理中动画 / 进度条 / 统计卡片 ---- */
.spin { display:inline-block; width:14px; height:14px; border:2px solid rgba(255,255,255,.4); border-top-color:#fff; border-radius:50%; animation:spin .7s linear infinite; vertical-align:-2px; margin-right:6px; }
.spin.dark { border-color:#cbd5e1; border-top-color:#2563eb; } .spin.tiny { width:10px; height:10px; border-width:2px; margin-right:4px; }
@keyframes spin { to { transform:rotate(360deg); } }
button.busy, .btn.busy { opacity:.75; cursor:progress; }
button.danger.busy .spin, button:not(.primary):not(.danger).busy .spin { border-color:#cbd5e1; border-top-color:#1f2328; }
.htmx-request .htmx-indicator { display:inline-block; }
button.ok { color:var(--ok); border-color:#86efac; }
.bar { height:8px; background:#e5e7eb; border-radius:4px; overflow:hidden; min-width:80px; }
.bar i { display:block; height:100%; background:#2563eb; border-radius:4px; } .bar i.full { background:#dc2626; }
.cards { display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); gap:12px; }
.card.stat { margin:0; } .card.stat .big { font-size:30px; font-weight:600; margin:4px 0 8px; } .card.stat .big small { font-size:13px; font-weight:400; color:var(--muted); }
.card.center { text-align:center; padding:40px; }
table.tight th, table.tight td { padding:5px 8px; } td.w40, th.w40 { width:40%; } .nowrap { white-space:nowrap; }
.warn { color:var(--warn); }
/* ---- 隧道建立中的跳动点 / 加减行 / 容量单位 ---- */
.dots { display:inline-block; margin-left:2px; }
.dots i { display:inline-block; width:4px; height:4px; margin-left:3px; border-radius:50%; background:currentColor; animation:blink 1.2s infinite; vertical-align:1px; }
.dots i:nth-child(2) { animation-delay:.2s; } .dots i:nth-child(3) { animation-delay:.4s; }
@keyframes blink { 0%,80%,100% { opacity:.15; } 40% { opacity:1; } }
table.rows td { padding:3px 4px; } table.rows td.narrow { width:90px; } table.rows input, table.rows select { margin-top:0; }
input.num { width:140px; display:inline-block; } select.unit { width:80px; display:inline-block; margin-left:6px; }
button.ghost { background:#f3f4f6; color:#374151; border-color:#d1d5db; margin-left:8px; }
.tplbar { display:flex; gap:14px; align-items:center; flex-wrap:wrap; padding:10px 18px; }
.tplbar label.inline { margin:0; } select.inline-sel { display:inline-block; width:auto; min-width:220px; margin:0 0 0 6px; }
h3.mt { margin-top:28px; }
.btn.vscode { background:#0b6fcf; border-color:#0b6fcf; color:#fff; } .small-note { font-size:12px; }
/* ---- 连接列：复制图标 + 迷你下拉 + 连接按钮 ---- */
td.conn { line-height:1.35; }
button.icon { padding:1px 5px; border:1px solid #cbd5e1; border-radius:5px; background:#fff; color:#52514e; vertical-align:-3px; margin-left:6px; line-height:1; cursor:pointer; }
button.icon:hover { background:#eef2f7; color:#1f2328; } button.icon.ok { color:var(--ok); border-color:#86efac; }
.connrow { display:inline-flex; gap:4px; align-items:center; margin-top:3px; }
select.mini { display:inline-block; width:auto; margin:0; padding:2px 22px 2px 6px; font-size:12px; height:24px; border-radius:5px; }
.connrow button.small { padding:2px 9px; font-size:12px; height:24px; }
/* ---- 任务监控：统计卡片 + ECharts ---- */
.cards.tiles { grid-template-columns:repeat(auto-fill, minmax(170px, 1fr)); margin-bottom:12px; }
.card.stat .big small { margin-left:3px; } .small { font-size:12px; }
.charts { display:grid; grid-template-columns:repeat(auto-fit, minmax(320px, 1fr)); gap:12px; }
.chart-box { height:230px; background:#fcfcfb; border:1px solid var(--line); border-radius:8px; }
button.small.on { background:#e5e7eb; }
td.narrow2 { width:260px; } table.mounts select { margin-top:0; }
/* ---- 设置 ---- */
header .me a.gear { display:inline-flex; align-items:center; gap:5px; padding:4px 10px; border:1px solid #374151; border-radius:6px; color:#e5e7eb; text-decoration:none; }
header .me a.gear:hover, header .me a.gear.on { background:#1f2937; color:#fff; }
hr.sep { border:0; border-top:1px solid var(--line); margin:16px 0; }
.evs { margin:8px 0 10px; } .evs label.inline { margin:4px 14px 4px 0; font-size:13px; }
/* 醒目的主操作按钮（任务状态页「启动任务」） */
.btn.cta { background:#2563eb; border-color:#2563eb; color:#fff; font-weight:600; box-shadow:0 1px 2px rgba(37,99,235,.35); }
.btn.cta:hover { background:#1d4ed8; border-color:#1d4ed8; }
.big-line { font-size:16px; margin:6px 0; }
