anentrypoint-design 0.0.166 → 0.0.168
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.
- package/README.md +1 -1
- package/app-shell.css +7 -7
- package/chat.css +13 -13
- package/colors_and_type.css +69 -0
- package/community.css +3 -3
- package/dist/247420.css +192 -63
- package/dist/247420.js +68 -36
- package/package.json +9 -3
- package/src/community-app.js +1 -1
- package/src/components/chat.js +1 -1
- package/src/components/content.js +2 -2
- package/src/components/freddie.js +3 -3
- package/src/components/shell.js +2 -2
- package/src/index.js +5 -1
- package/src/kits/os/freddie/pages-core.js +3 -3
- package/src/kits/os/freddie/pages-os.js +1 -1
- package/src/kits/os/freddie/pages-tools.js +1 -1
- package/src/kits/os/freddie/routes.js +1 -1
- package/src/kits/os/freddie-dashboard.css +7 -7
- package/src/kits/os/theme.css +129 -135
- package/src/kits/spoint/index.js +8 -0
- package/src/kits/spoint/loading-screen.css +67 -0
- package/src/kits/spoint/loading-screen.js +75 -0
- package/src/markdown-cache-perf-test.js +2 -2
- package/src/page-html.js +44 -12
- package/src/theme.js +62 -9
- package/src/web-components/ds-chat.js +1 -1
package/src/kits/os/theme.css
CHANGED
|
@@ -1,31 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* Fonts are declared once in the canonical theme (colors_and_type.css /
|
|
2
|
+
vendor/fonts.css), which every .ds-247420 consumer loads first. No @import
|
|
3
|
+
here — a second Inter-only import risked a weight-set FOUT mismatch. */
|
|
4
|
+
|
|
5
|
+
/* The OS shell namespaces its surfaces as --os-* but those are pure ALIASES of
|
|
6
|
+
the canonical semantic tokens from colors_and_type.css. colors_and_type.css
|
|
7
|
+
is always loaded before this sheet for any .ds-247420 consumer, so the
|
|
8
|
+
canonical tokens are guaranteed present and the alias fallbacks are dropped —
|
|
9
|
+
a fallback here would silently re-introduce theme drift (a baked light value
|
|
10
|
+
that ignores [data-theme="ink"]). One theme drives both token namespaces. */
|
|
3
11
|
:root {
|
|
4
|
-
--ff-ui
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
--
|
|
8
|
-
--os-accent
|
|
9
|
-
--os-accent-
|
|
10
|
-
--os-
|
|
11
|
-
--os-bg-
|
|
12
|
-
--os-bg-
|
|
13
|
-
--os-bg-
|
|
14
|
-
--os-
|
|
15
|
-
--os-fg
|
|
16
|
-
--os-fg-
|
|
17
|
-
--os-
|
|
18
|
-
--os-
|
|
19
|
-
--os-
|
|
20
|
-
--os-
|
|
21
|
-
--os-radius
|
|
12
|
+
/* --ff-ui is the OS-shell alias for the canonical body font; --ff-display
|
|
13
|
+
and --ff-mono are already canonical (colors_and_type.css), referenced
|
|
14
|
+
directly below — do not self-redefine them here (cycle). */
|
|
15
|
+
--ff-ui: var(--ff-body);
|
|
16
|
+
--os-accent: var(--accent);
|
|
17
|
+
--os-accent-2: var(--accent-bright, var(--accent));
|
|
18
|
+
--os-accent-soft: var(--accent-tint);
|
|
19
|
+
--os-bg-0: var(--bg);
|
|
20
|
+
--os-bg-1: var(--bg-2);
|
|
21
|
+
--os-bg-2: var(--bg-3);
|
|
22
|
+
--os-bg-3: var(--panel-3);
|
|
23
|
+
--os-fg: var(--fg);
|
|
24
|
+
--os-fg-2: var(--fg-2);
|
|
25
|
+
--os-fg-3: var(--fg-3);
|
|
26
|
+
--os-red: var(--warn);
|
|
27
|
+
--os-amber: var(--sun);
|
|
28
|
+
--os-green: var(--green);
|
|
29
|
+
--os-radius: var(--r-2);
|
|
30
|
+
--os-radius-sm: var(--r-1);
|
|
22
31
|
--os-bar-h: 44px;
|
|
23
32
|
--os-bar-h-mobile: 52px;
|
|
24
33
|
--os-rail-w: 64px;
|
|
25
34
|
--os-tap: 44px;
|
|
26
|
-
--os-font: var(--ff-ui
|
|
27
|
-
--os-display: var(--ff-display
|
|
28
|
-
--os-mono: var(--ff-mono
|
|
35
|
+
--os-font: var(--ff-ui);
|
|
36
|
+
--os-display: var(--ff-display);
|
|
37
|
+
--os-mono: var(--ff-mono);
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
html, body {
|
|
@@ -348,10 +357,10 @@ html, body {
|
|
|
348
357
|
.app-pane.mono pre { background: var(--os-bg-2); padding: 10px 12px; margin: 8px 0 0 0; max-height: 220px; overflow: auto; white-space: pre-wrap; font: 11.5px var(--os-mono); border-radius: var(--r-1, 6px); color: var(--os-fg); border: none; }
|
|
349
358
|
.app-shell-pane { margin: 0; padding: 8px; font: 12px var(--os-mono); color: var(--os-fg); background: var(--os-bg-0); height: 100%; overflow: auto; white-space: pre-wrap; box-sizing: border-box; }
|
|
350
359
|
.app-canvas { width: 100%; height: 100%; background: var(--os-bg-0); display: block; cursor: default; }
|
|
351
|
-
.app-canvas.x-display { background: #0b0d10; }
|
|
360
|
+
.app-canvas.x-display { background: #0b0d10; } /* intentional: fake CRT/terminal black screen, not a theme surface */
|
|
352
361
|
.app-frame { width: 100%; height: 100%; border: 0; background: var(--os-bg-0); }
|
|
353
362
|
.app-iframe { width: 100%; height: 100%; border: 0; display: block; }
|
|
354
|
-
.app-iframe.web { background: #ffffff; }
|
|
363
|
+
.app-iframe.web { background: #ffffff; } /* intentional: white canvas for embedded external web content that expects white */
|
|
355
364
|
.app-text-cursor { }
|
|
356
365
|
|
|
357
366
|
@media (prefers-reduced-motion: no-preference) {
|
|
@@ -429,53 +438,38 @@ html, body {
|
|
|
429
438
|
.wm-resize { display: none !important; }
|
|
430
439
|
}
|
|
431
440
|
|
|
432
|
-
/* ---- data-attr theme/
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
:root[data-theme="paper"] {
|
|
444
|
-
--os-bg-0: #f6f5f1;
|
|
445
|
-
--os-bg-1: #efece4;
|
|
446
|
-
--os-bg-2: #e7e3d8;
|
|
447
|
-
--os-bg-3: #d8d3c4;
|
|
448
|
-
--os-fg: #14131a;
|
|
449
|
-
--os-fg-2: #3a3833;
|
|
450
|
-
--os-fg-3: #6a6660;
|
|
451
|
-
color-scheme: light;
|
|
452
|
-
}
|
|
453
|
-
:root[data-density="compact"] { --os-bar-h: 28px; --os-tile-pad: 6px; --os-gap: 6px; }
|
|
441
|
+
/* ---- data-attr theme/accent: deferred to the canonical theme ----
|
|
442
|
+
* The OS shell no longer redefines surface or accent colors per theme. The
|
|
443
|
+
* --os-* aliases above consume the canonical semantic tokens (--bg/--fg/
|
|
444
|
+
* --accent), and colors_and_type.css already drives [data-theme] (paper/ink/
|
|
445
|
+
* auto, with color-scheme + --danger tuning) and [data-accent] (green/purple/
|
|
446
|
+
* mascot). Re-declaring the os surface or accent tokens per theme here only
|
|
447
|
+
* re-introduced drift (ink vs canonical ink; purple vs canonical purple).
|
|
448
|
+
* Density bar-height is genuinely OS-shell-specific, so it stays;
|
|
449
|
+
* --os-accent-tint maps to the canonical accent tint. */
|
|
450
|
+
:root { --os-accent-tint: var(--accent-tint); }
|
|
451
|
+
:root[data-density="compact"] { --os-bar-h: 28px; --os-tile-pad: 6px; --os-gap: 6px; }
|
|
454
452
|
:root[data-density="comfortable"] { --os-bar-h: 36px; --os-tile-pad: 10px; --os-gap: 10px; }
|
|
455
|
-
:root[data-density="spacious"]
|
|
456
|
-
:root[data-accent="green"] { --os-accent: #247420; --os-accent-tint: color-mix(in oklab, #247420 18%, transparent); }
|
|
457
|
-
:root[data-accent="purple"] { --os-accent: #7c5cff; --os-accent-tint: color-mix(in oklab, #7c5cff 18%, transparent); }
|
|
458
|
-
:root[data-accent="mascot"] { --os-accent: #ff6d3f; --os-accent-tint: color-mix(in oklab, #ff6d3f 18%, transparent); }
|
|
459
|
-
:root[data-theme="ink"][data-accent="green"] { --os-accent: #3FA93A; }
|
|
460
|
-
:root[data-theme="ink"][data-accent="purple"] { --os-accent: #a085ff; }
|
|
461
|
-
:root[data-theme="ink"][data-accent="mascot"] { --os-accent: #ff8a64; }
|
|
453
|
+
:root[data-density="spacious"] { --os-bar-h: 44px; --os-tile-pad: 14px; --os-gap: 14px; }
|
|
462
454
|
|
|
463
455
|
/* ============================================================
|
|
464
|
-
* thebird
|
|
456
|
+
* thebird brand layer (migrated from thebird's local thebird-brand.css
|
|
465
457
|
* 2026-05-26). thebird ships ZERO design CSS — every rule below lives here
|
|
466
458
|
* upstream and is delivered via the published package. Scoped to .ds-247420
|
|
467
|
-
* (thebird's OS root carries that class). Brand identity: Inter +
|
|
468
|
-
*
|
|
469
|
-
*
|
|
459
|
+
* (thebird's OS root carries that class). Brand identity: Inter + green accent
|
|
460
|
+
* + uniform 34px bars + Windows-style right-side window controls.
|
|
461
|
+
*
|
|
462
|
+
* NOTE: this no longer globally overrides --paper. A global :root override
|
|
463
|
+
* silently mutated the base theme for EVERY portfolio consumer (canonical
|
|
464
|
+
* --paper is #F6F5F1; thebird wanted #F5F0E4). The warm-paper variant is now a
|
|
465
|
+
* named preset [data-theme="thebird"] a consumer opts into, leaving the base
|
|
466
|
+
* theme untouched. The [data-theme="thebird"] COLOR preset now lives in the
|
|
467
|
+
* canonical colors_and_type.css (a first-class swappable theme); only the
|
|
468
|
+
* OS-shell chrome (bar geometry, typography alias) stays here scoped to
|
|
469
|
+
* .ds-247420.
|
|
470
470
|
* ============================================================ */
|
|
471
|
-
:root {
|
|
472
|
-
--paper: #F5F0E4;
|
|
473
|
-
}
|
|
474
471
|
.ds-247420 {
|
|
475
|
-
--ff-ui:
|
|
476
|
-
--ff-display: 'Inter', system-ui, sans-serif !important;
|
|
477
|
-
--ff-prose: 'Inter', system-ui, sans-serif !important;
|
|
478
|
-
--os-accent: #247420;
|
|
472
|
+
--ff-ui: var(--ff-body);
|
|
479
473
|
/* uniform bar height: 22px button + 6px+6px padding = 34px */
|
|
480
474
|
--os-bar-h: 34px !important;
|
|
481
475
|
--os-bar-h-mobile: 34px !important;
|
|
@@ -518,8 +512,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
518
512
|
position: fixed;
|
|
519
513
|
pointer-events: none;
|
|
520
514
|
z-index: 9050;
|
|
521
|
-
background: color-mix(in oklab, var(--os-accent
|
|
522
|
-
border: 2px solid var(--os-accent
|
|
515
|
+
background: color-mix(in oklab, var(--os-accent) 20%, transparent);
|
|
516
|
+
border: 2px solid var(--os-accent);
|
|
523
517
|
border-radius: 8px;
|
|
524
518
|
transition: all 120ms ease;
|
|
525
519
|
}
|
|
@@ -534,14 +528,14 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
534
528
|
top: 50%;
|
|
535
529
|
transform: translate(-50%, -50%);
|
|
536
530
|
padding: 16px 20px;
|
|
537
|
-
background: var(--os-bg-2
|
|
538
|
-
border: 1px solid var(--os-accent
|
|
531
|
+
background: var(--os-bg-2);
|
|
532
|
+
border: 1px solid var(--os-accent);
|
|
539
533
|
border-radius: 8px;
|
|
540
534
|
z-index: 9600;
|
|
541
|
-
font-family: var(--ff-ui
|
|
542
|
-
color: var(--os-fg
|
|
535
|
+
font-family: var(--ff-ui);
|
|
536
|
+
color: var(--os-fg);
|
|
543
537
|
min-width: 280px;
|
|
544
|
-
box-shadow:
|
|
538
|
+
box-shadow: var(--shadow-overlay);
|
|
545
539
|
}
|
|
546
540
|
.ds-247420 .wm-switcher-item {
|
|
547
541
|
padding: 8px 12px;
|
|
@@ -551,8 +545,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
551
545
|
gap: 10px;
|
|
552
546
|
}
|
|
553
547
|
.ds-247420 .wm-switcher-item.active {
|
|
554
|
-
background: var(--os-accent
|
|
555
|
-
color: var(--paper
|
|
548
|
+
background: var(--os-accent);
|
|
549
|
+
color: var(--paper);
|
|
556
550
|
}
|
|
557
551
|
|
|
558
552
|
/* freddie-chat font family (upstream still ships Nunito; brand is Inter). */
|
|
@@ -560,7 +554,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
560
554
|
.ds-247420 freddie-chat .chat-bubble,
|
|
561
555
|
.ds-247420 freddie-chat .chat-meta,
|
|
562
556
|
.ds-247420 freddie-chat .chat-head {
|
|
563
|
-
font-family: var(--ff-ui
|
|
557
|
+
font-family: var(--ff-ui);
|
|
564
558
|
}
|
|
565
559
|
.ds-247420 freddie-chat .chat-bubble pre,
|
|
566
560
|
.ds-247420 freddie-chat .chat-bubble code {
|
|
@@ -587,31 +581,31 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
587
581
|
display: inline-flex; align-items: center; gap: 6px;
|
|
588
582
|
height: 22px; padding: 0 6px 0 8px;
|
|
589
583
|
border-radius: var(--r-pill, 999px);
|
|
590
|
-
background: color-mix(in oklab, var(--fg
|
|
591
|
-
color: var(--fg
|
|
592
|
-
font-family: var(--ff-ui
|
|
584
|
+
background: color-mix(in oklab, var(--fg) 6%, transparent);
|
|
585
|
+
color: var(--fg);
|
|
586
|
+
font-family: var(--ff-ui); font-size: 11px; font-weight: 500;
|
|
593
587
|
cursor: pointer;
|
|
594
588
|
border: 1px solid transparent;
|
|
595
589
|
transition: background 120ms ease, border-color 120ms ease;
|
|
596
590
|
user-select: none; flex: 0 0 auto;
|
|
597
591
|
}
|
|
598
|
-
.ds-247420 .tb-sess-chip:hover { background: color-mix(in oklab, var(--fg
|
|
592
|
+
.ds-247420 .tb-sess-chip:hover { background: color-mix(in oklab, var(--fg) 12%, transparent); }
|
|
599
593
|
.ds-247420 .tb-sess-chip.active {
|
|
600
|
-
background: color-mix(in oklab, var(--os-accent
|
|
601
|
-
border-color: var(--os-accent
|
|
602
|
-
color: var(--fg
|
|
594
|
+
background: color-mix(in oklab, var(--os-accent) 18%, transparent);
|
|
595
|
+
border-color: var(--os-accent);
|
|
596
|
+
color: var(--fg);
|
|
603
597
|
}
|
|
604
|
-
.ds-247420 .tb-sess-chip.active .tb-sess-dot { background: var(--os-accent
|
|
605
|
-
.ds-247420 .tb-sess-dot { width: 6px; height: 6px; border-radius: 50%; background: color-mix(in oklab, var(--fg
|
|
598
|
+
.ds-247420 .tb-sess-chip.active .tb-sess-dot { background: var(--os-accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--os-accent) 30%, transparent); }
|
|
599
|
+
.ds-247420 .tb-sess-dot { width: 6px; height: 6px; border-radius: 50%; background: color-mix(in oklab, var(--fg) 40%, transparent); flex: 0 0 6px; }
|
|
606
600
|
.ds-247420 .tb-sess-label { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
607
601
|
.ds-247420 .tb-sess-badge {
|
|
608
602
|
display: inline-flex; align-items: center; justify-content: center;
|
|
609
603
|
min-width: 16px; height: 14px; padding: 0 4px;
|
|
610
604
|
border-radius: 7px;
|
|
611
|
-
background: color-mix(in oklab, var(--fg
|
|
605
|
+
background: color-mix(in oklab, var(--fg) 14%, transparent);
|
|
612
606
|
font-size: 9px; font-weight: 600; line-height: 1;
|
|
613
607
|
}
|
|
614
|
-
.ds-247420 .tb-sess-chip.active .tb-sess-badge { background: color-mix(in oklab, var(--os-accent
|
|
608
|
+
.ds-247420 .tb-sess-chip.active .tb-sess-badge { background: color-mix(in oklab, var(--os-accent) 30%, transparent); }
|
|
615
609
|
.ds-247420 .tb-sess-x {
|
|
616
610
|
width: 16px; height: 16px; line-height: 14px; text-align: center;
|
|
617
611
|
border: 0; padding: 0; background: transparent;
|
|
@@ -620,45 +614,45 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
620
614
|
opacity: 0.55; transition: opacity 120ms ease, background 120ms ease;
|
|
621
615
|
}
|
|
622
616
|
.ds-247420 .tb-sess-chip:hover .tb-sess-x { opacity: 1; }
|
|
623
|
-
.ds-247420 .tb-sess-x:hover { background: color-mix(in oklab,
|
|
617
|
+
.ds-247420 .tb-sess-x:hover { background: color-mix(in oklab, var(--danger) 30%, transparent); color: var(--on-color); }
|
|
624
618
|
|
|
625
619
|
.ds-247420 .tb-sess-add {
|
|
626
620
|
display: inline-flex; align-items: center; gap: 4px;
|
|
627
621
|
height: 22px; padding: 0 10px;
|
|
628
|
-
border: 1px dashed color-mix(in oklab, var(--fg
|
|
622
|
+
border: 1px dashed color-mix(in oklab, var(--fg) 30%, transparent);
|
|
629
623
|
background: transparent;
|
|
630
624
|
border-radius: var(--r-pill, 999px);
|
|
631
|
-
font-family: var(--ff-ui
|
|
632
|
-
color: var(--fg
|
|
625
|
+
font-family: var(--ff-ui); font-size: 11px; font-weight: 500;
|
|
626
|
+
color: var(--fg);
|
|
633
627
|
cursor: pointer;
|
|
634
628
|
margin-left: 6px;
|
|
635
629
|
transition: border-color 120ms ease, background 120ms ease;
|
|
636
630
|
}
|
|
637
631
|
.ds-247420 .tb-sess-add:hover {
|
|
638
|
-
border-color: var(--os-accent
|
|
639
|
-
background: color-mix(in oklab, var(--os-accent
|
|
632
|
+
border-color: var(--os-accent);
|
|
633
|
+
background: color-mix(in oklab, var(--os-accent) 8%, transparent);
|
|
640
634
|
}
|
|
641
635
|
.ds-247420 .tb-sess-add-plus { font-size: 13px; line-height: 1; }
|
|
642
636
|
.ds-247420 .tb-sess-add-lbl { line-height: 1; }
|
|
643
637
|
|
|
644
638
|
.tb-sess-overlay {
|
|
645
639
|
position: fixed; inset: 0; z-index: 9800;
|
|
646
|
-
background:
|
|
640
|
+
background: var(--scrim);
|
|
647
641
|
display: flex; align-items: center; justify-content: center;
|
|
648
642
|
animation: tb-sess-fade 120ms ease;
|
|
649
643
|
}
|
|
650
644
|
@keyframes tb-sess-fade { from { opacity: 0; } to { opacity: 1; } }
|
|
651
645
|
.tb-sess-modal {
|
|
652
|
-
background: var(--bg
|
|
653
|
-
color: var(--fg
|
|
646
|
+
background: var(--bg);
|
|
647
|
+
color: var(--fg);
|
|
654
648
|
border-radius: 12px;
|
|
655
|
-
box-shadow:
|
|
649
|
+
box-shadow: var(--shadow-overlay);
|
|
656
650
|
min-width: 320px; max-width: 480px;
|
|
657
|
-
border: 1px solid color-mix(in oklab, var(--fg
|
|
651
|
+
border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
|
|
658
652
|
overflow: hidden;
|
|
659
|
-
font-family: var(--ff-ui
|
|
653
|
+
font-family: var(--ff-ui);
|
|
660
654
|
}
|
|
661
|
-
.tb-sess-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid color-mix(in oklab, var(--fg
|
|
655
|
+
.tb-sess-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid color-mix(in oklab, var(--fg) 8%, transparent); }
|
|
662
656
|
.tb-sess-modal-title { font-weight: 600; font-size: 14px; }
|
|
663
657
|
.tb-sess-modal-x { background: transparent; border: 0; font-size: 20px; line-height: 1; cursor: pointer; color: inherit; padding: 0 4px; }
|
|
664
658
|
.tb-sess-modal-body { padding: 16px; display: flex; flex-direction: column; gap: 8px; }
|
|
@@ -666,28 +660,28 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
666
660
|
.tb-sess-modal-input {
|
|
667
661
|
width: 100%; box-sizing: border-box;
|
|
668
662
|
height: 32px; padding: 0 10px;
|
|
669
|
-
border: 1px solid color-mix(in oklab, var(--fg
|
|
663
|
+
border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent);
|
|
670
664
|
border-radius: 6px;
|
|
671
|
-
background: color-mix(in oklab, var(--fg
|
|
665
|
+
background: color-mix(in oklab, var(--fg) 6%, var(--bg));
|
|
672
666
|
color: inherit;
|
|
673
667
|
font-family: inherit; font-size: 13px;
|
|
674
668
|
}
|
|
675
|
-
.tb-sess-modal-input:focus { outline: none; border-color: var(--os-accent
|
|
669
|
+
.tb-sess-modal-input:focus { outline: none; border-color: var(--os-accent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--os-accent) 20%, transparent); }
|
|
676
670
|
.tb-sess-modal-hint { font-size: 11px; opacity: 0.7; }
|
|
677
671
|
.tb-sess-modal-msg { font-size: 13px; }
|
|
678
|
-
.tb-sess-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid color-mix(in oklab, var(--fg
|
|
672
|
+
.tb-sess-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid color-mix(in oklab, var(--fg) 8%, transparent); }
|
|
679
673
|
.tb-sess-modal-btn {
|
|
680
674
|
height: 28px; padding: 0 14px;
|
|
681
|
-
border-radius: 6px; border: 1px solid color-mix(in oklab, var(--fg
|
|
675
|
+
border-radius: 6px; border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent);
|
|
682
676
|
background: transparent; color: inherit;
|
|
683
677
|
font-family: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
|
|
684
678
|
transition: background 120ms ease, border-color 120ms ease;
|
|
685
679
|
}
|
|
686
|
-
.tb-sess-modal-btn:hover { background: color-mix(in oklab, var(--fg
|
|
687
|
-
.tb-sess-modal-btn.primary { background: var(--os-accent
|
|
688
|
-
.tb-sess-modal-btn.primary:hover { background: color-mix(in oklab, var(--os-accent
|
|
689
|
-
.tb-sess-modal-btn.danger { background:
|
|
690
|
-
.tb-sess-modal-btn.danger:hover { background:
|
|
680
|
+
.tb-sess-modal-btn:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
|
|
681
|
+
.tb-sess-modal-btn.primary { background: var(--os-accent); color: var(--on-color); border-color: var(--os-accent); }
|
|
682
|
+
.tb-sess-modal-btn.primary:hover { background: color-mix(in oklab, var(--os-accent) 80%, var(--ink)); }
|
|
683
|
+
.tb-sess-modal-btn.danger { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
|
|
684
|
+
.tb-sess-modal-btn.danger:hover { background: color-mix(in oklab, var(--danger) 80%, var(--ink)); }
|
|
691
685
|
|
|
692
686
|
.tb-sess-empty {
|
|
693
687
|
position: fixed; inset: 0; z-index: 8900;
|
|
@@ -696,65 +690,65 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
696
690
|
}
|
|
697
691
|
.tb-sess-empty-card {
|
|
698
692
|
pointer-events: auto;
|
|
699
|
-
background: var(--bg
|
|
700
|
-
color: var(--fg
|
|
701
|
-
border: 1px solid color-mix(in oklab, var(--fg
|
|
693
|
+
background: var(--bg);
|
|
694
|
+
color: var(--fg);
|
|
695
|
+
border: 1px solid color-mix(in oklab, var(--fg) 14%, transparent);
|
|
702
696
|
border-radius: 16px;
|
|
703
|
-
box-shadow:
|
|
697
|
+
box-shadow: var(--shadow-3);
|
|
704
698
|
padding: 32px 40px; text-align: center;
|
|
705
|
-
font-family: var(--ff-ui
|
|
699
|
+
font-family: var(--ff-ui);
|
|
706
700
|
max-width: 420px;
|
|
707
701
|
}
|
|
708
702
|
.tb-sess-empty-title { font-size: 18px; font-weight: 600; margin-bottom: 6px; }
|
|
709
703
|
.tb-sess-empty-sub { font-size: 13px; opacity: 0.7; margin-bottom: 20px; }
|
|
710
704
|
.tb-sess-empty-cta {
|
|
711
705
|
height: 40px; padding: 0 24px;
|
|
712
|
-
background: var(--os-accent
|
|
706
|
+
background: var(--os-accent); color: var(--on-color);
|
|
713
707
|
border: 0; border-radius: 999px;
|
|
714
708
|
font-family: inherit; font-size: 14px; font-weight: 600;
|
|
715
709
|
cursor: pointer;
|
|
716
710
|
transition: transform 120ms ease, box-shadow 120ms ease;
|
|
717
711
|
}
|
|
718
|
-
.tb-sess-empty-cta:hover { transform: translateY(-1px); box-shadow: 0 4px 16px color-mix(in oklab, var(--os-accent
|
|
712
|
+
.tb-sess-empty-cta:hover { transform: translateY(-1px); box-shadow: 0 4px 16px color-mix(in oklab, var(--os-accent) 40%, transparent); }
|
|
719
713
|
|
|
720
714
|
/* ---- Workspaces app — full-window session manager card grid ---- */
|
|
721
|
-
.ds-247420 .tb-sessions-app { display: flex; flex-direction: column; height: 100%; font-family: var(--ff-ui
|
|
722
|
-
.ds-247420 .tb-sessions-bar { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid color-mix(in oklab, var(--fg
|
|
715
|
+
.ds-247420 .tb-sessions-app { display: flex; flex-direction: column; height: 100%; font-family: var(--ff-ui); color: var(--fg); background: var(--bg); }
|
|
716
|
+
.ds-247420 .tb-sessions-bar { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid color-mix(in oklab, var(--fg) 10%, transparent); }
|
|
723
717
|
.ds-247420 .tb-sessions-title { font-weight: 600; font-size: 14px; }
|
|
724
718
|
.ds-247420 .tb-sessions-count { font-size: 12px; opacity: 0.6; margin-left: 4px; }
|
|
725
719
|
.ds-247420 .tb-sessions-spacer { flex: 1; }
|
|
726
|
-
.ds-247420 .tb-sessions-btn { height: 28px; padding: 0 12px; border-radius: 6px; border: 1px solid color-mix(in oklab, var(--fg
|
|
727
|
-
.ds-247420 .tb-sessions-btn:hover { background: color-mix(in oklab, var(--fg
|
|
728
|
-
.ds-247420 .tb-sessions-btn.primary { background: var(--os-accent
|
|
729
|
-
.ds-247420 .tb-sessions-btn.danger { background:
|
|
720
|
+
.ds-247420 .tb-sessions-btn { height: 28px; padding: 0 12px; border-radius: 6px; border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent); background: transparent; color: inherit; font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit; }
|
|
721
|
+
.ds-247420 .tb-sessions-btn:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
|
|
722
|
+
.ds-247420 .tb-sessions-btn.primary { background: var(--os-accent); color: var(--on-color); border-color: var(--os-accent); }
|
|
723
|
+
.ds-247420 .tb-sessions-btn.danger { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
|
|
730
724
|
.ds-247420 .tb-sessions-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
731
725
|
.ds-247420 .tb-sessions-grid { flex: 1; overflow: auto; padding: 14px; display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; align-content: start; }
|
|
732
|
-
.ds-247420 .tb-sessions-card { padding: 12px; border-radius: 10px; border: 1px solid color-mix(in oklab, var(--fg
|
|
733
|
-
.ds-247420 .tb-sessions-card:hover { border-color: var(--os-accent
|
|
734
|
-
.ds-247420 .tb-sessions-card.active { border-color: var(--os-accent
|
|
726
|
+
.ds-247420 .tb-sessions-card { padding: 12px; border-radius: 10px; border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent); background: color-mix(in oklab, var(--fg) 3%, transparent); display: flex; flex-direction: column; gap: 8px; transition: border-color 120ms ease, transform 120ms ease; }
|
|
727
|
+
.ds-247420 .tb-sessions-card:hover { border-color: var(--os-accent); }
|
|
728
|
+
.ds-247420 .tb-sessions-card.active { border-color: var(--os-accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--os-accent) 30%, transparent); }
|
|
735
729
|
.ds-247420 .tb-sessions-card-head { display: flex; align-items: center; gap: 8px; }
|
|
736
730
|
.ds-247420 .tb-sessions-card-check { width: 14px; height: 14px; cursor: pointer; flex: 0 0 14px; }
|
|
737
731
|
.ds-247420 .tb-sessions-card-name { font-weight: 600; font-size: 13px; flex: 1; outline: none; padding: 2px 4px; border-radius: 4px; }
|
|
738
|
-
.ds-247420 .tb-sessions-card-name[contenteditable="true"] { background: color-mix(in oklab, var(--fg
|
|
732
|
+
.ds-247420 .tb-sessions-card-name[contenteditable="true"] { background: color-mix(in oklab, var(--fg) 8%, transparent); }
|
|
739
733
|
.ds-247420 .tb-sessions-card-id { font-family: var(--os-mono, monospace); font-size: 10px; opacity: 0.5; }
|
|
740
734
|
.ds-247420 .tb-sessions-card-stats { font-size: 11px; opacity: 0.7; display: flex; gap: 12px; }
|
|
741
735
|
.ds-247420 .tb-sessions-card-actions { display: flex; gap: 6px; margin-top: 4px; }
|
|
742
|
-
.ds-247420 .tb-sessions-card-actions button { flex: 1; height: 24px; font-size: 11px; padding: 0 8px; border-radius: 4px; border: 1px solid color-mix(in oklab, var(--fg
|
|
743
|
-
.ds-247420 .tb-sessions-card-actions button:hover { background: color-mix(in oklab, var(--fg
|
|
744
|
-
.ds-247420 .tb-sessions-card-actions button.danger:hover { background:
|
|
736
|
+
.ds-247420 .tb-sessions-card-actions button { flex: 1; height: 24px; font-size: 11px; padding: 0 8px; border-radius: 4px; border: 1px solid color-mix(in oklab, var(--fg) 16%, transparent); background: transparent; color: inherit; cursor: pointer; font-family: inherit; }
|
|
737
|
+
.ds-247420 .tb-sessions-card-actions button:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
|
|
738
|
+
.ds-247420 .tb-sessions-card-actions button.danger:hover { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
|
|
745
739
|
.ds-247420 .tb-sessions-empty-mid { padding: 40px; text-align: center; opacity: 0.6; font-size: 13px; }
|
|
746
740
|
|
|
747
741
|
/* ---- prefers-contrast: more — strengthen borders + focus so the translucent
|
|
748
742
|
chrome stays legible under forced/high-contrast user settings. ---- */
|
|
749
743
|
@media (prefers-contrast: more) {
|
|
750
|
-
.ds-247420 .wm-win { border-color: var(--fg
|
|
751
|
-
.ds-247420 .wm-bar { border-bottom: 1px solid var(--fg
|
|
744
|
+
.ds-247420 .wm-win { border-color: var(--fg); }
|
|
745
|
+
.ds-247420 .wm-bar { border-bottom: 1px solid var(--fg); }
|
|
752
746
|
.ds-247420 .os-menubar,
|
|
753
|
-
.ds-247420 .os-taskbar { border-color: var(--fg
|
|
747
|
+
.ds-247420 .os-taskbar { border-color: var(--fg); }
|
|
754
748
|
.ds-247420 .tb-sess-chip,
|
|
755
749
|
.ds-247420 .tb-sessions-card,
|
|
756
|
-
.ds-247420 .tb-sessions-btn { border-color: var(--fg
|
|
757
|
-
.ds-247420 :focus-visible { outline: 2px solid var(--fg
|
|
750
|
+
.ds-247420 .tb-sessions-btn { border-color: var(--fg); }
|
|
751
|
+
.ds-247420 :focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
|
|
758
752
|
}
|
|
759
753
|
|
|
760
754
|
/* ---- print: a web-OS desktop has no meaningful print form. Suppress the
|
|
@@ -763,6 +757,6 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
763
757
|
.os-menubar, .os-taskbar, .wm-snap-preview,
|
|
764
758
|
.tb-sess-overlay, .tb-switching, .wm-switcher { display: none !important; }
|
|
765
759
|
.wm-root, .wm-canvas { position: static !important; transform: none !important; overflow: visible !important; }
|
|
766
|
-
.wm-win { position: static !important; box-shadow: none !important; border: 1px solid
|
|
760
|
+
.wm-win { position: static !important; box-shadow: none !important; border: 1px solid var(--fg) !important; page-break-inside: avoid; margin: 0 0 12px; width: auto !important; height: auto !important; }
|
|
767
761
|
.wm-win.wm-min { display: none !important; }
|
|
768
762
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// spoint kit — paint surfaces for the spoint game client (loading screen,
|
|
2
|
+
// HUD, editor chrome). Each render fn returns {node, ...controls, dispose};
|
|
3
|
+
// the consumer owns state/events, this kit owns layout + classes. Surfaced
|
|
4
|
+
// through the main bundle entry so spoint can import directly from unpkg.
|
|
5
|
+
|
|
6
|
+
export { renderLoadingScreen } from './loading-screen.js';
|
|
7
|
+
|
|
8
|
+
export const themeUrl = new URL('./loading-screen.css', import.meta.url).href;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* Loading-screen kit styles. Scoped under .ds-247420 at build time.
|
|
2
|
+
All colors reference design tokens (no raw literals) per the token-lint gate. */
|
|
3
|
+
.sp-loading {
|
|
4
|
+
position: fixed;
|
|
5
|
+
inset: 0;
|
|
6
|
+
z-index: 10000;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
background: var(--bg);
|
|
11
|
+
color: var(--fg);
|
|
12
|
+
font-family: var(--ff-mono);
|
|
13
|
+
transition: opacity var(--dur-slow) var(--ease);
|
|
14
|
+
}
|
|
15
|
+
.sp-loading-fade { opacity: 0; pointer-events: none; }
|
|
16
|
+
.sp-loading-container {
|
|
17
|
+
width: min(420px, 86vw);
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: 20px;
|
|
21
|
+
}
|
|
22
|
+
.sp-loading-header h1 {
|
|
23
|
+
margin: 0;
|
|
24
|
+
font-family: var(--ff-display);
|
|
25
|
+
font-size: var(--fs-h2);
|
|
26
|
+
letter-spacing: 0.04em;
|
|
27
|
+
}
|
|
28
|
+
.sp-loading-label {
|
|
29
|
+
margin: 4px 0 0;
|
|
30
|
+
color: var(--fg-2);
|
|
31
|
+
font-size: var(--fs-body);
|
|
32
|
+
}
|
|
33
|
+
.sp-loading-bars { display: flex; flex-direction: column; gap: 10px; }
|
|
34
|
+
.sp-loading-bar-row {
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: 88px 1fr 44px;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 10px;
|
|
39
|
+
}
|
|
40
|
+
.sp-loading-bar-name {
|
|
41
|
+
color: var(--fg-3);
|
|
42
|
+
font-size: var(--fs-small, 11px);
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
letter-spacing: 0.1em;
|
|
45
|
+
}
|
|
46
|
+
.sp-loading-bar-track {
|
|
47
|
+
height: 6px;
|
|
48
|
+
border-radius: 3px;
|
|
49
|
+
background: var(--bg-3);
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
}
|
|
52
|
+
.sp-loading-bar-fill {
|
|
53
|
+
height: 100%;
|
|
54
|
+
width: 0%;
|
|
55
|
+
background: var(--accent);
|
|
56
|
+
transition: width var(--dur-base) var(--ease);
|
|
57
|
+
}
|
|
58
|
+
.sp-loading-bar-pct {
|
|
59
|
+
color: var(--fg-2);
|
|
60
|
+
font-size: var(--fs-small, 11px);
|
|
61
|
+
text-align: right;
|
|
62
|
+
}
|
|
63
|
+
.sp-loading-detail {
|
|
64
|
+
min-height: 16px;
|
|
65
|
+
color: var(--fg-3);
|
|
66
|
+
font-size: var(--fs-small, 11px);
|
|
67
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Loading-screen paint surface for the spoint game client.
|
|
2
|
+
// renderLoadingScreen({brand, label}) -> { node, setLabel, setDownload,
|
|
3
|
+
// setProcessing, setDetail, hide, dispose }. The consumer (spoint
|
|
4
|
+
// LoadingManager) owns progress events; this module owns layout + classes.
|
|
5
|
+
// Two progress bars (download, processing), a label, and a detail line.
|
|
6
|
+
|
|
7
|
+
export function renderLoadingScreen(opts = {}) {
|
|
8
|
+
const { brand = 'spoint', label = 'Connecting...' } = opts;
|
|
9
|
+
|
|
10
|
+
const node = document.createElement('div');
|
|
11
|
+
node.className = 'sp-loading ds-247420';
|
|
12
|
+
node.dataset.component = 'loading-screen';
|
|
13
|
+
|
|
14
|
+
const container = document.createElement('div');
|
|
15
|
+
container.className = 'sp-loading-container';
|
|
16
|
+
|
|
17
|
+
const header = document.createElement('div');
|
|
18
|
+
header.className = 'sp-loading-header';
|
|
19
|
+
const title = document.createElement('h1');
|
|
20
|
+
title.textContent = brand;
|
|
21
|
+
const labelEl = document.createElement('p');
|
|
22
|
+
labelEl.className = 'sp-loading-label';
|
|
23
|
+
labelEl.textContent = label;
|
|
24
|
+
header.append(title, labelEl);
|
|
25
|
+
|
|
26
|
+
const bars = document.createElement('div');
|
|
27
|
+
bars.className = 'sp-loading-bars';
|
|
28
|
+
|
|
29
|
+
const mkBar = (name) => {
|
|
30
|
+
const row = document.createElement('div');
|
|
31
|
+
row.className = 'sp-loading-bar-row';
|
|
32
|
+
const nameEl = document.createElement('span');
|
|
33
|
+
nameEl.className = 'sp-loading-bar-name';
|
|
34
|
+
nameEl.textContent = name;
|
|
35
|
+
const track = document.createElement('div');
|
|
36
|
+
track.className = 'sp-loading-bar-track';
|
|
37
|
+
const fill = document.createElement('div');
|
|
38
|
+
fill.className = 'sp-loading-bar-fill';
|
|
39
|
+
track.appendChild(fill);
|
|
40
|
+
const pct = document.createElement('span');
|
|
41
|
+
pct.className = 'sp-loading-bar-pct';
|
|
42
|
+
pct.textContent = '0%';
|
|
43
|
+
row.append(nameEl, track, pct);
|
|
44
|
+
return { row, fill, pct };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const dl = mkBar('Download');
|
|
48
|
+
const proc = mkBar('Processing');
|
|
49
|
+
bars.append(dl.row, proc.row);
|
|
50
|
+
|
|
51
|
+
const detail = document.createElement('div');
|
|
52
|
+
detail.className = 'sp-loading-detail';
|
|
53
|
+
|
|
54
|
+
container.append(header, bars, detail);
|
|
55
|
+
node.appendChild(container);
|
|
56
|
+
|
|
57
|
+
const setBar = (bar, percent) => {
|
|
58
|
+
bar.fill.style.width = percent + '%';
|
|
59
|
+
bar.pct.textContent = Math.round(percent) + '%';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
node,
|
|
64
|
+
setLabel: (text) => { labelEl.textContent = text; },
|
|
65
|
+
setDownload: (percent) => setBar(dl, percent),
|
|
66
|
+
setProcessing: (percent) => setBar(proc, percent),
|
|
67
|
+
setDetail: (text) => { detail.textContent = text; },
|
|
68
|
+
hide: async () => {
|
|
69
|
+
node.classList.add('sp-loading-fade');
|
|
70
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
71
|
+
node.remove();
|
|
72
|
+
},
|
|
73
|
+
dispose: () => node.remove(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -158,9 +158,9 @@ async function runAllTests() {
|
|
|
158
158
|
const speedup = (10000 + initStats.initMs.markdown + initStats.initMs.prism) / (mdStats.avg * 100 + initStats.initMs.markdown + initStats.initMs.prism);
|
|
159
159
|
console.log(`Performance improvement: ~${speedup.toFixed(1)}x faster`);
|
|
160
160
|
|
|
161
|
-
console.log('\
|
|
161
|
+
console.log('\nPASS All tests completed successfully');
|
|
162
162
|
} catch (err) {
|
|
163
|
-
console.error('\
|
|
163
|
+
console.error('\nFAIL Test failed:', err.message);
|
|
164
164
|
console.error(err.stack);
|
|
165
165
|
process.exit(1);
|
|
166
166
|
}
|