rdbr 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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +36 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +155 -0
  5. data/app/public/application.js +609 -0
  6. data/app/public/database-diagram.js +602 -0
  7. data/app/public/styles.css +2141 -0
  8. data/app/views/data.haml +166 -0
  9. data/app/views/group.haml +50 -0
  10. data/app/views/index.haml +108 -0
  11. data/app/views/layout.haml +59 -0
  12. data/app/views/record.haml +81 -0
  13. data/demo/README.md +47 -0
  14. data/demo/compose.yml +34 -0
  15. data/demo/seed.rb +270 -0
  16. data/demo/smoke.rb +13 -0
  17. data/docs/RELEASING.md +30 -0
  18. data/docs/VALUE_PRESENTATION.md +54 -0
  19. data/exe/rdbr +5 -0
  20. data/lib/rdbr/access/read_only.rb +61 -0
  21. data/lib/rdbr/access.rb +6 -0
  22. data/lib/rdbr/browser_launcher.rb +71 -0
  23. data/lib/rdbr/catalog/connection.rb +68 -0
  24. data/lib/rdbr/catalog/errors.rb +12 -0
  25. data/lib/rdbr/catalog/mysql/queries.rb +131 -0
  26. data/lib/rdbr/catalog/mysql.rb +146 -0
  27. data/lib/rdbr/catalog/postgresql/queries.rb +171 -0
  28. data/lib/rdbr/catalog/postgresql.rb +138 -0
  29. data/lib/rdbr/catalog/reader.rb +30 -0
  30. data/lib/rdbr/catalog/serializer.rb +24 -0
  31. data/lib/rdbr/catalog/sqlite.rb +182 -0
  32. data/lib/rdbr/catalog.rb +20 -0
  33. data/lib/rdbr/cli.rb +74 -0
  34. data/lib/rdbr/cli_options.rb +63 -0
  35. data/lib/rdbr/metadata/column.rb +44 -0
  36. data/lib/rdbr/metadata/constraints.rb +25 -0
  37. data/lib/rdbr/metadata/database.rb +37 -0
  38. data/lib/rdbr/metadata/index.rb +30 -0
  39. data/lib/rdbr/metadata/keys.rb +56 -0
  40. data/lib/rdbr/metadata/namespace.rb +26 -0
  41. data/lib/rdbr/metadata/relation.rb +104 -0
  42. data/lib/rdbr/metadata/relationship_inference.rb +75 -0
  43. data/lib/rdbr/metadata/relationships.rb +126 -0
  44. data/lib/rdbr/metadata/values.rb +73 -0
  45. data/lib/rdbr/metadata.rb +10 -0
  46. data/lib/rdbr/presentation/record_identity.rb +125 -0
  47. data/lib/rdbr/query/connection.rb +138 -0
  48. data/lib/rdbr/query/errors.rb +33 -0
  49. data/lib/rdbr/query/lookup.rb +40 -0
  50. data/lib/rdbr/query/mysql.rb +15 -0
  51. data/lib/rdbr/query/page.rb +66 -0
  52. data/lib/rdbr/query/postgresql.rb +7 -0
  53. data/lib/rdbr/query/postgresql_dialect.rb +11 -0
  54. data/lib/rdbr/query/relational.rb +239 -0
  55. data/lib/rdbr/query/sqlite.rb +15 -0
  56. data/lib/rdbr/query/type_support.rb +68 -0
  57. data/lib/rdbr/query/value_limiter.rb +38 -0
  58. data/lib/rdbr/query.rb +32 -0
  59. data/lib/rdbr/version.rb +3 -0
  60. data/lib/rdbr/web/application.rb +234 -0
  61. data/lib/rdbr/web/array_value_helpers.rb +92 -0
  62. data/lib/rdbr/web/binary_value_helpers.rb +51 -0
  63. data/lib/rdbr/web/column_preferences.rb +56 -0
  64. data/lib/rdbr/web/database_graph.rb +91 -0
  65. data/lib/rdbr/web/deferred_column_value_helpers.rb +20 -0
  66. data/lib/rdbr/web/deferred_value_helpers.rb +76 -0
  67. data/lib/rdbr/web/document_value_helpers.rb +68 -0
  68. data/lib/rdbr/web/filter_presentation_helpers.rb +44 -0
  69. data/lib/rdbr/web/helpers.rb +42 -0
  70. data/lib/rdbr/web/identifier_value_helpers.rb +20 -0
  71. data/lib/rdbr/web/json_page_stream.rb +30 -0
  72. data/lib/rdbr/web/navigation_helpers.rb +115 -0
  73. data/lib/rdbr/web/presentation_helpers.rb +114 -0
  74. data/lib/rdbr/web/range_value_helpers.rb +86 -0
  75. data/lib/rdbr/web/record_value_helpers.rb +90 -0
  76. data/lib/rdbr/web/related_value_helpers.rb +99 -0
  77. data/lib/rdbr/web/relationship_loader.rb +65 -0
  78. data/lib/rdbr/web/search_value_helpers.rb +58 -0
  79. data/lib/rdbr/web/spatial_value_helpers.rb +83 -0
  80. data/lib/rdbr/web/through_relationship_loader.rb +90 -0
  81. data/lib/rdbr/web/vector_value_helpers.rb +59 -0
  82. data/lib/rdbr.rb +25 -0
  83. metadata +298 -0
@@ -0,0 +1,2141 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --light-canvas: #f2f5f6;
4
+ --light-surface: #fbfcfc;
5
+ --light-surface-raised: #fff;
6
+ --light-border: #d5dde1;
7
+ --light-border-strong: #aebbc2;
8
+ --light-text: #26343b;
9
+ --light-muted: #687981;
10
+ --light-orange: #b65b08;
11
+ --light-orange-bright: #934604;
12
+ --light-cool: #197d99;
13
+ --light-cool-bright: #11657d;
14
+ --light-blue: #256f98;
15
+ --light-blue-bright: #195675;
16
+ --light-green: #587d35;
17
+ --light-green-bright: #426326;
18
+ --light-yellow: #80651d;
19
+ --light-brown: #855a38;
20
+ --light-teal: #187b76;
21
+ --light-teal-bright: #0f5e5a;
22
+ --theme-text: var(--light-text);
23
+ --theme-surface-raised: var(--light-surface-raised);
24
+ --theme-border-strong: var(--light-border-strong);
25
+ --theme-muted: var(--light-muted);
26
+ --theme-accent: var(--light-cool);
27
+ --theme-link: var(--light-blue);
28
+ --theme-link-hover: var(--light-blue-bright);
29
+ --theme-primary: var(--light-orange);
30
+ --theme-primary-hover: var(--light-orange-bright);
31
+ --theme-data-action: var(--light-green);
32
+ --theme-data-action-hover: var(--light-green-bright);
33
+ --theme-utility: var(--light-teal);
34
+ --theme-metadata: var(--light-yellow);
35
+ --theme-warning: var(--light-brown);
36
+ --theme-overlay: rgb(23 32 51 / 45%);
37
+ --theme-popup-shadow: 0 0.8rem 2rem rgb(23 32 51 / 24%);
38
+ --theme-control-surface: var(--light-surface-raised);
39
+ --theme-control-text: var(--light-text);
40
+ --theme-important: #a94d0a;
41
+ --diagram-canvas: #edf2f3;
42
+ --diagram-grid: #d7e0e2;
43
+ --diagram-edge: #74868e;
44
+ --diagram-node: #fff;
45
+ --diagram-node-selected: #e3f2f1;
46
+ font-family: system-ui, sans-serif;
47
+ line-height: 1.5;
48
+ }
49
+
50
+ .popup-backdrop {
51
+ position: fixed;
52
+ inset: 0;
53
+ z-index: 100;
54
+ display: grid;
55
+ padding: 1.5rem;
56
+ background: var(--theme-overlay);
57
+ place-items: center;
58
+ }
59
+
60
+ .popup-surface {
61
+ color: var(--theme-text);
62
+ border: 1px solid var(--theme-border-strong);
63
+ border-radius: 0.5rem;
64
+ background: var(--theme-surface-raised);
65
+ box-shadow: var(--theme-popup-shadow);
66
+ }
67
+
68
+ .popup-surface .dialog-close {
69
+ color: var(--theme-control-text);
70
+ border-color: var(--theme-border-strong);
71
+ background: var(--theme-control-surface);
72
+ }
73
+
74
+ .popup-surface .dialog-close:hover {
75
+ color: var(--theme-accent);
76
+ border-color: var(--theme-accent);
77
+ background: var(--theme-control-surface);
78
+ }
79
+
80
+ body {
81
+ margin: 0;
82
+ color: #172033;
83
+ background: #f4f6f8;
84
+ }
85
+
86
+ a {
87
+ color: #075f52;
88
+ text-underline-offset: 0.15em;
89
+ }
90
+
91
+ body > header,
92
+ body > main {
93
+ width: min(70rem, calc(100% - 2rem));
94
+ margin: 0 auto;
95
+ }
96
+
97
+ body > header {
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: space-between;
101
+ padding: 1.25rem 0;
102
+ }
103
+
104
+ body > header .brand {
105
+ display: flex;
106
+ align-items: baseline;
107
+ gap: 0.75rem;
108
+ color: #172033;
109
+ text-decoration: none;
110
+ }
111
+
112
+ .brand-container {
113
+ position: relative;
114
+ z-index: 40;
115
+ }
116
+
117
+ .database-summary {
118
+ position: absolute;
119
+ top: calc(100% + 0.65rem);
120
+ left: 0;
121
+ z-index: 10;
122
+ width: max-content;
123
+ min-width: 18rem;
124
+ max-width: min(28rem, calc(100vw - 2rem));
125
+ padding: 0.85rem 1rem;
126
+ opacity: 0;
127
+ pointer-events: none;
128
+ transform: translateY(-0.25rem);
129
+ transition: opacity 120ms ease, transform 120ms ease;
130
+ }
131
+
132
+ .brand-container:hover .database-summary,
133
+ .brand-container:focus-within .database-summary {
134
+ opacity: 1;
135
+ transform: translateY(0);
136
+ }
137
+
138
+ .database-summary p {
139
+ margin: 0 0 0.65rem;
140
+ }
141
+
142
+ .database-summary dl {
143
+ display: flex;
144
+ gap: 1.5rem;
145
+ margin: 0;
146
+ }
147
+
148
+ .database-summary dl div {
149
+ display: flex;
150
+ gap: 0.4rem;
151
+ }
152
+
153
+ .database-summary dt {
154
+ color: #667085;
155
+ }
156
+
157
+ .database-summary dd {
158
+ margin: 0;
159
+ font-weight: 700;
160
+ }
161
+
162
+ body > header .brand strong {
163
+ font-size: 1.35rem;
164
+ }
165
+
166
+ body > header .brand-logo {
167
+ display: block;
168
+ width: 5.5rem;
169
+ height: auto;
170
+ }
171
+
172
+ body > header .brand span,
173
+ small,
174
+ .eyebrow {
175
+ color: #667085;
176
+ }
177
+
178
+ body > header nav {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 1rem;
182
+ }
183
+
184
+ .theme-picker {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 0.4rem;
188
+ color: var(--theme-muted);
189
+ font-size: 0.85rem;
190
+ }
191
+
192
+ .theme-picker select {
193
+ width: auto;
194
+ padding: 0.3rem 1.8rem 0.3rem 0.5rem;
195
+ }
196
+
197
+ main {
198
+ padding-bottom: 2rem;
199
+ }
200
+
201
+ .catalog-actions {
202
+ display: flex;
203
+ justify-content: flex-end;
204
+ }
205
+
206
+ section {
207
+ padding: 1.5rem;
208
+ border: 1px solid #d9dee8;
209
+ border-radius: 0.5rem;
210
+ background: #fff;
211
+ }
212
+
213
+ .page-heading {
214
+ display: flex;
215
+ align-items: flex-start;
216
+ justify-content: space-between;
217
+ border-bottom-right-radius: 0;
218
+ border-bottom-left-radius: 0;
219
+ }
220
+
221
+ .page-heading h2,
222
+ .page-heading p,
223
+ .record-section h3,
224
+ .relationship-section h3 {
225
+ margin-top: 0;
226
+ }
227
+
228
+ .page-heading h2 {
229
+ margin-bottom: 0.25rem;
230
+ }
231
+
232
+ .table-page-heading {
233
+ position: sticky;
234
+ top: 0;
235
+ z-index: 30;
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 1.25rem;
239
+ padding: 0.85rem 1rem;
240
+ }
241
+
242
+ .table-page-heading .heading-copy {
243
+ flex: 1 1 10rem;
244
+ }
245
+
246
+ .table-page-heading h2 {
247
+ margin: 0;
248
+ font-size: 1.3rem;
249
+ line-height: 1.25;
250
+ }
251
+
252
+ .table-page-heading .heading-copy > p {
253
+ margin: 0.35rem 0 0;
254
+ }
255
+
256
+ .eyebrow {
257
+ margin-bottom: 0.25rem;
258
+ font-size: 0.75rem;
259
+ font-weight: 700;
260
+ text-transform: uppercase;
261
+ }
262
+
263
+ .table-search {
264
+ position: relative;
265
+ flex: 0 1 18rem;
266
+ width: 18rem;
267
+ }
268
+
269
+ .table-search > span {
270
+ position: absolute;
271
+ top: 50%;
272
+ left: 0.65rem;
273
+ z-index: 1;
274
+ color: #667085;
275
+ font-size: 0.9rem;
276
+ transform: translateY(-50%);
277
+ pointer-events: none;
278
+ }
279
+
280
+ .table-search input[type='search'] {
281
+ width: 100%;
282
+ min-height: 2rem;
283
+ padding: 0.3rem 0.6rem 0.3rem 2rem;
284
+ }
285
+
286
+ .table-page-heading .table-heading-actions {
287
+ flex: 0 0 auto;
288
+ flex-wrap: nowrap;
289
+ white-space: nowrap;
290
+ }
291
+
292
+ .date-filter-trigger,
293
+ .temporal-value-filter {
294
+ min-height: 0;
295
+ padding: 0;
296
+ border: 0;
297
+ background: transparent;
298
+ color: #075f52;
299
+ font-weight: 400;
300
+ }
301
+
302
+ .date-filter-trigger {
303
+ color: #667085;
304
+ font-size: 0.9rem;
305
+ }
306
+
307
+ .temporal-value-filter {
308
+ text-decoration: underline;
309
+ text-decoration-style: dotted;
310
+ text-underline-offset: 0.15em;
311
+ }
312
+
313
+ .date-filter {
314
+ z-index: 110;
315
+ }
316
+
317
+ .date-filter[hidden] {
318
+ display: none;
319
+ }
320
+
321
+ .date-filter-panel {
322
+ box-sizing: border-box;
323
+ width: min(30rem, 100%);
324
+ padding: 1rem;
325
+ }
326
+
327
+ .date-filter-panel h3,
328
+ .date-filter-panel p {
329
+ margin: 0 0 0.75rem;
330
+ }
331
+
332
+ .date-filter-panel .dialog-close {
333
+ float: right;
334
+ min-width: 2rem;
335
+ min-height: 2rem;
336
+ padding: 0;
337
+ border-radius: 50%;
338
+ }
339
+
340
+ .date-presets {
341
+ display: flex;
342
+ flex-wrap: wrap;
343
+ gap: 0.4rem;
344
+ margin-bottom: 1rem;
345
+ }
346
+
347
+ .date-presets button {
348
+ min-height: 1.9rem;
349
+ padding: 0.25rem 0.5rem;
350
+ font-size: 0.8rem;
351
+ }
352
+
353
+ .date-range-form {
354
+ display: grid;
355
+ grid-template-columns: 9rem 9rem auto;
356
+ align-items: end;
357
+ gap: 0.5rem;
358
+ justify-content: start;
359
+ }
360
+
361
+ .date-range-form label {
362
+ display: grid;
363
+ gap: 0.2rem;
364
+ min-width: 0;
365
+ font-size: 0.75rem;
366
+ font-weight: 700;
367
+ }
368
+
369
+ .iso-date-input {
370
+ position: relative;
371
+ display: grid;
372
+ grid-template-columns: 1fr auto;
373
+ }
374
+
375
+ .iso-date-input > input[type='text'] {
376
+ width: 100%;
377
+ min-width: 0;
378
+ border-top-right-radius: 0;
379
+ border-bottom-right-radius: 0;
380
+ }
381
+
382
+ .date-picker-button {
383
+ min-width: 2.35rem;
384
+ padding: 0.35rem;
385
+ border-left: 0;
386
+ border-color: #b8c1cc;
387
+ border-top-left-radius: 0;
388
+ border-bottom-left-radius: 0;
389
+ color: #075f52;
390
+ background: #fff;
391
+ }
392
+
393
+ .native-date-picker {
394
+ position: absolute;
395
+ width: 1px;
396
+ height: 1px;
397
+ padding: 0;
398
+ overflow: hidden;
399
+ clip-path: inset(50%);
400
+ opacity: 0;
401
+ pointer-events: none;
402
+ }
403
+
404
+ input,
405
+ select,
406
+ button {
407
+ min-height: 2.35rem;
408
+ box-sizing: border-box;
409
+ padding: 0.45rem 0.6rem;
410
+ border: 1px solid #b8c1cc;
411
+ border-radius: 0.25rem;
412
+ background: #fff;
413
+ color: inherit;
414
+ font: inherit;
415
+ }
416
+
417
+ .column-picker-trigger,
418
+ .secondary-button {
419
+ border-color: #81b8ad;
420
+ background: #fff;
421
+ color: #075f52;
422
+ }
423
+
424
+ .column-picker {
425
+ position: fixed;
426
+ z-index: 100;
427
+ width: min(24rem, calc(100vw - 1rem));
428
+ max-height: calc(100vh - 1rem);
429
+ padding: 0.8rem;
430
+ overflow: auto;
431
+ }
432
+
433
+ .column-picker[hidden] {
434
+ display: none;
435
+ }
436
+
437
+ .column-picker-heading,
438
+ .column-picker-actions,
439
+ .column-picker li,
440
+ .column-picker label,
441
+ .column-move-actions {
442
+ display: flex;
443
+ align-items: center;
444
+ }
445
+
446
+ .column-picker-heading {
447
+ justify-content: space-between;
448
+ }
449
+
450
+ .column-picker h3,
451
+ .column-picker p {
452
+ margin: 0;
453
+ }
454
+
455
+ .column-picker p {
456
+ margin-top: 0.25rem;
457
+ color: #667085;
458
+ font-size: 0.75rem;
459
+ }
460
+
461
+ .column-picker-list {
462
+ display: grid;
463
+ gap: 0.25rem;
464
+ margin: 0.75rem 0;
465
+ padding: 0;
466
+ list-style: none;
467
+ }
468
+
469
+ .column-picker li {
470
+ gap: 0.4rem;
471
+ padding: 0.3rem;
472
+ border: 1px solid transparent;
473
+ border-radius: 0.25rem;
474
+ background: #f8fafb;
475
+ }
476
+
477
+ .column-picker li.dragging {
478
+ border-color: #81b8ad;
479
+ opacity: 0.55;
480
+ }
481
+
482
+ .column-drag-handle {
483
+ color: #98a2b3;
484
+ cursor: grab;
485
+ }
486
+
487
+ .column-picker label {
488
+ flex: 1;
489
+ gap: 0.4rem;
490
+ min-width: 0;
491
+ }
492
+
493
+ .column-picker label span {
494
+ overflow: hidden;
495
+ text-overflow: ellipsis;
496
+ white-space: nowrap;
497
+ }
498
+
499
+ .column-picker input[type='checkbox'] {
500
+ min-height: 0;
501
+ }
502
+
503
+ .column-move-actions {
504
+ gap: 0.2rem;
505
+ }
506
+
507
+ .column-move-actions button,
508
+ .column-picker .dialog-close {
509
+ min-width: 1.7rem;
510
+ min-height: 1.7rem;
511
+ padding: 0;
512
+ }
513
+
514
+ .column-picker-actions {
515
+ justify-content: flex-end;
516
+ gap: 0.4rem;
517
+ }
518
+
519
+ a:focus-visible,
520
+ button:focus-visible,
521
+ input:focus-visible,
522
+ select:focus-visible {
523
+ outline: 3px solid #f2b84b;
524
+ outline-offset: 2px;
525
+ }
526
+
527
+ button {
528
+ border-color: #075f52;
529
+ background: #075f52;
530
+ color: #fff;
531
+ cursor: pointer;
532
+ font-weight: 700;
533
+ }
534
+
535
+ .active-filters {
536
+ position: sticky;
537
+ top: var(--table-toolbar-height, 0);
538
+ z-index: 29;
539
+ display: flex;
540
+ align-items: center;
541
+ padding: 0.85rem 1rem;
542
+ border-top: 0;
543
+ border-radius: 0;
544
+ background: #eaf5f2;
545
+ }
546
+
547
+ .filter-chips {
548
+ display: flex;
549
+ align-items: center;
550
+ flex-wrap: wrap;
551
+ gap: 0.5rem;
552
+ }
553
+
554
+ .filter-chip {
555
+ display: inline-flex;
556
+ align-items: center;
557
+ gap: 0.5rem;
558
+ max-width: 100%;
559
+ padding: 0.3rem 0.5rem;
560
+ border: 1px solid #81b8ad;
561
+ border-radius: 0.25rem;
562
+ background: #fff;
563
+ font-size: 0.85rem;
564
+ }
565
+
566
+ .filter-chip strong {
567
+ overflow: hidden;
568
+ text-overflow: ellipsis;
569
+ white-space: nowrap;
570
+ font-size: 0.95rem;
571
+ }
572
+
573
+ .filter-chip small {
574
+ color: #667085;
575
+ font-size: 0.75rem;
576
+ }
577
+
578
+ .clear-all {
579
+ margin-left: 0.25rem;
580
+ color: #667085;
581
+ font-size: 0.8rem;
582
+ }
583
+
584
+ .remove-filter {
585
+ color: #98a2b3;
586
+ font-size: 1rem;
587
+ font-weight: 600;
588
+ line-height: 1;
589
+ text-decoration: none;
590
+ }
591
+
592
+ .data-section {
593
+ padding: 0;
594
+ border-top: 0;
595
+ border-top-left-radius: 0;
596
+ border-top-right-radius: 0;
597
+ }
598
+
599
+ .table-meta {
600
+ display: flex;
601
+ align-items: center;
602
+ justify-content: space-between;
603
+ gap: 1rem;
604
+ padding: 0.75rem 1rem;
605
+ }
606
+
607
+ .table-heading-actions,
608
+ .table-pagination {
609
+ display: flex;
610
+ align-items: center;
611
+ gap: 0.8rem;
612
+ }
613
+
614
+ .table-heading-actions {
615
+ flex-wrap: wrap;
616
+ justify-content: flex-end;
617
+ }
618
+
619
+ .rows-control,
620
+ .pagination {
621
+ display: flex;
622
+ align-items: center;
623
+ gap: 0.5rem;
624
+ }
625
+
626
+ .rows-control label {
627
+ font-size: 0.75rem;
628
+ font-weight: 700;
629
+ }
630
+
631
+ .rows-control select {
632
+ min-height: 1.75rem;
633
+ padding: 0.1rem 1.6rem 0.1rem 0.4rem;
634
+ font-size: 0.8rem;
635
+ }
636
+
637
+ .pagination a,
638
+ .pagination .disabled {
639
+ min-width: 1.5rem;
640
+ text-align: center;
641
+ }
642
+
643
+ .pagination input {
644
+ width: 3.8rem;
645
+ min-height: 1.75rem;
646
+ padding: 0.1rem 0.3rem;
647
+ font-size: 0.8rem;
648
+ text-align: center;
649
+ }
650
+
651
+ .visually-hidden {
652
+ position: absolute;
653
+ width: 1px;
654
+ height: 1px;
655
+ overflow: hidden;
656
+ clip: rect(0 0 0 0);
657
+ clip-path: inset(50%);
658
+ white-space: nowrap;
659
+ }
660
+
661
+ .table-meta p {
662
+ margin: 0;
663
+ }
664
+
665
+ .notice {
666
+ color: #8a4b08;
667
+ font-size: 0.875rem;
668
+ }
669
+
670
+ .table-scroll {
671
+ overflow-x: auto;
672
+ border-top: 1px solid #d9dee8;
673
+ border-bottom: 1px solid #d9dee8;
674
+ scrollbar-width: none;
675
+ }
676
+
677
+ [data-restore-table-scroll] .table-scroll {
678
+ visibility: hidden;
679
+ }
680
+
681
+ .table-scroll::-webkit-scrollbar {
682
+ height: 0;
683
+ }
684
+
685
+ .data-table {
686
+ white-space: nowrap;
687
+ }
688
+
689
+ .data-table tbody tr:hover {
690
+ background: #f3f8f7;
691
+ }
692
+
693
+ .data-table th {
694
+ vertical-align: bottom;
695
+ background: #f8fafb;
696
+ box-shadow: 0 0.35rem 0.5rem -0.5rem rgba(23, 32, 51, 0.65);
697
+ }
698
+
699
+ .floating-table-header {
700
+ position: fixed;
701
+ top: 0;
702
+ z-index: 20;
703
+ display: none;
704
+ overflow: hidden;
705
+ border-bottom: 1px solid #d9dee8;
706
+ background: #f8fafb;
707
+ box-shadow: 0 0.35rem 0.7rem rgba(23, 32, 51, 0.18);
708
+ }
709
+
710
+ .floating-table-header.visible {
711
+ display: block;
712
+ }
713
+
714
+ .floating-horizontal-scroll {
715
+ position: sticky;
716
+ z-index: 21;
717
+ display: none;
718
+ box-sizing: border-box;
719
+ height: 1rem;
720
+ overflow-x: auto;
721
+ overflow-y: hidden;
722
+ border-top: 1px solid #d7dde5;
723
+ border-bottom: 1px solid #bfc8d3;
724
+ background: #eef2f4;
725
+ scrollbar-color: #8d969f #eef2f4;
726
+ }
727
+
728
+ .floating-horizontal-scroll.visible {
729
+ display: block;
730
+ }
731
+
732
+ .floating-horizontal-scroll-width {
733
+ height: 1px;
734
+ }
735
+
736
+ .floating-table-header .data-table {
737
+ table-layout: fixed;
738
+ }
739
+
740
+ .floating-table-header th {
741
+ box-sizing: border-box;
742
+ }
743
+
744
+ .floating-table-header th.record-link-column {
745
+ z-index: 2;
746
+ }
747
+
748
+ .data-table td {
749
+ max-width: 28rem;
750
+ overflow: hidden;
751
+ text-overflow: ellipsis;
752
+ }
753
+
754
+ .value-filter {
755
+ display: inline-block;
756
+ max-width: 100%;
757
+ overflow: hidden;
758
+ color: inherit;
759
+ text-overflow: ellipsis;
760
+ vertical-align: bottom;
761
+ white-space: nowrap;
762
+ text-decoration-color: #81b8ad;
763
+ text-decoration-style: dotted;
764
+ }
765
+
766
+ .value-filter:hover {
767
+ color: #075f52;
768
+ text-decoration-style: solid;
769
+ }
770
+
771
+ .relationship-link {
772
+ margin-left: 0.4rem;
773
+ font-weight: 700;
774
+ text-decoration: none;
775
+ }
776
+
777
+ .column-heading {
778
+ display: flex;
779
+ align-items: baseline;
780
+ justify-content: space-between;
781
+ gap: 1rem;
782
+ }
783
+
784
+ .column-heading .column-name {
785
+ text-decoration-line: underline;
786
+ text-decoration-style: dotted;
787
+ text-decoration-color: #98a2b3;
788
+ text-underline-offset: 0.2em;
789
+ }
790
+
791
+ .group-link,
792
+ .secondary-link {
793
+ margin-left: 0.5rem;
794
+ font-size: 0.75rem;
795
+ font-weight: 400;
796
+ }
797
+
798
+ .record-link-column {
799
+ position: sticky;
800
+ left: 0;
801
+ z-index: 2;
802
+ background: rgba(248, 250, 251, 0.94);
803
+ box-shadow: 0.45rem 0 0.65rem -0.65rem rgba(23, 32, 51, 0.8);
804
+ backdrop-filter: blur(3px);
805
+ font-weight: 600;
806
+ }
807
+
808
+ .pagination .disabled {
809
+ color: #98a2b3;
810
+ }
811
+
812
+ .null,
813
+ .binary,
814
+ .empty {
815
+ color: #667085;
816
+ font-style: italic;
817
+ }
818
+
819
+ .boolean,
820
+ .number {
821
+ font-variant-numeric: tabular-nums;
822
+ }
823
+
824
+ .structured {
825
+ white-space: pre-wrap;
826
+ }
827
+
828
+ .record-section,
829
+ .relationship-section {
830
+ margin-top: 1rem;
831
+ }
832
+
833
+ .record-section {
834
+ padding: 0;
835
+ overflow: hidden;
836
+ }
837
+
838
+ .relationship-section {
839
+ padding: 1rem;
840
+ }
841
+
842
+ .relationship-section h3 {
843
+ margin-bottom: 0.4rem;
844
+ }
845
+
846
+ .record-fields {
847
+ display: grid;
848
+ grid-template-columns: repeat(2, minmax(0, 1fr));
849
+ margin: 0;
850
+ }
851
+
852
+ .record-fields > div {
853
+ display: grid;
854
+ grid-template-columns: minmax(7rem, 30%) minmax(0, 1fr);
855
+ align-items: baseline;
856
+ gap: 0.65rem;
857
+ min-width: 0;
858
+ padding: 0.65rem 0.75rem;
859
+ border-bottom: 1px solid #d9dee8;
860
+ }
861
+
862
+ .record-fields > div:nth-child(odd) {
863
+ border-right: 1px solid #d9dee8;
864
+ }
865
+
866
+ .record-fields dt,
867
+ .record-fields dd {
868
+ min-width: 0;
869
+ margin: 0;
870
+ }
871
+
872
+ .record-fields dt {
873
+ font-weight: 700;
874
+ overflow-wrap: anywhere;
875
+ }
876
+
877
+ .record-fields dd {
878
+ overflow-wrap: anywhere;
879
+ white-space: pre-wrap;
880
+ }
881
+
882
+ .record-fields dd.related-record-value {
883
+ white-space: normal;
884
+ }
885
+
886
+ .text-preview {
887
+ display: block;
888
+ width: 100%;
889
+ min-height: 0;
890
+ padding: 0;
891
+ border: 0;
892
+ background: transparent;
893
+ color: inherit;
894
+ font-weight: 400;
895
+ text-align: left;
896
+ }
897
+
898
+ .text-preview span {
899
+ display: block;
900
+ }
901
+
902
+ .text-preview small {
903
+ display: block;
904
+ margin-top: 0.25rem;
905
+ color: #075f52;
906
+ font-weight: 700;
907
+ }
908
+
909
+ .json-preview {
910
+ min-height: 0;
911
+ padding: 0;
912
+ border: 0;
913
+ background: transparent;
914
+ color: #075f52;
915
+ font-weight: 700;
916
+ text-decoration: underline;
917
+ text-underline-offset: 0.15em;
918
+ }
919
+
920
+ .deferred-value-controls {
921
+ display: inline-flex;
922
+ align-items: center;
923
+ gap: 0.3rem;
924
+ }
925
+
926
+ .deferred-value-view,
927
+ .deferred-value-copy {
928
+ min-height: 0;
929
+ padding: 0.1rem 0.25rem;
930
+ border: 0;
931
+ background: transparent;
932
+ color: #075f52;
933
+ }
934
+
935
+ .deferred-value-view {
936
+ font-size: 0.8rem;
937
+ font-weight: 600;
938
+ text-decoration: underline;
939
+ text-underline-offset: 0.15em;
940
+ }
941
+
942
+ .deferred-value-copy {
943
+ display: inline-grid;
944
+ place-items: center;
945
+ }
946
+
947
+ .deferred-value-copy svg {
948
+ width: 1rem;
949
+ height: 1rem;
950
+ fill: currentColor;
951
+ }
952
+
953
+ .deferred-copy-status {
954
+ color: #667085;
955
+ font-size: 0.7rem;
956
+ }
957
+
958
+ .deferred-value-summary {
959
+ color: #667085;
960
+ font-size: 0.75rem;
961
+ }
962
+
963
+ .deferred-value-summary::before {
964
+ content: '· ';
965
+ }
966
+
967
+ .deferred-dialog-copy {
968
+ position: sticky;
969
+ top: 0;
970
+ float: right;
971
+ display: inline-flex;
972
+ align-items: center;
973
+ gap: 0.2rem;
974
+ margin-right: 0.3rem;
975
+ }
976
+
977
+ .deferred-dialog-copy .deferred-value-copy {
978
+ min-width: 2rem;
979
+ min-height: 2rem;
980
+ }
981
+
982
+ .deferred-value-popover {
983
+ position: fixed;
984
+ z-index: 100;
985
+ box-sizing: border-box;
986
+ width: max-content;
987
+ max-width: min(32rem, calc(100vw - 1rem));
988
+ max-height: min(28rem, calc(100vh - 1rem));
989
+ padding: 0.7rem 2.4rem 0.7rem 0.8rem;
990
+ overflow: auto;
991
+ }
992
+
993
+ .deferred-value-popover[hidden] {
994
+ display: none;
995
+ }
996
+
997
+ .deferred-value-popover .dialog-close {
998
+ position: sticky;
999
+ top: 0.3rem;
1000
+ float: right;
1001
+ margin: -0.4rem -2.1rem 0 0.4rem;
1002
+ min-width: 1.6rem;
1003
+ min-height: 1.6rem;
1004
+ padding: 0;
1005
+ border-radius: 50%;
1006
+ line-height: 1;
1007
+ }
1008
+
1009
+ .deferred-value-popover pre {
1010
+ margin: 0;
1011
+ overflow-wrap: anywhere;
1012
+ white-space: pre-wrap;
1013
+ font: inherit;
1014
+ }
1015
+
1016
+ .text-dialog[hidden] {
1017
+ display: none;
1018
+ }
1019
+
1020
+ .text-dialog-panel {
1021
+ position: relative;
1022
+ width: min(52rem, calc(100% - 3rem));
1023
+ max-height: calc(100vh - 3rem);
1024
+ padding: 1.25rem;
1025
+ overflow: auto;
1026
+ }
1027
+
1028
+ .text-dialog .dialog-close {
1029
+ position: sticky;
1030
+ top: 0;
1031
+ float: right;
1032
+ min-width: 2rem;
1033
+ min-height: 2rem;
1034
+ padding: 0;
1035
+ border-radius: 50%;
1036
+ font-size: 1.25rem;
1037
+ line-height: 1;
1038
+ }
1039
+
1040
+ .text-dialog pre {
1041
+ margin: 0;
1042
+ padding-right: 2.5rem;
1043
+ overflow-wrap: anywhere;
1044
+ white-space: pre-wrap;
1045
+ font: inherit;
1046
+ }
1047
+
1048
+ .relationship-list {
1049
+ display: grid;
1050
+ gap: 0.5rem;
1051
+ padding-left: 1.25rem;
1052
+ }
1053
+
1054
+ .relationship-list small {
1055
+ margin-left: 0.5rem;
1056
+ }
1057
+
1058
+ .related-records {
1059
+ border-top: 1px solid #d9dee8;
1060
+ }
1061
+
1062
+ .related-records header {
1063
+ display: flex;
1064
+ align-items: baseline;
1065
+ gap: 0.65rem;
1066
+ padding: 0.5rem 0 0;
1067
+ }
1068
+
1069
+ .related-records h4 {
1070
+ margin: 0;
1071
+ }
1072
+
1073
+ .related-records ul {
1074
+ margin: 0.4rem 0;
1075
+ }
1076
+
1077
+ .empty-related-records {
1078
+ margin: 0.4rem 0;
1079
+ color: var(--theme-muted);
1080
+ }
1081
+
1082
+ .related-records > .secondary-link {
1083
+ display: inline-block;
1084
+ margin: 0.1rem 0 0.35rem;
1085
+ }
1086
+
1087
+ .empty-state {
1088
+ padding: 2rem;
1089
+ color: #667085;
1090
+ text-align: left;
1091
+ }
1092
+
1093
+ @media (max-width: 60rem) {
1094
+ .table-page-heading {
1095
+ flex-wrap: wrap;
1096
+ }
1097
+
1098
+ .table-search {
1099
+ order: 3;
1100
+ flex-basis: 100%;
1101
+ width: 100%;
1102
+ }
1103
+ }
1104
+
1105
+ @media (max-width: 40rem) {
1106
+ body > header,
1107
+ .page-heading,
1108
+ .table-meta {
1109
+ align-items: flex-start;
1110
+ flex-direction: column;
1111
+ }
1112
+
1113
+ body > header nav {
1114
+ margin-top: 0.5rem;
1115
+ }
1116
+
1117
+ .record-fields > div {
1118
+ grid-template-columns: minmax(6rem, 35%) minmax(0, 1fr);
1119
+ border-right: 0;
1120
+ }
1121
+
1122
+ .record-fields {
1123
+ grid-template-columns: 1fr;
1124
+ }
1125
+
1126
+ .date-range-form {
1127
+ grid-template-columns: 1fr;
1128
+ }
1129
+
1130
+ .date-range-form > button {
1131
+ width: 100%;
1132
+ }
1133
+ }
1134
+
1135
+ dl.summary {
1136
+ display: flex;
1137
+ gap: 2rem;
1138
+ }
1139
+
1140
+ dl.summary div {
1141
+ display: flex;
1142
+ gap: 0.5rem;
1143
+ }
1144
+
1145
+ dl.summary dt {
1146
+ font-weight: 700;
1147
+ }
1148
+
1149
+ section.namespace {
1150
+ margin-top: 1rem;
1151
+ }
1152
+
1153
+ .database-diagram[hidden] {
1154
+ display: none;
1155
+ }
1156
+
1157
+ .database-diagram {
1158
+ padding: 0.75rem;
1159
+ }
1160
+
1161
+ .database-diagram-shell {
1162
+ display: grid;
1163
+ grid-template-rows: auto auto minmax(0, 1fr);
1164
+ width: 100%;
1165
+ height: 100%;
1166
+ overflow: hidden;
1167
+ }
1168
+
1169
+ .database-diagram-heading,
1170
+ .database-diagram-toolbar {
1171
+ display: flex;
1172
+ align-items: center;
1173
+ justify-content: space-between;
1174
+ gap: 1rem;
1175
+ padding: 0.7rem 1rem;
1176
+ border-bottom: 1px solid var(--theme-border-strong);
1177
+ }
1178
+
1179
+ .database-diagram-heading h2,
1180
+ .database-diagram-heading p,
1181
+ .database-diagram-toolbar p {
1182
+ margin: 0;
1183
+ }
1184
+
1185
+ .database-diagram-actions {
1186
+ display: flex;
1187
+ align-items: center;
1188
+ gap: 0.4rem;
1189
+ }
1190
+
1191
+ .database-diagram-actions button {
1192
+ min-width: 2.25rem;
1193
+ }
1194
+
1195
+ .database-diagram-toolbar input {
1196
+ width: min(22rem, 40vw);
1197
+ }
1198
+
1199
+ .database-diagram-help,
1200
+ .database-diagram-kind {
1201
+ color: var(--theme-muted);
1202
+ }
1203
+
1204
+ .database-diagram-body {
1205
+ display: grid;
1206
+ grid-template-columns: minmax(0, 1fr) 20rem;
1207
+ min-height: 0;
1208
+ }
1209
+
1210
+ .database-diagram-canvas {
1211
+ position: relative;
1212
+ min-width: 0;
1213
+ min-height: 0;
1214
+ overflow: hidden;
1215
+ background-color: var(--diagram-canvas);
1216
+ background-image:
1217
+ linear-gradient(var(--diagram-grid) 1px, transparent 1px),
1218
+ linear-gradient(90deg, var(--diagram-grid) 1px, transparent 1px);
1219
+ background-size: 24px 24px;
1220
+ }
1221
+
1222
+ .database-diagram-status {
1223
+ position: absolute;
1224
+ top: 50%;
1225
+ left: 50%;
1226
+ z-index: 1;
1227
+ margin: 0;
1228
+ transform: translate(-50%, -50%);
1229
+ }
1230
+
1231
+ .database-diagram-canvas svg {
1232
+ display: block;
1233
+ width: 100%;
1234
+ height: 100%;
1235
+ cursor: grab;
1236
+ touch-action: none;
1237
+ }
1238
+
1239
+ .database-diagram-canvas svg.panning {
1240
+ cursor: grabbing;
1241
+ }
1242
+
1243
+ .database-diagram-edge {
1244
+ fill: none;
1245
+ stroke: var(--diagram-edge);
1246
+ stroke-width: 1.5;
1247
+ vector-effect: non-scaling-stroke;
1248
+ }
1249
+
1250
+ .database-diagram-edge.inferred {
1251
+ stroke-dasharray: 5 4;
1252
+ }
1253
+
1254
+ #database-diagram-arrow path {
1255
+ fill: var(--diagram-edge);
1256
+ }
1257
+
1258
+ .database-diagram-node {
1259
+ cursor: pointer;
1260
+ }
1261
+
1262
+ .database-diagram-node rect {
1263
+ fill: var(--diagram-node);
1264
+ stroke: var(--theme-border-strong);
1265
+ stroke-width: 1.5;
1266
+ vector-effect: non-scaling-stroke;
1267
+ }
1268
+
1269
+ .database-diagram-node.search-match rect {
1270
+ stroke: var(--theme-important);
1271
+ stroke-width: 3;
1272
+ }
1273
+
1274
+ .database-diagram-node:hover rect,
1275
+ .database-diagram-node:focus rect {
1276
+ fill: var(--diagram-node-selected);
1277
+ stroke: var(--theme-accent);
1278
+ stroke-width: 2.5;
1279
+ outline: none;
1280
+ }
1281
+
1282
+ .database-diagram-node.selected rect {
1283
+ fill: var(--diagram-node-selected);
1284
+ stroke: var(--theme-accent);
1285
+ stroke-width: 3;
1286
+ outline: none;
1287
+ }
1288
+
1289
+ .database-diagram-node:focus {
1290
+ outline: none;
1291
+ }
1292
+
1293
+ .database-diagram-node-name {
1294
+ fill: var(--theme-text);
1295
+ font-size: 15px;
1296
+ font-weight: 700;
1297
+ }
1298
+
1299
+ .database-diagram-node-namespace {
1300
+ fill: var(--theme-muted);
1301
+ font-size: 11px;
1302
+ }
1303
+
1304
+ .database-diagram-details {
1305
+ min-width: 0;
1306
+ padding: 1rem;
1307
+ overflow: auto;
1308
+ border-left: 1px solid var(--theme-border-strong);
1309
+ overscroll-behavior: contain;
1310
+ }
1311
+
1312
+ .database-diagram-details h3,
1313
+ .database-diagram-details p {
1314
+ margin-top: 0;
1315
+ overflow-wrap: anywhere;
1316
+ }
1317
+
1318
+ .database-diagram-details dl {
1319
+ margin: 1rem 0 0;
1320
+ }
1321
+
1322
+ .database-diagram-details dl div {
1323
+ padding: 0.45rem 0;
1324
+ border-top: 1px solid var(--theme-border-strong);
1325
+ }
1326
+
1327
+ .database-diagram-details dt {
1328
+ font-weight: 700;
1329
+ overflow-wrap: anywhere;
1330
+ }
1331
+
1332
+ .database-diagram-details dd {
1333
+ margin: 0.1rem 0 0;
1334
+ color: var(--theme-muted);
1335
+ overflow-wrap: anywhere;
1336
+ }
1337
+
1338
+ @media (max-width: 50rem) {
1339
+ .database-diagram {
1340
+ padding: 0;
1341
+ }
1342
+
1343
+ .database-diagram-shell {
1344
+ border-radius: 0;
1345
+ }
1346
+
1347
+ .database-diagram-heading,
1348
+ .database-diagram-toolbar {
1349
+ align-items: flex-start;
1350
+ }
1351
+
1352
+ .database-diagram-toolbar {
1353
+ flex-direction: column;
1354
+ }
1355
+
1356
+ .database-diagram-toolbar input {
1357
+ width: min(22rem, calc(100vw - 2rem));
1358
+ }
1359
+
1360
+ .database-diagram-body {
1361
+ grid-template-columns: minmax(0, 1fr);
1362
+ grid-template-rows: minmax(16rem, 1fr) minmax(8rem, 35%);
1363
+ }
1364
+
1365
+ .database-diagram-details {
1366
+ border-top: 1px solid var(--theme-border-strong);
1367
+ border-left: 0;
1368
+ }
1369
+ }
1370
+
1371
+ .relation-cell {
1372
+ display: flex;
1373
+ align-items: center;
1374
+ gap: 0.45rem;
1375
+ }
1376
+
1377
+ .relation-schema {
1378
+ position: relative;
1379
+ }
1380
+
1381
+ .relation-schema summary {
1382
+ display: grid;
1383
+ width: 1.25rem;
1384
+ height: 1.25rem;
1385
+ border: 1px solid var(--theme-border-strong);
1386
+ border-radius: 50%;
1387
+ color: var(--theme-muted);
1388
+ font-size: 0.75rem;
1389
+ font-weight: 700;
1390
+ line-height: 1;
1391
+ cursor: pointer;
1392
+ list-style: none;
1393
+ place-items: center;
1394
+ }
1395
+
1396
+ .relation-schema summary::-webkit-details-marker {
1397
+ display: none;
1398
+ }
1399
+
1400
+ .relation-schema summary:hover,
1401
+ .relation-schema summary:focus-visible,
1402
+ .relation-schema[open] summary {
1403
+ border-color: var(--theme-accent);
1404
+ color: var(--theme-accent);
1405
+ outline: none;
1406
+ }
1407
+
1408
+ .schema-popover {
1409
+ position: fixed;
1410
+ top: 50%;
1411
+ left: 50%;
1412
+ z-index: 100;
1413
+ width: min(44rem, calc(100vw - 3rem));
1414
+ max-height: calc(100vh - 3rem);
1415
+ padding: 1rem;
1416
+ overflow: auto;
1417
+ overscroll-behavior: contain;
1418
+ transform: translate(-50%, -50%);
1419
+ }
1420
+
1421
+ .schema-popover .dialog-close {
1422
+ position: sticky;
1423
+ top: 0;
1424
+ float: right;
1425
+ min-width: 1.75rem;
1426
+ min-height: 1.75rem;
1427
+ margin: -0.25rem -0.25rem 0 0.5rem;
1428
+ padding: 0;
1429
+ border-radius: 50%;
1430
+ font-size: 1.1rem;
1431
+ line-height: 1;
1432
+ }
1433
+
1434
+ .schema-popover-heading {
1435
+ display: flex;
1436
+ align-items: flex-end;
1437
+ justify-content: space-between;
1438
+ gap: 1rem;
1439
+ margin-bottom: 0.75rem;
1440
+ }
1441
+
1442
+ .schema-popover-heading h4,
1443
+ .schema-popover-heading p {
1444
+ margin: 0;
1445
+ }
1446
+
1447
+ .schema-table-scroll {
1448
+ overflow-x: auto;
1449
+ }
1450
+
1451
+ .schema-table {
1452
+ min-width: 36rem;
1453
+ font-size: 0.875rem;
1454
+ }
1455
+
1456
+ .schema-table th,
1457
+ .schema-table td {
1458
+ vertical-align: top;
1459
+ }
1460
+
1461
+ .schema-table tbody th {
1462
+ font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
1463
+ }
1464
+
1465
+ .schema-key {
1466
+ display: block;
1467
+ width: max-content;
1468
+ color: var(--theme-accent);
1469
+ font-size: 0.8rem;
1470
+ font-weight: 700;
1471
+ }
1472
+
1473
+ .schema-empty {
1474
+ color: var(--theme-muted);
1475
+ }
1476
+
1477
+ table {
1478
+ width: 100%;
1479
+ border-collapse: collapse;
1480
+ }
1481
+
1482
+ th,
1483
+ td {
1484
+ padding: 0.5rem;
1485
+ border-bottom: 1px solid #d9dee8;
1486
+ text-align: left;
1487
+ }
1488
+
1489
+ /* Light theme */
1490
+ body {
1491
+ color: var(--light-text);
1492
+ background:
1493
+ radial-gradient(circle at 88% -8%, rgb(25 125 153 / 12%), transparent 28rem),
1494
+ var(--light-canvas);
1495
+ }
1496
+
1497
+ a,
1498
+ .text-preview-toggle,
1499
+ .json-value-toggle {
1500
+ color: var(--theme-link);
1501
+ }
1502
+
1503
+ a:hover,
1504
+ .text-preview-toggle:hover,
1505
+ .json-value-toggle:hover {
1506
+ color: var(--theme-link-hover);
1507
+ }
1508
+
1509
+ body > header .brand {
1510
+ color: var(--light-text);
1511
+ }
1512
+
1513
+ body > header .brand strong {
1514
+ color: var(--light-cool-bright);
1515
+ }
1516
+
1517
+ body > header .brand span,
1518
+ body > header small,
1519
+ .eyebrow,
1520
+ .database-summary dt,
1521
+ .table-search-icon,
1522
+ .filter-label,
1523
+ .filter-remove,
1524
+ .page-jump-label,
1525
+ .empty-state {
1526
+ color: var(--light-muted);
1527
+ }
1528
+
1529
+ .database-summary {
1530
+ background: rgb(255 255 255 / 98%);
1531
+ }
1532
+
1533
+ section {
1534
+ border-color: var(--light-border);
1535
+ background: var(--light-surface);
1536
+ box-shadow: 0 0.65rem 1.6rem rgb(38 52 59 / 8%);
1537
+ }
1538
+
1539
+ .table-page-heading {
1540
+ background: var(--light-surface);
1541
+ box-shadow: 0 0.35rem 0.9rem rgb(38 52 59 / 11%);
1542
+ }
1543
+
1544
+ input,
1545
+ select,
1546
+ button,
1547
+ .text-preview-dialog,
1548
+ .json-value-dialog {
1549
+ color: var(--light-text);
1550
+ border-color: var(--light-border-strong);
1551
+ background: var(--light-surface-raised);
1552
+ }
1553
+
1554
+ input::placeholder {
1555
+ color: var(--light-muted);
1556
+ }
1557
+
1558
+ button {
1559
+ color: #fff;
1560
+ border-color: var(--theme-primary);
1561
+ background: var(--theme-primary);
1562
+ }
1563
+
1564
+ button:hover {
1565
+ border-color: var(--theme-primary-hover);
1566
+ background: var(--theme-primary-hover);
1567
+ }
1568
+
1569
+ .date-filter-trigger,
1570
+ .temporal-value-filter,
1571
+ .date-filter-trigger:hover,
1572
+ .temporal-value-filter:hover {
1573
+ border: 0;
1574
+ background: transparent;
1575
+ }
1576
+
1577
+ .date-filter-trigger {
1578
+ color: var(--light-muted);
1579
+ }
1580
+
1581
+ .date-filter-trigger:hover {
1582
+ color: var(--light-cool-bright);
1583
+ }
1584
+
1585
+ .temporal-value-filter {
1586
+ color: var(--theme-data-action);
1587
+ }
1588
+
1589
+ .temporal-value-filter:hover {
1590
+ color: var(--theme-data-action-hover);
1591
+ }
1592
+
1593
+ .group-link,
1594
+ .secondary-link {
1595
+ color: var(--theme-utility);
1596
+ }
1597
+
1598
+ .group-link:hover,
1599
+ .secondary-link:hover {
1600
+ color: var(--light-teal-bright);
1601
+ }
1602
+
1603
+ .active-filters {
1604
+ border-color: var(--light-border);
1605
+ border-left: 0.25rem solid var(--light-green);
1606
+ background: #edf4e8;
1607
+ }
1608
+
1609
+ .filter-chip {
1610
+ border-color: #b8c8ad;
1611
+ background: var(--light-surface-raised);
1612
+ }
1613
+
1614
+ .filter-chip strong,
1615
+ .relationship-link {
1616
+ color: var(--light-green);
1617
+ }
1618
+
1619
+ .filter-chip strong:hover,
1620
+ .relationship-link:hover {
1621
+ color: var(--light-green-bright);
1622
+ }
1623
+
1624
+ .notice {
1625
+ color: var(--theme-warning);
1626
+ }
1627
+
1628
+ .filter-chip small,
1629
+ .clear-all,
1630
+ .remove-filter,
1631
+ .column-picker p,
1632
+ .column-drag-handle,
1633
+ .deferred-copy-status,
1634
+ .deferred-value-summary {
1635
+ color: var(--light-muted);
1636
+ }
1637
+
1638
+ .table-scroll {
1639
+ border-color: var(--light-border);
1640
+ }
1641
+
1642
+ .data-table tbody tr:hover td {
1643
+ background: #edf5f4;
1644
+ }
1645
+
1646
+ .data-table th,
1647
+ .floating-table-header,
1648
+ .floating-table-header table {
1649
+ background: #edf3f5;
1650
+ }
1651
+
1652
+ .floating-table-header,
1653
+ .floating-horizontal-scroll {
1654
+ border-color: var(--light-border);
1655
+ box-shadow: 0 0.4rem 0.9rem rgb(38 52 59 / 14%);
1656
+ }
1657
+
1658
+ .record-link-column {
1659
+ background: rgb(242 247 248 / 97%);
1660
+ }
1661
+
1662
+ .data-table tbody tr:hover .record-link-column {
1663
+ background: rgb(230 241 240 / 98%);
1664
+ }
1665
+
1666
+ .disabled,
1667
+ .null,
1668
+ .related-empty,
1669
+ .empty {
1670
+ color: var(--light-muted);
1671
+ }
1672
+
1673
+ .binary {
1674
+ color: var(--light-brown);
1675
+ }
1676
+
1677
+ .boolean {
1678
+ color: var(--theme-metadata);
1679
+ }
1680
+
1681
+ .number {
1682
+ color: var(--light-blue);
1683
+ }
1684
+
1685
+ .value-filter {
1686
+ color: var(--light-text);
1687
+ text-decoration-color: var(--light-teal);
1688
+ }
1689
+
1690
+ .value-filter:hover {
1691
+ color: var(--theme-data-action-hover);
1692
+ text-decoration-color: var(--theme-data-action);
1693
+ }
1694
+
1695
+ .record-fields dt,
1696
+ .schema-table tbody th {
1697
+ color: var(--theme-metadata);
1698
+ }
1699
+
1700
+ .schema-key {
1701
+ color: var(--light-green);
1702
+ }
1703
+
1704
+ .record-fields,
1705
+ .record-fields > div,
1706
+ .related-records,
1707
+ th,
1708
+ td {
1709
+ border-color: var(--light-border);
1710
+ }
1711
+
1712
+ .text-preview,
1713
+ .text-preview:hover {
1714
+ color: var(--light-text);
1715
+ border: 0;
1716
+ background: transparent;
1717
+ }
1718
+
1719
+ .text-preview small,
1720
+ .json-preview,
1721
+ .deferred-value-view,
1722
+ .deferred-value-copy {
1723
+ color: var(--theme-utility);
1724
+ border: 0;
1725
+ background: transparent;
1726
+ }
1727
+
1728
+ .text-preview:hover small,
1729
+ .json-preview:hover,
1730
+ .deferred-value-view:hover,
1731
+ .deferred-value-copy:hover {
1732
+ color: var(--light-teal-bright);
1733
+ border: 0;
1734
+ background: transparent;
1735
+ }
1736
+
1737
+ .column-picker-trigger,
1738
+ .date-picker-button,
1739
+ .secondary-button {
1740
+ color: var(--light-cool-bright);
1741
+ border-color: var(--light-border-strong);
1742
+ background: var(--light-surface-raised);
1743
+ }
1744
+
1745
+ .column-picker-trigger:hover,
1746
+ .date-picker-button:hover,
1747
+ .secondary-button:hover {
1748
+ color: var(--light-cool-bright);
1749
+ border-color: var(--light-cool);
1750
+ background: #edf4f5;
1751
+ }
1752
+
1753
+ .column-picker li {
1754
+ background: #f2f6f7;
1755
+ }
1756
+
1757
+ .column-picker li.dragging {
1758
+ border-color: var(--light-cool);
1759
+ }
1760
+
1761
+ .column-move-actions button,
1762
+ .deferred-dialog-copy button {
1763
+ color: var(--light-text);
1764
+ border-color: var(--light-border-strong);
1765
+ background: var(--light-surface-raised);
1766
+ }
1767
+
1768
+ .column-move-actions button:hover,
1769
+ .deferred-dialog-copy button:hover {
1770
+ color: var(--light-cool-bright);
1771
+ border-color: var(--light-cool);
1772
+ background: #edf4f5;
1773
+ }
1774
+
1775
+ /* Dark theme */
1776
+ :root[data-theme='dark'] {
1777
+ color-scheme: dark;
1778
+ --dark-canvas: #101213;
1779
+ --dark-surface: #17191b;
1780
+ --dark-surface-raised: #202326;
1781
+ --dark-border: #34383c;
1782
+ --dark-border-strong: #4a5055;
1783
+ --dark-text: #d8dadb;
1784
+ --dark-muted: #92989d;
1785
+ --dark-accent: #f39819;
1786
+ --dark-accent-bright: #ffb044;
1787
+ --dark-cool: #18a8c7;
1788
+ --dark-cool-bright: #41c5df;
1789
+ --dark-state: #91ad58;
1790
+ --dark-blue: #4aa5d8;
1791
+ --dark-blue-bright: #70bce8;
1792
+ --dark-green: #91ad58;
1793
+ --dark-green-bright: #b0ca72;
1794
+ --dark-yellow: #d7ba7d;
1795
+ --dark-brown: #b88a5a;
1796
+ --dark-teal: #4db6ac;
1797
+ --theme-text: var(--dark-text);
1798
+ --theme-surface-raised: var(--dark-surface-raised);
1799
+ --theme-border-strong: var(--dark-border-strong);
1800
+ --theme-muted: var(--dark-muted);
1801
+ --theme-accent: var(--dark-cool);
1802
+ --theme-link: var(--dark-blue);
1803
+ --theme-link-hover: var(--dark-blue-bright);
1804
+ --theme-primary: var(--dark-accent);
1805
+ --theme-primary-hover: var(--dark-accent-bright);
1806
+ --theme-data-action: var(--dark-green);
1807
+ --theme-data-action-hover: var(--dark-green-bright);
1808
+ --theme-utility: var(--dark-teal);
1809
+ --theme-metadata: var(--dark-yellow);
1810
+ --theme-warning: var(--dark-brown);
1811
+ --theme-overlay: rgb(2 6 13 / 78%);
1812
+ --theme-popup-shadow: 0 0.8rem 2rem rgb(0 0 0 / 55%);
1813
+ --theme-control-surface: var(--dark-surface);
1814
+ --theme-control-text: var(--dark-text);
1815
+ --theme-important: var(--dark-accent-bright);
1816
+ --diagram-canvas: #0d1011;
1817
+ --diagram-grid: #1b2023;
1818
+ --diagram-edge: #68747b;
1819
+ --diagram-node: var(--dark-surface-raised);
1820
+ --diagram-node-selected: #183239;
1821
+ }
1822
+
1823
+ [data-theme='dark'] body {
1824
+ color: var(--dark-text);
1825
+ background:
1826
+ radial-gradient(circle at 85% -10%, rgb(24 88 106 / 20%), transparent 30rem),
1827
+ var(--dark-canvas);
1828
+ }
1829
+
1830
+ [data-theme='dark'] a,
1831
+ [data-theme='dark'] .text-preview-toggle,
1832
+ [data-theme='dark'] .json-value-toggle {
1833
+ color: var(--theme-link);
1834
+ }
1835
+
1836
+ [data-theme='dark'] a:hover,
1837
+ [data-theme='dark'] .text-preview-toggle:hover,
1838
+ [data-theme='dark'] .json-value-toggle:hover {
1839
+ color: var(--theme-link-hover);
1840
+ }
1841
+
1842
+ [data-theme='dark'] body > header .brand {
1843
+ color: var(--dark-text);
1844
+ }
1845
+
1846
+ [data-theme='dark'] body > header .brand strong {
1847
+ color: var(--dark-cool-bright);
1848
+ }
1849
+
1850
+ [data-theme='dark'] body > header .brand span,
1851
+ [data-theme='dark'] body > header small,
1852
+ [data-theme='dark'] .eyebrow,
1853
+ [data-theme='dark'] .database-summary dt,
1854
+ [data-theme='dark'] .table-search-icon,
1855
+ [data-theme='dark'] .filter-label,
1856
+ [data-theme='dark'] .filter-remove,
1857
+ [data-theme='dark'] .page-jump-label,
1858
+ [data-theme='dark'] .empty-state {
1859
+ color: var(--dark-muted);
1860
+ }
1861
+
1862
+ [data-theme='dark'] .database-summary {
1863
+ background: rgb(23 25 27 / 97%);
1864
+ }
1865
+
1866
+ [data-theme='dark'] section {
1867
+ border-color: var(--dark-border);
1868
+ background: var(--dark-surface);
1869
+ box-shadow: 0 0.8rem 2rem rgb(0 0 0 / 18%);
1870
+ }
1871
+
1872
+ [data-theme='dark'] .table-page-heading {
1873
+ background: var(--dark-surface);
1874
+ box-shadow: 0 0.4rem 1rem rgb(0 0 0 / 24%);
1875
+ }
1876
+
1877
+ [data-theme='dark'] input,
1878
+ [data-theme='dark'] select,
1879
+ [data-theme='dark'] button,
1880
+ [data-theme='dark'] .text-preview-dialog,
1881
+ [data-theme='dark'] .json-value-dialog {
1882
+ color: var(--dark-text);
1883
+ border-color: var(--dark-border-strong);
1884
+ background: var(--dark-surface-raised);
1885
+ }
1886
+
1887
+ [data-theme='dark'] input::placeholder {
1888
+ color: var(--dark-muted);
1889
+ }
1890
+
1891
+ [data-theme='dark'] button {
1892
+ color: #1b1308;
1893
+ border-color: var(--theme-primary);
1894
+ background: var(--theme-primary);
1895
+ }
1896
+
1897
+ [data-theme='dark'] button:hover {
1898
+ border-color: var(--theme-primary-hover);
1899
+ background: var(--theme-primary-hover);
1900
+ }
1901
+
1902
+ [data-theme='dark'] .date-filter-trigger,
1903
+ [data-theme='dark'] .temporal-value-filter,
1904
+ [data-theme='dark'] .date-filter-trigger:hover,
1905
+ [data-theme='dark'] .temporal-value-filter:hover {
1906
+ border: 0;
1907
+ background: transparent;
1908
+ }
1909
+
1910
+ [data-theme='dark'] .date-filter-trigger {
1911
+ color: var(--dark-muted);
1912
+ }
1913
+
1914
+ [data-theme='dark'] .date-filter-trigger:hover {
1915
+ color: var(--dark-cool-bright);
1916
+ }
1917
+
1918
+ [data-theme='dark'] .temporal-value-filter {
1919
+ color: var(--theme-data-action);
1920
+ }
1921
+
1922
+ [data-theme='dark'] .temporal-value-filter:hover {
1923
+ color: var(--theme-data-action-hover);
1924
+ }
1925
+
1926
+ [data-theme='dark'] .popup-surface .dialog-close {
1927
+ color: var(--theme-control-text);
1928
+ border-color: var(--theme-border-strong);
1929
+ background: var(--theme-control-surface);
1930
+ }
1931
+
1932
+ [data-theme='dark'] .popup-surface .dialog-close:hover {
1933
+ color: var(--theme-accent);
1934
+ border-color: var(--theme-accent);
1935
+ background: var(--theme-control-surface);
1936
+ }
1937
+
1938
+ [data-theme='dark'] .group-link,
1939
+ [data-theme='dark'] .secondary-link {
1940
+ color: var(--theme-utility);
1941
+ }
1942
+
1943
+ [data-theme='dark'] .group-link:hover,
1944
+ [data-theme='dark'] .secondary-link:hover {
1945
+ color: var(--dark-cool-bright);
1946
+ }
1947
+
1948
+ [data-theme='dark'] .active-filters {
1949
+ border-color: var(--dark-border);
1950
+ border-left-color: var(--dark-state);
1951
+ background: #1c201d;
1952
+ }
1953
+
1954
+ [data-theme='dark'] .filter-chip {
1955
+ border-color: var(--dark-border-strong);
1956
+ background: var(--dark-surface-raised);
1957
+ }
1958
+
1959
+ [data-theme='dark'] .filter-chip strong,
1960
+ [data-theme='dark'] .relationship-link {
1961
+ color: var(--dark-state);
1962
+ }
1963
+
1964
+ [data-theme='dark'] .filter-chip strong:hover,
1965
+ [data-theme='dark'] .relationship-link:hover {
1966
+ color: var(--dark-green-bright);
1967
+ }
1968
+
1969
+ [data-theme='dark'] .notice {
1970
+ color: var(--theme-warning);
1971
+ }
1972
+
1973
+ [data-theme='dark'] .filter-chip small,
1974
+ [data-theme='dark'] .clear-all,
1975
+ [data-theme='dark'] .remove-filter,
1976
+ [data-theme='dark'] .column-picker p,
1977
+ [data-theme='dark'] .column-drag-handle,
1978
+ [data-theme='dark'] .deferred-copy-status,
1979
+ [data-theme='dark'] .deferred-value-summary {
1980
+ color: var(--dark-muted);
1981
+ }
1982
+
1983
+ [data-theme='dark'] .table-scroll {
1984
+ border-color: var(--dark-border);
1985
+ }
1986
+
1987
+ [data-theme='dark'] .data-table tbody tr:hover td {
1988
+ background: #24282a;
1989
+ }
1990
+
1991
+ [data-theme='dark'] .data-table th,
1992
+ [data-theme='dark'] .floating-table-header,
1993
+ [data-theme='dark'] .floating-table-header table,
1994
+ [data-theme='dark'] .floating-horizontal-scroll {
1995
+ background: var(--dark-surface-raised);
1996
+ }
1997
+
1998
+ [data-theme='dark'] .floating-table-header,
1999
+ [data-theme='dark'] .floating-horizontal-scroll {
2000
+ border-color: var(--dark-border);
2001
+ box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 35%);
2002
+ }
2003
+
2004
+ [data-theme='dark'] .floating-horizontal-scroll {
2005
+ scrollbar-color: #a6a6a6 var(--dark-surface-raised);
2006
+ }
2007
+
2008
+ [data-theme='dark'] .floating-horizontal-scroll::-webkit-scrollbar-track {
2009
+ background: var(--dark-surface-raised);
2010
+ }
2011
+
2012
+ [data-theme='dark'] .floating-horizontal-scroll::-webkit-scrollbar-thumb {
2013
+ border-color: var(--dark-surface-raised);
2014
+ background: #a6a6a6;
2015
+ }
2016
+
2017
+ [data-theme='dark'] .floating-horizontal-scroll::-webkit-scrollbar-thumb:hover {
2018
+ background: #c0c0c0;
2019
+ }
2020
+
2021
+ [data-theme='dark'] .data-table .horizontal-scroll-clearance td {
2022
+ background: var(--dark-surface-raised);
2023
+ }
2024
+
2025
+ [data-theme='dark'] .data-table .record-link-column,
2026
+ [data-theme='dark'] .floating-table-header .record-link-column {
2027
+ background: rgb(27 30 32 / 97%);
2028
+ }
2029
+
2030
+ [data-theme='dark'] .data-table tbody tr:hover .record-link-column {
2031
+ background: rgb(36 40 42 / 98%);
2032
+ }
2033
+
2034
+ [data-theme='dark'] .disabled,
2035
+ [data-theme='dark'] .null,
2036
+ [data-theme='dark'] .related-empty,
2037
+ [data-theme='dark'] .empty {
2038
+ color: var(--dark-muted);
2039
+ }
2040
+
2041
+ [data-theme='dark'] .binary {
2042
+ color: var(--dark-brown);
2043
+ }
2044
+
2045
+ [data-theme='dark'] .boolean {
2046
+ color: var(--dark-yellow);
2047
+ }
2048
+
2049
+ [data-theme='dark'] .number {
2050
+ color: var(--dark-blue-bright);
2051
+ }
2052
+
2053
+ [data-theme='dark'] .value-filter {
2054
+ color: var(--dark-text);
2055
+ text-decoration-color: var(--dark-teal);
2056
+ }
2057
+
2058
+ [data-theme='dark'] .value-filter:hover {
2059
+ color: var(--theme-data-action-hover);
2060
+ text-decoration-color: var(--theme-data-action);
2061
+ }
2062
+
2063
+ [data-theme='dark'] .record-fields dt,
2064
+ [data-theme='dark'] .schema-table tbody th {
2065
+ color: var(--theme-metadata);
2066
+ }
2067
+
2068
+ [data-theme='dark'] .schema-key {
2069
+ color: var(--dark-green);
2070
+ }
2071
+
2072
+ [data-theme='dark'] .record-fields,
2073
+ [data-theme='dark'] .record-fields > div,
2074
+ [data-theme='dark'] .related-records,
2075
+ [data-theme='dark'] th,
2076
+ [data-theme='dark'] td {
2077
+ border-color: var(--dark-border);
2078
+ }
2079
+
2080
+ [data-theme='dark'] .text-preview,
2081
+ [data-theme='dark'] .text-preview:hover {
2082
+ color: var(--dark-text);
2083
+ border: 0;
2084
+ background: transparent;
2085
+ }
2086
+
2087
+ [data-theme='dark'] .text-preview small,
2088
+ [data-theme='dark'] .json-preview,
2089
+ [data-theme='dark'] .deferred-value-view,
2090
+ [data-theme='dark'] .deferred-value-copy {
2091
+ color: var(--theme-utility);
2092
+ border: 0;
2093
+ background: transparent;
2094
+ }
2095
+
2096
+ [data-theme='dark'] .text-preview:hover small,
2097
+ [data-theme='dark'] .json-preview:hover,
2098
+ [data-theme='dark'] .deferred-value-view:hover,
2099
+ [data-theme='dark'] .deferred-value-copy:hover {
2100
+ color: var(--dark-cool-bright);
2101
+ border: 0;
2102
+ background: transparent;
2103
+ }
2104
+
2105
+ [data-theme='dark'] .column-picker-trigger,
2106
+ [data-theme='dark'] .date-picker-button,
2107
+ [data-theme='dark'] .secondary-button {
2108
+ color: var(--dark-cool-bright);
2109
+ border-color: var(--dark-border-strong);
2110
+ background: var(--dark-surface-raised);
2111
+ }
2112
+
2113
+ [data-theme='dark'] .column-picker-trigger:hover,
2114
+ [data-theme='dark'] .date-picker-button:hover,
2115
+ [data-theme='dark'] .secondary-button:hover {
2116
+ color: var(--dark-cool-bright);
2117
+ border-color: var(--dark-cool);
2118
+ background: #292d30;
2119
+ }
2120
+
2121
+ [data-theme='dark'] .column-picker li {
2122
+ background: var(--dark-surface);
2123
+ }
2124
+
2125
+ [data-theme='dark'] .column-picker li.dragging {
2126
+ border-color: var(--dark-cool);
2127
+ }
2128
+
2129
+ [data-theme='dark'] .column-move-actions button,
2130
+ [data-theme='dark'] .deferred-dialog-copy button {
2131
+ color: var(--dark-text);
2132
+ border-color: var(--dark-border-strong);
2133
+ background: var(--dark-surface);
2134
+ }
2135
+
2136
+ [data-theme='dark'] .column-move-actions button:hover,
2137
+ [data-theme='dark'] .deferred-dialog-copy button:hover {
2138
+ color: var(--dark-cool-bright);
2139
+ border-color: var(--dark-cool);
2140
+ background: #292d30;
2141
+ }