@changfenhuang/dsh-genui 0.9.9 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/SKILL.md +128 -6
- package/lib/assets/echarts-core.js +43 -0
- package/lib/assets/{echarts.js → echarts-full.js} +1 -1
- package/lib/assets/mermaid.js +1 -1
- package/lib/client.js +5 -3
- package/lib/index.js +230 -69
- package/lib/types/client/EChartNode.d.ts +9 -0
- package/lib/types/client/GenuiBlock.d.ts +3 -4
- package/lib/types/client/asset-echarts-core.d.ts +1 -0
- package/lib/types/client/asset-echarts.d.ts +3 -2
- package/lib/types/client/asset-loader.d.ts +2 -2
- package/lib/types/client/blocks/advanced.d.ts +0 -3
- package/lib/types/client/blocks/charts.d.ts +23 -12
- package/lib/types/client/blocks/state.d.ts +5 -3
- package/lib/types/client/echarts-lazy.d.ts +4 -1
- package/lib/types/client/genui-runtime/schema.d.ts +11 -1
- package/lib/types/client/inline.d.ts +29 -0
- package/lib/types/client/spec.d.ts +76 -6
- package/lib/types/plugin/index.d.ts +1 -1
- package/package.json +4 -3
- package/src/client/EChartNode.tsx +233 -19
- package/src/client/GenuiBlock.module.css +895 -145
- package/src/client/GenuiBlock.tsx +31 -23
- package/src/client/PlotBlock.module.css +17 -1
- package/src/client/PlotBlock.tsx +33 -1
- package/src/client/asset-echarts-core.ts +39 -0
- package/src/client/asset-echarts.ts +4 -3
- package/src/client/asset-loader.ts +5 -3
- package/src/client/blocks/advanced.tsx +60 -16
- package/src/client/blocks/charts.tsx +761 -144
- package/src/client/blocks/render-node.tsx +252 -11
- package/src/client/blocks/state.ts +5 -3
- package/src/client/dom-fence.tsx +60 -6
- package/src/client/echarts-lazy.ts +11 -2
- package/src/client/fence-render.tsx +6 -5
- package/src/client/gallery.ts +78 -2
- package/src/client/genui-runtime/schema.ts +45 -11
- package/src/client/guard.ts +161 -23
- package/src/client/index.tsx +14 -3
- package/src/client/inline.ts +73 -0
- package/src/client/mermaid-core.ts +42 -5
- package/src/client/spec.ts +79 -6
- package/src/plugin/index.ts +33 -45
- package/src/plugin/tool.ts +5 -1
- package/tsdown.config.ts +2 -1
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
literals here are only last-resort fallbacks for hosts without the token
|
|
17
17
|
sheets. */
|
|
18
18
|
|
|
19
|
+
/* Dark theme: the layer step already lifts the card off the canvas, so the
|
|
20
|
+
extra label tint stays a small overlay (4%) instead of the 10% that light
|
|
21
|
+
mode needs to clear the 4% lightness-step minimum. */
|
|
22
|
+
body[data-ds-dark-theme] .block,
|
|
23
|
+
body[data-ds-dark-theme] .panel {
|
|
24
|
+
--dsl-g-surface: color-mix(in srgb, var(--dsw-alias-label-primary) 4%,
|
|
25
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, var(--dsw-alias-markdown-code-block, transparent))));
|
|
26
|
+
--dsl-g-shadow-card: 0 1px 2px rgba(0, 0, 0, 0.24), 0 8px 24px rgba(0, 0, 0, 0.18);
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
.block,
|
|
20
30
|
.panel {
|
|
21
31
|
/* ── design tokens (design system v2) ──
|
|
@@ -25,16 +35,22 @@
|
|
|
25
35
|
gap/padding collapsed to zero). */
|
|
26
36
|
--dsl-g-radius-surface: 12px;
|
|
27
37
|
--dsl-g-radius-control: 8px;
|
|
38
|
+
--dsl-g-radius-sm: 6px;
|
|
28
39
|
--dsl-g-radius-pill: 999px;
|
|
29
40
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
--dsl-g-font-
|
|
35
|
-
--dsl-g-font-
|
|
36
|
-
--dsl-g-font-
|
|
37
|
-
--dsl-g-font-
|
|
41
|
+
/* Design system v4: the v3 scale was too compressed — every level sat
|
|
42
|
+
within 26..12px, so nothing dominated. v4 restores a display contrast
|
|
43
|
+
(hero 34 / display 28 / h1 24 / h2 19 / h3 16) against a 14.5px body, and
|
|
44
|
+
the reading floor stays 12px. */
|
|
45
|
+
--dsl-g-font-hero: 34px;
|
|
46
|
+
--dsl-g-font-display: 28px;
|
|
47
|
+
--dsl-g-font-h1: 24px;
|
|
48
|
+
--dsl-g-font-h2: 19px;
|
|
49
|
+
--dsl-g-font-h3: 16px;
|
|
50
|
+
--dsl-g-font-body: 14.5px;
|
|
51
|
+
--dsl-g-font-title: 13.5px;
|
|
52
|
+
--dsl-g-font-meta: 12.5px;
|
|
53
|
+
--dsl-g-font-data: 12px;
|
|
38
54
|
|
|
39
55
|
--dsl-g-gap-lg: 16px;
|
|
40
56
|
--dsl-g-gap-md: 12px;
|
|
@@ -48,9 +64,28 @@
|
|
|
48
64
|
/* Row/surface hover: a 4% wash of the theme's own label color works on
|
|
49
65
|
* dark AND light hosts without any off-brand literal. */
|
|
50
66
|
--dsl-g-hover: color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);
|
|
67
|
+
/* Zebra rows / table header wash: half the hover strength, so a striped
|
|
68
|
+
table still reads as one surface rather than a stack of bands. */
|
|
69
|
+
--dsl-g-zebra: color-mix(in srgb, var(--dsw-alias-label-primary) 2.5%, transparent);
|
|
51
70
|
--dsl-g-tint: 8%;
|
|
52
71
|
--dsl-g-tint-strong: 14%;
|
|
53
72
|
--dsl-g-font-mono: var(--ds-font-family-code, ui-monospace, 'SF Mono', monospace);
|
|
73
|
+
/* Elevation, theme-agnostic: the light theme maps EVERY bg layer to white,
|
|
74
|
+
so a card there is white-on-white and a border alone cannot carry the
|
|
75
|
+
hierarchy. Both a tint of the theme's own label colour and the surface
|
|
76
|
+
border are derived from tokens that exist in both themes:
|
|
77
|
+
light: label ≈ near-black → tint darkens the white card to ~#f5f5f5
|
|
78
|
+
dark : label ≈ near-white → tint lifts the card off the page */
|
|
79
|
+
/* 4% / 14% measured as 255→246 and read as "no difference" in review: the
|
|
80
|
+
tint now sits clearly above the perception floor. Light: page 255 → card
|
|
81
|
+
~232, border ~190. Dark: page 21 → card ~62 (an unmistakable elevation). */
|
|
82
|
+
--dsl-g-surface: color-mix(in srgb, var(--dsw-alias-label-primary) 10%,
|
|
83
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, var(--dsw-alias-markdown-code-block, transparent))));
|
|
84
|
+
/* Borders separate, shadows lift (design standard: "shadows over borders"):
|
|
85
|
+
the outline stays quiet and the layered shadow carries the depth, with the
|
|
86
|
+
first layer at the documented minimum `0 1px 3px rgba(0,0,0,0.10)`. */
|
|
87
|
+
--dsl-g-border-surface: color-mix(in srgb, var(--dsw-alias-label-primary) 12%, transparent);
|
|
88
|
+
--dsl-g-shadow-card: 0 1px 3px rgba(0, 0, 0, 0.10), 0 8px 24px rgba(0, 0, 0, 0.06);
|
|
54
89
|
}
|
|
55
90
|
|
|
56
91
|
.block {
|
|
@@ -60,15 +95,23 @@
|
|
|
60
95
|
does not need a card wrapper. */
|
|
61
96
|
margin: 8px 0;
|
|
62
97
|
color: var(--dsw-alias-label-primary);
|
|
98
|
+
/* Numbers line up wherever they appear (stats, tables, progress, legends). */
|
|
99
|
+
font-variant-numeric: tabular-nums;
|
|
63
100
|
}
|
|
101
|
+
/* Content-box padding made a <select> and an <input> with the same
|
|
102
|
+
width:100% measure 365 vs 391px. One reset inside our subtree. */
|
|
103
|
+
.block *, .block *::before, .block *::after,
|
|
104
|
+
.panel *, .panel *::before, .panel *::after { box-sizing: border-box; }
|
|
64
105
|
|
|
65
106
|
.banner {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
107
|
+
/* Hierarchy through type, not decoration: 22px/800 with generous space
|
|
108
|
+
below. The accent bars v4 added read as PPT chrome and are gone. */
|
|
109
|
+
font-size: 22px;
|
|
110
|
+
font-weight: 800;
|
|
111
|
+
letter-spacing: -0.02em;
|
|
69
112
|
color: var(--dsw-alias-label-primary);
|
|
70
|
-
padding-bottom:
|
|
71
|
-
margin-bottom:
|
|
113
|
+
padding-bottom: 14px;
|
|
114
|
+
margin-bottom: 18px;
|
|
72
115
|
border-bottom: 1px solid var(--dsl-g-border);
|
|
73
116
|
}
|
|
74
117
|
|
|
@@ -78,6 +121,17 @@
|
|
|
78
121
|
.row { display: flex; align-items: center; gap: var(--dsl-g-gap-md); }
|
|
79
122
|
.row.wrap { flex-wrap: wrap; }
|
|
80
123
|
.grid { display: grid; gap: var(--dsl-g-gap-md); }
|
|
124
|
+
/* Bento child: occupies N grid columns (the wrapper exists only so the child
|
|
125
|
+
keeps its own layout). */
|
|
126
|
+
.gridSpan { display: flex; flex-direction: column; min-width: 0; }
|
|
127
|
+
.gridSpan > * { flex: 1; }
|
|
128
|
+
/* Narrow conversation column (phone / split pane): a fixed 3-4 column grid
|
|
129
|
+
would squeeze every cell, so the grid collapses to one column. The inline
|
|
130
|
+
gridTemplateColumns from the spec needs !important to be overridden. */
|
|
131
|
+
@media (max-width: 560px) {
|
|
132
|
+
.grid { grid-template-columns: 1fr !important; }
|
|
133
|
+
.row { flex-wrap: wrap; }
|
|
134
|
+
}
|
|
81
135
|
.spacer { flex: 1; }
|
|
82
136
|
.divider {
|
|
83
137
|
height: 1px;
|
|
@@ -87,31 +141,66 @@
|
|
|
87
141
|
}
|
|
88
142
|
|
|
89
143
|
.card {
|
|
90
|
-
|
|
91
|
-
|
|
144
|
+
/* Elevated surface: on the dark theme layer-1 (35,35,36) sits only ~14 units
|
|
145
|
+
above the page (21,21,23) and read as "a black box". layer-2 (44,44,46) is
|
|
146
|
+
the host's own elevated surface; light theme maps all layers to one colour,
|
|
147
|
+
so this changes nothing there. */
|
|
148
|
+
background: var(--dsl-g-surface);
|
|
149
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
92
150
|
border-radius: var(--dsl-g-radius-surface);
|
|
93
151
|
padding: var(--dsl-g-gap-lg);
|
|
94
152
|
display: flex;
|
|
95
153
|
flex-direction: column;
|
|
96
154
|
gap: var(--dsl-g-gap-md);
|
|
97
|
-
|
|
155
|
+
min-width: 0;
|
|
156
|
+
box-shadow: var(--dsl-g-shadow-card);
|
|
157
|
+
}
|
|
158
|
+
/* Bento rows size every card to the tallest one. Without this, a short card
|
|
159
|
+
(a single donut next to a tall table) kept its content pinned to the top and
|
|
160
|
+
left a large dead block underneath. The last child absorbs the extra height,
|
|
161
|
+
and the graphic shapes centre themselves inside it. */
|
|
162
|
+
.card > :last-child { flex: 1 1 auto; min-height: 0; }
|
|
163
|
+
.card > .chart,
|
|
164
|
+
.card > .lineChart,
|
|
165
|
+
.card > .donut,
|
|
166
|
+
.card > .hbars { justify-content: center; }
|
|
167
|
+
.card > .col { justify-content: center; }
|
|
98
168
|
|
|
99
169
|
.cardTitle {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
170
|
+
/* Was 12.5px uppercase with tracking while the card BODY is 14.5px: the
|
|
171
|
+
title read as a small grey label, which is why nothing scanned. A card
|
|
172
|
+
title is a section heading, so it sits above body size, sentence case,
|
|
173
|
+
no tracking. The 12.5px uppercase treatment belongs to eyebrows only. */
|
|
174
|
+
font-size: var(--dsl-g-font-h3);
|
|
175
|
+
font-weight: 650;
|
|
176
|
+
letter-spacing: -0.01em;
|
|
177
|
+
text-transform: none;
|
|
103
178
|
color: var(--dsw-alias-label-secondary);
|
|
104
179
|
}
|
|
105
180
|
|
|
106
181
|
/* ---------- text ---------- */
|
|
107
182
|
|
|
108
183
|
.text { color: var(--dsw-alias-label-primary); }
|
|
109
|
-
.text.h1 {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
184
|
+
.text.h1 {
|
|
185
|
+
font-size: var(--dsl-g-font-h1);
|
|
186
|
+
font-weight: 800;
|
|
187
|
+
line-height: 1.25;
|
|
188
|
+
letter-spacing: -0.02em;
|
|
189
|
+
}
|
|
190
|
+
.text.h2 {
|
|
191
|
+
font-size: var(--dsl-g-font-h2);
|
|
192
|
+
font-weight: 700;
|
|
193
|
+
line-height: 1.3;
|
|
194
|
+
letter-spacing: -0.015em;
|
|
195
|
+
}
|
|
196
|
+
.text.h3 { font-size: var(--dsl-g-font-h3); font-weight: 650; line-height: 1.45; }
|
|
197
|
+
/* CJK reads looser than Latin at the same size: 1.7 for body copy, 1.65 for
|
|
198
|
+
secondary lines, and no letter-spacing on Chinese runs (0.02em inserts
|
|
199
|
+
visible gaps between Han characters). */
|
|
200
|
+
/* ~65ch keeps a comfortable reading measure when the block is wide. */
|
|
201
|
+
.text.body { font-size: var(--dsl-g-font-body); line-height: 1.7; color: var(--dsw-alias-label-primary); text-wrap: pretty; max-width: 68ch; }
|
|
202
|
+
.text.muted { font-size: var(--dsl-g-font-title); line-height: 1.65; color: var(--dsw-alias-label-secondary); }
|
|
203
|
+
.text.caption { font-size: var(--dsl-g-font-meta); line-height: 1.6; color: var(--dsw-alias-label-secondary); }
|
|
115
204
|
.text.center { text-align: center; }
|
|
116
205
|
|
|
117
206
|
/* ---------- controls ---------- */
|
|
@@ -129,6 +218,10 @@
|
|
|
129
218
|
cursor: pointer;
|
|
130
219
|
transition: border-color 0.15s, filter 0.15s, background 0.15s, transform 0.1s;
|
|
131
220
|
text-align: center;
|
|
221
|
+
/* A button in a `col` must hug its label; only `full: true` stretches.
|
|
222
|
+
(Default flex `align-items: stretch` used to make every stacked button a
|
|
223
|
+
full-width slab.) */
|
|
224
|
+
align-self: flex-start;
|
|
132
225
|
}
|
|
133
226
|
|
|
134
227
|
.button:hover:not(:disabled) { border-color: var(--dsl-g-accent); filter: brightness(1.06); }
|
|
@@ -168,8 +261,8 @@
|
|
|
168
261
|
.field > span { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-tertiary); }
|
|
169
262
|
|
|
170
263
|
.input, .select {
|
|
171
|
-
background: var(--
|
|
172
|
-
border: 1px solid var(--dsl-g-border);
|
|
264
|
+
background: var(--dsl-g-surface);
|
|
265
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
173
266
|
border-radius: var(--dsl-g-radius-control);
|
|
174
267
|
color: var(--dsw-alias-label-primary);
|
|
175
268
|
padding: 8px 12px;
|
|
@@ -221,15 +314,102 @@
|
|
|
221
314
|
display: flex;
|
|
222
315
|
flex-direction: column;
|
|
223
316
|
gap: var(--dsl-g-gap-sm);
|
|
224
|
-
background: var(--
|
|
225
|
-
border: 1px solid var(--dsl-g-border);
|
|
317
|
+
background: var(--dsl-g-surface);
|
|
318
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
226
319
|
border-radius: var(--dsl-g-radius-surface);
|
|
227
320
|
}
|
|
228
321
|
.mediaLabel { font-size: var(--dsl-g-font-title); font-weight: 600; color: var(--dsw-alias-label-primary); }
|
|
229
|
-
.mediaPlayer { display: block; width: 100%; min-width: 0; }
|
|
322
|
+
.mediaPlayer { display: block; width: 100%; min-width: 0; border-radius: var(--dsl-g-radius-control); }
|
|
323
|
+
/* Reserve the box before the bytes arrive: without an intrinsic ratio an
|
|
324
|
+
unloaded <img> collapses to 0px and the card looks broken. */
|
|
325
|
+
img.mediaPlayer { aspect-ratio: 16 / 9; object-fit: cover; background: var(--dsl-g-surface); }
|
|
230
326
|
.videoPlayer { max-height: min(70vh, 720px); background: #000; object-fit: contain; }
|
|
231
327
|
.mediaError { font-size: var(--dsl-g-font-title); color: var(--dsw-alias-state-error-primary, #f25a5a); }
|
|
232
328
|
|
|
329
|
+
/* ---------- hero (cover band) ----------
|
|
330
|
+
The answer's focal point: an eyebrow, an oversized metric, a title and a
|
|
331
|
+
subtitle on a soft tinted surface. Tone changes the wash, never the layout. */
|
|
332
|
+
|
|
333
|
+
.hero {
|
|
334
|
+
position: relative;
|
|
335
|
+
display: flex;
|
|
336
|
+
flex-direction: column;
|
|
337
|
+
gap: 6px;
|
|
338
|
+
padding: 22px 24px 24px;
|
|
339
|
+
border-radius: 14px;
|
|
340
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
341
|
+
background:
|
|
342
|
+
radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--dsl-g-accent) 22%, transparent) 0%, transparent 58%),
|
|
343
|
+
linear-gradient(180deg, color-mix(in srgb, var(--dsl-g-accent) 7%, transparent), transparent 70%),
|
|
344
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, transparent));
|
|
345
|
+
overflow: hidden;
|
|
346
|
+
box-shadow: var(--dsl-g-shadow-card);
|
|
347
|
+
}
|
|
348
|
+
.heroSuccess {
|
|
349
|
+
background:
|
|
350
|
+
radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) 20%, transparent) 0%, transparent 58%),
|
|
351
|
+
linear-gradient(180deg, color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) 6%, transparent), transparent 70%),
|
|
352
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, transparent));
|
|
353
|
+
}
|
|
354
|
+
.heroWarning {
|
|
355
|
+
background:
|
|
356
|
+
radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f5b83d) 20%, transparent) 0%, transparent 58%),
|
|
357
|
+
linear-gradient(180deg, color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f5b83d) 6%, transparent), transparent 70%),
|
|
358
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, transparent));
|
|
359
|
+
}
|
|
360
|
+
.heroDanger {
|
|
361
|
+
background:
|
|
362
|
+
radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--dsw-alias-state-error-primary, #ff6b6b) 18%, transparent) 0%, transparent 58%),
|
|
363
|
+
linear-gradient(180deg, color-mix(in srgb, var(--dsw-alias-state-error-primary, #ff6b6b) 6%, transparent), transparent 70%),
|
|
364
|
+
var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, transparent));
|
|
365
|
+
}
|
|
366
|
+
.heroLabel {
|
|
367
|
+
font-size: var(--dsl-g-font-meta);
|
|
368
|
+
font-weight: 700;
|
|
369
|
+
letter-spacing: 0.1em;
|
|
370
|
+
text-transform: uppercase;
|
|
371
|
+
color: var(--dsw-alias-label-secondary);
|
|
372
|
+
}
|
|
373
|
+
.heroTop { display: flex; align-items: baseline; gap: var(--dsl-g-gap-md); flex-wrap: wrap; }
|
|
374
|
+
.heroValue {
|
|
375
|
+
display: inline-flex;
|
|
376
|
+
align-items: baseline;
|
|
377
|
+
gap: 4px;
|
|
378
|
+
font-family: var(--dsl-g-font-mono);
|
|
379
|
+
font-size: 52px;
|
|
380
|
+
font-weight: 750;
|
|
381
|
+
letter-spacing: -0.028em;
|
|
382
|
+
line-height: 1;
|
|
383
|
+
color: var(--dsw-alias-label-primary);
|
|
384
|
+
font-variant-numeric: tabular-nums;
|
|
385
|
+
}
|
|
386
|
+
.heroUnit { font-size: 0.44em; font-weight: 650; letter-spacing: 0; color: var(--dsw-alias-label-secondary); }
|
|
387
|
+
.heroSpark { margin-left: auto; width: 168px; align-self: center; }
|
|
388
|
+
.heroTitle { font-size: 20px; font-weight: 700; letter-spacing: -0.01em; color: var(--dsw-alias-label-primary); line-height: 1.3; }
|
|
389
|
+
.heroSubtitle { font-size: var(--dsl-g-font-title); color: var(--dsw-alias-label-secondary); line-height: 1.6; text-wrap: pretty; }
|
|
390
|
+
|
|
391
|
+
/* ---------- inline markup (inline.ts) ----------
|
|
392
|
+
Emphasis that stays INSIDE a sentence: a paragraph should not have to be
|
|
393
|
+
split into several nodes to bold one phrase. */
|
|
394
|
+
.inlineCode {
|
|
395
|
+
font-family: var(--dsl-g-font-mono);
|
|
396
|
+
font-size: 0.92em;
|
|
397
|
+
padding: 1px 5px;
|
|
398
|
+
border-radius: 5px;
|
|
399
|
+
background: var(--dsl-g-surface);
|
|
400
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
401
|
+
white-space: nowrap;
|
|
402
|
+
}
|
|
403
|
+
.inlineStrong { font-weight: 680; color: var(--dsw-alias-label-primary); }
|
|
404
|
+
.inlineMark {
|
|
405
|
+
background: color-mix(in srgb, var(--dsl-g-accent) 20%, transparent);
|
|
406
|
+
color: inherit;
|
|
407
|
+
padding: 0 3px;
|
|
408
|
+
border-radius: 4px;
|
|
409
|
+
}
|
|
410
|
+
.inlineLink { color: var(--dsl-g-accent); text-decoration: underline; text-underline-offset: 2px; }
|
|
411
|
+
.inlineLink:hover { text-decoration-thickness: 2px; }
|
|
412
|
+
|
|
233
413
|
/* ---------- badges / stat / progress ---------- */
|
|
234
414
|
|
|
235
415
|
.badge {
|
|
@@ -271,37 +451,86 @@
|
|
|
271
451
|
.stat {
|
|
272
452
|
display: flex;
|
|
273
453
|
flex-direction: column;
|
|
274
|
-
gap:
|
|
275
|
-
|
|
454
|
+
gap: 4px;
|
|
455
|
+
/* Metric card: the number IS the design. No accent stripe, no bar — the
|
|
456
|
+
40px figure against a 12px uppercase label carries the hierarchy. */
|
|
457
|
+
padding: 14px 16px 15px;
|
|
458
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
459
|
+
border-radius: var(--dsl-g-radius-surface);
|
|
460
|
+
background: var(--dsl-g-surface);
|
|
461
|
+
min-width: 0;
|
|
462
|
+
overflow: hidden;
|
|
463
|
+
box-shadow: var(--dsl-g-shadow-card);
|
|
276
464
|
}
|
|
465
|
+
/* Hero stat: one number is the answer's anchor (use it once per fence). */
|
|
466
|
+
.statHero { padding: 18px 20px 20px; }
|
|
467
|
+
.statHero .statValue { font-size: 44px; line-height: 1.02; letter-spacing: -0.035em; }
|
|
468
|
+
.statHero .statLabel { font-size: 13px; }
|
|
277
469
|
.grid > .stat, .row > .stat { border-left: 1px solid var(--dsl-g-border); }
|
|
278
|
-
.
|
|
279
|
-
|
|
470
|
+
.statLabel {
|
|
471
|
+
font-size: var(--dsl-g-font-meta);
|
|
472
|
+
color: var(--dsw-alias-label-secondary);
|
|
473
|
+
letter-spacing: 0.05em;
|
|
474
|
+
text-transform: uppercase;
|
|
475
|
+
line-height: 1.4;
|
|
476
|
+
}
|
|
280
477
|
.statValue {
|
|
478
|
+
display: flex;
|
|
479
|
+
align-items: baseline;
|
|
480
|
+
gap: 3px;
|
|
281
481
|
font-family: var(--dsl-g-font-mono);
|
|
282
|
-
font-size: var(--dsl-g-font-
|
|
283
|
-
font-weight:
|
|
284
|
-
letter-spacing: -0.
|
|
482
|
+
font-size: var(--dsl-g-font-hero);
|
|
483
|
+
font-weight: 700;
|
|
484
|
+
letter-spacing: -0.03em;
|
|
285
485
|
font-variant-numeric: tabular-nums;
|
|
286
486
|
color: var(--dsw-alias-label-primary);
|
|
287
|
-
line-height: 1.
|
|
487
|
+
line-height: 1.05;
|
|
488
|
+
overflow-wrap: anywhere;
|
|
489
|
+
}
|
|
490
|
+
/* Unit suffix (%, GB, k, ms): same baseline, half the size, muted — the
|
|
491
|
+
number keeps the weight. This is the real typography win in v5. */
|
|
492
|
+
.statUnit {
|
|
493
|
+
font-size: 0.5em;
|
|
494
|
+
font-weight: 600;
|
|
495
|
+
letter-spacing: 0;
|
|
496
|
+
color: var(--dsw-alias-label-secondary);
|
|
497
|
+
}
|
|
498
|
+
.statHero .statUnit { font-size: 0.46em; }
|
|
499
|
+
.statDelta {
|
|
500
|
+
font-size: var(--dsl-g-font-meta);
|
|
501
|
+
font-weight: 600;
|
|
502
|
+
width: fit-content;
|
|
503
|
+
padding: 0 6px;
|
|
504
|
+
border-radius: var(--dsl-g-radius-pill);
|
|
505
|
+
color: var(--dsw-alias-label-secondary);
|
|
506
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 5%, transparent);
|
|
507
|
+
}
|
|
508
|
+
.statDelta.up { color: var(--dsw-alias-state-success-secondary, #1f9d63); background: color-mix(in srgb, var(--dsw-alias-state-success-primary, #22c55e) 12%, transparent); }
|
|
509
|
+
.statSpark {
|
|
510
|
+
display: block;
|
|
511
|
+
width: calc(100% + 32px);
|
|
512
|
+
max-width: none;
|
|
513
|
+
height: 30px;
|
|
514
|
+
margin: 6px -16px -15px;
|
|
515
|
+
overflow: visible;
|
|
288
516
|
}
|
|
289
|
-
.
|
|
290
|
-
|
|
291
|
-
.statDelta.down { color: var(--dsw-alias-state-error-primary, #f25a5a); }
|
|
517
|
+
.statHero .statSpark { width: calc(100% + 40px); margin: 8px -20px -20px; }
|
|
518
|
+
|
|
519
|
+
.statDelta.down { color: var(--dsw-alias-state-error-primary, #d94848); background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #f25a5a) 12%, transparent); }
|
|
292
520
|
|
|
293
521
|
.progress { display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
294
522
|
.progressRow {
|
|
295
523
|
display: flex;
|
|
296
524
|
justify-content: space-between;
|
|
525
|
+
gap: var(--dsl-g-gap-md);
|
|
297
526
|
font-size: var(--dsl-g-font-meta);
|
|
298
|
-
color: var(--dsw-alias-label-
|
|
527
|
+
color: var(--dsw-alias-label-secondary);
|
|
299
528
|
}
|
|
300
|
-
.progressRow span:last-child { font-family: var(--dsl-g-font-mono); }
|
|
529
|
+
.progressRow span:last-child { font-family: var(--dsl-g-font-mono); color: var(--dsw-alias-label-primary); font-weight: 600; }
|
|
301
530
|
.track {
|
|
302
|
-
height:
|
|
531
|
+
height: 8px;
|
|
303
532
|
border-radius: var(--dsl-g-radius-pill);
|
|
304
|
-
background: var(--dsw-alias-
|
|
533
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent);
|
|
305
534
|
overflow: hidden;
|
|
306
535
|
box-shadow: inset 0 0 0 1px var(--dsl-g-border);
|
|
307
536
|
}
|
|
@@ -316,14 +545,34 @@
|
|
|
316
545
|
/* ---------- list / table / chart / tabs / avatar ---------- */
|
|
317
546
|
|
|
318
547
|
.list { display: flex; flex-direction: column; }
|
|
319
|
-
.li {
|
|
548
|
+
.li {
|
|
549
|
+
position: relative;
|
|
550
|
+
padding: 9px var(--dsl-g-gap-xs) 9px 16px;
|
|
551
|
+
display: flex;
|
|
552
|
+
flex-direction: column;
|
|
553
|
+
gap: 3px;
|
|
554
|
+
}
|
|
555
|
+
/* Accent dot instead of a bare indented line: 202 of ~3.7k real nodes are
|
|
556
|
+
list items, and a marker makes a multi-line list scannable at a glance. */
|
|
557
|
+
.li::before {
|
|
558
|
+
content: "";
|
|
559
|
+
position: absolute;
|
|
560
|
+
left: 2px;
|
|
561
|
+
top: 15px;
|
|
562
|
+
width: 5px;
|
|
563
|
+
height: 5px;
|
|
564
|
+
border-radius: 50%;
|
|
565
|
+
background: var(--dsl-g-accent);
|
|
566
|
+
opacity: 0.6;
|
|
567
|
+
}
|
|
320
568
|
.li + .li { border-top: 1px solid var(--dsl-g-border); }
|
|
321
569
|
.li:last-child { border-bottom: none; }
|
|
322
|
-
.liTitle { font-size: var(--dsl-g-font-
|
|
323
|
-
.liDesc { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-
|
|
570
|
+
.liTitle { font-size: var(--dsl-g-font-body); color: var(--dsw-alias-label-primary); font-weight: 650; line-height: 1.5; }
|
|
571
|
+
.liDesc { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-secondary); line-height: 1.55; }
|
|
324
572
|
|
|
325
573
|
.tableWrap {
|
|
326
574
|
border-radius: var(--dsl-g-radius-control);
|
|
575
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
327
576
|
/* A table whose nowrap cells exceed the column width must scroll, not clip
|
|
328
577
|
(mirrors the shell markdown table's .tableScroll pattern). */
|
|
329
578
|
overflow-x: auto;
|
|
@@ -334,26 +583,40 @@
|
|
|
334
583
|
.table { width: 100%; border-collapse: collapse; font-size: var(--dsl-g-font-title); }
|
|
335
584
|
.table th {
|
|
336
585
|
text-align: left;
|
|
337
|
-
padding:
|
|
338
|
-
color: var(--dsw-alias-label-
|
|
339
|
-
font-weight:
|
|
586
|
+
padding: 9px var(--dsl-g-gap-md);
|
|
587
|
+
color: var(--dsw-alias-label-secondary);
|
|
588
|
+
font-weight: 700;
|
|
340
589
|
font-size: var(--dsl-g-font-meta);
|
|
341
|
-
|
|
590
|
+
letter-spacing: 0.06em;
|
|
591
|
+
text-transform: uppercase;
|
|
592
|
+
border-bottom: 1px solid var(--dsl-g-border-strong);
|
|
593
|
+
background: var(--dsl-g-zebra);
|
|
342
594
|
white-space: nowrap;
|
|
343
595
|
}
|
|
344
596
|
.table td {
|
|
345
|
-
padding:
|
|
597
|
+
padding: 10px var(--dsl-g-gap-md);
|
|
346
598
|
border-bottom: 1px solid var(--dsl-g-border);
|
|
347
|
-
color: var(--dsw-alias-label-
|
|
599
|
+
color: var(--dsw-alias-label-primary);
|
|
348
600
|
white-space: nowrap;
|
|
349
601
|
font-variant-numeric: tabular-nums;
|
|
350
602
|
line-height: 1.5;
|
|
603
|
+
vertical-align: middle;
|
|
351
604
|
}
|
|
352
|
-
|
|
605
|
+
/* The first column is the row's name: give it the weight of a label so a
|
|
606
|
+
table reads as "these rows, these values" instead of a uniform grid. */
|
|
607
|
+
.table td:first-child { font-weight: 600; }
|
|
608
|
+
.table th:first-child { color: var(--dsw-alias-label-primary); }
|
|
609
|
+
.table tbody tr:nth-child(even) { background: var(--dsl-g-zebra); }
|
|
353
610
|
.table tbody tr:hover { background: var(--dsl-g-hover); }
|
|
611
|
+
.table tr:last-child td { border-bottom: none; }
|
|
354
612
|
/* Numeric columns (auto-detected) right-align with tabular numerals — the
|
|
355
613
|
table's data voice. */
|
|
356
614
|
.table th.thNum, .table td.tdNum { text-align: right; }
|
|
615
|
+
/* Signed values read as a delta chip (+12.4% / -3%) without any new spec
|
|
616
|
+
field: the renderer classifies the cell text. */
|
|
617
|
+
.tdDelta { font-weight: 600; }
|
|
618
|
+
.tdDeltaUp { color: var(--dsw-alias-state-success-secondary, #1f9d63); }
|
|
619
|
+
.tdDeltaDown { color: var(--dsw-alias-state-error-primary, #d94848); }
|
|
357
620
|
|
|
358
621
|
/* sortable header button (v2.9) */
|
|
359
622
|
.thSort {
|
|
@@ -378,13 +641,28 @@
|
|
|
378
641
|
|
|
379
642
|
/* Chart skeleton: plot area with baseline + 25/50/75% gridlines, category
|
|
380
643
|
labels in their own row below the axis (they must never cross the lines). */
|
|
381
|
-
.chart { display: flex; flex-direction: column; gap: var(--dsl-g-gap-
|
|
644
|
+
.chart { position: relative; display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
645
|
+
/* Y-axis gutter + plot share one measured box so tick labels line up with the
|
|
646
|
+
gridlines instead of being guessed from the container height. */
|
|
647
|
+
.chartBody { display: flex; gap: 6px; align-items: stretch; }
|
|
648
|
+
.chartYAxis { position: relative; width: 42px; flex-shrink: 0; }
|
|
649
|
+
.chartYTick {
|
|
650
|
+
position: absolute;
|
|
651
|
+
right: 0;
|
|
652
|
+
transform: translateY(50%);
|
|
653
|
+
font-family: var(--dsl-g-font-mono);
|
|
654
|
+
font-size: var(--dsl-g-font-data);
|
|
655
|
+
color: var(--dsw-alias-label-tertiary);
|
|
656
|
+
white-space: nowrap;
|
|
657
|
+
}
|
|
382
658
|
.chartPlot {
|
|
383
659
|
position: relative;
|
|
384
660
|
display: flex;
|
|
385
661
|
align-items: flex-end;
|
|
386
662
|
gap: var(--dsl-g-gap-sm);
|
|
387
|
-
height:
|
|
663
|
+
height: 160px;
|
|
664
|
+
flex: 1;
|
|
665
|
+
min-width: 0;
|
|
388
666
|
}
|
|
389
667
|
.baseline {
|
|
390
668
|
position: absolute;
|
|
@@ -402,33 +680,99 @@
|
|
|
402
680
|
}
|
|
403
681
|
.chartLabels { display: flex; gap: var(--dsl-g-gap-sm); }
|
|
404
682
|
.chartLabels > span { flex: 1; min-width: 0; }
|
|
405
|
-
.
|
|
406
|
-
|
|
683
|
+
.chartLegend {
|
|
684
|
+
display: flex;
|
|
685
|
+
flex-wrap: wrap;
|
|
686
|
+
gap: var(--dsl-g-gap-md);
|
|
687
|
+
font-size: var(--dsl-g-font-meta);
|
|
688
|
+
color: var(--dsw-alias-label-secondary);
|
|
689
|
+
line-height: 1.5;
|
|
690
|
+
}
|
|
691
|
+
.legendItem { display: inline-flex; align-items: center; gap: 6px; }
|
|
692
|
+
.legendSwatch { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
|
|
693
|
+
.lineArea { fill: var(--dsl-g-accent); opacity: 0.1; }
|
|
694
|
+
|
|
695
|
+
/* Instant hover readout (charts). Native `title` is slow and cannot show a
|
|
696
|
+
stacked breakdown; this is drawn by the chart itself. */
|
|
697
|
+
.chartTip {
|
|
698
|
+
position: absolute;
|
|
699
|
+
transform: translate(-50%, calc(-100% - 10px));
|
|
407
700
|
display: flex;
|
|
408
701
|
flex-direction: column;
|
|
409
|
-
|
|
410
|
-
|
|
702
|
+
gap: 2px;
|
|
703
|
+
padding: 6px 10px;
|
|
704
|
+
border-radius: var(--dsl-g-radius-control);
|
|
705
|
+
border: 1px solid var(--dsl-g-border-strong);
|
|
706
|
+
background: var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1, #1c1c1e)));
|
|
707
|
+
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.3);
|
|
708
|
+
color: var(--dsw-alias-label-primary);
|
|
709
|
+
font-size: var(--dsl-g-font-meta);
|
|
710
|
+
line-height: 1.4;
|
|
711
|
+
white-space: nowrap;
|
|
712
|
+
pointer-events: none;
|
|
713
|
+
z-index: 6;
|
|
714
|
+
}
|
|
715
|
+
.chartTipRow { display: flex; justify-content: space-between; gap: 14px; }
|
|
716
|
+
.chartTipValue { font-family: var(--dsl-g-font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
717
|
+
/* Value printed inside a stacked segment when the segment is tall enough. */
|
|
718
|
+
.stackValue {
|
|
719
|
+
display: block;
|
|
720
|
+
text-align: center;
|
|
721
|
+
font-family: var(--dsl-g-font-mono);
|
|
722
|
+
font-size: var(--dsl-g-font-data);
|
|
723
|
+
font-weight: 700;
|
|
724
|
+
line-height: 1.5;
|
|
725
|
+
color: #fff;
|
|
726
|
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
|
|
727
|
+
font-variant-numeric: tabular-nums;
|
|
728
|
+
}
|
|
729
|
+
.barCol {
|
|
730
|
+
position: relative;
|
|
731
|
+
flex: 1;
|
|
411
732
|
min-width: 0;
|
|
412
733
|
height: 100%;
|
|
413
734
|
}
|
|
414
735
|
.barValue {
|
|
736
|
+
position: absolute;
|
|
737
|
+
left: 0;
|
|
738
|
+
right: 0;
|
|
415
739
|
font-family: var(--dsl-g-font-mono);
|
|
416
740
|
font-size: var(--dsl-g-font-data);
|
|
417
741
|
font-variant-numeric: tabular-nums;
|
|
418
|
-
color: var(--dsw-alias-label-
|
|
742
|
+
color: var(--dsw-alias-label-primary);
|
|
743
|
+
font-weight: 600;
|
|
419
744
|
text-align: center;
|
|
420
745
|
line-height: 1.2;
|
|
421
746
|
}
|
|
747
|
+
.stack {
|
|
748
|
+
position: absolute;
|
|
749
|
+
left: 0;
|
|
750
|
+
right: 0;
|
|
751
|
+
bottom: 0;
|
|
752
|
+
display: flex;
|
|
753
|
+
flex-direction: column-reverse;
|
|
754
|
+
/* A hairline gap between segments: without it a two-colour stack reads as
|
|
755
|
+
one block and the boundary is impossible to find. */
|
|
756
|
+
gap: 2px;
|
|
757
|
+
border-radius: 5px 5px 0 0;
|
|
758
|
+
overflow: hidden;
|
|
759
|
+
transition: height 0.6s ease;
|
|
760
|
+
}
|
|
761
|
+
.stackSeg { width: 100%; transition: height 0.6s ease, filter 0.15s; }
|
|
762
|
+
.stackSeg:hover { filter: brightness(1.15); }
|
|
422
763
|
.barFill {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
764
|
+
position: absolute;
|
|
765
|
+
left: 0;
|
|
766
|
+
right: 0;
|
|
767
|
+
border-radius: 5px 5px 0 0;
|
|
768
|
+
min-height: 2px;
|
|
769
|
+
background: linear-gradient(180deg, color-mix(in srgb, var(--dsl-g-accent) 78%, white), var(--dsl-g-accent));
|
|
426
770
|
transition: height 0.6s ease, filter 0.15s;
|
|
427
771
|
}
|
|
428
772
|
.barFill:hover { filter: brightness(1.18); }
|
|
429
773
|
.barLabel {
|
|
430
774
|
font-size: var(--dsl-g-font-meta);
|
|
431
|
-
color: var(--dsw-alias-label-
|
|
775
|
+
color: var(--dsw-alias-label-secondary);
|
|
432
776
|
text-align: center;
|
|
433
777
|
white-space: nowrap;
|
|
434
778
|
overflow: hidden;
|
|
@@ -437,23 +781,27 @@
|
|
|
437
781
|
}
|
|
438
782
|
|
|
439
783
|
.tabs { display: flex; flex-direction: column; gap: var(--dsl-g-gap-md); }
|
|
440
|
-
.tabBar { display: flex; gap:
|
|
784
|
+
.tabBar { display: flex; gap: 2px; border-bottom: 1px solid var(--dsl-g-border); }
|
|
441
785
|
.tab {
|
|
442
786
|
background: transparent;
|
|
443
787
|
border: none;
|
|
444
|
-
|
|
788
|
+
/* Inactive tabs were tertiary (barely readable); secondary + a hover wash
|
|
789
|
+
keeps the hierarchy while staying legible. */
|
|
790
|
+
color: var(--dsw-alias-label-secondary);
|
|
445
791
|
font-size: var(--dsl-g-font-title);
|
|
446
792
|
font-weight: 600;
|
|
447
793
|
font-family: inherit;
|
|
448
|
-
padding:
|
|
794
|
+
padding: 8px 14px;
|
|
449
795
|
border-bottom: 2px solid transparent;
|
|
796
|
+
border-radius: var(--dsl-g-radius-sm) var(--dsl-g-radius-sm) 0 0;
|
|
450
797
|
margin-bottom: -1px;
|
|
451
798
|
cursor: pointer;
|
|
452
799
|
line-height: 1.5;
|
|
453
|
-
transition: color 0.15s, border-bottom-color 0.15s;
|
|
800
|
+
transition: color 0.15s, background 0.15s, border-bottom-color 0.15s;
|
|
454
801
|
}
|
|
455
|
-
.tab:hover { color: var(--dsw-alias-label-
|
|
456
|
-
.tabActive { color: var(--dsw-alias-label-primary); border-bottom-color: var(--dsl-g-accent); }
|
|
802
|
+
.tab:hover { color: var(--dsw-alias-label-primary); background: var(--dsl-g-hover); }
|
|
803
|
+
.tabActive { color: var(--dsw-alias-label-primary); font-weight: 650; border-bottom-color: var(--dsl-g-accent); }
|
|
804
|
+
.tab:focus-visible { outline: 2px solid var(--dsl-g-accent); outline-offset: -2px; }
|
|
457
805
|
|
|
458
806
|
.avatar {
|
|
459
807
|
width: 32px;
|
|
@@ -470,45 +818,38 @@
|
|
|
470
818
|
}
|
|
471
819
|
|
|
472
820
|
/* ---------- callout ----------
|
|
473
|
-
|
|
474
|
-
|
|
821
|
+
语义由「底色 + 标题色」表达,不用左侧竖条:竖条是 PPT 式装饰,底色与
|
|
822
|
+
文字色才是信息层级。 */
|
|
475
823
|
|
|
476
824
|
.callout {
|
|
477
825
|
display: flex;
|
|
478
826
|
flex-direction: column;
|
|
479
|
-
gap:
|
|
480
|
-
padding:
|
|
481
|
-
border-radius: var(--dsl-g-radius-
|
|
482
|
-
border: 1px solid var(--dsl-g-border);
|
|
827
|
+
gap: 3px;
|
|
828
|
+
padding: 12px 15px;
|
|
829
|
+
border-radius: var(--dsl-g-radius-surface);
|
|
830
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
483
831
|
font-size: var(--dsl-g-font-title);
|
|
484
|
-
line-height: 1.
|
|
485
|
-
background: var(--
|
|
832
|
+
line-height: 1.65;
|
|
833
|
+
background: var(--dsl-g-surface);
|
|
834
|
+
box-shadow: var(--dsl-g-shadow-card);
|
|
486
835
|
}
|
|
487
836
|
.calloutInfo { background: color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent); }
|
|
488
837
|
.calloutSuccess { background: color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) var(--dsl-g-tint), transparent); }
|
|
489
838
|
.calloutWarning { background: color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f5b83d) var(--dsl-g-tint), transparent); }
|
|
490
839
|
.calloutError { background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #ff6b6b) var(--dsl-g-tint), transparent); }
|
|
840
|
+
.calloutInfo .calloutTitle { color: var(--dsw-alias-state-business-primary, #4f8ef7); }
|
|
841
|
+
.calloutSuccess .calloutTitle { color: var(--dsw-alias-state-success-primary, #2f9e6b); }
|
|
842
|
+
.calloutWarning .calloutTitle { color: var(--dsw-alias-state-warn-primary, #b8860b); }
|
|
843
|
+
.calloutError .calloutTitle { color: var(--dsw-alias-state-error-primary, #d94848); }
|
|
491
844
|
.calloutTitle {
|
|
492
845
|
display: flex;
|
|
493
846
|
align-items: center;
|
|
494
847
|
gap: 6px;
|
|
495
|
-
font-weight:
|
|
496
|
-
font-size: var(--dsl-g-font-
|
|
497
|
-
letter-spacing: 0.
|
|
498
|
-
color: var(--dsw-alias-label-
|
|
499
|
-
}
|
|
500
|
-
/* 小圆点:用色点替代左侧竖条表达语义,克制且可读 */
|
|
501
|
-
.calloutTitle::before {
|
|
502
|
-
content: "";
|
|
503
|
-
width: 6px;
|
|
504
|
-
height: 6px;
|
|
505
|
-
border-radius: 50%;
|
|
506
|
-
background: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary));
|
|
848
|
+
font-weight: 700;
|
|
849
|
+
font-size: var(--dsl-g-font-h3);
|
|
850
|
+
letter-spacing: -0.005em;
|
|
851
|
+
color: var(--dsw-alias-label-primary);
|
|
507
852
|
}
|
|
508
|
-
.calloutInfo .calloutTitle::before { background: var(--dsl-g-accent); }
|
|
509
|
-
.calloutSuccess .calloutTitle::before { background: var(--dsw-alias-state-success-primary, #3ecf8e); }
|
|
510
|
-
.calloutWarning .calloutTitle::before { background: var(--dsw-alias-state-warn-primary, #f5b83d); }
|
|
511
|
-
.calloutError .calloutTitle::before { background: var(--dsw-alias-state-error-primary, #ff6b6b); }
|
|
512
853
|
.calloutBody { color: var(--dsw-alias-label-secondary); }
|
|
513
854
|
|
|
514
855
|
/* ---------- steps ---------- */
|
|
@@ -519,9 +860,24 @@
|
|
|
519
860
|
padding: 0;
|
|
520
861
|
display: flex;
|
|
521
862
|
flex-direction: column;
|
|
522
|
-
gap: var(--dsl-g-gap-
|
|
863
|
+
gap: var(--dsl-g-gap-md);
|
|
864
|
+
}
|
|
865
|
+
.step { position: relative; display: flex; gap: var(--dsl-g-gap-md); align-items: flex-start; }
|
|
866
|
+
/* Connector between markers: turns a stack of badges into a visible sequence. */
|
|
867
|
+
.step:not(:last-child)::before {
|
|
868
|
+
content: "";
|
|
869
|
+
position: absolute;
|
|
870
|
+
left: 11px;
|
|
871
|
+
top: 27px;
|
|
872
|
+
bottom: calc(-1 * var(--dsl-g-gap-md));
|
|
873
|
+
width: 1px;
|
|
874
|
+
background: var(--dsl-g-border);
|
|
523
875
|
}
|
|
524
|
-
|
|
876
|
+
/* The rail behind a finished step picks up the success tint, so the sequence
|
|
877
|
+
reads as progress instead of a row of badges. */
|
|
878
|
+
.stepDone:not(:last-child)::before { background: color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) 45%, transparent); }
|
|
879
|
+
.stepTitle { transition: color 0.15s; }
|
|
880
|
+
.stepActive .stepTitle { color: var(--dsl-g-accent); }
|
|
525
881
|
.stepMarker {
|
|
526
882
|
width: 24px;
|
|
527
883
|
height: 24px;
|
|
@@ -531,19 +887,25 @@
|
|
|
531
887
|
font-size: var(--dsl-g-font-meta);
|
|
532
888
|
font-weight: 700;
|
|
533
889
|
flex-shrink: 0;
|
|
534
|
-
background: var(--
|
|
535
|
-
border: 1px solid var(--dsl-g-border);
|
|
536
|
-
color: var(--dsw-alias-label-
|
|
890
|
+
background: var(--dsl-g-surface);
|
|
891
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
892
|
+
color: var(--dsw-alias-label-secondary);
|
|
893
|
+
z-index: 1;
|
|
894
|
+
}
|
|
895
|
+
.stepDone .stepMarker {
|
|
896
|
+
background: color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) 18%, transparent);
|
|
897
|
+
border-color: color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) 55%, transparent);
|
|
898
|
+
color: var(--dsw-alias-state-success-primary, #2f9e6b);
|
|
899
|
+
font-size: 13px;
|
|
537
900
|
}
|
|
538
|
-
.stepDone .stepMarker { background: var(--dsw-alias-state-success-primary, #3ecf8e); border-color: transparent; color: #fff; font-size: 13px; }
|
|
539
901
|
.stepActive .stepMarker {
|
|
540
902
|
background: color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent);
|
|
541
903
|
border-color: var(--dsl-g-accent);
|
|
542
904
|
color: var(--dsl-g-accent);
|
|
543
905
|
}
|
|
544
|
-
.stepContent { display: flex; flex-direction: column; gap: 2px; padding-top:
|
|
545
|
-
.stepTitle { font-size: var(--dsl-g-font-
|
|
546
|
-
.stepDesc { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-
|
|
906
|
+
.stepContent { display: flex; flex-direction: column; gap: 2px; padding-top: 2px; }
|
|
907
|
+
.stepTitle { font-size: var(--dsl-g-font-body); font-weight: 650; color: var(--dsw-alias-label-primary); line-height: 1.45; }
|
|
908
|
+
.stepDesc { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-secondary); line-height: 1.55; }
|
|
547
909
|
|
|
548
910
|
/* ---------- keyvalue ---------- */
|
|
549
911
|
|
|
@@ -551,13 +913,14 @@
|
|
|
551
913
|
.kvRow {
|
|
552
914
|
display: flex;
|
|
553
915
|
gap: var(--dsl-g-gap-md);
|
|
554
|
-
padding:
|
|
916
|
+
padding: 7px 0;
|
|
555
917
|
font-size: var(--dsl-g-font-title);
|
|
918
|
+
align-items: baseline;
|
|
556
919
|
}
|
|
557
920
|
.kvRow + .kvRow { border-top: 1px solid var(--dsl-g-border); }
|
|
558
921
|
.kvRow:last-child { border-bottom: none; }
|
|
559
|
-
.kvKey { width:
|
|
560
|
-
.kvValue { margin: 0; color: var(--dsw-alias-label-primary); word-break: break-word; line-height: 1.5; }
|
|
922
|
+
.kvKey { width: 120px; flex-shrink: 0; color: var(--dsw-alias-label-secondary); font-weight: 600; }
|
|
923
|
+
.kvValue { margin: 0; color: var(--dsw-alias-label-primary); font-weight: 600; word-break: break-word; line-height: 1.5; font-variant-numeric: tabular-nums; }
|
|
561
924
|
|
|
562
925
|
/* ---------- json scalar ---------- */
|
|
563
926
|
|
|
@@ -565,7 +928,7 @@
|
|
|
565
928
|
|
|
566
929
|
/* ---------- chart variants ---------- */
|
|
567
930
|
|
|
568
|
-
.lineChart { display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
931
|
+
.lineChart { position: relative; display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
569
932
|
.linePath { fill: none; stroke: var(--dsl-g-accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
|
|
570
933
|
.lineDot { fill: var(--dsl-g-accent); transition: filter 0.15s; }
|
|
571
934
|
.lineDot:hover { filter: brightness(1.3); }
|
|
@@ -576,6 +939,10 @@
|
|
|
576
939
|
font-family: var(--dsl-g-font-mono);
|
|
577
940
|
font-size: var(--dsl-g-font-data);
|
|
578
941
|
}
|
|
942
|
+
.lineLabel {
|
|
943
|
+
fill: var(--dsw-alias-label-secondary);
|
|
944
|
+
font-size: var(--dsl-g-font-meta);
|
|
945
|
+
}
|
|
579
946
|
.lineLabels { display: flex; justify-content: space-between; }
|
|
580
947
|
|
|
581
948
|
.groupedBars { display: flex; gap: var(--dsl-g-gap-xs); align-items: flex-end; height: 100%; width: 100%; }
|
|
@@ -602,13 +969,295 @@
|
|
|
602
969
|
.groupedFill { flex: 0 0 auto; width: 100%; border-radius: 4px 4px 2px 2px; min-height: 3px; background: var(--dsl-g-accent); transition: filter 0.15s; }
|
|
603
970
|
.groupedFill:hover { filter: brightness(1.18); }
|
|
604
971
|
|
|
605
|
-
.donut { display: flex; align-items: center; gap: var(--dsl-g-gap-lg); }
|
|
972
|
+
.donut { position: relative; display: flex; align-items: center; gap: var(--dsl-g-gap-lg); }
|
|
606
973
|
.donutTrack { stroke: var(--dsw-alias-border-l1, rgba(255, 255, 255, 0.08)); }
|
|
607
974
|
.donutSeg { transition: filter 0.15s; }
|
|
608
975
|
.donutSeg:hover { filter: brightness(1.18); }
|
|
609
976
|
.donutTotal { fill: var(--dsw-alias-label-primary); font-size: var(--dsl-g-font-h2); font-weight: 700; }
|
|
610
977
|
.donutTotalLabel { fill: var(--dsw-alias-label-tertiary); font-size: 10px; }
|
|
611
|
-
.donutLegend { display: flex; flex-direction: column; gap: var(--dsl-g-gap-
|
|
978
|
+
.donutLegend { display: flex; flex-direction: column; justify-content: center; gap: var(--dsl-g-gap-sm); font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-secondary); line-height: 1.5; }
|
|
979
|
+
.donutPct { color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; }
|
|
980
|
+
|
|
981
|
+
/* ---------- progress ring + target marker ---------- */
|
|
982
|
+
|
|
983
|
+
.ring { display: flex; align-items: center; gap: var(--dsl-g-gap-md); }
|
|
984
|
+
.ringTrack { stroke: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent); }
|
|
985
|
+
.ringFill { stroke: var(--dsl-g-accent); transition: stroke-dasharray 0.6s ease; }
|
|
986
|
+
.ringValue {
|
|
987
|
+
fill: var(--dsw-alias-label-primary);
|
|
988
|
+
font-family: var(--dsl-g-font-mono);
|
|
989
|
+
font-size: 17px;
|
|
990
|
+
font-weight: 700;
|
|
991
|
+
font-variant-numeric: tabular-nums;
|
|
992
|
+
}
|
|
993
|
+
.ringMeta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
994
|
+
.ringLabel { font-size: var(--dsl-g-font-body); font-weight: 650; color: var(--dsw-alias-label-primary); }
|
|
995
|
+
.ringSub { font-size: var(--dsl-g-font-meta); color: var(--dsw-alias-label-secondary); }
|
|
996
|
+
|
|
997
|
+
.track { position: relative; overflow: visible; }
|
|
998
|
+
.targetMark {
|
|
999
|
+
position: absolute;
|
|
1000
|
+
top: -3px;
|
|
1001
|
+
bottom: -3px;
|
|
1002
|
+
width: 2px;
|
|
1003
|
+
margin-left: -1px;
|
|
1004
|
+
border-radius: 1px;
|
|
1005
|
+
background: var(--dsw-alias-label-primary);
|
|
1006
|
+
opacity: 0.6;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/* Live-filter feedback: how many rows survived the bound control. */
|
|
1010
|
+
.filterRow td {
|
|
1011
|
+
padding: 7px var(--dsl-g-gap-md);
|
|
1012
|
+
border-top: 1px solid var(--dsl-g-border);
|
|
1013
|
+
color: var(--dsw-alias-label-secondary);
|
|
1014
|
+
font-size: var(--dsl-g-font-meta);
|
|
1015
|
+
font-variant-numeric: tabular-nums;
|
|
1016
|
+
background: transparent;
|
|
1017
|
+
}
|
|
1018
|
+
.filterHint {
|
|
1019
|
+
display: block;
|
|
1020
|
+
padding-top: 6px;
|
|
1021
|
+
color: var(--dsw-alias-label-secondary);
|
|
1022
|
+
font-size: var(--dsl-g-font-meta);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/* Export chips (`table.export`): a quiet toolbar above the table. */
|
|
1026
|
+
.tableTools {
|
|
1027
|
+
display: flex;
|
|
1028
|
+
justify-content: flex-end;
|
|
1029
|
+
gap: 6px;
|
|
1030
|
+
padding: 6px 8px 4px;
|
|
1031
|
+
}
|
|
1032
|
+
.tableTool {
|
|
1033
|
+
padding: 2px 9px;
|
|
1034
|
+
border: 1px solid var(--dsl-g-border);
|
|
1035
|
+
border-radius: var(--dsl-g-radius-pill);
|
|
1036
|
+
background: transparent;
|
|
1037
|
+
color: var(--dsw-alias-label-secondary);
|
|
1038
|
+
font-family: inherit;
|
|
1039
|
+
font-size: var(--dsl-g-font-meta);
|
|
1040
|
+
cursor: pointer;
|
|
1041
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
1042
|
+
}
|
|
1043
|
+
.tableTool:hover { color: var(--dsw-alias-label-primary); border-color: var(--dsl-g-border-strong); background: var(--dsl-g-hover); }
|
|
1044
|
+
.tableTool:focus-visible { outline: 2px solid var(--dsl-g-accent); outline-offset: 1px; }
|
|
1045
|
+
/* Card accent (`card.accent`): the border comes in inline; the title lifts the
|
|
1046
|
+
hue toward the theme's own text colour so it stays legible on dark AND light
|
|
1047
|
+
surfaces (a raw accent colour on a dark card reads muddy). */
|
|
1048
|
+
.card[style*="--dsl-card-accent"] > .cardTitle {
|
|
1049
|
+
color: color-mix(in srgb, var(--dsl-card-accent) 38%, var(--dsw-alias-label-primary));
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/* Master-detail rows (table.details): a chevron in the first cell opens a
|
|
1053
|
+
full-width panel underneath, so a table can drill down without leaving the
|
|
1054
|
+
page or opening a modal. */
|
|
1055
|
+
.detailCell { padding-left: var(--dsl-g-gap-sm); }
|
|
1056
|
+
.detailToggle {
|
|
1057
|
+
display: inline-flex;
|
|
1058
|
+
align-items: center;
|
|
1059
|
+
gap: 6px;
|
|
1060
|
+
padding: 0;
|
|
1061
|
+
border: none;
|
|
1062
|
+
background: none;
|
|
1063
|
+
font: inherit;
|
|
1064
|
+
font-weight: 600;
|
|
1065
|
+
color: inherit;
|
|
1066
|
+
cursor: pointer;
|
|
1067
|
+
text-align: left;
|
|
1068
|
+
}
|
|
1069
|
+
.detailToggle:hover { color: var(--dsl-g-accent); }
|
|
1070
|
+
.detailToggle:focus-visible { outline: 2px solid var(--dsl-g-accent); outline-offset: 2px; border-radius: 4px; }
|
|
1071
|
+
.detailChevron {
|
|
1072
|
+
flex-shrink: 0;
|
|
1073
|
+
font-size: 10px;
|
|
1074
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1075
|
+
transition: transform 0.18s ease;
|
|
1076
|
+
}
|
|
1077
|
+
.detailChevron[data-open="true"] { transform: rotate(90deg); }
|
|
1078
|
+
.table tbody tr.detailRow > td {
|
|
1079
|
+
padding: 0 var(--dsl-g-gap-md) 12px;
|
|
1080
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent);
|
|
1081
|
+
border-bottom: 1px solid var(--dsl-g-border);
|
|
1082
|
+
}
|
|
1083
|
+
.table tbody tr.detailRow:hover > td { background: color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent); }
|
|
1084
|
+
.detailBody {
|
|
1085
|
+
display: flex;
|
|
1086
|
+
flex-direction: column;
|
|
1087
|
+
gap: var(--dsl-g-gap-sm);
|
|
1088
|
+
padding: 12px 14px;
|
|
1089
|
+
border-radius: var(--dsl-g-radius-control);
|
|
1090
|
+
background: var(--dsw-alias-bg-layer-1, transparent);
|
|
1091
|
+
box-shadow: inset 2px 0 0 color-mix(in srgb, var(--dsl-g-accent) 45%, transparent);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/* Section header rows (types[0] === 'group').
|
|
1095
|
+
v7 looked like a data row; v8 was a heavy band; v9 was quiet but still read
|
|
1096
|
+
as "same level" — a hairline and air do not say "these rows belong to me".
|
|
1097
|
+
v10 makes the relationship structural: the header is a TOGGLE (chevron +
|
|
1098
|
+
label + child count) and its rows are indented children under a guide rail,
|
|
1099
|
+
so the tree is unmistakable and each section can be folded away. */
|
|
1100
|
+
.groupRow td {
|
|
1101
|
+
background: none;
|
|
1102
|
+
padding: 22px var(--dsl-g-gap-md) 6px;
|
|
1103
|
+
border-top: none;
|
|
1104
|
+
border-bottom: none;
|
|
1105
|
+
box-shadow: inset 0 1px 0 var(--dsl-g-border);
|
|
1106
|
+
}
|
|
1107
|
+
.table tbody tr.groupRow:first-child td { box-shadow: none; padding-top: 10px; }
|
|
1108
|
+
.table tbody tr.groupRow:hover { background: none; }
|
|
1109
|
+
.table tbody tr.groupRow:nth-child(even) { background: none; }
|
|
1110
|
+
.groupToggle {
|
|
1111
|
+
display: inline-flex;
|
|
1112
|
+
align-items: center;
|
|
1113
|
+
gap: 7px;
|
|
1114
|
+
padding: 0;
|
|
1115
|
+
border: none;
|
|
1116
|
+
background: none;
|
|
1117
|
+
font: inherit;
|
|
1118
|
+
font-size: var(--dsl-g-font-title);
|
|
1119
|
+
font-weight: 650;
|
|
1120
|
+
letter-spacing: 0.02em;
|
|
1121
|
+
color: var(--dsw-alias-label-primary);
|
|
1122
|
+
cursor: pointer;
|
|
1123
|
+
}
|
|
1124
|
+
.groupToggle:hover { color: var(--dsl-g-accent); }
|
|
1125
|
+
.groupToggle:focus-visible { outline: 2px solid var(--dsl-g-accent); outline-offset: 2px; border-radius: 4px; }
|
|
1126
|
+
.groupChevron { color: var(--dsw-alias-label-tertiary); font-size: 11px; width: 10px; }
|
|
1127
|
+
.groupCount {
|
|
1128
|
+
padding: 0 7px;
|
|
1129
|
+
border-radius: var(--dsl-g-radius-pill);
|
|
1130
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent);
|
|
1131
|
+
color: var(--dsw-alias-label-secondary);
|
|
1132
|
+
font-size: var(--dsl-g-font-meta);
|
|
1133
|
+
font-weight: 600;
|
|
1134
|
+
font-variant-numeric: tabular-nums;
|
|
1135
|
+
}
|
|
1136
|
+
/* Children: indented one level and tied to the section by a guide rail. */
|
|
1137
|
+
.table tbody tr.groupChild td:first-child {
|
|
1138
|
+
padding-left: calc(var(--dsl-g-gap-md) + 22px);
|
|
1139
|
+
position: relative;
|
|
1140
|
+
}
|
|
1141
|
+
.table tbody tr.groupChild td:first-child::before {
|
|
1142
|
+
content: "";
|
|
1143
|
+
position: absolute;
|
|
1144
|
+
left: calc(var(--dsl-g-gap-md) + 8px);
|
|
1145
|
+
top: 0;
|
|
1146
|
+
bottom: 0;
|
|
1147
|
+
width: 1px;
|
|
1148
|
+
background: var(--dsl-g-border);
|
|
1149
|
+
}
|
|
1150
|
+
.table tbody tr.groupChild:last-child td:first-child::before { bottom: 50%; }
|
|
1151
|
+
.table tfoot td {
|
|
1152
|
+
border-top: 1px solid var(--dsl-g-border-strong);
|
|
1153
|
+
border-bottom: none;
|
|
1154
|
+
font-weight: 700;
|
|
1155
|
+
color: var(--dsw-alias-label-primary);
|
|
1156
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/* Card surface tones: tint + colored title, no bars. */
|
|
1160
|
+
.cardInfo { background: color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent); }
|
|
1161
|
+
.cardSuccess { background: color-mix(in srgb, var(--dsw-alias-state-success-primary, #3ecf8e) var(--dsl-g-tint), transparent); }
|
|
1162
|
+
.cardWarning { background: color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f5b83d) var(--dsl-g-tint), transparent); }
|
|
1163
|
+
.cardDanger { background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #ff6b6b) var(--dsl-g-tint), transparent); }
|
|
1164
|
+
.cardInfo > .cardTitle { color: var(--dsw-alias-state-business-primary, #4f8ef7); }
|
|
1165
|
+
.cardSuccess > .cardTitle { color: var(--dsw-alias-state-success-primary, #2f9e6b); }
|
|
1166
|
+
.cardWarning > .cardTitle { color: var(--dsw-alias-state-warn-primary, #b8860b); }
|
|
1167
|
+
.cardDanger > .cardTitle { color: var(--dsw-alias-state-error-primary, #d94848); }
|
|
1168
|
+
|
|
1169
|
+
/* ---------- horizontal bars (chart.horizontal) ---------- */
|
|
1170
|
+
|
|
1171
|
+
.hbars { display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
1172
|
+
.hbarRow { display: flex; align-items: center; gap: var(--dsl-g-gap-md); }
|
|
1173
|
+
.hbarLabel {
|
|
1174
|
+
width: 96px;
|
|
1175
|
+
flex-shrink: 0;
|
|
1176
|
+
text-align: right;
|
|
1177
|
+
font-size: var(--dsl-g-font-meta);
|
|
1178
|
+
color: var(--dsw-alias-label-secondary);
|
|
1179
|
+
white-space: nowrap;
|
|
1180
|
+
overflow: hidden;
|
|
1181
|
+
text-overflow: ellipsis;
|
|
1182
|
+
}
|
|
1183
|
+
.hbarTracks { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
|
|
1184
|
+
.hbarSeg { height: 100%; }
|
|
1185
|
+
.hbarTrack {
|
|
1186
|
+
display: flex;
|
|
1187
|
+
height: 14px;
|
|
1188
|
+
border-radius: var(--dsl-g-radius-sm);
|
|
1189
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent);
|
|
1190
|
+
overflow: hidden;
|
|
1191
|
+
}
|
|
1192
|
+
.hbarFill {
|
|
1193
|
+
height: 100%;
|
|
1194
|
+
min-width: 2px;
|
|
1195
|
+
border-radius: var(--dsl-g-radius-sm);
|
|
1196
|
+
background: var(--dsl-g-accent);
|
|
1197
|
+
transition: width 0.6s ease;
|
|
1198
|
+
}
|
|
1199
|
+
.hbarValue {
|
|
1200
|
+
width: 64px;
|
|
1201
|
+
flex-shrink: 0;
|
|
1202
|
+
text-align: right;
|
|
1203
|
+
font-family: var(--dsl-g-font-mono);
|
|
1204
|
+
font-size: var(--dsl-g-font-data);
|
|
1205
|
+
color: var(--dsw-alias-label-primary);
|
|
1206
|
+
font-variant-numeric: tabular-nums;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/* ---------- table cell types (types: ["bar"|"badge"|...]) ---------- */
|
|
1210
|
+
|
|
1211
|
+
.cellBadge {
|
|
1212
|
+
display: inline-block;
|
|
1213
|
+
padding: 1px 8px;
|
|
1214
|
+
border-radius: var(--dsl-g-radius-pill);
|
|
1215
|
+
background: color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);
|
|
1216
|
+
color: var(--dsw-alias-label-primary);
|
|
1217
|
+
font-size: var(--dsl-g-font-meta);
|
|
1218
|
+
font-weight: 600;
|
|
1219
|
+
}
|
|
1220
|
+
.cellSpark { display: block; width: 88px; height: 22px; overflow: visible; }
|
|
1221
|
+
.cellRing { display: inline-flex; align-items: center; gap: 6px; }
|
|
1222
|
+
.cellRingText {
|
|
1223
|
+
font-family: var(--dsl-g-font-mono);
|
|
1224
|
+
font-size: var(--dsl-g-font-data);
|
|
1225
|
+
color: var(--dsw-alias-label-primary);
|
|
1226
|
+
font-variant-numeric: tabular-nums;
|
|
1227
|
+
}
|
|
1228
|
+
.cellIndex {
|
|
1229
|
+
display: inline-block;
|
|
1230
|
+
min-width: 18px;
|
|
1231
|
+
font-family: var(--dsl-g-font-mono);
|
|
1232
|
+
font-size: var(--dsl-g-font-data);
|
|
1233
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1234
|
+
font-variant-numeric: tabular-nums;
|
|
1235
|
+
}
|
|
1236
|
+
.cellBar {
|
|
1237
|
+
position: relative;
|
|
1238
|
+
display: block;
|
|
1239
|
+
min-width: 104px;
|
|
1240
|
+
height: 18px;
|
|
1241
|
+
border-radius: var(--dsl-g-radius-sm);
|
|
1242
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent);
|
|
1243
|
+
overflow: hidden;
|
|
1244
|
+
}
|
|
1245
|
+
.cellBarFill {
|
|
1246
|
+
position: absolute;
|
|
1247
|
+
inset: 0 auto 0 0;
|
|
1248
|
+
border-radius: var(--dsl-g-radius-sm);
|
|
1249
|
+
background: color-mix(in srgb, var(--dsl-g-accent) 72%, transparent);
|
|
1250
|
+
}
|
|
1251
|
+
.cellBarText {
|
|
1252
|
+
position: relative;
|
|
1253
|
+
display: block;
|
|
1254
|
+
text-align: right;
|
|
1255
|
+
padding: 0 6px;
|
|
1256
|
+
font-family: var(--dsl-g-font-mono);
|
|
1257
|
+
font-size: var(--dsl-g-font-data);
|
|
1258
|
+
line-height: 18px;
|
|
1259
|
+
color: var(--dsw-alias-label-primary);
|
|
1260
|
+
}
|
|
612
1261
|
|
|
613
1262
|
/* ---------- radio / switch / textarea ---------- */
|
|
614
1263
|
|
|
@@ -716,8 +1365,8 @@
|
|
|
716
1365
|
|
|
717
1366
|
.textarea {
|
|
718
1367
|
width: 100%;
|
|
719
|
-
background: var(--
|
|
720
|
-
border: 1px solid var(--dsl-g-border);
|
|
1368
|
+
background: var(--dsl-g-surface);
|
|
1369
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
721
1370
|
border-radius: var(--dsl-g-radius-control);
|
|
722
1371
|
color: var(--dsw-alias-label-primary);
|
|
723
1372
|
padding: var(--dsl-g-gap-sm) 12px;
|
|
@@ -737,9 +1386,11 @@
|
|
|
737
1386
|
.accordion {
|
|
738
1387
|
display: flex;
|
|
739
1388
|
flex-direction: column;
|
|
740
|
-
border: 1px solid var(--dsl-g-border);
|
|
1389
|
+
border: 1px solid var(--dsl-g-border-surface);
|
|
741
1390
|
border-radius: var(--dsl-g-radius-surface);
|
|
742
1391
|
overflow: hidden;
|
|
1392
|
+
background: var(--dsl-g-surface);
|
|
1393
|
+
box-shadow: var(--dsl-g-shadow-card);
|
|
743
1394
|
}
|
|
744
1395
|
.accItem { border-bottom: 1px solid var(--dsl-g-border); }
|
|
745
1396
|
.accItem:last-child { border-bottom: none; }
|
|
@@ -749,26 +1400,35 @@
|
|
|
749
1400
|
align-items: center;
|
|
750
1401
|
justify-content: space-between;
|
|
751
1402
|
gap: var(--dsl-g-gap-sm);
|
|
752
|
-
background:
|
|
1403
|
+
background: transparent;
|
|
753
1404
|
border: none;
|
|
754
1405
|
color: var(--dsw-alias-label-primary);
|
|
755
|
-
padding:
|
|
756
|
-
font-size: var(--dsl-g-font-
|
|
1406
|
+
padding: 12px 15px;
|
|
1407
|
+
font-size: var(--dsl-g-font-body);
|
|
757
1408
|
font-weight: 600;
|
|
758
1409
|
cursor: pointer;
|
|
759
1410
|
font-family: inherit;
|
|
760
1411
|
line-height: 1.5;
|
|
1412
|
+
text-align: left;
|
|
761
1413
|
transition: background 0.15s, color 0.15s;
|
|
762
1414
|
}
|
|
763
|
-
.accHead:hover { background:
|
|
764
|
-
.accHead
|
|
765
|
-
|
|
1415
|
+
.accHead:hover { background: var(--dsl-g-hover); }
|
|
1416
|
+
.accHead[aria-expanded="true"] { border-bottom: 1px solid var(--dsl-g-border); }
|
|
1417
|
+
/* One chevron that rotates, instead of swapping glyphs: the state change reads
|
|
1418
|
+
as motion, and the closed/open shapes stay consistent. */
|
|
1419
|
+
.accChevron {
|
|
1420
|
+
flex-shrink: 0;
|
|
1421
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1422
|
+
font-size: 11px;
|
|
1423
|
+
transition: transform 0.2s ease;
|
|
1424
|
+
}
|
|
1425
|
+
.accChevron[data-open="true"] { transform: rotate(90deg); }
|
|
766
1426
|
.accBody {
|
|
767
|
-
padding:
|
|
1427
|
+
padding: 12px 15px 14px;
|
|
768
1428
|
display: flex;
|
|
769
1429
|
flex-direction: column;
|
|
770
1430
|
gap: var(--dsl-g-gap-sm);
|
|
771
|
-
background: var(--dsw-alias-
|
|
1431
|
+
background: color-mix(in srgb, var(--dsw-alias-label-primary) 2%, transparent);
|
|
772
1432
|
}
|
|
773
1433
|
|
|
774
1434
|
/* ---------- copy chip ---------- */
|
|
@@ -864,22 +1524,34 @@
|
|
|
864
1524
|
|
|
865
1525
|
.timeline { display: flex; flex-direction: column; }
|
|
866
1526
|
.tlItem { display: flex; gap: var(--dsl-g-gap-md); }
|
|
867
|
-
.tlRail { display: flex; flex-direction: column; align-items: center; width:
|
|
1527
|
+
.tlRail { display: flex; flex-direction: column; align-items: center; width: 10px; flex-shrink: 0; }
|
|
868
1528
|
.tlDot {
|
|
869
|
-
width:
|
|
870
|
-
height:
|
|
1529
|
+
width: 9px;
|
|
1530
|
+
height: 9px;
|
|
871
1531
|
border-radius: 50%;
|
|
872
|
-
margin-top:
|
|
1532
|
+
margin-top: 5px;
|
|
873
1533
|
flex-shrink: 0;
|
|
874
1534
|
background: var(--dsl-g-accent);
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1535
|
+
/* A soft halo instead of a hard ring: the dot reads as a marker on the rail
|
|
1536
|
+
rather than a bullet stuck to the text. */
|
|
1537
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) 16%, transparent);
|
|
1538
|
+
transition: transform 0.15s ease;
|
|
1539
|
+
}
|
|
1540
|
+
.tlItem:hover .tlDot { transform: scale(1.15); }
|
|
1541
|
+
.tlLine { flex: 1; width: 1px; margin: 4px 0 0; background: var(--dsl-g-border); }
|
|
1542
|
+
.tlBody { padding-bottom: 18px; flex: 1; min-width: 0; }
|
|
1543
|
+
.tlItem:last-child .tlBody { padding-bottom: 0; }
|
|
879
1544
|
.tlHead { display: flex; align-items: baseline; gap: var(--dsl-g-gap-md); }
|
|
880
|
-
.tlTitle { font-size: var(--dsl-g-font-
|
|
881
|
-
.tlTime {
|
|
882
|
-
|
|
1545
|
+
.tlTitle { font-size: var(--dsl-g-font-body); font-weight: 650; color: var(--dsw-alias-label-primary); line-height: 1.45; }
|
|
1546
|
+
.tlTime {
|
|
1547
|
+
margin-left: auto;
|
|
1548
|
+
white-space: nowrap;
|
|
1549
|
+
font-family: var(--dsl-g-font-mono);
|
|
1550
|
+
font-size: var(--dsl-g-font-data);
|
|
1551
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1552
|
+
font-variant-numeric: tabular-nums;
|
|
1553
|
+
}
|
|
1554
|
+
.tlDesc { font-size: var(--dsl-g-font-title); color: var(--dsw-alias-label-secondary); margin-top: 3px; line-height: 1.55; }
|
|
883
1555
|
|
|
884
1556
|
/* ---------- file tree ---------- */
|
|
885
1557
|
|
|
@@ -896,28 +1568,51 @@
|
|
|
896
1568
|
max-width: 100%;
|
|
897
1569
|
min-width: 0;
|
|
898
1570
|
}
|
|
899
|
-
.
|
|
900
|
-
.ftRow
|
|
901
|
-
|
|
902
|
-
|
|
1571
|
+
.ftChildren { display: block; }
|
|
1572
|
+
.ftRow {
|
|
1573
|
+
position: relative;
|
|
1574
|
+
display: flex;
|
|
1575
|
+
align-items: center;
|
|
1576
|
+
gap: 6px;
|
|
1577
|
+
min-height: 26px;
|
|
1578
|
+
padding: 2px var(--dsl-g-gap-xs);
|
|
1579
|
+
border-radius: var(--dsl-g-radius-sm);
|
|
1580
|
+
transition: background 0.12s;
|
|
1581
|
+
}
|
|
1582
|
+
.ftRow:hover { background: color-mix(in srgb, var(--dsw-alias-label-primary) 5%, transparent); }
|
|
1583
|
+
/* One hairline per depth level: the rail that makes a tree read as a tree. */
|
|
1584
|
+
/* Depth rails are absolutely positioned so the indentation itself stays the
|
|
1585
|
+
inline padding-left on the row (it must survive a stylesheet failure). */
|
|
1586
|
+
.ftGuide {
|
|
1587
|
+
position: absolute;
|
|
1588
|
+
top: 0;
|
|
1589
|
+
bottom: 0;
|
|
1590
|
+
width: 1px;
|
|
1591
|
+
background: var(--dsl-g-border);
|
|
1592
|
+
}
|
|
1593
|
+
.ftChevron {
|
|
1594
|
+
width: 10px;
|
|
903
1595
|
flex-shrink: 0;
|
|
904
|
-
|
|
905
|
-
text-align: center;
|
|
906
|
-
font-family: var(--dsl-g-font-mono);
|
|
907
|
-
color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary));
|
|
1596
|
+
font-size: 10px;
|
|
908
1597
|
line-height: 1;
|
|
1598
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1599
|
+
transition: transform 0.15s ease;
|
|
1600
|
+
transform-origin: 50% 50%;
|
|
909
1601
|
}
|
|
910
|
-
.
|
|
1602
|
+
.ftChevron[data-open="true"] { transform: rotate(90deg); }
|
|
1603
|
+
.ftGlyph { display: inline-flex; flex-shrink: 0; color: var(--dsw-alias-label-tertiary); }
|
|
1604
|
+
.ftGlyphDir { color: var(--dsl-g-accent); }
|
|
911
1605
|
/* Long paths must stay on ONE line (issue #28: per-character vertical
|
|
912
1606
|
wrapping when the host message column gets narrow). */
|
|
913
1607
|
.ftName {
|
|
914
1608
|
color: var(--dsw-alias-label-secondary);
|
|
1609
|
+
font-size: var(--dsl-g-font-title);
|
|
915
1610
|
white-space: nowrap;
|
|
916
1611
|
overflow: hidden;
|
|
917
1612
|
text-overflow: ellipsis;
|
|
918
1613
|
min-width: 0;
|
|
919
1614
|
}
|
|
920
|
-
.ftDir { color: var(--dsw-alias-label-primary); font-weight:
|
|
1615
|
+
.ftDir { color: var(--dsw-alias-label-primary); font-weight: 650; }
|
|
921
1616
|
.ftNameBtn {
|
|
922
1617
|
display: inline-flex;
|
|
923
1618
|
align-items: center;
|
|
@@ -927,7 +1622,7 @@
|
|
|
927
1622
|
background: none;
|
|
928
1623
|
border: none;
|
|
929
1624
|
font-family: inherit;
|
|
930
|
-
font-size: var(--dsl-g-font-
|
|
1625
|
+
font-size: var(--dsl-g-font-title);
|
|
931
1626
|
padding: 0;
|
|
932
1627
|
cursor: default;
|
|
933
1628
|
text-align: left;
|
|
@@ -945,6 +1640,52 @@ button.ftNameBtn[aria-expanded] { cursor: pointer; }
|
|
|
945
1640
|
.bcCurrent { color: var(--dsw-alias-label-primary); font-weight: 600; cursor: default; }
|
|
946
1641
|
.bcSep { color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); }
|
|
947
1642
|
|
|
1643
|
+
/* ---------- streaming skeleton ----------
|
|
1644
|
+
Shown while a fence body is still arriving and no component has finished.
|
|
1645
|
+
It replaces half-written JSON with a quiet shimmer that mirrors the block
|
|
1646
|
+
layout; the settle sweep restores the raw code block if the body never
|
|
1647
|
+
parses. */
|
|
1648
|
+
|
|
1649
|
+
.skeleton {
|
|
1650
|
+
display: flex;
|
|
1651
|
+
flex-direction: column;
|
|
1652
|
+
gap: var(--dsl-g-gap-md);
|
|
1653
|
+
padding: var(--dsl-g-gap-lg);
|
|
1654
|
+
border: 1px solid var(--dsl-g-border);
|
|
1655
|
+
border-radius: var(--dsl-g-radius-surface);
|
|
1656
|
+
background: var(--dsl-g-surface);
|
|
1657
|
+
}
|
|
1658
|
+
.skeletonTitle {
|
|
1659
|
+
display: block;
|
|
1660
|
+
width: 34%;
|
|
1661
|
+
height: 12px;
|
|
1662
|
+
border-radius: var(--dsl-g-radius-pill);
|
|
1663
|
+
}
|
|
1664
|
+
.skeletonBars { display: flex; gap: var(--dsl-g-gap-sm); }
|
|
1665
|
+
.skeletonBars > span { display: block; height: 44px; border-radius: var(--dsl-g-radius-control); }
|
|
1666
|
+
.skeletonBlock { display: block; height: 76px; border-radius: var(--dsl-g-radius-control); }
|
|
1667
|
+
.skeletonTitle,
|
|
1668
|
+
.skeletonBars > span,
|
|
1669
|
+
.skeletonBlock {
|
|
1670
|
+
background: linear-gradient(
|
|
1671
|
+
90deg,
|
|
1672
|
+
color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent) 0%,
|
|
1673
|
+
color-mix(in srgb, var(--dsw-alias-label-primary) 13%, transparent) 50%,
|
|
1674
|
+
color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent) 100%
|
|
1675
|
+
);
|
|
1676
|
+
background-size: 200% 100%;
|
|
1677
|
+
animation: dsl-skeleton 1.4s ease-in-out infinite;
|
|
1678
|
+
}
|
|
1679
|
+
@keyframes dsl-skeleton {
|
|
1680
|
+
0% { background-position: 200% 0; }
|
|
1681
|
+
100% { background-position: -200% 0; }
|
|
1682
|
+
}
|
|
1683
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1684
|
+
.skeletonTitle,
|
|
1685
|
+
.skeletonBars > span,
|
|
1686
|
+
.skeletonBlock { animation: none; }
|
|
1687
|
+
}
|
|
1688
|
+
|
|
948
1689
|
/* ---------- staggered reveal ---------- */
|
|
949
1690
|
|
|
950
1691
|
@keyframes genuiReveal {
|
|
@@ -1096,7 +1837,16 @@ button.ftNameBtn[aria-expanded] { cursor: pointer; }
|
|
|
1096
1837
|
color: var(--dsw-alias-state-success-primary, #3ecf8e);
|
|
1097
1838
|
line-height: 1.5;
|
|
1098
1839
|
}
|
|
1099
|
-
.quizMarker {
|
|
1840
|
+
.quizMarker {
|
|
1841
|
+
display: inline-block;
|
|
1842
|
+
width: 14px;
|
|
1843
|
+
text-align: center;
|
|
1844
|
+
font-weight: 700;
|
|
1845
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1846
|
+
flex-shrink: 0;
|
|
1847
|
+
}
|
|
1848
|
+
.quizOptCorrect .quizMarker { color: var(--dsw-alias-state-success-primary, #3ecf8e); }
|
|
1849
|
+
.quizOptWrong .quizMarker { color: var(--dsw-alias-state-error-primary, #ff6b6b); }
|
|
1100
1850
|
.quizResult { display: flex; flex-direction: column; gap: var(--dsl-g-gap-sm); }
|
|
1101
1851
|
.quizCorrectMsg { font-size: var(--dsl-g-font-title); font-weight: 600; color: var(--dsw-alias-state-success-primary, #3ecf8e); }
|
|
1102
1852
|
.quizWrongMsg { font-size: var(--dsl-g-font-title); font-weight: 600; color: var(--dsw-alias-state-error-primary, #ff6b6b); }
|