pivotgrid-js 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,1091 @@
1
+ /* ── PivotGrid styles ─────────────────────────────────────────────────────── */
2
+
3
+ .pg-root {
4
+ position: relative;
5
+ overflow: hidden;
6
+ font-family: -apple-system, 'Segoe UI', sans-serif;
7
+ font-size: 13px;
8
+ border: 1px solid #e0e0e0;
9
+ border-radius: 8px;
10
+ background: #fff;
11
+ user-select: none;
12
+ }
13
+
14
+ .pg-col-resize-handle:hover,
15
+ .pg-col-resize-handle:active {
16
+ background: rgba(26, 115, 232, 0.25);
17
+ }
18
+
19
+ /* ── Scroll area ─────────────────────────────────────────────────────────── */
20
+
21
+ .pg-scroll {
22
+ position: absolute;
23
+ left: 0;
24
+ right: 0;
25
+ bottom: 0;
26
+ overflow: auto;
27
+ }
28
+
29
+ /* ── Column header ───────────────────────────────────────────────────────── */
30
+
31
+ .pg-col-header {
32
+ position: absolute;
33
+ top: 0;
34
+ left: 0;
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: flex-start;
38
+ background: #fafafa;
39
+ border-bottom: 1px solid #d0d0d0;
40
+ z-index: 10;
41
+ }
42
+
43
+ .pg-col-header-cell {
44
+ flex-shrink: 0;
45
+ display: flex;
46
+ align-items: flex-start;
47
+ justify-content: flex-start;
48
+ padding: 0 10px;
49
+ box-sizing: border-box;
50
+ font-size: 11px;
51
+ font-weight: 500;
52
+ color: #666;
53
+ text-transform: uppercase;
54
+ letter-spacing: 0.04em;
55
+ border-right: 1px solid #e8e8e8;
56
+ white-space: nowrap;
57
+ overflow: hidden;
58
+ background: #fafafa;
59
+ padding-top: 6px
60
+ }
61
+
62
+ .pg-col-header-cell.row-label {
63
+ justify-content: flex-start;
64
+ color: #999;
65
+ position: sticky;
66
+ left: 0;
67
+ background: #fafafa;
68
+ z-index: 11;
69
+ border-right: 1px solid #d0d0d0;
70
+ }
71
+
72
+ .pg-col-header-cell.total-col {
73
+ color: #444;
74
+ font-weight: 600;
75
+ }
76
+
77
+ /* ── Rows ────────────────────────────────────────────────────────────────── */
78
+
79
+ .pg-row {
80
+ position: absolute;
81
+ left: 0;
82
+ display: flex;
83
+ align-items: center;
84
+ box-sizing: border-box;
85
+ border-bottom: 1px solid #f0f0f0;
86
+ transition: background 0.08s;
87
+ }
88
+
89
+ .pg-row:hover {
90
+ background: #f5f9ff !important;
91
+ }
92
+
93
+ .pg-row.grand-total {
94
+ font-weight: 500;
95
+ border-top: 1px solid #d0d0d0;
96
+ background: #fafafa;
97
+ }
98
+
99
+ /* ── Row header cell (sticky left) ──────────────────────────────────────── */
100
+
101
+ .pg-cell-header {
102
+ flex-shrink: 0;
103
+ display: flex;
104
+ align-items: center;
105
+ height: 100%;
106
+ box-sizing: border-box;
107
+ border-right: 1px solid #f0f0f0;
108
+ overflow: hidden;
109
+ white-space: nowrap;
110
+ color: #1a1a1a;
111
+ position: sticky;
112
+ left: 0;
113
+ background: inherit;
114
+ z-index: 1;
115
+ }
116
+
117
+ .pg-cell-header .pg-label {
118
+ margin-left: 4px;
119
+ overflow: hidden;
120
+ text-overflow: ellipsis;
121
+ white-space: nowrap;
122
+ }
123
+
124
+ .pg-cell-header .pg-label.depth-0 {
125
+ font-weight: 500;
126
+ color: #1a1a1a;
127
+ font-size: 13px;
128
+ }
129
+
130
+ .pg-cell-header .pg-label.depth-1 {
131
+ font-weight: 400;
132
+ color: #555;
133
+ font-size: 12px;
134
+ }
135
+
136
+ .pg-cell-header .pg-label.depth-2 {
137
+ font-weight: 400;
138
+ color: #777;
139
+ font-size: 12px;
140
+ }
141
+
142
+ /* ── Toggle button ───────────────────────────────────────────────────────── */
143
+
144
+ .pg-toggle {
145
+ display: inline-flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ width: 16px;
149
+ height: 16px;
150
+ flex-shrink: 0;
151
+ cursor: pointer;
152
+ color: #999;
153
+ font-size: 10px;
154
+ transition: transform 0.15s;
155
+ border-radius: 3px;
156
+ }
157
+
158
+ .pg-toggle:hover {
159
+ background: #e8e8e8;
160
+ color: #333;
161
+ }
162
+
163
+ .pg-toggle.collapsed {
164
+ transform: rotate(-90deg);
165
+ }
166
+
167
+ .pg-toggle-spacer {
168
+ width: 16px;
169
+ flex-shrink: 0;
170
+ display: inline-block;
171
+ }
172
+
173
+ /* ── Value cells ─────────────────────────────────────────────────────────── */
174
+
175
+ .pg-cell {
176
+ flex-shrink: 0;
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: flex-end;
180
+ height: 100%;
181
+ padding: 0 10px;
182
+ box-sizing: border-box;
183
+ border-right: 1px solid #f0f0f0;
184
+ font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
185
+ font-size: 12px;
186
+ color: #2a2a2a;
187
+ cursor: pointer;
188
+ transition: background 0.08s, color 0.08s;
189
+ }
190
+
191
+ .pg-cell:hover {
192
+ background: #e8f0fe;
193
+ color: #1a73e8;
194
+ }
195
+
196
+ .pg-cell.total {
197
+ background: #fafafa;
198
+ color: #555;
199
+ font-weight: 500;
200
+ }
201
+
202
+ .pg-cell.total:hover {
203
+ background: #e8f0fe;
204
+ color: #1a73e8;
205
+ }
206
+
207
+ .pg-cell.grand-total-val {
208
+ font-weight: 600;
209
+ color: #1a1a1a;
210
+ }
211
+
212
+ .pg-cell.empty {
213
+ color: #ccc;
214
+ cursor: default;
215
+ }
216
+
217
+ .pg-cell.empty:hover {
218
+ background: transparent;
219
+ color: #ccc;
220
+ }
221
+
222
+ .pg-col-header-group {
223
+ border-bottom: 1px solid #d0d0d0;
224
+ justify-content: flex-start;
225
+ padding-left: 6px;
226
+ font-weight: 600;
227
+ color: #444;
228
+ }
229
+
230
+ .pg-cell.subtotal,
231
+ .pg-col-header-cell.subtotal-col {
232
+ background: #f5f5f5;
233
+ color: #555;
234
+ border-left: 2px solid #d0d0d0;
235
+ }
236
+
237
+ .pg-row:hover .pg-cell.subtotal,
238
+ .pg-row--hover .pg-cell.subtotal {
239
+ background: #f5f9ff !important;
240
+ }
241
+
242
+ .pg-row:hover .pg-cell:hover,
243
+ .pg-row--hover .pg-cell:hover {
244
+ background: #e8f0fe !important;
245
+ color: #1a73e8 !important;
246
+ }
247
+
248
+ .pg-row:hover .pg-cell.subtotal:hover,
249
+ .pg-row--hover .pg-cell.subtotal:hover {
250
+ background: #e8f0fe !important;
251
+ color: #1a73e8 !important;
252
+ }
253
+ .fz-zone--filters { flex: 1.5; }
254
+
255
+ [data-fz-zone="filters"] .fz-chip {
256
+ background: #fff8f0;
257
+ border-color: #f4c27a;
258
+ color: #7a4200;
259
+ }
260
+
261
+ [data-fz-zone="filters"] .fz-chip:hover {
262
+ border-color: #e67e22;
263
+ color: #5d3100;
264
+ box-shadow: 0 1px 4px rgba(230,126,34,0.2);
265
+ }
266
+
267
+ [data-fz-zone="filters"] .fz-chip.fz-chip--active {
268
+ background: #fff0dc;
269
+ border-color: #e67e22;
270
+ font-weight: 500;
271
+ }
272
+
273
+ .fz-chip-label { cursor: pointer; }
274
+
275
+ /* ── Field Zones ────────────────────────────────────────────────────── */
276
+
277
+ .field-zones {
278
+ display: flex;
279
+ gap: 8px;
280
+ padding: 8px 12px;
281
+ background: #fff;
282
+ border: 1px solid #e0e0e0;
283
+ border-radius: 8px;
284
+ min-height: 48px;
285
+ align-items: stretch;
286
+ margin-bottom: 8px;
287
+ flex-shrink: 0;
288
+ }
289
+
290
+ .fz-zone {
291
+ display: flex;
292
+ flex-direction: column;
293
+ gap: 4px;
294
+ flex: 1;
295
+ min-width: 0;
296
+ }
297
+
298
+ .fz-zone--rows { flex: 2; }
299
+ .fz-zone--columns { flex: 1.5; }
300
+ .fz-zone--free { flex: 1.5; }
301
+
302
+ .fz-zone-label {
303
+ font-size: 10px;
304
+ font-weight: 600;
305
+ color: #999;
306
+ text-transform: uppercase;
307
+ letter-spacing: 0.06em;
308
+ padding: 0 4px;
309
+ }
310
+
311
+ .fz-zone-body {
312
+ display: flex;
313
+ flex-wrap: wrap;
314
+ gap: 4px;
315
+ min-height: 33px;
316
+ max-height: 66px;
317
+ overflow-y: auto;
318
+ padding: 4px 6px;
319
+ border: 1.5px dashed #d0d0d0;
320
+ border-radius: 6px;
321
+ background: #fff;
322
+ transition: background 0.15s, border-color 0.15s;
323
+ }
324
+
325
+ .fz-zone-body.fz-zone--over {
326
+ background: #e8f0fe;
327
+ border-color: #1a73e8;
328
+ }
329
+
330
+ /* Chips */
331
+ .fz-chip {
332
+ display: inline-flex;
333
+ align-items: center;
334
+ gap: 4px;
335
+ padding: 3px 8px;
336
+ background: #fff;
337
+ border: 1px solid #d0d0d0;
338
+ border-radius: 4px;
339
+ font-size: 12px;
340
+ color: #333;
341
+ cursor: grab;
342
+ user-select: none;
343
+ white-space: nowrap;
344
+ transition: box-shadow 0.1s, border-color 0.1s;
345
+ }
346
+
347
+ .fz-chip:hover {
348
+ border-color: #1a73e8;
349
+ color: #1a73e8;
350
+ box-shadow: 0 1px 4px rgba(26,115,232,0.15);
351
+ }
352
+
353
+ /* Chips in rows/columns — slightly coloured */
354
+ [data-fz-zone="rows"] .fz-chip {
355
+ background: #f0f4ff;
356
+ border-color: #c5d3f7;
357
+ color: #2c4bad;
358
+ }
359
+
360
+ [data-fz-zone="columns"] .fz-chip {
361
+ background: #f0fdf4;
362
+ border-color: #a7d7b8;
363
+ color: #1a6638;
364
+ }
365
+
366
+ .fz-chip--dragging {
367
+ opacity: 0.35;
368
+ cursor: grabbing;
369
+ }
370
+
371
+ .fz-chip--ghost {
372
+ cursor: grabbing;
373
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
374
+ }
375
+
376
+ .fz-chip-remove {
377
+ font-size: 13px;
378
+ line-height: 1;
379
+ color: #999;
380
+ cursor: pointer;
381
+ padding: 0 1px;
382
+ border-radius: 2px;
383
+ }
384
+
385
+ .fz-chip-remove:hover {
386
+ color: #e53935;
387
+ background: #fde;
388
+ }
389
+
390
+ .fz-chip--filtered {
391
+ border-color: #6172f3;
392
+ }
393
+
394
+ .fz-chip-hint {
395
+ font-size: 10px;
396
+ font-weight: 600;
397
+ color: #6172f3;
398
+ background: #eff4ff;
399
+ border-radius: 4px;
400
+ padding: 0 4px;
401
+ margin-left: 2px;
402
+ pointer-events: none;
403
+ }
404
+
405
+ .fz-tooltip {
406
+ display: none;
407
+ position: fixed;
408
+ z-index: 10000;
409
+ background: #fff;
410
+ color: #344054;
411
+ font-size: 12px;
412
+ padding: 6px 10px;
413
+ border: 1px solid #d0d5dd;
414
+ border-radius: 6px;
415
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
416
+ white-space: pre-wrap;
417
+ max-width: 260px;
418
+ pointer-events: none;
419
+ }
420
+ /* ── Demo page styles ────────────────────────────────────────────────────── */
421
+
422
+ *, *::before, *::after {
423
+ box-sizing: border-box;
424
+ margin: 0;
425
+ padding: 0;
426
+ }
427
+
428
+ body {
429
+ font-family: -apple-system, 'Segoe UI', sans-serif;
430
+ background: #f4f5f7;
431
+ color: #1a1a1a;
432
+ padding: 12px;
433
+ min-height: 100vh;
434
+
435
+ display: flex;
436
+ flex-direction: column;
437
+ height: 100dvh;
438
+ overflow: hidden;
439
+ gap: 8px;
440
+ }
441
+
442
+ /* ── Toolbar ─────────────────────────────────────────────────────────────── */
443
+
444
+ .toolbar {
445
+ display: flex;
446
+ align-items: center;
447
+ gap: 10px;
448
+ flex-wrap: wrap;
449
+ background: #fff;
450
+ border: 1px solid #e0e0e0;
451
+ border-radius: 8px;
452
+ padding: 8px 12px;
453
+ }
454
+
455
+ .toolbar-label {
456
+ font-size: 11px;
457
+ color: #999;
458
+ text-transform: uppercase;
459
+ letter-spacing: 0.04em;
460
+ white-space: nowrap;
461
+ }
462
+
463
+ .toolbar select {
464
+ padding: 4px 8px;
465
+ font-size: 12px;
466
+ border: 1px solid #d0d0d0;
467
+ border-radius: 6px;
468
+ background: #fff;
469
+ cursor: pointer;
470
+ outline: none;
471
+ color: #333;
472
+ }
473
+
474
+ .toolbar select:focus {
475
+ border-color: #1a73e8;
476
+ }
477
+
478
+ .toolbar-sep {
479
+ width: 1px;
480
+ height: 18px;
481
+ background: #e0e0e0;
482
+ flex-shrink: 0;
483
+ }
484
+
485
+ .toolbar-btn {
486
+ padding: 4px 12px;
487
+ font-size: 12px;
488
+ border: 1px solid #d0d0d0;
489
+ border-radius: 6px;
490
+ background: #fff;
491
+ cursor: pointer;
492
+ color: #333;
493
+ transition: background 0.1s, border-color 0.1s;
494
+ white-space: nowrap;
495
+ }
496
+
497
+ .toolbar-btn:hover:not(:disabled) {
498
+ background: #f0f0f0;
499
+ border-color: #bbb;
500
+ }
501
+
502
+ .toolbar-btn:disabled {
503
+ opacity: 0.45;
504
+ cursor: default;
505
+ }
506
+
507
+ .toolbar-stat {
508
+ margin-left: auto;
509
+ font-size: 11px;
510
+ color: #aaa;
511
+ white-space: nowrap;
512
+ }
513
+
514
+ /* ── Cache zone ──────────────────────────────────────────────────────────── */
515
+
516
+ .cache-zone {
517
+ background: #fff;
518
+ border: 1px solid #e0e0e0;
519
+ border-radius: 8px;
520
+ padding: 8px 12px;
521
+ margin-bottom: 8px;
522
+ flex-shrink: 0;
523
+ }
524
+
525
+ .cache-zone-header {
526
+ display: flex;
527
+ align-items: center;
528
+ gap: 10px;
529
+ margin-bottom: 6px;
530
+ }
531
+
532
+ .cache-zone-label {
533
+ font-size: 11px;
534
+ font-weight: 600;
535
+ color: #999;
536
+ text-transform: uppercase;
537
+ letter-spacing: 0.04em;
538
+ white-space: nowrap;
539
+ }
540
+
541
+ /* Метр заполненности кэша */
542
+ .cache-meter-wrap {
543
+ display: flex;
544
+ align-items: center;
545
+ gap: 8px;
546
+ flex: 1;
547
+ min-width: 0;
548
+ }
549
+
550
+ .cache-meter-bar {
551
+ flex: 1;
552
+ height: 4px;
553
+ background: #f0f0f0;
554
+ border-radius: 2px;
555
+ overflow: hidden;
556
+ min-width: 60px;
557
+ }
558
+
559
+ .cache-meter-fill {
560
+ height: 100%;
561
+ border-radius: 2px;
562
+ transition: width 0.35s ease, background 0.35s;
563
+ }
564
+
565
+ .cache-meter-fill.ok { background: #1a9e5c; }
566
+ .cache-meter-fill.warn { background: #e67e22; }
567
+ .cache-meter-fill.danger { background: #e53935; }
568
+
569
+ .cache-meter-label {
570
+ font-size: 11px;
571
+ white-space: nowrap;
572
+ color: #bbb;
573
+ min-width: 120px;
574
+ }
575
+
576
+ .cache-meter-label.ok { color: #1a9e5c; }
577
+ .cache-meter-label.warn { color: #e67e22; }
578
+ .cache-meter-label.danger { color: #e53935; }
579
+
580
+ /* Статус кэша */
581
+ .cache-status {
582
+ font-size: 11px;
583
+ white-space: nowrap;
584
+ }
585
+
586
+ .cache-status.fresh { color: #1a9e5c; }
587
+ .cache-status.stale { color: #e67e22; font-weight: 500; }
588
+ .cache-status.empty { color: #ccc; }
589
+
590
+ /* Кнопка «Обновить кэш» — подсвечивается когда кэш stale */
591
+ .cache-refresh-btn--stale {
592
+ border-color: #1a73e8 !important;
593
+ color: #1a73e8 !important;
594
+ }
595
+
596
+ /* Fullscreen overlay при обновлении кэша */
597
+ #cache-fullscreen-loader {
598
+ position: fixed;
599
+ inset: 0;
600
+ background: rgba(255, 255, 255, 0.55);
601
+ display: flex;
602
+ align-items: center;
603
+ justify-content: center;
604
+ font-size: 15px;
605
+ color: #999;
606
+ z-index: 500;
607
+ }
608
+
609
+ /* Состояние загрузки кэша — блокируем все чипы */
610
+ .cache-zone--loading .cache-chip {
611
+ pointer-events: none;
612
+ opacity: 0.4;
613
+ }
614
+
615
+ .cache-zone--loading .cache-zone-label,
616
+ .cache-zone--loading .cache-meter-wrap,
617
+ .cache-zone--loading .cache-status {
618
+ opacity: 0.4;
619
+ }
620
+
621
+ /* Кнопка в loading не меняет внешний вид при hover */
622
+ .cache-zone--loading #btn-refresh-cache {
623
+ cursor: wait;
624
+ }
625
+
626
+ /* Чипы измерений */
627
+ .cache-zone-body {
628
+ display: flex;
629
+ flex-wrap: wrap;
630
+ gap: 4px;
631
+ min-height: 28px;
632
+ }
633
+
634
+ .cache-chip {
635
+ display: inline-flex;
636
+ align-items: center;
637
+ padding: 3px 8px;
638
+ background: #fff;
639
+ border: 1px solid #d0d0d0;
640
+ border-radius: 4px;
641
+ font-size: 12px;
642
+ color: #666;
643
+ cursor: pointer;
644
+ user-select: none;
645
+ white-space: nowrap;
646
+ transition: border-color 0.1s, background 0.1s, color 0.1s;
647
+ }
648
+
649
+ .cache-chip:hover {
650
+ border-color: #1a73e8;
651
+ color: #1a73e8;
652
+ }
653
+
654
+ /* В кэше — синий (совпадает с зоной «Строки») */
655
+ .cache-chip.is-cached {
656
+ background: #f0f4ff;
657
+ border-color: #c5d3f7;
658
+ color: #2c4bad;
659
+ }
660
+
661
+ .cache-chip.is-cached:hover {
662
+ border-color: #e53935;
663
+ background: #fff5f5;
664
+ color: #c62828;
665
+ }
666
+
667
+ /* Идёт COUNT-запрос */
668
+ .cache-chip.is-checking {
669
+ background: #fff8e6;
670
+ border-color: #f0a500;
671
+ color: #7a4f00;
672
+ cursor: wait;
673
+ animation: cache-pulse 0.9s ease-in-out infinite;
674
+ }
675
+
676
+ /* Отклонено — превышение лимита */
677
+ .cache-chip.is-rejected {
678
+ background: #fff0f0;
679
+ border-color: #e53935;
680
+ color: #c62828;
681
+ cursor: default;
682
+ animation: cache-shake 0.3s ease-in-out;
683
+ }
684
+
685
+ @keyframes cache-pulse {
686
+ 0%, 100% { opacity: 1; }
687
+ 50% { opacity: 0.45; }
688
+ }
689
+
690
+ @keyframes cache-shake {
691
+ 0%, 100% { transform: translateX(0); }
692
+ 25% { transform: translateX(-5px); }
693
+ 75% { transform: translateX(5px); }
694
+ }
695
+
696
+ /* ── Toast ───────────────────────────────────────────────────────────────── */
697
+
698
+ .cache-toast {
699
+ position: fixed;
700
+ bottom: 24px;
701
+ left: 50%;
702
+ transform: translateX(-50%);
703
+ background: #323232;
704
+ color: #fff;
705
+ font-size: 12px;
706
+ padding: 8px 18px;
707
+ border-radius: 6px;
708
+ box-shadow: 0 4px 16px rgba(0,0,0,0.18);
709
+ opacity: 0;
710
+ pointer-events: none;
711
+ transition: opacity 0.2s;
712
+ z-index: 300;
713
+ white-space: nowrap;
714
+ max-width: calc(100vw - 48px);
715
+ overflow: hidden;
716
+ text-overflow: ellipsis;
717
+ }
718
+
719
+ .cache-toast.visible {
720
+ opacity: 1;
721
+ }
722
+
723
+ /* ── Filter popup ────────────────────────────────────────────────────────── */
724
+
725
+ .fm-popup {
726
+ position: fixed;
727
+ background: #fff;
728
+ border: 1px solid #d0d0d0;
729
+ border-radius: 8px;
730
+ box-shadow: 0 4px 20px rgba(0,0,0,0.12);
731
+ width: 280px;
732
+ max-height: 420px;
733
+ display: flex;
734
+ flex-direction: column;
735
+ z-index: 1000;
736
+ font-size: 13px;
737
+ }
738
+
739
+ .fm-popup-header {
740
+ display: flex;
741
+ align-items: center;
742
+ justify-content: space-between;
743
+ padding: 10px 12px;
744
+ border-bottom: 1px solid #efefef;
745
+ font-weight: 500;
746
+ font-size: 13px;
747
+ flex-shrink: 0;
748
+ }
749
+
750
+ .fm-popup-close {
751
+ background: none;
752
+ border: none;
753
+ cursor: pointer;
754
+ font-size: 18px;
755
+ color: #aaa;
756
+ line-height: 1;
757
+ padding: 0;
758
+ }
759
+
760
+ .fm-popup-close:hover { color: #333; }
761
+
762
+ .fm-search-section {
763
+ padding: 8px 12px;
764
+ border-bottom: 1px solid #efefef;
765
+ flex-shrink: 0;
766
+ }
767
+
768
+ .fm-search-type {
769
+ display: flex;
770
+ gap: 12px;
771
+ margin-bottom: 6px;
772
+ font-size: 12px;
773
+ color: #555;
774
+ }
775
+
776
+ .fm-search-type label {
777
+ display: flex;
778
+ align-items: center;
779
+ gap: 4px;
780
+ cursor: pointer;
781
+ }
782
+
783
+ .fm-search-input {
784
+ width: 100%;
785
+ padding: 5px 8px;
786
+ border: 1px solid #d0d0d0;
787
+ border-radius: 5px;
788
+ font-size: 12px;
789
+ outline: none;
790
+ box-sizing: border-box;
791
+ }
792
+
793
+ .fm-search-input:focus { border-color: #1a73e8; }
794
+
795
+ .fm-checkbox-list {
796
+ flex: 1;
797
+ overflow: hidden;
798
+ display: flex;
799
+ flex-direction: column;
800
+ min-height: 0;
801
+ }
802
+
803
+ .fm-select-all-wrap {
804
+ padding: 5px 12px !important;
805
+ border-bottom: 1px solid #efefef;
806
+ color: #888;
807
+ font-style: italic;
808
+ }
809
+
810
+ .fm-checkbox-scroll {
811
+ flex: 1;
812
+ overflow-y: auto;
813
+ max-height: 200px;
814
+ }
815
+
816
+ .fm-checkbox {
817
+ display: flex;
818
+ align-items: center;
819
+ gap: 6px;
820
+ padding: 4px 12px;
821
+ cursor: pointer;
822
+ font-size: 12px;
823
+ color: #333;
824
+ }
825
+
826
+ .fm-checkbox:hover { background: #f5f9ff; }
827
+ .fm-checkbox input { cursor: pointer; }
828
+
829
+ .fm-no-checkboxes {
830
+ padding: 12px;
831
+ color: #aaa;
832
+ font-size: 12px;
833
+ font-style: italic;
834
+ }
835
+
836
+ .fm-popup-footer {
837
+ display: flex;
838
+ justify-content: space-between;
839
+ padding: 8px 12px;
840
+ border-top: 1px solid #efefef;
841
+ gap: 8px;
842
+ flex-shrink: 0;
843
+ }
844
+
845
+ .fm-btn {
846
+ padding: 5px 14px;
847
+ border-radius: 5px;
848
+ font-size: 12px;
849
+ cursor: pointer;
850
+ border: 1px solid #d0d0d0;
851
+ background: #fff;
852
+ color: #333;
853
+ }
854
+
855
+ .fm-btn:hover { background: #f0f0f0; }
856
+
857
+ .fm-btn-primary {
858
+ background: #1a73e8;
859
+ border-color: #1a73e8;
860
+ color: #fff;
861
+ }
862
+
863
+ .fm-btn-primary:hover { background: #1558b0; }
864
+
865
+ /* ── Pivot container ─────────────────────────────────────────────────────── */
866
+
867
+ #pivot-container {
868
+ /* transition: margin-bottom 0.2s; */
869
+
870
+ flex: 1;
871
+ min-height: 200px;
872
+ overflow: hidden;
873
+ }
874
+
875
+ /* ── Drillthrough panel ──────────────────────────────────────────────────── */
876
+
877
+ .dt-panel {
878
+ display: none;
879
+ position: fixed;
880
+ bottom: 0;
881
+ left: 0;
882
+ right: 0;
883
+ height: 300px;
884
+ background: #fff;
885
+ border-top: 1px solid #d0d0d0;
886
+ box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.08);
887
+ z-index: 100;
888
+ flex-direction: column;
889
+ }
890
+
891
+ .dt-panel.visible {
892
+ display: flex;
893
+ }
894
+
895
+ .dt-header {
896
+ display: flex;
897
+ align-items: center;
898
+ gap: 8px;
899
+ padding: 8px 16px;
900
+ background: #fafafa;
901
+ border-bottom: 1px solid #e8e8e8;
902
+ flex-shrink: 0;
903
+ }
904
+
905
+ .dt-header-label {
906
+ font-size: 11px;
907
+ color: #aaa;
908
+ text-transform: uppercase;
909
+ letter-spacing: 0.05em;
910
+ }
911
+
912
+ .dt-header-context {
913
+ font-size: 13px;
914
+ font-weight: 500;
915
+ color: #1a1a1a;
916
+ }
917
+
918
+ .dt-header-value {
919
+ font-size: 13px;
920
+ color: #1a73e8;
921
+ font-family: 'SF Mono', 'Fira Code', monospace;
922
+ }
923
+
924
+ .dt-header-close {
925
+ margin-left: auto;
926
+ background: none;
927
+ border: none;
928
+ cursor: pointer;
929
+ font-size: 20px;
930
+ line-height: 1;
931
+ color: #aaa;
932
+ padding: 0 2px;
933
+ transition: color 0.1s;
934
+ }
935
+
936
+ .dt-header-close:hover {
937
+ color: #333;
938
+ }
939
+
940
+ .dt-filters {
941
+ display: flex;
942
+ align-items: center;
943
+ gap: 6px;
944
+ flex-wrap: wrap;
945
+ padding: 6px 16px;
946
+ background: #fafafa;
947
+ border-bottom: 1px solid #efefef;
948
+ flex-shrink: 0;
949
+ }
950
+
951
+ .dt-filter-tag {
952
+ display: inline-flex;
953
+ align-items: center;
954
+ gap: 4px;
955
+ padding: 2px 10px;
956
+ background: #e8f0fe;
957
+ color: #1a73e8;
958
+ font-size: 12px;
959
+ border-radius: 10px;
960
+ }
961
+
962
+ .dt-filter-tag .tag-key {
963
+ color: #5f8dd3;
964
+ }
965
+
966
+ .dt-body {
967
+ flex: 1;
968
+ overflow: auto;
969
+ }
970
+
971
+ .dt-table {
972
+ width: 100%;
973
+ border-collapse: collapse;
974
+ font-size: 12px;
975
+ }
976
+
977
+ .dt-table thead th {
978
+ position: sticky;
979
+ top: 0;
980
+ background: #fafafa;
981
+ padding: 6px 12px;
982
+ text-align: left;
983
+ font-size: 11px;
984
+ font-weight: 500;
985
+ color: #888;
986
+ text-transform: uppercase;
987
+ letter-spacing: 0.04em;
988
+ border-bottom: 1px solid #e0e0e0;
989
+ white-space: nowrap;
990
+ }
991
+
992
+ .dt-table thead th.num {
993
+ text-align: right;
994
+ }
995
+
996
+ .dt-table tbody tr:nth-child(even) {
997
+ background: #fafafa;
998
+ }
999
+
1000
+ .dt-table tbody tr:hover {
1001
+ background: #f0f6ff;
1002
+ }
1003
+
1004
+ .dt-table tbody td {
1005
+ padding: 5px 12px;
1006
+ color: #333;
1007
+ border-bottom: 1px solid #f4f4f4;
1008
+ white-space: nowrap;
1009
+ }
1010
+
1011
+ .dt-table tbody td.num {
1012
+ text-align: right;
1013
+ font-family: 'SF Mono', 'Fira Code', monospace;
1014
+ color: #1a1a1a;
1015
+ }
1016
+
1017
+ .dt-footer {
1018
+ display: flex;
1019
+ align-items: center;
1020
+ gap: 20px;
1021
+ padding: 6px 16px;
1022
+ background: #fafafa;
1023
+ border-top: 1px solid #efefef;
1024
+ font-size: 12px;
1025
+ color: #888;
1026
+ flex-shrink: 0;
1027
+ }
1028
+
1029
+ .dt-footer strong {
1030
+ color: #1a1a1a;
1031
+ font-weight: 500;
1032
+ }
1033
+
1034
+ .dt-footer .dt-warning {
1035
+ color: #e67e22;
1036
+ }
1037
+
1038
+ .fz-chip-placeholder {
1039
+ display: inline-flex;
1040
+ width: 3px;
1041
+ height: 24px;
1042
+ background: #1a73e8;
1043
+ border-radius: 2px;
1044
+ margin: 0 2px;
1045
+ pointer-events: none;
1046
+ }
1047
+
1048
+ .fz-chip[data-zone="rows"].fz-chip--last {
1049
+ background: #1a73e8 !important;
1050
+ border-color: #1a73e8 !important;
1051
+ color: #fff !important;
1052
+ }
1053
+
1054
+ .fz-chip[data-zone="columns"].fz-chip--last {
1055
+ background: #1a6638 !important;
1056
+ border-color: #1a6638 !important;
1057
+ color: #fff !important;
1058
+ }
1059
+
1060
+ .fz-chip[data-zone="free"].fz-chip--last {
1061
+ background: #666 !important;
1062
+ border-color: #666 !important;
1063
+ color: #fff !important;
1064
+ }
1065
+
1066
+ .toolbar-btn--toggle.is-active {
1067
+ background: #e8f0fe;
1068
+ border-color: #1a73e8;
1069
+ color: #1a73e8;
1070
+ }
1071
+
1072
+ .demo-toggles {
1073
+ display: flex;
1074
+ gap: 16px;
1075
+ font-size: 12px;
1076
+ color: #666;
1077
+ margin-bottom: 8px;
1078
+ }
1079
+
1080
+ .demo-toggles label {
1081
+ display: flex;
1082
+ align-items: center;
1083
+ gap: 6px;
1084
+ cursor: pointer;
1085
+ }
1086
+
1087
+ #pivot-grid {
1088
+ flex: 1;
1089
+ min-height: 200px;
1090
+ overflow: hidden;
1091
+ }