hood-traders 0.1.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.
@@ -0,0 +1,309 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ --bg: #0a0a0d;
4
+ --bg-elevated: #111116;
5
+ --bg-card: #16161d;
6
+ --border: #26262f;
7
+ --border-hover: #34343f;
8
+ --text: #eaeaf0;
9
+ --text-dim: #9a9aa8;
10
+ --text-faint: #66666f;
11
+ --accent-a: #6d5ef8;
12
+ --accent-b: #2fd0e0;
13
+ --green: #34d399;
14
+ --red: #f87171;
15
+ --amber: #fbbf24;
16
+ --radius: 10px;
17
+ --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, Consolas, monospace;
18
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, sans-serif;
19
+ }
20
+
21
+ * { box-sizing: border-box; }
22
+
23
+ html, body {
24
+ margin: 0;
25
+ padding: 0;
26
+ background: var(--bg);
27
+ color: var(--text);
28
+ font-family: var(--font-sans);
29
+ min-height: 100vh;
30
+ }
31
+
32
+ body {
33
+ background-image: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(109, 94, 248, 0.12), transparent);
34
+ }
35
+
36
+ a { color: var(--accent-b); text-decoration: none; }
37
+ a:hover { text-decoration: underline; }
38
+
39
+ button {
40
+ font-family: inherit;
41
+ cursor: pointer;
42
+ }
43
+ button:focus-visible, a:focus-visible, [tabindex]:focus-visible {
44
+ outline: 2px solid var(--accent-b);
45
+ outline-offset: 2px;
46
+ }
47
+
48
+ /* ── layout ─────────────────────────────────────────────────────────────── */
49
+
50
+ .wrap {
51
+ max-width: 1280px;
52
+ margin: 0 auto;
53
+ padding: 24px 20px 64px;
54
+ }
55
+
56
+ .topbar {
57
+ display: flex;
58
+ align-items: center;
59
+ justify-content: space-between;
60
+ gap: 16px;
61
+ padding-bottom: 20px;
62
+ border-bottom: 1px solid var(--border);
63
+ margin-bottom: 24px;
64
+ flex-wrap: wrap;
65
+ }
66
+
67
+ .brand {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 10px;
71
+ font-weight: 600;
72
+ font-size: 15px;
73
+ letter-spacing: -0.01em;
74
+ }
75
+
76
+ .brand .dot {
77
+ width: 8px; height: 8px; border-radius: 50%;
78
+ background: linear-gradient(135deg, var(--accent-a), var(--accent-b));
79
+ box-shadow: 0 0 12px rgba(109, 94, 248, 0.6);
80
+ }
81
+
82
+ /* [hidden] must win over .badge's display: inline-flex — equal specificity,
83
+ later source order would otherwise re-show a badge JS explicitly hid. */
84
+ .badge[hidden] { display: none; }
85
+
86
+ .badge {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ gap: 6px;
90
+ padding: 4px 10px;
91
+ border-radius: 999px;
92
+ font-size: 12px;
93
+ font-weight: 600;
94
+ border: 1px solid var(--border);
95
+ background: var(--bg-elevated);
96
+ color: var(--text-dim);
97
+ }
98
+ .badge.paper { color: var(--accent-b); border-color: rgba(47, 208, 224, 0.3); background: rgba(47, 208, 224, 0.08); }
99
+ .badge.live { color: var(--red); border-color: rgba(248, 113, 113, 0.35); background: rgba(248, 113, 113, 0.08); }
100
+ .badge.killed { color: var(--red); border-color: rgba(248, 113, 113, 0.4); background: rgba(248, 113, 113, 0.12); }
101
+
102
+ .topbar-right { display: flex; align-items: center; gap: 10px; }
103
+
104
+ .kill-btn {
105
+ padding: 8px 14px;
106
+ border-radius: 8px;
107
+ border: 1px solid rgba(248, 113, 113, 0.4);
108
+ background: rgba(248, 113, 113, 0.1);
109
+ color: var(--red);
110
+ font-weight: 600;
111
+ font-size: 13px;
112
+ transition: background 0.15s, transform 0.1s;
113
+ }
114
+ .kill-btn:hover { background: rgba(248, 113, 113, 0.2); }
115
+ .kill-btn:active { transform: scale(0.97); }
116
+ .kill-btn:disabled { opacity: 0.5; cursor: not-allowed; }
117
+
118
+ /* ── summary strip ─────────────────────────────────────────────────────── */
119
+
120
+ .summary-grid {
121
+ display: grid;
122
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
123
+ gap: 12px;
124
+ margin-bottom: 28px;
125
+ }
126
+
127
+ .stat-tile {
128
+ background: var(--bg-card);
129
+ border: 1px solid var(--border);
130
+ border-radius: var(--radius);
131
+ padding: 14px 16px;
132
+ transition: border-color 0.15s;
133
+ }
134
+ .stat-tile:hover { border-color: var(--border-hover); }
135
+
136
+ .stat-label {
137
+ font-size: 11px;
138
+ text-transform: uppercase;
139
+ letter-spacing: 0.06em;
140
+ color: var(--text-faint);
141
+ margin-bottom: 6px;
142
+ }
143
+
144
+ .stat-value {
145
+ font-family: var(--font-mono);
146
+ font-size: 20px;
147
+ font-weight: 600;
148
+ letter-spacing: -0.02em;
149
+ }
150
+ .stat-value.pos { color: var(--green); }
151
+ .stat-value.neg { color: var(--red); }
152
+
153
+ /* ── agent cards ────────────────────────────────────────────────────────── */
154
+
155
+ .section-title {
156
+ font-size: 13px;
157
+ font-weight: 600;
158
+ text-transform: uppercase;
159
+ letter-spacing: 0.06em;
160
+ color: var(--text-faint);
161
+ margin: 32px 0 12px;
162
+ }
163
+
164
+ .agents-grid {
165
+ display: grid;
166
+ grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
167
+ gap: 16px;
168
+ }
169
+
170
+ .agent-card {
171
+ background: var(--bg-card);
172
+ border: 1px solid var(--border);
173
+ border-radius: var(--radius);
174
+ padding: 18px;
175
+ transition: border-color 0.15s, transform 0.15s;
176
+ }
177
+ .agent-card:hover { border-color: var(--border-hover); }
178
+
179
+ .agent-head {
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: space-between;
183
+ margin-bottom: 4px;
184
+ }
185
+
186
+ .agent-name { font-weight: 600; font-size: 15px; }
187
+ .agent-strategy { font-size: 12px; color: var(--text-faint); margin-bottom: 14px; }
188
+
189
+ .status-dot {
190
+ width: 7px; height: 7px; border-radius: 50%;
191
+ display: inline-block;
192
+ background: var(--text-faint);
193
+ }
194
+ .status-dot.running { background: var(--green); box-shadow: 0 0 8px rgba(52, 211, 153, 0.6); }
195
+ .status-dot.killed { background: var(--red); }
196
+
197
+ .agent-metrics {
198
+ display: grid;
199
+ grid-template-columns: 1fr 1fr;
200
+ gap: 10px 16px;
201
+ margin-bottom: 14px;
202
+ }
203
+
204
+ .metric { font-size: 12px; }
205
+ .metric-label { color: var(--text-faint); margin-bottom: 2px; }
206
+ .metric-value { font-family: var(--font-mono); font-weight: 600; }
207
+
208
+ .positions-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
209
+ .position-row {
210
+ display: flex;
211
+ justify-content: space-between;
212
+ align-items: center;
213
+ font-size: 12px;
214
+ padding: 6px 10px;
215
+ background: var(--bg-elevated);
216
+ border-radius: 6px;
217
+ font-family: var(--font-mono);
218
+ }
219
+ .no-positions {
220
+ font-size: 12px;
221
+ color: var(--text-faint);
222
+ padding: 10px;
223
+ text-align: center;
224
+ border: 1px dashed var(--border);
225
+ border-radius: 6px;
226
+ }
227
+
228
+ .mini-chart { height: 48px; margin-bottom: 12px; }
229
+ .mini-chart svg { width: 100%; height: 100%; display: block; }
230
+
231
+ .journal-toggle {
232
+ font-size: 12px;
233
+ color: var(--accent-b);
234
+ background: none;
235
+ border: none;
236
+ padding: 4px 0;
237
+ }
238
+
239
+ .journal-list {
240
+ display: none;
241
+ flex-direction: column;
242
+ gap: 4px;
243
+ max-height: 220px;
244
+ overflow-y: auto;
245
+ margin-top: 8px;
246
+ padding-top: 8px;
247
+ border-top: 1px solid var(--border);
248
+ }
249
+ .journal-list.open { display: flex; }
250
+
251
+ .journal-row {
252
+ font-size: 11px;
253
+ font-family: var(--font-mono);
254
+ padding: 5px 8px;
255
+ border-radius: 5px;
256
+ line-height: 1.4;
257
+ }
258
+ .journal-row.kind-alert { background: rgba(251, 191, 36, 0.08); color: #fcd34d; }
259
+ .journal-row.kind-refused { background: rgba(248, 113, 113, 0.08); color: #fca5a5; }
260
+ .journal-row.kind-observe { color: var(--text-faint); }
261
+ .journal-row.kind-trade { background: rgba(52, 211, 153, 0.08); color: #6ee7b7; }
262
+ .journal-time { color: var(--text-faint); margin-right: 6px; }
263
+
264
+ .error-banner {
265
+ margin-top: 10px;
266
+ font-size: 11px;
267
+ color: var(--red);
268
+ background: rgba(248, 113, 113, 0.08);
269
+ border-radius: 6px;
270
+ padding: 6px 10px;
271
+ font-family: var(--font-mono);
272
+ }
273
+
274
+ /* ── empty / loading / error page states ──────────────────────────────────── */
275
+
276
+ .state-block {
277
+ text-align: center;
278
+ padding: 60px 20px;
279
+ color: var(--text-faint);
280
+ }
281
+ .state-block .state-icon { font-size: 32px; margin-bottom: 12px; opacity: 0.6; }
282
+ .state-block .state-title { font-size: 15px; color: var(--text-dim); margin-bottom: 6px; }
283
+ .state-block .state-detail { font-size: 13px; }
284
+
285
+ .footer {
286
+ margin-top: 48px;
287
+ padding-top: 20px;
288
+ border-top: 1px solid var(--border);
289
+ font-size: 12px;
290
+ color: var(--text-faint);
291
+ display: flex;
292
+ justify-content: space-between;
293
+ flex-wrap: wrap;
294
+ gap: 8px;
295
+ }
296
+
297
+ /* ── responsive ─────────────────────────────────────────────────────────── */
298
+
299
+ @media (max-width: 640px) {
300
+ .summary-grid { grid-template-columns: repeat(2, 1fr); }
301
+ .agents-grid { grid-template-columns: 1fr; }
302
+ .topbar { flex-direction: column; align-items: flex-start; }
303
+ }
304
+
305
+ @keyframes pulse {
306
+ 0%, 100% { opacity: 1; }
307
+ 50% { opacity: 0.4; }
308
+ }
309
+ .live-pulse { animation: pulse 2s ease-in-out infinite; }