panelbox 0.2.0__py3-none-any.whl

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 (90) hide show
  1. panelbox/__init__.py +67 -0
  2. panelbox/__version__.py +14 -0
  3. panelbox/cli/__init__.py +0 -0
  4. panelbox/cli/{commands}/__init__.py +0 -0
  5. panelbox/core/__init__.py +0 -0
  6. panelbox/core/base_model.py +164 -0
  7. panelbox/core/formula_parser.py +318 -0
  8. panelbox/core/panel_data.py +387 -0
  9. panelbox/core/results.py +366 -0
  10. panelbox/datasets/__init__.py +0 -0
  11. panelbox/datasets/{data}/__init__.py +0 -0
  12. panelbox/gmm/__init__.py +65 -0
  13. panelbox/gmm/difference_gmm.py +645 -0
  14. panelbox/gmm/estimator.py +562 -0
  15. panelbox/gmm/instruments.py +580 -0
  16. panelbox/gmm/results.py +550 -0
  17. panelbox/gmm/system_gmm.py +621 -0
  18. panelbox/gmm/tests.py +535 -0
  19. panelbox/models/__init__.py +11 -0
  20. panelbox/models/dynamic/__init__.py +0 -0
  21. panelbox/models/iv/__init__.py +0 -0
  22. panelbox/models/static/__init__.py +13 -0
  23. panelbox/models/static/fixed_effects.py +516 -0
  24. panelbox/models/static/pooled_ols.py +298 -0
  25. panelbox/models/static/random_effects.py +512 -0
  26. panelbox/report/__init__.py +61 -0
  27. panelbox/report/asset_manager.py +410 -0
  28. panelbox/report/css_manager.py +472 -0
  29. panelbox/report/exporters/__init__.py +15 -0
  30. panelbox/report/exporters/html_exporter.py +440 -0
  31. panelbox/report/exporters/latex_exporter.py +510 -0
  32. panelbox/report/exporters/markdown_exporter.py +446 -0
  33. panelbox/report/renderers/__init__.py +11 -0
  34. panelbox/report/renderers/static/__init__.py +0 -0
  35. panelbox/report/renderers/static_validation_renderer.py +341 -0
  36. panelbox/report/report_manager.py +502 -0
  37. panelbox/report/template_manager.py +337 -0
  38. panelbox/report/transformers/__init__.py +0 -0
  39. panelbox/report/transformers/static/__init__.py +0 -0
  40. panelbox/report/validation_transformer.py +449 -0
  41. panelbox/standard_errors/__init__.py +0 -0
  42. panelbox/templates/__init__.py +0 -0
  43. panelbox/templates/assets/css/base_styles.css +382 -0
  44. panelbox/templates/assets/css/report_components.css +747 -0
  45. panelbox/templates/assets/js/tab-navigation.js +161 -0
  46. panelbox/templates/assets/js/utils.js +276 -0
  47. panelbox/templates/common/footer.html +24 -0
  48. panelbox/templates/common/header.html +44 -0
  49. panelbox/templates/common/meta.html +5 -0
  50. panelbox/templates/validation/interactive/index.html +272 -0
  51. panelbox/templates/validation/interactive/partials/charts.html +58 -0
  52. panelbox/templates/validation/interactive/partials/methodology.html +201 -0
  53. panelbox/templates/validation/interactive/partials/overview.html +146 -0
  54. panelbox/templates/validation/interactive/partials/recommendations.html +101 -0
  55. panelbox/templates/validation/interactive/partials/test_results.html +231 -0
  56. panelbox/utils/__init__.py +0 -0
  57. panelbox/utils/formatting.py +172 -0
  58. panelbox/utils/matrix_ops.py +233 -0
  59. panelbox/utils/statistical.py +173 -0
  60. panelbox/validation/__init__.py +58 -0
  61. panelbox/validation/base.py +175 -0
  62. panelbox/validation/cointegration/__init__.py +0 -0
  63. panelbox/validation/cross_sectional_dependence/__init__.py +13 -0
  64. panelbox/validation/cross_sectional_dependence/breusch_pagan_lm.py +222 -0
  65. panelbox/validation/cross_sectional_dependence/frees.py +297 -0
  66. panelbox/validation/cross_sectional_dependence/pesaran_cd.py +188 -0
  67. panelbox/validation/heteroskedasticity/__init__.py +13 -0
  68. panelbox/validation/heteroskedasticity/breusch_pagan.py +222 -0
  69. panelbox/validation/heteroskedasticity/modified_wald.py +172 -0
  70. panelbox/validation/heteroskedasticity/white.py +208 -0
  71. panelbox/validation/instruments/__init__.py +0 -0
  72. panelbox/validation/robustness/__init__.py +0 -0
  73. panelbox/validation/serial_correlation/__init__.py +13 -0
  74. panelbox/validation/serial_correlation/baltagi_wu.py +220 -0
  75. panelbox/validation/serial_correlation/breusch_godfrey.py +260 -0
  76. panelbox/validation/serial_correlation/wooldridge_ar.py +200 -0
  77. panelbox/validation/specification/__init__.py +16 -0
  78. panelbox/validation/specification/chow.py +273 -0
  79. panelbox/validation/specification/hausman.py +264 -0
  80. panelbox/validation/specification/mundlak.py +331 -0
  81. panelbox/validation/specification/reset.py +273 -0
  82. panelbox/validation/unit_root/__init__.py +0 -0
  83. panelbox/validation/validation_report.py +257 -0
  84. panelbox/validation/validation_suite.py +401 -0
  85. panelbox-0.2.0.dist-info/METADATA +337 -0
  86. panelbox-0.2.0.dist-info/RECORD +90 -0
  87. panelbox-0.2.0.dist-info/WHEEL +5 -0
  88. panelbox-0.2.0.dist-info/entry_points.txt +2 -0
  89. panelbox-0.2.0.dist-info/licenses/LICENSE +21 -0
  90. panelbox-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,747 @@
1
+ /**
2
+ * PanelBox Reports - Component Styles (Layer 2)
3
+ * ==============================================
4
+ *
5
+ * Reusable components for all report types.
6
+ * Built on top of base_styles.css (Layer 1).
7
+ *
8
+ * Size: ~15-20 KB
9
+ * Version: 1.0.0
10
+ */
11
+
12
+ /* ============================================
13
+ REPORT CONTAINER
14
+ ============================================ */
15
+
16
+ .report-container {
17
+ max-width: 1280px;
18
+ margin: 0 auto;
19
+ padding: var(--space-6);
20
+ background-color: #ffffff;
21
+ min-height: 100vh;
22
+ }
23
+
24
+ .report-content {
25
+ margin-top: var(--space-6);
26
+ }
27
+
28
+ .report-section {
29
+ margin-bottom: var(--space-8);
30
+ }
31
+
32
+ .report-section:last-child {
33
+ margin-bottom: 0;
34
+ }
35
+
36
+ /* ============================================
37
+ HEADER
38
+ ============================================ */
39
+
40
+ .report-header {
41
+ border-bottom: 2px solid var(--gray-200);
42
+ padding-bottom: var(--space-6);
43
+ margin-bottom: var(--space-8);
44
+ }
45
+
46
+ .report-title {
47
+ font-size: var(--text-4xl);
48
+ font-weight: var(--font-bold);
49
+ color: var(--gray-900);
50
+ margin-bottom: var(--space-2);
51
+ }
52
+
53
+ .report-subtitle {
54
+ font-size: var(--text-lg);
55
+ color: var(--gray-600);
56
+ margin-bottom: var(--space-4);
57
+ }
58
+
59
+ .report-meta {
60
+ display: flex;
61
+ gap: var(--space-6);
62
+ flex-wrap: wrap;
63
+ color: var(--gray-600);
64
+ font-size: var(--text-sm);
65
+ }
66
+
67
+ .report-meta-item {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: var(--space-2);
71
+ }
72
+
73
+ .report-meta-label {
74
+ font-weight: var(--font-medium);
75
+ }
76
+
77
+ /* ============================================
78
+ METRIC CARDS
79
+ ============================================ */
80
+
81
+ .metric-grid {
82
+ display: grid;
83
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
84
+ gap: var(--space-4);
85
+ margin-bottom: var(--space-6);
86
+ }
87
+
88
+ .metric-card {
89
+ background: #ffffff;
90
+ border: 1px solid var(--gray-200);
91
+ border-radius: var(--radius-lg);
92
+ padding: var(--space-4);
93
+ transition: all var(--transition-base);
94
+ }
95
+
96
+ .metric-card:hover {
97
+ box-shadow: var(--shadow-md);
98
+ border-color: var(--primary-light);
99
+ }
100
+
101
+ .metric-label {
102
+ font-size: var(--text-sm);
103
+ color: var(--gray-600);
104
+ font-weight: var(--font-medium);
105
+ margin-bottom: var(--space-2);
106
+ display: block;
107
+ }
108
+
109
+ .metric-value {
110
+ font-size: var(--text-2xl);
111
+ font-weight: var(--font-bold);
112
+ color: var(--gray-900);
113
+ display: block;
114
+ margin-bottom: var(--space-1);
115
+ }
116
+
117
+ .metric-unit {
118
+ font-size: var(--text-sm);
119
+ color: var(--gray-500);
120
+ font-weight: var(--font-normal);
121
+ }
122
+
123
+ .metric-change {
124
+ font-size: var(--text-xs);
125
+ display: inline-flex;
126
+ align-items: center;
127
+ gap: var(--space-1);
128
+ padding: var(--space-1) var(--space-2);
129
+ border-radius: var(--radius);
130
+ margin-top: var(--space-2);
131
+ }
132
+
133
+ .metric-change.positive {
134
+ background-color: var(--success-light);
135
+ color: var(--success);
136
+ }
137
+
138
+ .metric-change.negative {
139
+ background-color: var(--danger-light);
140
+ color: var(--danger);
141
+ }
142
+
143
+ /* ============================================
144
+ SECTION HEADERS
145
+ ============================================ */
146
+
147
+ .section-header {
148
+ display: flex;
149
+ align-items: center;
150
+ justify-content: space-between;
151
+ margin-bottom: var(--space-4);
152
+ padding-bottom: var(--space-3);
153
+ border-bottom: 1px solid var(--gray-200);
154
+ }
155
+
156
+ .section-title {
157
+ font-size: var(--text-2xl);
158
+ font-weight: var(--font-semibold);
159
+ color: var(--gray-900);
160
+ display: flex;
161
+ align-items: center;
162
+ gap: var(--space-2);
163
+ }
164
+
165
+ .section-title-icon {
166
+ width: 24px;
167
+ height: 24px;
168
+ color: var(--primary);
169
+ }
170
+
171
+ .section-actions {
172
+ display: flex;
173
+ gap: var(--space-2);
174
+ }
175
+
176
+ .section-description {
177
+ color: var(--gray-600);
178
+ font-size: var(--text-sm);
179
+ margin-bottom: var(--space-4);
180
+ line-height: var(--line-height-relaxed);
181
+ }
182
+
183
+ /* ============================================
184
+ TABS
185
+ ============================================ */
186
+
187
+ .tabs-container {
188
+ margin-bottom: var(--space-6);
189
+ }
190
+
191
+ .tabs-nav {
192
+ display: flex;
193
+ gap: var(--space-1);
194
+ border-bottom: 2px solid var(--gray-200);
195
+ margin-bottom: var(--space-6);
196
+ overflow-x: auto;
197
+ -webkit-overflow-scrolling: touch;
198
+ }
199
+
200
+ .tab-button {
201
+ padding: var(--space-3) var(--space-4);
202
+ font-size: var(--text-sm);
203
+ font-weight: var(--font-medium);
204
+ color: var(--gray-600);
205
+ background: none;
206
+ border: none;
207
+ border-bottom: 2px solid transparent;
208
+ cursor: pointer;
209
+ transition: all var(--transition-fast);
210
+ white-space: nowrap;
211
+ position: relative;
212
+ margin-bottom: -2px;
213
+ }
214
+
215
+ .tab-button:hover {
216
+ color: var(--primary);
217
+ background-color: var(--gray-50);
218
+ }
219
+
220
+ .tab-button.active {
221
+ color: var(--primary);
222
+ border-bottom-color: var(--primary);
223
+ font-weight: var(--font-semibold);
224
+ }
225
+
226
+ .tab-content {
227
+ display: none;
228
+ }
229
+
230
+ .tab-content.active {
231
+ display: block;
232
+ animation: fadeIn 0.2s ease;
233
+ }
234
+
235
+ @keyframes fadeIn {
236
+ from {
237
+ opacity: 0;
238
+ transform: translateY(-10px);
239
+ }
240
+ to {
241
+ opacity: 1;
242
+ transform: translateY(0);
243
+ }
244
+ }
245
+
246
+ /* ============================================
247
+ CARDS
248
+ ============================================ */
249
+
250
+ .card {
251
+ background: #ffffff;
252
+ border: 1px solid var(--gray-200);
253
+ border-radius: var(--radius-lg);
254
+ overflow: hidden;
255
+ margin-bottom: var(--space-4);
256
+ }
257
+
258
+ .card-header {
259
+ padding: var(--space-4);
260
+ border-bottom: 1px solid var(--gray-200);
261
+ background-color: var(--gray-50);
262
+ }
263
+
264
+ .card-title {
265
+ font-size: var(--text-lg);
266
+ font-weight: var(--font-semibold);
267
+ color: var(--gray-900);
268
+ }
269
+
270
+ .card-body {
271
+ padding: var(--space-4);
272
+ }
273
+
274
+ .card-footer {
275
+ padding: var(--space-4);
276
+ border-top: 1px solid var(--gray-200);
277
+ background-color: var(--gray-50);
278
+ font-size: var(--text-sm);
279
+ color: var(--gray-600);
280
+ }
281
+
282
+ /* ============================================
283
+ CHART CONTAINERS
284
+ ============================================ */
285
+
286
+ .chart-container {
287
+ background: #ffffff;
288
+ border: 1px solid var(--gray-200);
289
+ border-radius: var(--radius-lg);
290
+ padding: var(--space-4);
291
+ margin-bottom: var(--space-6);
292
+ }
293
+
294
+ .chart-header {
295
+ display: flex;
296
+ justify-content: space-between;
297
+ align-items: center;
298
+ margin-bottom: var(--space-4);
299
+ }
300
+
301
+ .chart-title {
302
+ font-size: var(--text-lg);
303
+ font-weight: var(--font-semibold);
304
+ color: var(--gray-900);
305
+ }
306
+
307
+ .chart-subtitle {
308
+ font-size: var(--text-sm);
309
+ color: var(--gray-600);
310
+ margin-top: var(--space-1);
311
+ }
312
+
313
+ .chart-body {
314
+ min-height: 300px;
315
+ position: relative;
316
+ }
317
+
318
+ .chart-footer {
319
+ margin-top: var(--space-4);
320
+ padding-top: var(--space-4);
321
+ border-top: 1px solid var(--gray-200);
322
+ font-size: var(--text-xs);
323
+ color: var(--gray-500);
324
+ }
325
+
326
+ /* ============================================
327
+ TABLES
328
+ ============================================ */
329
+
330
+ .table-container {
331
+ overflow-x: auto;
332
+ border: 1px solid var(--gray-200);
333
+ border-radius: var(--radius-lg);
334
+ margin-bottom: var(--space-6);
335
+ }
336
+
337
+ .data-table {
338
+ width: 100%;
339
+ border-collapse: collapse;
340
+ font-size: var(--text-sm);
341
+ }
342
+
343
+ .data-table thead {
344
+ background-color: var(--gray-50);
345
+ border-bottom: 2px solid var(--gray-200);
346
+ }
347
+
348
+ .data-table th {
349
+ padding: var(--space-3) var(--space-4);
350
+ text-align: left;
351
+ font-weight: var(--font-semibold);
352
+ color: var(--gray-700);
353
+ white-space: nowrap;
354
+ }
355
+
356
+ .data-table th.text-right {
357
+ text-align: right;
358
+ }
359
+
360
+ .data-table td {
361
+ padding: var(--space-3) var(--space-4);
362
+ border-top: 1px solid var(--gray-200);
363
+ color: var(--gray-900);
364
+ }
365
+
366
+ .data-table td.text-right {
367
+ text-align: right;
368
+ font-family: var(--font-mono);
369
+ }
370
+
371
+ .data-table tbody tr:hover {
372
+ background-color: var(--gray-50);
373
+ }
374
+
375
+ .data-table tbody tr.highlight {
376
+ background-color: var(--primary-lighter);
377
+ }
378
+
379
+ /* Table cell types */
380
+ .table-cell-number {
381
+ font-family: var(--font-mono);
382
+ text-align: right;
383
+ }
384
+
385
+ .table-cell-pvalue {
386
+ font-family: var(--font-mono);
387
+ font-size: var(--text-xs);
388
+ }
389
+
390
+ .table-cell-pvalue.significant {
391
+ font-weight: var(--font-semibold);
392
+ color: var(--primary);
393
+ }
394
+
395
+ /* ============================================
396
+ BADGES & PILLS
397
+ ============================================ */
398
+
399
+ .badge {
400
+ display: inline-flex;
401
+ align-items: center;
402
+ padding: var(--space-1) var(--space-2);
403
+ font-size: var(--text-xs);
404
+ font-weight: var(--font-medium);
405
+ border-radius: var(--radius);
406
+ line-height: 1;
407
+ }
408
+
409
+ .badge-primary {
410
+ background-color: var(--primary-lighter);
411
+ color: var(--primary-dark);
412
+ }
413
+
414
+ .badge-success {
415
+ background-color: var(--success-light);
416
+ color: var(--success);
417
+ }
418
+
419
+ .badge-warning {
420
+ background-color: var(--warning-light);
421
+ color: var(--warning);
422
+ }
423
+
424
+ .badge-danger {
425
+ background-color: var(--danger-light);
426
+ color: var(--danger);
427
+ }
428
+
429
+ .badge-info {
430
+ background-color: var(--info-light);
431
+ color: var(--info);
432
+ }
433
+
434
+ .badge-gray {
435
+ background-color: var(--gray-100);
436
+ color: var(--gray-700);
437
+ }
438
+
439
+ /* ============================================
440
+ ALERTS & MESSAGES
441
+ ============================================ */
442
+
443
+ .alert {
444
+ padding: var(--space-4);
445
+ border-radius: var(--radius-lg);
446
+ border-left: 4px solid;
447
+ margin-bottom: var(--space-4);
448
+ display: flex;
449
+ gap: var(--space-3);
450
+ }
451
+
452
+ .alert-icon {
453
+ flex-shrink: 0;
454
+ width: 20px;
455
+ height: 20px;
456
+ }
457
+
458
+ .alert-content {
459
+ flex: 1;
460
+ }
461
+
462
+ .alert-title {
463
+ font-weight: var(--font-semibold);
464
+ margin-bottom: var(--space-1);
465
+ }
466
+
467
+ .alert-message {
468
+ font-size: var(--text-sm);
469
+ line-height: var(--line-height-relaxed);
470
+ }
471
+
472
+ .alert-success {
473
+ background-color: var(--success-light);
474
+ border-color: var(--success);
475
+ color: var(--success);
476
+ }
477
+
478
+ .alert-warning {
479
+ background-color: var(--warning-light);
480
+ border-color: var(--warning);
481
+ color: var(--warning);
482
+ }
483
+
484
+ .alert-danger {
485
+ background-color: var(--danger-light);
486
+ border-color: var(--danger);
487
+ color: var(--danger);
488
+ }
489
+
490
+ .alert-info {
491
+ background-color: var(--info-light);
492
+ border-color: var(--info);
493
+ color: var(--info);
494
+ }
495
+
496
+ /* ============================================
497
+ BUTTONS
498
+ ============================================ */
499
+
500
+ .btn {
501
+ display: inline-flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ gap: var(--space-2);
505
+ padding: var(--space-2) var(--space-4);
506
+ font-size: var(--text-sm);
507
+ font-weight: var(--font-medium);
508
+ border-radius: var(--radius);
509
+ border: 1px solid transparent;
510
+ cursor: pointer;
511
+ transition: all var(--transition-fast);
512
+ text-decoration: none;
513
+ white-space: nowrap;
514
+ }
515
+
516
+ .btn:hover {
517
+ transform: translateY(-1px);
518
+ box-shadow: var(--shadow);
519
+ }
520
+
521
+ .btn:active {
522
+ transform: translateY(0);
523
+ }
524
+
525
+ .btn-primary {
526
+ background-color: var(--primary);
527
+ color: #ffffff;
528
+ border-color: var(--primary);
529
+ }
530
+
531
+ .btn-primary:hover {
532
+ background-color: var(--primary-dark);
533
+ border-color: var(--primary-dark);
534
+ }
535
+
536
+ .btn-secondary {
537
+ background-color: #ffffff;
538
+ color: var(--gray-700);
539
+ border-color: var(--gray-300);
540
+ }
541
+
542
+ .btn-secondary:hover {
543
+ background-color: var(--gray-50);
544
+ border-color: var(--gray-400);
545
+ }
546
+
547
+ .btn-sm {
548
+ padding: var(--space-1) var(--space-3);
549
+ font-size: var(--text-xs);
550
+ }
551
+
552
+ .btn-lg {
553
+ padding: var(--space-3) var(--space-6);
554
+ font-size: var(--text-base);
555
+ }
556
+
557
+ /* ============================================
558
+ TEST RESULTS
559
+ ============================================ */
560
+
561
+ .test-result {
562
+ display: flex;
563
+ align-items: center;
564
+ gap: var(--space-2);
565
+ padding: var(--space-2);
566
+ border-radius: var(--radius);
567
+ }
568
+
569
+ .test-result-icon {
570
+ width: 16px;
571
+ height: 16px;
572
+ flex-shrink: 0;
573
+ }
574
+
575
+ .test-result-reject {
576
+ background-color: var(--reject-bg);
577
+ color: var(--reject);
578
+ }
579
+
580
+ .test-result-accept {
581
+ background-color: var(--accept-bg);
582
+ color: var(--accept);
583
+ }
584
+
585
+ .test-result-inconclusive {
586
+ background-color: var(--inconclusive-bg);
587
+ color: var(--inconclusive);
588
+ }
589
+
590
+ /* ============================================
591
+ STATISTICS DISPLAY
592
+ ============================================ */
593
+
594
+ .stat-row {
595
+ display: flex;
596
+ justify-content: space-between;
597
+ padding: var(--space-2) 0;
598
+ border-bottom: 1px solid var(--gray-100);
599
+ }
600
+
601
+ .stat-row:last-child {
602
+ border-bottom: none;
603
+ }
604
+
605
+ .stat-label {
606
+ font-weight: var(--font-medium);
607
+ color: var(--gray-700);
608
+ }
609
+
610
+ .stat-value {
611
+ font-family: var(--font-mono);
612
+ color: var(--gray-900);
613
+ }
614
+
615
+ .stat-group {
616
+ background-color: var(--gray-50);
617
+ border-radius: var(--radius-lg);
618
+ padding: var(--space-4);
619
+ margin-bottom: var(--space-4);
620
+ }
621
+
622
+ .stat-group-title {
623
+ font-size: var(--text-sm);
624
+ font-weight: var(--font-semibold);
625
+ color: var(--gray-700);
626
+ margin-bottom: var(--space-3);
627
+ text-transform: uppercase;
628
+ letter-spacing: 0.5px;
629
+ }
630
+
631
+ /* ============================================
632
+ CODE BLOCKS
633
+ ============================================ */
634
+
635
+ .code-block {
636
+ background-color: var(--gray-900);
637
+ color: var(--gray-100);
638
+ padding: var(--space-4);
639
+ border-radius: var(--radius-lg);
640
+ overflow-x: auto;
641
+ margin-bottom: var(--space-4);
642
+ font-family: var(--font-mono);
643
+ font-size: var(--text-sm);
644
+ line-height: var(--line-height-relaxed);
645
+ }
646
+
647
+ .code-block code {
648
+ color: inherit;
649
+ background: none;
650
+ }
651
+
652
+ /* ============================================
653
+ FOOTER
654
+ ============================================ */
655
+
656
+ .report-footer {
657
+ margin-top: var(--space-12);
658
+ padding-top: var(--space-6);
659
+ border-top: 2px solid var(--gray-200);
660
+ text-align: center;
661
+ color: var(--gray-500);
662
+ font-size: var(--text-sm);
663
+ }
664
+
665
+ .report-footer-actions {
666
+ display: flex;
667
+ justify-content: center;
668
+ gap: var(--space-4);
669
+ margin-bottom: var(--space-4);
670
+ }
671
+
672
+ .report-footer-text {
673
+ line-height: var(--line-height-relaxed);
674
+ }
675
+
676
+ /* ============================================
677
+ RESPONSIVE
678
+ ============================================ */
679
+
680
+ @media (max-width: 768px) {
681
+ .report-container {
682
+ padding: var(--space-4);
683
+ }
684
+
685
+ .report-title {
686
+ font-size: var(--text-3xl);
687
+ }
688
+
689
+ .metric-grid {
690
+ grid-template-columns: 1fr;
691
+ }
692
+
693
+ .tabs-nav {
694
+ flex-wrap: nowrap;
695
+ overflow-x: auto;
696
+ }
697
+
698
+ .section-header {
699
+ flex-direction: column;
700
+ align-items: flex-start;
701
+ gap: var(--space-2);
702
+ }
703
+
704
+ .table-container {
705
+ font-size: var(--text-xs);
706
+ }
707
+
708
+ .data-table th,
709
+ .data-table td {
710
+ padding: var(--space-2);
711
+ }
712
+ }
713
+
714
+ /* ============================================
715
+ PRINT STYLES
716
+ ============================================ */
717
+
718
+ @media print {
719
+ .report-container {
720
+ padding: 0;
721
+ max-width: 100%;
722
+ }
723
+
724
+ .report-header {
725
+ border-bottom: 2px solid #000;
726
+ }
727
+
728
+ .btn,
729
+ .tab-button,
730
+ .report-footer-actions {
731
+ display: none !important;
732
+ }
733
+
734
+ .chart-container,
735
+ .card {
736
+ page-break-inside: avoid;
737
+ }
738
+
739
+ .tab-content {
740
+ display: block !important;
741
+ }
742
+
743
+ a {
744
+ color: #000;
745
+ text-decoration: underline;
746
+ }
747
+ }