neuroalpha 0.3.16 → 0.5.1

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.
Files changed (41) hide show
  1. package/README.md +0 -1
  2. package/config/certs/russian_trusted_root_ca.pem +33 -0
  3. package/docs//320/224/320/225/320/237/320/233/320/236/320/231.md +4 -4
  4. package/docs//320/230/320/235/320/241/320/242/320/240/320/243/320/232/320/246/320/230/320/257.md +2 -6
  5. package/docs//320/234/320/225/320/245/320/220/320/235/320/230/320/232/320/220_/320/230_/320/237/320/220/320/240/320/220/320/234/320/225/320/242/320/240/320/253.md +2 -2
  6. package/package.json +60 -53
  7. package/public/activate.html +36 -0
  8. package/public/activate.js +33 -0
  9. package/public/admin.html +126 -7
  10. package/public/app.js +608 -182
  11. package/public/index.html +57 -47
  12. package/public/landing.html +106 -37
  13. package/public/legal.html +4 -4
  14. package/public/styles.css +152 -36
  15. package/server/api/routes.js +308 -37
  16. package/server/auth/index.js +79 -15
  17. package/server/brokers/index.js +1022 -172
  18. package/server/build-info.js +7 -0
  19. package/server/config.js +13 -6
  20. package/server/data/moex.js +6 -4
  21. package/server/db.js +22 -18
  22. package/server/desktop-entry.js +103 -0
  23. package/server/hub.js +28 -14
  24. package/server/index.js +82 -12
  25. package/server/instance/agent.js +259 -0
  26. package/server/instance/central.js +491 -0
  27. package/server/instance/identity.js +79 -0
  28. package/server/instance/provision.js +166 -0
  29. package/server/instance/signing.js +71 -0
  30. package/server/model/edge.js +19 -0
  31. package/server/model/forecast.js +107 -57
  32. package/server/model/live.js +1 -1
  33. package/server/model/models.js +12 -3
  34. package/server/model/research.js +218 -30
  35. package/server/notify/index.js +51 -16
  36. package/server/params-meta.js +3 -3
  37. package/server/role.js +44 -0
  38. package/server/security.js +40 -0
  39. package/server/strategist/index.js +462 -488
  40. package/server/strategist/tools.js +675 -532
  41. package/server/tls-ca.js +32 -0
package/public/styles.css CHANGED
@@ -13,6 +13,8 @@
13
13
  --best-bg: #13241a;
14
14
  --flash-bg: #2a1f45;
15
15
  --chat-w: 38%;
16
+ --accent-bg: rgba(79, 140, 255, 0.14);
17
+ --hover-bg: rgba(255, 255, 255, 0.05);
16
18
  }
17
19
  body.light {
18
20
  --bg: #f6f8fa;
@@ -27,6 +29,8 @@ body.light {
27
29
  --violet: #8250df;
28
30
  --best-bg: #dcfce7;
29
31
  --flash-bg: #ede9fe;
32
+ --accent-bg: rgba(36, 87, 214, 0.09);
33
+ --hover-bg: #f0f3f6;
30
34
  }
31
35
  * { box-sizing: border-box; }
32
36
  html, body { height: 100%; }
@@ -38,10 +42,10 @@ body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.5 syst
38
42
  .neg { color: var(--red); }
39
43
  h4 { margin: 18px 0 6px; font-size: 13px; color: var(--muted); font-weight: 500; }
40
44
 
41
- header { height: 46px; display: flex; justify-content: space-between; align-items: center; padding: 0 16px; border-bottom: 1px solid var(--line); }
42
- .brand { display: flex; gap: 8px; align-items: baseline; }
45
+ header { height: 48px; display: flex; justify-content: space-between; align-items: center; padding: 0 16px; border-bottom: 1px solid var(--line); background: var(--panel); }
46
+ .brand { display: flex; gap: 8px; align-items: center; }
43
47
  .logo { color: var(--accent); font-size: 18px; }
44
- .hright { display: flex; gap: 10px; align-items: center; }
48
+ .hright { display: flex; gap: 8px; align-items: center; }
45
49
  .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); display: inline-block; cursor: help; }
46
50
  .dot.ok { background: var(--green); }
47
51
  .dot.warn { background: var(--yellow); }
@@ -49,17 +53,37 @@ header { height: 46px; display: flex; justify-content: space-between; align-item
49
53
 
50
54
  input, select, textarea { background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; font: inherit; }
51
55
  textarea { resize: none; width: 100%; }
52
- button { background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 6px 12px; cursor: pointer; font: inherit; font-weight: 500; }
53
- button:hover { border-color: var(--accent); }
56
+ button, a.hdr-btn {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ gap: 5px;
61
+ background: var(--panel);
62
+ color: var(--text);
63
+ border: 1px solid var(--line);
64
+ border-radius: 6px;
65
+ padding: 5px 12px;
66
+ cursor: pointer;
67
+ font: inherit;
68
+ font-size: 13px;
69
+ font-weight: 500;
70
+ line-height: 1.35;
71
+ text-decoration: none;
72
+ transition: background .15s, border-color .15s, color .15s;
73
+ }
74
+ button:hover:not(:disabled), a.hdr-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--hover-bg); }
54
75
  button:disabled { opacity: .55; cursor: default; }
55
- button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
56
- button.icon { padding: 2px 8px; color: var(--text); background: transparent; }
76
+ button.primary { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
77
+ button.primary:hover:not(:disabled) { background: var(--accent); border-color: var(--accent); color: #fff; filter: brightness(1.08); }
78
+ button.icon { padding: 4px 9px; color: var(--text); background: var(--panel); border: 1px solid var(--line); }
57
79
  button.icon-lg { width: 40px; height: 40px; padding: 0; font-size: 15px; flex: none; }
80
+ .hdr-btn { padding: 4px 10px; font-size: 12.5px; }
81
+ .hdr-btn.icon-only { width: 30px; height: 30px; padding: 0; }
58
82
 
59
- main { display: grid; grid-template-columns: var(--chat-w) 5px 1fr; height: calc(100vh - 46px); }
83
+ main { display: grid; grid-template-columns: var(--chat-w) 5px 1fr; height: calc(100vh - 48px); }
60
84
  body.chat-closed main { grid-template-columns: 1fr; }
61
85
  body.chat-closed .chat, body.chat-closed #splitter { display: none; }
62
- #btn-chat-toggle.active { border-color: var(--accent); color: var(--accent); background: rgba(79, 140, 255, 0.1); }
86
+ #btn-chat-toggle.active { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); font-weight: 600; }
63
87
  #splitter { cursor: col-resize; background: var(--line); transition: background .15s; }
64
88
  #splitter:hover, #splitter.drag { background: var(--accent); }
65
89
  body.dragging { cursor: col-resize; user-select: none; }
@@ -210,15 +234,16 @@ body.light .tbadge.run { background: #dbeafe; border-color: #93c5fd; }
210
234
  .ld-sym { font-size: 11px; padding: 2px 7px; border-radius: 5px; background: var(--bg); border: 1px solid var(--line); color: var(--text); }
211
235
  .ld-sym.ok { border-color: rgba(63, 185, 80, 0.5); color: var(--green); }
212
236
  .verdict { margin: 10px 0; font-size: 13.5px; line-height: 1.45; }
213
- .kpis { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
214
- @media (max-width: 1180px) { .kpis { grid-template-columns: repeat(3, 1fr); } }
215
- .kpi { background: var(--bg); padding: 10px 14px; cursor: help; }
216
- .kpi .v { font-size: 21px; font-weight: 600; line-height: 1.2; }
217
- .kpi .l { font-size: 12px; color: var(--muted); margin-top: 2px; }
218
- .kpi .sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.3; }
219
- .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; margin: 14px 0 6px; }
220
- .seg button { border: 0; border-radius: 0; padding: 3px 10px; font-size: 12px; color: var(--muted); }
221
- .seg button.active { background: var(--panel); color: var(--text); }
237
+ .kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
238
+ .kpi { background: var(--bg); padding: 10px 14px; cursor: help; min-width: 0; }
239
+ .kpi .v { font-size: 19px; font-weight: 600; line-height: 1.25; word-break: break-word; }
240
+ .kpi .l { font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.35; word-break: break-word; }
241
+ .kpi .sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.3; word-break: break-word; }
242
+ .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; margin: 14px 0 6px; background: var(--panel); }
243
+ .seg button { border: 0; border-right: 1px solid var(--line); border-radius: 0; padding: 4px 11px; font-size: 12.5px; color: var(--muted); background: transparent; }
244
+ .seg button:last-child { border-right: 0; }
245
+ .seg button:hover { color: var(--accent); background: var(--hover-bg); }
246
+ .seg button.active { background: var(--accent-bg); color: var(--accent); font-weight: 600; }
222
247
  .chart { height: 260px; }
223
248
  .chart.small { height: 160px; }
224
249
  .legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin-top: 4px; }
@@ -279,8 +304,6 @@ body.light .msg.user { background: #dbe8ff; color: #1f2328; }
279
304
  body.light details.think summary { color: var(--violet); }
280
305
  body.light .think-body { color: #4b5563; }
281
306
  body.light .scard { background: var(--panel); }
282
- body.light .snav button.active { background: #eaeef2; color: var(--text); }
283
- body.light .snav button:hover { background: #f0f3f6; }
284
307
  body.light .progress .bar { background: linear-gradient(90deg, #b6d0ff 0%, #60a5fa 50%, #b6d0ff 100%); background-size: 200% 100%; }
285
308
  body.light .feed-down, body.light #toast div { box-shadow: 0 6px 20px rgba(15, 23, 42, 0.14); }
286
309
  body.light ::-webkit-scrollbar-thumb { background: #c1c8d1; border-color: var(--bg); }
@@ -288,25 +311,25 @@ body.light ::-webkit-scrollbar-thumb:hover { background: #9aa4b2; }
288
311
  body.light .feed, body.light .tab, body.light .think-body, body.light .modal .md { scrollbar-color: #c1c8d1 transparent; }
289
312
  body.light input[type=checkbox].switch { background: #d0d7de; border-color: #afb8c1; }
290
313
  body.light input[type=checkbox].switch::after { background: #fff; }
291
- body.light input[type=checkbox].switch:checked { background: #1a7f37; border-color: #1a7f37; }
314
+ body.light input[type=checkbox].switch:checked { background: var(--accent); border-color: var(--accent); }
292
315
  .headbar { display: grid; grid-template-columns: 1fr 140px 56px; gap: 8px; align-items: center; font-size: 12.5px; padding: 1px 0; }
293
316
  .headbar .b { height: 6px; background: var(--panel); border-radius: 3px; position: relative; }
294
317
  .headbar .b div { position: absolute; top: 0; bottom: 0; border-radius: 3px; }
295
318
 
296
319
  .settings-wrap { display: grid; grid-template-columns: 205px minmax(0, 1fr); gap: 24px; align-items: start; min-width: 0; }
297
320
  @media (max-width: 1100px) { .settings-wrap { grid-template-columns: 180px minmax(0, 1fr); gap: 16px; } }
298
- .snav { display: flex; flex-direction: column; gap: 3px; position: sticky; top: 0; min-width: 0; }
321
+ .snav { display: flex; flex-direction: column; gap: 4px; position: sticky; top: 0; min-width: 0; }
299
322
  .snav #s-search { width: 100%; margin-bottom: 10px; background: transparent; border-color: var(--line); padding: 6px 10px; font-size: 13px; }
300
- .snav button { text-align: left; border: 0; padding: 7px 12px; border-radius: 6px; color: var(--muted); font-size: 13.5px; }
301
- .snav button:hover { background: #ffffff08; color: var(--text); }
302
- .snav button.active { background: #262b36; color: var(--text); font-weight: 500; }
323
+ .snav button { justify-content: flex-start; text-align: left; border: 1px solid transparent; background: transparent; padding: 7px 12px; border-radius: 6px; color: var(--muted); font-size: 13.5px; font-weight: 500; }
324
+ .snav button:hover { background: var(--hover-bg); border-color: var(--line); color: var(--text); }
325
+ .snav button.active { background: var(--accent-bg); border-color: var(--accent); color: var(--accent); font-weight: 600; }
303
326
  .snav .ssep { height: 1px; background: var(--line); margin: 8px 4px; }
304
327
  .snav .sreset { color: var(--muted); font-size: 12.5px; }
305
328
  .spane { min-width: 0; overflow: hidden; }
306
329
  .ssec { margin-bottom: 24px; min-width: 0; }
307
330
  .stitle { font-size: 14px; font-weight: 600; margin: 2px 0 12px; color: var(--text); }
308
331
  .stitle.bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
309
- .scard { background: #141820; border: 1px solid var(--line); border-radius: 10px; padding: 0 20px; min-width: 0; overflow: hidden; }
332
+ .scard { background: #141820; border: 1px solid var(--line); border-radius: 10px; padding: 0 20px; min-width: 0; overflow-x: auto; overflow-y: visible; }
310
333
  .scard.spadded { padding: 16px 20px; }
311
334
  .srow { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 20px; align-items: center; padding: 15px 0; border-bottom: 1px solid var(--line); }
312
335
  .srow.sblock { display: flex; flex-direction: column; align-items: stretch; gap: 12px; padding: 16px 0; }
@@ -320,7 +343,7 @@ body.light input[type=checkbox].switch:checked { background: #1a7f37; border-col
320
343
  .srow input[type=number].sctrl { width: 110px; text-align: right; background: var(--bg); }
321
344
  input[type=checkbox].switch { appearance: none; width: 38px; height: 22px; background: #2b313d; border: 1px solid #3a4252; border-radius: 999px; position: relative; cursor: pointer; transition: background .15s, border-color .15s; flex: none; padding: 0; }
322
345
  input[type=checkbox].switch::after { content: ""; position: absolute; width: 16px; height: 16px; border-radius: 50%; background: #d0d7de; top: 2px; left: 2px; transition: transform .15s, background .15s; }
323
- input[type=checkbox].switch:checked { background: #3fb9a0; border-color: #3fb9a0; }
346
+ input[type=checkbox].switch:checked { background: var(--accent); border-color: var(--accent); }
324
347
  input[type=checkbox].switch:checked::after { transform: translateX(16px); background: #fff; }
325
348
  .chat-head #chat-model { max-width: 190px; min-width: 0; text-overflow: ellipsis; }
326
349
  #llm-box details { margin-top: 12px; }
@@ -372,9 +395,10 @@ table.cmp { font-size: 12.5px; }
372
395
  table.cmp th { padding: 4px 8px; font-size: 12px; }
373
396
  table.cmp td { padding: 3px 8px; }
374
397
  .secret-input { -webkit-text-security: disc; text-security: disc; font-family: monospace; }
375
- .brk-subtabs { display: flex; gap: 6px; margin: 10px 0 8px; border-bottom: 1px solid var(--line); padding-bottom: 6px; }
376
- .brk-subtabs button { background: transparent; border: 1px solid transparent; padding: 5px 12px; border-radius: 6px; font-weight: 500; color: var(--muted); }
377
- .brk-subtabs button.active { background: var(--bg); border-color: var(--line); color: var(--text); font-weight: 600; }
398
+ .brk-subtabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 10px; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
399
+ .brk-subtabs button { background: var(--panel); border: 1px solid var(--line); padding: 5px 12px; border-radius: 6px; font-weight: 500; font-size: 13px; color: var(--muted); }
400
+ .brk-subtabs button:hover { border-color: var(--accent); color: var(--accent); background: var(--hover-bg); }
401
+ .brk-subtabs button.active { background: var(--accent-bg); border-color: var(--accent); color: var(--accent); font-weight: 600; }
378
402
  .brk-alloc-wrap { margin: 6px 0 12px; padding: 8px 10px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; }
379
403
  .brk-alloc-bar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; gap: 2px; margin-bottom: 7px; background: var(--line); }
380
404
  .brk-alloc-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; color: var(--muted); }
@@ -384,9 +408,11 @@ table.cmp td { padding: 3px 8px; }
384
408
  .brk-specs .k { color: var(--muted); }
385
409
  .brk-specs .v { color: var(--text); }
386
410
  .brk-toolbar { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; padding: 8px 0 10px; margin-bottom: 10px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); overflow-x: auto; }
387
- .brk-toggle { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 6px; font-size: 13px; border: 1px solid var(--line); background: var(--panel); color: var(--muted); transition: .15s; }
388
- .brk-toggle.on { border-color: rgba(22, 163, 74, 0.55); background: rgba(22, 163, 74, 0.14); color: #4ade80; font-weight: 600; }
389
- .brk-icon-btn { width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; font-size: 15px; flex: none; }
411
+ .brk-toggle { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 6px; font-size: 13px; font-weight: 500; border: 1px solid var(--line); background: var(--panel); color: var(--muted); transition: .15s; }
412
+ .brk-toggle:hover { border-color: var(--accent); color: var(--accent); background: var(--hover-bg); }
413
+ .brk-toggle.on { border-color: var(--accent); background: var(--accent-bg); color: var(--accent); font-weight: 600; }
414
+ .brk-icon-btn { width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; font-size: 15px; flex: none; background: var(--panel); border: 1px solid var(--line); color: var(--muted); }
415
+ .brk-icon-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--hover-bg); }
390
416
  tr.day-group-row td { background: var(--panel); color: var(--text); font-weight: 600; font-size: 12.5px; padding: 7px 10px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
391
417
  details.hist-year-box { margin-top: 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); overflow: hidden; }
392
418
  details.hist-year-box > summary { padding: 10px 14px; cursor: pointer; font-weight: 600; font-size: 13.5px; background: var(--panel); display: flex; justify-content: space-between; align-items: center; gap: 10px; user-select: none; }
@@ -394,11 +420,101 @@ details.hist-year-box > summary:hover { border-color: var(--accent); color: var(
394
420
  details.hist-year-box[open] > summary { border-bottom: 1px solid var(--line); }
395
421
  @media (max-width: 700px) { .brk-specs { grid-template-columns: 1fr; } }
396
422
 
397
- @media (max-width: 900px) {
423
+ @media (max-width: 960px) {
398
424
  body { overflow: auto; }
425
+ header { height: auto; min-height: 46px; padding: 6px 10px; flex-wrap: wrap; gap: 6px; }
399
426
  main { grid-template-columns: 1fr; height: auto; }
400
427
  #splitter { display: none; }
401
- .chat { height: 70vh; border-bottom: 1px solid var(--line); }
402
- .kpis { grid-template-columns: repeat(2, 1fr); }
428
+ .chat { height: 62vh; border-bottom: 1px solid var(--line); }
429
+ .tab { padding: 10px 12px 24px; overflow: visible; }
430
+ .settings-wrap { grid-template-columns: 1fr; gap: 12px; }
431
+ .snav { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; position: static; gap: 6px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
432
+ .snav button { white-space: nowrap; flex: none; padding: 6px 10px; font-size: 13px; border: 1px solid var(--line); }
433
+ .snav .ssep { display: none; }
434
+ .scard, .scard.spadded { padding: 12px 12px; }
435
+ .live-card, .live-card.collapsed { padding: 12px 12px; }
436
+ form#llm-add label, form#broker-form label { grid-template-columns: 1fr; gap: 4px; }
437
+ .modal { padding: 8px; }
438
+ .modal-box { max-height: calc(100vh - 16px); width: 100%; }
439
+ .kpis { grid-template-columns: repeat(auto-fit, minmax(135px, 1fr)); }
403
440
  .cmp-grid { grid-template-columns: 1fr; }
404
441
  }
442
+
443
+ /* Модальное окно досье акции — гарантированный вертикальный скролл без сжатия блоков */
444
+ .stock-modal-box {
445
+ max-width: 1000px;
446
+ width: min(1000px, 96vw);
447
+ max-height: calc(100vh - 36px);
448
+ display: flex;
449
+ flex-direction: column;
450
+ overflow: hidden;
451
+ }
452
+ .stock-modal-body {
453
+ flex: 1 1 auto;
454
+ min-height: 0;
455
+ overflow-y: auto;
456
+ overflow-x: hidden;
457
+ padding: 16px 18px 24px;
458
+ display: flex;
459
+ flex-direction: column;
460
+ gap: 14px;
461
+ }
462
+ .stock-modal-body > * {
463
+ flex-shrink: 0;
464
+ }
465
+ #stock-chart-box {
466
+ width: 100%;
467
+ height: 260px;
468
+ min-height: 260px;
469
+ position: relative;
470
+ }
471
+
472
+ /* Кликабельные метки акций (досье инструмента) */
473
+ .sym-link {
474
+ display: inline-flex;
475
+ align-items: center;
476
+ gap: 4px;
477
+ cursor: pointer;
478
+ color: inherit;
479
+ border-radius: 5px;
480
+ padding: 1px 5px;
481
+ margin: -1px -5px;
482
+ transition: background 0.14s, color 0.14s;
483
+ text-decoration: none;
484
+ }
485
+ .sym-link:hover {
486
+ background: rgba(59, 130, 246, 0.14);
487
+ color: var(--accent);
488
+ }
489
+ .sym-pill {
490
+ display: inline-flex;
491
+ align-items: center;
492
+ gap: 3px;
493
+ cursor: pointer;
494
+ padding: 1px 6px;
495
+ border-radius: 5px;
496
+ border: 1px solid var(--line);
497
+ background: var(--bg);
498
+ font-weight: 600;
499
+ font-size: 12px;
500
+ color: var(--text);
501
+ transition: border-color 0.14s, background 0.14s, color 0.14s;
502
+ }
503
+ .sym-pill:hover {
504
+ border-color: var(--accent);
505
+ background: rgba(59, 130, 246, 0.12);
506
+ color: var(--accent);
507
+ }
508
+ .stock-trait-bar {
509
+ height: 6px;
510
+ border-radius: 4px;
511
+ background: var(--line);
512
+ overflow: hidden;
513
+ width: 90px;
514
+ flex: none;
515
+ }
516
+ .stock-trait-bar > div {
517
+ height: 100%;
518
+ background: var(--accent);
519
+ border-radius: 4px;
520
+ }