-
-
-
+
+
+
+
-
⌁协议工作区已就绪
连接标准 Teamserver 后,Capability 将驱动此处的操作和结果视图。
+
-
+
);
diff --git a/src/styles.css b/src/styles.css
index 7a94407..f471353 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -1,56 +1,90 @@
-:root { font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif; color: #292724; background: #f7f6f3; font-synthesis: none; }
+:root {
+ font-family: Inter, "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+ color: #e7eaf0; background: #0f1115; font-synthesis: none; font-size: 13px;
+ --app: #0f1115; --nav: #14171c; --content: #181c22; --hover: #20252d;
+ --selected: #27313d; --border: #2a3039; --text: #e7eaf0; --muted: #929aa8;
+ --online: #38b57a; --warning: #d9a441; --error: #e05b63; --info: #4c8dda;
+}
* { box-sizing: border-box; }
-body { margin: 0; min-width: 900px; min-height: 100vh; }
-button, input { font: inherit; }
-button { color: inherit; }
-.shell { display: grid; grid-template-columns: 56px 250px 1fr; min-height: 100vh; }
-.server-rail { background: #181817; padding: 12px 8px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
-.brand { width: 36px; height: 36px; display: grid; place-items: center; color: #111; background: #f1e65d; border-radius: 10px; font-weight: 900; margin-bottom: 8px; }
-.server-button { position: relative; width: 38px; height: 38px; border: 0; border-radius: 10px; background: #353432; color: #d9d7d2; font-size: 11px; cursor: pointer; }
-.server-button:hover, .server-button.active { background: #ece9df; color: #171716; }
-.server-button.active::before { content: ""; position: absolute; width: 3px; height: 24px; background: #f1e65d; left: -8px; top: 7px; border-radius: 2px; }
-.server-button.add { color: #aaa; font-size: 22px; background: transparent; border: 1px dashed #555; }
-.presence { position: absolute; width: 9px; height: 9px; border: 2px solid #181817; border-radius: 50%; right: -2px; bottom: -2px; background: #47b881; }
-.presence.degraded { background: #e8a441; }
-.badge { position: absolute; min-width: 16px; height: 16px; padding: 0 4px; line-height: 16px; background: #d85b53; color: white; border-radius: 9px; right: -7px; top: -7px; font-size: 9px; }
-.project-sidebar { background: #eeece7; border-right: 1px solid #dedbd4; display: flex; flex-direction: column; padding: 20px 14px 10px; }
-.project-sidebar header { padding: 0 6px 14px; }
-.eyebrow { color: #8b8881; font-size: 10px; font-weight: 700; letter-spacing: .12em; margin: 0 0 5px; }
-h1 { font-size: 16px; margin: 0 0 8px; }
-.connection { font-size: 9px; font-weight: 800; color: #36865d; background: #dbeadd; border-radius: 4px; padding: 3px 6px; }
-.connection.degraded { color: #9b6b21; background: #f3e4c9; }
-.search { display: flex; align-items: center; gap: 7px; margin: 8px 4px 18px; padding: 7px 8px; border: 1px solid #d5d2cb; border-radius: 6px; background: #f8f7f4; color: #7c7973; }
-.search input { min-width: 0; width: 100%; border: 0; outline: 0; background: transparent; }
-kbd { font-size: 9px; white-space: nowrap; }
+body { margin: 0; min-width: 900px; min-height: 100vh; background: var(--app); }
+button, input { font: inherit; color: inherit; }
+button { cursor: pointer; }
+button:focus-visible, input:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--info); outline-offset: -2px; }
+.shell { display: grid; grid-template-columns: 52px 260px 1fr; min-height: 100vh; background: var(--app); }
+.server-rail { background: #101318; border-right: 1px solid var(--border); padding: 10px 7px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
+.brand { width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid #3a414c; border-radius: 5px; color: var(--text); background: #1b2027; font: 700 14px ui-monospace, "JetBrains Mono", monospace; margin-bottom: 9px; }
+.server-button { position: relative; width: 36px; height: 36px; border: 1px solid transparent; border-radius: 5px; background: #1b2027; color: #a9b0bc; font: 600 10px ui-monospace, "JetBrains Mono", monospace; transition: background 100ms ease, border-color 100ms ease; }
+.server-button:hover { background: var(--hover); border-color: #343c47; color: var(--text); }
+.server-button.active { background: var(--selected); border-color: #3c4959; color: var(--text); }
+.server-button.active::before { content: ""; position: absolute; width: 2px; height: 22px; background: var(--info); left: -8px; top: 6px; border-radius: 1px; }
+.server-button.add { color: var(--muted); font-size: 18px; background: transparent; border: 1px dashed #3a414c; }
+.presence { position: absolute; width: 8px; height: 8px; border: 2px solid #101318; border-radius: 50%; right: -3px; bottom: -3px; background: var(--online); }
+.presence.degraded { background: var(--warning); }
+.badge { position: absolute; min-width: 16px; height: 16px; padding: 0 4px; line-height: 16px; background: var(--error); color: white; border-radius: 8px; right: -7px; top: -7px; font: 600 9px ui-monospace, monospace; }
+.project-sidebar { background: var(--nav); border-right: 1px solid var(--border); display: flex; flex-direction: column; padding: 18px 12px 9px; }
+.project-sidebar header { padding: 0 7px 13px; }
+.eyebrow { color: var(--muted); font-size: 10px; font-weight: 650; letter-spacing: .1em; margin: 0 0 6px; }
+h1 { font-size: 14px; line-height: 20px; margin: 0 0 8px; font-weight: 600; }
+.connection { display: inline-flex; font: 600 9px ui-monospace, monospace; color: #82d5aa; background: #193128; border: 1px solid #28523e; border-radius: 4px; padding: 2px 5px; }
+.connection::before { content: "✓"; margin-right: 4px; }
+.connection.degraded { color: #e5bb67; background: #322a1d; border-color: #5a4727; }
+.connection.degraded::before { content: "!"; }
+.search, .table-toolbar label { display: flex; align-items: center; gap: 7px; border: 1px solid var(--border); border-radius: 4px; background: #111419; color: var(--muted); }
+.search { margin: 8px 1px 17px; padding: 6px 8px; }
+.search input, .table-toolbar input { min-width: 0; width: 100%; border: 0; outline: 0; background: transparent; }
+kbd { border: 1px solid #343b45; border-radius: 3px; padding: 1px 4px; font-size: 9px; white-space: nowrap; }
nav { display: flex; flex-direction: column; gap: 2px; }
-nav a { display: flex; justify-content: space-between; padding: 7px 10px; border-radius: 5px; color: #5e5b56; font-size: 13px; cursor: default; }
-nav a.selected { background: #dedbd4; color: #242321; font-weight: 600; }
-nav strong { color: #9b554e; }
-.nav-heading { margin: 20px 10px 5px; font-size: 10px; color: #85817b; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
-.memory-note { margin-top: auto; padding: 9px; font-size: 10px; color: #8a8780; }
-.workspace { display: grid; grid-template-rows: 39px 43px 1fr 24px; min-width: 0; height: 100vh; }
-.tabbar { display: flex; background: #e7e5e0; border-bottom: 1px solid #d6d3cc; overflow: hidden; }
-.tabbar button { max-width: 190px; border: 0; border-right: 1px solid #d7d4cd; background: transparent; padding: 0 11px; font-size: 11px; color: #74716c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.tabbar button.active { background: #f7f6f3; color: #292724; }
-.close { color: #aaa; margin-left: 15px; }
-.running { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: #e0a53b; margin-right: 7px; }
-.contextbar { border-bottom: 1px solid #e4e1da; padding: 13px 20px; font-size: 11px; color: #77736d; }
-.contextbar span { color: #bbb7af; padding: 0 7px; }
-.content { overflow: auto; padding: 40px max(40px, 7vw); }
-.content-heading { display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e1ded7; padding-bottom: 22px; }
-h2 { font-family: Georgia, serif; font-size: 30px; margin: 0; font-weight: 500; }
-.primary { border: 0; background: #272624; color: #fff; padding: 8px 13px; border-radius: 5px; font-size: 12px; }
-.notice { display: flex; gap: 12px; margin: 22px 0; padding: 14px; background: #edf3ec; border: 1px solid #d9e7d6; border-radius: 7px; font-size: 12px; }
-.notice > span { color: #4e8e5f; }
-.notice p { color: #686d66; margin: 4px 0 0; }
-.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
-.stats section { background: #fff; border: 1px solid #e3e0d9; border-radius: 7px; padding: 15px; }
-.stats p { margin: 0 0 9px; color: #8a8780; font-size: 11px; }
-.stats strong { font-size: 14px; }
-.empty-state { text-align: center; padding: 70px 20px; color: #8a8780; }
-.empty-state > span { font-size: 38px; color: #c3bfb7; }
-.empty-state h3 { color: #4d4a46; font-family: Georgia, serif; font-weight: 500; margin-bottom: 8px; }
-.empty-state p { font-size: 12px; }
-.statusbar { display: flex; gap: 24px; align-items: center; padding: 0 12px; color: #aaa69e; background: #262523; font-size: 9px; }
-.statusbar span:first-child { color: #70bd91; }
-@media (max-width: 1000px) { .shell { grid-template-columns: 52px 220px 1fr; } .content { padding: 30px; } }
+nav a { display: flex; justify-content: space-between; padding: 6px 9px; border-radius: 4px; color: #aab1bd; font-size: 12px; transition: background 100ms ease; }
+nav a:hover { background: var(--hover); }
+nav a.selected { background: var(--selected); color: var(--text); font-weight: 550; box-shadow: inset 2px 0 var(--info); }
+nav strong { color: #f1888f; font: 600 10px ui-monospace, monospace; }
+.nav-heading { margin: 18px 9px 5px; font-size: 10px; color: #737c89; font-weight: 650; text-transform: uppercase; letter-spacing: .08em; }
+.memory-note { margin-top: auto; padding: 9px; border-top: 1px solid var(--border); font-size: 10px; color: #727b88; }
+.workspace { display: grid; grid-template-rows: 38px 42px 1fr 24px; min-width: 0; height: 100vh; background: var(--content); }
+.tabbar { display: flex; background: #111419; border-bottom: 1px solid var(--border); overflow: hidden; }
+.tabbar button { min-width: 132px; max-width: 190px; border: 0; border-right: 1px solid var(--border); background: transparent; padding: 0 11px; font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: background 100ms ease; }
+.tabbar button:hover { background: var(--hover); color: #cbd0d8; }
+.tabbar button.active { background: var(--content); color: var(--text); box-shadow: inset 0 2px var(--info); }
+.close { color: #69717d; margin-left: 15px; }
+.running { display: inline-block; width: 6px; height: 6px; border-radius: 2px; background: var(--warning); margin-right: 7px; }
+.contextbar { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border); padding: 0 16px; font-size: 11px; color: var(--muted); background: #171b21; }
+.contextbar i { color: #515967; font-style: normal; }
+.contextbar b { color: #cdd2da; font: 500 11px ui-monospace, "JetBrains Mono", monospace; }
+.context-lock { color: #77a9e4; font: 650 9px ui-monospace, monospace; border-right: 1px solid var(--border); padding-right: 10px; margin-right: 2px; }
+.content { overflow: auto; padding: 22px 24px 30px; background: var(--content); }
+.content-heading { display: flex; align-items: center; justify-content: space-between; padding-bottom: 18px; }
+.content-heading h2 { font-size: 20px; line-height: 27px; margin: 0; font-weight: 600; letter-spacing: -.01em; }
+.content-heading p { margin: 3px 0 0; color: var(--muted); font-size: 11px; }
+.heading-actions { display: flex; gap: 7px; }
+.primary, .secondary, .table-toolbar button { border: 1px solid var(--border); border-radius: 4px; padding: 6px 9px; font-size: 11px; background: #1b2027; }
+.primary { border-color: #457dbd; background: #326ba9; color: #fff; }
+.primary:hover { background: #3d78b8; }
+.secondary:hover, .table-toolbar button:hover { background: var(--hover); }
+.table-toolbar { height: 40px; display: flex; align-items: center; gap: 6px; border: 1px solid var(--border); border-bottom: 0; padding: 5px 7px; background: #15191f; }
+.table-toolbar label { width: 220px; height: 28px; padding: 0 8px; }
+.table-toolbar button { height: 28px; padding: 0 8px; color: #aeb5c0; }
+.toolbar-spacer, .status-spacer { flex: 1; }
+.session-table { min-width: 880px; border: 1px solid var(--border); background: #15191f; }
+.table-row { display: grid; grid-template-columns: 34px 92px 104px minmax(150px, 1.3fr) 120px 130px 92px minmax(120px, 1fr) 34px; min-height: 36px; border-bottom: 1px solid #252b33; align-items: stretch; font-size: 12px; color: #cbd0d8; }
+.table-row > span, .table-row > strong, .table-row > button { display: flex; align-items: center; padding: 0 9px; min-width: 0; border-right: 1px solid #222831; }
+.table-row:hover { background: var(--hover); }
+.table-row.focused { background: #202a35; box-shadow: inset 2px 0 var(--info); }
+.table-head { position: sticky; top: -22px; z-index: 2; min-height: 30px; background: #111419; color: #78818e; font-size: 9px; font-weight: 650; letter-spacing: .04em; }
+.table-row b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; color: #dde1e7; }
+.table-row small { display: block; color: #7f8895; font-size: 10px; }
+.mono { font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; font-weight: 500; color: #9ec7f4; }
+.muted { color: var(--muted); }
+.status-mark { width: 7px; height: 7px; margin-right: 7px; border-radius: 2px; background: var(--online); }
+.status-mark.idle { background: var(--warning); }
+.status-mark.offline { background: #69717d; box-shadow: inset 0 0 0 1px #89919c; }
+.tags { gap: 4px; }
+.tags small { display: inline; padding: 2px 5px; border: 1px solid #343c47; border-radius: 3px; background: #1d2229; color: #a8b0bb; }
+.row-action { border: 0; background: transparent; color: #79818d; }
+.session-table > footer { display: flex; align-items: center; justify-content: flex-end; gap: 10px; height: 34px; padding: 0 8px; color: #7f8895; font-size: 10px; }
+.session-table > footer span:first-child { margin-right: auto; }
+.session-table > footer button { width: 24px; height: 22px; border: 1px solid var(--border); background: #1b2027; border-radius: 3px; color: var(--muted); }
+.statusbar { display: flex; gap: 20px; align-items: center; padding: 0 10px; border-top: 1px solid #2b323c; color: #78818d; background: #111419; font-size: 9px; }
+.statusbar span:first-child { color: #75c99c; }
+input[type="checkbox"] { accent-color: var(--info); width: 12px; height: 12px; }
+@media (max-width: 1050px) { .shell { grid-template-columns: 52px 230px 1fr; } .content { padding-inline: 16px; } .table-row { grid-template-columns: 34px 84px 96px minmax(140px, 1fr) 110px 120px 84px minmax(110px, 1fr) 34px; } }
+@media (prefers-reduced-motion: reduce) { * { transition-duration: 0.01ms !important; } }
diff --git a/src/test/setup.ts b/src/test/setup.ts
index f149f27..bb32bff 100644
--- a/src/test/setup.ts
+++ b/src/test/setup.ts
@@ -1 +1,5 @@
import "@testing-library/jest-dom/vitest";
+import { cleanup } from "@testing-library/react";
+import { afterEach } from "vitest";
+
+afterEach(cleanup);