anentrypoint-design 0.0.379 → 0.0.381
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/app-shell.css +16 -0
- package/chat.css +102 -62
- package/colors_and_type.css +66 -7
- package/community.css +112 -70
- package/dist/247420.css +908 -308
- package/dist/247420.js +26 -23
- package/package.json +1 -1
- package/src/components/content.js +13 -4
- package/src/components/freddie/helpers.js +7 -0
- package/src/components/freddie.js +21 -21
- package/src/css/app-shell/base.css +11 -1
- package/src/css/app-shell/catalog-theme.css +7 -0
- package/src/css/app-shell/chat-polish.css +6 -1
- package/src/css/app-shell/data-density.css +22 -4
- package/src/css/app-shell/files.css +3 -3
- package/src/css/app-shell/hero-content.css +1 -1
- package/src/css/app-shell/kits-appended.css +387 -33
- package/src/css/app-shell/panel-row.css +6 -1
- package/src/css/app-shell/plugins-config.css +1 -1
- package/src/css/app-shell/responsive2-workspace.css +17 -12
- package/src/css/app-shell/states-interactions.css +9 -4
- package/src/kits/os/launcher.css +1 -1
- package/src/kits/os/theme.css +359 -283
- package/src/kits/os/wm.css +2 -2
- package/src/kits/slides/deck-stage-style.js +5 -2
- package/src/kits/spoint/host-join-lobby.css +1 -1
- package/src/kits/spoint/loading-screen.css +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.381",
|
|
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",
|
|
@@ -538,14 +538,23 @@ export function ProcessRegistryTable({ processes = [], emptyText = 'no live proc
|
|
|
538
538
|
|
|
539
539
|
export function HomeView({ state = {}, onNav, onToggleWork, works = [], posts = [], manifesto = [], currentlyShipping } = {}) {
|
|
540
540
|
return [
|
|
541
|
+
// The page's one deliberate kicker. 'an entrypoint' is the collective's
|
|
542
|
+
// name-as-tagline — it says something the <h1> does not, and it is the
|
|
543
|
+
// masthead position where a print eyebrow actually belongs. The sections
|
|
544
|
+
// below intentionally carry NO eyebrow: each has a heading that already
|
|
545
|
+
// names it, so a kicker there would only restate the <h3> one word
|
|
546
|
+
// shorter. Do not add eyebrows to the sibling sections to "match" this.
|
|
541
547
|
Hero({
|
|
542
548
|
eyebrow: 'an entrypoint',
|
|
543
549
|
title: 'Small, weird, useful tools — built in public.',
|
|
544
550
|
body: '247420 is a creative collective of eight, scattered across three timezones. We have been shipping open-source tools for the web since 2018.',
|
|
545
551
|
accent: 'Some become the future. Most don\'t. That\'s the deal.'
|
|
546
552
|
}),
|
|
553
|
+
// Titleless section: promoted its former eyebrow to the actual heading
|
|
554
|
+
// rather than leaving a kicker hovering over an unnamed panel. The label
|
|
555
|
+
// was carrying the section's only name, so it became the <h3>.
|
|
547
556
|
currentlyShipping ? Section({
|
|
548
|
-
|
|
557
|
+
title: 'currently shipping',
|
|
549
558
|
children: Panel({
|
|
550
559
|
kind: 'wide',
|
|
551
560
|
children: currentlyShipping.map((row, i) => {
|
|
@@ -560,15 +569,15 @@ export function HomeView({ state = {}, onNav, onToggleWork, works = [], posts =
|
|
|
560
569
|
})
|
|
561
570
|
}) : null,
|
|
562
571
|
works.length ? Section({
|
|
563
|
-
|
|
572
|
+
title: 'Everything else.',
|
|
564
573
|
children: WorksList({ works, openedIndex: state.opened ?? -1, onToggle: onToggleWork })
|
|
565
574
|
}) : null,
|
|
566
575
|
posts.length ? Section({
|
|
567
|
-
|
|
576
|
+
title: 'When we have something to say.',
|
|
568
577
|
children: WritingList({ posts })
|
|
569
578
|
}) : null,
|
|
570
579
|
manifesto.length ? Section({
|
|
571
|
-
|
|
580
|
+
title: 'Eight people, three timezones, one ongoing conversation.',
|
|
572
581
|
children: Manifesto({ paragraphs: manifesto })
|
|
573
582
|
}) : null
|
|
574
583
|
].filter(Boolean);
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
import * as webjsx from '../../../vendor/webjsx/index.js';
|
|
11
11
|
const h = webjsx.createElement;
|
|
12
12
|
|
|
13
|
+
// The ONE eyebrow on the freddie surface, and it earns it by being the only
|
|
14
|
+
// label that varies: `freddie · <id>` names the specific unimplemented route,
|
|
15
|
+
// which is the whole point of a stub — the reader needs to know WHICH page
|
|
16
|
+
// failed to resolve, and the <h2> below only shows a human title. The real
|
|
17
|
+
// freddie pages (src/components/freddie.js) deliberately carry NO eyebrow:
|
|
18
|
+
// there, the kicker was the constant string 'freddie' on all 22 headers, which
|
|
19
|
+
// named nothing the topbar/crumb did not already say. Do not add siblings.
|
|
13
20
|
export function renderPageStub({ id, title }) {
|
|
14
21
|
return h('div', { class: 'ds-freddie-stub' },
|
|
15
22
|
h('span', { class: 'eyebrow' }, 'freddie · ' + id),
|
|
@@ -80,7 +80,7 @@ export const home = makePage((ctx) => {
|
|
|
80
80
|
const tools = ctx.host?.pi?.tools?.size ?? s.toolsCount ?? '—';
|
|
81
81
|
const skills = ctx.host?.pi?.skills?.size ?? s.skillsCount ?? '—';
|
|
82
82
|
return [
|
|
83
|
-
PageHeader({
|
|
83
|
+
PageHeader({ title: 'dashboard', lede: 'agent harness · live overview' }),
|
|
84
84
|
Kpi({ items: [
|
|
85
85
|
[tools, 'tools'],
|
|
86
86
|
[skills, 'skills'],
|
|
@@ -315,7 +315,7 @@ export const voice = makePage((ctx) => {
|
|
|
315
315
|
const v = s.voice;
|
|
316
316
|
const enabled = v && (v.enabled || v.transcription || v.tts);
|
|
317
317
|
return [
|
|
318
|
-
PageHeader({
|
|
318
|
+
PageHeader({ title: 'voice', lede: 'voice surfaces', right: enabled ? Chip({ tone: 'ok', children: 'enabled' }) : Chip({ tone: 'neutral', children: 'not configured' }) }),
|
|
319
319
|
enabled
|
|
320
320
|
? section('backends', Table({ headers: ['capability', 'status'], rows: [['transcription', v.transcription ? Chip({ tone: 'ok', children: 'on' }) : Chip({ tone: 'neutral', children: 'off' })], ['tts', v.tts ? Chip({ tone: 'ok', children: 'on' }) : Chip({ tone: 'neutral', children: 'off' })]] }))
|
|
321
321
|
: section('status', emptyState('no voice backend wired in this build. configure a transcription/tts plugin to enable.')),
|
|
@@ -349,7 +349,7 @@ export const sessions = makePage((ctx) => {
|
|
|
349
349
|
if (s.error && !s.list) return errorState(s.error, load);
|
|
350
350
|
const list = Array.isArray(s.list) ? s.list : [];
|
|
351
351
|
return [
|
|
352
|
-
PageHeader({
|
|
352
|
+
PageHeader({ title: 'sessions', lede: list.length + ' sessions', right: refreshBtn(refresh, s.refreshing) }),
|
|
353
353
|
s.error && s.list ? refreshError(s.error) : null,
|
|
354
354
|
SearchInput({ value: s.q, label: 'search sessions', placeholder: 'search messages…', onInput: (v) => { s.q = v; }, onSubmit: (v) => search(v) }),
|
|
355
355
|
section('sessions',
|
|
@@ -392,7 +392,7 @@ export const projects = makePage((ctx) => {
|
|
|
392
392
|
const d = s.data || {}; const list = d.projects || [];
|
|
393
393
|
const activeName = (d.active && d.active.name) || d.active || 'default';
|
|
394
394
|
return [
|
|
395
|
-
PageHeader({
|
|
395
|
+
PageHeader({ title: 'projects', lede: 'isolated workspaces · active: ' + activeName }),
|
|
396
396
|
noteAlert(s.note),
|
|
397
397
|
section('projects',
|
|
398
398
|
list.length ? list.map((p, i) => Row({
|
|
@@ -421,7 +421,7 @@ export const agents = makePage((ctx) => {
|
|
|
421
421
|
if (s.error && !s.data) return errorState(s.error, load);
|
|
422
422
|
const d = s.data || {};
|
|
423
423
|
return [
|
|
424
|
-
PageHeader({
|
|
424
|
+
PageHeader({ title: 'agents', lede: 'live agent activity' }),
|
|
425
425
|
s.error && s.data ? refreshError(s.error) : null,
|
|
426
426
|
Kpi({ items: [[d.count ?? 0, 'active'], [d.turns ?? 0, 'total turns'], [d.last_activity ? fmtAgo(d.last_activity) : '—', 'last activity']] }),
|
|
427
427
|
section('detail', Table({ headers: ['field', 'value'], rows: Object.entries(d).map(([k, v]) => [k, String(v)]) })),
|
|
@@ -450,7 +450,7 @@ export const analytics = makePage((ctx) => {
|
|
|
450
450
|
const ok = samp.filter(x => x && x.available !== false).length;
|
|
451
451
|
const sum = s.avail?.summary || {};
|
|
452
452
|
return [
|
|
453
|
-
PageHeader({
|
|
453
|
+
PageHeader({ title: 'analytics', lede: 'provider availability & sampler health' }),
|
|
454
454
|
s.error && (s.sampler || s.avail) ? refreshError(s.error) : null,
|
|
455
455
|
Kpi({ items: [[ok + '/' + samp.length, 'providers up'], [sum.total_models ?? '—', 'models'], [sum.usable_in_any_mode ?? '—', 'usable']] }),
|
|
456
456
|
section('sampler', samp.length ? Table({ headers: ['provider', 'available', 'fails'], rows: Object.entries(s.sampler.status).map(([k, v]) => [k, v.available === false ? 'no' : 'yes', String(v.failCount ?? 0)]) }) : emptyState('no sampler data')),
|
|
@@ -482,7 +482,7 @@ export const models = makePage((ctx) => {
|
|
|
482
482
|
return () => {
|
|
483
483
|
const s = ctx.state;
|
|
484
484
|
return [
|
|
485
|
-
PageHeader({
|
|
485
|
+
PageHeader({ title: 'models', lede: s.data ? (s.data.summary?.total_models ?? 0) + ' models across ' + (s.data.summary?.total_providers ?? 0) + ' providers' : 'model availability matrix' }),
|
|
486
486
|
ModelsConfig({
|
|
487
487
|
data: s.data, loading: s.loading, error: s.error,
|
|
488
488
|
selectedProviderId: s.selectedProviderId, onSelectProvider: (id) => ctx.set({ selectedProviderId: id, selectedModel: null }),
|
|
@@ -514,7 +514,7 @@ export const cron = makePage((ctx) => {
|
|
|
514
514
|
if (s.error && !s.list) return errorState(s.error, load);
|
|
515
515
|
const list = Array.isArray(s.list) ? s.list : [];
|
|
516
516
|
return [
|
|
517
|
-
PageHeader({
|
|
517
|
+
PageHeader({ title: 'cron', lede: list.length + ' scheduled jobs' }),
|
|
518
518
|
noteAlert(s.note),
|
|
519
519
|
section('jobs', list.length ? list.map((j, i) => Row({
|
|
520
520
|
key: i, code: j.enabled ? Icon('play') : Icon('pause'), title: j.cron, sub: trunc(j.prompt, TRUNC_SUB).text,
|
|
@@ -553,7 +553,7 @@ export const skills = makePage((ctx) => {
|
|
|
553
553
|
enabled: skillState[sk.name] !== false,
|
|
554
554
|
}));
|
|
555
555
|
return [
|
|
556
|
-
PageHeader({
|
|
556
|
+
PageHeader({ title: 'skills', lede: mapped.length + ' skills' }),
|
|
557
557
|
SkillsConfig({
|
|
558
558
|
skills: mapped, selected: s.selected, loading: s.loading, error: s.error,
|
|
559
559
|
busyName: s.busyName, query: s.query, onQuery: (q) => ctx.set({ query: q }),
|
|
@@ -577,7 +577,7 @@ export const plugins = makePage((ctx) => {
|
|
|
577
577
|
const s = ctx.state;
|
|
578
578
|
const list = Array.isArray(s.list) ? s.list : (s.list?.plugins || []);
|
|
579
579
|
return [
|
|
580
|
-
PageHeader({
|
|
580
|
+
PageHeader({ title: 'plugins', lede: list.length + ' plugins loaded' }),
|
|
581
581
|
PluginsConfig({
|
|
582
582
|
plugins: list, selected: s.selected, loading: s.loading, error: s.error,
|
|
583
583
|
onSelect: (name) => ctx.set({ selected: s.selected === name ? null : name }),
|
|
@@ -620,7 +620,7 @@ export const config = makePage((ctx) => {
|
|
|
620
620
|
const skinList = Array.isArray(s.skins) ? s.skins : (s.skins?.skins || s.skins?.available || []);
|
|
621
621
|
const activeSkin = cfg.skin || s.skins?.active || '';
|
|
622
622
|
return [
|
|
623
|
-
PageHeader({
|
|
623
|
+
PageHeader({ title: 'config', lede: 'runtime configuration' }),
|
|
624
624
|
noteAlert(s.note),
|
|
625
625
|
liveRegion(s.busy ? 'saving configuration' : ''),
|
|
626
626
|
nested.length ? h('div', { class: 'ds-alert ds-alert-info', role: 'note' },
|
|
@@ -676,7 +676,7 @@ export const env = makePage((ctx) => {
|
|
|
676
676
|
const providerEnvs = new Set(auth.map(a => a.env));
|
|
677
677
|
const otherRows = vars.filter(v => !providerEnvs.has(v.key)).map(v => [v.key, v.set ? Chip({ tone: 'ok', children: v.source || 'set' }) : Chip({ tone: 'neutral', children: 'unset' })]);
|
|
678
678
|
return [
|
|
679
|
-
PageHeader({
|
|
679
|
+
PageHeader({ title: 'keys', lede: 'provider api keys · stored locally, never displayed' }),
|
|
680
680
|
noteAlert(s.note),
|
|
681
681
|
section('provider keys',
|
|
682
682
|
auth.length ? auth.map((a, i) => Row({
|
|
@@ -707,7 +707,7 @@ export const tools = makePage((ctx) => {
|
|
|
707
707
|
const groups = {};
|
|
708
708
|
for (const t of list) { const g = t.toolset || 'core'; (groups[g] = groups[g] || []).push(t); }
|
|
709
709
|
return [
|
|
710
|
-
PageHeader({
|
|
710
|
+
PageHeader({ title: 'tools', lede: list.length + ' tools' }),
|
|
711
711
|
SearchInput({ value: s.q, label: 'filter tools', placeholder: 'filter tools…', onInput: (v) => ctx.set({ q: v }) }),
|
|
712
712
|
...Object.entries(groups).map(([g, ts]) => section(g + ' · ' + ts.length, ts.map((t, i) => h('div', { key: i },
|
|
713
713
|
Row({ title: t.name, sub: trunc(t.schema?.description || t.description, TRUNC_DESC).text, onClick: () => ctx.set({ open: ctx.state.open === t.name ? null : t.name }), active: ctx.state.open === t.name }),
|
|
@@ -733,7 +733,7 @@ export const batch = makePage((ctx) => {
|
|
|
733
733
|
return () => {
|
|
734
734
|
const s = ctx.state;
|
|
735
735
|
return [
|
|
736
|
-
PageHeader({
|
|
736
|
+
PageHeader({ title: 'batch', lede: 'parallel prompt runner' }),
|
|
737
737
|
noteAlert(s.note),
|
|
738
738
|
section('prompts',
|
|
739
739
|
TextField({ label: 'prompts (one per line)', value: s.prompts, multiline: true, rows: 6, onInput: (v) => { s.prompts = v; } }),
|
|
@@ -767,7 +767,7 @@ export const gateway = makePage((ctx) => {
|
|
|
767
767
|
const platforms = d.platforms || d;
|
|
768
768
|
const rows = Object.entries(platforms).map(([k, v]) => [k, typeof v === 'object' ? (v.running || v.up ? Chip({ tone: 'ok', children: 'up' }) : Chip({ tone: 'miss', children: 'down' })) : String(v)]);
|
|
769
769
|
return [
|
|
770
|
-
PageHeader({
|
|
770
|
+
PageHeader({ title: 'gateway', lede: 'messaging platform status' }),
|
|
771
771
|
s.error && s.data ? refreshError(s.error) : null,
|
|
772
772
|
section('platforms', rows.length ? Table({ headers: ['platform', 'status'], rows }) : emptyState('no platforms configured')),
|
|
773
773
|
].filter(Boolean);
|
|
@@ -806,7 +806,7 @@ export const chains = makePage((ctx) => {
|
|
|
806
806
|
const chainsList = s.list?.chains || s.list || [];
|
|
807
807
|
const up = s.health && (s.health.ok || s.health.status === 'ok' || s.health.healthy);
|
|
808
808
|
return [
|
|
809
|
-
PageHeader({
|
|
809
|
+
PageHeader({ title: 'chains', lede: 'acptoapi fallback chains', right: up ? Chip({ tone: 'ok', children: 'acptoapi up' }) : Chip({ tone: 'miss', children: 'acptoapi down' }) }),
|
|
810
810
|
noteAlert(s.note),
|
|
811
811
|
section('chains', Array.isArray(chainsList) && chainsList.length ? chainsList.map((c, i) => Row({
|
|
812
812
|
key: i, title: c.name || c, sub: Array.isArray(c.links) ? c.links.join(' -> ') : '',
|
|
@@ -833,7 +833,7 @@ export const machines = makePage((ctx) => {
|
|
|
833
833
|
const d = s.data || {};
|
|
834
834
|
const list = Array.isArray(d) ? d : (d.machines || Object.entries(d).map(([kind, v]) => ({ kind, ...(typeof v === 'object' ? v : { value: v }) })));
|
|
835
835
|
return [
|
|
836
|
-
PageHeader({
|
|
836
|
+
PageHeader({ title: 'machines', lede: 'persisted xstate machine census' }),
|
|
837
837
|
s.error && s.data ? refreshError(s.error) : null,
|
|
838
838
|
section('machines', list.length ? Table({
|
|
839
839
|
headers: ['kind', 'key', 'state'],
|
|
@@ -863,7 +863,7 @@ export const health = makePage((ctx) => {
|
|
|
863
863
|
const hd = s.health || {};
|
|
864
864
|
const provs = Array.isArray(s.providers) ? s.providers : (s.providers?.providers || []);
|
|
865
865
|
return [
|
|
866
|
-
PageHeader({
|
|
866
|
+
PageHeader({ title: 'health', lede: 'system & provider health', right: hd.ok ? Chip({ tone: 'ok', children: 'healthy' }) : Chip({ tone: 'miss', children: 'degraded' }) }),
|
|
867
867
|
s.error && (s.health || s.providers) ? refreshError(s.error) : null,
|
|
868
868
|
section('checks', Object.keys(hd).length ? Table({ headers: ['check', 'status'], rows: Object.entries(hd).map(([k, v]) => [k, typeof v === 'object' ? truncJson(v) : (v === true ? Chip({ tone: 'ok', children: 'ok' }) : v === false ? Chip({ tone: 'miss', children: 'no' }) : String(v))]) }) : emptyState('no health data')),
|
|
869
869
|
provs.length ? section('providers', Table({ headers: ['provider', 'status'], rows: provs.map(p => { const n = typeof p === 'string' ? p : p.name || p.id; const ok = typeof p === 'object' ? (p.ok ?? p.available) : null; return [n, ok == null ? '—' : (ok ? Chip({ tone: 'ok', children: 'up' }) : Chip({ tone: 'miss', children: 'down' }))]; }) })) : null,
|
|
@@ -931,7 +931,7 @@ export const logs = makePage((ctx) => {
|
|
|
931
931
|
const severities = ['error', 'warning', 'info', 'debug'];
|
|
932
932
|
return [
|
|
933
933
|
PageHeader({
|
|
934
|
-
|
|
934
|
+
title: 'logs', lede: 'live JSONL log tail — /api/logs/stream',
|
|
935
935
|
right: s.connected ? Chip({ tone: 'ok', children: 'live' }) : Chip({ tone: 'miss', children: 'reconnecting…' }),
|
|
936
936
|
}),
|
|
937
937
|
s.wsError ? refreshError(s.wsError) : null,
|
|
@@ -981,7 +981,7 @@ export const debug = makePage((ctx) => {
|
|
|
981
981
|
const d = s.data || {};
|
|
982
982
|
const subsystems = d.subsystems || Object.keys(d);
|
|
983
983
|
return [
|
|
984
|
-
PageHeader({
|
|
984
|
+
PageHeader({ title: 'debug', lede: 'subsystem snapshots & logs' }),
|
|
985
985
|
section('subsystems', subsystems.length ? subsystems.map((name, i) => Row({
|
|
986
986
|
key: i, title: name, onClick: () => loadLogs(name), active: s.sub === name,
|
|
987
987
|
})) : emptyState('no debug subsystems')),
|
|
@@ -1041,7 +1041,7 @@ export const git = makePage((ctx) => {
|
|
|
1041
1041
|
const worktrees = wtFailed ? [] : (s.worktrees && s.worktrees.worktrees) || s.worktrees || [];
|
|
1042
1042
|
const current = Array.isArray(worktrees) ? (worktrees.find(w => w.path === s.cwd) || {}).path : undefined;
|
|
1043
1043
|
return [
|
|
1044
|
-
PageHeader({
|
|
1044
|
+
PageHeader({ title: 'git', lede: s.cwd || 'active project' }),
|
|
1045
1045
|
noteAlert(s.note),
|
|
1046
1046
|
statusFailed ? refreshError(statusFailed) : null,
|
|
1047
1047
|
section('worktrees',
|
|
@@ -23,7 +23,10 @@ button, input, select, textarea { font: inherit; }
|
|
|
23
23
|
color: var(--accent-fg);
|
|
24
24
|
padding: 8px 16px;
|
|
25
25
|
text-decoration: none;
|
|
26
|
-
|
|
26
|
+
/* Must outrank every layer of chrome once focused, or the first Tab press
|
|
27
|
+
lands on a control hidden behind the sticky header (was z-index:100,
|
|
28
|
+
which the header alone now matches). */
|
|
29
|
+
z-index: var(--z-top);
|
|
27
30
|
border-radius: var(--r-pill);
|
|
28
31
|
font-weight: 600;
|
|
29
32
|
font-size: var(--fs-sm);
|
|
@@ -78,6 +81,13 @@ h4, .t-h4 { font-family: var(--ff-display); font-size: var(--fs-h4); line-height
|
|
|
78
81
|
.t-mono { font-family: var(--ff-mono); }
|
|
79
82
|
.t-body { font-family: var(--ff-body); }
|
|
80
83
|
|
|
84
|
+
/* House small-label voice, in two sizes. Every declaration here is sourced
|
|
85
|
+
from a token, so a sheet that cannot join these selector lists (community.css
|
|
86
|
+
and gm-prose.css ship as separate <link>-able exports and must not depend on
|
|
87
|
+
app-shell.css being present) still composes the same voice by referencing the
|
|
88
|
+
same four tokens — --ff-mono / --fs-* / uppercase / --tr-label. That token
|
|
89
|
+
set, not this rule, is the single source of truth; a selector that restates a
|
|
90
|
+
literal instead of the token is the drift this pairing exists to prevent. */
|
|
81
91
|
.t-label { font-family: var(--ff-mono); font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--tr-label); font-weight: 500; }
|
|
82
92
|
.t-micro { font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-label); color: var(--fg-3); }
|
|
83
93
|
.t-meta { font-family: var(--ff-body); font-size: var(--fs-sm); color: var(--fg-3); }
|
|
@@ -121,6 +121,13 @@
|
|
|
121
121
|
transition: color var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
|
|
122
122
|
}
|
|
123
123
|
.ds-segmented .ds-seg-btn:hover { color: var(--fg); }
|
|
124
|
+
/* Touch floor — a segmented control is a primary mode switch but renders ~30px
|
|
125
|
+
tall from its 4px padding, below the 44px minimum the rest of the system
|
|
126
|
+
holds. Grows the hit area only; the pill's visual size is unchanged at
|
|
127
|
+
fine-pointer sizes. */
|
|
128
|
+
@media (pointer: coarse) {
|
|
129
|
+
.ds-segmented .ds-seg-btn { min-height: 44px; padding-inline: var(--space-3); }
|
|
130
|
+
}
|
|
124
131
|
.ds-segmented .ds-seg-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
|
|
125
132
|
.ds-segmented .ds-seg-btn.is-on {
|
|
126
133
|
background: var(--bg); color: var(--fg);
|
|
@@ -126,7 +126,12 @@
|
|
|
126
126
|
.chat-bubble.chat-md li { margin: var(--space-1) 0; }
|
|
127
127
|
.chat-bubble.chat-md blockquote {
|
|
128
128
|
margin: var(--space-2) 0; padding: 4px 12px;
|
|
129
|
-
|
|
129
|
+
/* DELIBERATE, but slimmed to the --bw-rule tier. This is a real markdown
|
|
130
|
+
<blockquote> inside a chat bubble: the left rule is the standard
|
|
131
|
+
typographic quotation mark, not a colored alert stripe (the tone is a
|
|
132
|
+
currentColor mix that inherits the bubble's own ink — never an accent).
|
|
133
|
+
A 3px off-scale literal read as the generic tell; 2px reads as type. */
|
|
134
|
+
border-left: var(--bw-rule) solid color-mix(in oklab, currentColor 30%, transparent);
|
|
130
135
|
color: color-mix(in oklab, currentColor 75%, transparent); font-style: italic;
|
|
131
136
|
}
|
|
132
137
|
.chat-bubble.chat-md pre {
|
|
@@ -102,10 +102,28 @@
|
|
|
102
102
|
.ds-sub-btn:hover { border-color: var(--accent); color: var(--accent-ink); }
|
|
103
103
|
.ds-sub-btn span { display: block; font-size: 18px; font-weight: 700; color: var(--accent-ink); }
|
|
104
104
|
|
|
105
|
-
/* SessionRow —
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
/* SessionRow — the RICH treatment (hover/focus/active, rail tones, nesting,
|
|
106
|
+
inline rename/delete) lives in chat.css with the rest of the chat session
|
|
107
|
+
list. But SessionRow is part of this data-density family and is used by kits
|
|
108
|
+
that never link chat.css (gm_inspector links only colors_and_type +
|
|
109
|
+
app-shell + editor-primitives), where the component rendered with NO layout
|
|
110
|
+
at all: gap resolved to `normal`, so id/counts/devcnt/phasewalk/span all
|
|
111
|
+
butted together at 0px. The layout floor therefore belongs here, next to the
|
|
112
|
+
sub-parts it positions, so the component is never shipped shapeless.
|
|
113
|
+
chat.css still layers its interactive states on top; these declarations are
|
|
114
|
+
identical to the ones there, so a kit loading both gets the same result. */
|
|
115
|
+
.ds-session-row {
|
|
116
|
+
position: relative; display: flex; align-items: center; gap: var(--space-2);
|
|
117
|
+
width: 100%; padding: var(--space-2); min-height: 52px; margin-bottom: 2px;
|
|
118
|
+
background: transparent; border: none; border-radius: var(--r-1);
|
|
119
|
+
text-align: left; color: var(--fg);
|
|
120
|
+
}
|
|
121
|
+
/* Only an interactive row gets the pointer affordance (chat.css sets cursor
|
|
122
|
+
unconditionally because every row there is clickable; here rows are often
|
|
123
|
+
static readouts). */
|
|
124
|
+
.ds-session-row[role="button"], a.ds-session-row { cursor: pointer; }
|
|
125
|
+
|
|
126
|
+
/* Sub-parts that decorate the row above. */
|
|
109
127
|
.ds-session-row-id {
|
|
110
128
|
font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--accent-ink);
|
|
111
129
|
flex: 0 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
}
|
|
302
302
|
.ds-file-cell-meta { font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg-3); text-align: left; }
|
|
303
303
|
.ds-file-cell-check {
|
|
304
|
-
position: absolute; top: 4px; left: 4px; z-index:
|
|
304
|
+
position: absolute; top: 4px; left: 4px; z-index: var(--z-raised);
|
|
305
305
|
background: color-mix(in oklab, var(--bg) 78%, transparent);
|
|
306
306
|
}
|
|
307
307
|
|
|
@@ -447,7 +447,7 @@
|
|
|
447
447
|
.ds-dropzone--wrap { position: relative; border: none; border-radius: 0; background: transparent; }
|
|
448
448
|
.ds-dropzone--wrap > .ds-dropzone-inner { display: none; }
|
|
449
449
|
.ds-dropzone--wrap.dragover > .ds-dropzone-inner {
|
|
450
|
-
display: flex; position: absolute; inset: 0; z-index:
|
|
450
|
+
display: flex; position: absolute; inset: 0; z-index: var(--z-raised);
|
|
451
451
|
margin: 0; padding: var(--space-3);
|
|
452
452
|
align-items: center; justify-content: center;
|
|
453
453
|
background: color-mix(in srgb, var(--bg) 84%, transparent);
|
|
@@ -539,7 +539,7 @@
|
|
|
539
539
|
|
|
540
540
|
/* -- Modals ------------------------------------------------- */
|
|
541
541
|
.ds-modal-backdrop {
|
|
542
|
-
position: fixed; inset: 0; z-index: var(--z-modal
|
|
542
|
+
position: fixed; inset: 0; z-index: var(--z-modal);
|
|
543
543
|
display: flex; align-items: center; justify-content: center;
|
|
544
544
|
/* Notch/home-indicator safe: near-fullscreen modals must not slide under. */
|
|
545
545
|
padding: max(var(--space-3), env(safe-area-inset-top))
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
============================================================ */
|
|
101
101
|
.ds-grain { position: relative; isolation: isolate; }
|
|
102
102
|
.ds-grain::after {
|
|
103
|
-
content: ''; position: absolute; inset: 0; z-index: -
|
|
103
|
+
content: ''; position: absolute; inset: 0; z-index: var(--z-below);
|
|
104
104
|
pointer-events: none;
|
|
105
105
|
background-image: var(--grain);
|
|
106
106
|
background-size: 160px 160px;
|