claude-code-watch 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-watch",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Web-based real-time monitor for Claude Code.",
5
5
  "main": "./src/server/server.js",
6
6
  "bin": {
@@ -0,0 +1,474 @@
1
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
2
+
3
+ :root {
4
+ --bg: #111827;
5
+ --bg2: #1f2937;
6
+ --bg3: #374151;
7
+ --border: #4b5563;
8
+ --text: #d1d5db;
9
+ --dim: #6b7280;
10
+ --white: #f9fafb;
11
+ --purple: #7c3aed;
12
+ --purple2: #5b21b6;
13
+ --blue: #3b82f6;
14
+ --magenta: #c084fc;
15
+ --yellow: #fbbf24;
16
+ --yellow2: #92400e;
17
+ --green: #34d399;
18
+ --cyan: #22d3ee;
19
+ --red: #f87171;
20
+ --red2: #dc2626;
21
+ --gray: #9ca3af;
22
+ --orange: #fb923c;
23
+ }
24
+
25
+ :root[data-theme="light"] {
26
+ --bg: #f8f9fa;
27
+ --bg2: #e9ecef;
28
+ --bg3: #ced4da;
29
+ --border: #adb5bd;
30
+ --text: #495057;
31
+ --dim: #868e96;
32
+ --white: #212529;
33
+ --purple: #6741d9;
34
+ --purple2: #5b21b6;
35
+ --blue: #2563eb;
36
+ --magenta: #9333ea;
37
+ --yellow: #d97706;
38
+ --yellow2: #92400e;
39
+ --green: #059669;
40
+ --cyan: #0891b2;
41
+ --red: #dc2626;
42
+ --red2: #b91c1c;
43
+ --gray: #6b7280;
44
+ --orange: #ea580c;
45
+ }
46
+
47
+ body {
48
+ background: var(--bg);
49
+ color: var(--text);
50
+ font-family: 'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace;
51
+ font-size: 13px;
52
+ line-height: 1.5;
53
+ height: 100vh;
54
+ display: flex;
55
+ flex-direction: column;
56
+ overflow: hidden;
57
+ }
58
+
59
+ /* ── Header ── */
60
+ #header {
61
+ height: 32px;
62
+ background: var(--bg3);
63
+ display: flex;
64
+ align-items: center;
65
+ padding: 0 12px;
66
+ gap: 8px;
67
+ font-size: 12px;
68
+ color: var(--white);
69
+ flex-shrink: 0;
70
+ user-select: none;
71
+ }
72
+ #header .sep { color: var(--dim); margin: 0 4px; }
73
+ #header .auto { margin-left: auto; display: flex; gap: 4px; align-items: center; }
74
+
75
+ .btn {
76
+ position: relative;
77
+ display: inline-flex; align-items: center; gap: 3px;
78
+ padding: 2px 8px; border-radius: 4px; border: 1px solid var(--border);
79
+ background: var(--bg2); color: var(--text); cursor: pointer;
80
+ font-family: inherit; font-size: 11px; line-height: 1.5;
81
+ white-space: nowrap; user-select: none; transition: all 0.15s;
82
+ }
83
+ .btn[data-tooltip]:hover::after {
84
+ content: attr(data-tooltip);
85
+ position: absolute;
86
+ top: calc(100% + 5px);
87
+ left: 0;
88
+ background: var(--bg2); color: var(--white);
89
+ padding: 2px 8px; border-radius: 4px;
90
+ font-size: 10px; white-space: nowrap; z-index: 9999;
91
+ pointer-events: none; border: 1px solid var(--border);
92
+ font-family: inherit; line-height: 1.4;
93
+ }
94
+ .btn:hover { background: var(--bg3); border-color: var(--dim); }
95
+ .btn.on { background: var(--purple); border-color: var(--purple); color: var(--white); }
96
+ .btn.on:hover { background: var(--purple2); }
97
+ .btn.on:hover::after { background: var(--purple2); }
98
+ .btn.danger { border-color: var(--red2); color: var(--red); }
99
+ .btn.danger:hover { background: var(--red2); color: var(--white); }
100
+ .btn.accent { border-color: var(--yellow2); color: var(--yellow); }
101
+ .btn:disabled { opacity: 0.3; cursor: not-allowed; }
102
+ .btn-icon { padding: 2px 6px; min-width: 28px; justify-content: center; }
103
+
104
+ /* ── Main area ── */
105
+ #main {
106
+ display: flex;
107
+ flex: 1;
108
+ overflow: hidden;
109
+ }
110
+
111
+ /* ── Tree panel ── */
112
+ #tree-panel {
113
+ width: 30%; min-width: 180px; max-width: 60%;
114
+ border-right: 1px solid var(--border);
115
+ background: var(--bg2);
116
+ overflow: hidden;
117
+ display: flex; flex-direction: column;
118
+ flex-shrink: 0;
119
+ position: relative;
120
+ }
121
+ #tree-panel.hidden { display: none; }
122
+
123
+ #tree-resize-handle {
124
+ position: absolute; right: -3px; top: 0; bottom: 0;
125
+ width: 6px; cursor: col-resize; z-index: 10;
126
+ }
127
+ #tree-resize-handle:hover, #tree-resize-handle.active { background: var(--purple); }
128
+
129
+ #tree-toolbar {
130
+ display: flex; gap: 4px; padding: 4px 6px;
131
+ border-bottom: 1px solid var(--border);
132
+ flex-shrink: 0; flex-wrap: wrap;
133
+ }
134
+ #tree-content {
135
+ flex: 1; overflow-y: auto; overflow-x: hidden; padding: 4px 0;
136
+ }
137
+
138
+ /* ── Tree node styles ── */
139
+ .tree-row {
140
+ display: flex; align-items: flex-start;
141
+ }
142
+ .tree-row-session {
143
+ margin-top: 6px;
144
+ }
145
+ .tree-row-folder {
146
+ margin-top: 6px;
147
+ }
148
+ .folder-node {
149
+ font-size: 13px; font-weight: 500; color: var(--yellow);
150
+ }
151
+ .tree-content {
152
+ flex: 1; min-width: 0;
153
+ }
154
+ .tree-content:hover { background: rgba(255,255,255,0.05); }
155
+ .tree-row.selected > .tree-content { background: rgba(124,58,237,0.3); }
156
+ .tree-content.dim { opacity: 0.4; }
157
+ .tree-node {
158
+ display: flex; align-items: center;
159
+ padding: 3px 2px 3px 0;
160
+ cursor: pointer; white-space: nowrap; gap: 4px;
161
+ overflow: hidden;
162
+ }
163
+ .tree-prefix { color: var(--dim); font-size: 12px; flex-shrink: 0; letter-spacing: 0; font-family: monospace; white-space: pre; }
164
+ .tree-activity {
165
+ font-size: 10px; color: var(--dim); white-space: pre;
166
+ overflow: hidden; line-height: 1.2;
167
+ padding: 0 2px 2px; cursor: pointer;
168
+ }
169
+ .tree-activity .act-text {
170
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
171
+ }
172
+ .tree-node .ctx-pct { font-size: 10px; margin-left: 4px; flex-shrink: 0; }
173
+ .tree-node .ctx-pct.warn { color: var(--yellow); }
174
+ .tree-node .ctx-pct.danger { color: var(--red); }
175
+ .tree-node .active-dot { flex-shrink: 0; }
176
+ .tree-node .active-dot.on { color: var(--green); text-shadow: 0 0 6px var(--green); }
177
+ .tree-node .active-dot.off { color: #555; opacity: 1; }
178
+ .tree-node .tree-agent-id { font-size: 10px; color: var(--dim); margin-left: 2px; font-family: monospace; }
179
+
180
+ .tree-node .session-prefix {
181
+ background: rgba(255,255,255,0.08);
182
+ padding: 0 3px; border-radius: 3px; flex-shrink: 0; font-family: monospace;
183
+ letter-spacing: 0.5px; vertical-align: middle; font-weight: 600;
184
+ position: relative; cursor: pointer;
185
+ }
186
+ .session-id-tip {
187
+ position: fixed; z-index: 10000;
188
+ background: var(--bg2); border: 1px solid var(--border); border-radius: 4px;
189
+ padding: 4px 8px; font-size: 11px; white-space: nowrap; color: var(--text);
190
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4); display: flex; align-items: center; gap: 6px;
191
+ }
192
+ .session-id-tip code { font-family: monospace; user-select: all; color: var(--white); }
193
+ .session-id-tip .tip-copy-btn {
194
+ background: var(--bg3); border: 1px solid var(--border); border-radius: 3px;
195
+ color: var(--text); font-size: 10px; padding: 1px 5px; cursor: pointer;
196
+ }
197
+ .session-id-tip .tip-copy-btn:hover { background: var(--accent); color: #fff; }
198
+ .tree-actions { display: none; gap: 2px; padding-right: 4px; }
199
+ .tree-row:hover .tree-actions { display: flex; }
200
+ .tree-row.selected>.tree-actions { display: flex; }
201
+
202
+ /* ── Tokens page ── */
203
+ #tokens-page { flex: 1; display: flex; flex-direction: column; overflow-y: auto; padding: 20px 24px; gap: 16px; background: var(--bg); }
204
+ .tp-refresh-bar { display: flex; align-items: center; justify-content: flex-end; gap: 12px; padding-bottom: 4px; }
205
+ .tp-refresh-info { font-size: 11px; color: var(--dim); }
206
+ .tp-top { display: flex; gap: 16px; }
207
+ .tp-left { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px; }
208
+ .tp-right { flex: 1; display: flex; flex-direction: column; gap: 12px; }
209
+ .tp-box { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 14px 16px; }
210
+ .tp-total-label { font-size: 11px; color: var(--dim); text-transform: uppercase; margin-bottom: 2px; }
211
+ .tp-total-value { font-size: 22px; font-weight: 700; color: var(--white); font-family: monospace; }
212
+ .tp-total-sub { font-size: 10px; color: var(--dim); margin-top: 2px; }
213
+ .tp-stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
214
+ .tp-stat { padding: 8px 10px; background: var(--bg3); border-radius: 6px; }
215
+ .tp-stat .tp-s-l { font-size: 10px; color: var(--dim); }
216
+ .tp-stat .tp-s-v { font-size: 13px; font-weight: 600; color: var(--white); font-family: monospace; }
217
+ .tp-rank-title { font-size: 12px; color: var(--dim); font-weight: 600; margin-bottom: 8px; }
218
+ .tp-rank-item { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--border); }
219
+ .tp-rank-num { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--bg3); font-size: 10px; font-weight: 600; color: var(--dim); flex-shrink: 0; }
220
+ .tp-rank-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
221
+ .tp-rank-name { font-size: 12px; color: var(--text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
222
+ .tp-rank-pct { font-size: 12px; font-weight: 600; color: var(--white); font-family: monospace; flex-shrink: 0; }
223
+ .tp-footer-stats { display: flex; justify-content: space-between; padding-top: 8px; border-top: 1px solid var(--border); font-size: 11px; color: var(--dim); }
224
+ .tp-footer-stats .tp-fv { color: var(--text); font-family: monospace; }
225
+ .tp-h3 { font-size: 12px; color: var(--dim); font-weight: 600; text-transform: uppercase; margin-bottom: 8px; }
226
+
227
+ /* ── Heatmap ── */
228
+ .tp-heatmap { overflow-x: auto; }
229
+ .tp-heatmap-inner { display: inline-flex; flex-direction: column; gap: 2px; }
230
+ .tp-hm-months { display: flex; gap: 0; font-size: 10px; color: var(--dim); margin-bottom: 2px; padding-left: 28px; }
231
+ .tp-hm-row { display: flex; align-items: center; gap: 2px; }
232
+ .tp-hm-day-label { width: 24px; font-size: 10px; color: var(--dim); text-align: right; flex-shrink: 0; }
233
+ .tp-hm-cell { width: 12px; height: 12px; border-radius: 2px; transition: transform 0.15s; cursor: pointer; position: relative; }
234
+ .tp-hm-cell:hover { transform: scale(1.6); z-index: 10; }
235
+ .tp-hm-cell[title]:hover::after { content: attr(title); position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); background: var(--bg2); color: var(--white); padding: 2px 8px; border-radius: 4px; font-size: 10px; white-space: nowrap; z-index: 100; border: 1px solid var(--border); pointer-events: none; }
236
+ .tp-hm-legend { display: flex; align-items: center; gap: 4px; font-size: 10px; color: var(--dim); margin-top: 6px; justify-content: flex-end; }
237
+ .tp-hm-legend-cell { width: 12px; height: 12px; border-radius: 2px; }
238
+
239
+ /* ── Trend bars ── */
240
+ .tp-trend-bars { display: flex; align-items: flex-end; gap: 3px; height: 140px; position: relative; padding-bottom: 20px; }
241
+ .tp-trend-bar-wrap { flex: 1; display: flex; flex-direction: column; position: relative; min-width: 0; }
242
+ .tp-trend-bar { position: relative; border-radius: 3px 3px 0 0; transition: all 0.15s; cursor: pointer; min-height: 4px; }
243
+ .tp-trend-bar:hover { filter: brightness(1.3); }
244
+ .tp-trend-bar:hover::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); background: var(--bg2); color: var(--white); padding: 2px 8px; border-radius: 4px; font-size: 10px; white-space: nowrap; z-index: 100; border: 1px solid var(--border); pointer-events: none; }
245
+ .tp-trend-label { font-size: 9px; color: var(--dim); text-align: center; position: absolute; bottom: 0; width: 100%; white-space: nowrap; overflow: hidden; }
246
+ .tp-trend-grid-lines { position: absolute; inset: 0 0 20px 0; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
247
+ .tp-trend-grid-line { width: 100%; border-top: 1px dashed var(--border); opacity: 0.4; }
248
+
249
+ /* ── Detail table ── */
250
+ .tp-tabs { display: flex; gap: 2px; }
251
+ .tp-tab { padding: 5px 12px; cursor: pointer; border-radius: 6px 6px 0 0; background: var(--bg3); color: var(--dim); border: 1px solid var(--border); border-bottom: none; font-size: 12px; font-weight: 500; }
252
+ .tp-tab.active { background: var(--bg2); color: var(--white); font-weight: 600; }
253
+ .tp-tc { display: none; }
254
+ .tp-tc.active { display: block; }
255
+ .tp-st { max-height: 480px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }
256
+ .tp-table { width: 100%; border-collapse: collapse; font-size: 11px; background: var(--bg2); }
257
+ .tp-table th { background: var(--bg3); color: var(--white); padding: 7px 10px; text-align: left; font-weight: 600; white-space: nowrap; }
258
+ .tp-table td { padding: 6px 10px; border-top: 1px solid var(--border); white-space: nowrap; font-family: monospace; color: var(--text); }
259
+ .tp-table tr:hover td { background: var(--bg3); }
260
+ .tp-table tfoot td { font-weight: 700; background: var(--bg3); }
261
+ .tp-mtag { display: inline-block; padding: 1px 6px; border-radius: 3px; border: 1px solid; font-size: 10px; margin: 1px; font-weight: 500; }
262
+ .tp-mbreak { white-space: normal; min-width: 200px; }
263
+
264
+ /* ── Charts grid (4 charts: weekly, monthly, model pie, hourly) ── */
265
+ .tp-charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
266
+ .tp-chart-box { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 14px 16px; }
267
+ .tp-chart-title { font-size: 12px; color: var(--dim); font-weight: 600; text-transform: uppercase; margin-bottom: 10px; }
268
+
269
+ /* ── Stacked bar chart (weekly / monthly) ── */
270
+ .tp-stack-bars { display: flex; align-items: flex-end; gap: 4px; height: 160px; position: relative; padding-bottom: 22px; }
271
+ .tp-stack-wrap { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; position: relative; min-width: 0; height: 100%; }
272
+ .tp-stack-seg { transition: all 0.15s; cursor: pointer; min-height: 1px; }
273
+ .tp-stack-seg:hover { filter: brightness(1.3); }
274
+ .tp-stack-bar-group:hover::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); background: var(--bg2); color: var(--white); padding: 3px 10px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 100; border: 1px solid var(--border); pointer-events: none; font-family: monospace; }
275
+ .tp-stack-bar-group { display: flex; flex-direction: column; justify-content: flex-end; position: relative; height: 100%; cursor: pointer; }
276
+ .tp-stack-label { font-size: 9px; color: var(--dim); text-align: center; position: absolute; bottom: 0; width: 100%; white-space: nowrap; overflow: hidden; }
277
+ .tp-stack-grid { position: absolute; inset: 0 0 22px 0; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
278
+ .tp-stack-grid-line { width: 100%; border-top: 1px dashed var(--border); opacity: 0.3; }
279
+
280
+ /* ── Hourly distribution chart ── */
281
+ .tp-hourly-bars { display: flex; align-items: flex-end; gap: 2px; height: 140px; position: relative; padding-bottom: 22px; }
282
+ .tp-hourly-bar-wrap { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; position: relative; min-width: 0; height: 100%; }
283
+ .tp-hourly-bar { border-radius: 3px 3px 0 0; transition: all 0.15s; cursor: pointer; min-height: 2px; }
284
+ .tp-hourly-bar:hover { filter: brightness(1.3); }
285
+ .tp-hourly-bar:hover::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); background: var(--bg2); color: var(--white); padding: 2px 8px; border-radius: 4px; font-size: 10px; white-space: nowrap; z-index: 100; border: 1px solid var(--border); pointer-events: none; font-family: monospace; }
286
+ .tp-hourly-label { font-size: 8px; color: var(--dim); text-align: center; position: absolute; bottom: 0; width: 100%; }
287
+ .tp-hourly-grid { position: absolute; inset: 0 0 22px 0; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
288
+
289
+ /* ── Model proportion doughnut ── */
290
+ .tp-pie-wrap { display: flex; align-items: center; gap: 16px; }
291
+ .tp-pie-ring { position: relative; width: 180px; height: 180px; border-radius: 50%; flex-shrink: 0; }
292
+ .tp-pie-hole { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90px; height: 90px; border-radius: 50%; background: var(--bg2); display: flex; align-items: center; justify-content: center; flex-direction: column; }
293
+ .tp-pie-hole-v { font-size: 14px; font-weight: 700; color: var(--white); font-family: monospace; }
294
+ .tp-pie-hole-l { font-size: 9px; color: var(--dim); }
295
+ .tp-pie-legend { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; max-height: 180px; }
296
+ .tp-pie-legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; }
297
+ .tp-pie-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
298
+ .tp-pie-name { color: var(--text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
299
+ .tp-pie-pct { color: var(--white); font-weight: 600; font-family: monospace; flex-shrink: 0; }
300
+
301
+ /* ── Stream panel ── */
302
+ #stream-panel-wrap {
303
+ flex: 1; display: flex; flex-direction: column; overflow: hidden;
304
+ }
305
+ #stream-toolbar {
306
+ display: flex; gap: 4px; padding: 4px 8px;
307
+ border-bottom: 1px solid var(--border);
308
+ background: var(--bg); flex-shrink: 0;
309
+ }
310
+ #stream-panel {
311
+ flex: 1; overflow-y: auto; padding: 8px 12px;
312
+ font-size: 12px;
313
+ }
314
+
315
+ /* ── Stream lines ── */
316
+ .stream-line { white-space: pre-wrap; word-break: break-all; }
317
+ .stream-line.thinking { color: var(--magenta); }
318
+ .stream-line.tool-input { color: var(--yellow); }
319
+ .stream-line.tool-output { color: var(--green); }
320
+ .stream-line.text { color: var(--text); }
321
+ .stream-line.hook { color: var(--cyan); }
322
+ .stream-line .hook-label { color: var(--dim); }
323
+ .stream-line.diag { color: var(--red); }
324
+ .stream-line.debug { color: var(--gray); }
325
+ .stream-line.marker { color: var(--dim); }
326
+ .stream-line.agent-tag { font-weight: bold; display: flex; justify-content: space-between; align-items: baseline; white-space: nowrap; }
327
+ .stream-line.agent-main { color: var(--blue); }
328
+ .stream-line.agent-sub { color: var(--magenta); }
329
+ .stream-line.agent-tag .tag-label { flex-shrink: 0; }
330
+ .stream-line.agent-tag .timestamp { font-weight: normal; font-size: 0.85em; color: var(--dim); white-space: nowrap; }
331
+ .stream-line.separator { color: var(--dim); }
332
+ .stream-line.user-prompt-block {
333
+ background: rgba(59,130,246,0.08);
334
+ border-left: 8px solid var(--blue);
335
+ border-radius: 4px;
336
+ padding: 6px 10px;
337
+ margin: 4px 0;
338
+ color: var(--white);
339
+ line-height: 1.5;
340
+ }
341
+
342
+ /* ── Footer ── */
343
+ #footer {
344
+ height: 28px; background: var(--bg2);
345
+ border-top: 1px solid var(--border);
346
+ display: flex; align-items: center;
347
+ padding: 0 8px; gap: 6px;
348
+ font-size: 11px; flex-shrink: 0; flex-wrap: wrap;
349
+ }
350
+ #footer .sep { color: var(--dim); margin: 0 2px; }
351
+
352
+ /* ── Scrollbar ── */
353
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
354
+ ::-webkit-scrollbar-track { background: transparent; }
355
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
356
+
357
+ /* ── Focus ring ── */
358
+ #stream-panel:focus { outline: none; }
359
+
360
+ /* ── Markdown & code blocks ── */
361
+ .md-content { line-height: 1.6; color: var(--text); }
362
+ .md-content p { margin: 4px 0; }
363
+ .md-content ul, .md-content ol { padding-left: 20px; margin: 4px 0; }
364
+ .md-content li { margin: 2px 0; }
365
+ .md-content strong { color: var(--white); }
366
+ .md-content a { color: var(--blue); text-decoration: underline; }
367
+ .md-content h1, .md-content h2, .md-content h3, .md-content h4,
368
+ .md-content h5, .md-content h6 { color: var(--white); margin: 8px 0 4px; font-size: inherit; font-weight: bold; }
369
+ .md-content blockquote { border-left: 3px solid var(--purple); padding-left: 12px; color: var(--dim); margin: 4px 0; }
370
+ .md-content hr { border: none; border-top: 1px solid var(--border); margin: 8px 0; }
371
+ .md-content table { border-collapse: collapse; margin: 4px 0; width: 100%; }
372
+ .md-content th, .md-content td { border: 1px solid var(--border); padding: 4px 8px; text-align: left; }
373
+ .md-content th { background: var(--bg3); color: var(--white); }
374
+ .md-content img { max-width: 100%; }
375
+
376
+ .code-block-wrapper { margin: 8px 0; border-radius: 6px; overflow: hidden; border: 1px solid var(--border); }
377
+ .code-block-header { display: flex; align-items: center; justify-content: space-between; padding: 4px 12px; background: var(--bg3); font-size: 11px; color: var(--dim); }
378
+ .code-block-header .lang-tag { color: var(--blue); font-weight: bold; }
379
+ .code-block-header .copy-btn { cursor: pointer; opacity: 0.5; transition: opacity 0.2s; font-size: 11px; }
380
+ .code-block-header .copy-btn:hover { opacity: 1; }
381
+ .code-block-wrapper pre { margin: 0; padding: 12px; overflow-x: auto; font-size: 12px; line-height: 1.5; }
382
+ .code-block-wrapper pre code { font-family: 'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace; font-size: 12px; }
383
+
384
+ /* Override highlight.js background to match our theme */
385
+ .hljs { background: #0d1117 !important; }
386
+
387
+ /* Light theme overrides */
388
+ :root[data-theme="light"] .btn.on { background: var(--purple); border-color: var(--purple); color: #fff; }
389
+ :root[data-theme="light"] .btn.on:hover { background: var(--purple2); color: #fff; }
390
+ :root[data-theme="light"] .btn.on:hover::after { background: var(--purple2); color: #fff; }
391
+ :root[data-theme="light"] .hljs { background: #f0f0f0 !important; }
392
+ :root[data-theme="light"] .tree-content:hover { background: rgba(0,0,0,0.06); }
393
+ :root[data-theme="light"] .tree-row.selected > .tree-content { background: rgba(124,58,237,0.2); }
394
+ :root[data-theme="light"] .tree-node .active-dot.off { color: #bbb; }
395
+ :root[data-theme="light"] #tree-resize-handle:hover,
396
+ :root[data-theme="light"] #tree-resize-handle.active { background: var(--purple); }
397
+ :root[data-theme="light"] .stream-line.text { color: var(--text); }
398
+
399
+ /* Theme toggle button */
400
+ #btn-theme { font-size: 14px; }
401
+
402
+ /* ── Export modal ── */
403
+ .modal-overlay {
404
+ position: fixed; inset: 0;
405
+ background: rgba(0, 0, 0, 0.6);
406
+ z-index: 10000;
407
+ display: flex; align-items: center; justify-content: center;
408
+ }
409
+ :root[data-theme="light"] .modal-overlay { background: rgba(0, 0, 0, 0.3); }
410
+ :root[data-theme="light"] .modal-session-row.selected { background: rgba(124, 58, 237, 0.2); }
411
+
412
+ .modal-box {
413
+ background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
414
+ width: 480px; max-width: 90vw; max-height: 80vh;
415
+ display: flex; flex-direction: column; overflow: hidden;
416
+ }
417
+
418
+ .modal-header {
419
+ display: flex; align-items: center; justify-content: space-between;
420
+ padding: 8px 12px; border-bottom: 1px solid var(--border); background: var(--bg2); flex-shrink: 0;
421
+ }
422
+ .modal-title { font-size: 13px; font-weight: 600; color: var(--white); }
423
+
424
+ .modal-toolbar {
425
+ display: flex; align-items: center; gap: 4px;
426
+ padding: 6px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
427
+ }
428
+ .modal-count { margin-left: auto; font-size: 11px; color: var(--dim); }
429
+
430
+ .modal-body { flex: 1; overflow-y: auto; padding: 6px 0; }
431
+
432
+ .modal-session-row {
433
+ display: flex; align-items: center; gap: 8px;
434
+ padding: 6px 12px; cursor: pointer; transition: background 0.1s; user-select: none;
435
+ }
436
+ .modal-session-row:hover { background: var(--bg2); }
437
+ .modal-session-row.selected { background: rgba(124, 58, 237, 0.15); }
438
+
439
+ .modal-checkbox {
440
+ appearance: none; width: 16px; height: 16px;
441
+ border: 1px solid var(--border); border-radius: 3px; background: var(--bg2);
442
+ cursor: pointer; position: relative; flex-shrink: 0; transition: all 0.15s;
443
+ }
444
+ .modal-checkbox:checked { background: var(--purple); border-color: var(--purple); }
445
+ .modal-checkbox:checked::after {
446
+ content: '✓'; position: absolute; inset: 0;
447
+ display: flex; align-items: center; justify-content: center;
448
+ color: var(--white); font-size: 11px; font-weight: bold;
449
+ }
450
+
451
+ .modal-session-prefix {
452
+ font-family: monospace; font-size: 12px; font-weight: 600; letter-spacing: 0.5px; flex-shrink: 0;
453
+ }
454
+ .modal-session-info {
455
+ flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 4px; overflow: hidden;
456
+ }
457
+ .modal-session-project {
458
+ font-size: 12px; font-weight: 500; color: var(--text);
459
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
460
+ }
461
+ .modal-session-model { font-size: 10px; color: var(--dim); flex-shrink: 0; }
462
+ .modal-session-time { font-size: 10px; color: var(--dim); flex-shrink: 0; margin-left: auto; }
463
+
464
+ .modal-footer {
465
+ display: flex; align-items: center; justify-content: flex-end; gap: 6px;
466
+ padding: 8px 12px; border-top: 1px solid var(--border); background: var(--bg2); flex-shrink: 0;
467
+ }
468
+
469
+ @media (max-width: 768px) {
470
+ .tp-top { flex-direction: column; }
471
+ .tp-left { width: 100%; }
472
+ .tp-charts-row { grid-template-columns: 1fr; }
473
+ .tp-pie-wrap { flex-direction: column; align-items: center; }
474
+ }