brainzlab 0.1.1 → 0.1.2

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -0
  3. data/lib/brainzlab/beacon/client.rb +209 -0
  4. data/lib/brainzlab/beacon/provisioner.rb +44 -0
  5. data/lib/brainzlab/beacon.rb +215 -0
  6. data/lib/brainzlab/configuration.rb +341 -3
  7. data/lib/brainzlab/cortex/cache.rb +59 -0
  8. data/lib/brainzlab/cortex/client.rb +141 -0
  9. data/lib/brainzlab/cortex/provisioner.rb +49 -0
  10. data/lib/brainzlab/cortex.rb +227 -0
  11. data/lib/brainzlab/dendrite/client.rb +232 -0
  12. data/lib/brainzlab/dendrite/provisioner.rb +44 -0
  13. data/lib/brainzlab/dendrite.rb +195 -0
  14. data/lib/brainzlab/devtools/assets/devtools.css +1106 -0
  15. data/lib/brainzlab/devtools/assets/devtools.js +322 -0
  16. data/lib/brainzlab/devtools/assets/logo.svg +6 -0
  17. data/lib/brainzlab/devtools/assets/templates/debug_panel.html.erb +500 -0
  18. data/lib/brainzlab/devtools/assets/templates/error_page.html.erb +1086 -0
  19. data/lib/brainzlab/devtools/data/collector.rb +248 -0
  20. data/lib/brainzlab/devtools/middleware/asset_server.rb +63 -0
  21. data/lib/brainzlab/devtools/middleware/database_handler.rb +180 -0
  22. data/lib/brainzlab/devtools/middleware/debug_panel.rb +126 -0
  23. data/lib/brainzlab/devtools/middleware/error_page.rb +376 -0
  24. data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +155 -0
  25. data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +94 -0
  26. data/lib/brainzlab/devtools.rb +75 -0
  27. data/lib/brainzlab/flux/buffer.rb +96 -0
  28. data/lib/brainzlab/flux/client.rb +70 -0
  29. data/lib/brainzlab/flux/provisioner.rb +57 -0
  30. data/lib/brainzlab/flux.rb +174 -0
  31. data/lib/brainzlab/instrumentation/active_record.rb +18 -1
  32. data/lib/brainzlab/instrumentation/aws.rb +179 -0
  33. data/lib/brainzlab/instrumentation/dalli.rb +108 -0
  34. data/lib/brainzlab/instrumentation/excon.rb +152 -0
  35. data/lib/brainzlab/instrumentation/good_job.rb +102 -0
  36. data/lib/brainzlab/instrumentation/resque.rb +115 -0
  37. data/lib/brainzlab/instrumentation/solid_queue.rb +198 -0
  38. data/lib/brainzlab/instrumentation/stripe.rb +164 -0
  39. data/lib/brainzlab/instrumentation/typhoeus.rb +104 -0
  40. data/lib/brainzlab/instrumentation.rb +72 -0
  41. data/lib/brainzlab/nerve/client.rb +217 -0
  42. data/lib/brainzlab/nerve/provisioner.rb +44 -0
  43. data/lib/brainzlab/nerve.rb +219 -0
  44. data/lib/brainzlab/pulse/instrumentation.rb +35 -2
  45. data/lib/brainzlab/pulse/propagation.rb +1 -1
  46. data/lib/brainzlab/pulse/tracer.rb +1 -1
  47. data/lib/brainzlab/pulse.rb +1 -1
  48. data/lib/brainzlab/rails/log_subscriber.rb +1 -2
  49. data/lib/brainzlab/rails/railtie.rb +36 -3
  50. data/lib/brainzlab/recall/provisioner.rb +17 -0
  51. data/lib/brainzlab/recall.rb +6 -1
  52. data/lib/brainzlab/reflex.rb +2 -2
  53. data/lib/brainzlab/sentinel/client.rb +218 -0
  54. data/lib/brainzlab/sentinel/provisioner.rb +44 -0
  55. data/lib/brainzlab/sentinel.rb +165 -0
  56. data/lib/brainzlab/signal/client.rb +62 -0
  57. data/lib/brainzlab/signal/provisioner.rb +55 -0
  58. data/lib/brainzlab/signal.rb +136 -0
  59. data/lib/brainzlab/synapse/client.rb +290 -0
  60. data/lib/brainzlab/synapse/provisioner.rb +44 -0
  61. data/lib/brainzlab/synapse.rb +270 -0
  62. data/lib/brainzlab/utilities/circuit_breaker.rb +265 -0
  63. data/lib/brainzlab/utilities/health_check.rb +296 -0
  64. data/lib/brainzlab/utilities/log_formatter.rb +256 -0
  65. data/lib/brainzlab/utilities/rate_limiter.rb +230 -0
  66. data/lib/brainzlab/utilities.rb +17 -0
  67. data/lib/brainzlab/vault/cache.rb +80 -0
  68. data/lib/brainzlab/vault/client.rb +198 -0
  69. data/lib/brainzlab/vault/provisioner.rb +49 -0
  70. data/lib/brainzlab/vault.rb +268 -0
  71. data/lib/brainzlab/version.rb +1 -1
  72. data/lib/brainzlab/vision/client.rb +128 -0
  73. data/lib/brainzlab/vision/provisioner.rb +136 -0
  74. data/lib/brainzlab/vision.rb +157 -0
  75. data/lib/brainzlab.rb +101 -0
  76. metadata +60 -1
@@ -0,0 +1,1106 @@
1
+ /* BrainzLab DevTools - Brainz Design System */
2
+
3
+ :root {
4
+ --brainz-cream-50: #FFFDFB;
5
+ --brainz-cream-100: #FFF8F0;
6
+ --brainz-cream-200: #F5EDE3;
7
+ --brainz-cream-300: #E8DED3;
8
+ --brainz-orange: #FF6B35;
9
+ --brainz-orange-dark: #E55A2B;
10
+ --brainz-orange-light: #FF8A5C;
11
+ --brainz-text: #2D3748;
12
+ --brainz-text-muted: #718096;
13
+ --brainz-text-light: #A0AEC0;
14
+ --brainz-border: #E2E8F0;
15
+ --brainz-border-dark: #CBD5E0;
16
+ --brainz-error: #E53E3E;
17
+ --brainz-error-light: #FED7D7;
18
+ --brainz-success: #38A169;
19
+ --brainz-success-light: #C6F6D5;
20
+ --brainz-warning: #D69E2E;
21
+ --brainz-warning-light: #FEFCBF;
22
+ --brainz-info: #3182CE;
23
+ --brainz-info-light: #BEE3F8;
24
+ --brainz-code-bg: #1A202C;
25
+ --brainz-code-text: #E2E8F0;
26
+ --brainz-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
27
+ --brainz-mono: "SF Mono", "Monaco", "Inconsolata", "Fira Code", "Droid Sans Mono", monospace;
28
+ --brainz-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
29
+ --brainz-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
30
+ }
31
+
32
+ /* ============================================
33
+ ERROR PAGE STYLES
34
+ ============================================ */
35
+
36
+ .brainz-error-page {
37
+ font-family: var(--brainz-font);
38
+ background: var(--brainz-cream-100);
39
+ min-height: 100vh;
40
+ padding: 2rem;
41
+ margin: 0;
42
+ color: var(--brainz-text);
43
+ line-height: 1.6;
44
+ }
45
+
46
+ .brainz-error-page * {
47
+ box-sizing: border-box;
48
+ }
49
+
50
+ .brainz-container {
51
+ max-width: 1200px;
52
+ margin: 0 auto;
53
+ }
54
+
55
+ /* Error Header */
56
+ .brainz-error-header {
57
+ background: linear-gradient(135deg, var(--brainz-orange), var(--brainz-orange-dark));
58
+ color: white;
59
+ padding: 2rem;
60
+ border-radius: 12px;
61
+ margin-bottom: 1.5rem;
62
+ box-shadow: var(--brainz-shadow-lg);
63
+ }
64
+
65
+ .brainz-error-header-content {
66
+ display: flex;
67
+ align-items: flex-start;
68
+ gap: 1rem;
69
+ }
70
+
71
+ .brainz-logo {
72
+ flex-shrink: 0;
73
+ }
74
+
75
+ .brainz-logo img {
76
+ width: 40px;
77
+ height: 40px;
78
+ }
79
+
80
+ .brainz-error-title {
81
+ font-size: 1.5rem;
82
+ font-weight: 700;
83
+ margin: 0 0 0.5rem 0;
84
+ letter-spacing: -0.025em;
85
+ }
86
+
87
+ .brainz-error-message {
88
+ font-size: 1rem;
89
+ opacity: 0.95;
90
+ margin: 0;
91
+ word-break: break-word;
92
+ }
93
+
94
+ /* Sections */
95
+ .brainz-section {
96
+ background: white;
97
+ border-radius: 12px;
98
+ padding: 1.5rem;
99
+ margin-bottom: 1rem;
100
+ box-shadow: var(--brainz-shadow);
101
+ }
102
+
103
+ .brainz-section h2 {
104
+ font-size: 0.875rem;
105
+ font-weight: 600;
106
+ text-transform: uppercase;
107
+ letter-spacing: 0.05em;
108
+ color: var(--brainz-text-muted);
109
+ margin: 0 0 1rem 0;
110
+ padding-bottom: 0.5rem;
111
+ border-bottom: 1px solid var(--brainz-border);
112
+ }
113
+
114
+ .brainz-section h3 {
115
+ font-size: 0.8125rem;
116
+ font-weight: 600;
117
+ color: var(--brainz-text);
118
+ margin: 1rem 0 0.5rem 0;
119
+ }
120
+
121
+ /* File Path */
122
+ .brainz-file-path {
123
+ font-family: var(--brainz-mono);
124
+ font-size: 0.8125rem;
125
+ color: var(--brainz-text-muted);
126
+ margin-bottom: 0.75rem;
127
+ padding: 0.5rem 0.75rem;
128
+ background: var(--brainz-cream-200);
129
+ border-radius: 6px;
130
+ }
131
+
132
+ /* Source Code */
133
+ .brainz-source-code {
134
+ background: var(--brainz-code-bg);
135
+ border-radius: 8px;
136
+ padding: 1rem;
137
+ overflow-x: auto;
138
+ margin: 0;
139
+ }
140
+
141
+ .brainz-source-line {
142
+ font-family: var(--brainz-mono);
143
+ font-size: 0.8125rem;
144
+ line-height: 1.7;
145
+ color: var(--brainz-code-text);
146
+ display: flex;
147
+ gap: 1rem;
148
+ padding: 0 0.5rem;
149
+ margin: 0 -0.5rem;
150
+ }
151
+
152
+ .brainz-source-line.highlight {
153
+ background: rgba(255, 107, 53, 0.25);
154
+ border-left: 3px solid var(--brainz-orange);
155
+ margin-left: -1rem;
156
+ padding-left: calc(1rem - 3px);
157
+ }
158
+
159
+ .brainz-source-line .line-number {
160
+ color: var(--brainz-text-muted);
161
+ min-width: 3rem;
162
+ text-align: right;
163
+ user-select: none;
164
+ flex-shrink: 0;
165
+ }
166
+
167
+ .brainz-source-line .line-content {
168
+ white-space: pre;
169
+ }
170
+
171
+ /* Backtrace */
172
+ .brainz-backtrace {
173
+ font-family: var(--brainz-mono);
174
+ font-size: 0.8125rem;
175
+ max-height: 400px;
176
+ overflow-y: auto;
177
+ }
178
+
179
+ .brainz-frame {
180
+ padding: 0.5rem 0.75rem;
181
+ margin: 0 -0.75rem;
182
+ border-radius: 4px;
183
+ display: flex;
184
+ gap: 0.25rem;
185
+ flex-wrap: wrap;
186
+ }
187
+
188
+ .brainz-frame:hover {
189
+ background: var(--brainz-cream-200);
190
+ }
191
+
192
+ .brainz-frame.in-app {
193
+ color: var(--brainz-text);
194
+ font-weight: 500;
195
+ }
196
+
197
+ .brainz-frame:not(.in-app) {
198
+ color: var(--brainz-text-muted);
199
+ }
200
+
201
+ .brainz-frame.first {
202
+ background: var(--brainz-error-light);
203
+ color: var(--brainz-error);
204
+ font-weight: 600;
205
+ }
206
+
207
+ .brainz-frame .frame-file {
208
+ word-break: break-all;
209
+ }
210
+
211
+ .brainz-frame .frame-line {
212
+ color: var(--brainz-orange);
213
+ }
214
+
215
+ .brainz-frame .frame-function {
216
+ color: var(--brainz-text-muted);
217
+ }
218
+
219
+ /* Info Tables */
220
+ .brainz-info-table {
221
+ width: 100%;
222
+ font-size: 0.875rem;
223
+ border-collapse: collapse;
224
+ }
225
+
226
+ .brainz-info-table th,
227
+ .brainz-info-table td {
228
+ padding: 0.5rem 0.75rem;
229
+ text-align: left;
230
+ border-bottom: 1px solid var(--brainz-border);
231
+ }
232
+
233
+ .brainz-info-table th {
234
+ width: 140px;
235
+ color: var(--brainz-text-muted);
236
+ font-weight: 500;
237
+ }
238
+
239
+ .brainz-info-table td {
240
+ font-family: var(--brainz-mono);
241
+ font-size: 0.8125rem;
242
+ color: var(--brainz-text);
243
+ word-break: break-all;
244
+ }
245
+
246
+ /* Parameters */
247
+ .brainz-params {
248
+ background: var(--brainz-cream-200);
249
+ border-radius: 8px;
250
+ padding: 1rem;
251
+ font-family: var(--brainz-mono);
252
+ font-size: 0.8125rem;
253
+ overflow-x: auto;
254
+ white-space: pre-wrap;
255
+ margin: 0;
256
+ }
257
+
258
+ /* Query Table */
259
+ .brainz-query-table {
260
+ width: 100%;
261
+ font-size: 0.8125rem;
262
+ border-collapse: collapse;
263
+ }
264
+
265
+ .brainz-query-table th,
266
+ .brainz-query-table td {
267
+ padding: 0.5rem;
268
+ text-align: left;
269
+ border-bottom: 1px solid var(--brainz-border);
270
+ }
271
+
272
+ .brainz-query-table th {
273
+ color: var(--brainz-text-muted);
274
+ font-weight: 500;
275
+ background: var(--brainz-cream-100);
276
+ }
277
+
278
+ .brainz-query-duration {
279
+ font-family: var(--brainz-mono);
280
+ font-size: 0.75rem;
281
+ white-space: nowrap;
282
+ }
283
+
284
+ .brainz-query-duration.slow {
285
+ color: var(--brainz-warning);
286
+ font-weight: 600;
287
+ }
288
+
289
+ .brainz-query-duration.very-slow {
290
+ color: var(--brainz-error);
291
+ font-weight: 600;
292
+ }
293
+
294
+ .brainz-query-sql {
295
+ font-family: var(--brainz-mono);
296
+ font-size: 0.75rem;
297
+ color: var(--brainz-text-muted);
298
+ max-width: 500px;
299
+ overflow: hidden;
300
+ text-overflow: ellipsis;
301
+ white-space: nowrap;
302
+ }
303
+
304
+ /* ============================================
305
+ DEBUG PANEL STYLES
306
+ ============================================ */
307
+
308
+ .brainz-debug-panel {
309
+ position: fixed;
310
+ bottom: 0;
311
+ left: 0;
312
+ right: 0;
313
+ max-height: 50vh;
314
+ background: white;
315
+ border-top: 3px solid var(--brainz-orange);
316
+ box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);
317
+ font-family: var(--brainz-font);
318
+ z-index: 999999;
319
+ display: flex;
320
+ flex-direction: column;
321
+ transition: max-height 0.2s ease;
322
+ }
323
+
324
+ .brainz-debug-panel * {
325
+ box-sizing: border-box;
326
+ }
327
+
328
+ .brainz-debug-panel.collapsed {
329
+ max-height: 44px;
330
+ overflow: hidden;
331
+ }
332
+
333
+ .brainz-debug-panel.collapsed .brainz-debug-tabs,
334
+ .brainz-debug-panel.collapsed .brainz-debug-content {
335
+ display: none;
336
+ }
337
+
338
+ /* Toolbar */
339
+ .brainz-debug-toolbar {
340
+ display: flex;
341
+ align-items: center;
342
+ padding: 0.5rem 1rem;
343
+ background: var(--brainz-cream-100);
344
+ border-bottom: 1px solid var(--brainz-border);
345
+ gap: 0.75rem;
346
+ cursor: pointer;
347
+ min-height: 44px;
348
+ flex-shrink: 0;
349
+ }
350
+
351
+ .brainz-debug-toolbar:hover {
352
+ background: var(--brainz-cream-200);
353
+ }
354
+
355
+ .brainz-debug-logo {
356
+ width: 24px;
357
+ height: 24px;
358
+ flex-shrink: 0;
359
+ }
360
+
361
+ .brainz-debug-stat {
362
+ font-size: 0.75rem;
363
+ padding: 0.25rem 0.5rem;
364
+ border-radius: 4px;
365
+ background: white;
366
+ border: 1px solid var(--brainz-border);
367
+ display: flex;
368
+ align-items: center;
369
+ gap: 0.25rem;
370
+ }
371
+
372
+ .brainz-debug-stat strong {
373
+ font-weight: 600;
374
+ color: var(--brainz-text);
375
+ }
376
+
377
+ .brainz-debug-stat.error {
378
+ background: var(--brainz-error-light);
379
+ border-color: var(--brainz-error);
380
+ color: var(--brainz-error);
381
+ }
382
+
383
+ .brainz-debug-stat.warning {
384
+ background: var(--brainz-warning-light);
385
+ border-color: var(--brainz-warning);
386
+ color: var(--brainz-warning);
387
+ }
388
+
389
+ .brainz-debug-stat.success {
390
+ background: var(--brainz-success-light);
391
+ border-color: var(--brainz-success);
392
+ color: var(--brainz-success);
393
+ }
394
+
395
+ .brainz-debug-expand {
396
+ margin-left: auto;
397
+ color: var(--brainz-text-muted);
398
+ transition: transform 0.2s ease;
399
+ }
400
+
401
+ .brainz-debug-panel.collapsed .brainz-debug-expand {
402
+ transform: rotate(180deg);
403
+ }
404
+
405
+ /* Performance Score */
406
+ .brainz-score {
407
+ position: relative;
408
+ width: 32px;
409
+ height: 32px;
410
+ flex-shrink: 0;
411
+ }
412
+
413
+ .brainz-score-ring {
414
+ width: 100%;
415
+ height: 100%;
416
+ }
417
+
418
+ .brainz-score-bg {
419
+ stroke: #E5E5E5;
420
+ }
421
+
422
+ .brainz-score-progress {
423
+ stroke-linecap: round;
424
+ transition: stroke-dasharray 0.3s ease;
425
+ }
426
+
427
+ .brainz-score-value {
428
+ position: absolute;
429
+ inset: 0;
430
+ display: flex;
431
+ align-items: center;
432
+ justify-content: center;
433
+ font-size: 0.6875rem;
434
+ font-weight: 600;
435
+ color: #1A1A1A;
436
+ }
437
+
438
+ /* Score grades */
439
+ .brainz-score.excellent .brainz-score-progress { stroke: #22C55E; }
440
+ .brainz-score.excellent .brainz-score-value { color: #16A34A; }
441
+
442
+ .brainz-score.good .brainz-score-progress { stroke: #3B82F6; }
443
+ .brainz-score.good .brainz-score-value { color: #2563EB; }
444
+
445
+ .brainz-score.warning .brainz-score-progress { stroke: #F59E0B; }
446
+ .brainz-score.warning .brainz-score-value { color: #D97706; }
447
+
448
+ .brainz-score.poor .brainz-score-progress { stroke: #EF4444; }
449
+ .brainz-score.poor .brainz-score-value { color: #DC2626; }
450
+
451
+ /* Tabs */
452
+ .brainz-debug-tabs {
453
+ display: flex;
454
+ background: var(--brainz-cream-200);
455
+ border-bottom: 1px solid var(--brainz-border);
456
+ flex-shrink: 0;
457
+ overflow-x: auto;
458
+ }
459
+
460
+ .brainz-debug-tab {
461
+ padding: 0.625rem 1rem;
462
+ font-size: 0.8125rem;
463
+ font-weight: 500;
464
+ border: none;
465
+ background: none;
466
+ cursor: pointer;
467
+ color: var(--brainz-text-muted);
468
+ white-space: nowrap;
469
+ transition: all 0.15s ease;
470
+ }
471
+
472
+ .brainz-debug-tab:hover {
473
+ color: var(--brainz-text);
474
+ background: var(--brainz-cream-100);
475
+ }
476
+
477
+ .brainz-debug-tab.active {
478
+ color: var(--brainz-orange);
479
+ background: white;
480
+ box-shadow: inset 0 -2px 0 var(--brainz-orange);
481
+ }
482
+
483
+ .brainz-debug-tab .badge {
484
+ display: inline-flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ min-width: 18px;
488
+ height: 18px;
489
+ padding: 0 5px;
490
+ margin-left: 0.375rem;
491
+ font-size: 0.6875rem;
492
+ font-weight: 600;
493
+ background: var(--brainz-border);
494
+ border-radius: 9px;
495
+ color: var(--brainz-text-muted);
496
+ }
497
+
498
+ .brainz-debug-tab.active .badge {
499
+ background: var(--brainz-orange);
500
+ color: white;
501
+ }
502
+
503
+ /* Content */
504
+ .brainz-debug-content {
505
+ flex: 1;
506
+ overflow: auto;
507
+ padding: 1rem;
508
+ background: white;
509
+ }
510
+
511
+ /* Panes */
512
+ .brainz-debug-pane {
513
+ display: none;
514
+ }
515
+
516
+ .brainz-debug-pane.active {
517
+ display: block;
518
+ }
519
+
520
+ /* Alert Box */
521
+ .brainz-alert {
522
+ padding: 0.75rem 1rem;
523
+ border-radius: 8px;
524
+ margin-bottom: 1rem;
525
+ font-size: 0.8125rem;
526
+ }
527
+
528
+ .brainz-alert.error {
529
+ background: var(--brainz-error-light);
530
+ border-left: 3px solid var(--brainz-error);
531
+ color: var(--brainz-error);
532
+ }
533
+
534
+ .brainz-alert.warning {
535
+ background: var(--brainz-warning-light);
536
+ border-left: 3px solid var(--brainz-warning);
537
+ color: var(--brainz-warning);
538
+ }
539
+
540
+ .brainz-alert strong {
541
+ font-weight: 600;
542
+ }
543
+
544
+ /* N+1 Detection */
545
+ .brainz-n-plus-one {
546
+ background: rgba(229, 62, 62, 0.05);
547
+ border-left: 3px solid var(--brainz-error);
548
+ padding: 0.5rem 0.75rem;
549
+ margin-top: 0.5rem;
550
+ font-size: 0.8125rem;
551
+ border-radius: 0 6px 6px 0;
552
+ }
553
+
554
+ .brainz-n-plus-one-header {
555
+ display: flex;
556
+ align-items: center;
557
+ justify-content: space-between;
558
+ gap: 0.5rem;
559
+ flex-wrap: wrap;
560
+ }
561
+
562
+ .brainz-n-plus-one code {
563
+ display: block;
564
+ margin-top: 0.375rem;
565
+ font-family: var(--brainz-mono);
566
+ font-size: 0.75rem;
567
+ color: var(--brainz-text-muted);
568
+ overflow: hidden;
569
+ text-overflow: ellipsis;
570
+ white-space: nowrap;
571
+ }
572
+
573
+ .brainz-n-plus-one .source {
574
+ color: var(--brainz-text-light);
575
+ font-size: 0.75rem;
576
+ margin-left: 0.5rem;
577
+ }
578
+
579
+ /* Copy to AI Button */
580
+ .brainz-copy-to-ai-btn {
581
+ display: inline-flex;
582
+ align-items: center;
583
+ gap: 0.375rem;
584
+ padding: 0.25rem 0.5rem;
585
+ font-size: 0.6875rem;
586
+ font-weight: 500;
587
+ font-family: var(--brainz-font);
588
+ color: var(--brainz-orange);
589
+ background: white;
590
+ border: 1px solid var(--brainz-orange);
591
+ border-radius: 4px;
592
+ cursor: pointer;
593
+ transition: all 0.15s ease;
594
+ flex-shrink: 0;
595
+ }
596
+
597
+ .brainz-copy-to-ai-btn:hover {
598
+ background: var(--brainz-orange);
599
+ color: white;
600
+ }
601
+
602
+ .brainz-copy-to-ai-btn:active {
603
+ transform: scale(0.95);
604
+ }
605
+
606
+ .brainz-copy-to-ai-btn svg {
607
+ flex-shrink: 0;
608
+ }
609
+
610
+ /* ============================================
611
+ ISSUES TAB - Anthropic/Claude Design
612
+ Clean, minimal, warm, elegant
613
+ ============================================ */
614
+
615
+ /* Issues Tab styling */
616
+ .brainz-debug-tab.has-issues {
617
+ color: #C35A3C;
618
+ }
619
+
620
+ .brainz-debug-tab .badge.error {
621
+ background: #C35A3C;
622
+ color: white;
623
+ }
624
+
625
+ /* No Issues State */
626
+ .brainz-no-issues {
627
+ display: flex;
628
+ flex-direction: column;
629
+ align-items: center;
630
+ justify-content: center;
631
+ padding: 3rem 2rem;
632
+ text-align: center;
633
+ }
634
+
635
+ .brainz-no-issues svg {
636
+ width: 48px;
637
+ height: 48px;
638
+ margin-bottom: 1rem;
639
+ color: #16A34A;
640
+ }
641
+
642
+ .brainz-no-issues p {
643
+ font-size: 0.9375rem;
644
+ font-weight: 500;
645
+ color: #1A1A1A;
646
+ margin: 0 0 0.25rem 0;
647
+ }
648
+
649
+ .brainz-no-issues span {
650
+ font-size: 0.8125rem;
651
+ color: #6B6B6B;
652
+ }
653
+
654
+ /* Issues Container */
655
+ .brainz-issues-container {
656
+ display: flex;
657
+ flex-direction: column;
658
+ gap: 0.75rem;
659
+ }
660
+
661
+ /* Issue Section */
662
+ .brainz-issue-section {
663
+ border: 1px solid #E5E5E5;
664
+ border-radius: 8px;
665
+ overflow: hidden;
666
+ }
667
+
668
+ /* Issue Header */
669
+ .brainz-issue-header {
670
+ display: flex;
671
+ align-items: center;
672
+ gap: 0.5rem;
673
+ padding: 0.625rem 0.875rem;
674
+ font-size: 0.8125rem;
675
+ font-weight: 500;
676
+ color: #1A1A1A;
677
+ background: #FAFAFA;
678
+ border-bottom: 1px solid #E5E5E5;
679
+ }
680
+
681
+ .brainz-issue-header.error {
682
+ background: #FEF2F2;
683
+ color: #B91C1C;
684
+ }
685
+
686
+ .brainz-issue-header.warning {
687
+ background: #FFFBEB;
688
+ color: #B45309;
689
+ }
690
+
691
+ .brainz-issue-header svg {
692
+ flex-shrink: 0;
693
+ width: 14px;
694
+ height: 14px;
695
+ }
696
+
697
+ .brainz-issue-header .issue-count {
698
+ margin-left: auto;
699
+ font-size: 0.6875rem;
700
+ font-weight: 500;
701
+ color: inherit;
702
+ opacity: 0.7;
703
+ }
704
+
705
+ /* Issue Item */
706
+ .brainz-issue-item {
707
+ display: flex;
708
+ align-items: flex-start;
709
+ justify-content: space-between;
710
+ gap: 1rem;
711
+ padding: 0.75rem 0.875rem;
712
+ background: white;
713
+ border-bottom: 1px solid #F3F3F3;
714
+ }
715
+
716
+ .brainz-issue-item:last-child {
717
+ border-bottom: none;
718
+ }
719
+
720
+ /* Issue Content */
721
+ .brainz-issue-content {
722
+ flex: 1;
723
+ min-width: 0;
724
+ font-size: 0.8125rem;
725
+ line-height: 1.5;
726
+ color: #374151;
727
+ }
728
+
729
+ .brainz-issue-content strong {
730
+ color: #1A1A1A;
731
+ font-weight: 600;
732
+ }
733
+
734
+ .brainz-issue-content code {
735
+ display: block;
736
+ margin-top: 0.5rem;
737
+ padding: 0.5rem;
738
+ font-family: var(--brainz-mono);
739
+ font-size: 0.6875rem;
740
+ color: #6B7280;
741
+ background: #F9FAFB;
742
+ border-radius: 4px;
743
+ overflow: hidden;
744
+ text-overflow: ellipsis;
745
+ white-space: nowrap;
746
+ }
747
+
748
+ .brainz-issue-source {
749
+ font-size: 0.6875rem;
750
+ color: #9CA3AF;
751
+ margin-left: 0.25rem;
752
+ }
753
+
754
+ .brainz-issue-source::before {
755
+ content: "·";
756
+ margin-right: 0.25rem;
757
+ }
758
+
759
+ .brainz-issue-name {
760
+ color: #6B7280;
761
+ font-weight: 400;
762
+ }
763
+
764
+ .brainz-issue-hint {
765
+ display: block;
766
+ margin-top: 0.375rem;
767
+ font-size: 0.75rem;
768
+ color: #9CA3AF;
769
+ }
770
+
771
+ /* Issue Metric Badge */
772
+ .brainz-issue-metric {
773
+ display: inline-flex;
774
+ align-items: center;
775
+ padding: 0.125rem 0.375rem;
776
+ font-size: 0.6875rem;
777
+ font-weight: 600;
778
+ border-radius: 4px;
779
+ margin-right: 0.375rem;
780
+ }
781
+
782
+ .brainz-issue-metric.critical {
783
+ background: #FEE2E2;
784
+ color: #B91C1C;
785
+ }
786
+
787
+ .brainz-issue-metric.slow {
788
+ background: #FEF3C7;
789
+ color: #B45309;
790
+ }
791
+
792
+ /* Copy to AI Button - Clean minimal style */
793
+ .brainz-copy-to-ai-btn {
794
+ display: inline-flex;
795
+ align-items: center;
796
+ gap: 0.375rem;
797
+ padding: 0.375rem 0.625rem;
798
+ font-size: 0.6875rem;
799
+ font-weight: 500;
800
+ font-family: var(--brainz-font);
801
+ color: var(--brainz-text-muted);
802
+ background: white;
803
+ border: 1px solid var(--brainz-border);
804
+ border-radius: 6px;
805
+ cursor: pointer;
806
+ transition: all 0.15s ease;
807
+ flex-shrink: 0;
808
+ }
809
+
810
+ .brainz-copy-to-ai-btn:hover {
811
+ color: var(--brainz-text);
812
+ border-color: var(--brainz-text-muted);
813
+ background: var(--brainz-cream-100);
814
+ }
815
+
816
+ .brainz-copy-to-ai-btn:active {
817
+ transform: scale(0.97);
818
+ }
819
+
820
+ .brainz-copy-to-ai-btn.copied {
821
+ color: var(--brainz-success);
822
+ border-color: var(--brainz-success);
823
+ }
824
+
825
+ .brainz-copy-to-ai-btn svg {
826
+ flex-shrink: 0;
827
+ opacity: 0.7;
828
+ }
829
+
830
+ /* Toast notification */
831
+ .brainz-toast {
832
+ position: fixed;
833
+ bottom: 60px;
834
+ right: 20px;
835
+ padding: 0.5rem 1rem;
836
+ background: var(--brainz-code-bg);
837
+ color: white;
838
+ border-radius: 6px;
839
+ font-size: 0.8125rem;
840
+ font-family: var(--brainz-font);
841
+ z-index: 1000001;
842
+ opacity: 0;
843
+ transform: translateY(8px);
844
+ transition: opacity 0.2s ease, transform 0.2s ease;
845
+ }
846
+
847
+ .brainz-toast.visible {
848
+ opacity: 1;
849
+ transform: translateY(0);
850
+ }
851
+
852
+ /* Slow indicators */
853
+ .brainz-query-row.slow {
854
+ background: rgba(214, 158, 46, 0.08);
855
+ }
856
+
857
+ .brainz-slow {
858
+ color: var(--brainz-warning) !important;
859
+ font-weight: 600;
860
+ }
861
+
862
+ /* View Table */
863
+ .brainz-view-table {
864
+ width: 100%;
865
+ font-size: 0.8125rem;
866
+ border-collapse: collapse;
867
+ }
868
+
869
+ .brainz-view-table th,
870
+ .brainz-view-table td {
871
+ padding: 0.5rem;
872
+ text-align: left;
873
+ border-bottom: 1px solid var(--brainz-border);
874
+ }
875
+
876
+ .brainz-view-table th {
877
+ color: var(--brainz-text-muted);
878
+ font-weight: 500;
879
+ background: var(--brainz-cream-100);
880
+ }
881
+
882
+ /* Log Entry */
883
+ .brainz-log-entry {
884
+ display: flex;
885
+ align-items: flex-start;
886
+ gap: 0.75rem;
887
+ padding: 0.375rem 0;
888
+ font-size: 0.8125rem;
889
+ border-bottom: 1px solid var(--brainz-border);
890
+ }
891
+
892
+ .brainz-log-entry:last-child {
893
+ border-bottom: none;
894
+ }
895
+
896
+ .brainz-log-entry .log-level {
897
+ font-size: 0.6875rem;
898
+ font-weight: 600;
899
+ padding: 0.125rem 0.375rem;
900
+ border-radius: 3px;
901
+ text-transform: uppercase;
902
+ flex-shrink: 0;
903
+ min-width: 48px;
904
+ text-align: center;
905
+ }
906
+
907
+ .brainz-log-entry.error .log-level {
908
+ background: var(--brainz-error-light);
909
+ color: var(--brainz-error);
910
+ }
911
+
912
+ .brainz-log-entry.warning .log-level {
913
+ background: var(--brainz-warning-light);
914
+ color: var(--brainz-warning);
915
+ }
916
+
917
+ .brainz-log-entry.info .log-level {
918
+ background: var(--brainz-info-light);
919
+ color: var(--brainz-info);
920
+ }
921
+
922
+ .brainz-log-entry.debug .log-level {
923
+ background: var(--brainz-cream-200);
924
+ color: var(--brainz-text-muted);
925
+ }
926
+
927
+ .brainz-log-entry .log-time {
928
+ font-family: var(--brainz-mono);
929
+ font-size: 0.75rem;
930
+ color: var(--brainz-text-light);
931
+ flex-shrink: 0;
932
+ }
933
+
934
+ .brainz-log-entry .log-message {
935
+ flex: 1;
936
+ word-break: break-word;
937
+ }
938
+
939
+ /* Code Block */
940
+ .brainz-code-block {
941
+ background: var(--brainz-cream-200);
942
+ border-radius: 8px;
943
+ padding: 0.75rem 1rem;
944
+ font-family: var(--brainz-mono);
945
+ font-size: 0.75rem;
946
+ overflow-x: auto;
947
+ white-space: pre-wrap;
948
+ word-break: break-all;
949
+ margin: 0.5rem 0 0 0;
950
+ }
951
+
952
+ /* Timeline */
953
+ /* ============================================
954
+ TIMELINE - Clean Anthropic Design
955
+ ============================================ */
956
+
957
+ /* Header with total time */
958
+ .timeline-header {
959
+ display: flex;
960
+ align-items: baseline;
961
+ gap: 0.5rem;
962
+ margin-bottom: 1rem;
963
+ }
964
+
965
+ .timeline-total {
966
+ font-size: 1.75rem;
967
+ font-weight: 600;
968
+ color: #1A1A1A;
969
+ letter-spacing: -0.02em;
970
+ }
971
+
972
+ .timeline-label {
973
+ font-size: 0.8125rem;
974
+ color: #9CA3AF;
975
+ }
976
+
977
+ /* Timeline Bar */
978
+ .timeline-bar {
979
+ display: flex;
980
+ height: 8px;
981
+ background: #F3F4F6;
982
+ border-radius: 4px;
983
+ overflow: hidden;
984
+ margin-bottom: 1.25rem;
985
+ }
986
+
987
+ .timeline-segment {
988
+ display: flex;
989
+ align-items: center;
990
+ justify-content: center;
991
+ transition: opacity 0.15s ease;
992
+ }
993
+
994
+ .timeline-segment:hover {
995
+ opacity: 0.85;
996
+ }
997
+
998
+ .timeline-segment-label {
999
+ display: none;
1000
+ }
1001
+
1002
+ .timeline-segment.db {
1003
+ background: #3B82F6;
1004
+ }
1005
+
1006
+ .timeline-segment.views {
1007
+ background: #10B981;
1008
+ }
1009
+
1010
+ .timeline-segment.other {
1011
+ background: #9CA3AF;
1012
+ }
1013
+
1014
+ /* Stats Grid */
1015
+ .timeline-stats {
1016
+ display: flex;
1017
+ flex-direction: column;
1018
+ gap: 0.5rem;
1019
+ }
1020
+
1021
+ .timeline-stat {
1022
+ display: flex;
1023
+ align-items: center;
1024
+ gap: 0.75rem;
1025
+ padding: 0.625rem 0.75rem;
1026
+ background: #FAFAFA;
1027
+ border: 1px solid #F3F4F6;
1028
+ border-radius: 8px;
1029
+ }
1030
+
1031
+ .timeline-stat:hover {
1032
+ background: #F5F5F5;
1033
+ }
1034
+
1035
+ .timeline-stat-icon {
1036
+ display: flex;
1037
+ align-items: center;
1038
+ justify-content: center;
1039
+ width: 32px;
1040
+ height: 32px;
1041
+ border-radius: 6px;
1042
+ flex-shrink: 0;
1043
+ }
1044
+
1045
+ .timeline-stat-icon.db {
1046
+ background: #EFF6FF;
1047
+ color: #3B82F6;
1048
+ }
1049
+
1050
+ .timeline-stat-icon.views {
1051
+ background: #ECFDF5;
1052
+ color: #10B981;
1053
+ }
1054
+
1055
+ .timeline-stat-icon.other {
1056
+ background: #F3F4F6;
1057
+ color: #6B7280;
1058
+ }
1059
+
1060
+ .timeline-stat-content {
1061
+ flex: 1;
1062
+ min-width: 0;
1063
+ }
1064
+
1065
+ .timeline-stat-value {
1066
+ font-size: 0.9375rem;
1067
+ font-weight: 600;
1068
+ color: #1A1A1A;
1069
+ }
1070
+
1071
+ .timeline-stat-label {
1072
+ font-size: 0.75rem;
1073
+ color: #6B7280;
1074
+ margin-top: 0.125rem;
1075
+ }
1076
+
1077
+ .timeline-stat-pct {
1078
+ font-size: 0.8125rem;
1079
+ font-weight: 500;
1080
+ color: #9CA3AF;
1081
+ padding: 0.25rem 0.5rem;
1082
+ background: white;
1083
+ border-radius: 4px;
1084
+ }
1085
+
1086
+ /* Cached Query Styling */
1087
+ .brainz-query-row.cached {
1088
+ opacity: 0.6;
1089
+ }
1090
+
1091
+ .brainz-query-row.cached td:first-child::after {
1092
+ content: " (cached)";
1093
+ font-size: 0.6875rem;
1094
+ color: var(--brainz-text-light);
1095
+ }
1096
+
1097
+ /* Keyboard Hint */
1098
+ .brainz-keyboard-hint {
1099
+ font-size: 0.6875rem;
1100
+ color: var(--brainz-text-light);
1101
+ margin-left: auto;
1102
+ padding: 0.125rem 0.375rem;
1103
+ background: var(--brainz-cream-200);
1104
+ border-radius: 3px;
1105
+ font-family: var(--brainz-mono);
1106
+ }