@runtypelabs/persona 4.7.0 → 4.9.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.
- package/README.md +1 -0
- package/dist/animations/glyph-cycle.cjs +2 -2
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/glyph-cycle.js +2 -2
- package/dist/animations/{types-CSmiKRVa.d.cts → types-4ROVJ1gA.d.cts} +85 -3
- package/dist/animations/{types-CSmiKRVa.d.ts → types-4ROVJ1gA.d.ts} +85 -3
- package/dist/animations/wipe.cjs +2 -2
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/chunk-5EIIHQLQ.js +1 -0
- package/dist/chunk-IO5VVUKP.js +3 -0
- package/dist/chunk-IPVK3KOM.js +1 -0
- package/dist/chunk-UPO4GUFC.js +1 -0
- package/dist/codegen.cjs +13 -13
- package/dist/codegen.js +14 -14
- package/dist/context-mentions-7S5KVUTG.js +169 -0
- package/dist/context-mentions-inline-TTCN7ZM2.js +4 -0
- package/dist/context-mentions-inline.cjs +4 -0
- package/dist/context-mentions-inline.d.cts +203 -0
- package/dist/context-mentions-inline.d.ts +203 -0
- package/dist/context-mentions-inline.js +4 -0
- package/dist/context-mentions.cjs +295 -0
- package/dist/context-mentions.d.cts +7025 -0
- package/dist/context-mentions.d.ts +7025 -0
- package/dist/context-mentions.js +295 -0
- package/dist/index.cjs +99 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1507 -182
- package/dist/index.d.ts +1507 -182
- package/dist/index.global.js +88 -56
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +99 -68
- package/dist/index.js.map +1 -1
- package/dist/install.global.js +1 -1
- package/dist/install.global.js.map +1 -1
- package/dist/launcher.global.js +3 -2
- package/dist/launcher.global.js.map +1 -1
- package/dist/markdown-parsers.js +24 -24
- package/dist/plugin-kit.cjs +1 -1
- package/dist/plugin-kit.d.cts +17 -0
- package/dist/plugin-kit.d.ts +17 -0
- package/dist/plugin-kit.js +1 -1
- package/dist/runtype-tts-entry-UJAEF7NZ.js +1 -0
- package/dist/runtype-tts.js +1 -1
- package/dist/session-reconnect-JKIJBHS5.js +1 -0
- package/dist/smart-dom-reader.cjs +18 -17
- package/dist/smart-dom-reader.d.cts +1260 -16
- package/dist/smart-dom-reader.d.ts +1260 -16
- package/dist/smart-dom-reader.js +18 -17
- package/dist/testing.cjs +3 -3
- package/dist/testing.js +3 -3
- package/dist/theme-editor-preview.cjs +260 -58
- package/dist/theme-editor-preview.d.cts +1234 -15
- package/dist/theme-editor-preview.d.ts +1234 -15
- package/dist/theme-editor-preview.js +87 -58
- package/dist/theme-editor.cjs +10 -10
- package/dist/theme-editor.d.cts +1226 -15
- package/dist/theme-editor.d.ts +1226 -15
- package/dist/theme-editor.js +10 -10
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +76 -0
- package/dist/theme-reference.d.ts +76 -0
- package/dist/theme-reference.js +1 -1
- package/dist/voice-worklet-player.cjs +2 -2
- package/dist/voice-worklet-player.js +2 -2
- package/dist/webmcp-polyfill.js +2 -2
- package/dist/widget.css +1 -1
- package/package.json +16 -5
- package/src/artifacts-session.test.ts +178 -0
- package/src/client.test.ts +255 -1
- package/src/client.ts +157 -60
- package/src/components/artifact-card.test.ts +333 -0
- package/src/components/artifact-card.ts +75 -28
- package/src/components/artifact-inline.test.ts +1328 -0
- package/src/components/artifact-inline.ts +920 -0
- package/src/components/artifact-pane.test.ts +1042 -0
- package/src/components/artifact-pane.ts +440 -131
- package/src/components/artifact-preview.test.ts +1155 -0
- package/src/components/artifact-preview.ts +994 -0
- package/src/components/composer-parts.ts +3 -12
- package/src/components/context-mention-button.test.ts +70 -0
- package/src/components/context-mention-button.ts +82 -0
- package/src/components/context-mention-chip.ts +134 -0
- package/src/components/context-mention-menu.test.ts +508 -0
- package/src/components/context-mention-menu.ts +0 -0
- package/src/components/message-bubble.test.ts +175 -0
- package/src/components/message-bubble.ts +177 -19
- package/src/components/panel.ts +7 -10
- package/src/components/pill-composer-builder.test.ts +6 -2
- package/src/components/pill-composer-builder.ts +6 -6
- package/src/components/reasoning-bubble.ts +1 -13
- package/src/components/registry.ts +38 -3
- package/src/components/tool-bubble.ts +1 -13
- package/src/context-mentions-bundle.test.ts +163 -0
- package/src/context-mentions-entry.ts +185 -0
- package/src/context-mentions-inline-entry.test.ts +136 -0
- package/src/context-mentions-inline-entry.ts +226 -0
- package/src/context-mentions-inline-loader.test.ts +30 -0
- package/src/context-mentions-inline-loader.ts +36 -0
- package/src/context-mentions-inline.ts +15 -0
- package/src/context-mentions-loader.ts +32 -0
- package/src/context-mentions.ts +16 -0
- package/src/defaults.ts +1 -0
- package/src/generated/runtype-openapi-contract.ts +55 -3
- package/src/index-core.ts +46 -1
- package/src/index-global.ts +51 -0
- package/src/index.ts +8 -0
- package/src/markdown-parsers-loader.test.ts +158 -0
- package/src/markdown-parsers-loader.ts +83 -27
- package/src/plugin-kit.test.ts +40 -0
- package/src/plugin-kit.ts +39 -5
- package/src/runtime/host-layout.test.ts +163 -0
- package/src/runtime/host-layout.ts +110 -7
- package/src/runtime/init.ts +18 -61
- package/src/session.mentions.test.ts +175 -0
- package/src/session.test.ts +52 -4
- package/src/session.ts +197 -27
- package/src/smart-dom-reader.test.ts +129 -2
- package/src/smart-dom-reader.ts +127 -1
- package/src/styles/context-mention-menu-css.ts +176 -0
- package/src/styles/widget.css +1002 -152
- package/src/theme-editor/preview.ts +2 -0
- package/src/theme-editor/sections.test.ts +26 -1
- package/src/theme-editor/sections.ts +13 -5
- package/src/theme-reference.ts +2 -2
- package/src/tool-call-display-defaults.test.ts +1 -0
- package/src/types/theme.ts +79 -0
- package/src/types.ts +1041 -17
- package/src/ui.artifact-pane-gating.test.ts +636 -0
- package/src/ui.component-directive.test.ts +104 -0
- package/src/ui.composer-bar.test.ts +60 -2
- package/src/ui.detached-panel.test.ts +1049 -0
- package/src/ui.mention-submit.test.ts +235 -0
- package/src/ui.tool-display.test.ts +51 -0
- package/src/ui.ts +998 -159
- package/src/utils/artifact-custom-actions.ts +128 -0
- package/src/utils/artifact-display.test.ts +42 -0
- package/src/utils/artifact-display.ts +84 -0
- package/src/utils/artifact-file.test.ts +116 -0
- package/src/utils/artifact-file.ts +117 -0
- package/src/utils/artifact-gate.test.ts +112 -5
- package/src/utils/artifact-gate.ts +39 -14
- package/src/utils/artifact-loading-status.ts +55 -0
- package/src/utils/artifact-status-label.ts +190 -0
- package/src/utils/buttons.ts +7 -1
- package/src/utils/chunk-loader.test.ts +97 -0
- package/src/utils/chunk-loader.ts +88 -0
- package/src/utils/code-highlight.test.ts +186 -0
- package/src/utils/code-highlight.ts +400 -0
- package/src/utils/composer-contenteditable.test.ts +507 -0
- package/src/utils/composer-contenteditable.ts +626 -0
- package/src/utils/composer-document.test.ts +280 -0
- package/src/utils/composer-document.ts +293 -0
- package/src/utils/composer-history.test.ts +35 -7
- package/src/utils/composer-history.ts +30 -20
- package/src/utils/composer-input.ts +159 -0
- package/src/utils/context-mention-controller.test.ts +1215 -0
- package/src/utils/context-mention-controller.ts +1186 -0
- package/src/utils/context-mention-manager.test.ts +422 -0
- package/src/utils/context-mention-manager.ts +410 -0
- package/src/utils/context-mention-orchestrator.test.ts +538 -0
- package/src/utils/context-mention-orchestrator.ts +348 -0
- package/src/utils/icons.ts +2 -0
- package/src/utils/live-region.test.ts +108 -0
- package/src/utils/live-region.ts +94 -0
- package/src/utils/mention-channels.ts +63 -0
- package/src/utils/mention-llm-format.test.ts +91 -0
- package/src/utils/mention-llm-format.ts +79 -0
- package/src/utils/mention-matcher.test.ts +86 -0
- package/src/utils/mention-matcher.ts +221 -0
- package/src/utils/mention-token.ts +72 -0
- package/src/utils/mention-trigger.test.ts +155 -0
- package/src/utils/mention-trigger.ts +156 -0
- package/src/utils/roving-tablist.test.ts +152 -0
- package/src/utils/roving-tablist.ts +111 -0
- package/src/utils/spinner.ts +45 -0
- package/src/utils/theme.test.ts +76 -4
- package/src/utils/theme.ts +7 -0
- package/src/utils/tokens.ts +118 -11
- package/src/utils/tool-loading-animation.test.ts +32 -0
- package/src/utils/tool-loading-animation.ts +24 -0
- package/dist/chunk-DFBSCFYN.js +0 -1
- package/dist/runtype-tts-entry-HFUV2UF7.js +0 -1
- package/dist/session-reconnect-U77QFUR7.js +0 -1
package/src/styles/widget.css
CHANGED
|
@@ -53,10 +53,6 @@
|
|
|
53
53
|
align-items: center;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
.persona-items-end {
|
|
57
|
-
align-items: flex-end;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
56
|
.persona-items-start {
|
|
61
57
|
align-items: flex-start;
|
|
62
58
|
}
|
|
@@ -238,6 +234,24 @@
|
|
|
238
234
|
border-radius: var(--persona-button-radius);
|
|
239
235
|
}
|
|
240
236
|
|
|
237
|
+
/* Composer ghost icon buttons (attachment + mention): transparent, neutral
|
|
238
|
+
foreground, subtle hover. Themeable via `components.button.ghost.*`
|
|
239
|
+
→ `--persona-button-ghost-*`. The `[data-persona-root]` prefix outranks the
|
|
240
|
+
`.persona-rounded-button` full-radius above so the ghost radius wins. */
|
|
241
|
+
[data-persona-root] .persona-mention-button,
|
|
242
|
+
[data-persona-root] .persona-attachment-button {
|
|
243
|
+
background-color: var(--persona-button-ghost-bg, transparent);
|
|
244
|
+
color: var(--persona-button-ghost-fg, var(--persona-text, #111827));
|
|
245
|
+
border: none;
|
|
246
|
+
border-radius: var(--persona-button-ghost-radius, var(--persona-radius-md, 0.375rem));
|
|
247
|
+
transition: background-color 0.15s ease;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
[data-persona-root] .persona-mention-button:hover,
|
|
251
|
+
[data-persona-root] .persona-attachment-button:hover {
|
|
252
|
+
background-color: var(--persona-button-ghost-hover-bg, rgba(0, 0, 0, 0.05));
|
|
253
|
+
}
|
|
254
|
+
|
|
241
255
|
.persona-overflow-hidden {
|
|
242
256
|
overflow: hidden;
|
|
243
257
|
}
|
|
@@ -274,10 +288,6 @@
|
|
|
274
288
|
background-color: #f3f4f6;
|
|
275
289
|
}
|
|
276
290
|
|
|
277
|
-
.persona-bg-gray-200 {
|
|
278
|
-
background-color: #e5e7eb;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
291
|
.persona-text-persona-primary {
|
|
282
292
|
color: var(--persona-primary, #171717);
|
|
283
293
|
}
|
|
@@ -436,14 +446,6 @@
|
|
|
436
446
|
padding-left: 0.75rem;
|
|
437
447
|
}
|
|
438
448
|
|
|
439
|
-
.persona-pl-7 {
|
|
440
|
-
padding-left: 1.75rem;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
.persona-pr-7 {
|
|
444
|
-
padding-right: 1.75rem;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
449
|
.persona-pl-8 {
|
|
448
450
|
padding-left: 2rem;
|
|
449
451
|
}
|
|
@@ -526,22 +528,10 @@
|
|
|
526
528
|
opacity: 0.5;
|
|
527
529
|
}
|
|
528
530
|
|
|
529
|
-
.persona-shadow-2xl {
|
|
530
|
-
box-shadow: 0 30px 60px -15px rgba(15, 23, 42, 0.35);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
531
|
.persona-shadow-sm {
|
|
534
532
|
box-shadow: 0 5px 15px rgba(15, 23, 42, 0.08);
|
|
535
533
|
}
|
|
536
534
|
|
|
537
|
-
.persona-shadow-md {
|
|
538
|
-
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
.persona-shadow-lg {
|
|
542
|
-
box-shadow: 0 20px 40px rgba(15, 23, 42, 0.18);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
535
|
.persona-border {
|
|
546
536
|
border-width: 1px;
|
|
547
537
|
border-style: solid;
|
|
@@ -558,14 +548,6 @@
|
|
|
558
548
|
border-bottom-color: rgba(148, 163, 184, 0.28);
|
|
559
549
|
}
|
|
560
550
|
|
|
561
|
-
.persona-border-gray-100 {
|
|
562
|
-
border-color: #f1f5f9;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
.persona-border-persona-secondary {
|
|
566
|
-
border-color: var(--persona-secondary, #7c3aed);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
551
|
.persona-border-persona-border {
|
|
570
552
|
border-color: var(--persona-border, #e5e7eb);
|
|
571
553
|
}
|
|
@@ -576,18 +558,6 @@
|
|
|
576
558
|
border-top-color: rgba(148, 163, 184, 0.28);
|
|
577
559
|
}
|
|
578
560
|
|
|
579
|
-
.persona-border-t-persona-border {
|
|
580
|
-
border-top-width: 1px;
|
|
581
|
-
border-top-style: solid;
|
|
582
|
-
border-top-color: var(--persona-border, #f1f5f9);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
.persona-border-b-persona-border {
|
|
586
|
-
border-bottom-width: 1px;
|
|
587
|
-
border-bottom-style: solid;
|
|
588
|
-
border-bottom-color: var(--persona-border, #f1f5f9);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
561
|
.persona-border-t-persona-divider {
|
|
592
562
|
border-top-width: 1px;
|
|
593
563
|
border-top-style: solid;
|
|
@@ -664,13 +634,6 @@
|
|
|
664
634
|
width: 2.5rem;
|
|
665
635
|
}
|
|
666
636
|
|
|
667
|
-
.persona-h-12 {
|
|
668
|
-
height: 3rem;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
.persona-w-12 {
|
|
672
|
-
width: 3rem;
|
|
673
|
-
}
|
|
674
637
|
|
|
675
638
|
.persona-leading-relaxed {
|
|
676
639
|
line-height: 1.75;
|
|
@@ -725,6 +688,10 @@
|
|
|
725
688
|
flex-shrink: 0;
|
|
726
689
|
}
|
|
727
690
|
|
|
691
|
+
.persona-shrink-0 {
|
|
692
|
+
flex-shrink: 0;
|
|
693
|
+
}
|
|
694
|
+
|
|
728
695
|
.persona-min-w-0 {
|
|
729
696
|
min-width: 0;
|
|
730
697
|
}
|
|
@@ -773,8 +740,6 @@
|
|
|
773
740
|
margin-top: 0.5rem;
|
|
774
741
|
}
|
|
775
742
|
|
|
776
|
-
.persona-h-12,
|
|
777
|
-
.persona-w-12,
|
|
778
743
|
.persona-h-10,
|
|
779
744
|
.persona-w-10,
|
|
780
745
|
.persona-h-8,
|
|
@@ -786,10 +751,6 @@
|
|
|
786
751
|
text-align: right;
|
|
787
752
|
}
|
|
788
753
|
|
|
789
|
-
.hover\:persona-bg-gray-200:hover {
|
|
790
|
-
background-color: #e5e7eb;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
754
|
.hover\:persona-bg-persona-container:hover {
|
|
794
755
|
background-color: var(--persona-container, #f8fafc);
|
|
795
756
|
}
|
|
@@ -863,6 +824,10 @@
|
|
|
863
824
|
overflow-y: auto;
|
|
864
825
|
}
|
|
865
826
|
|
|
827
|
+
.persona-overflow-x-auto {
|
|
828
|
+
overflow-x: auto;
|
|
829
|
+
}
|
|
830
|
+
|
|
866
831
|
.persona-widget-body {
|
|
867
832
|
overscroll-behavior: contain;
|
|
868
833
|
}
|
|
@@ -1340,68 +1305,6 @@
|
|
|
1340
1305
|
font-size: 0.8125rem;
|
|
1341
1306
|
}
|
|
1342
1307
|
|
|
1343
|
-
/* Code block copy button */
|
|
1344
|
-
.persona-code-block-wrapper {
|
|
1345
|
-
position: relative;
|
|
1346
|
-
margin: 0.5rem 0;
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
.persona-code-block-wrapper pre {
|
|
1350
|
-
margin: 0 !important;
|
|
1351
|
-
border-top-left-radius: 0 !important;
|
|
1352
|
-
border-top-right-radius: 0 !important;
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
.persona-code-block-header {
|
|
1356
|
-
display: flex;
|
|
1357
|
-
align-items: center;
|
|
1358
|
-
justify-content: space-between;
|
|
1359
|
-
background-color: var(--persona-md-code-block-bg, #f3f4f6);
|
|
1360
|
-
border: 1px solid var(--persona-md-code-block-border-color, #e5e7eb);
|
|
1361
|
-
border-bottom: none;
|
|
1362
|
-
border-top-left-radius: var(--persona-md-code-block-border-radius, 0.375rem);
|
|
1363
|
-
border-top-right-radius: var(--persona-md-code-block-border-radius, 0.375rem);
|
|
1364
|
-
padding: 0.25rem 0.5rem 0.25rem 0.75rem;
|
|
1365
|
-
font-size: 0.75rem;
|
|
1366
|
-
color: var(--persona-text-muted, #6b7280);
|
|
1367
|
-
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
.persona-code-copy-btn {
|
|
1371
|
-
display: inline-flex;
|
|
1372
|
-
align-items: center;
|
|
1373
|
-
gap: 0.25rem;
|
|
1374
|
-
background: none;
|
|
1375
|
-
border: 1px solid transparent;
|
|
1376
|
-
border-radius: 0.25rem;
|
|
1377
|
-
padding: 0.25rem 0.5rem;
|
|
1378
|
-
cursor: pointer;
|
|
1379
|
-
color: var(--persona-text-muted, #6b7280);
|
|
1380
|
-
font-size: 0.75rem;
|
|
1381
|
-
font-family: inherit;
|
|
1382
|
-
line-height: 1;
|
|
1383
|
-
transition: color 0.15s ease, border-color 0.15s ease;
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
.persona-code-copy-btn:hover {
|
|
1387
|
-
color: var(--persona-text, #111827);
|
|
1388
|
-
border-color: var(--persona-md-code-block-border-color, #e5e7eb);
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
.persona-code-copy-btn.persona-code-copied {
|
|
1392
|
-
color: #16a34a;
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
.persona-code-copy-btn.persona-code-copy-generating {
|
|
1396
|
-
cursor: default;
|
|
1397
|
-
opacity: 0.5;
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
.persona-code-copy-btn.persona-code-copy-generating:hover {
|
|
1401
|
-
color: var(--persona-text-muted, #6b7280);
|
|
1402
|
-
border-color: transparent;
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
1308
|
/* Ensure all links in chat bubbles have underlines */
|
|
1406
1309
|
.persona-message-bubble a {
|
|
1407
1310
|
text-decoration: underline;
|
|
@@ -2668,7 +2571,12 @@
|
|
|
2668
2571
|
}
|
|
2669
2572
|
|
|
2670
2573
|
/* Document toolbar preset: optional layout vars: --persona-artifact-doc-toolbar-icon-color, etc. */
|
|
2671
|
-
|
|
2574
|
+
/* Document-toolbar icon/copy button styling is shared by the artifact pane's
|
|
2575
|
+
document preset and the inline chrome actions cluster, so both surfaces read
|
|
2576
|
+
the same `components.artifact.toolbar` tokens (the vars are emitted globally
|
|
2577
|
+
at the widget root). */
|
|
2578
|
+
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-icon-btn,
|
|
2579
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions .persona-artifact-doc-icon-btn {
|
|
2672
2580
|
display: inline-flex;
|
|
2673
2581
|
align-items: center;
|
|
2674
2582
|
justify-content: center;
|
|
@@ -2681,17 +2589,20 @@
|
|
|
2681
2589
|
line-height: 1;
|
|
2682
2590
|
}
|
|
2683
2591
|
|
|
2684
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-icon-btn:hover
|
|
2592
|
+
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-icon-btn:hover,
|
|
2593
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions .persona-artifact-doc-icon-btn:hover {
|
|
2685
2594
|
color: var(--persona-artifact-toolbar-icon-hover-color, inherit);
|
|
2686
|
-
background: var(--persona-artifact-toolbar-icon-hover-bg, var(--persona-container, #f3f4f6));
|
|
2595
|
+
background: var(--persona-artifact-toolbar-icon-hover-bg, var(--persona-icon-btn-hover-bg, var(--persona-container, #f3f4f6)));
|
|
2687
2596
|
}
|
|
2688
2597
|
|
|
2689
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-icon-btn[aria-pressed="true"]
|
|
2690
|
-
|
|
2691
|
-
|
|
2598
|
+
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-icon-btn[aria-pressed="true"],
|
|
2599
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions .persona-artifact-doc-icon-btn[aria-pressed="true"] {
|
|
2600
|
+
background: var(--persona-artifact-doc-toggle-active-bg, var(--persona-icon-btn-active-bg, var(--persona-container, #f3f4f6)));
|
|
2601
|
+
border-color: var(--persona-artifact-doc-toggle-active-border, var(--persona-icon-btn-active-border, var(--persona-border, #e5e7eb)));
|
|
2692
2602
|
}
|
|
2693
2603
|
|
|
2694
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-copy-btn
|
|
2604
|
+
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-copy-btn,
|
|
2605
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions .persona-artifact-doc-copy-btn {
|
|
2695
2606
|
display: inline-flex;
|
|
2696
2607
|
align-items: center;
|
|
2697
2608
|
gap: 0.35rem;
|
|
@@ -2705,19 +2616,23 @@
|
|
|
2705
2616
|
line-height: 1.25;
|
|
2706
2617
|
}
|
|
2707
2618
|
|
|
2708
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-copy-btn:hover
|
|
2709
|
-
|
|
2619
|
+
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-copy-btn:hover,
|
|
2620
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions .persona-artifact-doc-copy-btn:hover {
|
|
2621
|
+
background: var(--persona-artifact-toolbar-icon-hover-bg, var(--persona-icon-btn-hover-bg, var(--persona-container, #f3f4f6)));
|
|
2710
2622
|
}
|
|
2711
2623
|
|
|
2712
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-doc-copy-label {
|
|
2713
|
-
font-weight: 500;
|
|
2714
|
-
}
|
|
2715
2624
|
|
|
2716
2625
|
/* Artifact tab theming */
|
|
2717
2626
|
[data-persona-root] .persona-artifact-tab {
|
|
2718
2627
|
background: var(--persona-artifact-tab-bg, transparent);
|
|
2719
2628
|
border-radius: var(--persona-artifact-tab-radius, 0.5rem);
|
|
2720
2629
|
color: var(--persona-artifact-tab-color, inherit);
|
|
2630
|
+
/* Keep each tab on one line and cap its width so the strip scrolls
|
|
2631
|
+
horizontally instead of wrapping/overflowing the pane. */
|
|
2632
|
+
white-space: nowrap;
|
|
2633
|
+
max-width: var(--persona-artifact-tab-max-width, 12rem);
|
|
2634
|
+
overflow: hidden;
|
|
2635
|
+
text-overflow: ellipsis;
|
|
2721
2636
|
}
|
|
2722
2637
|
|
|
2723
2638
|
[data-persona-root] .persona-artifact-tab.persona-bg-persona-container {
|
|
@@ -2730,27 +2645,40 @@
|
|
|
2730
2645
|
background: var(--persona-artifact-toolbar-bg, var(--persona-surface, #fff));
|
|
2731
2646
|
}
|
|
2732
2647
|
|
|
2733
|
-
/* Toggle group
|
|
2734
|
-
|
|
2735
|
-
gap: var(--persona-artifact-toolbar-toggle-group-gap, 0.25rem);
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
/* Toggle button border-radius (view/code buttons) */
|
|
2739
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-view-btn,
|
|
2740
|
-
[data-persona-root] .persona-artifact-toolbar-document .persona-artifact-code-btn {
|
|
2741
|
-
border-radius: var(--persona-artifact-toolbar-toggle-radius, var(--persona-artifact-toolbar-icon-radius, var(--persona-radius-md, 0.375rem)));
|
|
2742
|
-
}
|
|
2648
|
+
/* Toggle group + view/code button styling lives in the segmented
|
|
2649
|
+
.persona-toggle-group.persona-artifact-toggle-group block further down. */
|
|
2743
2650
|
|
|
2744
2651
|
/* Tab hover */
|
|
2745
2652
|
[data-persona-root] .persona-artifact-tab:hover {
|
|
2746
2653
|
background: var(--persona-artifact-tab-hover-bg, var(--persona-container, #f3f4f6));
|
|
2747
2654
|
}
|
|
2748
2655
|
|
|
2656
|
+
/* Keyboard focus ring, themed to match cards/buttons instead of the UA default
|
|
2657
|
+
(which varies by browser). Custom renderTabBar bars reuse .persona-artifact-tab,
|
|
2658
|
+
so they inherit the same ring; give a scroll container enough padding that the
|
|
2659
|
+
2px offset isn't clipped. */
|
|
2660
|
+
[data-persona-root] .persona-artifact-tab:focus-visible {
|
|
2661
|
+
outline: 2px solid var(--persona-accent, #171717);
|
|
2662
|
+
outline-offset: 2px;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2749
2665
|
/* Tab list container */
|
|
2750
2666
|
[data-persona-root] .persona-artifact-list {
|
|
2751
2667
|
background: var(--persona-artifact-tab-list-bg, transparent);
|
|
2752
2668
|
border-bottom-color: var(--persona-artifact-tab-list-border-color, var(--persona-border, #e5e7eb));
|
|
2753
2669
|
padding: var(--persona-artifact-tab-list-padding, 0.5rem);
|
|
2670
|
+
/* Thin, unobtrusive horizontal scrollbar for the tab strip. */
|
|
2671
|
+
scrollbar-width: thin;
|
|
2672
|
+
scroll-behavior: smooth;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
[data-persona-root] .persona-artifact-list::-webkit-scrollbar {
|
|
2676
|
+
height: 6px;
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
[data-persona-root] .persona-artifact-list::-webkit-scrollbar-thumb {
|
|
2680
|
+
background: var(--persona-artifact-tab-list-scrollbar, var(--persona-border, #e5e7eb));
|
|
2681
|
+
border-radius: 9999px;
|
|
2754
2682
|
}
|
|
2755
2683
|
|
|
2756
2684
|
/* Toolbar border override */
|
|
@@ -2758,6 +2686,23 @@
|
|
|
2758
2686
|
border-bottom: var(--persona-artifact-toolbar-border, 1px solid var(--persona-border, #e5e7eb));
|
|
2759
2687
|
}
|
|
2760
2688
|
|
|
2689
|
+
/* Artifact reference card (chat thread) */
|
|
2690
|
+
[data-persona-root] .persona-artifact-card {
|
|
2691
|
+
background: var(--persona-artifact-card-bg, var(--persona-surface, #ffffff));
|
|
2692
|
+
border: var(--persona-artifact-card-border, 1px solid var(--persona-border, #e5e7eb));
|
|
2693
|
+
border-radius: var(--persona-artifact-card-radius, var(--persona-message-assistant-radius, var(--persona-radius-lg, 0.5rem)));
|
|
2694
|
+
cursor: pointer;
|
|
2695
|
+
transition: background-color 0.15s ease, border-color 0.15s ease;
|
|
2696
|
+
}
|
|
2697
|
+
[data-persona-root] .persona-artifact-card:hover {
|
|
2698
|
+
background: var(--persona-artifact-card-hover-bg, #f3f4f6);
|
|
2699
|
+
border-color: var(--persona-artifact-card-hover-border, var(--persona-border, #e5e7eb));
|
|
2700
|
+
}
|
|
2701
|
+
[data-persona-root] .persona-artifact-card:focus-visible {
|
|
2702
|
+
outline: 2px solid var(--persona-accent, #171717);
|
|
2703
|
+
outline-offset: 2px;
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2761
2706
|
/* ── Composable button utilities ── */
|
|
2762
2707
|
|
|
2763
2708
|
/* Icon button: base for all icon-only buttons created by createIconButton() */
|
|
@@ -2929,6 +2874,89 @@
|
|
|
2929
2874
|
border-bottom-right-radius: var(--persona-toggle-group-radius, var(--persona-icon-btn-radius, var(--persona-radius-md, 0.375rem)));
|
|
2930
2875
|
}
|
|
2931
2876
|
|
|
2877
|
+
/* Artifact view/source toggle: one segmented pill. The container carries the
|
|
2878
|
+
border; segments are borderless and the active one is highlighted, so the
|
|
2879
|
+
pair reads as a single mutually exclusive switch instead of two buttons. */
|
|
2880
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group {
|
|
2881
|
+
gap: var(--persona-artifact-toolbar-toggle-group-gap, 2px);
|
|
2882
|
+
padding: var(--persona-artifact-toolbar-toggle-group-padding, 2px);
|
|
2883
|
+
border: var(--persona-artifact-toolbar-toggle-group-border, 1px solid var(--persona-border, #e5e7eb));
|
|
2884
|
+
/* Default to the toolbar button radius (document preset var, then the plain
|
|
2885
|
+
icon-button var) so the pill matches the neighboring copy/close buttons
|
|
2886
|
+
instead of standing out as a capsule. */
|
|
2887
|
+
border-radius: var(--persona-artifact-toolbar-toggle-group-radius, var(--persona-artifact-toolbar-icon-radius, var(--persona-icon-btn-radius, var(--persona-radius-md, 0.375rem))));
|
|
2888
|
+
background: var(--persona-artifact-toolbar-toggle-group-bg, var(--persona-surface, #ffffff));
|
|
2889
|
+
}
|
|
2890
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group > .persona-icon-btn {
|
|
2891
|
+
border: none;
|
|
2892
|
+
background: transparent;
|
|
2893
|
+
/* Segment padding = standalone icon-button padding minus the container's
|
|
2894
|
+
padding, so the pill's outer height matches the neighboring icon buttons
|
|
2895
|
+
(the container's 1px border stands in for the border the segments lost).
|
|
2896
|
+
calc() clamps to 0 if a theme sets group padding larger than icon padding. */
|
|
2897
|
+
padding: calc(var(--persona-artifact-toolbar-icon-padding, var(--persona-icon-btn-padding, 0.25rem)) - var(--persona-artifact-toolbar-toggle-group-padding, 2px));
|
|
2898
|
+
/* Container radius minus the 2px padding so the segment nests concentrically. */
|
|
2899
|
+
border-radius: var(--persona-artifact-toolbar-toggle-radius, calc(var(--persona-artifact-toolbar-icon-radius, var(--persona-icon-btn-radius, var(--persona-radius-md, 0.375rem))) - 2px));
|
|
2900
|
+
}
|
|
2901
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group > .persona-icon-btn:hover {
|
|
2902
|
+
background: var(--persona-artifact-toolbar-icon-hover-bg, var(--persona-icon-btn-hover-bg, var(--persona-container, #f3f4f6)));
|
|
2903
|
+
}
|
|
2904
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group > .persona-icon-btn[aria-pressed="true"] {
|
|
2905
|
+
background: var(--persona-artifact-doc-toggle-active-bg, var(--persona-icon-btn-active-bg, var(--persona-container, #f3f4f6)));
|
|
2906
|
+
/* Inset ring instead of a border so documentToolbarToggleActiveBorderColor
|
|
2907
|
+
still applies inside the borderless segment (transparent by default). */
|
|
2908
|
+
box-shadow: inset 0 0 0 1px var(--persona-artifact-doc-toggle-active-border, transparent);
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
/* Sliding selection thumb: a container ::before that translates between the
|
|
2912
|
+
two equal-width segments, keyed off aria-pressed via :has(). The static
|
|
2913
|
+
aria-pressed background above stays as the fallback for browsers without
|
|
2914
|
+
:has() and is disabled inside the @supports block so the highlight is only
|
|
2915
|
+
ever painted once. Geometry assumes the group's two segments are equal
|
|
2916
|
+
width (both are square icon buttons). */
|
|
2917
|
+
@supports selector(:has(*)) {
|
|
2918
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group {
|
|
2919
|
+
position: relative;
|
|
2920
|
+
}
|
|
2921
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group::before {
|
|
2922
|
+
content: "";
|
|
2923
|
+
position: absolute;
|
|
2924
|
+
top: var(--persona-artifact-toolbar-toggle-group-padding, 2px);
|
|
2925
|
+
bottom: var(--persona-artifact-toolbar-toggle-group-padding, 2px);
|
|
2926
|
+
left: var(--persona-artifact-toolbar-toggle-group-padding, 2px);
|
|
2927
|
+
width: calc(
|
|
2928
|
+
50% - var(--persona-artifact-toolbar-toggle-group-padding, 2px) -
|
|
2929
|
+
(var(--persona-artifact-toolbar-toggle-group-gap, 2px) / 2)
|
|
2930
|
+
);
|
|
2931
|
+
border-radius: var(--persona-artifact-toolbar-toggle-radius, calc(var(--persona-artifact-toolbar-icon-radius, var(--persona-icon-btn-radius, var(--persona-radius-md, 0.375rem))) - 2px));
|
|
2932
|
+
background: var(--persona-artifact-doc-toggle-active-bg, var(--persona-icon-btn-active-bg, var(--persona-container, #f3f4f6)));
|
|
2933
|
+
box-shadow: inset 0 0 0 1px var(--persona-artifact-doc-toggle-active-border, transparent);
|
|
2934
|
+
transition: transform 0.18s ease;
|
|
2935
|
+
pointer-events: none;
|
|
2936
|
+
}
|
|
2937
|
+
[data-persona-root]
|
|
2938
|
+
.persona-toggle-group.persona-artifact-toggle-group:has(
|
|
2939
|
+
> .persona-icon-btn:last-child[aria-pressed="true"]
|
|
2940
|
+
)::before {
|
|
2941
|
+
transform: translateX(calc(100% + var(--persona-artifact-toolbar-toggle-group-gap, 2px)));
|
|
2942
|
+
}
|
|
2943
|
+
/* Positioned so the segments paint above the absolutely positioned thumb
|
|
2944
|
+
(document order applies once both are in the positioned layer). */
|
|
2945
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group > .persona-icon-btn {
|
|
2946
|
+
position: relative;
|
|
2947
|
+
}
|
|
2948
|
+
/* The thumb carries the highlight; keep the segment itself transparent. */
|
|
2949
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group > .persona-icon-btn[aria-pressed="true"] {
|
|
2950
|
+
background: transparent;
|
|
2951
|
+
box-shadow: none;
|
|
2952
|
+
}
|
|
2953
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2954
|
+
[data-persona-root] .persona-toggle-group.persona-artifact-toggle-group::before {
|
|
2955
|
+
transition: none;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2932
2960
|
/* Combo button: label + chevron with dropdown */
|
|
2933
2961
|
[data-persona-root] .persona-combo-btn {
|
|
2934
2962
|
font-size: var(--persona-combo-btn-font-size, 0.8125rem);
|
|
@@ -3019,11 +3047,560 @@
|
|
|
3019
3047
|
max-width: var(--persona-artifact-pane-max-width, 28rem);
|
|
3020
3048
|
min-width: var(--persona-artifact-pane-min-width, 0);
|
|
3021
3049
|
flex-shrink: 0;
|
|
3022
|
-
|
|
3050
|
+
/* No default elevation on the pane; welded reads as one card, detached and
|
|
3051
|
+
the drawer set their own shadow. Explicit paneShadow still wins. */
|
|
3052
|
+
box-shadow: var(--persona-artifact-pane-shadow, none);
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
/* Expanded artifact pane: pane takes the whole split root, chat column hides.
|
|
3057
|
+
Split-view only: below 641px / narrow hosts the drawer already covers everything. */
|
|
3058
|
+
@media (min-width: 641px) {
|
|
3059
|
+
[data-persona-root].persona-artifact-expanded .persona-artifact-split-root > :first-child {
|
|
3060
|
+
display: none;
|
|
3061
|
+
}
|
|
3062
|
+
[data-persona-root].persona-artifact-expanded .persona-artifact-pane {
|
|
3063
|
+
width: 100%;
|
|
3064
|
+
max-width: none;
|
|
3065
|
+
}
|
|
3066
|
+
[data-persona-root].persona-artifact-expanded .persona-artifact-split-handle {
|
|
3067
|
+
display: none !important;
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
@media (max-width: 640px) {
|
|
3071
|
+
[data-persona-root] .persona-artifact-expand-btn {
|
|
3072
|
+
display: none !important;
|
|
3023
3073
|
}
|
|
3024
3074
|
}
|
|
3075
|
+
[data-persona-root].persona-artifact-narrow-host .persona-artifact-expand-btn {
|
|
3076
|
+
display: none !important;
|
|
3077
|
+
}
|
|
3025
3078
|
|
|
3026
3079
|
/* paneBorderRadius: works on any paneAppearance; overflow clips content to rounded shape */
|
|
3080
|
+
/* Positioned frame wrapping the sandboxed preview iframe (artifact-preview.ts).
|
|
3081
|
+
`position: relative` gives the absolute loading overlay a containing block
|
|
3082
|
+
(the shared preview body is display: contents, so the iframe alone has no
|
|
3083
|
+
positioning context). The frame owns the rendered height and the iframe is
|
|
3084
|
+
100% of it — see the pane default here and the inline overrides below.
|
|
3085
|
+
|
|
3086
|
+
Opaque-canvas / color-scheme trap: an opaque-origin srcdoc (sandbox without
|
|
3087
|
+
allow-same-origin) that declares no color-scheme can get a UA-forced opaque
|
|
3088
|
+
canvas that flashes before content paints. Declaring color-scheme on the
|
|
3089
|
+
iframe plus an explicit background on both the frame and iframe makes the
|
|
3090
|
+
pre-paint surface a deliberate, themeable canvas rather than an uncontrolled
|
|
3091
|
+
flash. Artifact content generally assumes a light canvas, so white stays the
|
|
3092
|
+
default; override via --persona-artifact-frame-bg. */
|
|
3093
|
+
[data-persona-root] .persona-artifact-frame {
|
|
3094
|
+
position: relative;
|
|
3095
|
+
width: 100%;
|
|
3096
|
+
height: 100%;
|
|
3097
|
+
background: var(--persona-artifact-frame-bg, #ffffff);
|
|
3098
|
+
}
|
|
3099
|
+
/* Previewable file artifact: sandboxed iframe fills its frame. */
|
|
3100
|
+
[data-persona-root] .persona-artifact-iframe {
|
|
3101
|
+
display: block;
|
|
3102
|
+
width: 100%;
|
|
3103
|
+
height: 100%;
|
|
3104
|
+
border: 0;
|
|
3105
|
+
color-scheme: light;
|
|
3106
|
+
background: var(--persona-artifact-frame-bg, #ffffff);
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
/* Loading overlay above the preview iframe (artifact-preview.ts): absolutely
|
|
3110
|
+
fills the frame with the same themed canvas the iframe paints onto, so the
|
|
3111
|
+
pre-paint area reads as one deliberate surface. Appended only after
|
|
3112
|
+
`loading.delayMs`; the --out modifier fades it before removal. */
|
|
3113
|
+
[data-persona-root] .persona-artifact-frame-loading {
|
|
3114
|
+
position: absolute;
|
|
3115
|
+
inset: 0;
|
|
3116
|
+
display: flex;
|
|
3117
|
+
align-items: center;
|
|
3118
|
+
justify-content: center;
|
|
3119
|
+
background: var(--persona-artifact-frame-bg, #ffffff);
|
|
3120
|
+
opacity: 1;
|
|
3121
|
+
transition: opacity var(--persona-artifact-frame-loading-fade, 200ms) ease;
|
|
3122
|
+
}
|
|
3123
|
+
[data-persona-root] .persona-artifact-frame-loading--out {
|
|
3124
|
+
opacity: 0;
|
|
3125
|
+
}
|
|
3126
|
+
/* Default indicator column: the icon spinner, with the escalation label (when
|
|
3127
|
+
present) stacked below it. Icon-first, text only as a later escalation. */
|
|
3128
|
+
[data-persona-root] .persona-artifact-frame-loading-indicator {
|
|
3129
|
+
display: flex;
|
|
3130
|
+
flex-direction: column;
|
|
3131
|
+
align-items: center;
|
|
3132
|
+
gap: 0.625rem;
|
|
3133
|
+
}
|
|
3134
|
+
/* Escalation label: calm, muted, small — NO shimmer (deliberate, per research).
|
|
3135
|
+
Hidden until setupPreviewLoading adds --visible after labelDelayMs; a plain
|
|
3136
|
+
opacity transition fades it in. */
|
|
3137
|
+
[data-persona-root] .persona-artifact-frame-loading-text {
|
|
3138
|
+
color: var(
|
|
3139
|
+
--persona-artifact-frame-loading-color,
|
|
3140
|
+
var(--persona-text-muted, #6b7280)
|
|
3141
|
+
);
|
|
3142
|
+
font-size: 0.8125rem;
|
|
3143
|
+
font-weight: 500;
|
|
3144
|
+
opacity: 0;
|
|
3145
|
+
transition: opacity 240ms ease;
|
|
3146
|
+
}
|
|
3147
|
+
[data-persona-root] .persona-artifact-frame-loading-text--visible {
|
|
3148
|
+
opacity: 1;
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3151
|
+
/* Reusable icon spinner (utils/spinner.ts): a faint full track ring with a
|
|
3152
|
+
rotating arc on top. Icon-first loading is the norm across preview surfaces
|
|
3153
|
+
(Sandpack, embeds, v0/ChatGPT) and design systems (HIG/Material/Carbon/Geist);
|
|
3154
|
+
text-only "loading" is used by none. The arc spins via a GPU-friendly
|
|
3155
|
+
`transform: rotate` keyframe. Fallback chains:
|
|
3156
|
+
- size: --persona-artifact-spinner-size (default 28px)
|
|
3157
|
+
- arc: --persona-artifact-spinner-color → --persona-accent → --persona-primary
|
|
3158
|
+
→ neutral dark (the interactive/brand hue)
|
|
3159
|
+
- track: --persona-artifact-spinner-track-color → --persona-border → light gray
|
|
3160
|
+
- speed: --persona-artifact-spinner-speed (default 0.8s) */
|
|
3161
|
+
[data-persona-root] .persona-spinner {
|
|
3162
|
+
width: var(--persona-artifact-spinner-size, 28px);
|
|
3163
|
+
height: var(--persona-artifact-spinner-size, 28px);
|
|
3164
|
+
transform-origin: center;
|
|
3165
|
+
animation: persona-spinner-rotate var(--persona-artifact-spinner-speed, 0.8s)
|
|
3166
|
+
linear infinite;
|
|
3167
|
+
}
|
|
3168
|
+
[data-persona-root] .persona-spinner-track {
|
|
3169
|
+
fill: none;
|
|
3170
|
+
stroke: var(
|
|
3171
|
+
--persona-artifact-spinner-track-color,
|
|
3172
|
+
var(--persona-border, #e5e7eb)
|
|
3173
|
+
);
|
|
3174
|
+
stroke-width: 2.5;
|
|
3175
|
+
}
|
|
3176
|
+
[data-persona-root] .persona-spinner-arc {
|
|
3177
|
+
fill: none;
|
|
3178
|
+
stroke: var(
|
|
3179
|
+
--persona-artifact-spinner-color,
|
|
3180
|
+
var(--persona-accent, var(--persona-primary, #171717))
|
|
3181
|
+
);
|
|
3182
|
+
stroke-width: 2.5;
|
|
3183
|
+
stroke-linecap: round;
|
|
3184
|
+
/* r=9 → circumference ≈ 56.5; ~15u arc reads as a quarter-ish sweep. */
|
|
3185
|
+
stroke-dasharray: 15 42;
|
|
3186
|
+
}
|
|
3187
|
+
@keyframes persona-spinner-rotate {
|
|
3188
|
+
from {
|
|
3189
|
+
transform: rotate(0deg);
|
|
3190
|
+
}
|
|
3191
|
+
to {
|
|
3192
|
+
transform: rotate(360deg);
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
/* Reduced motion: stop the rotation (the static arc still reads as a ring) and
|
|
3196
|
+
drop the label fade. */
|
|
3197
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3198
|
+
[data-persona-root] .persona-spinner {
|
|
3199
|
+
animation: none;
|
|
3200
|
+
}
|
|
3201
|
+
[data-persona-root] .persona-artifact-frame-loading-text {
|
|
3202
|
+
transition: none;
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3206
|
+
/* Shared artifact preview body wrapper (artifact-preview.ts): generates no box
|
|
3207
|
+
so children (e.g. the iframe's height: 100%) lay out against the host
|
|
3208
|
+
container exactly as if they were its direct children. */
|
|
3209
|
+
[data-persona-root] .persona-artifact-preview-body {
|
|
3210
|
+
display: contents;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
/* Syntax-highlighted source view (code-highlight.ts). The host <pre> keeps its
|
|
3214
|
+
wrapping (persona-whitespace-pre-wrap); <code> resets white-space to normal so
|
|
3215
|
+
the literal "\n" separator text nodes between block line spans collapse
|
|
3216
|
+
visually while still reconstructing the verbatim source via textContent. Each
|
|
3217
|
+
line reserves a left gutter whose number is drawn by a CSS counter — never
|
|
3218
|
+
real text, so it is not selectable or copyable. */
|
|
3219
|
+
/* The source view sits directly on the pane surface (transparent, matching
|
|
3220
|
+
Claude's code view); set --persona-code-bg via theme.components.code.background
|
|
3221
|
+
to render it as an inset sheet instead. */
|
|
3222
|
+
[data-persona-root] .persona-code-pre {
|
|
3223
|
+
margin: 0;
|
|
3224
|
+
background: var(--persona-code-bg, transparent);
|
|
3225
|
+
border-radius: var(--persona-radius-md, 0.375rem);
|
|
3226
|
+
padding: 0.5rem 0.75rem 0.5rem 0.25rem;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
/* Pane source view is full-bleed: the pane drops its content padding (class
|
|
3230
|
+
toggled in artifact-pane.ts when the body rendered a code pre) so the
|
|
3231
|
+
line-number gutter sits flush against the pane's left edge. */
|
|
3232
|
+
[data-persona-root] .persona-artifact-content-flush {
|
|
3233
|
+
padding: 0;
|
|
3234
|
+
}
|
|
3235
|
+
[data-persona-root] .persona-artifact-content-flush .persona-code-pre {
|
|
3236
|
+
padding: 0.5rem 0.75rem 0.5rem 0;
|
|
3237
|
+
border-radius: 0;
|
|
3238
|
+
min-height: 100%;
|
|
3239
|
+
}
|
|
3240
|
+
[data-persona-root] .persona-code {
|
|
3241
|
+
display: block;
|
|
3242
|
+
white-space: normal;
|
|
3243
|
+
counter-reset: persona-code-line;
|
|
3244
|
+
/* Defend against host-page element rules (`code { background/padding/… }`):
|
|
3245
|
+
without Shadow DOM those selectors reach into the widget, and inline-code
|
|
3246
|
+
chip styling on a full source view reads as a mystery tinted block. */
|
|
3247
|
+
background: transparent;
|
|
3248
|
+
padding: 0;
|
|
3249
|
+
border-radius: 0;
|
|
3250
|
+
font-family: inherit;
|
|
3251
|
+
font-size: inherit;
|
|
3252
|
+
color: inherit;
|
|
3253
|
+
}
|
|
3254
|
+
[data-persona-root] .persona-code-line {
|
|
3255
|
+
display: block;
|
|
3256
|
+
position: relative;
|
|
3257
|
+
white-space: pre-wrap;
|
|
3258
|
+
padding-left: 3em;
|
|
3259
|
+
counter-increment: persona-code-line;
|
|
3260
|
+
/* An empty source line emits a childless span — a zero-height block whose
|
|
3261
|
+
absolutely-positioned gutter number would paint on top of the next line's.
|
|
3262
|
+
Reserve one line box (1lh; 1em as the older-engine fallback). */
|
|
3263
|
+
min-height: 1em;
|
|
3264
|
+
min-height: 1lh;
|
|
3265
|
+
}
|
|
3266
|
+
[data-persona-root] .persona-code-line::before {
|
|
3267
|
+
content: counter(persona-code-line);
|
|
3268
|
+
position: absolute;
|
|
3269
|
+
top: 0;
|
|
3270
|
+
left: 0;
|
|
3271
|
+
width: 2em;
|
|
3272
|
+
padding-right: 0.5em;
|
|
3273
|
+
text-align: right;
|
|
3274
|
+
color: var(--persona-code-line-number-color, #a0a1a7);
|
|
3275
|
+
border-right: 1px solid
|
|
3276
|
+
var(--persona-code-gutter-border-color, var(--persona-border, #e5e7eb));
|
|
3277
|
+
-webkit-user-select: none;
|
|
3278
|
+
user-select: none;
|
|
3279
|
+
}
|
|
3280
|
+
/* Default syntax palette: One Light (Atom), the same theme Claude.ai's code
|
|
3281
|
+
view uses. Numbers and attribute names share One's constant orange; CSS
|
|
3282
|
+
properties / JSON keys take the function blue so keys stay distinct from
|
|
3283
|
+
string values. */
|
|
3284
|
+
[data-persona-root] .persona-code-token-keyword {
|
|
3285
|
+
color: var(--persona-code-keyword-color, #a626a4);
|
|
3286
|
+
}
|
|
3287
|
+
[data-persona-root] .persona-code-token-string {
|
|
3288
|
+
color: var(--persona-code-string-color, #50a14f);
|
|
3289
|
+
}
|
|
3290
|
+
[data-persona-root] .persona-code-token-comment {
|
|
3291
|
+
color: var(--persona-code-comment-color, #a0a1a7);
|
|
3292
|
+
font-style: italic;
|
|
3293
|
+
}
|
|
3294
|
+
[data-persona-root] .persona-code-token-number {
|
|
3295
|
+
color: var(--persona-code-number-color, #986801);
|
|
3296
|
+
}
|
|
3297
|
+
[data-persona-root] .persona-code-token-tag {
|
|
3298
|
+
color: var(--persona-code-tag-color, #e45649);
|
|
3299
|
+
}
|
|
3300
|
+
[data-persona-root] .persona-code-token-attr {
|
|
3301
|
+
color: var(--persona-code-attr-color, #986801);
|
|
3302
|
+
}
|
|
3303
|
+
[data-persona-root] .persona-code-token-property {
|
|
3304
|
+
color: var(--persona-code-property-color, #4078f2);
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
/* Dark-scheme defaults for the syntax palette (One Dark counterparts of the
|
|
3308
|
+
One Light defaults above). Keyed off the widget's resolved scheme, stamped
|
|
3309
|
+
as data-persona-color-scheme by applyThemeVariables — NOT the OS
|
|
3310
|
+
prefers-color-scheme, which diverges whenever a host pins colorScheme.
|
|
3311
|
+
The widget's semantic vars can't drive these (syntax colors aren't
|
|
3312
|
+
derivable from surface/text). Explicit theme.components.code values still
|
|
3313
|
+
win in both schemes. */
|
|
3314
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-line::before {
|
|
3315
|
+
color: var(--persona-code-line-number-color, #4b5263);
|
|
3316
|
+
border-right-color: var(--persona-code-gutter-border-color, #3b4048);
|
|
3317
|
+
}
|
|
3318
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-keyword {
|
|
3319
|
+
color: var(--persona-code-keyword-color, #c678dd);
|
|
3320
|
+
}
|
|
3321
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-string {
|
|
3322
|
+
color: var(--persona-code-string-color, #98c379);
|
|
3323
|
+
}
|
|
3324
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-comment {
|
|
3325
|
+
color: var(--persona-code-comment-color, #5c6370);
|
|
3326
|
+
}
|
|
3327
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-number {
|
|
3328
|
+
color: var(--persona-code-number-color, #d19a66);
|
|
3329
|
+
}
|
|
3330
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-tag {
|
|
3331
|
+
color: var(--persona-code-tag-color, #e06c75);
|
|
3332
|
+
}
|
|
3333
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-attr {
|
|
3334
|
+
color: var(--persona-code-attr-color, #d19a66);
|
|
3335
|
+
}
|
|
3336
|
+
[data-persona-root][data-persona-color-scheme="dark"] .persona-code-token-property {
|
|
3337
|
+
color: var(--persona-code-property-color, #61afef);
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
/* Inline artifact block (artifact-inline.ts, display: "inline"): carries its
|
|
3341
|
+
own border/surface (registered with bubbleChrome: false, like the card).
|
|
3342
|
+
Reads like a file preview: a flush title/toolbar chrome bar above the body.
|
|
3343
|
+
Default vars draw from the same semantic surface/border/text/muted family
|
|
3344
|
+
the card uses, so light/dark themes work with zero config. */
|
|
3345
|
+
[data-persona-root] .persona-artifact-inline {
|
|
3346
|
+
border: var(--persona-artifact-inline-border, 1px solid var(--persona-border, #e5e7eb));
|
|
3347
|
+
border-radius: var(
|
|
3348
|
+
--persona-artifact-inline-radius,
|
|
3349
|
+
var(--persona-message-assistant-radius, var(--persona-radius-lg, 0.5rem))
|
|
3350
|
+
);
|
|
3351
|
+
background: var(--persona-artifact-inline-bg, var(--persona-surface, #ffffff));
|
|
3352
|
+
overflow: hidden;
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
/* completeDisplay: "card" — once the block collapses to the compact reference
|
|
3356
|
+
card it keeps the same root (updater keying + theme zone survive) but must
|
|
3357
|
+
drop the inline frame styling, since the nested card carries its own border,
|
|
3358
|
+
background, and radius. overflow: visible so the card's focus outline (which
|
|
3359
|
+
uses outline-offset) isn't clipped. */
|
|
3360
|
+
[data-persona-root] .persona-artifact-inline.persona-artifact-inline--card {
|
|
3361
|
+
border: none;
|
|
3362
|
+
background: transparent;
|
|
3363
|
+
border-radius: 0;
|
|
3364
|
+
overflow: visible;
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
/* Title/toolbar chrome bar: flush to the frame edge (no frame padding). */
|
|
3368
|
+
[data-persona-root] .persona-artifact-inline-chrome {
|
|
3369
|
+
display: flex;
|
|
3370
|
+
align-items: center;
|
|
3371
|
+
gap: 0.5rem;
|
|
3372
|
+
padding: 0.5rem 0.75rem;
|
|
3373
|
+
background: var(--persona-artifact-inline-chrome-bg, var(--persona-surface, #ffffff));
|
|
3374
|
+
border-bottom: 1px solid var(--persona-artifact-inline-chrome-border, var(--persona-border, #e5e7eb));
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
/* Leading cluster: file icon + title + type label / streaming status. */
|
|
3378
|
+
[data-persona-root] .persona-artifact-inline-chrome-lead {
|
|
3379
|
+
display: flex;
|
|
3380
|
+
align-items: center;
|
|
3381
|
+
gap: 0.5rem;
|
|
3382
|
+
min-width: 0;
|
|
3383
|
+
flex: 1 1 auto;
|
|
3384
|
+
color: var(--persona-artifact-inline-title-color, var(--persona-text, #111827));
|
|
3385
|
+
font-size: 0.8125rem;
|
|
3386
|
+
font-weight: 500;
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
[data-persona-root] .persona-artifact-inline-chrome-lead .persona-artifact-inline-type,
|
|
3390
|
+
[data-persona-root] .persona-artifact-inline-chrome-lead .persona-artifact-inline-status {
|
|
3391
|
+
color: var(--persona-artifact-inline-muted-color, var(--persona-text-muted, #6b7280));
|
|
3392
|
+
font-weight: 400;
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
/* Streaming status: animated label span + optional plain detail span (live
|
|
3396
|
+
counters). The label carries the loading animation; the detail updates freely
|
|
3397
|
+
per delta and stays un-animated. Shared by the card, the inline chrome, and
|
|
3398
|
+
the inline status body (features.artifacts.statusLabel). Keep the status span
|
|
3399
|
+
from blowing out the chrome bar when a long detail streams in. */
|
|
3400
|
+
[data-persona-root] .persona-artifact-inline-chrome-lead .persona-artifact-inline-status {
|
|
3401
|
+
min-width: 0;
|
|
3402
|
+
overflow: hidden;
|
|
3403
|
+
white-space: nowrap;
|
|
3404
|
+
text-overflow: ellipsis;
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
[data-persona-root] .persona-artifact-status-detail {
|
|
3408
|
+
color: var(--persona-artifact-inline-muted-color, var(--persona-text-muted, #6b7280));
|
|
3409
|
+
margin-left: 0.375rem;
|
|
3410
|
+
font-variant-numeric: tabular-nums;
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
/* Trailing cluster: custom inlineActions, copy, expand. */
|
|
3414
|
+
[data-persona-root] .persona-artifact-inline-chrome-actions {
|
|
3415
|
+
display: flex;
|
|
3416
|
+
align-items: center;
|
|
3417
|
+
gap: 0.25rem;
|
|
3418
|
+
flex: 0 0 auto;
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
|
+
/* Body wraps the chrome-free preview; padding lives here so the chrome sits
|
|
3422
|
+
flush to the frame edge. */
|
|
3423
|
+
[data-persona-root] .persona-artifact-inline-body {
|
|
3424
|
+
padding: 0.75rem;
|
|
3425
|
+
}
|
|
3426
|
+
|
|
3427
|
+
/* The preview frame (and its 100%-height iframe) is height: 100%, which
|
|
3428
|
+
collapses inside the auto-height inline block; pin a themeable fixed height on
|
|
3429
|
+
the frame instead. Height var chain: inlineBody.height
|
|
3430
|
+
(--persona-artifact-inline-body-height, set per state by artifact-inline.ts) →
|
|
3431
|
+
the legacy --persona-artifact-inline-frame-height override → 320px. The legacy
|
|
3432
|
+
var still wins when the new one is unset (inlineBody.height "auto"), so themes
|
|
3433
|
+
pinned to it keep working. The --sized rule below (equal specificity, declared
|
|
3434
|
+
later) overrides this to 100% when the body wrapper owns the height. */
|
|
3435
|
+
[data-persona-root] .persona-artifact-inline .persona-artifact-frame {
|
|
3436
|
+
height: var(
|
|
3437
|
+
--persona-artifact-inline-body-height,
|
|
3438
|
+
var(--persona-artifact-inline-frame-height, 320px)
|
|
3439
|
+
);
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
/* Inline body height model (features.artifacts.inlineBody). The block root sets
|
|
3443
|
+
--persona-artifact-inline-body-height (px) for the current state; leaving it
|
|
3444
|
+
unset (inlineBody.height "auto") lets the body size to content and the iframe
|
|
3445
|
+
fall back through the chain above. */
|
|
3446
|
+
|
|
3447
|
+
/* Code bodies are full-bleed, matching the pane's source-view treatment (same
|
|
3448
|
+
class the pane toggles): the line-number gutter sits flush against the frame
|
|
3449
|
+
edge. Declared after .persona-artifact-inline-body so padding: 0 wins the
|
|
3450
|
+
specificity tie. */
|
|
3451
|
+
[data-persona-root] .persona-artifact-inline-body.persona-artifact-content-flush {
|
|
3452
|
+
padding: 0;
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
/* Numeric inlineBody.height: the body wrapper owns the reserved height
|
|
3456
|
+
(border-box), so flush code, padded iframe, and padded status bodies all
|
|
3457
|
+
occupy the same outer box and every state swap is layout neutral. Fill-capable
|
|
3458
|
+
content stretches to the wrapper. */
|
|
3459
|
+
[data-persona-root] .persona-artifact-inline-body--sized {
|
|
3460
|
+
height: var(--persona-artifact-inline-body-height, auto);
|
|
3461
|
+
}
|
|
3462
|
+
[data-persona-root] .persona-artifact-inline-body--sized .persona-artifact-source-window--fixed,
|
|
3463
|
+
[data-persona-root] .persona-artifact-inline-body--sized .persona-artifact-frame {
|
|
3464
|
+
height: 100%;
|
|
3465
|
+
}
|
|
3466
|
+
[data-persona-root] .persona-artifact-inline-body--sized .persona-artifact-status-view {
|
|
3467
|
+
min-height: 100%;
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3470
|
+
/* Fixed-height streaming source window: a reserved scroll viewport so streamed
|
|
3471
|
+
source no longer grows an unbounded <pre> and then snaps to the preview. The
|
|
3472
|
+
height comes from the sized body wrapper above (the --fixed class is only
|
|
3473
|
+
ever applied together with it). The bare (non-fixed) window is an inert
|
|
3474
|
+
wrapper (pane path never adds it; the source <pre> sits directly on el
|
|
3475
|
+
there). */
|
|
3476
|
+
[data-persona-root] .persona-artifact-source-window {
|
|
3477
|
+
min-width: 0;
|
|
3478
|
+
}
|
|
3479
|
+
[data-persona-root] .persona-artifact-source-window--fixed {
|
|
3480
|
+
overflow-y: auto;
|
|
3481
|
+
}
|
|
3482
|
+
|
|
3483
|
+
/* Clipped preview window (inlineBody.overflow: "clip"): a fixed-height window
|
|
3484
|
+
showing the top of the document with no internal scroll. Applied together with
|
|
3485
|
+
--fixed (which supplies the reserved height via the --sized body wrapper and
|
|
3486
|
+
the fill-capable detection in artifact-inline.ts); declared after --fixed so
|
|
3487
|
+
this overflow: hidden wins its overflow-y: auto on the specificity tie. */
|
|
3488
|
+
[data-persona-root] .persona-artifact-source-window--clip {
|
|
3489
|
+
overflow: hidden;
|
|
3490
|
+
}
|
|
3491
|
+
|
|
3492
|
+
/* Edge fade masks on the fixed window (top fade signals content clipped above).
|
|
3493
|
+
mask-image works over any themed background; size via --persona-artifact-fade-size
|
|
3494
|
+
(defaults to 40px). */
|
|
3495
|
+
[data-persona-root]
|
|
3496
|
+
.persona-artifact-fade-top:not(.persona-artifact-fade-bottom) {
|
|
3497
|
+
-webkit-mask-image: linear-gradient(
|
|
3498
|
+
to bottom,
|
|
3499
|
+
transparent 0,
|
|
3500
|
+
#000 var(--persona-artifact-fade-size, 40px)
|
|
3501
|
+
);
|
|
3502
|
+
mask-image: linear-gradient(
|
|
3503
|
+
to bottom,
|
|
3504
|
+
transparent 0,
|
|
3505
|
+
#000 var(--persona-artifact-fade-size, 40px)
|
|
3506
|
+
);
|
|
3507
|
+
}
|
|
3508
|
+
[data-persona-root]
|
|
3509
|
+
.persona-artifact-fade-bottom:not(.persona-artifact-fade-top) {
|
|
3510
|
+
-webkit-mask-image: linear-gradient(
|
|
3511
|
+
to top,
|
|
3512
|
+
transparent 0,
|
|
3513
|
+
#000 var(--persona-artifact-fade-size, 40px)
|
|
3514
|
+
);
|
|
3515
|
+
mask-image: linear-gradient(
|
|
3516
|
+
to top,
|
|
3517
|
+
transparent 0,
|
|
3518
|
+
#000 var(--persona-artifact-fade-size, 40px)
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
[data-persona-root]
|
|
3522
|
+
.persona-artifact-fade-top.persona-artifact-fade-bottom {
|
|
3523
|
+
-webkit-mask-image: linear-gradient(
|
|
3524
|
+
to bottom,
|
|
3525
|
+
transparent 0,
|
|
3526
|
+
#000 var(--persona-artifact-fade-size, 40px),
|
|
3527
|
+
#000 calc(100% - var(--persona-artifact-fade-size, 40px)),
|
|
3528
|
+
transparent 100%
|
|
3529
|
+
);
|
|
3530
|
+
mask-image: linear-gradient(
|
|
3531
|
+
to bottom,
|
|
3532
|
+
transparent 0,
|
|
3533
|
+
#000 var(--persona-artifact-fade-size, 40px),
|
|
3534
|
+
#000 calc(100% - var(--persona-artifact-fade-size, 40px)),
|
|
3535
|
+
transparent 100%
|
|
3536
|
+
);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
/* Edge fade on the horizontally scrollable tab strip. Visual hint only; the
|
|
3540
|
+
tablist keyboard behavior is the real affordance. Sized via
|
|
3541
|
+
--persona-artifact-tab-fade-size (default 24px). */
|
|
3542
|
+
[data-persona-root]
|
|
3543
|
+
.persona-artifact-tab-fade-start:not(.persona-artifact-tab-fade-end) {
|
|
3544
|
+
-webkit-mask-image: linear-gradient(
|
|
3545
|
+
to right,
|
|
3546
|
+
transparent 0,
|
|
3547
|
+
#000 var(--persona-artifact-tab-fade-size, 24px)
|
|
3548
|
+
);
|
|
3549
|
+
mask-image: linear-gradient(
|
|
3550
|
+
to right,
|
|
3551
|
+
transparent 0,
|
|
3552
|
+
#000 var(--persona-artifact-tab-fade-size, 24px)
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3555
|
+
[data-persona-root]
|
|
3556
|
+
.persona-artifact-tab-fade-end:not(.persona-artifact-tab-fade-start) {
|
|
3557
|
+
-webkit-mask-image: linear-gradient(
|
|
3558
|
+
to left,
|
|
3559
|
+
transparent 0,
|
|
3560
|
+
#000 var(--persona-artifact-tab-fade-size, 24px)
|
|
3561
|
+
);
|
|
3562
|
+
mask-image: linear-gradient(
|
|
3563
|
+
to left,
|
|
3564
|
+
transparent 0,
|
|
3565
|
+
#000 var(--persona-artifact-tab-fade-size, 24px)
|
|
3566
|
+
);
|
|
3567
|
+
}
|
|
3568
|
+
[data-persona-root]
|
|
3569
|
+
.persona-artifact-tab-fade-start.persona-artifact-tab-fade-end {
|
|
3570
|
+
-webkit-mask-image: linear-gradient(
|
|
3571
|
+
to right,
|
|
3572
|
+
transparent 0,
|
|
3573
|
+
#000 var(--persona-artifact-tab-fade-size, 24px),
|
|
3574
|
+
#000 calc(100% - var(--persona-artifact-tab-fade-size, 24px)),
|
|
3575
|
+
transparent 100%
|
|
3576
|
+
);
|
|
3577
|
+
mask-image: linear-gradient(
|
|
3578
|
+
to right,
|
|
3579
|
+
transparent 0,
|
|
3580
|
+
#000 var(--persona-artifact-tab-fade-size, 24px),
|
|
3581
|
+
#000 calc(100% - var(--persona-artifact-tab-fade-size, 24px)),
|
|
3582
|
+
transparent 100%
|
|
3583
|
+
);
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3586
|
+
/* Reserved-height status placeholder (inlineBody.streamingView: "status").
|
|
3587
|
+
Numeric height reserves the var; "auto" falls back to a modest 160px min-height
|
|
3588
|
+
so the card doesn't collapse. */
|
|
3589
|
+
[data-persona-root] .persona-artifact-status-view {
|
|
3590
|
+
display: flex;
|
|
3591
|
+
align-items: center;
|
|
3592
|
+
justify-content: center;
|
|
3593
|
+
min-height: var(--persona-artifact-inline-body-height, 160px);
|
|
3594
|
+
}
|
|
3595
|
+
|
|
3596
|
+
/* Complete-state height cap for non-iframe bodies (rendered markdown, source
|
|
3597
|
+
view, component). The iframe path is sized by the iframe rule above instead,
|
|
3598
|
+
so this class is only applied when the completed body has no iframe. */
|
|
3599
|
+
[data-persona-root] .persona-artifact-inline-body--cap {
|
|
3600
|
+
max-height: var(--persona-artifact-inline-body-height, none);
|
|
3601
|
+
overflow-y: auto;
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3027
3604
|
[data-persona-root] .persona-artifact-pane {
|
|
3028
3605
|
border-radius: var(--persona-artifact-pane-radius, 0);
|
|
3029
3606
|
overflow: hidden;
|
|
@@ -3072,23 +3649,71 @@
|
|
|
3072
3649
|
border: var(--persona-artifact-pane-border) !important;
|
|
3073
3650
|
}
|
|
3074
3651
|
|
|
3652
|
+
/* paneAppearance: 'detached': floating card with gap, all-side border, radius, elevation, canvas behind */
|
|
3653
|
+
/* Split gap defaults to --persona-panel-inset from ui.ts; canvas paints behind both columns. */
|
|
3654
|
+
[data-persona-root].persona-artifact-appearance-detached .persona-artifact-split-root {
|
|
3655
|
+
background: var(--persona-panel-canvas-bg);
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3658
|
+
/* Desktop split only (drawer keeps its own chrome). Non-!important so explicit
|
|
3659
|
+
paneBorder / paneShadow / paneBorderRadius overrides still win. */
|
|
3660
|
+
@media (min-width: 641px) {
|
|
3661
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-appearance-detached .persona-artifact-pane {
|
|
3662
|
+
border-radius: var(
|
|
3663
|
+
--persona-artifact-pane-radius,
|
|
3664
|
+
var(--persona-panel-radius, var(--persona-radius-xl, 0.75rem))
|
|
3665
|
+
);
|
|
3666
|
+
border: var(--persona-panel-border, 1px solid var(--persona-border, #e5e7eb));
|
|
3667
|
+
box-shadow: var(
|
|
3668
|
+
--persona-artifact-pane-shadow,
|
|
3669
|
+
var(--persona-panel-shadow, var(--persona-palette-shadows-xl, 0 25px 50px -12px rgba(0, 0, 0, 0.25)))
|
|
3670
|
+
);
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
/* chatSurface: 'flush': chat is flat flush background, only the pane floats. The
|
|
3675
|
+
chat has no perimeter inset, so inset the pane on 3 sides (left gap comes from
|
|
3676
|
+
the existing detached split flex gap). Keeps the pane's border/radius/shadow. */
|
|
3677
|
+
@media (min-width: 641px) {
|
|
3678
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-chat-flush .persona-artifact-pane {
|
|
3679
|
+
margin-top: var(--persona-panel-inset);
|
|
3680
|
+
margin-right: var(--persona-panel-inset);
|
|
3681
|
+
margin-bottom: var(--persona-panel-inset);
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3075
3685
|
/*
|
|
3076
|
-
*
|
|
3077
|
-
*
|
|
3686
|
+
* Welded split chrome (panel + seamless): one card. The outer panel carries the
|
|
3687
|
+
* border + radius + shadow (set in ui.ts); each column rounds only its outer
|
|
3688
|
+
* corners and clips, so the columns fill the panel's rounded rect and butt flush
|
|
3689
|
+
* at the seam. Desktop split only (narrowed via :not(.narrow-host) + breakpoint).
|
|
3690
|
+
* Toggled from ui.ts by splitChromeMode(); the pane's flex layout owns gap 0.
|
|
3078
3691
|
*/
|
|
3079
3692
|
@media (min-width: 641px) {
|
|
3080
|
-
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-
|
|
3693
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-welded-split .persona-artifact-split-root {
|
|
3694
|
+
position: relative;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-welded-split .persona-widget-container {
|
|
3081
3698
|
border-top-right-radius: 0 !important;
|
|
3082
3699
|
border-bottom-right-radius: 0 !important;
|
|
3700
|
+
overflow: hidden;
|
|
3083
3701
|
}
|
|
3084
3702
|
|
|
3085
|
-
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-
|
|
3703
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-welded-split .persona-artifact-pane {
|
|
3086
3704
|
border-top-left-radius: 0 !important;
|
|
3087
3705
|
border-bottom-left-radius: 0 !important;
|
|
3088
|
-
border-top-right-radius: var(--persona-artifact-
|
|
3089
|
-
border-bottom-right-radius: var(--persona-artifact-
|
|
3706
|
+
border-top-right-radius: var(--persona-artifact-welded-outer-radius, var(--persona-panel-radius, var(--persona-radius-xl, 0.75rem))) !important;
|
|
3707
|
+
border-bottom-right-radius: var(--persona-artifact-welded-outer-radius, var(--persona-panel-radius, var(--persona-radius-xl, 0.75rem))) !important;
|
|
3090
3708
|
overflow: hidden;
|
|
3091
3709
|
}
|
|
3710
|
+
|
|
3711
|
+
/* panel appearance: a hairline divider on the pane's chat-facing edge. seamless
|
|
3712
|
+
omits it (it already zeroes border-left). Non-!important so paneBorder /
|
|
3713
|
+
paneBorderLeft overrides win. */
|
|
3714
|
+
[data-persona-root]:not(.persona-artifact-narrow-host).persona-artifact-welded-split.persona-artifact-appearance-panel .persona-artifact-pane {
|
|
3715
|
+
border-left: 1px solid var(--persona-border, #e5e7eb);
|
|
3716
|
+
}
|
|
3092
3717
|
}
|
|
3093
3718
|
|
|
3094
3719
|
/* Narrow floating panel: drawer inside panel (class toggled by JS from panel width) */
|
|
@@ -3789,6 +4414,20 @@
|
|
|
3789
4414
|
gap: 8px;
|
|
3790
4415
|
}
|
|
3791
4416
|
|
|
4417
|
+
/* Configured / agent-pushed suggestion chips belong to the expanded
|
|
4418
|
+
* conversation surface, not the always-on collapsed composer. Keeping the
|
|
4419
|
+
* row in pillRoot lets it sit directly above the textarea without re-entering
|
|
4420
|
+
* the transcript's scrolling region. */
|
|
4421
|
+
.persona-widget-pill-root[data-state="collapsed"] [data-persona-composer-suggestions] {
|
|
4422
|
+
display: none;
|
|
4423
|
+
}
|
|
4424
|
+
|
|
4425
|
+
.persona-widget-pill-root[data-state="expanded"] [data-persona-composer-suggestions] {
|
|
4426
|
+
display: flex;
|
|
4427
|
+
justify-content: center;
|
|
4428
|
+
margin: 0 8px 4px;
|
|
4429
|
+
}
|
|
4430
|
+
|
|
3792
4431
|
/* Attachment previews row (above the pill). AttachmentManager toggles
|
|
3793
4432
|
* display:flex when items are added; default is display:none. */
|
|
3794
4433
|
.persona-pill-composer__previews {
|
|
@@ -4039,3 +4678,214 @@
|
|
|
4039
4678
|
display: none;
|
|
4040
4679
|
}
|
|
4041
4680
|
}
|
|
4681
|
+
|
|
4682
|
+
/* ===========================================================================
|
|
4683
|
+
* Context mentions (composer @-mentions): chip row, menu, affordance button.
|
|
4684
|
+
* Tokens default off the existing palette vars so themed widgets pick them up.
|
|
4685
|
+
* =========================================================================== */
|
|
4686
|
+
|
|
4687
|
+
/* Composer size-query container. Both the full and pill composers carry
|
|
4688
|
+
* `data-persona-composer-form`; establishing a container here lets a host
|
|
4689
|
+
* stylesheet make composer controls responsive to the PANEL width rather than
|
|
4690
|
+
* the viewport — correct across floating / docked / fullscreen, where the
|
|
4691
|
+
* composer is frequently narrower than the screen. Safe: the form is block-level
|
|
4692
|
+
* and already sized by its parent, so inline-size containment doesn't change its
|
|
4693
|
+
* width, and the ask sheet + mention menu mount OUTSIDE the form, so layout
|
|
4694
|
+
* containment can't capture them. Query with `@container persona-composer (...)`;
|
|
4695
|
+
* `.persona-mention-button` is a supported, stable hook. */
|
|
4696
|
+
[data-persona-composer-form] {
|
|
4697
|
+
container-type: inline-size;
|
|
4698
|
+
container-name: persona-composer;
|
|
4699
|
+
}
|
|
4700
|
+
|
|
4701
|
+
.persona-mention-context-row {
|
|
4702
|
+
display: none; /* toggled to flex by the manager when chips exist */
|
|
4703
|
+
flex-wrap: wrap;
|
|
4704
|
+
gap: var(--persona-mention-chip-gap, 6px);
|
|
4705
|
+
margin-bottom: var(--persona-mention-row-gap, 8px);
|
|
4706
|
+
}
|
|
4707
|
+
|
|
4708
|
+
.persona-mention-chip {
|
|
4709
|
+
display: inline-flex;
|
|
4710
|
+
align-items: center;
|
|
4711
|
+
gap: 5px;
|
|
4712
|
+
height: var(--persona-mention-chip-height, 26px);
|
|
4713
|
+
padding: 0 6px 0 8px;
|
|
4714
|
+
border-radius: var(--persona-mention-chip-radius, 6px);
|
|
4715
|
+
background: var(--persona-mention-chip-bg, var(--persona-container, #f3f4f6));
|
|
4716
|
+
border: 1px solid var(--persona-mention-chip-border, var(--persona-border, #e5e7eb));
|
|
4717
|
+
color: var(--persona-mention-chip-fg, var(--persona-text, #111827));
|
|
4718
|
+
font-size: var(--persona-mention-chip-font-size, 12px);
|
|
4719
|
+
line-height: 1;
|
|
4720
|
+
max-width: 220px;
|
|
4721
|
+
}
|
|
4722
|
+
|
|
4723
|
+
.persona-mention-chip[data-status="error"] {
|
|
4724
|
+
border-color: var(--persona-mention-error, #dc2626);
|
|
4725
|
+
color: var(--persona-mention-error, #dc2626);
|
|
4726
|
+
}
|
|
4727
|
+
|
|
4728
|
+
.persona-mention-chip-icon {
|
|
4729
|
+
display: inline-flex;
|
|
4730
|
+
align-items: center;
|
|
4731
|
+
flex: 0 0 auto;
|
|
4732
|
+
opacity: 0.8;
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
.persona-mention-chip-label {
|
|
4736
|
+
overflow: hidden;
|
|
4737
|
+
text-overflow: ellipsis;
|
|
4738
|
+
white-space: nowrap;
|
|
4739
|
+
}
|
|
4740
|
+
|
|
4741
|
+
.persona-mention-chip-spinner {
|
|
4742
|
+
flex: 0 0 auto;
|
|
4743
|
+
width: 12px;
|
|
4744
|
+
height: 12px;
|
|
4745
|
+
border-radius: 50%;
|
|
4746
|
+
border: 2px solid var(--persona-mention-chip-border, var(--persona-border, #d1d5db));
|
|
4747
|
+
border-top-color: var(--persona-mention-accent, var(--persona-accent, #0f0f0f));
|
|
4748
|
+
animation: persona-mention-spin 0.7s linear infinite;
|
|
4749
|
+
}
|
|
4750
|
+
|
|
4751
|
+
@keyframes persona-mention-spin {
|
|
4752
|
+
to {
|
|
4753
|
+
transform: rotate(360deg);
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4756
|
+
|
|
4757
|
+
.persona-mention-chip-remove {
|
|
4758
|
+
display: inline-flex;
|
|
4759
|
+
align-items: center;
|
|
4760
|
+
justify-content: center;
|
|
4761
|
+
flex: 0 0 auto;
|
|
4762
|
+
width: 16px;
|
|
4763
|
+
height: 16px;
|
|
4764
|
+
padding: 0;
|
|
4765
|
+
border: none;
|
|
4766
|
+
border-radius: 4px;
|
|
4767
|
+
background: transparent;
|
|
4768
|
+
color: inherit;
|
|
4769
|
+
opacity: 0.6;
|
|
4770
|
+
cursor: pointer;
|
|
4771
|
+
transition: opacity 0.15s ease, background-color 0.15s ease;
|
|
4772
|
+
}
|
|
4773
|
+
|
|
4774
|
+
.persona-mention-chip-remove:hover {
|
|
4775
|
+
opacity: 1;
|
|
4776
|
+
background: var(--persona-palette-colors-black-alpha-50, rgba(0, 0, 0, 0.06));
|
|
4777
|
+
}
|
|
4778
|
+
|
|
4779
|
+
/* The mention MENU CSS (.persona-mention-menu / -list / -search / -group /
|
|
4780
|
+
* -option / -status / -error / -retry and its coarse-pointer row sizing) lives
|
|
4781
|
+
* in the lazy context-mentions chunk (src/styles/context-mention-menu-css.ts)
|
|
4782
|
+
* and is injected on first menu open — so it also styles the body-mounted menu
|
|
4783
|
+
* inside a useShadowDom widget. Only the eagerly-rendered chip / context-row
|
|
4784
|
+
* pieces stay here. */
|
|
4785
|
+
|
|
4786
|
+
.persona-mention-chip-readonly {
|
|
4787
|
+
padding-right: 8px;
|
|
4788
|
+
cursor: default;
|
|
4789
|
+
}
|
|
4790
|
+
|
|
4791
|
+
/* Inline mention token (display: "inline"). Atomic styled chip that sits INSIDE
|
|
4792
|
+
* the sentence — in the contenteditable composer and in the read-only sent
|
|
4793
|
+
* bubble. Kept in the core stylesheet (tiny) so tokens are styled the instant a
|
|
4794
|
+
* segmented bubble renders, without waiting on the inline chunk's CSS. */
|
|
4795
|
+
.persona-mention-token {
|
|
4796
|
+
/* Per-token accent — set inline from `ref.color`, per source via
|
|
4797
|
+
* `.persona-mention-token[data-mention-source="…"]`, or globally by overriding
|
|
4798
|
+
* this var. Recolors the whole pill (tint bg + icon + label). */
|
|
4799
|
+
--persona-mention-token-accent: var(--persona-accent, #4338ca);
|
|
4800
|
+
display: inline-flex;
|
|
4801
|
+
align-items: center;
|
|
4802
|
+
gap: var(--persona-mention-token-gap, 4px);
|
|
4803
|
+
padding: var(--persona-mention-token-padding, 1px 6px);
|
|
4804
|
+
border-radius: var(--persona-mention-token-radius, 6px);
|
|
4805
|
+
/* Fallback flat tint first (older browsers), then a per-accent translucent
|
|
4806
|
+
* tint via color-mix so each type reads as its own color (Slack/Cursor). */
|
|
4807
|
+
background: var(--persona-mention-token-bg, #eef2ff);
|
|
4808
|
+
background: var(
|
|
4809
|
+
--persona-mention-token-bg,
|
|
4810
|
+
color-mix(in srgb, var(--persona-mention-token-accent) 14%, transparent)
|
|
4811
|
+
);
|
|
4812
|
+
color: var(--persona-mention-token-fg, var(--persona-mention-token-accent));
|
|
4813
|
+
font-size: var(--persona-mention-token-font-size, 0.95em);
|
|
4814
|
+
font-weight: var(--persona-mention-token-font-weight, 550);
|
|
4815
|
+
line-height: 1.5;
|
|
4816
|
+
white-space: nowrap;
|
|
4817
|
+
vertical-align: baseline;
|
|
4818
|
+
user-select: none;
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
.persona-mention-token-icon {
|
|
4822
|
+
display: inline-flex;
|
|
4823
|
+
align-items: center;
|
|
4824
|
+
}
|
|
4825
|
+
|
|
4826
|
+
.persona-mention-token-label {
|
|
4827
|
+
white-space: nowrap;
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
/* Read-only token in a sent bubble: no editable affordances (the composer's
|
|
4831
|
+
* atomic caret/select behavior doesn't apply), so it reads as inert prose. */
|
|
4832
|
+
.persona-mention-token-readonly {
|
|
4833
|
+
cursor: default;
|
|
4834
|
+
user-select: text;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
/* Resolve failure on an inline token: recolor the pill to the danger accent and
|
|
4838
|
+
* add a subtle inset border ring, reusing the same accent custom-property the
|
|
4839
|
+
* token already themes on (so bg tint + icon + label all shift together). */
|
|
4840
|
+
.persona-mention-token-error {
|
|
4841
|
+
--persona-mention-token-accent: var(--persona-mention-error, #dc2626);
|
|
4842
|
+
box-shadow: inset 0 0 0 1px
|
|
4843
|
+
color-mix(in srgb, var(--persona-mention-token-accent) 45%, transparent);
|
|
4844
|
+
}
|
|
4845
|
+
|
|
4846
|
+
/* The contenteditable composer surface: behaves like the textarea it replaced. */
|
|
4847
|
+
.persona-composer-contenteditable {
|
|
4848
|
+
white-space: pre-wrap;
|
|
4849
|
+
overflow-wrap: anywhere;
|
|
4850
|
+
outline: none;
|
|
4851
|
+
max-height: var(--persona-composer-max-height, 200px);
|
|
4852
|
+
overflow-y: auto;
|
|
4853
|
+
}
|
|
4854
|
+
|
|
4855
|
+
.persona-composer-contenteditable:empty::before {
|
|
4856
|
+
content: attr(data-placeholder);
|
|
4857
|
+
color: var(--persona-placeholder, var(--persona-muted, #9ca3af));
|
|
4858
|
+
pointer-events: none;
|
|
4859
|
+
}
|
|
4860
|
+
|
|
4861
|
+
.persona-message-mentions {
|
|
4862
|
+
margin-top: 6px;
|
|
4863
|
+
margin-bottom: 0;
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4866
|
+
/* Touch targets: on coarse pointers (phones/tablets) grow the chip + its remove
|
|
4867
|
+
* control to the ~44px minimum. Desktop keeps the compact sizing above. (The
|
|
4868
|
+
* menu row / retry coarse sizing ships with the menu CSS in the lazy chunk.) */
|
|
4869
|
+
@media (pointer: coarse) {
|
|
4870
|
+
.persona-mention-chip {
|
|
4871
|
+
height: auto;
|
|
4872
|
+
min-height: 40px;
|
|
4873
|
+
}
|
|
4874
|
+
.persona-mention-chip-remove {
|
|
4875
|
+
width: 36px;
|
|
4876
|
+
height: 36px;
|
|
4877
|
+
margin-right: -6px; /* keep the visual gap tight while the hit area grows */
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
@media (prefers-reduced-motion: reduce) {
|
|
4882
|
+
/* No spin: show a static neutral ring instead of a rotating arc. */
|
|
4883
|
+
.persona-mention-chip-spinner {
|
|
4884
|
+
animation: none;
|
|
4885
|
+
border-top-color: var(
|
|
4886
|
+
--persona-mention-chip-border,
|
|
4887
|
+
var(--persona-border, #d1d5db)
|
|
4888
|
+
);
|
|
4889
|
+
opacity: 0.6;
|
|
4890
|
+
}
|
|
4891
|
+
}
|