jsgui3-server 0.0.140 → 0.0.142

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 (32) hide show
  1. package/.github/agents/jsgui3-server.agent.md +699 -0
  2. package/.github/instructions/copilot.instructions.md +180 -0
  3. package/.playwright-mcp/page-2025-11-29T23-39-18-629Z.png +0 -0
  4. package/.playwright-mcp/page-2025-11-29T23-39-31-903Z.png +0 -0
  5. package/.playwright-mcp/page-2025-11-30T00-33-56-265Z.png +0 -0
  6. package/.playwright-mcp/page-2025-11-30T00-34-06-619Z.png +0 -0
  7. package/docs/agent-development-guide.md +108 -4
  8. package/docs/api-reference.md +116 -0
  9. package/docs/controls-development.md +127 -0
  10. package/docs/css/luxuryObsidianCss.js +1203 -0
  11. package/docs/css/obsidian-scrollbars.css +370 -0
  12. package/docs/diagrams/jsgui3-stack.svg +568 -0
  13. package/docs/guides/JSGUI3_UI_ARCHITECTURE_GUIDE.md +2527 -0
  14. package/docs/guides/OBSIDIAN_LUXURY_DESIGN_GUIDE.md +847 -0
  15. package/docs/jsgui3-vs-express-comparison.svg +542 -0
  16. package/docs/jsgui3-vs-nestjs-comparison.svg +550 -0
  17. package/docs/publishers-guide.md +76 -0
  18. package/docs/troubleshooting.md +51 -0
  19. package/examples/controls/15) window, observable SSE/README.md +125 -0
  20. package/examples/controls/15) window, observable SSE/check.js +144 -0
  21. package/examples/controls/15) window, observable SSE/client.js +395 -0
  22. package/examples/controls/15) window, observable SSE/server.js +111 -0
  23. package/http/responders/static/Static_Route_HTTP_Responder.js +16 -16
  24. package/module.js +7 -0
  25. package/package.json +9 -8
  26. package/port-utils.js +112 -0
  27. package/serve-factory.js +27 -5
  28. package/tests/README.md +40 -26
  29. package/tests/examples-controls.e2e.test.js +164 -0
  30. package/tests/observable-sse.test.js +363 -0
  31. package/tests/port-utils.test.js +114 -0
  32. package/tests/test-runner.js +13 -12
@@ -0,0 +1,1203 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Industrial Luxury Obsidian Theme CSS
5
+ *
6
+ * A premium dark theme inspired by the decision-tree-engine-deep-dive.svg.
7
+ * Features deep obsidian backgrounds, gold accents, and gemstone highlight colors.
8
+ *
9
+ * Design Philosophy:
10
+ * - Deep, layered obsidian backgrounds create depth
11
+ * - Gold accents provide luxury feel without overwhelming
12
+ * - Gemstone colors (emerald, ruby, sapphire) for semantic highlights
13
+ * - Subtle ambient glows and soft shadows add dimensionality
14
+ * - Premium typography with Georgia serif headings
15
+ */
16
+
17
+ // ═══════════════════════════════════════════════════════════════════════════════
18
+ // COLOR PALETTE
19
+ // ═══════════════════════════════════════════════════════════════════════════════
20
+
21
+ const COLORS = {
22
+ // Primary Background - Deep Obsidian
23
+ obsidian: {
24
+ darkest: "#050508",
25
+ dark: "#0a0d14",
26
+ base: "#0f1420",
27
+ card: "#141824",
28
+ cardHover: "#1a1f2e",
29
+ cardLight: "#252b3d"
30
+ },
31
+
32
+ // Gold Accent - Luxury
33
+ gold: {
34
+ bright: "#ffd700",
35
+ light: "#fffacd",
36
+ muted: "#d4af37",
37
+ primary: "#c9a227",
38
+ dark: "#b8960f",
39
+ darkest: "#a07d00",
40
+ dim: "#8b7500"
41
+ },
42
+
43
+ // Gemstone Colors - Accents
44
+ emerald: {
45
+ light: "#50c878",
46
+ base: "#2e8b57",
47
+ dark: "#1a5d38"
48
+ },
49
+ ruby: {
50
+ light: "#ff6b6b",
51
+ base: "#e31837",
52
+ dark: "#8b0000"
53
+ },
54
+ sapphire: {
55
+ light: "#6fa8dc",
56
+ base: "#0f52ba",
57
+ dark: "#082567"
58
+ },
59
+ amethyst: {
60
+ light: "#da70d6",
61
+ base: "#9966cc",
62
+ dark: "#4b0082"
63
+ },
64
+ topaz: {
65
+ light: "#ffc87c",
66
+ base: "#ff9f00",
67
+ dark: "#cc7000"
68
+ },
69
+
70
+ // Text Colors
71
+ text: {
72
+ primary: "#cbd5e1",
73
+ secondary: "#94a3b8",
74
+ muted: "#64748b",
75
+ dim: "#475569",
76
+ inverted: "#0f1420"
77
+ },
78
+
79
+ // Borders & Dividers
80
+ border: {
81
+ subtle: "#334155",
82
+ muted: "#475569",
83
+ accent: "#c9a227"
84
+ }
85
+ };
86
+
87
+ // ═══════════════════════════════════════════════════════════════════════════════
88
+ // TYPOGRAPHY
89
+ // ═══════════════════════════════════════════════════════════════════════════════
90
+
91
+ const FONTS = {
92
+ heading: '"Georgia", "Playfair Display", serif',
93
+ body: '"Inter", system-ui, -apple-system, sans-serif',
94
+ mono: '"JetBrains Mono", "Fira Code", "Consolas", monospace'
95
+ };
96
+
97
+ // ═══════════════════════════════════════════════════════════════════════════════
98
+ // CSS GENERATION
99
+ // ═══════════════════════════════════════════════════════════════════════════════
100
+
101
+ /**
102
+ * Generate the complete Luxury Obsidian CSS
103
+ */
104
+ function buildLuxuryObsidianCss() {
105
+ return `
106
+ /* ═══════════════════════════════════════════════════════════════════════════════
107
+ INDUSTRIAL LUXURY OBSIDIAN THEME
108
+ Premium dark theme with gold accents and gemstone highlights
109
+ ═══════════════════════════════════════════════════════════════════════════════ */
110
+
111
+ :root {
112
+ /* Obsidian Background Scale */
113
+ --lux-bg-darkest: ${COLORS.obsidian.darkest};
114
+ --lux-bg-dark: ${COLORS.obsidian.dark};
115
+ --lux-bg-base: ${COLORS.obsidian.base};
116
+ --lux-bg-card: ${COLORS.obsidian.card};
117
+ --lux-bg-card-hover: ${COLORS.obsidian.cardHover};
118
+ --lux-bg-card-light: ${COLORS.obsidian.cardLight};
119
+
120
+ /* Gold Accent Scale */
121
+ --lux-gold-bright: ${COLORS.gold.bright};
122
+ --lux-gold-light: ${COLORS.gold.light};
123
+ --lux-gold-muted: ${COLORS.gold.muted};
124
+ --lux-gold: ${COLORS.gold.primary};
125
+ --lux-gold-dark: ${COLORS.gold.dark};
126
+ --lux-gold-dim: ${COLORS.gold.dim};
127
+
128
+ /* Gemstone Accents */
129
+ --lux-emerald: ${COLORS.emerald.light};
130
+ --lux-emerald-base: ${COLORS.emerald.base};
131
+ --lux-ruby: ${COLORS.ruby.light};
132
+ --lux-ruby-base: ${COLORS.ruby.base};
133
+ --lux-sapphire: ${COLORS.sapphire.light};
134
+ --lux-sapphire-base: ${COLORS.sapphire.base};
135
+ --lux-amethyst: ${COLORS.amethyst.light};
136
+ --lux-topaz: ${COLORS.topaz.light};
137
+
138
+ /* Text Colors */
139
+ --lux-text: ${COLORS.text.primary};
140
+ --lux-text-secondary: ${COLORS.text.secondary};
141
+ --lux-text-muted: ${COLORS.text.muted};
142
+
143
+ /* Borders */
144
+ --lux-border: ${COLORS.border.subtle};
145
+ --lux-border-accent: ${COLORS.border.accent};
146
+
147
+ /* Typography */
148
+ --lux-font-heading: ${FONTS.heading};
149
+ --lux-font-body: ${FONTS.body};
150
+ --lux-font-mono: ${FONTS.mono};
151
+
152
+ /* Shadows & Glows */
153
+ --lux-shadow-soft: 0 4px 20px rgba(0, 0, 0, 0.5);
154
+ --lux-shadow-deep: 0 8px 32px rgba(0, 0, 0, 0.7);
155
+ --lux-glow-gold: 0 0 20px rgba(201, 162, 39, 0.3);
156
+ --lux-glow-gold-strong: 0 0 30px rgba(201, 162, 39, 0.5);
157
+
158
+ /* Transitions */
159
+ --lux-transition-fast: 150ms ease;
160
+ --lux-transition-medium: 250ms ease;
161
+ --lux-transition-slow: 400ms cubic-bezier(0.4, 0, 0.2, 1);
162
+
163
+ /* Spacing */
164
+ --lux-space-xs: 4px;
165
+ --lux-space-sm: 8px;
166
+ --lux-space-md: 16px;
167
+ --lux-space-lg: 24px;
168
+ --lux-space-xl: 32px;
169
+ --lux-space-2xl: 48px;
170
+
171
+ /* Border Radius */
172
+ --lux-radius-sm: 6px;
173
+ --lux-radius-md: 10px;
174
+ --lux-radius-lg: 16px;
175
+ }
176
+
177
+ /* ═══════════════════════════════════════════════════════════════════════════════
178
+ BASE STYLES
179
+ ═══════════════════════════════════════════════════════════════════════════════ */
180
+
181
+ *, *::before, *::after {
182
+ box-sizing: border-box;
183
+ }
184
+
185
+ html, body {
186
+ margin: 0;
187
+ padding: 0;
188
+ min-height: 100vh;
189
+ }
190
+
191
+ body.luxury-obsidian {
192
+ background:
193
+ /* Diagonal hatch pattern */
194
+ repeating-linear-gradient(
195
+ 45deg,
196
+ transparent,
197
+ transparent 8px,
198
+ rgba(201, 162, 39, 0.02) 8px,
199
+ rgba(201, 162, 39, 0.02) 9px
200
+ ),
201
+ /* Luxury grid pattern */
202
+ linear-gradient(to right, rgba(201, 162, 39, 0.03) 1px, transparent 1px),
203
+ linear-gradient(to bottom, rgba(201, 162, 39, 0.03) 1px, transparent 1px),
204
+ /* Base gradient */
205
+ linear-gradient(135deg, var(--lux-bg-darkest) 0%, var(--lux-bg-dark) 25%, var(--lux-bg-base) 50%, var(--lux-bg-dark) 75%, var(--lux-bg-darkest) 100%);
206
+ background-size: auto, 80px 80px, 80px 80px, 100% 100%;
207
+ background-attachment: fixed;
208
+ color: var(--lux-text);
209
+ font-family: var(--lux-font-body);
210
+ font-size: 14px;
211
+ line-height: 1.6;
212
+ -webkit-font-smoothing: antialiased;
213
+ -moz-osx-font-smoothing: grayscale;
214
+ }
215
+
216
+ /* ═══════════════════════════════════════════════════════════════════════════════
217
+ PAGE SHELL
218
+ ═══════════════════════════════════════════════════════════════════════════════ */
219
+
220
+ .lux-shell {
221
+ min-height: 100vh;
222
+ display: flex;
223
+ flex-direction: column;
224
+ }
225
+
226
+ .lux-shell__header {
227
+ position: sticky;
228
+ top: 0;
229
+ z-index: 100;
230
+ background: linear-gradient(180deg, var(--lux-bg-dark) 0%, rgba(10, 13, 20, 0.95) 100%);
231
+ backdrop-filter: blur(12px);
232
+ border-bottom: 1px solid var(--lux-border);
233
+ padding: var(--lux-space-md) var(--lux-space-xl);
234
+ }
235
+
236
+ .lux-shell__header::after {
237
+ content: "";
238
+ position: absolute;
239
+ bottom: 0;
240
+ left: 0;
241
+ right: 0;
242
+ height: 1px;
243
+ background: linear-gradient(90deg,
244
+ transparent 0%,
245
+ var(--lux-gold-dim) 20%,
246
+ var(--lux-gold) 50%,
247
+ var(--lux-gold-dim) 80%,
248
+ transparent 100%
249
+ );
250
+ opacity: 0.6;
251
+ }
252
+
253
+ .lux-shell__main {
254
+ flex: 1;
255
+ padding: var(--lux-space-xl);
256
+ max-width: 1600px;
257
+ margin: 0 auto;
258
+ width: 100%;
259
+ }
260
+
261
+ .lux-shell__footer {
262
+ padding: var(--lux-space-lg) var(--lux-space-xl);
263
+ border-top: 1px solid var(--lux-border);
264
+ text-align: center;
265
+ color: var(--lux-text-muted);
266
+ font-size: 12px;
267
+ }
268
+
269
+ /* ═══════════════════════════════════════════════════════════════════════════════
270
+ HERO SECTION
271
+ ═══════════════════════════════════════════════════════════════════════════════ */
272
+
273
+ .lux-hero {
274
+ text-align: center;
275
+ padding: var(--lux-space-2xl) var(--lux-space-xl);
276
+ position: relative;
277
+ margin-bottom: var(--lux-space-xl);
278
+ }
279
+
280
+ .lux-hero::before {
281
+ content: "";
282
+ position: absolute;
283
+ top: 50%;
284
+ left: 50%;
285
+ transform: translate(-50%, -50%);
286
+ width: 600px;
287
+ height: 200px;
288
+ background: radial-gradient(ellipse, rgba(201, 162, 39, 0.15) 0%, transparent 70%);
289
+ pointer-events: none;
290
+ }
291
+
292
+ .lux-hero__icon {
293
+ font-size: 48px;
294
+ margin-bottom: var(--lux-space-md);
295
+ display: block;
296
+ }
297
+
298
+ .lux-hero__title {
299
+ font-family: var(--lux-font-heading);
300
+ font-size: 42px;
301
+ font-weight: 700;
302
+ margin: 0 0 var(--lux-space-sm) 0;
303
+ background: linear-gradient(90deg,
304
+ var(--lux-gold-dim) 0%,
305
+ var(--lux-gold-bright) 30%,
306
+ var(--lux-gold-light) 50%,
307
+ var(--lux-gold-bright) 70%,
308
+ var(--lux-gold-dim) 100%
309
+ );
310
+ -webkit-background-clip: text;
311
+ -webkit-text-fill-color: transparent;
312
+ background-clip: text;
313
+ text-shadow: 0 0 40px rgba(201, 162, 39, 0.3);
314
+ letter-spacing: -0.02em;
315
+ position: relative;
316
+ }
317
+
318
+ .lux-hero__subtitle {
319
+ font-family: var(--lux-font-body);
320
+ font-size: 14px;
321
+ color: var(--lux-text-secondary);
322
+ letter-spacing: 3px;
323
+ text-transform: uppercase;
324
+ margin: 0;
325
+ }
326
+
327
+ /* ═══════════════════════════════════════════════════════════════════════════════
328
+ PANEL / CARD
329
+ ═══════════════════════════════════════════════════════════════════════════════ */
330
+
331
+ .lux-panel {
332
+ background: linear-gradient(180deg, var(--lux-bg-card-hover) 0%, var(--lux-bg-card) 50%, var(--lux-bg-base) 100%);
333
+ border-radius: var(--lux-radius-lg);
334
+ border: 2px solid var(--lux-border);
335
+ box-shadow: var(--lux-shadow-soft);
336
+ overflow: hidden;
337
+ position: relative;
338
+ }
339
+
340
+ .lux-panel::before {
341
+ content: "";
342
+ position: absolute;
343
+ inset: 0;
344
+ border-radius: var(--lux-radius-lg);
345
+ padding: 2px;
346
+ background: linear-gradient(180deg,
347
+ rgba(201, 162, 39, 0.4) 0%,
348
+ rgba(201, 162, 39, 0.1) 50%,
349
+ transparent 100%
350
+ );
351
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
352
+ mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
353
+ -webkit-mask-composite: xor;
354
+ mask-composite: exclude;
355
+ pointer-events: none;
356
+ }
357
+
358
+ .lux-panel--gold {
359
+ border-color: var(--lux-gold-dark);
360
+ }
361
+
362
+ .lux-panel--emerald {
363
+ border-color: var(--lux-emerald-base);
364
+ }
365
+
366
+ .lux-panel--sapphire {
367
+ border-color: var(--lux-sapphire-base);
368
+ }
369
+
370
+ .lux-panel__header {
371
+ padding: var(--lux-space-md) var(--lux-space-lg);
372
+ background: linear-gradient(90deg, var(--lux-bg-base) 0%, var(--lux-bg-card-hover) 50%, var(--lux-bg-base) 100%);
373
+ border-bottom: 1px solid var(--lux-border);
374
+ display: flex;
375
+ align-items: center;
376
+ justify-content: space-between;
377
+ }
378
+
379
+ .lux-panel__title {
380
+ font-family: var(--lux-font-heading);
381
+ font-size: 18px;
382
+ font-weight: 600;
383
+ color: var(--lux-gold);
384
+ margin: 0;
385
+ display: flex;
386
+ align-items: center;
387
+ gap: var(--lux-space-sm);
388
+ }
389
+
390
+ .lux-panel__title::before,
391
+ .lux-panel__title::after {
392
+ content: "◆";
393
+ font-size: 10px;
394
+ opacity: 0.6;
395
+ }
396
+
397
+ .lux-panel__meta {
398
+ font-size: 12px;
399
+ color: var(--lux-text-muted);
400
+ }
401
+
402
+ .lux-panel__body {
403
+ padding: var(--lux-space-lg);
404
+ }
405
+
406
+ .lux-panel__footer {
407
+ padding: var(--lux-space-md) var(--lux-space-lg);
408
+ background: var(--lux-bg-dark);
409
+ border-top: 1px solid var(--lux-border);
410
+ }
411
+
412
+ /* ═══════════════════════════════════════════════════════════════════════════════
413
+ TABLE
414
+ ═══════════════════════════════════════════════════════════════════════════════ */
415
+
416
+ .lux-table {
417
+ width: 100%;
418
+ border-collapse: separate;
419
+ border-spacing: 0;
420
+ font-size: 13px;
421
+ }
422
+
423
+ .lux-table thead {
424
+ position: sticky;
425
+ top: 0;
426
+ z-index: 10;
427
+ }
428
+
429
+ .lux-table th {
430
+ background: var(--lux-bg-dark);
431
+ color: var(--lux-gold);
432
+ font-family: var(--lux-font-body);
433
+ font-weight: 600;
434
+ font-size: 11px;
435
+ text-transform: uppercase;
436
+ letter-spacing: 1px;
437
+ padding: var(--lux-space-sm) var(--lux-space-md);
438
+ text-align: left;
439
+ border-bottom: 2px solid var(--lux-gold-dim);
440
+ }
441
+
442
+ .lux-table th:first-child {
443
+ border-top-left-radius: var(--lux-radius-sm);
444
+ }
445
+
446
+ .lux-table th:last-child {
447
+ border-top-right-radius: var(--lux-radius-sm);
448
+ }
449
+
450
+ .lux-table td {
451
+ padding: var(--lux-space-sm) var(--lux-space-md);
452
+ border-bottom: 1px solid var(--lux-border);
453
+ vertical-align: middle;
454
+ transition: background var(--lux-transition-fast);
455
+ }
456
+
457
+ .lux-table tbody tr {
458
+ background: transparent;
459
+ transition: background var(--lux-transition-fast);
460
+ }
461
+
462
+ .lux-table tbody tr:hover {
463
+ background: rgba(201, 162, 39, 0.05);
464
+ }
465
+
466
+ .lux-table tbody tr:hover td {
467
+ border-bottom-color: var(--lux-gold-dim);
468
+ }
469
+
470
+ /* Row index column */
471
+ .lux-table td.is-index {
472
+ color: var(--lux-text-muted);
473
+ font-family: var(--lux-font-mono);
474
+ font-size: 11px;
475
+ width: 50px;
476
+ text-align: right;
477
+ padding-right: var(--lux-space-lg);
478
+ }
479
+
480
+ /* URL column */
481
+ .lux-table td.is-url {
482
+ font-family: var(--lux-font-mono);
483
+ font-size: 12px;
484
+ max-width: 500px;
485
+ overflow: hidden;
486
+ text-overflow: ellipsis;
487
+ white-space: nowrap;
488
+ }
489
+
490
+ /* Status badges */
491
+ .lux-table td.is-status {
492
+ text-align: center;
493
+ }
494
+
495
+ /* Links in table */
496
+ .lux-table a {
497
+ color: var(--lux-sapphire);
498
+ text-decoration: none;
499
+ transition: color var(--lux-transition-fast);
500
+ }
501
+
502
+ .lux-table a:hover {
503
+ color: var(--lux-sapphire-light);
504
+ text-decoration: underline;
505
+ }
506
+
507
+ /* Numeric columns */
508
+ .lux-table td.is-numeric {
509
+ font-family: var(--lux-font-mono);
510
+ text-align: right;
511
+ color: var(--lux-text-secondary);
512
+ }
513
+
514
+ /* ═══════════════════════════════════════════════════════════════════════════════
515
+ PAGINATION
516
+ ═══════════════════════════════════════════════════════════════════════════════ */
517
+
518
+ .lux-pager {
519
+ display: flex;
520
+ align-items: center;
521
+ justify-content: space-between;
522
+ padding: var(--lux-space-md) 0;
523
+ gap: var(--lux-space-lg);
524
+ }
525
+
526
+ .lux-pager__info {
527
+ font-size: 13px;
528
+ color: var(--lux-text-secondary);
529
+ }
530
+
531
+ .lux-pager__info strong {
532
+ color: var(--lux-gold);
533
+ font-weight: 600;
534
+ }
535
+
536
+ .lux-pager__controls {
537
+ display: flex;
538
+ gap: var(--lux-space-xs);
539
+ }
540
+
541
+ .lux-pager__btn {
542
+ display: inline-flex;
543
+ align-items: center;
544
+ justify-content: center;
545
+ min-width: 40px;
546
+ height: 36px;
547
+ padding: 0 var(--lux-space-md);
548
+ font-family: var(--lux-font-body);
549
+ font-size: 13px;
550
+ font-weight: 500;
551
+ color: var(--lux-text);
552
+ background: var(--lux-bg-card);
553
+ border: 1px solid var(--lux-border);
554
+ border-radius: var(--lux-radius-sm);
555
+ cursor: pointer;
556
+ transition: all var(--lux-transition-fast);
557
+ }
558
+
559
+ .lux-pager__btn:hover:not(:disabled) {
560
+ background: var(--lux-bg-card-hover);
561
+ border-color: var(--lux-gold-dim);
562
+ color: var(--lux-gold);
563
+ }
564
+
565
+ .lux-pager__btn:disabled {
566
+ opacity: 0.4;
567
+ cursor: not-allowed;
568
+ }
569
+
570
+ .lux-pager__btn--active {
571
+ background: linear-gradient(180deg, var(--lux-gold) 0%, var(--lux-gold-dark) 100%);
572
+ border-color: var(--lux-gold);
573
+ color: var(--lux-bg-darkest);
574
+ font-weight: 600;
575
+ box-shadow: var(--lux-glow-gold);
576
+ }
577
+
578
+ .lux-pager__btn--active:hover {
579
+ background: linear-gradient(180deg, var(--lux-gold-bright) 0%, var(--lux-gold) 100%);
580
+ color: var(--lux-bg-darkest);
581
+ }
582
+
583
+ /* ═══════════════════════════════════════════════════════════════════════════════
584
+ STATUS INDICATORS
585
+ ═══════════════════════════════════════════════════════════════════════════════ */
586
+
587
+ .lux-status {
588
+ display: inline-flex;
589
+ align-items: center;
590
+ gap: var(--lux-space-xs);
591
+ padding: 2px var(--lux-space-sm);
592
+ font-size: 11px;
593
+ font-weight: 500;
594
+ border-radius: 999px;
595
+ text-transform: uppercase;
596
+ letter-spacing: 0.5px;
597
+ }
598
+
599
+ .lux-status--success {
600
+ background: rgba(80, 200, 120, 0.15);
601
+ color: var(--lux-emerald);
602
+ border: 1px solid var(--lux-emerald-base);
603
+ }
604
+
605
+ .lux-status--warning {
606
+ background: rgba(255, 200, 124, 0.15);
607
+ color: var(--lux-topaz);
608
+ border: 1px solid var(--lux-topaz-dark);
609
+ }
610
+
611
+ .lux-status--error {
612
+ background: rgba(255, 107, 107, 0.15);
613
+ color: var(--lux-ruby);
614
+ border: 1px solid var(--lux-ruby-base);
615
+ }
616
+
617
+ .lux-status--info {
618
+ background: rgba(111, 168, 220, 0.15);
619
+ color: var(--lux-sapphire);
620
+ border: 1px solid var(--lux-sapphire-base);
621
+ }
622
+
623
+ .lux-status__dot {
624
+ width: 6px;
625
+ height: 6px;
626
+ border-radius: 50%;
627
+ background: currentColor;
628
+ }
629
+
630
+ /* ═══════════════════════════════════════════════════════════════════════════════
631
+ BUTTONS
632
+ ═══════════════════════════════════════════════════════════════════════════════ */
633
+
634
+ .lux-btn {
635
+ display: inline-flex;
636
+ align-items: center;
637
+ justify-content: center;
638
+ gap: var(--lux-space-sm);
639
+ padding: var(--lux-space-sm) var(--lux-space-lg);
640
+ font-family: var(--lux-font-body);
641
+ font-size: 13px;
642
+ font-weight: 500;
643
+ color: var(--lux-text);
644
+ background: var(--lux-bg-card);
645
+ border: 1px solid var(--lux-border);
646
+ border-radius: var(--lux-radius-sm);
647
+ cursor: pointer;
648
+ transition: all var(--lux-transition-fast);
649
+ text-decoration: none;
650
+ }
651
+
652
+ .lux-btn:hover {
653
+ background: var(--lux-bg-card-hover);
654
+ border-color: var(--lux-gold-dim);
655
+ }
656
+
657
+ .lux-btn--gold {
658
+ background: linear-gradient(180deg, var(--lux-gold) 0%, var(--lux-gold-dark) 100%);
659
+ border-color: var(--lux-gold);
660
+ color: var(--lux-bg-darkest);
661
+ font-weight: 600;
662
+ }
663
+
664
+ .lux-btn--gold:hover {
665
+ background: linear-gradient(180deg, var(--lux-gold-bright) 0%, var(--lux-gold) 100%);
666
+ box-shadow: var(--lux-glow-gold);
667
+ }
668
+
669
+ .lux-btn--outline-gold {
670
+ background: transparent;
671
+ border-color: var(--lux-gold);
672
+ color: var(--lux-gold);
673
+ }
674
+
675
+ .lux-btn--outline-gold:hover {
676
+ background: rgba(201, 162, 39, 0.1);
677
+ }
678
+
679
+ /* ═══════════════════════════════════════════════════════════════════════════════
680
+ NAV LINKS
681
+ ═══════════════════════════════════════════════════════════════════════════════ */
682
+
683
+ .lux-nav {
684
+ display: flex;
685
+ align-items: center;
686
+ gap: var(--lux-space-xs);
687
+ }
688
+
689
+ .lux-nav__link {
690
+ display: inline-flex;
691
+ align-items: center;
692
+ gap: var(--lux-space-xs);
693
+ padding: var(--lux-space-xs) var(--lux-space-md);
694
+ font-size: 13px;
695
+ color: var(--lux-text-secondary);
696
+ text-decoration: none;
697
+ border-radius: var(--lux-radius-sm);
698
+ transition: all var(--lux-transition-fast);
699
+ }
700
+
701
+ .lux-nav__link:hover {
702
+ color: var(--lux-gold);
703
+ background: rgba(201, 162, 39, 0.1);
704
+ }
705
+
706
+ .lux-nav__link--active {
707
+ color: var(--lux-gold);
708
+ background: rgba(201, 162, 39, 0.15);
709
+ font-weight: 500;
710
+ }
711
+
712
+ .lux-nav__divider {
713
+ width: 1px;
714
+ height: 20px;
715
+ background: var(--lux-border);
716
+ margin: 0 var(--lux-space-sm);
717
+ }
718
+
719
+ /* ═══════════════════════════════════════════════════════════════════════════════
720
+ STAT CARDS (for metrics display)
721
+ ═══════════════════════════════════════════════════════════════════════════════ */
722
+
723
+ .lux-stats {
724
+ display: grid;
725
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
726
+ gap: var(--lux-space-md);
727
+ margin-bottom: var(--lux-space-xl);
728
+ }
729
+
730
+ .lux-stat {
731
+ background: var(--lux-bg-card);
732
+ border: 1px solid var(--lux-border);
733
+ border-radius: var(--lux-radius-md);
734
+ padding: var(--lux-space-lg);
735
+ text-align: center;
736
+ position: relative;
737
+ overflow: hidden;
738
+ }
739
+
740
+ .lux-stat::before {
741
+ content: "";
742
+ position: absolute;
743
+ top: 0;
744
+ left: 0;
745
+ right: 0;
746
+ height: 3px;
747
+ background: var(--lux-gold);
748
+ opacity: 0.6;
749
+ }
750
+
751
+ .lux-stat__value {
752
+ font-family: var(--lux-font-heading);
753
+ font-size: 32px;
754
+ font-weight: 700;
755
+ color: var(--lux-gold);
756
+ margin-bottom: var(--lux-space-xs);
757
+ }
758
+
759
+ .lux-stat__label {
760
+ font-size: 12px;
761
+ color: var(--lux-text-muted);
762
+ text-transform: uppercase;
763
+ letter-spacing: 1px;
764
+ }
765
+
766
+ .lux-stat--emerald::before {
767
+ background: var(--lux-emerald);
768
+ }
769
+ .lux-stat--emerald .lux-stat__value {
770
+ color: var(--lux-emerald);
771
+ }
772
+
773
+ .lux-stat--sapphire::before {
774
+ background: var(--lux-sapphire);
775
+ }
776
+ .lux-stat--sapphire .lux-stat__value {
777
+ color: var(--lux-sapphire);
778
+ }
779
+
780
+ .lux-stat--amethyst::before {
781
+ background: var(--lux-amethyst);
782
+ }
783
+ .lux-stat--amethyst .lux-stat__value {
784
+ color: var(--lux-amethyst);
785
+ }
786
+
787
+ /* ═══════════════════════════════════════════════════════════════════════════════
788
+ LOADING STATES
789
+ ═══════════════════════════════════════════════════════════════════════════════ */
790
+
791
+ .lux-loading {
792
+ display: flex;
793
+ align-items: center;
794
+ justify-content: center;
795
+ padding: var(--lux-space-2xl);
796
+ color: var(--lux-text-muted);
797
+ }
798
+
799
+ .lux-loading__spinner {
800
+ width: 24px;
801
+ height: 24px;
802
+ border: 2px solid var(--lux-border);
803
+ border-top-color: var(--lux-gold);
804
+ border-radius: 50%;
805
+ animation: lux-spin 0.8s linear infinite;
806
+ margin-right: var(--lux-space-sm);
807
+ }
808
+
809
+ @keyframes lux-spin {
810
+ to { transform: rotate(360deg); }
811
+ }
812
+
813
+ /* ═══════════════════════════════════════════════════════════════════════════════
814
+ EMPTY STATE
815
+ ═══════════════════════════════════════════════════════════════════════════════ */
816
+
817
+ .lux-empty {
818
+ text-align: center;
819
+ padding: var(--lux-space-2xl);
820
+ color: var(--lux-text-muted);
821
+ }
822
+
823
+ .lux-empty__icon {
824
+ font-size: 48px;
825
+ margin-bottom: var(--lux-space-md);
826
+ opacity: 0.5;
827
+ }
828
+
829
+ .lux-empty__title {
830
+ font-family: var(--lux-font-heading);
831
+ font-size: 18px;
832
+ color: var(--lux-text-secondary);
833
+ margin-bottom: var(--lux-space-sm);
834
+ }
835
+
836
+ .lux-empty__message {
837
+ font-size: 13px;
838
+ }
839
+
840
+ /* ═══════════════════════════════════════════════════════════════════════════════
841
+ FACTS POPUP
842
+ ═══════════════════════════════════════════════════════════════════════════════ */
843
+
844
+ /* Body state when popup is open */
845
+ body.lux-popup-open {
846
+ overflow: hidden;
847
+ }
848
+
849
+ /* Popup container */
850
+ .lux-facts-popup {
851
+ position: fixed;
852
+ top: 0;
853
+ left: 0;
854
+ right: 0;
855
+ bottom: 0;
856
+ z-index: 1000;
857
+ display: none;
858
+ align-items: center;
859
+ justify-content: center;
860
+ }
861
+
862
+ /* Backdrop */
863
+ .lux-facts-popup__backdrop {
864
+ position: absolute;
865
+ top: 0;
866
+ left: 0;
867
+ right: 0;
868
+ bottom: 0;
869
+ background: rgba(5, 5, 8, 0.85);
870
+ backdrop-filter: blur(4px);
871
+ }
872
+
873
+ /* Modal */
874
+ .lux-facts-popup__modal {
875
+ position: relative;
876
+ background: var(--lux-bg-card);
877
+ border: 1px solid var(--lux-gold-dim);
878
+ border-radius: 12px;
879
+ max-width: 700px;
880
+ width: 90%;
881
+ max-height: 80vh;
882
+ overflow: hidden;
883
+ display: flex;
884
+ flex-direction: column;
885
+ box-shadow:
886
+ 0 0 60px rgba(201, 162, 39, 0.15),
887
+ 0 25px 50px rgba(0, 0, 0, 0.5);
888
+ animation: lux-popup-appear 0.2s ease-out;
889
+ }
890
+
891
+ @keyframes lux-popup-appear {
892
+ from {
893
+ opacity: 0;
894
+ transform: scale(0.95) translateY(-10px);
895
+ }
896
+ to {
897
+ opacity: 1;
898
+ transform: scale(1) translateY(0);
899
+ }
900
+ }
901
+
902
+ /* Header */
903
+ .lux-facts-popup__header {
904
+ display: flex;
905
+ align-items: center;
906
+ justify-content: space-between;
907
+ padding: var(--lux-space-md) var(--lux-space-lg);
908
+ border-bottom: 1px solid var(--lux-border);
909
+ background: linear-gradient(135deg, var(--lux-bg-card-hover) 0%, var(--lux-bg-card) 100%);
910
+ }
911
+
912
+ .lux-facts-popup__title {
913
+ margin: 0;
914
+ font-family: var(--lux-font-heading);
915
+ font-size: 18px;
916
+ font-weight: 600;
917
+ color: var(--lux-gold-light);
918
+ }
919
+
920
+ .lux-facts-popup__close {
921
+ background: transparent;
922
+ border: 1px solid var(--lux-border);
923
+ border-radius: 6px;
924
+ width: 32px;
925
+ height: 32px;
926
+ display: flex;
927
+ align-items: center;
928
+ justify-content: center;
929
+ color: var(--lux-text-muted);
930
+ font-size: 14px;
931
+ cursor: pointer;
932
+ transition: all 0.15s ease;
933
+ }
934
+
935
+ .lux-facts-popup__close:hover {
936
+ border-color: var(--lux-gold);
937
+ color: var(--lux-gold);
938
+ background: rgba(201, 162, 39, 0.1);
939
+ }
940
+
941
+ /* URL display */
942
+ .lux-facts-popup__url {
943
+ padding: var(--lux-space-md) var(--lux-space-lg);
944
+ background: var(--lux-bg-dark);
945
+ border-bottom: 1px solid var(--lux-border);
946
+ }
947
+
948
+ .lux-facts-popup__url-text {
949
+ font-family: var(--lux-font-mono);
950
+ font-size: 12px;
951
+ color: var(--lux-gold);
952
+ word-break: break-all;
953
+ line-height: 1.6;
954
+ }
955
+
956
+ /* Facts list */
957
+ .lux-facts-popup__facts {
958
+ flex: 1;
959
+ overflow-y: auto;
960
+ padding: var(--lux-space-md);
961
+ }
962
+
963
+ /* Fact item */
964
+ .lux-fact-item {
965
+ display: flex;
966
+ align-items: flex-start;
967
+ gap: var(--lux-space-md);
968
+ padding: var(--lux-space-md);
969
+ margin-bottom: var(--lux-space-sm);
970
+ border-radius: 8px;
971
+ background: var(--lux-bg-card-hover);
972
+ border: 1px solid var(--lux-border);
973
+ transition: all 0.15s ease;
974
+ }
975
+
976
+ .lux-fact-item:last-child {
977
+ margin-bottom: 0;
978
+ }
979
+
980
+ .lux-fact-item:hover {
981
+ border-color: var(--lux-gold-dim);
982
+ }
983
+
984
+ /* True facts - emerald accent */
985
+ .lux-fact-item--true {
986
+ border-left: 3px solid var(--lux-emerald);
987
+ }
988
+
989
+ .lux-fact-item--true .lux-fact-item__indicator {
990
+ color: var(--lux-emerald);
991
+ }
992
+
993
+ .lux-fact-item--true .lux-fact-item__badge {
994
+ background: var(--lux-emerald-dark);
995
+ color: var(--lux-emerald-light);
996
+ }
997
+
998
+ /* False facts - muted appearance */
999
+ .lux-fact-item--false {
1000
+ border-left: 3px solid var(--lux-border);
1001
+ opacity: 0.7;
1002
+ }
1003
+
1004
+ .lux-fact-item--false .lux-fact-item__indicator {
1005
+ color: var(--lux-text-dim);
1006
+ }
1007
+
1008
+ .lux-fact-item--false .lux-fact-item__badge {
1009
+ background: var(--lux-bg-dark);
1010
+ color: var(--lux-text-dim);
1011
+ }
1012
+
1013
+ /* Error facts - ruby accent */
1014
+ .lux-fact-item--error {
1015
+ border-left: 3px solid var(--lux-ruby);
1016
+ }
1017
+
1018
+ .lux-fact-item--error .lux-fact-item__indicator {
1019
+ color: var(--lux-ruby);
1020
+ }
1021
+
1022
+ /* Indicator */
1023
+ .lux-fact-item__indicator {
1024
+ font-size: 16px;
1025
+ flex-shrink: 0;
1026
+ width: 20px;
1027
+ text-align: center;
1028
+ }
1029
+
1030
+ /* Content */
1031
+ .lux-fact-item__content {
1032
+ flex: 1;
1033
+ min-width: 0;
1034
+ }
1035
+
1036
+ .lux-fact-item__name {
1037
+ font-family: var(--lux-font-mono);
1038
+ font-size: 13px;
1039
+ color: var(--lux-text-primary);
1040
+ margin-bottom: 4px;
1041
+ }
1042
+
1043
+ .lux-fact-item__evidence {
1044
+ font-size: 12px;
1045
+ color: var(--lux-text-muted);
1046
+ word-break: break-word;
1047
+ }
1048
+
1049
+ .lux-fact-item__evidence--error {
1050
+ color: var(--lux-ruby-light);
1051
+ }
1052
+
1053
+ /* Badge */
1054
+ .lux-fact-item__badge {
1055
+ font-family: var(--lux-font-mono);
1056
+ font-size: 10px;
1057
+ font-weight: 600;
1058
+ padding: 3px 8px;
1059
+ border-radius: 4px;
1060
+ flex-shrink: 0;
1061
+ text-transform: uppercase;
1062
+ letter-spacing: 0.5px;
1063
+ }
1064
+
1065
+ /* Footer */
1066
+ .lux-facts-popup__footer {
1067
+ padding: var(--lux-space-sm) var(--lux-space-lg);
1068
+ border-top: 1px solid var(--lux-border);
1069
+ background: var(--lux-bg-dark);
1070
+ font-size: 11px;
1071
+ color: var(--lux-text-dim);
1072
+ text-align: center;
1073
+ font-style: italic;
1074
+ }
1075
+
1076
+ /* Clickable URL rows */
1077
+ .lux-url-list .is-url a {
1078
+ cursor: pointer;
1079
+ }
1080
+
1081
+ .lux-url-list .is-url a:hover {
1082
+ text-decoration: underline;
1083
+ text-decoration-color: var(--lux-gold);
1084
+ }
1085
+
1086
+ /* ═══════════════════════════════════════════════════════════════════════════════
1087
+ DECORATIVE ELEMENTS
1088
+ ═══════════════════════════════════════════════════════════════════════════════ */
1089
+
1090
+ /* Gold corner flourishes */
1091
+ .lux-flourish {
1092
+ position: fixed;
1093
+ width: 100px;
1094
+ height: 100px;
1095
+ pointer-events: none;
1096
+ opacity: 0.25;
1097
+ }
1098
+
1099
+ .lux-flourish--tl {
1100
+ top: 0;
1101
+ left: 0;
1102
+ background: radial-gradient(ellipse at 0% 0%, var(--lux-gold-dim) 0%, transparent 70%);
1103
+ }
1104
+
1105
+ .lux-flourish--tr {
1106
+ top: 0;
1107
+ right: 0;
1108
+ background: radial-gradient(ellipse at 100% 0%, var(--lux-gold-dim) 0%, transparent 70%);
1109
+ }
1110
+
1111
+ .lux-flourish--bl {
1112
+ bottom: 0;
1113
+ left: 0;
1114
+ background: radial-gradient(ellipse at 0% 100%, var(--lux-gold-dim) 0%, transparent 70%);
1115
+ }
1116
+
1117
+ .lux-flourish--br {
1118
+ bottom: 0;
1119
+ right: 0;
1120
+ background: radial-gradient(ellipse at 100% 100%, var(--lux-gold-dim) 0%, transparent 70%);
1121
+ }
1122
+
1123
+ /* Decorative separator */
1124
+ .lux-divider {
1125
+ display: flex;
1126
+ align-items: center;
1127
+ justify-content: center;
1128
+ margin: var(--lux-space-xl) 0;
1129
+ }
1130
+
1131
+ .lux-divider::before,
1132
+ .lux-divider::after {
1133
+ content: "";
1134
+ flex: 1;
1135
+ height: 1px;
1136
+ background: linear-gradient(90deg, transparent, var(--lux-border), transparent);
1137
+ }
1138
+
1139
+ .lux-divider__gem {
1140
+ padding: 0 var(--lux-space-md);
1141
+ color: var(--lux-gold);
1142
+ font-size: 12px;
1143
+ }
1144
+
1145
+ /* ═══════════════════════════════════════════════════════════════════════════════
1146
+ RESPONSIVE
1147
+ ═══════════════════════════════════════════════════════════════════════════════ */
1148
+
1149
+ @media (max-width: 768px) {
1150
+ .lux-shell__main {
1151
+ padding: var(--lux-space-md);
1152
+ }
1153
+
1154
+ .lux-hero__title {
1155
+ font-size: 28px;
1156
+ }
1157
+
1158
+ .lux-stats {
1159
+ grid-template-columns: 1fr 1fr;
1160
+ }
1161
+
1162
+ .lux-pager {
1163
+ flex-direction: column;
1164
+ gap: var(--lux-space-md);
1165
+ }
1166
+ }
1167
+
1168
+ /* ═══════════════════════════════════════════════════════════════════════════════
1169
+ SCROLLBAR
1170
+ ═══════════════════════════════════════════════════════════════════════════════ */
1171
+
1172
+ .luxury-obsidian ::-webkit-scrollbar {
1173
+ width: 10px;
1174
+ height: 10px;
1175
+ }
1176
+
1177
+ .luxury-obsidian ::-webkit-scrollbar-track {
1178
+ background: var(--lux-bg-dark);
1179
+ }
1180
+
1181
+ .luxury-obsidian ::-webkit-scrollbar-thumb {
1182
+ background: var(--lux-bg-card-light);
1183
+ border-radius: 5px;
1184
+ border: 2px solid var(--lux-bg-dark);
1185
+ }
1186
+
1187
+ .luxury-obsidian ::-webkit-scrollbar-thumb:hover {
1188
+ background: var(--lux-gold-dim);
1189
+ }
1190
+
1191
+ /* Firefox */
1192
+ .luxury-obsidian {
1193
+ scrollbar-width: thin;
1194
+ scrollbar-color: var(--lux-bg-card-light) var(--lux-bg-dark);
1195
+ }
1196
+ `;
1197
+ }
1198
+
1199
+ module.exports = {
1200
+ buildLuxuryObsidianCss,
1201
+ COLORS,
1202
+ FONTS
1203
+ };