anentrypoint-design 0.0.487 → 0.0.488
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 +2 -1
- package/chat.css +1 -1
- package/colors_and_type.css +22 -1
- package/community.css +3 -0
- package/dist/247420.css +474 -72
- package/dist/247420.js +24 -24
- package/package.json +1 -1
- package/src/components/content/fields.js +3 -1
- package/src/components/content/panel.js +1 -1
- package/src/components/files/chrome.js +5 -3
- package/src/components/overlay-primitives/floating.js +1 -0
- package/src/components/shell/workspace-columns.js +2 -0
- package/src/css/app-shell/base.css +22 -0
- package/src/css/app-shell/chat-polish.css +165 -0
- package/src/css/app-shell/files.css +39 -0
- package/src/css/app-shell/hero-content.css +13 -4
- package/src/css/app-shell/kits-appended.css +45 -7
- package/src/css/app-shell/loading-alerts.css +3 -1
- package/src/css/app-shell/panel-row.css +11 -1
- package/src/css/app-shell/primitives.css +48 -2
- package/src/css/app-shell/responsive2-workspace.css +24 -5
- package/src/css/app-shell/states-interactions.css +20 -34
- package/src/css/app-shell/topbar.css +47 -13
- package/src/kits/os/launcher.css +7 -0
- package/src/kits/os/theme.css +25 -1
- package/src/kits/os/validate.css +7 -0
- package/src/kits/os/wm.css +7 -0
- package/types/components.d.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.488",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -46,7 +46,9 @@ export function SearchInput({ value = '', placeholder = 'search…', onInput, on
|
|
|
46
46
|
// has no way to morph one element type into another in place - it produced
|
|
47
47
|
// a corrupted merged DOM node carrying attributes from both shapes.
|
|
48
48
|
return h('span', { key, class: 'ds-search-input-wrap' },
|
|
49
|
-
|
|
49
|
+
h('span', { key: 'fld', class: 'ds-search-field' },
|
|
50
|
+
h('span', { key: 'ic', class: 'ds-search-icon', 'aria-hidden': 'true' }, Icon('search', { size: 15 })),
|
|
51
|
+
input),
|
|
50
52
|
clearBtn,
|
|
51
53
|
resultCount != null ? h('span', { key: 'cnt', class: 'sr-only', role: 'status', 'aria-live': 'polite' }, resultCount) : null);
|
|
52
54
|
}
|
|
@@ -17,7 +17,7 @@ export function Panel({ title, count, right, style = '', class: className = '',
|
|
|
17
17
|
return h('div', { class: cls, style, ...(id ? { id } : {}) },
|
|
18
18
|
title != null ? h('div', { class: 'panel-head' },
|
|
19
19
|
h(headingTag, { class: 'panel-title' }, title),
|
|
20
|
-
right != null ? right : (count != null ? h('span', {}, String(count)) : null)
|
|
20
|
+
right != null ? right : (count != null ? h('span', { class: 'ds-badge' }, String(count)) : null)
|
|
21
21
|
) : null,
|
|
22
22
|
h('div', { class: 'panel-body' }, ...(Array.isArray(children) ? children : [children]))
|
|
23
23
|
);
|
|
@@ -48,14 +48,16 @@ export function RootsPicker({ roots = [], selected, onSelect, label = 'roots' }
|
|
|
48
48
|
}, r.label || r.id)));
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export function DropZone({ children, dragover, onDrop, onDragOver, onDragLeave, label = 'drop files here', onPick } = {}) {
|
|
51
|
+
export function DropZone({ children, dragover, rejected, onDrop, onDragOver, onDragLeave, label = 'drop files here', onPick } = {}) {
|
|
52
52
|
// With children the zone is a passive WRAPPER: content renders normally and
|
|
53
53
|
// the dashed affordance appears only while a drag is over it (real file
|
|
54
54
|
// managers never burn a permanent band on a maybe-drop). Without children
|
|
55
|
-
// it keeps the explicit picker-block look.
|
|
55
|
+
// it keeps the explicit picker-block look. `rejected` lets the host flag a
|
|
56
|
+
// drag whose payload fails a type/size guard with a distinct treatment
|
|
57
|
+
// (.rejected) instead of the normal accept-toned .dragover.
|
|
56
58
|
const kids = Array.isArray(children) ? children : children ? [children] : [];
|
|
57
59
|
return h('div', {
|
|
58
|
-
class: 'ds-dropzone' + (kids.length ? ' ds-dropzone--wrap' : '') + (dragover ? ' dragover' : ''),
|
|
60
|
+
class: 'ds-dropzone' + (kids.length ? ' ds-dropzone--wrap' : '') + (dragover ? ' dragover' : '') + (rejected ? ' rejected' : ''),
|
|
59
61
|
ondragover: (e) => { e.preventDefault(); onDragOver && onDragOver(e); },
|
|
60
62
|
ondragleave: (e) => { if (!e.currentTarget.contains(e.relatedTarget)) { onDragLeave && onDragLeave(e); } },
|
|
61
63
|
ondrop: (e) => { e.preventDefault(); onDrop && onDrop(e.dataTransfer.files); }
|
|
@@ -45,6 +45,7 @@ export function useFloating(anchorEl, contentEl, { placement = 'bottom-start', o
|
|
|
45
45
|
contentEl.style.left = x + 'px';
|
|
46
46
|
contentEl.style.top = y + 'px';
|
|
47
47
|
finalPlacement = s + '-' + align;
|
|
48
|
+
contentEl.setAttribute('data-placement', finalPlacement);
|
|
48
49
|
};
|
|
49
50
|
compute();
|
|
50
51
|
const cb = () => compute();
|
|
@@ -88,12 +88,14 @@ export function WsResizer(col) {
|
|
|
88
88
|
const onDown = (e) => {
|
|
89
89
|
e.preventDefault();
|
|
90
90
|
const handleEl = e.currentTarget;
|
|
91
|
+
handleEl.classList.add('ws-resizer-active');
|
|
91
92
|
let lastX = e.clientX;
|
|
92
93
|
const move = (ev) => { const dx = ev.clientX - lastX; lastX = ev.clientX; wsResize(col, dx, false, handleEl); };
|
|
93
94
|
const up = () => {
|
|
94
95
|
document.removeEventListener('pointermove', move);
|
|
95
96
|
document.removeEventListener('pointerup', up);
|
|
96
97
|
document.body.style.cursor = '';
|
|
98
|
+
handleEl.classList.remove('ws-resizer-active');
|
|
97
99
|
wsResize(col, 0, true, handleEl); // commit the settled width once
|
|
98
100
|
};
|
|
99
101
|
document.addEventListener('pointermove', move);
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
html, body { margin: 0; padding: 0; }
|
|
3
3
|
button, input, select, textarea { font: inherit; }
|
|
4
4
|
|
|
5
|
+
/* Global reduced-motion safety net: catches any component transition/animation
|
|
6
|
+
that lacks its own per-file prefers-reduced-motion override (most components
|
|
7
|
+
already opt out locally; this is the backstop for the rest, e.g.
|
|
8
|
+
plugins-config.css, catalog-theme.css, sidebar-misc.css, row-print.css,
|
|
9
|
+
topbar.css, primitives.css, git-status.css, panel-row.css). Scroll-snap
|
|
10
|
+
carousels handle scroll-behavior themselves and are unaffected. */
|
|
11
|
+
@media (prefers-reduced-motion: reduce) {
|
|
12
|
+
*, *::before, *::after {
|
|
13
|
+
animation-duration: 0.001ms !important;
|
|
14
|
+
animation-iteration-count: 1 !important;
|
|
15
|
+
transition-duration: 0.001ms !important;
|
|
16
|
+
scroll-behavior: auto !important;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
5
20
|
.skip-link {
|
|
6
21
|
--skip-link-preflight-translate-clear: -100%;
|
|
7
22
|
position: absolute;
|
|
@@ -193,6 +208,13 @@ a.ds-link-accent, .ds-prose a {
|
|
|
193
208
|
text-underline-offset: 4px;
|
|
194
209
|
text-decoration-thickness: 2px;
|
|
195
210
|
}
|
|
211
|
+
/* Visited state was entirely absent -- a returning user had no way to tell an
|
|
212
|
+
already-read link from an unread one, the one link state browsers don't
|
|
213
|
+
fake for you. --purple-2 keeps it distinct from both the unvisited accent
|
|
214
|
+
and any hover/danger tone already in the palette. */
|
|
215
|
+
a.ds-link-accent:visited, .ds-prose a:visited {
|
|
216
|
+
color: var(--purple-2);
|
|
217
|
+
}
|
|
196
218
|
a.ds-link-accent:hover, .ds-prose a:hover {
|
|
197
219
|
background: var(--accent); color: var(--accent-fg); text-decoration-color: transparent;
|
|
198
220
|
}
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
text-transform: lowercase; letter-spacing: 0.02em; user-select: none;
|
|
60
60
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
61
61
|
position: relative;
|
|
62
|
+
box-shadow: inset 0 0 0 1px var(--rule);
|
|
62
63
|
}
|
|
63
64
|
.chat-msg:hover .chat-avatar { transform: scale(1.03); box-shadow: 0 1px 4px color-mix(in oklab, var(--fg) 6%, transparent); }
|
|
64
65
|
.chat-msg.you .chat-avatar {
|
|
@@ -100,6 +101,13 @@
|
|
|
100
101
|
min-width: 0;
|
|
101
102
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
102
103
|
}
|
|
104
|
+
/* Tail corner: the bubble edge nearest its own avatar (bottom-left for
|
|
105
|
+
'them', bottom-right for 'you') squares off slightly, matching bubble
|
|
106
|
+
position to the sender's avatar the way a speech-bubble tail would — a
|
|
107
|
+
consistent radius on all four corners reads as a generic card, not a
|
|
108
|
+
turn in a conversation. */
|
|
109
|
+
.chat-msg:not(.you) .chat-bubble { border-bottom-left-radius: var(--r-0); }
|
|
110
|
+
.chat-msg.you .chat-bubble { border-bottom-right-radius: var(--r-0); }
|
|
103
111
|
.chat-msg:hover .chat-bubble { transform: translateY(-1px); box-shadow: 0 2px 8px color-mix(in oklab, var(--fg) 6%, transparent); transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease); }
|
|
104
112
|
/* Own bubble — calm tinted lead, not a full electric fill (chat stays readable). */
|
|
105
113
|
.chat-msg.you .chat-bubble { background: var(--accent-tint); color: var(--fg); }
|
|
@@ -538,3 +546,160 @@
|
|
|
538
546
|
fell back to the paper tone at 3.13:1 on ink. */
|
|
539
547
|
.aicat-meta .name { color: var(--mascot-deep, var(--mascot)); font-weight: 600; }
|
|
540
548
|
|
|
549
|
+
/* ============================================================
|
|
550
|
+
Composer attachment-detected badge, context line, hint, toolbar,
|
|
551
|
+
note strip, elapsed counter, dragover state — all referenced from
|
|
552
|
+
composer.js / composer-affordances.js but previously had no CSS at
|
|
553
|
+
all (unstyled DOM nodes / plain text falling through to block
|
|
554
|
+
defaults).
|
|
555
|
+
============================================================ */
|
|
556
|
+
.chat-composer-context {
|
|
557
|
+
display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1);
|
|
558
|
+
width: 100%; order: -1;
|
|
559
|
+
padding: var(--space-1) var(--space-1) 0;
|
|
560
|
+
font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3);
|
|
561
|
+
letter-spacing: 0.01em;
|
|
562
|
+
}
|
|
563
|
+
button.chat-composer-context {
|
|
564
|
+
background: transparent; border: 0; cursor: pointer; text-align: left;
|
|
565
|
+
border-radius: var(--r-0);
|
|
566
|
+
}
|
|
567
|
+
button.chat-composer-context:hover { color: var(--fg-2); }
|
|
568
|
+
button.chat-composer-context:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
569
|
+
.chat-composer-context-sep { color: var(--fg-3); opacity: 0.6; }
|
|
570
|
+
.chat-composer-context-bit {
|
|
571
|
+
background: transparent; border: 0; padding: 0; margin: 0; cursor: pointer;
|
|
572
|
+
font: inherit; color: var(--fg-3); border-radius: var(--r-0);
|
|
573
|
+
transition: color var(--dur-snap, .15s) var(--ease, ease);
|
|
574
|
+
}
|
|
575
|
+
.chat-composer-context-bit:hover { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
|
|
576
|
+
.chat-composer-context-bit:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
577
|
+
.chat-composer-context-text { color: var(--fg-3); }
|
|
578
|
+
|
|
579
|
+
.chat-composer-detected-badge {
|
|
580
|
+
display: flex; align-items: center; gap: var(--space-2);
|
|
581
|
+
width: 100%; order: -1;
|
|
582
|
+
padding: var(--space-1) var(--space-2-5);
|
|
583
|
+
margin: 0 0 var(--space-1);
|
|
584
|
+
background: color-mix(in oklab, var(--accent) 12%, var(--bg-2));
|
|
585
|
+
border: 1px solid color-mix(in oklab, var(--accent) 28%, transparent);
|
|
586
|
+
border-radius: var(--r-1);
|
|
587
|
+
font-size: var(--fs-xs); color: var(--fg);
|
|
588
|
+
}
|
|
589
|
+
.chat-composer-detected-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
590
|
+
.chat-composer-detected-dismiss {
|
|
591
|
+
flex-shrink: 0; width: 20px; height: 20px;
|
|
592
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
593
|
+
background: transparent; border: 0; cursor: pointer; border-radius: 50%;
|
|
594
|
+
color: var(--fg-3); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1;
|
|
595
|
+
transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
|
|
596
|
+
}
|
|
597
|
+
.chat-composer-detected-dismiss:hover { background: color-mix(in oklab, var(--fg) 10%, transparent); color: var(--fg); }
|
|
598
|
+
.chat-composer-detected-dismiss:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
599
|
+
|
|
600
|
+
.chat-composer-hint {
|
|
601
|
+
width: 100%; order: 2;
|
|
602
|
+
font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3);
|
|
603
|
+
padding: 0 var(--space-1);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.chat-composer-toolbar {
|
|
607
|
+
display: flex; align-items: center; gap: var(--space-1);
|
|
608
|
+
flex-shrink: 0;
|
|
609
|
+
}
|
|
610
|
+
.chat-composer-toolbar .composer-btn {
|
|
611
|
+
width: 32px; height: 32px; border-radius: var(--r-1);
|
|
612
|
+
}
|
|
613
|
+
@media (pointer: coarse) {
|
|
614
|
+
.chat-composer-toolbar .composer-btn { width: 44px; height: 44px; }
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.chat-composer-note {
|
|
618
|
+
width: 100%; order: 3;
|
|
619
|
+
font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3);
|
|
620
|
+
padding: var(--space-1) var(--space-1) 0;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.chat-composer-elapsed {
|
|
624
|
+
font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3);
|
|
625
|
+
flex-shrink: 0; padding: 0 var(--space-1);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.chat-composer.dragover {
|
|
629
|
+
border-color: var(--accent);
|
|
630
|
+
box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
|
|
631
|
+
background: color-mix(in oklab, var(--accent) 4%, var(--bg));
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/* ============================================================
|
|
635
|
+
EmojiPicker (ov-emoji-*) — an anchored popover with search input,
|
|
636
|
+
category tabs, and an emoji grid; previously entirely unstyled.
|
|
637
|
+
Search input mirrors .ds-search-input's tonal-fill treatment so it
|
|
638
|
+
reads consistently with the rest of the system's search fields.
|
|
639
|
+
============================================================ */
|
|
640
|
+
.ov-emoji-root {
|
|
641
|
+
position: fixed;
|
|
642
|
+
display: flex; flex-direction: column; gap: var(--space-2);
|
|
643
|
+
width: 280px; max-height: 320px;
|
|
644
|
+
padding: var(--space-2-5);
|
|
645
|
+
background: var(--bg);
|
|
646
|
+
border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
|
|
647
|
+
border-radius: var(--r-2);
|
|
648
|
+
box-shadow: var(--shadow-overlay, var(--shadow-3));
|
|
649
|
+
z-index: var(--z-dropdown, var(--z-raised));
|
|
650
|
+
}
|
|
651
|
+
.ov-emoji-search {
|
|
652
|
+
width: 100%; box-sizing: border-box;
|
|
653
|
+
font: inherit; font-size: var(--fs-sm); color: var(--fg);
|
|
654
|
+
background: var(--bg-2); border: 0;
|
|
655
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule);
|
|
656
|
+
border-radius: var(--r-1);
|
|
657
|
+
height: var(--ctl-sm, 32px);
|
|
658
|
+
padding: 0 var(--space-2-5);
|
|
659
|
+
transition: box-shadow var(--dur-snap, .15s) var(--ease, ease);
|
|
660
|
+
}
|
|
661
|
+
.ov-emoji-search::placeholder { color: var(--fg-3); }
|
|
662
|
+
.ov-emoji-search:focus-visible,
|
|
663
|
+
.ov-emoji-search:focus {
|
|
664
|
+
outline: none;
|
|
665
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--accent), 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
|
|
666
|
+
}
|
|
667
|
+
.ov-emoji-tabs {
|
|
668
|
+
display: flex; gap: var(--space-1);
|
|
669
|
+
border-bottom: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
|
|
670
|
+
padding-bottom: var(--space-1);
|
|
671
|
+
}
|
|
672
|
+
.ov-emoji-tab {
|
|
673
|
+
flex: 1;
|
|
674
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
675
|
+
height: 30px; font-size: var(--fs-sm);
|
|
676
|
+
background: transparent; border: 0; border-radius: var(--r-1);
|
|
677
|
+
cursor: pointer;
|
|
678
|
+
transition: background var(--dur-snap, .15s) var(--ease, ease);
|
|
679
|
+
}
|
|
680
|
+
.ov-emoji-tab:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); }
|
|
681
|
+
.ov-emoji-tab[aria-selected="true"] { background: color-mix(in oklab, var(--accent) 16%, transparent); }
|
|
682
|
+
.ov-emoji-tab:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
683
|
+
.ov-emoji-grid { overflow-y: auto; flex: 1; min-height: 0; scrollbar-width: thin; scrollbar-color: var(--bg-3) transparent; }
|
|
684
|
+
.ov-emoji-grid-inner {
|
|
685
|
+
display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--space-1);
|
|
686
|
+
}
|
|
687
|
+
.ov-emoji-cell {
|
|
688
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
689
|
+
aspect-ratio: 1; font-size: var(--fs-lg); line-height: 1;
|
|
690
|
+
background: transparent; border: 0; border-radius: var(--r-1);
|
|
691
|
+
cursor: pointer;
|
|
692
|
+
transition: background var(--dur-snap, .15s) var(--ease, ease), transform 0.12s ease;
|
|
693
|
+
}
|
|
694
|
+
.ov-emoji-cell:hover { background: color-mix(in oklab, var(--fg) 10%, transparent); transform: scale(1.12); }
|
|
695
|
+
.ov-emoji-cell:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; background: color-mix(in oklab, var(--fg) 10%, transparent); }
|
|
696
|
+
.ov-emoji-empty {
|
|
697
|
+
grid-column: 1 / -1;
|
|
698
|
+
text-align: center; color: var(--fg-3); font-size: var(--fs-xs);
|
|
699
|
+
padding: var(--space-3) 0;
|
|
700
|
+
}
|
|
701
|
+
@media (prefers-reduced-motion: reduce) {
|
|
702
|
+
.ov-emoji-cell { transition: background var(--dur-snap, .15s) var(--ease, ease); }
|
|
703
|
+
.ov-emoji-cell:hover { transform: none; }
|
|
704
|
+
}
|
|
705
|
+
|
|
@@ -449,6 +449,13 @@
|
|
|
449
449
|
border-radius: var(--r-3); background: var(--bg);
|
|
450
450
|
transition: border-color var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
|
|
451
451
|
}
|
|
452
|
+
/* Idle hover: a quiet pre-drag affordance (border firms up, faint tint) so a
|
|
453
|
+
pointer resting over the zone reads as "droppable" before a drag even
|
|
454
|
+
starts — distinct from and weaker than the .dragover treatment below. */
|
|
455
|
+
.ds-dropzone:hover {
|
|
456
|
+
border-color: var(--fg-3);
|
|
457
|
+
background: var(--bg-2);
|
|
458
|
+
}
|
|
452
459
|
.ds-dropzone-inner {
|
|
453
460
|
display: flex; align-items: center; justify-content: center;
|
|
454
461
|
gap: var(--space-2); flex-wrap: wrap;
|
|
@@ -457,6 +464,9 @@
|
|
|
457
464
|
/* Icon size, not type — see .ds-file-cell-media .ds-file-icon above. */
|
|
458
465
|
.ds-dropzone-glyph { font-size: var(--icon-lg, 24px); color: var(--fg-3); }
|
|
459
466
|
.ds-dropzone-label { font-size: var(--fs-sm); color: var(--fg-3); }
|
|
467
|
+
.ds-dropzone:not(.dragover):not(.rejected):hover {
|
|
468
|
+
border-color: var(--fg-3);
|
|
469
|
+
}
|
|
460
470
|
.ds-dropzone.dragover {
|
|
461
471
|
border-color: var(--accent);
|
|
462
472
|
background: var(--accent-tint);
|
|
@@ -470,6 +480,26 @@
|
|
|
470
480
|
0%, 100% { border-color: var(--accent); }
|
|
471
481
|
50% { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }
|
|
472
482
|
}
|
|
483
|
+
/* Rejected — an in-flight drag carrying a disallowed payload (wrong type,
|
|
484
|
+
over the size cap). Distinct from dragover: warn tone, not accent, so the
|
|
485
|
+
two "something is happening" states never read as the same affordance. */
|
|
486
|
+
.ds-dropzone.rejected {
|
|
487
|
+
border-color: var(--warn);
|
|
488
|
+
background: color-mix(in oklab, var(--warn) 10%, var(--bg));
|
|
489
|
+
}
|
|
490
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
491
|
+
.ds-dropzone.rejected { animation: ds-dropzone-shake 0.4s var(--ease); }
|
|
492
|
+
}
|
|
493
|
+
.ds-dropzone.rejected .ds-dropzone-glyph,
|
|
494
|
+
.ds-dropzone.rejected .ds-dropzone-label { color: var(--warn); }
|
|
495
|
+
@keyframes ds-dropzone-shake {
|
|
496
|
+
0%, 100% { transform: translateX(0); }
|
|
497
|
+
25% { transform: translateX(-3px); }
|
|
498
|
+
75% { transform: translateX(3px); }
|
|
499
|
+
}
|
|
500
|
+
.ds-dropzone--wrap.rejected > .ds-dropzone-inner {
|
|
501
|
+
outline-color: var(--warn);
|
|
502
|
+
}
|
|
473
503
|
/* Wrapper form (has children): no permanent chrome - the content renders as if
|
|
474
504
|
the zone were not there, and the dashed affordance overlays it ONLY while a
|
|
475
505
|
drag is in flight. */
|
|
@@ -577,6 +607,8 @@
|
|
|
577
607
|
max(var(--space-3), env(safe-area-inset-bottom))
|
|
578
608
|
max(var(--space-3), env(safe-area-inset-left));
|
|
579
609
|
background: color-mix(in oklab, var(--ink) 55%, transparent);
|
|
610
|
+
backdrop-filter: blur(2px);
|
|
611
|
+
-webkit-backdrop-filter: blur(2px);
|
|
580
612
|
}
|
|
581
613
|
@media (prefers-reduced-motion: no-preference) {
|
|
582
614
|
.ds-modal-backdrop { animation: ds-modal-fade var(--dur-base) var(--ease); }
|
|
@@ -651,10 +683,17 @@
|
|
|
651
683
|
floor. --ink on the same fill measures 6.27:1. Same principle as the
|
|
652
684
|
--accent/--accent-ink split the token layer documents: a light saturated fill
|
|
653
685
|
takes the dark text tone. Measured in a live browser. */
|
|
686
|
+
/* Severity is never color-alone (gd-14, color-blindness/grayscale-print safe):
|
|
687
|
+
the bold weight + widened letter-spacing is a shape cue that survives a
|
|
688
|
+
colorless render, matching how .btn-primary.danger differs from every
|
|
689
|
+
other .btn-primary at a glance even with color stripped out. */
|
|
654
690
|
.btn-primary.danger {
|
|
655
691
|
background: var(--warn);
|
|
656
692
|
border-color: var(--warn);
|
|
657
693
|
color: var(--ink);
|
|
694
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) color-mix(in oklab, var(--ink) 25%, transparent);
|
|
695
|
+
font-weight: 700;
|
|
696
|
+
letter-spacing: 0.01em;
|
|
658
697
|
}
|
|
659
698
|
.btn-primary.danger:hover { filter: brightness(0.92); border-color: var(--warn); }
|
|
660
699
|
|
|
@@ -61,6 +61,12 @@
|
|
|
61
61
|
padding-bottom: var(--space-2); border-bottom: var(--bw-hair) solid var(--bg-3);
|
|
62
62
|
}
|
|
63
63
|
.ds-hero-stat:last-child { border-bottom: 0; padding-bottom: 0; }
|
|
64
|
+
/* HeroFromPageData's richer badge shape ({label, desc}) renders a strong
|
|
65
|
+
figure plus a muted descriptor inside the same .ds-hero-stat row — give
|
|
66
|
+
the pair a baseline-aligned inline layout instead of falling back to
|
|
67
|
+
unstyled default inline flow. */
|
|
68
|
+
.ds-hero-stat-n { font-weight: 700; color: var(--fg); margin-right: var(--space-2); }
|
|
69
|
+
.ds-hero-stat-l { color: var(--fg-3); font-size: var(--fs-xs); }
|
|
64
70
|
.ds-hero-title {
|
|
65
71
|
font-family: var(--ff-display); font-weight: 700;
|
|
66
72
|
/* Bespoke display clamp, deliberately off the --fs-* ladder: --fs-hero is
|
|
@@ -173,6 +179,8 @@
|
|
|
173
179
|
padding: var(--space-2) 0;
|
|
174
180
|
font-family: var(--ff-display); font-weight: 600;
|
|
175
181
|
text-transform: uppercase; letter-spacing: var(--tr-caps);
|
|
182
|
+
mask-image: linear-gradient(90deg, transparent 0, var(--fg) 28px, var(--fg) calc(100% - 28px), transparent 100%);
|
|
183
|
+
-webkit-mask-image: linear-gradient(90deg, transparent 0, var(--fg) 28px, var(--fg) calc(100% - 28px), transparent 100%);
|
|
176
184
|
}
|
|
177
185
|
.ds-marquee-track {
|
|
178
186
|
display: inline-flex; gap: var(--space-5);
|
|
@@ -205,7 +213,7 @@
|
|
|
205
213
|
.cli {
|
|
206
214
|
display: flex; align-items: center; gap: 14px;
|
|
207
215
|
overflow-x: auto;
|
|
208
|
-
padding:
|
|
216
|
+
padding: var(--space-3-5) var(--space-4);
|
|
209
217
|
background: var(--ink); color: var(--paper);
|
|
210
218
|
border-radius: var(--r-3);
|
|
211
219
|
font-family: var(--ff-mono); font-size: var(--fs-lg);
|
|
@@ -213,12 +221,13 @@
|
|
|
213
221
|
.cli .prompt { color: var(--green-2); }
|
|
214
222
|
.cli .cmd { flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; color: var(--paper); }
|
|
215
223
|
.cli .copy {
|
|
216
|
-
padding:
|
|
224
|
+
padding: var(--space-2) var(--space-3); background: transparent; color: var(--paper);
|
|
217
225
|
font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--tr-caps);
|
|
218
226
|
cursor: pointer; box-shadow: inset 0 0 0 1px var(--rule-strong);
|
|
219
227
|
border-radius: var(--r-pill);
|
|
220
228
|
}
|
|
221
229
|
.cli .copy:hover { background: var(--fg-3); }
|
|
230
|
+
.cli .copy:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
222
231
|
|
|
223
232
|
/* Multi-line CLI block: when .cli holds .ds-cli-row / .ds-cli-comment children
|
|
224
233
|
(quickstart scripts, multi-command snippets — see CliBlock in
|
|
@@ -254,7 +263,7 @@
|
|
|
254
263
|
.ds-quickstart-cli { flex-direction: column; align-items: stretch; gap: var(--space-2); }
|
|
255
264
|
.ds-quickstart-copy {
|
|
256
265
|
align-self: flex-end;
|
|
257
|
-
padding:
|
|
266
|
+
padding: var(--space-2) var(--space-3); background: transparent; color: var(--paper);
|
|
258
267
|
font-family: var(--ff-mono); font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--tr-caps);
|
|
259
268
|
cursor: pointer; box-shadow: inset 0 0 0 1px var(--rule-strong);
|
|
260
269
|
border-radius: var(--r-pill); border: none;
|
|
@@ -450,7 +459,7 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
|
|
|
450
459
|
display: inline-flex; align-items: center; gap: var(--space-hair);
|
|
451
460
|
font-size: var(--fs-xs); font-weight: 600;
|
|
452
461
|
}
|
|
453
|
-
.kpi-delta-up { color: var(--
|
|
462
|
+
.kpi-delta-up { color: var(--success); }
|
|
454
463
|
.kpi-delta-down { color: var(--danger); }
|
|
455
464
|
.ds-sparkline path { stroke: currentColor; }
|
|
456
465
|
.ds-sparkline-up { color: var(--success); }
|
|
@@ -157,7 +157,17 @@
|
|
|
157
157
|
aspect-ratio: auto;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
.ds-deck-slide {
|
|
160
|
+
.ds-deck-slide {
|
|
161
|
+
flex: 1; display: flex; min-width: 0;
|
|
162
|
+
animation: ds-deck-slide-in var(--dur-base) var(--ease);
|
|
163
|
+
}
|
|
164
|
+
@media (prefers-reduced-motion: reduce) {
|
|
165
|
+
.ds-deck-slide { animation: none; }
|
|
166
|
+
}
|
|
167
|
+
@keyframes ds-deck-slide-in {
|
|
168
|
+
from { opacity: 0; transform: translateY(var(--space-1-75)); }
|
|
169
|
+
to { opacity: 1; transform: none; }
|
|
170
|
+
}
|
|
161
171
|
.ds-deck-controls {
|
|
162
172
|
/* 14px sits between --space-2-75 (12) and --space-3 (16) with no tier; it is
|
|
163
173
|
the deck control spacing tuned against the mono glyph run. */
|
|
@@ -168,6 +178,19 @@
|
|
|
168
178
|
@media (pointer: coarse) {
|
|
169
179
|
.ds-deck-controls .btn { min-height: 44px; min-width: 44px; }
|
|
170
180
|
}
|
|
181
|
+
/* Dot progress indicator: one dot per slide, current slide filled with
|
|
182
|
+
--accent (same fill token .ds-dot-on uses elsewhere in the system), rest
|
|
183
|
+
dim at --fg-3 so the row reads as a track, not a second counter. */
|
|
184
|
+
.ds-deck-progress {
|
|
185
|
+
display: flex; align-items: center; justify-content: center;
|
|
186
|
+
gap: var(--space-1-5); padding-bottom: var(--space-2);
|
|
187
|
+
}
|
|
188
|
+
.ds-deck-dot {
|
|
189
|
+
width: var(--space-1-5); height: var(--space-1-5); border-radius: 50%;
|
|
190
|
+
background: var(--fg-3); flex: 0 0 auto;
|
|
191
|
+
transition: background var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
|
|
192
|
+
}
|
|
193
|
+
.ds-deck-dot--active { background: var(--accent); transform: scale(1.3); }
|
|
171
194
|
/* Kit small-label voice — one local composition of the house `.t-label` recipe
|
|
172
195
|
(base.css) for every eyebrow/label in the appended kit blocks below. These
|
|
173
196
|
previously each restated the four declarations with drifted tracking
|
|
@@ -278,7 +301,12 @@
|
|
|
278
301
|
}
|
|
279
302
|
.ds-gallery-tile {
|
|
280
303
|
cursor: pointer; display: flex; flex-direction: column; gap: var(--space-1-75);
|
|
281
|
-
padding: var(--space-2-75); border-radius: var(--r-1);
|
|
304
|
+
padding: var(--space-2-75); border-radius: var(--r-1);
|
|
305
|
+
/* Fixed aspect-ratio (not just a min-height floor) so every tile in the grid
|
|
306
|
+
occupies the same shape regardless of caption length — the ascii specimen
|
|
307
|
+
is centered inside via .ds-tile-cap's flex alignment, the equivalent of
|
|
308
|
+
object-fit: cover for a text tile with no bitmap to crop. */
|
|
309
|
+
aspect-ratio: 4 / 3;
|
|
282
310
|
border: 0; text-align: left; font: inherit; color: inherit;
|
|
283
311
|
background: var(--tile-tone, var(--panel-1));
|
|
284
312
|
transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
|
|
@@ -288,7 +316,7 @@
|
|
|
288
316
|
translateY + shadow idiom .chat-msg:hover .chat-bubble already uses. */
|
|
289
317
|
.ds-gallery-tile:hover { transform: translateY(-2px); box-shadow: 0 2px 8px color-mix(in oklab, var(--fg) 10%, transparent); }
|
|
290
318
|
.ds-gallery-tile:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
291
|
-
.ds-gallery-tile--tight {
|
|
319
|
+
.ds-gallery-tile--tight { aspect-ratio: 3 / 2; }
|
|
292
320
|
/* The lightbox scrim/card chrome itself is now Dialog's (.ds-ep-dialog /
|
|
293
321
|
.ds-ep-dialog-backdrop in editor-primitives.css) — Dialog already ships
|
|
294
322
|
role="dialog", aria-modal, Tab-trap and focus-restore-on-close, which the
|
|
@@ -312,13 +340,21 @@
|
|
|
312
340
|
@media (max-width: 480px) {
|
|
313
341
|
.ds-topbar-search { flex-basis: 100%; }
|
|
314
342
|
}
|
|
315
|
-
.ds-empty-state
|
|
343
|
+
/* Namespaced .ds-kit-empty-state (not .ds-empty-state) -- .ds-empty-state is
|
|
344
|
+
primitives.css's shared base (padding var(--space-6), color var(--fg-3));
|
|
345
|
+
this sheet loads after it in app-shell.css's import order, so reusing the
|
|
346
|
+
same class name silently overrode that base's padding/color for every
|
|
347
|
+
consumer, defeating the "shared base, one place" contract primitives.css
|
|
348
|
+
documents. This block is unused by any component today, but kept
|
|
349
|
+
namespaced so a future consumer gets this sheet's fluid clamp() treatment
|
|
350
|
+
deliberately rather than by cascade accident. */
|
|
351
|
+
.ds-kit-empty-state { padding: clamp(var(--space-3), 5vw, var(--space-4)); text-align: center; color: var(--panel-text-3); }
|
|
316
352
|
/* Fluid ICON size (empty-state mark), not a type tier: it scales with the
|
|
317
353
|
viewport between 24 and 32px. Every fluid --fs-* tier is a heading clamp
|
|
318
354
|
tuned to cqi + heading weight, so none of them substitutes here. */
|
|
319
|
-
.ds-empty-state-glyph { font-size: clamp(24px, 6vw, 32px); }
|
|
320
|
-
.ds-empty-state-msg { margin: var(--space-1-75) 0; }
|
|
321
|
-
.ds-empty-state-hint { margin: 0; font-size: var(--fs-sm); }
|
|
355
|
+
.ds-kit-empty-state-glyph { font-size: clamp(24px, 6vw, 32px); }
|
|
356
|
+
.ds-kit-empty-state-msg { margin: var(--space-1-75) 0; }
|
|
357
|
+
.ds-kit-empty-state-hint { margin: 0; font-size: var(--fs-sm); }
|
|
322
358
|
|
|
323
359
|
/* --- system primer ------------------------------------------ */
|
|
324
360
|
/* The three primer panels below share one fluid inset,
|
|
@@ -707,6 +743,7 @@
|
|
|
707
743
|
border-radius: 50%; background: var(--bg-3); color: var(--fg);
|
|
708
744
|
font-family: var(--ff-mono); font-weight: 600; text-transform: lowercase;
|
|
709
745
|
letter-spacing: 0.02em; user-select: none; flex-shrink: 0; object-fit: cover;
|
|
746
|
+
box-shadow: inset 0 0 0 1px var(--rule);
|
|
710
747
|
}
|
|
711
748
|
.ds-avatar-sm { width: 24px; height: 24px; font-size: var(--fs-pico); }
|
|
712
749
|
.ds-avatar-md { width: 36px; height: 36px; font-size: var(--fs-micro); }
|
|
@@ -834,6 +871,7 @@
|
|
|
834
871
|
font-weight: 600;
|
|
835
872
|
line-height: 1;
|
|
836
873
|
user-select: none;
|
|
874
|
+
box-shadow: inset 0 0 0 1px var(--rule);
|
|
837
875
|
}
|
|
838
876
|
|
|
839
877
|
/* Body stack — name + time on one baseline, text beneath. .chat-stack's
|
|
@@ -55,9 +55,11 @@
|
|
|
55
55
|
.ds-skeleton {
|
|
56
56
|
background: linear-gradient(90deg, var(--bg-2) 25%, var(--bg-3) 50%, var(--bg-2) 75%);
|
|
57
57
|
background-size: 200% 100%;
|
|
58
|
-
animation: ds-shimmer 1.5s infinite;
|
|
59
58
|
border-radius: var(--r-1);
|
|
60
59
|
}
|
|
60
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
61
|
+
.ds-skeleton { animation: ds-shimmer 1.5s infinite; }
|
|
62
|
+
}
|
|
61
63
|
|
|
62
64
|
@keyframes ds-shimmer {
|
|
63
65
|
0% { background-position: 200% 0; }
|
|
@@ -59,9 +59,19 @@
|
|
|
59
59
|
font-size: var(--fs-tiny); font-weight: 600;
|
|
60
60
|
color: var(--fg-3);
|
|
61
61
|
letter-spacing: var(--tr-caps); text-transform: uppercase;
|
|
62
|
+
/* A hairline divider is the header's only structural separator from the
|
|
63
|
+
body — without it, an uppercase caps label at fs-tiny/600 reads as just
|
|
64
|
+
another dim meta line once the eye drops past the top of the panel. */
|
|
65
|
+
border-bottom: var(--bw-hair) solid var(--rule);
|
|
66
|
+
margin-bottom: var(--space-1);
|
|
62
67
|
}
|
|
63
68
|
.panel.panel-wide .panel-head { padding-left: 0; padding-right: 0; }
|
|
64
|
-
.panel-
|
|
69
|
+
/* A borderless .panel-wide (no card edge to lean on) would otherwise show a
|
|
70
|
+
divider floating with nothing to visually anchor it — drop it there and
|
|
71
|
+
rely on spacing alone, matching panel-wide's already-transparent chrome. */
|
|
72
|
+
.panel.panel-wide .panel-head { border-bottom: none; margin-bottom: 0; }
|
|
73
|
+
.panel.panel--dense .panel-head { border-bottom: var(--bw-hair) solid var(--rule); margin-bottom: 0; }
|
|
74
|
+
.panel-head > :last-child:not(.ds-badge) {
|
|
65
75
|
font-weight: 500; color: var(--fg-3);
|
|
66
76
|
font-family: var(--ff-mono); letter-spacing: 0;
|
|
67
77
|
}
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
.ds-icon-btn-base { width: 32px; height: 32px; }
|
|
66
66
|
.ds-icon-btn-lg { width: 40px; height: 40px; }
|
|
67
67
|
.ds-icon-btn-xl { width: 48px; height: 48px; }
|
|
68
|
+
@media (pointer: coarse) {
|
|
69
|
+
.ds-icon-btn-xs { width: 32px; height: 32px; }
|
|
70
|
+
.ds-icon-btn-sm { width: 32px; height: 32px; }
|
|
71
|
+
}
|
|
68
72
|
.ds-icon-btn-ghost { background: transparent; }
|
|
69
73
|
.ds-icon-btn-ghost:hover { background: var(--fg); color: var(--bg); }
|
|
70
74
|
.ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
|
|
@@ -86,7 +90,11 @@
|
|
|
86
90
|
border-radius: var(--r-pill);
|
|
87
91
|
background: var(--bg-3); color: var(--fg-2);
|
|
88
92
|
}
|
|
89
|
-
|
|
93
|
+
/* --fs-nano (11px), not --fs-pico (10px): --fs-pico sits below the 11px
|
|
94
|
+
legibility floor other small-scale labels in this system respect (see
|
|
95
|
+
.ds-stat-lbl, .ds-session-row-id), and this size is used live for the
|
|
96
|
+
workspace rail item-count badge (atoms.js Badge size="sm"). */
|
|
97
|
+
.ds-badge.ds-badge--sm { min-width: var(--icon-xs); height: var(--icon-xs); padding: 0 var(--space-1); font-size: var(--fs-nano); }
|
|
90
98
|
.ds-badge.ds-badge--lg { min-width: 22px; height: 22px; padding: 0 var(--space-2); font-size: var(--fs-tiny); }
|
|
91
99
|
.ds-badge.tone-green, .ds-badge.tone-live, .ds-badge.tone-success {
|
|
92
100
|
background: var(--green-tint); color: var(--green-deep);
|
|
@@ -143,7 +151,6 @@
|
|
|
143
151
|
.chip.tone-disabled { background: var(--bg-3); color: var(--fg-3); }
|
|
144
152
|
.chip.tone-blue { background: var(--accent-tint); color: var(--accent-ink); }
|
|
145
153
|
.chip.tone-orange { background: color-mix(in oklab, var(--flame) 30%, var(--sun) 70%); color: var(--ink); }
|
|
146
|
-
.chip.tone-yellow { background: var(--sun); color: var(--ink); }
|
|
147
154
|
|
|
148
155
|
.chip.ds-chip-removable { padding-right: var(--space-1); }
|
|
149
156
|
.ds-chip-remove-btn {
|
|
@@ -183,6 +190,7 @@
|
|
|
183
190
|
}
|
|
184
191
|
.glyph { --glyph-size-sm: var(--fs-nano); --glyph-size-base: var(--fs-tiny); --glyph-size-lg: var(--fs-body); }
|
|
185
192
|
.glyph-sm { width: var(--icon-xs); height: var(--icon-xs); }
|
|
193
|
+
.glyph-base { width: 18px; height: 18px; }
|
|
186
194
|
.glyph-lg { width: 22px; height: 22px; }
|
|
187
195
|
|
|
188
196
|
/* Shared empty-state base -- hero-content.css's .empty and community.css's
|
|
@@ -201,3 +209,41 @@
|
|
|
201
209
|
.ds-empty-state--panel { background: var(--bg-2); border-radius: var(--r-1); }
|
|
202
210
|
.ds-empty-state--compact { padding: var(--space-5) var(--space-3); }
|
|
203
211
|
|
|
212
|
+
/* .ds-tooltip — shared floating bubble (overlay-primitives/tooltip.js appends
|
|
213
|
+
one instance to <body> and repositions it via useFloating). Fade timing
|
|
214
|
+
matches the component's own 350ms hover-intent delay. */
|
|
215
|
+
.ds-tooltip {
|
|
216
|
+
position: fixed;
|
|
217
|
+
z-index: var(--z-top);
|
|
218
|
+
max-width: 240px;
|
|
219
|
+
padding: var(--space-1) var(--space-2);
|
|
220
|
+
border-radius: var(--r-1);
|
|
221
|
+
background: var(--fg);
|
|
222
|
+
color: var(--bg);
|
|
223
|
+
font-size: var(--fs-xs);
|
|
224
|
+
line-height: 1.35;
|
|
225
|
+
box-shadow: var(--shadow-2);
|
|
226
|
+
pointer-events: none;
|
|
227
|
+
opacity: 0;
|
|
228
|
+
transform: scale(0.96);
|
|
229
|
+
transition: opacity var(--dur-snap) var(--ease), transform var(--dur-snap) var(--ease);
|
|
230
|
+
}
|
|
231
|
+
.ds-tooltip:not([hidden]) { opacity: 1; transform: scale(1); }
|
|
232
|
+
.ds-tooltip::after {
|
|
233
|
+
content: '';
|
|
234
|
+
position: absolute;
|
|
235
|
+
width: 6px;
|
|
236
|
+
height: 6px;
|
|
237
|
+
background: var(--fg);
|
|
238
|
+
transform: rotate(45deg);
|
|
239
|
+
}
|
|
240
|
+
.ds-tooltip[data-placement^="top"]::after { bottom: -3px; left: 50%; margin-left: -3px; }
|
|
241
|
+
.ds-tooltip[data-placement^="bottom"]::after { top: -3px; left: 50%; margin-left: -3px; }
|
|
242
|
+
.ds-tooltip[data-placement^="left"]::after { right: -3px; top: 50%; margin-top: -3px; }
|
|
243
|
+
.ds-tooltip[data-placement^="right"]::after { left: -3px; top: 50%; margin-top: -3px; }
|
|
244
|
+
.ds-tooltip.kind-danger { background: var(--warn); color: var(--ink); }
|
|
245
|
+
.ds-tooltip.kind-danger::after { background: var(--warn); }
|
|
246
|
+
@media (prefers-reduced-motion: reduce) {
|
|
247
|
+
.ds-tooltip { transition: none; }
|
|
248
|
+
}
|
|
249
|
+
|