anentrypoint-design 1.0.19 → 1.0.21
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/colors_and_type.css +34 -7
- package/dist/247420.css +182 -92
- package/dist/247420.js +28 -28
- package/package.json +1 -1
- package/src/components/agent-chat/empty-state.js +8 -3
- package/src/components/chat-message-parts/inline.js +15 -2
- package/src/components/content/lists.js +1 -1
- package/src/components/editor-primitives/json-viewer.js +6 -5
- package/src/components/files-modals/preview-bodies.js +6 -2
- package/src/components/shell/app-shell.js +6 -0
- package/src/components/shell/atoms.js +1 -1
- package/src/css/app-shell/base.css +6 -6
- package/src/css/app-shell/calendar.css +1 -2
- package/src/css/app-shell/catalog-theme.css +1 -1
- package/src/css/app-shell/chat-polish.css +3 -3
- package/src/css/app-shell/files.css +2 -2
- package/src/css/app-shell/git-status.css +2 -2
- package/src/css/app-shell/hero-content.css +13 -5
- package/src/css/app-shell/kits-appended.css +8 -4
- package/src/css/app-shell/models-config.css +1 -1
- package/src/css/app-shell/panel-row.css +36 -12
- package/src/css/app-shell/plugins-config.css +3 -3
- package/src/css/app-shell/primitives.css +35 -6
- package/src/css/app-shell/responsive2-workspace.css +8 -5
- package/src/css/app-shell/sidebar-misc.css +2 -2
- package/src/css/app-shell/skills-config.css +1 -1
- package/src/css/app-shell/topbar.css +27 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
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",
|
|
@@ -39,9 +39,14 @@ export function AgentEmptyState({ name, selectedAgent, suggestions, onSuggestion
|
|
|
39
39
|
'aria-label': 'copy install command for ' + c.agent, title: 'copy command',
|
|
40
40
|
onclick: (e) => {
|
|
41
41
|
const btn = e.currentTarget;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const done = () => { btn.textContent = 'copied'; setTimeout(() => { btn.textContent = 'copy'; }, 1200); };
|
|
43
|
+
// Falls back whenever the async Clipboard API is
|
|
44
|
+
// absent OR its promise rejects (permission denied,
|
|
45
|
+
// an unfocused document) instead of optimistically
|
|
46
|
+
// claiming "copied" before the write is confirmed.
|
|
47
|
+
const fallback = () => { try { const t = document.createElement('textarea'); t.value = c.command; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t); done(); } catch { /* swallow: no copy mechanism available */ } };
|
|
48
|
+
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(c.command).then(done, fallback);
|
|
49
|
+
else fallback();
|
|
45
50
|
},
|
|
46
51
|
}, 'copy'))))
|
|
47
52
|
: null,
|
|
@@ -56,14 +56,27 @@ export function fileIconName(name) {
|
|
|
56
56
|
// this extraction. Same behavior in every caller: try the async Clipboard
|
|
57
57
|
// API, fall back to a hidden textarea + execCommand('copy') when unavailable,
|
|
58
58
|
// flip the trigger button's own label/class to "copied" for ~1.6s either way.
|
|
59
|
+
function execCommandCopy(text) {
|
|
60
|
+
const t = document.createElement('textarea');
|
|
61
|
+
t.value = text; document.body.appendChild(t); t.select();
|
|
62
|
+
document.execCommand('copy'); document.body.removeChild(t);
|
|
63
|
+
}
|
|
59
64
|
export function copyToClipboardWithFeedback(text, btn) {
|
|
60
65
|
const done = () => {
|
|
61
66
|
btn.textContent = 'copied';
|
|
62
67
|
btn.classList.add('is-copied');
|
|
63
68
|
setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('is-copied'); }, 1600);
|
|
64
69
|
};
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
// Falls back to execCommand whenever the async Clipboard API is either
|
|
71
|
+
// absent OR its promise rejects (permission denied, an unfocused
|
|
72
|
+
// document -- a real failure mode, not just an old-browser one). The
|
|
73
|
+
// prior version only fell back when navigator.clipboard didn't exist at
|
|
74
|
+
// all, so a live rejection silently did nothing -- no feedback, no copy.
|
|
75
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
76
|
+
navigator.clipboard.writeText(text).then(done, () => { try { execCommandCopy(text); done(); } catch { /* swallow: no copy mechanism available */ } });
|
|
77
|
+
} else {
|
|
78
|
+
try { execCommandCopy(text); done(); } catch { /* swallow: no copy mechanism available */ }
|
|
79
|
+
}
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
// Inject a per-block copy button into every <pre> inside a rendered-markdown
|
|
@@ -31,7 +31,7 @@ export function WorksList({ works = [], openedIndex = -1, onToggle }) {
|
|
|
31
31
|
h('p', { class: 'ds-work-body' }, w.body)
|
|
32
32
|
),
|
|
33
33
|
h('div', { class: 'ds-work-actions' },
|
|
34
|
-
Btn({ variant: 'primary', href: w.href || '#', children: 'open ->' }),
|
|
34
|
+
Btn({ variant: 'primary', href: w.href || '#', 'aria-label': 'open ' + (w.title || 'project'), children: 'open ->' }),
|
|
35
35
|
Btn({ href: w.source || '#', children: 'source' })
|
|
36
36
|
)
|
|
37
37
|
) : null
|
|
@@ -90,11 +90,12 @@ function jsonCopyButton(text) {
|
|
|
90
90
|
btn.classList.toggle('copied', ok);
|
|
91
91
|
setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('copied'); }, 1200);
|
|
92
92
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
const fallback = () => {
|
|
94
|
+
try { const t = document.createElement('textarea'); t.value = text; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t); show('copied', true); }
|
|
95
|
+
catch { show('failed', false); }
|
|
96
|
+
};
|
|
97
|
+
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(() => show('copied', true), fallback);
|
|
98
|
+
else fallback();
|
|
98
99
|
},
|
|
99
100
|
}, 'copy');
|
|
100
101
|
}
|
|
@@ -61,8 +61,12 @@ export function FilePreviewCode({ content = '', lang, filename, wrap, onWrapTogg
|
|
|
61
61
|
const onCopy = (e) => {
|
|
62
62
|
const btn = e.currentTarget;
|
|
63
63
|
const done = () => { btn.textContent = 'copied'; btn.classList.add('is-copied'); setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('is-copied'); }, 1600); };
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const fallback = () => { try { const t = document.createElement('textarea'); t.value = content; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t); done(); } catch { /* swallow: no copy mechanism available */ } };
|
|
65
|
+
// Falls back whenever the async Clipboard API is absent OR its
|
|
66
|
+
// promise rejects (permission denied, an unfocused document) --
|
|
67
|
+
// was previously only reached when navigator.clipboard didn't exist.
|
|
68
|
+
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(content).then(done, fallback);
|
|
69
|
+
else fallback();
|
|
66
70
|
};
|
|
67
71
|
const hasPreview = previewHtml != null && onModeChange;
|
|
68
72
|
const activeMode = hasPreview ? (mode || 'source') : 'source';
|
|
@@ -43,6 +43,12 @@ export function Topbar({ brand = '247420', leaf = '', items = [], active = '', o
|
|
|
43
43
|
href,
|
|
44
44
|
class: active === cleanLabel ? 'active' : '',
|
|
45
45
|
'aria-current': active === cleanLabel ? 'page' : null,
|
|
46
|
+
// The visible label keeps its ' ->' ASCII arrow (sanctioned
|
|
47
|
+
// per AGENTS.md's icon policy), but a screen reader spelling
|
|
48
|
+
// that out literally ("source dash greater-than") is noise --
|
|
49
|
+
// aria-label gives the same cleaned text the active-state
|
|
50
|
+
// comparison already computes, read once, without the arrow.
|
|
51
|
+
'aria-label': cleanLabel !== String(label) ? cleanLabel : null,
|
|
46
52
|
onclick: (e) => {
|
|
47
53
|
if (!String(href).startsWith('http') && onNav) {
|
|
48
54
|
e.preventDefault();
|
|
@@ -65,7 +65,7 @@ export function Btn({ href, variant = 'default', size = 'md', children, onClick,
|
|
|
65
65
|
// modifier that snaps height/padding/font to the --ctl-* ladder. Unknown
|
|
66
66
|
// sizes fall back to md so a typo never drops the button's base styling.
|
|
67
67
|
const sizeCls = size === 'sm' ? ' btn-sm' : (size === 'lg' ? ' btn-lg' : '');
|
|
68
|
-
const cls = (resolvedVariant === 'primary' ? 'btn-primary' : (resolvedVariant === 'ghost' ? 'btn-ghost' : (resolvedVariant === 'danger' ? 'btn-primary danger' : 'btn')))
|
|
68
|
+
const cls = (resolvedVariant === 'primary' ? 'btn-primary' : (resolvedVariant === 'ghost' ? 'btn-ghost' : (resolvedVariant === 'danger' ? 'btn-primary danger' : (resolvedVariant === 'link' ? 'btn-link' : 'btn'))))
|
|
69
69
|
+ sizeCls
|
|
70
70
|
+ (disabled ? ' is-disabled' : '')
|
|
71
71
|
+ (className ? ' ' + className : '');
|
|
@@ -109,14 +109,14 @@ body {
|
|
|
109
109
|
border-radius: var(--r-pill, 999px);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
h1, .t-h1 { font-family: var(--ff-display); font-size: var(--fs-h1); line-height: var(--lh-snug); letter-spacing: var(--tr-tight); font-weight:
|
|
112
|
+
h1, .t-h1 { font-family: var(--ff-display); font-size: var(--fs-h1); line-height: var(--lh-snug); letter-spacing: var(--tr-tight); font-weight: var(--fw-semibold); margin: 0; }
|
|
113
113
|
h2, .t-h2 { font-family: var(--ff-display); font-size: var(--fs-h2); line-height: var(--lh-snug); letter-spacing: var(--tr-tight); font-weight: 600; margin: 0; }
|
|
114
114
|
h3, .t-h3 { font-family: var(--ff-display); font-size: var(--fs-h3); line-height: var(--lh-snug); letter-spacing: -0.01em; font-weight: 600; margin: 0; }
|
|
115
115
|
h4, .t-h4 { font-family: var(--ff-display); font-size: var(--fs-h4); line-height: var(--lh-snug); font-weight: 600; margin: 0; }
|
|
116
116
|
|
|
117
|
-
[data-typescale="app"] h1, [data-typescale="app"] .t-h1 { font-size: var(--fs-h1-app); line-height: 1.15; }
|
|
118
|
-
[data-typescale="app"] h2, [data-typescale="app"] .t-h2 { font-size: var(--fs-h2-app); }
|
|
119
|
-
[data-typescale="app"] h3, [data-typescale="app"] .t-h3 { font-size: var(--fs-h3-app); }
|
|
117
|
+
[data-typescale="app"] h1, [data-typescale="app"] .t-h1 { font-size: var(--fs-h1-app); line-height: 1.15; font-weight: var(--fw-medium); }
|
|
118
|
+
[data-typescale="app"] h2, [data-typescale="app"] .t-h2 { font-size: var(--fs-h2-app); font-weight: var(--fw-medium); }
|
|
119
|
+
[data-typescale="app"] h3, [data-typescale="app"] .t-h3 { font-size: var(--fs-h3-app); font-weight: var(--fw-medium); }
|
|
120
120
|
[data-typescale="app"] h4, [data-typescale="app"] .t-h4 { font-size: var(--fs-h4-app); }
|
|
121
121
|
|
|
122
122
|
.t-hero { font-family: var(--ff-display); font-size: var(--fs-hero); line-height: var(--lh-tight); letter-spacing: var(--tr-tighter); font-weight: 700; margin: 0; }
|
|
@@ -126,8 +126,8 @@ h4, .t-h4 { font-family: var(--ff-display); font-size: var(--fs-h4); line-height
|
|
|
126
126
|
.t-mono { font-family: var(--ff-mono); font-weight: 400; }
|
|
127
127
|
.t-body { font-family: var(--ff-body); }
|
|
128
128
|
|
|
129
|
-
.t-label { font-family: var(--ff-
|
|
130
|
-
.t-micro { font-family: var(--ff-
|
|
129
|
+
.t-label { font-family: var(--ff-body); font-size: var(--fs-tiny); letter-spacing: 0; font-weight: 600; }
|
|
130
|
+
.t-micro { font-family: var(--ff-body); font-size: var(--fs-micro); letter-spacing: 0; color: var(--fg-3); font-weight: 600; }
|
|
131
131
|
.t-meta { font-family: var(--ff-body); font-size: var(--fs-sm); color: var(--fg-3); }
|
|
132
132
|
|
|
133
133
|
.lede, .t-lede {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
.ds-catalog-side h1 { font-size: var(--fs-lg); margin: 0 0 var(--space-1); }
|
|
17
17
|
.ds-catalog-side .subtitle { font-size: var(--fs-micro); color: var(--fg-3); margin: 0 0 var(--space-4); }
|
|
18
18
|
.ds-catalog-side nav h4 {
|
|
19
|
-
font-size: var(--fs-micro);
|
|
19
|
+
font-size: var(--fs-micro); letter-spacing: var(--tr-tight); font-weight: 600;
|
|
20
20
|
color: var(--fg-3); margin: var(--space-3) 0 var(--space-1);
|
|
21
21
|
}
|
|
22
22
|
.ds-catalog-side nav a {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
width: 36px; height: 36px; flex-shrink: 0;
|
|
56
56
|
border-radius: 50%; background: var(--bg-3); color: var(--fg);
|
|
57
57
|
display: inline-flex; align-items: center; justify-content: center;
|
|
58
|
-
font-family: var(--ff-
|
|
58
|
+
font-family: var(--ff-body); font-size: var(--fs-micro); font-weight: 600;
|
|
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;
|
|
@@ -355,7 +355,7 @@
|
|
|
355
355
|
.chat-link .thumb,
|
|
356
356
|
.chat-link img.thumb { width: 80px; height: 80px; border-radius: var(--r-0); object-fit: cover; background: var(--bg-3) center/cover no-repeat; }
|
|
357
357
|
.chat-link .meta { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
|
|
358
|
-
.chat-link .host { font-family: var(--ff-
|
|
358
|
+
.chat-link .host { font-family: var(--ff-body); font-size: var(--fs-xs); color: var(--fg-3); text-transform: lowercase; }
|
|
359
359
|
.chat-link .title { font-weight: 600; font-size: var(--fs-sm); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
360
360
|
.chat-link .desc { font-size: var(--fs-xs); color: var(--fg-2); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
361
361
|
|
|
@@ -367,7 +367,7 @@
|
|
|
367
367
|
.chat-meta .who { font-weight: 600; color: var(--fg-2); }
|
|
368
368
|
.chat-meta .who::after { content: ' ·'; color: var(--fg-3); font-weight: 400; }
|
|
369
369
|
.chat-meta .t { color: var(--fg-3); }
|
|
370
|
-
.chat-meta .tick { color: var(--fg-3); margin-left: var(--space-hair); letter-spacing: -2px; font-family: var(--ff-
|
|
370
|
+
.chat-meta .tick { color: var(--fg-3); margin-left: var(--space-hair); letter-spacing: -2px; font-family: var(--ff-body); }
|
|
371
371
|
.chat-meta .tick.read { color: var(--accent-ink); }
|
|
372
372
|
|
|
373
373
|
.chat-reactions {
|
|
@@ -690,8 +690,8 @@
|
|
|
690
690
|
.btn-primary.danger {
|
|
691
691
|
background: var(--warn);
|
|
692
692
|
border-color: var(--warn);
|
|
693
|
-
color: var(--
|
|
694
|
-
box-shadow: inset 0 0 0 var(--bw-hair, 1px) color-mix(in oklab, var(--
|
|
693
|
+
color: var(--warn-fg);
|
|
694
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) color-mix(in oklab, var(--warn-fg) 25%, transparent);
|
|
695
695
|
font-weight: 700;
|
|
696
696
|
letter-spacing: 0.01em;
|
|
697
697
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
.ds-git-status-chip {
|
|
21
21
|
display: inline-flex; align-items: center; justify-content: center;
|
|
22
22
|
flex: 0 0 auto; width: 18px; height: 18px;
|
|
23
|
-
font-family: var(--ff-
|
|
23
|
+
font-family: var(--ff-body); font-size: var(--fs-micro); font-weight: 700;
|
|
24
24
|
border-radius: var(--r-1);
|
|
25
25
|
}
|
|
26
26
|
.ds-git-status-chip.tone-add { color: var(--green-2); background: color-mix(in oklab, var(--green-2) 16%, transparent); }
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
flex: 0 0 auto; font-size: var(--fs-micro); color: var(--fg-3);
|
|
39
39
|
border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1); padding: 1px 6px;
|
|
40
40
|
}
|
|
41
|
-
.ds-git-row-stats { flex: 0 0 auto; display: inline-flex; gap: 6px; font-family: var(--ff-
|
|
41
|
+
.ds-git-row-stats { flex: 0 0 auto; display: inline-flex; gap: 6px; font-family: var(--ff-body); font-size: var(--fs-micro); }
|
|
42
42
|
.ds-git-stat-add { color: var(--green-2); }
|
|
43
43
|
.ds-git-stat-del { color: var(--flame); }
|
|
44
44
|
|
|
@@ -218,11 +218,15 @@
|
|
|
218
218
|
border-radius: var(--r-3);
|
|
219
219
|
font-family: var(--ff-mono); font-size: var(--fs-lg);
|
|
220
220
|
}
|
|
221
|
-
.cli .prompt
|
|
221
|
+
/* user-select:none (matching .ds-cli-row .prompt below) so selecting/copying
|
|
222
|
+
a command line grabs only the command text, not the prompt mark itself --
|
|
223
|
+
otherwise every copy-pasted line carries a leading '$ ' that has to be
|
|
224
|
+
stripped by hand before it can be re-run. */
|
|
225
|
+
.cli .prompt { color: var(--green-2); user-select: none; }
|
|
222
226
|
.cli .cmd { flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; color: var(--paper); }
|
|
223
227
|
.cli .copy {
|
|
224
228
|
padding: var(--space-2) var(--space-3); background: transparent; color: var(--paper);
|
|
225
|
-
font-size: var(--fs-tiny);
|
|
229
|
+
font-size: var(--fs-tiny); letter-spacing: var(--tr-tight); font-weight: 500;
|
|
226
230
|
cursor: pointer; box-shadow: inset 0 0 0 1px var(--rule-strong);
|
|
227
231
|
border-radius: var(--r-pill);
|
|
228
232
|
}
|
|
@@ -264,7 +268,7 @@
|
|
|
264
268
|
.ds-quickstart-copy {
|
|
265
269
|
align-self: flex-end;
|
|
266
270
|
padding: var(--space-2) var(--space-3); background: transparent; color: var(--paper);
|
|
267
|
-
font-family: var(--ff-
|
|
271
|
+
font-family: var(--ff-body); font-size: var(--fs-tiny); letter-spacing: var(--tr-tight); font-weight: 500;
|
|
268
272
|
cursor: pointer; box-shadow: inset 0 0 0 1px var(--rule-strong);
|
|
269
273
|
border-radius: var(--r-pill); border: none;
|
|
270
274
|
}
|
|
@@ -431,7 +435,11 @@ table td.is-num, table th.is-num { text-align: right; font-variant-numeric: tabu
|
|
|
431
435
|
============================================================ */
|
|
432
436
|
.ds-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex-shrink: 0; vertical-align: middle; }
|
|
433
437
|
.ds-dot-on { color: var(--green-2); }
|
|
434
|
-
|
|
438
|
+
/* Off/idle reads as a HOLLOW ring (transparent fill, currentColor outline)
|
|
439
|
+
instead of a solid dot in a dimmer color -- filled-vs-outline is a shape
|
|
440
|
+
cue that survives grayscale/colorblind simulation, where a solid green dot
|
|
441
|
+
and a solid gray dot at the same size can look identical in luminance. */
|
|
442
|
+
.ds-dot-off { color: var(--fg-3); background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
|
|
435
443
|
/* live is a distinct hue from a plain "on" dot — see .chip.tone-live's
|
|
436
444
|
comment for the success-vs-live rationale. */
|
|
437
445
|
.ds-dot-live { color: var(--sky); }
|
|
@@ -496,7 +504,7 @@ table td.is-num, table th.is-num { text-align: right; font-variant-numeric: tabu
|
|
|
496
504
|
.kpi-card .lbl {
|
|
497
505
|
font-size: var(--fs-xs); color: var(--fg-3);
|
|
498
506
|
font-weight: 600; margin-top: 8px;
|
|
499
|
-
letter-spacing: var(--tr-
|
|
507
|
+
letter-spacing: var(--tr-tight);
|
|
500
508
|
}
|
|
501
509
|
.kpi-foot {
|
|
502
510
|
display: flex; align-items: center; justify-content: space-between;
|
|
@@ -487,8 +487,13 @@
|
|
|
487
487
|
/* .ds-field-eyebrow joins the kit small-label voice above with no overrides. */
|
|
488
488
|
.ds-hint-sm { font-size: var(--fs-xs); color: var(--panel-text-2); }
|
|
489
489
|
.ds-note-quiet { margin: 0; color: var(--panel-text-2); }
|
|
490
|
-
.ds-btn-row { display: flex; gap: var(--space-2, 8px); flex-wrap: wrap; }
|
|
490
|
+
.ds-btn-row { display: flex; gap: var(--space-2, 8px); flex-wrap: wrap; align-items: center; }
|
|
491
491
|
.ds-btn-row-tight { gap: var(--space-1-75, 6px); }
|
|
492
|
+
/* Size-ladder demo group: each size's caption+button pair stacks and the
|
|
493
|
+
group aligns at the BOTTOM so buttons of different heights share one
|
|
494
|
+
visual baseline instead of centering on their own mismatched midpoints. */
|
|
495
|
+
.ds-btn-size-row { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; }
|
|
496
|
+
.ds-btn-size-col { display: flex; flex-direction: column; gap: var(--space-1-75); align-items: flex-start; }
|
|
492
497
|
.ds-key-input { flex: 1 1 160px; min-width: 0; font-family: var(--ff-mono); }
|
|
493
498
|
.ds-toggle-btn { min-width: 78px; }
|
|
494
499
|
/* Side-by-side checked/unchecked reference pair (settings kit theme panel) --
|
|
@@ -799,7 +804,7 @@
|
|
|
799
804
|
.ds-avatar {
|
|
800
805
|
display: inline-flex; align-items: center; justify-content: center;
|
|
801
806
|
border-radius: 50%; background: var(--bg-3); color: var(--fg);
|
|
802
|
-
font-family: var(--ff-
|
|
807
|
+
font-family: var(--ff-body); font-weight: 600; text-transform: lowercase;
|
|
803
808
|
letter-spacing: 0.02em; user-select: none; flex-shrink: 0; object-fit: cover;
|
|
804
809
|
box-shadow: inset 0 0 0 1px var(--rule);
|
|
805
810
|
}
|
|
@@ -1024,8 +1029,7 @@
|
|
|
1024
1029
|
color: var(--fg-3);
|
|
1025
1030
|
font-family: var(--ff-mono);
|
|
1026
1031
|
font-size: var(--fs-xs);
|
|
1027
|
-
letter-spacing: 0
|
|
1028
|
-
text-transform: uppercase;
|
|
1032
|
+
letter-spacing: 0;
|
|
1029
1033
|
}
|
|
1030
1034
|
.panel.panel-docs .panel-title::before {
|
|
1031
1035
|
content: 'docs · ';
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
display: flex; align-items: center; gap: var(--space-2);
|
|
53
53
|
margin-bottom: var(--space-2);
|
|
54
54
|
}
|
|
55
|
-
.ds-mc-detail-title { font-family: var(--ff-
|
|
55
|
+
.ds-mc-detail-title { font-family: var(--ff-body); font-size: var(--fs-base); font-weight: 700; }
|
|
56
56
|
|
|
57
57
|
.ds-mc-discovery-error {
|
|
58
58
|
display: flex; align-items: center; gap: var(--space-1-75);
|
|
@@ -2,18 +2,40 @@
|
|
|
2
2
|
Panel — soft tonal container, no border decoration
|
|
3
3
|
============================================================ */
|
|
4
4
|
.panel {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/* PilotDeck-parity: the reference canvas has NO visible container edge
|
|
6
|
+
anywhere except a single hairline (sidebar only) — page bg and panel
|
|
7
|
+
fill read as the same tone. Stacking a tonal fill + a border + a shadow
|
|
8
|
+
(the previous three-layer treatment) is what critics independently
|
|
9
|
+
flagged as "every card reads as a boxed gray tile" / "grid of gray
|
|
10
|
+
cards" — the single most-repeated, highest-impact gap. Panels are now
|
|
11
|
+
flat (transparent, no border): content groups are separated by
|
|
12
|
+
whitespace and an optional --panel-shadow-1 whisper only, never a fill.
|
|
13
|
+
Use .panel-tonal to opt back into the filled/bordered look for surfaces
|
|
14
|
+
that genuinely need a floating card (e.g. dropdowns, dialogs already
|
|
15
|
+
have their own elevation scale and are unaffected). */
|
|
16
|
+
background: transparent;
|
|
17
|
+
border: none;
|
|
7
18
|
border-radius: var(--r-2);
|
|
8
|
-
|
|
9
|
-
|
|
19
|
+
/* AGENTS.md "outer 2:1 inner": outer separation is --space-6, inner
|
|
20
|
+
sibling gap --space-4 (48:24 = 2:1), matching .ds-panel-trio/
|
|
21
|
+
.ds-panel-duo. Bumped up one rung from --space-5/--space-3 for more
|
|
22
|
+
PilotDeck-style airy whitespace while preserving the 2:1 ratio. */
|
|
23
|
+
margin: 0 0 var(--space-6);
|
|
24
|
+
padding: var(--space-4);
|
|
10
25
|
position: relative;
|
|
11
|
-
/* Crisp, restrained elevation — a hairline border does the edge definition;
|
|
12
|
-
the shadow only adds a whisper of lift, not a soft glow-card float. */
|
|
13
|
-
box-shadow: var(--shadow-1);
|
|
14
26
|
transition: box-shadow var(--dur-base) var(--ease-spring), border-color var(--dur-snap) var(--ease),
|
|
15
27
|
transform var(--dur-base) var(--ease-spring);
|
|
16
28
|
}
|
|
29
|
+
/* Opt-in tonal/bordered card — the pre-restyle .panel look, kept for
|
|
30
|
+
surfaces that need to read as a discrete floating card rather than a
|
|
31
|
+
text grouping on flat canvas (e.g. a composer input, which PilotDeck
|
|
32
|
+
itself DOES give a faint 1px border+no fill — see .panel-inline below
|
|
33
|
+
for that exact treatment). */
|
|
34
|
+
.panel.panel-tonal {
|
|
35
|
+
background: var(--panel-1, var(--bg-2));
|
|
36
|
+
border: var(--bw-hair) solid var(--rule);
|
|
37
|
+
box-shadow: var(--panel-shadow-1);
|
|
38
|
+
}
|
|
17
39
|
/* Editorial accent spine — an opt-in printed-ink rule down the left edge that
|
|
18
40
|
reads as a magazine pull-quote bar, not a glow card. */
|
|
19
41
|
.panel.panel-spine {
|
|
@@ -25,7 +47,9 @@
|
|
|
25
47
|
width: var(--bw-chunk); background: var(--accent);
|
|
26
48
|
border-radius: var(--bw-chunk) 0 0 var(--bw-chunk);
|
|
27
49
|
}
|
|
28
|
-
|
|
50
|
+
/* PilotDeck's composer is the ONE element with a visible edge on an
|
|
51
|
+
otherwise flat canvas — a faint 1px border, no tonal fill. */
|
|
52
|
+
.panel.panel-inline { background: transparent; border: var(--bw-hair) solid var(--rule); padding: var(--space-3) var(--space-3); }
|
|
29
53
|
.panel.panel-wide { background: transparent; box-shadow: none; border: none; }
|
|
30
54
|
/* Changelog (and any other panel-wide content) needs its OWN container-query
|
|
31
55
|
context: the existing `@container (max-width: 760px) .ds-changelog-row`
|
|
@@ -56,11 +80,11 @@
|
|
|
56
80
|
rows sit on ONE left axis (the old 24/32 padding was authored for the
|
|
57
81
|
pre-padding .panel-wide era and indented the label 16px past its content). */
|
|
58
82
|
padding: var(--space-2) var(--space-3);
|
|
59
|
-
font-size: var(--fs-
|
|
60
|
-
color: var(--fg-
|
|
61
|
-
letter-spacing:
|
|
83
|
+
font-size: var(--fs-sm); font-weight: 600;
|
|
84
|
+
color: var(--fg-2);
|
|
85
|
+
letter-spacing: 0;
|
|
62
86
|
/* A hairline divider is the header's only structural separator from the
|
|
63
|
-
body — without it,
|
|
87
|
+
body — without it, a sentence-case label at fs-sm/600 reads as just
|
|
64
88
|
another dim meta line once the eye drops past the top of the panel. */
|
|
65
89
|
border-bottom: var(--bw-hair) solid var(--rule);
|
|
66
90
|
margin-bottom: var(--space-1);
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
|
|
54
54
|
.ds-plugins-row-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
55
55
|
.ds-plugins-row-name {
|
|
56
|
-
font-family: var(--ff-
|
|
56
|
+
font-family: var(--ff-body); font-size: var(--fs-sm); color: var(--fg);
|
|
57
57
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
58
58
|
}
|
|
59
59
|
.ds-plugins-row-meta {
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
}
|
|
83
83
|
.ds-plugins-detail-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
84
84
|
.ds-plugins-detail-title .name {
|
|
85
|
-
font-family: var(--ff-
|
|
85
|
+
font-family: var(--ff-body); font-size: var(--fs-md); font-weight: 600; color: var(--fg);
|
|
86
86
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
87
87
|
}
|
|
88
88
|
.ds-plugins-version { font-size: var(--fs-micro); color: var(--fg-3); }
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
|
|
119
119
|
.ds-plugins-group-label {
|
|
120
120
|
font-size: var(--fs-micro); font-weight: 600; color: var(--fg-3);
|
|
121
|
-
|
|
121
|
+
letter-spacing: 0; margin-bottom: 6px;
|
|
122
122
|
}
|
|
123
123
|
.ds-plugins-requires-list { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
124
124
|
.ds-plugins-chip {
|
|
@@ -21,9 +21,18 @@
|
|
|
21
21
|
font-weight: 700;
|
|
22
22
|
}
|
|
23
23
|
.btn-primary:hover { background: var(--fg); color: var(--bg); transform: translateY(-1px); box-shadow: var(--shadow-2); }
|
|
24
|
-
.btn-ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0
|
|
24
|
+
.btn-ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 var(--bw-hair) var(--fg); }
|
|
25
25
|
.btn-ghost:hover { background: color-mix(in oklab, var(--fg) 12%, transparent); transform: translateY(-1px); }
|
|
26
26
|
.btn:active, .btn-primary:active, .btn-ghost:active { transform: translateY(1px); box-shadow: none; }
|
|
27
|
+
/* Disabled state: --fg-3 (the tuned tertiary-text token, AA-clear against
|
|
28
|
+
every panel tier) instead of a blind opacity halving -- opacity multiplies
|
|
29
|
+
the SURROUNDING contrast too, so a light-on-dark button can drop under 3:1
|
|
30
|
+
even though "disabled" only needs to stay legible, not full-strength. */
|
|
31
|
+
.btn:disabled, .btn-primary:disabled, .btn-ghost:disabled,
|
|
32
|
+
.btn.is-disabled, .btn-primary.is-disabled, .btn-ghost.is-disabled {
|
|
33
|
+
background: var(--bg-2); color: var(--fg-3); border-color: var(--rule);
|
|
34
|
+
box-shadow: none; cursor: not-allowed; pointer-events: none;
|
|
35
|
+
}
|
|
27
36
|
.btn:focus-visible, .btn-primary:focus-visible, .btn-ghost:focus-visible, .ds-icon-btn:focus-visible {
|
|
28
37
|
outline: var(--focus-w) solid var(--focus-color);
|
|
29
38
|
outline-offset: var(--focus-offset);
|
|
@@ -33,6 +42,23 @@
|
|
|
33
42
|
height: var(--ctl-sm); min-height: var(--ctl-sm);
|
|
34
43
|
padding: 0 var(--space-2); font-size: var(--fs-tiny); gap: var(--space-1);
|
|
35
44
|
}
|
|
45
|
+
|
|
46
|
+
/* Link-styled button: an underline (not just color) is the affordance that
|
|
47
|
+
separates "this navigates" from "this triggers an action" -- .btn-ghost's
|
|
48
|
+
outline reads as a secondary ACTION button, not a link, at a glance. */
|
|
49
|
+
.btn-link {
|
|
50
|
+
display: inline-flex; align-items: center; gap: var(--space-1);
|
|
51
|
+
background: none; border: none; box-shadow: none; padding: 0;
|
|
52
|
+
height: auto; min-height: 0;
|
|
53
|
+
font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-sm);
|
|
54
|
+
color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
}
|
|
57
|
+
.btn-link:hover { color: var(--fg); }
|
|
58
|
+
.btn-link:focus-visible {
|
|
59
|
+
outline: var(--focus-w) solid var(--focus-color);
|
|
60
|
+
outline-offset: var(--focus-offset);
|
|
61
|
+
}
|
|
36
62
|
.btn-lg, .btn-lg.btn-primary, .btn-lg.btn-ghost {
|
|
37
63
|
height: var(--ctl-lg); min-height: var(--ctl-lg);
|
|
38
64
|
padding: 0 var(--space-4); font-size: var(--fs-body); gap: var(--space-2);
|
|
@@ -73,10 +99,13 @@
|
|
|
73
99
|
.ds-icon-btn-ghost:hover { background: var(--fg); color: var(--bg); }
|
|
74
100
|
.ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
|
|
75
101
|
.ds-icon-btn-primary:hover { background: var(--fg); color: var(--accent-ink); }
|
|
76
|
-
/* --
|
|
77
|
-
--warn (#FF5A52
|
|
78
|
-
|
|
79
|
-
|
|
102
|
+
/* --warn-fg (not a bare --ink/--on-color literal): --ink only clears AA
|
|
103
|
+
against dark theme's lighter --warn (#FF5A52, 6.27:1); light theme's
|
|
104
|
+
--warn is a darker red (#C41C0C) where --ink measures just 2.92:1, well
|
|
105
|
+
under the 4.5:1 floor. --warn-fg is the theme-paired token (light: paper
|
|
106
|
+
text 5.97:1, dark: ink text 6.27:1) -- same fix as .btn-primary.danger in
|
|
107
|
+
app-shell/files.css, which had this exact light-theme regression live. */
|
|
108
|
+
.ds-icon-btn-danger { background: var(--warn); color: var(--warn-fg); }
|
|
80
109
|
.ds-icon-btn-danger:hover { filter: brightness(0.92); }
|
|
81
110
|
.ds-icon-btn:active { transform: translateY(1px); }
|
|
82
111
|
.ds-icon-btn:disabled, .ds-icon-btn.is-disabled {
|
|
@@ -282,7 +311,7 @@
|
|
|
282
311
|
.ds-tooltip[data-placement^="bottom"]::after { top: -3px; left: 50%; margin-left: -3px; }
|
|
283
312
|
.ds-tooltip[data-placement^="left"]::after { right: -3px; top: 50%; margin-top: -3px; }
|
|
284
313
|
.ds-tooltip[data-placement^="right"]::after { left: -3px; top: 50%; margin-top: -3px; }
|
|
285
|
-
.ds-tooltip.kind-danger { background: var(--warn); color: var(--
|
|
314
|
+
.ds-tooltip.kind-danger { background: var(--warn); color: var(--warn-fg); }
|
|
286
315
|
.ds-tooltip.kind-danger::after { background: var(--warn); }
|
|
287
316
|
@media (prefers-reduced-motion: reduce) {
|
|
288
317
|
.ds-tooltip { transition: none; }
|
|
@@ -245,11 +245,14 @@
|
|
|
245
245
|
@media (prefers-reduced-motion: no-preference) {
|
|
246
246
|
.ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
|
|
247
247
|
}
|
|
248
|
-
/* Ultrawide:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
/* Ultrawide: .ws-shell itself stays full-width (fills the real screen edges
|
|
249
|
+
at any viewport, matching .app's own unbounded-width rule in topbar.css) --
|
|
250
|
+
only the 1fr content track's OWN inner measure is capped, so rail/sessions/
|
|
251
|
+
pane keep their fixed/clamped widths and only the middle content column's
|
|
252
|
+
text gets a readability ceiling, instead of the whole grid (and its side
|
|
253
|
+
columns) shrinking together and leaving dead margin on either side of the
|
|
254
|
+
shell. */
|
|
255
|
+
.ws-content { max-width: var(--measure-wide, 1200px); margin-inline: auto; width: 100%; }
|
|
253
256
|
|
|
254
257
|
/* Rail (left nav) */
|
|
255
258
|
.ws-rail {
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
|
|
20
20
|
.app-side .count {
|
|
21
21
|
padding: 1px 8px; font-size: var(--fs-micro); font-weight: 700;
|
|
22
|
-
font-family: var(--ff-
|
|
22
|
+
font-family: var(--ff-body); letter-spacing: 0.04em;
|
|
23
23
|
min-width: 18px; text-align: center;
|
|
24
24
|
}
|
|
25
25
|
.app-side a:has(> .count:empty) > .count,
|
|
26
26
|
.app-side .count:empty { display: none; }
|
|
27
|
-
.app-side a .glyph { font-family: var(--ff-
|
|
27
|
+
.app-side a .glyph { font-family: var(--ff-body); font-size: 13px; font-weight: 600; color: var(--fg-3); text-align: center; }
|
|
28
28
|
.app-side a.active .glyph { color: var(--accent-ink); }
|
|
29
29
|
|
|
30
30
|
/* -- select primitive --------------------------------------------------- */
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
.ds-skills-group-label {
|
|
15
15
|
padding: var(--space-2) var(--space-2) 3px;
|
|
16
16
|
font-size: var(--fs-micro); font-weight: 600; color: var(--fg-3);
|
|
17
|
-
|
|
17
|
+
letter-spacing: 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
.ds-skills-description { font-size: var(--fs-sm); color: var(--fg-2); line-height: 1.5; }
|