@open-feishu-card/renderer 0.1.0 → 0.2.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/dist/styles.css CHANGED
@@ -1,605 +1,1010 @@
1
- /**
2
- * open-feishu-card 样式表。
3
- * 精简复刻飞书 Universal Card 外观,自包含(不依赖飞书 design token)。
4
- * 类名沿用飞书原版前缀 universal-card。
5
- *
6
- * 注意:header 高光纹理图通过 JS 内联 base64 注入到 .universal-card-header__bg
7
- * 的 background-image(见 renderCard 输出的内联 style),故此处不写 url()。
8
- */
9
-
10
- .universal-card-root {
11
- /* 对齐飞书网页版 locale=zh 字体栈:西文优先 Helvetica Neue / Tahoma,
12
- * 中文再回落到 PingFang SC / Microsoft Yahei。原先把 PingFang 放在西文字体前,
13
- * Windows 上会用微软雅黑的拉丁字形,观感与真卡不一致。 */
14
- font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma,
15
- "PingFang SC", "Microsoft YaHei", Arial, "Hiragino Sans GB", sans-serif,
16
- "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
17
- font-size: 14px;
18
- line-height: 1.6;
19
- color: #1f2329;
20
- background-color: #fff;
21
- border-radius: 8px;
22
- border: 1px solid #dee0e3;
23
- overflow: hidden;
24
- width: 100%;
25
- max-width: 605px;
26
- box-sizing: border-box;
27
- box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
28
- }
29
- .universal-card-root *,
30
- .universal-card-root *::before,
31
- .universal-card-root *::after { box-sizing: border-box; }
32
-
33
- /* ---- header ---- */
34
- .universal-card-header {
35
- width: 100%;
36
- overflow: hidden;
37
- border-top-left-radius: 8px;
38
- border-top-right-radius: 8px;
39
- }
40
- .universal-card-header__bg {
41
- box-sizing: border-box;
42
- width: 100%;
43
- padding: 12px;
44
- background-repeat: no-repeat;
45
- background-position: 0 0;
46
- /* 图宽=header宽,使纹理自身的左右暗边落在 header 两端、亮带居中 */
47
- background-size: 100% 140px;
48
- }
49
- /* 内容行:左侧图标 + 右侧标题区(对齐网页版 header__content = row) */
50
- .universal-card-header__content {
51
- width: 100%;
52
- display: flex;
53
- flex-direction: row;
54
- align-items: flex-start;
55
- }
56
- .universal-card-header__icon {
57
- display: flex;
58
- height: 24px;
59
- align-items: center;
60
- margin-right: 8px;
61
- flex-shrink: 0;
62
- color: inherit;
63
- }
64
- .universal-card-header__text {
65
- flex: 1;
66
- max-width: 100%;
67
- line-height: 24px;
68
- overflow: hidden;
69
- min-width: 0;
70
- }
71
- /* 标题行:标题 + 右侧标签同排 */
72
- .universal-card-header__text-title-wrapper,
73
- .universal-card-header__title-row {
74
- display: flex;
75
- flex-wrap: wrap;
76
- align-items: center;
77
- }
78
- .universal-card-header__tags {
79
- display: inline-flex;
80
- align-items: center;
81
- gap: 4px;
82
- line-height: 1;
83
- max-width: 100%;
84
- }
85
- .universal-card-header__text-title {
86
- overflow: hidden;
87
- margin-right: 4px;
88
- font-size: 16px;
89
- font-weight: 600;
90
- line-height: 24px;
91
- word-break: break-word;
92
- }
93
- /* 副标题:与标题同色,仅字重更轻(对齐真机 font-weight:400,无 opacity) */
94
- .universal-card-header__text-subtitle {
95
- margin-top: 2px;
96
- font-size: 14px;
97
- font-weight: 400;
98
- line-height: 22px;
99
- overflow: hidden;
100
- display: -webkit-box;
101
- -webkit-box-orient: vertical;
102
- -webkit-line-clamp: 1;
103
- word-break: break-word;
104
- }
105
-
106
- /* ---- body ---- */
107
- .universal-card-body {
108
- padding: 12px;
109
- display: flex;
110
- flex-direction: column;
111
- row-gap: 8px;
112
- align-items: flex-start;
113
- }
114
- .universal-card-body > * { width: 100%; box-sizing: border-box; }
115
-
116
- /* ---- markdown 段落 ---- */
117
- /* 对齐网页版:line-height 默认 1.6;具体字号/行高由组件内联 style 按 text_size 给出 */
118
- .universal-card-markdown {
119
- display: flex;
120
- width: 100%;
121
- box-sizing: border-box;
122
- font-size: 14px;
123
- line-height: 1.6;
124
- color: #1f2329;
125
- word-break: break-word;
126
- vertical-align: middle;
127
- }
128
- .universal-card-markdown__children {
129
- flex: 1;
130
- min-width: 0;
131
- overflow: hidden;
132
- white-space: pre-wrap;
133
- }
134
-
135
- /* ---- hr 分割线 ---- */
136
- .universal-card-hr {
137
- width: 100%;
138
- height: 1px;
139
- background-color: #dee0e3;
140
- border: none;
141
- margin: 8px 0;
142
- }
143
-
144
- /* ---- div ---- */
145
- .universal-card-div > * + * { margin-top: 8px; }
146
- /* div 带前置图标:icon 在左、文本在右排成一行(复刻网页版 .universal-card-div 布局) */
147
- .universal-card-div--with-icon {
148
- display: flex; flex-wrap: nowrap; align-items: flex-start; line-height: 1.6;
149
- }
150
- .universal-card-div--with-icon > * + * { margin-top: 0; }
151
- .universal-card-div__icon_wrapper {
152
- margin-right: 8px; flex-shrink: 0; height: 1.6em;
153
- display: flex; align-items: center; overflow: hidden;
154
- }
155
- .universal-card-div__content { flex: 1; min-width: 0; }
156
-
157
- /* ---- 布局:column_set / column ---- */
158
- .universal-card-column-set { display: flex; }
159
- .universal-card-column { box-sizing: border-box; overflow-wrap: anywhere; }
160
- /* 列内纵向间距唯一来源是 column 组件输出的 flex row-gap(默认 8px,可被 vertical_spacing 覆盖)。
161
- 这里不再给相邻子元素设 margin-top——否则与 row-gap 叠加,间距翻倍。 */
162
-
163
- /* ---- 图片 ---- */
164
- .universal-card-image__wrapper { display: flex; max-width: 100%; }
165
- .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 4px; }
166
- .universal-card-image__placeholder {
167
- display: inline-flex; align-items: center; justify-content: center;
168
- min-width: 80px; min-height: 48px; padding: 8px 12px;
169
- color: #8f959e; background: #f5f6f7; border: 1px dashed #dee0e3; border-radius: 4px;
170
- font-size: 12px;
171
- }
172
-
173
- /* ---- 按钮 ---- */
174
- /* 飞书按钮文本是纯文本、单行:min-height 容纳偶发换行,文字超长省略号收尾。
175
- 样式全集逆向自网页版 ud__button:三大族——outlined(描边)/ text(纯文字)/ filled(实心),
176
- 每族再分 default / primary / danger 色,另加 laser 渐变。默认(未加变体类)= outlined-default。 */
177
- .universal-card-button {
178
- display: inline-flex; align-items: center; justify-content: center;
179
- gap: 4px;
180
- min-height: 28px; padding: 4px 12px;
181
- font-size: 14px; line-height: 22px; border-radius: 6px;
182
- border: 1px solid transparent; background: transparent; color: #1f2329;
183
- cursor: pointer; text-decoration: none; box-sizing: border-box;
184
- white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
185
- transition: background-color .1s, border-color .1s, color .1s;
186
- }
187
- /* 按钮前置图标:继承按钮文字色(currentColor),高度对齐行高 */
188
- .universal-card-button__icon {
189
- display: inline-flex; align-items: center; justify-content: center;
190
- flex-shrink: 0; height: 1.2em; color: inherit;
191
- }
192
- .universal-card-button__icon .universal-card-icon { color: inherit; }
193
- /* default 宽度:按内容收缩。列是 flex column(默认 align-items:stretch),
194
- body 又有 > * { width:100% },不加这两条会被撑满所在列。 */
195
- .universal-card-button:not(.universal-card-button--block) {
196
- width: auto;
197
- max-width: 100%;
198
- align-self: flex-start;
199
- }
200
- /* fill(width:"fill"):撑满所在列 */
201
- .universal-card-button--block { width: 100%; }
202
-
203
- /* —— outlined 描边族 —— */
204
- /* default:灰描边 + 白底 + 深字(未加变体类的裸 .universal-card-button 已是白底深字,
205
- 这里补上默认灰边与 default 变体一致) */
206
- .universal-card-button,
207
- .universal-card-button--default {
208
- border-color: #dee0e3; background: #fff; color: #1f2329;
209
- }
210
- .universal-card-button--default:not(.universal-card-button--static):hover { background: #f5f6f7; }
211
- /* primary:蓝描边 + 蓝字 + 白底 */
212
- .universal-card-button--primary {
213
- border-color: #1456f0; background: #fff; color: #1456f0;
214
- }
215
- .universal-card-button--primary:not(.universal-card-button--static):hover { background: #f0f4ff; }
216
- /* danger:红描边 + 红字 + 白底 */
217
- .universal-card-button--danger {
218
- border-color: #f54a45; background: #fff; color: #f54a45;
219
- }
220
- .universal-card-button--danger:not(.universal-card-button--static):hover { background: #fef0f0; }
221
-
222
- /* —— text 纯文字族(无边框/无底色,按内容宽) —— */
223
- .universal-card-button--text,
224
- .universal-card-button--primary_text,
225
- .universal-card-button--danger_text {
226
- border-color: transparent; background: transparent; padding: 4px 8px;
227
- }
228
- .universal-card-button--text { color: #1f2329; }
229
- .universal-card-button--primary_text { color: #1456f0; }
230
- .universal-card-button--danger_text { color: #f54a45; }
231
- .universal-card-button--text:not(.universal-card-button--static):hover { background: #f5f6f7; }
232
- .universal-card-button--primary_text:not(.universal-card-button--static):hover { background: #f0f4ff; }
233
- .universal-card-button--danger_text:not(.universal-card-button--static):hover { background: #fef0f0; }
234
-
235
- /* —— filled 实心族(有底色 + 白字) —— */
236
- .universal-card-button--primary_filled {
237
- border-color: #1456f0; background: #1456f0; color: #fff;
238
- }
239
- .universal-card-button--primary_filled:not(.universal-card-button--static):hover { background: #0442d2; border-color: #0442d2; }
240
- .universal-card-button--danger_filled {
241
- border-color: #f54a45; background: #f54a45; color: #fff;
242
- }
243
- .universal-card-button--danger_filled:not(.universal-card-button--static):hover { background: #e22e28; border-color: #e22e28; }
244
- /* laser:飞书「激光」渐变实心按钮(蓝→紫渐变 + 白字) */
245
- .universal-card-button--laser {
246
- border-color: transparent; color: #fff;
247
- background: linear-gradient(97deg, #4e83fd 0%, #7a35f0 100%);
248
- }
249
- .universal-card-button--laser:not(.universal-card-button--static):hover { filter: brightness(1.05); }
250
-
251
- .universal-card-button--disabled,
252
- .universal-card-button:disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
253
- /* 非跳转按钮:保留外观,但不可点(默认光标、无 hover、不响应点击) */
254
- .universal-card-button--static { cursor: default; pointer-events: none; }
255
-
256
- /* ---- 表单(预览:仅透传,无表单语义) ---- */
257
- .universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
258
- .universal-card-form > * { width: 100%; }
259
- /* input / select 等输入控件:预览里渲染成只读静态框,展示 placeholder */
260
- .universal-card-input--static {
261
- min-height: 32px; padding: 6px 12px; box-sizing: border-box;
262
- font-size: 14px; line-height: 20px; color: #8f959e;
263
- background: #f5f6f7; border: 1px solid #dee0e3; border-radius: 6px;
264
- cursor: default; pointer-events: none;
265
- }
266
-
267
- /* ---- action 容器 ---- */
268
- .universal-card-action { display: flex; flex-wrap: wrap; gap: 12px; }
269
-
270
- /* ---- checker 勾选器(对齐网页版 universal-card-checker) ---- */
271
- .universal-card-checker {
272
- display: flex; box-sizing: border-box; overflow: hidden; align-items: flex-start;
273
- color: inherit;
274
- }
275
- .universal-card-checker--hover.universal-card-checker:hover {
276
- background-color: rgba(31, 35, 41, 0.05); cursor: pointer;
277
- }
278
- .universal-card-checker--disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
279
- .universal-card-checker__checkbox-container {
280
- display: inline-flex; align-items: center; margin-right: 8px; flex-shrink: 0;
281
- height: calc(var(--universal-card-checker-line-height, 22px));
282
- position: relative; cursor: pointer;
283
- }
284
- /* 原生 checkbox 藏起,用自定义方框画外观;点击由外层 label / 本 label 承接 */
285
- .universal-card-checker__input {
286
- position: absolute; opacity: 0; width: 0; height: 0; margin: 0; padding: 0;
287
- }
288
- .universal-card-checker__box {
289
- width: 16px; height: 16px; box-sizing: border-box;
290
- border: 1px solid #8f959e; border-radius: 4px; background: #fff;
291
- display: inline-flex; align-items: center; justify-content: center;
292
- flex-shrink: 0; transition: background-color .1s, border-color .1s;
293
- }
294
- .universal-card-checker__input:checked + .universal-card-checker__box {
295
- background: #1456f0; border-color: #1456f0;
296
- }
297
- .universal-card-checker__input:checked + .universal-card-checker__box::after {
298
- content: ""; width: 3.5px; height: 7px;
299
- border: solid #fff; border-width: 0 2px 2px 0;
300
- transform: rotate(45deg) translateY(-0.5px);
301
- }
302
- .universal-card-checker__content {
303
- /* 真机:content 是 flex,唯一子项是 .universal-card-text(行内排版)。
304
- * 不要把 text_tag / plain_text 直接做成 flex 子项——行首空格会被吃掉,
305
- * tag 与后续文字贴死(真机靠 break-spaces + 行内流保留 content 里的空格)。 */
306
- display: flex; flex: 1; min-width: 35px;
307
- line-height: calc(var(--universal-card-checker-line-height, 22px));
308
- word-break: break-word;
309
- }
310
- /* 真机 .universal-card-text:保留连续空格(text_tag 后常见两个空格) */
311
- .universal-card-text {
312
- word-break: break-word;
313
- white-space: break-spaces;
314
- }
315
- /* 勾选态:删除线 / 透明度由 :has(:checked) 驱动,本地切换无需 JS */
316
- .universal-card-checker--strike:has(.universal-card-checker__input:checked) .universal-card-checker__content {
317
- text-decoration-line: line-through;
318
- text-decoration-color: inherit;
319
- }
320
- .universal-card-checker:has(.universal-card-checker__input:checked) .universal-card-checker__content {
321
- opacity: var(--checker-checked-opacity, 1);
322
- }
323
- .universal-card-checker__content--right { justify-content: right; }
324
- .universal-card-checker__content--center { justify-content: center; }
325
- .universal-card-checker__buttons {
326
- display: flex; margin-left: 16px; column-gap: 10px; max-width: 150px; flex-shrink: 0;
327
- align-items: center;
328
- }
329
- .universal-card-checker__buttons--auto-hide { opacity: 0; }
330
- .universal-card-checker:hover .universal-card-checker__buttons--auto-hide { opacity: 1; }
331
- .universal-card-checker__button { display: inline-flex; align-items: center; }
332
-
333
-
334
- /* ---- interactive_container 可点击交互容器 ---- */
335
- .universal-card-interactive-container {
336
- display: flex; flex-direction: column; box-sizing: border-box;
337
- border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
338
- cursor: pointer; transition: background-color .1s;
339
- }
340
- .universal-card-interactive-container:not(.universal-card-interactive-container--disabled):hover {
341
- background-color: rgba(31, 35, 41, 0.05);
342
- }
343
- .universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
344
- /* disabled:去掉手型指针与 hover 灰底,外观退回普通块 */
345
- .universal-card-interactive-container--disabled {
346
- cursor: default; transition: none;
347
- }
348
-
349
- /* ---- collapsible_panel 折叠面板(原生 <details>/<summary>,纯 CSS 可点) ---- */
350
- /* 外层 <details> 容器:border/background/radius 由内联 style 给(来自 border/background_color)。 */
351
- .universal-card-collapsible-panel {
352
- box-sizing: border-box; overflow: hidden;
353
- }
354
- /* header(<summary>):可点击整行;去掉浏览器默认三角标记,标题占满、箭头贴右
355
- (icon_position=left 时靠 DOM 顺序在左)。 */
356
- .universal-card-collapsible-panel__header {
357
- display: flex; align-items: center; gap: 8px;
358
- padding: 8px 12px;
359
- cursor: pointer; box-sizing: border-box;
360
- list-style: none; user-select: none;
361
- }
362
- .universal-card-collapsible-panel__header::-webkit-details-marker { display: none; }
363
- .universal-card-collapsible-panel__header::marker { content: ''; }
364
- .universal-card-collapsible-panel__title {
365
- flex: 1; min-width: 0; font-size: 14px; line-height: 22px; color: #1f2329;
366
- word-break: break-word;
367
- }
368
- /* 箭头图标包裹:收起态角度 0;展开态(details[open])旋转到 --panel-icon-angle(内联给出,默认 -180deg)。
369
- 由用户点击 <summary> 切换 [open],箭头方向随之自动更新,无需 JS。 */
370
- .universal-card-collapsible-panel__icon {
371
- flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
372
- transition: transform .2s; color: #646a73; transform: rotate(0deg);
373
- }
374
- .universal-card-collapsible-panel[open] .universal-card-collapsible-panel__icon {
375
- transform: rotate(var(--panel-icon-angle, -180deg));
376
- }
377
- /* 内容区:展开时显示(折叠态由 <details> 交给浏览器隐藏)。左右/底部内边距对齐 header
378
- (真机内容 margin 0 12px 12px),顶部紧贴 header 不留空。 */
379
- .universal-card-collapsible-panel__content {
380
- box-sizing: border-box; padding: 0 12px 12px;
381
- }
382
-
383
- /* ---- 人员 person_v1 / person_list(对齐网页版 universal-card-person*)---- */
384
- .universal-card-person {
385
- display: inline-flex; align-items: center; width: auto; max-width: 100%;
386
- vertical-align: bottom;
387
- }
388
- .universal-card-person__content {
389
- display: flex; align-items: center; max-width: 100%; cursor: default;
390
- }
391
- /* 真机 --udtoken-tag-neutral-bg-normal = rgba(N900-raw, .1) = rgba(31,35,41,.1) */
392
- .universal-card-person__content--capsule.universal-card-person__content--name {
393
- background: rgba(31, 35, 41, 0.1); border-radius: 99px;
394
- }
395
- .universal-card-person__avatar-wrapper {
396
- display: flex; flex-shrink: 0;
397
- }
398
- .universal-card-person__internal-avatar,
399
- .universal-card-person-list__avatar,
400
- .universal-card-person-list__unknown-avatar {
401
- flex-shrink: 0; border-radius: 50%; object-fit: cover;
402
- display: inline-flex; align-items: center; justify-content: center;
403
- overflow: hidden; vertical-align: middle;
404
- }
405
- .universal-card-person__avatar--placeholder {
406
- background-color: #bbbfc4; color: #fff; font-weight: 500;
407
- line-height: 1; text-transform: uppercase; user-select: none;
408
- }
409
- .universal-card-person__name {
410
- display: inline-flex; align-items: center; min-width: 0;
411
- color: #1f2329; max-width: 100%;
412
- }
413
- .universal-card-person__name .universal-card-text--line-1 {
414
- display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1;
415
- overflow: hidden; word-break: break-all;
416
- }
417
- .universal-card-person .universal-card-text { line-height: inherit; }
418
-
419
- .universal-card-person-list {
420
- display: flex; width: 100%; position: relative; align-items: flex-start;
421
- justify-content: flex-start;
422
- }
423
- .universal-card-person-list--table {
424
- flex-wrap: wrap; gap: 4px 8px; width: auto;
425
- }
426
- .universal-card-person-list__icon {
427
- margin-right: 8px; flex-shrink: 0; overflow: hidden;
428
- display: flex; align-items: center; height: 1.6em;
429
- }
430
- .universal-card-person-list__content {
431
- overflow: hidden; min-width: 0; flex: 1;
432
- }
433
- .universal-card-person-list__content--lines {
434
- display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden;
435
- }
436
- .universal-card-person-list__content--combine {
437
- display: flex; flex-wrap: wrap; column-gap: 12px; row-gap: 8px;
438
- }
439
- .universal-card-person-list__avatar-name {
440
- display: inline-flex; overflow: hidden; text-overflow: ellipsis;
441
- white-space: nowrap; align-items: center; max-width: 100%;
442
- }
443
- .universal-card-person-list__avatar-name .universal-card-person-list__avatar,
444
- .universal-card-person-list__avatar-name .universal-card-person-list__unknown-avatar {
445
- margin-right: 4px; flex-shrink: 0;
446
- }
447
- .universal-card-person-list__reaction-user {
448
- align-items: center; display: inline-flex; overflow: hidden;
449
- text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
450
- vertical-align: middle;
451
- }
452
- .universal-card-person-list__reaction-user--blue { color: #1456f0; }
453
- .universal-card-person-list__reaction-user--disabled { cursor: default; }
454
- .universal-card-person-list__reaction-user__name {
455
- overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
456
- vertical-align: middle; display: inline-block; max-width: 100%;
457
- }
458
- .universal-card-person-list__reaction-user__comma {
459
- color: #8f959e; white-space: pre; vertical-align: middle;
460
- }
461
- /* 葫芦串:叠放头像,重叠处用 SVG mask 挖月牙(对齐 ud__avatar-hollow-out,不用白描边) */
462
- .universal-card-person-list__avatar-group {
463
- display: inline-flex; align-items: center; white-space: nowrap;
464
- }
465
- .universal-card-person-list__avatar-group-item {
466
- display: inline-flex; border-radius: 50%; overflow: hidden;
467
- position: relative; flex-shrink: 0;
468
- }
469
- .universal-card-person-list__avatar-group-item .universal-card-person-list__avatar,
470
- .universal-card-person-list__avatar-group-item .universal-card-person-list__unknown-avatar {
471
- display: block; width: 100%; height: 100%;
472
- }
473
-
474
- /* ---- @人 / 链接 ---- */
475
- .universal-card-markdown-at { word-break: break-word; }
476
- .universal-card-markdown-link { color: #1456f0; text-decoration: none; }
477
- .universal-card-markdown-link:hover { text-decoration: underline; }
478
-
479
- /* ---- text_tag 彩色标签 ---- */
480
- .universal-card-text-tag { vertical-align: middle; margin: 0 2px; white-space: nowrap; }
481
-
482
- /* ---- markdown: heading / blockquote / list / code ---- */
483
- .universal-card-markdown-heading { word-break: break-word; }
484
- .universal-card-blockquote {
485
- padding-left: 10px; position: relative; color: #646a73;
486
- }
487
- .universal-card-blockquote::before {
488
- content: " "; position: absolute; left: 0; top: 0; height: 100%; width: 2px;
489
- background-color: #dee0e3;
490
- }
491
- .universal-card-markdown-list { text-align: left; }
492
- .universal-card-markdown-list__item { align-items: flex-start; }
493
- .universal-card-markdown-list__marker { color: #1456f0; line-height: 1.6; }
494
- .universal-card-markdown-list__li-content { display: inline-block; }
495
- .universal-card-code-span {
496
- border-radius: 4px; border: 1px solid #dee0e3; padding: 0 4px;
497
- background-color: #f5f6f7; font-family: Menlo, Consolas, monospace; font-size: 13px;
498
- }
499
- .universal-card-markdown-code-block {
500
- text-align: left; padding: 12px; min-width: 210px; margin: 4px 0;
501
- font-size: 13px; font-weight: 400; line-height: 1.5;
502
- background-color: #f5f6f7; border-radius: 6px; overflow-x: auto;
503
- font-family: Menlo, Consolas, monospace; white-space: pre;
504
- }
505
- .universal-card-emoji { display: inline; }
506
- /* emoji 雪碧图:<i> 的 background-image/size/position/width 由 emoji.css(larkw-emoji__img--emoji-*)提供;
507
- 这里只管行内对齐(vertical-align 让表情与文字基线大致对齐)。 */
508
- .universal-card-emoji__img { display: inline-block; vertical-align: -0.15em; }
509
-
510
- /* 图标(standard_icon / ud_icon):glyph 由图标字体 :before 画出。
511
- 字体 @font-face 与每图标 content 规则随 JS 注入(浏览器端 renderCard 自动注入,
512
- Node/SSR 端引入 open-feishu-card/icon-font.css)。这里只管布局对齐。 */
513
- .universal-card-icon {
514
- display: inline-flex;
515
- align-items: center;
516
- justify-content: center;
517
- vertical-align: -0.125em;
518
- }
519
-
520
- /* ---- chart 图表 ---- */
521
- /* 挂载容器:aspect-ratio / height 由内联 style 给(来自 aspect_ratio)。
522
- VChart 水合后会往 __vchart 里塞 <canvas>;水合前显示 loading 占位。 */
523
- .universal-card-chart {
524
- position: relative;
525
- width: 100%;
526
- box-sizing: border-box;
527
- overflow: hidden;
528
- }
529
- .universal-card-chart__vchart {
530
- position: relative;
531
- width: 100%;
532
- height: 100%;
533
- display: block;
534
- }
535
- .universal-card-chart__vchart canvas { display: block; }
536
- .universal-card-chart__loading,
537
- .universal-card-chart__placeholder {
538
- display: flex; align-items: center; justify-content: center;
539
- width: 100%; height: 100%;
540
- color: #8f959e; font-size: 12px;
541
- background: #f5f6f7; border: 1px dashed #dee0e3; border-radius: 4px;
542
- box-sizing: border-box;
543
- }
544
-
545
- /* ---- table 表格 ---- */
546
- .universal-card-table {
547
- width: 100%;
548
- box-sizing: border-box;
549
- border: 1px solid #dee0e3;
550
- border-radius: 6px;
551
- overflow: hidden;
552
- }
553
- .universal-card-table__scroll { width: 100%; overflow-x: auto; }
554
- .universal-card-table__table {
555
- width: 100%;
556
- border-collapse: collapse;
557
- table-layout: auto;
558
- font-size: 14px;
559
- color: #1f2329;
560
- }
561
- .universal-card-table__th,
562
- .universal-card-table__td {
563
- padding: 8px 12px;
564
- border-bottom: 1px solid #dee0e3;
565
- border-right: 1px solid #eff0f1;
566
- vertical-align: middle;
567
- box-sizing: border-box;
568
- }
569
- .universal-card-table__th:last-child,
570
- .universal-card-table__td:last-child { border-right: none; }
571
- .universal-card-table__tbody tr:last-child .universal-card-table__td { border-bottom: none; }
572
- .universal-card-table__th {
573
- font-size: 14px;
574
- line-height: 22px;
575
- white-space: nowrap;
576
- color: #1f2329;
577
- }
578
- .universal-card-table__th-text--bold { font-weight: 600; }
579
- .universal-card-table__cell {
580
- display: flex;
581
- align-items: center;
582
- gap: 4px;
583
- word-break: break-word;
584
- }
585
- .universal-card-table__tags { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; }
586
-
587
- /* 暗色主题下的表格/图表占位 */
588
- .universal-card-root.theme-dark .universal-card-table { border-color: #2e2e30; }
589
- .universal-card-root.theme-dark .universal-card-table__th,
590
- .universal-card-root.theme-dark .universal-card-table__td { border-color: #2e2e30; color: #d6d6d6; }
591
- .universal-card-root.theme-dark .universal-card-table__th { color: #ebebeb; }
592
- .universal-card-root.theme-dark .universal-card-chart__loading,
593
- .universal-card-root.theme-dark .universal-card-chart__placeholder {
594
- background: #232323; border-color: #2e2e30; color: #8a8a8a;
595
- }
596
-
597
- /* ---- 暗色主题(可选):给 .universal-card-root 加 .theme-dark 即可 ----
598
- 暗色高光图同样由 JS 注入;如需纯 CSS 暗色,可自行覆盖 background-image。 */
599
- .universal-card-root.theme-dark {
600
- color: #ebebeb;
601
- background-color: #1a1a1a;
602
- border-color: #2e2e30;
603
- }
604
- .universal-card-root.theme-dark .universal-card-markdown { color: #d6d6d6; }
605
- .universal-card-root.theme-dark .universal-card-hr { background-color: #2e2e30; }
1
+ /**
2
+ * open-feishu-card 样式表。
3
+ * 精简复刻飞书 Universal Card 外观,自包含(不依赖飞书 design token)。
4
+ * 类名沿用飞书原版前缀 universal-card。
5
+ *
6
+ * 注意:header 高光纹理图通过 JS 内联 base64 注入到 .universal-card-header__bg
7
+ * 的 background-image(见 renderCard 输出的内联 style),故此处不写 url()。
8
+ */
9
+
10
+ .universal-card-root {
11
+ /* 对齐飞书网页版 locale=zh 字体栈:西文优先 Helvetica Neue / Tahoma,
12
+ * 中文再回落到 PingFang SC / Microsoft Yahei。原先把 PingFang 放在西文字体前,
13
+ * Windows 上会用微软雅黑的拉丁字形,观感与真卡不一致。 */
14
+ font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma,
15
+ "PingFang SC", "Microsoft YaHei", Arial, "Hiragino Sans GB", sans-serif,
16
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
17
+ font-size: 14px;
18
+ line-height: 1.6;
19
+ color: #1f2329;
20
+ background-color: #fff;
21
+ border-radius: 8px;
22
+ border: 1px solid #dee0e3;
23
+ overflow: hidden;
24
+ width: 100%;
25
+ max-width: 605px;
26
+ box-sizing: border-box;
27
+ box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
28
+ /* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
29
+ /* 正文 color:var(--O400) 等依赖这些变量;与飞书 :root light 色阶对齐 */
30
+ --B50: #f0f4ff;
31
+ --B100: #e0e9ff;
32
+ --B200: #c2d4ff;
33
+ --B300: #94b4ff;
34
+ --B350: #7aa2ff;
35
+ --B400: #5083fb;
36
+ --B500: #336df4;
37
+ --B600: #1456f0;
38
+ --B700: #0442d2;
39
+ --B800: #002f9e;
40
+ --B900: #002270;
41
+ --C50: #fef0f8;
42
+ --C100: #fee2f2;
43
+ --C200: #f8c4e1;
44
+ --C300: #f598cc;
45
+ --C350: #eb78b8;
46
+ --C400: #df58a5;
47
+ --C500: #cc398c;
48
+ --C600: #b82879;
49
+ --C700: #9d1562;
50
+ --C800: #730744;
51
+ --C900: #550c35;
52
+ --G50: #e4fae1;
53
+ --G100: #d0f5ce;
54
+ --G200: #95e599;
55
+ --G300: #5cd168;
56
+ --G350: #35bd4b;
57
+ --G400: #32a645;
58
+ --G500: #258832;
59
+ --G600: #1a7526;
60
+ --G700: #0b6017;
61
+ --G800: #04430c;
62
+ --G900: #022c07;
63
+ --I50: #f2f3fd;
64
+ --I100: #e9eafb;
65
+ --I200: #cccff9;
66
+ --I300: #abb0f2;
67
+ --I350: #959bee;
68
+ --I400: #757df0;
69
+ --I500: #5b65f5;
70
+ --I600: #4752e6;
71
+ --I700: #333dcc;
72
+ --I800: #1e27a4;
73
+ --I900: #151b70;
74
+ --L50: #f2f8d3;
75
+ --L100: #e3f0a3;
76
+ --L200: #c8dd5f;
77
+ --L300: #a2c10b;
78
+ --L350: #91ad00;
79
+ --L400: #7b9207;
80
+ --L500: #6b7f06;
81
+ --L600: #5c6d08;
82
+ --L700: #4a5804;
83
+ --L800: #333d00;
84
+ --L900: #262e00;
85
+ --N00: #ffffff;
86
+ --N50: #f5f6f7;
87
+ --N100: #f2f3f5;
88
+ --N200: #eff0f1;
89
+ --N300: #dee0e3;
90
+ --N350: #d0d3d6;
91
+ --N400: #bbbfc4;
92
+ --N500: #8f959e;
93
+ --N600: #646a73;
94
+ --N650: #51565d;
95
+ --N700: #373c43;
96
+ --N800: #2b2f36;
97
+ --N900: #1f2329;
98
+ --N950: #0f1114;
99
+ --N1000: #000000;
100
+ --O50: #fff3e5;
101
+ --O100: #fee7cd;
102
+ --O200: #fec48b;
103
+ --O300: #ff9d4c;
104
+ --O350: #ff811a;
105
+ --O400: #ed6d0c;
106
+ --O500: #c25705;
107
+ --O600: #a44904;
108
+ --O700: #853a05;
109
+ --O800: #642b02;
110
+ --O900: #3b1a02;
111
+ --P50: #f5f0fe;
112
+ --P100: #efe6fe;
113
+ --P200: #dcc9fd;
114
+ --P300: #c8a9fc;
115
+ --P350: #b791fa;
116
+ --P400: #9f6ff1;
117
+ --P500: #8d55ed;
118
+ --P600: #7a35f0;
119
+ --P700: #611fd6;
120
+ --P800: #4811a6;
121
+ --P900: #2f0080;
122
+ --R50: #fef0f0;
123
+ --R100: #fee3e2;
124
+ --R200: #fdc6c4;
125
+ --R300: #f89e9b;
126
+ --R350: #ff7570;
127
+ --R400: #f54a45;
128
+ --R500: #e22e28;
129
+ --R600: #c02a26;
130
+ --R700: #a11c17;
131
+ --R800: #741915;
132
+ --R900: #590603;
133
+ --S50: #ffffdb;
134
+ --S100: #fffca3;
135
+ --S200: #fff67a;
136
+ --S300: #fff258;
137
+ --S350: #ffe928;
138
+ --S400: #e5ce00;
139
+ --S500: #c2a800;
140
+ --S600: #8f7c00;
141
+ --S700: #5c4f00;
142
+ --S800: #423700;
143
+ --S900: #2c2502;
144
+ --T50: #e2f8f5;
145
+ --T100: #c4f2ec;
146
+ --T200: #6fe8d8;
147
+ --T300: #33d6c0;
148
+ --T350: #2dbeab;
149
+ --T400: #10a893;
150
+ --T500: #0f8575;
151
+ --T600: #067062;
152
+ --T700: #045d51;
153
+ --T800: #03443b;
154
+ --T900: #02312a;
155
+ --V50: #fceefc;
156
+ --V100: #f9e2f9;
157
+ --V200: #f3c4f3;
158
+ --V300: #e59ce5;
159
+ --V350: #de81de;
160
+ --V400: #cf5ecf;
161
+ --V500: #bf3dbf;
162
+ --V600: #a630a6;
163
+ --V700: #872787;
164
+ --V800: #6a116a;
165
+ --V900: #520052;
166
+ --W50: #e7f8fe;
167
+ --W100: #caeffc;
168
+ --W200: #97dcfc;
169
+ --W300: #3ec3f7;
170
+ --W350: #25b0e7;
171
+ --W400: #1295ca;
172
+ --W500: #047fb0;
173
+ --W600: #076a94;
174
+ --W700: #0f587a;
175
+ --W800: #06415c;
176
+ --W900: #072b3d;
177
+ --Y50: #fbf4df;
178
+ --Y100: #faedc2;
179
+ --Y200: #fcdf7e;
180
+ --Y300: #fad355;
181
+ --Y350: #ffc60a;
182
+ --Y400: #d99904;
183
+ --Y500: #ad7a03;
184
+ --Y600: #865b03;
185
+ --Y700: #6f4a01;
186
+ --Y800: #573601;
187
+ --Y900: #382201;
188
+ /* END PALETTE VARS */
189
+ }
190
+ .universal-card-root *,
191
+ .universal-card-root *::before,
192
+ .universal-card-root *::after { box-sizing: border-box; }
193
+
194
+ /* ---- header ---- */
195
+ .universal-card-header {
196
+ width: 100%;
197
+ overflow: hidden;
198
+ border-top-left-radius: 8px;
199
+ border-top-right-radius: 8px;
200
+ }
201
+ .universal-card-header__bg {
202
+ box-sizing: border-box;
203
+ width: 100%;
204
+ padding: 12px;
205
+ background-repeat: no-repeat;
206
+ background-position: 0 0;
207
+ /* 对齐飞书:max(100%, 605px) 140px,窄卡不把高光拉稀 */
208
+ background-size: max(100%, 605px) 140px;
209
+ }
210
+ /* 内容行:左侧图标 + 右侧标题区(对齐网页版 header__content = row) */
211
+ .universal-card-header__content {
212
+ width: 100%;
213
+ display: flex;
214
+ flex-direction: row;
215
+ align-items: flex-start;
216
+ }
217
+ .universal-card-header__icon {
218
+ display: flex;
219
+ height: 24px;
220
+ align-items: center;
221
+ margin-right: 8px;
222
+ flex-shrink: 0;
223
+ color: inherit;
224
+ }
225
+ .universal-card-header__text {
226
+ flex: 1;
227
+ max-width: 100%;
228
+ line-height: 24px;
229
+ overflow: hidden;
230
+ min-width: 0;
231
+ }
232
+ /* 标题行:标题 + 右侧标签同排 */
233
+ .universal-card-header__text-title-wrapper,
234
+ .universal-card-header__title-row {
235
+ display: flex;
236
+ flex-wrap: wrap;
237
+ align-items: center;
238
+ }
239
+ .universal-card-header__tags {
240
+ display: inline-flex;
241
+ align-items: center;
242
+ gap: 4px;
243
+ line-height: 1;
244
+ max-width: 100%;
245
+ }
246
+ .universal-card-header__text-title {
247
+ overflow: hidden;
248
+ margin-right: 4px;
249
+ font-size: 16px;
250
+ font-weight: 600;
251
+ line-height: 24px;
252
+ word-break: break-word;
253
+ }
254
+ /* 副标题:与标题同色,仅字重更轻(对齐真机 font-weight:400,无 opacity) */
255
+ .universal-card-header__text-subtitle {
256
+ margin-top: 2px;
257
+ font-size: 14px;
258
+ font-weight: 400;
259
+ line-height: 22px;
260
+ overflow: hidden;
261
+ display: -webkit-box;
262
+ -webkit-box-orient: vertical;
263
+ -webkit-line-clamp: 1;
264
+ word-break: break-word;
265
+ }
266
+
267
+ /* ---- body ---- */
268
+ .universal-card-body {
269
+ padding: 12px;
270
+ display: flex;
271
+ flex-direction: column;
272
+ row-gap: 8px;
273
+ align-items: flex-start;
274
+ }
275
+ .universal-card-body > * { width: 100%; box-sizing: border-box; }
276
+
277
+ /* ---- markdown 段落 ---- */
278
+ /* 对齐网页版:line-height 默认 1.6;具体字号/行高由组件内联 style 按 text_size 给出 */
279
+ .universal-card-markdown {
280
+ display: flex;
281
+ width: 100%;
282
+ box-sizing: border-box;
283
+ font-size: 14px;
284
+ line-height: 1.6;
285
+ color: #1f2329;
286
+ word-break: break-word;
287
+ vertical-align: middle;
288
+ }
289
+ .universal-card-markdown__children {
290
+ flex: 1;
291
+ min-width: 0;
292
+ overflow: hidden;
293
+ white-space: pre-wrap;
294
+ }
295
+
296
+ /* ---- hr 分割线 ---- */
297
+ .universal-card-hr {
298
+ width: 100%;
299
+ height: 1px;
300
+ background-color: #dee0e3;
301
+ border: none;
302
+ margin: 8px 0;
303
+ }
304
+
305
+ /* ---- div / note ---- */
306
+ .universal-card-div > * + * { margin-top: 8px; }
307
+ /* div 带前置图标:icon 在左、文本在右排成一行(复刻网页版 .universal-card-div 布局) */
308
+ .universal-card-div--with-icon {
309
+ display: flex; flex-wrap: nowrap; align-items: flex-start; line-height: 1.6;
310
+ }
311
+ .universal-card-div--with-icon > * + * { margin-top: 0; }
312
+ .universal-card-div__icon_wrapper {
313
+ margin-right: 8px; flex-shrink: 0; height: 1.6em;
314
+ display: flex; align-items: center; overflow: hidden;
315
+ }
316
+ .universal-card-div__content { flex: 1; min-width: 0; }
317
+ .universal-card-note {
318
+ font-size: 12px;
319
+ color: #8f959e;
320
+ }
321
+
322
+ /* ---- 布局:column_set / column ---- */
323
+ .universal-card-column-set { display: flex; }
324
+ .universal-card-column { box-sizing: border-box; overflow-wrap: anywhere; }
325
+ /* 列内纵向间距唯一来源是 column 组件输出的 flex row-gap(默认 8px,可被 vertical_spacing 覆盖)。
326
+ 这里不再给相邻子元素设 margin-top——否则与 row-gap 叠加,间距翻倍。 */
327
+
328
+ /* ---- 图片 ---- */
329
+ .universal-card-image__wrapper { display: flex; max-width: 100%; }
330
+ .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 4px; }
331
+ .universal-card-image__placeholder {
332
+ display: inline-flex; align-items: center; justify-content: center;
333
+ min-width: 80px; min-height: 48px; padding: 8px 12px;
334
+ color: #8f959e; background: #f5f6f7; border: 1px dashed #dee0e3; border-radius: 4px;
335
+ font-size: 12px;
336
+ }
337
+
338
+ /* ---- 按钮 ---- */
339
+ /* 飞书按钮文本是纯文本、单行:min-height 容纳偶发换行,文字超长省略号收尾。
340
+ 样式全集逆向自网页版 ud__button:三大族——outlined(描边)/ text(纯文字)/ filled(实心),
341
+ 每族再分 default / primary / danger 色,另加 laser 渐变。默认(未加变体类)= outlined-default。 */
342
+ .universal-card-button {
343
+ display: inline-flex; align-items: center; justify-content: center;
344
+ gap: 4px;
345
+ min-height: 28px; padding: 4px 12px;
346
+ font-size: 14px; line-height: 22px; border-radius: 6px;
347
+ border: 1px solid transparent; background: transparent; color: #1f2329;
348
+ cursor: pointer; text-decoration: none; box-sizing: border-box;
349
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
350
+ transition: background-color .1s, border-color .1s, color .1s;
351
+ }
352
+ /* 按钮前置图标:继承按钮文字色(currentColor),高度对齐行高 */
353
+ .universal-card-button__icon {
354
+ display: inline-flex; align-items: center; justify-content: center;
355
+ flex-shrink: 0; height: 1.2em; color: inherit;
356
+ }
357
+ .universal-card-button__icon .universal-card-icon { color: inherit; }
358
+ /* default 宽度:按内容收缩。列是 flex column(默认 align-items:stretch),
359
+ body 又有 > * { width:100% },不加这两条会被撑满所在列。 */
360
+ .universal-card-button:not(.universal-card-button--block) {
361
+ width: auto;
362
+ max-width: 100%;
363
+ align-self: flex-start;
364
+ }
365
+ /* fill(width:"fill"):撑满所在列 */
366
+ .universal-card-button--block { width: 100%; }
367
+
368
+ /* —— outlined 描边族 —— */
369
+ /* default:灰描边 + 白底 + 深字(未加变体类的裸 .universal-card-button 已是白底深字,
370
+ 这里补上默认灰边与 default 变体一致) */
371
+ .universal-card-button,
372
+ .universal-card-button--default {
373
+ border-color: #dee0e3; background: #fff; color: #1f2329;
374
+ }
375
+ .universal-card-button--default:not(.universal-card-button--static):hover { background: #f5f6f7; }
376
+ /* primary:蓝描边 + 蓝字 + 白底 */
377
+ .universal-card-button--primary {
378
+ border-color: #1456f0; background: #fff; color: #1456f0;
379
+ }
380
+ .universal-card-button--primary:not(.universal-card-button--static):hover { background: #f0f4ff; }
381
+ /* danger:红描边 + 红字 + 白底 */
382
+ .universal-card-button--danger {
383
+ border-color: #f54a45; background: #fff; color: #f54a45;
384
+ }
385
+ .universal-card-button--danger:not(.universal-card-button--static):hover { background: #fef0f0; }
386
+
387
+ /* —— text 纯文字族(无边框/无底色,按内容宽) —— */
388
+ .universal-card-button--text,
389
+ .universal-card-button--primary_text,
390
+ .universal-card-button--danger_text {
391
+ border-color: transparent; background: transparent; padding: 4px 8px;
392
+ }
393
+ .universal-card-button--text { color: #1f2329; }
394
+ .universal-card-button--primary_text { color: #1456f0; }
395
+ .universal-card-button--danger_text { color: #f54a45; }
396
+ .universal-card-button--text:not(.universal-card-button--static):hover { background: #f5f6f7; }
397
+ .universal-card-button--primary_text:not(.universal-card-button--static):hover { background: #f0f4ff; }
398
+ .universal-card-button--danger_text:not(.universal-card-button--static):hover { background: #fef0f0; }
399
+
400
+ /* —— filled 实心族(有底色 + 白字) —— */
401
+ .universal-card-button--primary_filled {
402
+ border-color: #1456f0; background: #1456f0; color: #fff;
403
+ }
404
+ .universal-card-button--primary_filled:not(.universal-card-button--static):hover { background: #0442d2; border-color: #0442d2; }
405
+ .universal-card-button--danger_filled {
406
+ border-color: #f54a45; background: #f54a45; color: #fff;
407
+ }
408
+ .universal-card-button--danger_filled:not(.universal-card-button--static):hover { background: #e22e28; border-color: #e22e28; }
409
+ /* laser:飞书「激光」渐变实心按钮(蓝→紫渐变 + 白字) */
410
+ .universal-card-button--laser {
411
+ border-color: transparent; color: #fff;
412
+ background: linear-gradient(97deg, #4e83fd 0%, #7a35f0 100%);
413
+ }
414
+ .universal-card-button--laser:not(.universal-card-button--static):hover { filter: brightness(1.05); }
415
+
416
+ .universal-card-button--disabled,
417
+ .universal-card-button:disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
418
+ /* 非跳转按钮:保留外观,但不可点(默认光标、无 hover、不响应点击) */
419
+ .universal-card-button--static { cursor: default; pointer-events: none; }
420
+
421
+ /* ---- 表单(预览:仅透传,无表单语义) ---- */
422
+ .universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
423
+ .universal-card-form > * { width: 100%; }
424
+ /* input / select 等输入控件:预览里渲染成只读静态框,展示 placeholder */
425
+ .universal-card-input--static {
426
+ min-height: 32px; padding: 6px 12px; box-sizing: border-box;
427
+ font-size: 14px; line-height: 20px; color: #8f959e;
428
+ background: #f5f6f7; border: 1px solid #dee0e3; border-radius: 6px;
429
+ cursor: default; pointer-events: none;
430
+ }
431
+
432
+ /* ---- action 容器 ---- */
433
+ .universal-card-action { display: flex; flex-wrap: wrap; gap: 12px; }
434
+
435
+ /* ---- checker 勾选器(对齐网页版 universal-card-checker) ---- */
436
+ .universal-card-checker {
437
+ display: flex; box-sizing: border-box; overflow: hidden; align-items: flex-start;
438
+ color: inherit;
439
+ }
440
+ .universal-card-checker--hover.universal-card-checker:hover {
441
+ background-color: rgba(31, 35, 41, 0.05); cursor: pointer;
442
+ }
443
+ .universal-card-checker--disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
444
+ .universal-card-checker__checkbox-container {
445
+ display: inline-flex; align-items: center; margin-right: 8px; flex-shrink: 0;
446
+ height: calc(var(--universal-card-checker-line-height, 22px));
447
+ position: relative; cursor: pointer;
448
+ }
449
+ /* 原生 checkbox 藏起,用自定义方框画外观;点击由外层 label / 本 label 承接 */
450
+ .universal-card-checker__input {
451
+ position: absolute; opacity: 0; width: 0; height: 0; margin: 0; padding: 0;
452
+ }
453
+ .universal-card-checker__box {
454
+ width: 16px; height: 16px; box-sizing: border-box;
455
+ border: 1px solid #8f959e; border-radius: 4px; background: #fff;
456
+ display: inline-flex; align-items: center; justify-content: center;
457
+ flex-shrink: 0; transition: background-color .1s, border-color .1s;
458
+ }
459
+ .universal-card-checker__input:checked + .universal-card-checker__box {
460
+ background: #1456f0; border-color: #1456f0;
461
+ }
462
+ .universal-card-checker__input:checked + .universal-card-checker__box::after {
463
+ content: ""; width: 3.5px; height: 7px;
464
+ border: solid #fff; border-width: 0 2px 2px 0;
465
+ transform: rotate(45deg) translateY(-0.5px);
466
+ }
467
+ .universal-card-checker__content {
468
+ /* 真机:content 是 flex,唯一子项是 .universal-card-text(行内排版)。
469
+ * 不要把 text_tag / plain_text 直接做成 flex 子项——行首空格会被吃掉,
470
+ * tag 与后续文字贴死(真机靠 break-spaces + 行内流保留 content 里的空格)。 */
471
+ display: flex; flex: 1; min-width: 35px;
472
+ line-height: calc(var(--universal-card-checker-line-height, 22px));
473
+ word-break: break-word;
474
+ }
475
+ /* 真机 .universal-card-text:保留连续空格(text_tag 后常见两个空格) */
476
+ .universal-card-text {
477
+ word-break: break-word;
478
+ white-space: break-spaces;
479
+ }
480
+ /* textStyle.attributes → BEM 修饰类(对齐真机 bold/italic/through) */
481
+ .universal-card-text--bold { font-weight: 600; }
482
+ .universal-card-text--italic { font-style: italic; }
483
+ .universal-card-text--through { text-decoration: line-through; }
484
+ /* 勾选态:删除线 / 透明度由 :has(:checked) 驱动,本地切换无需 JS */
485
+ .universal-card-checker--strike:has(.universal-card-checker__input:checked) .universal-card-checker__content {
486
+ text-decoration-line: line-through;
487
+ text-decoration-color: inherit;
488
+ }
489
+ .universal-card-checker:has(.universal-card-checker__input:checked) .universal-card-checker__content {
490
+ opacity: var(--checker-checked-opacity, 1);
491
+ }
492
+ .universal-card-checker__content--right { justify-content: right; }
493
+ .universal-card-checker__content--center { justify-content: center; }
494
+ .universal-card-checker__buttons {
495
+ display: flex; margin-left: 16px; column-gap: 10px; max-width: 150px; flex-shrink: 0;
496
+ align-items: center;
497
+ }
498
+ .universal-card-checker__buttons--auto-hide { opacity: 0; }
499
+ .universal-card-checker:hover .universal-card-checker__buttons--auto-hide { opacity: 1; }
500
+ .universal-card-checker__button { display: inline-flex; align-items: center; }
501
+
502
+
503
+ /* ---- interactive_container 可点击交互容器 ---- */
504
+ .universal-card-interactive-container {
505
+ display: flex; flex-direction: column; box-sizing: border-box;
506
+ border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
507
+ cursor: pointer; transition: background-color .1s;
508
+ }
509
+ .universal-card-interactive-container:not(.universal-card-interactive-container--disabled):hover {
510
+ background-color: rgba(31, 35, 41, 0.05);
511
+ }
512
+ .universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
513
+ /* disabled:去掉手型指针与 hover 灰底,外观退回普通块 */
514
+ .universal-card-interactive-container--disabled {
515
+ cursor: default; transition: none;
516
+ }
517
+
518
+ /* ---- collapsible_panel 折叠面板(原生 <details>/<summary>,纯 CSS 可点) ---- */
519
+ /* 外层 <details> 容器:border/background/radius 由内联 style 给(来自 border/background_color)。 */
520
+ .universal-card-collapsible-panel {
521
+ box-sizing: border-box; overflow: hidden;
522
+ }
523
+ /* header(<summary>):可点击整行;去掉浏览器默认三角标记,标题占满、箭头贴右
524
+ (icon_position=left 时靠 DOM 顺序在左)。 */
525
+ .universal-card-collapsible-panel__header {
526
+ display: flex; align-items: center; gap: 8px;
527
+ padding: 8px 12px;
528
+ cursor: pointer; box-sizing: border-box;
529
+ list-style: none; user-select: none;
530
+ }
531
+ .universal-card-collapsible-panel__header::-webkit-details-marker { display: none; }
532
+ .universal-card-collapsible-panel__header::marker { content: ''; }
533
+ .universal-card-collapsible-panel__title {
534
+ flex: 1; min-width: 0; font-size: 14px; line-height: 22px; color: #1f2329;
535
+ word-break: break-word;
536
+ }
537
+ /* 箭头图标包裹:收起态角度 0;展开态(details[open])旋转到 --panel-icon-angle(内联给出,默认 -180deg)。
538
+ 由用户点击 <summary> 切换 [open],箭头方向随之自动更新,无需 JS。 */
539
+ .universal-card-collapsible-panel__icon {
540
+ flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
541
+ transition: transform .2s; color: #646a73; transform: rotate(0deg);
542
+ }
543
+ .universal-card-collapsible-panel[open] .universal-card-collapsible-panel__icon {
544
+ transform: rotate(var(--panel-icon-angle, -180deg));
545
+ }
546
+ /* 内容区:展开时显示(折叠态由 <details> 交给浏览器隐藏)。左右/底部内边距对齐 header
547
+ (真机内容 margin 0 12px 12px),顶部紧贴 header 不留空。 */
548
+ .universal-card-collapsible-panel__content {
549
+ box-sizing: border-box; padding: 0 12px 12px;
550
+ }
551
+
552
+ /* ---- 人员 person_v1 / person_list(对齐网页版 universal-card-person*)---- */
553
+ .universal-card-person {
554
+ display: inline-flex; align-items: center; width: auto; max-width: 100%;
555
+ }
556
+ /* 有头像:网页版就是 vertical-align:bottom。middle 按拉丁 x-height 居中,
557
+ * 中文行里整盒(头像 18 + 姓名 22)会视觉偏下。
558
+ * 仅姓名:跟正文基线对齐,不要 bottom/middle。 */
559
+ .universal-card-markdown .universal-card-person--avatar,
560
+ .universal-card-person--avatar {
561
+ vertical-align: bottom;
562
+ }
563
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) {
564
+ vertical-align: baseline;
565
+ align-items: baseline;
566
+ }
567
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) .universal-card-person__content,
568
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) .universal-card-person__name {
569
+ align-items: baseline;
570
+ }
571
+ .universal-card-person__content {
572
+ display: flex; align-items: center; max-width: 100%; cursor: default;
573
+ }
574
+ /* 真机 --udtoken-tag-neutral-bg-normal = rgba(N900-raw, .1) = rgba(31,35,41,.1) */
575
+ .universal-card-person__content--capsule.universal-card-person__content--name {
576
+ background: rgba(31, 35, 41, 0.1); border-radius: 99px;
577
+ }
578
+ .universal-card-person__avatar-wrapper {
579
+ display: flex; flex-shrink: 0;
580
+ }
581
+ .universal-card-person__internal-avatar,
582
+ .universal-card-person-list__avatar,
583
+ .universal-card-person-list__unknown-avatar {
584
+ flex-shrink: 0; border-radius: 50%; object-fit: cover;
585
+ display: inline-flex; align-items: center; justify-content: center;
586
+ overflow: hidden; vertical-align: middle;
587
+ }
588
+ .universal-card-person__avatar--placeholder {
589
+ background-color: #bbbfc4; color: #fff; font-weight: 500;
590
+ line-height: 1; text-transform: uppercase; user-select: none;
591
+ }
592
+ .universal-card-person__name {
593
+ display: inline-flex; align-items: center; min-width: 0;
594
+ color: #1f2329; max-width: 100%;
595
+ }
596
+ /* 真机 --line-1 是 block + nowrap,不是 -webkit-box clamp;
597
+ * clamp 会破坏 inline-flex 基线,姓名在正文里看起来靠下。 */
598
+ .universal-card-person__name .universal-card-text--line-1 {
599
+ display: block; white-space: nowrap;
600
+ overflow: hidden; text-overflow: ellipsis;
601
+ }
602
+ .universal-card-person .universal-card-text { line-height: inherit; }
603
+
604
+ .universal-card-person-list {
605
+ display: flex; width: 100%; position: relative; align-items: flex-start;
606
+ justify-content: flex-start;
607
+ }
608
+ .universal-card-person-list--table {
609
+ flex-wrap: wrap; gap: 4px 8px; width: auto;
610
+ }
611
+ .universal-card-person-list__icon {
612
+ margin-right: 8px; flex-shrink: 0; overflow: hidden;
613
+ display: flex; align-items: center; height: 1.6em;
614
+ }
615
+ .universal-card-person-list__content {
616
+ overflow: hidden; min-width: 0; flex: 1;
617
+ }
618
+ .universal-card-person-list__content--lines {
619
+ display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden;
620
+ }
621
+ .universal-card-person-list__content--combine {
622
+ display: flex; flex-wrap: wrap; column-gap: 12px; row-gap: 8px;
623
+ }
624
+ .universal-card-person-list__avatar-name {
625
+ display: inline-flex; overflow: hidden; text-overflow: ellipsis;
626
+ white-space: nowrap; align-items: center; max-width: 100%;
627
+ }
628
+ .universal-card-person-list__avatar-name .universal-card-person-list__avatar,
629
+ .universal-card-person-list__avatar-name .universal-card-person-list__unknown-avatar {
630
+ margin-right: 4px; flex-shrink: 0;
631
+ }
632
+ .universal-card-person-list__reaction-user {
633
+ align-items: center; display: inline-flex; overflow: hidden;
634
+ text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
635
+ vertical-align: middle;
636
+ }
637
+ .universal-card-person-list__reaction-user--blue { color: #1456f0; }
638
+ .universal-card-person-list__reaction-user--disabled { cursor: default; }
639
+ .universal-card-person-list__reaction-user__name {
640
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
641
+ vertical-align: middle; display: inline-block; max-width: 100%;
642
+ }
643
+ .universal-card-person-list__reaction-user__comma {
644
+ color: #8f959e; white-space: pre; vertical-align: middle;
645
+ }
646
+ /* 葫芦串:叠放头像,重叠处用 SVG mask 挖月牙(对齐 ud__avatar-hollow-out,不用白描边) */
647
+ .universal-card-person-list__avatar-group {
648
+ display: inline-flex; align-items: center; white-space: nowrap;
649
+ }
650
+ .universal-card-person-list__avatar-group-item {
651
+ display: inline-flex; border-radius: 50%; overflow: hidden;
652
+ position: relative; flex-shrink: 0;
653
+ }
654
+ .universal-card-person-list__avatar-group-item .universal-card-person-list__avatar,
655
+ .universal-card-person-list__avatar-group-item .universal-card-person-list__unknown-avatar {
656
+ display: block; width: 100%; height: 100%;
657
+ }
658
+
659
+ /* ---- @人 / 链接 ---- */
660
+ .universal-card-markdown-at { word-break: break-word; }
661
+ .universal-card-markdown-link { color: #1456f0; text-decoration: none; }
662
+ .universal-card-markdown-link:hover { text-decoration: underline; }
663
+
664
+ /* ---- text_tag 彩色标签 ---- */
665
+ .universal-card-text-tag { vertical-align: middle; margin: 0 2px; white-space: nowrap; }
666
+
667
+ /* ---- markdown: heading / blockquote / list / code ---- */
668
+ .universal-card-markdown-heading { word-break: break-word; }
669
+ .universal-card-blockquote {
670
+ padding-left: 10px; position: relative; color: #646a73;
671
+ }
672
+ .universal-card-blockquote::before {
673
+ content: " "; position: absolute; left: 0; top: 0; height: 100%; width: 2px;
674
+ background-color: #dee0e3;
675
+ }
676
+ .universal-card-markdown-list { text-align: left; }
677
+ .universal-card-markdown-list__item { align-items: flex-start; }
678
+ .universal-card-markdown-list__marker { color: #1456f0; line-height: 1.6; }
679
+ .universal-card-markdown-list__li-content { display: inline-block; }
680
+ .universal-card-code-span {
681
+ border-radius: 4px; border: 1px solid #dee0e3; padding: 0 4px;
682
+ background-color: #f5f6f7; font-family: Menlo, Consolas, monospace; font-size: 13px;
683
+ }
684
+ .universal-card-markdown-code-block {
685
+ text-align: left; padding: 12px; min-width: 210px; margin: 4px 0;
686
+ font-size: 13px; font-weight: 400; line-height: 1.5;
687
+ background-color: #f5f6f7; border-radius: 6px; overflow-x: auto;
688
+ font-family: Menlo, Consolas, monospace; white-space: pre;
689
+ }
690
+ .universal-card-emoji { display: inline; }
691
+ /* emoji 雪碧图:<i> 的 background-image/size/position/width 由 emoji.css(larkw-emoji__img--emoji-*)提供;
692
+ 这里只管行内对齐(vertical-align 让表情与文字基线大致对齐)。 */
693
+ .universal-card-emoji__img { display: inline-block; vertical-align: -0.15em; }
694
+
695
+ /* 图标(standard_icon / ud_icon):glyph 由图标字体 :before 画出。
696
+ 字体 @font-face 与每图标 content 规则随 JS 注入(浏览器端 renderCard 自动注入,
697
+ Node/SSR 端引入 open-feishu-card/icon-font.css)。这里只管布局对齐。 */
698
+ .universal-card-icon {
699
+ display: inline-flex;
700
+ align-items: center;
701
+ justify-content: center;
702
+ vertical-align: -0.125em;
703
+ }
704
+
705
+ /* ---- video 视频 ---- */
706
+ /* 对齐飞书 .universal-card-video:有 src 时原生 <video controls>;无 src 时封面 + 播放钮。 */
707
+ .universal-card-video {
708
+ position: relative;
709
+ display: block;
710
+ width: 100%;
711
+ min-width: 96px;
712
+ min-height: 54px;
713
+ aspect-ratio: 16 / 9;
714
+ background-color: rgba(0, 0, 0, 0.8);
715
+ overflow: hidden;
716
+ cursor: default;
717
+ border-radius: 4px;
718
+ object-fit: contain;
719
+ box-sizing: border-box;
720
+ }
721
+ .universal-card-video__cover {
722
+ width: 100%;
723
+ height: 100%;
724
+ display: flex;
725
+ justify-content: center;
726
+ align-items: center;
727
+ }
728
+ .universal-card-video__host-image {
729
+ width: 100%;
730
+ height: 100%;
731
+ object-fit: cover;
732
+ display: block;
733
+ }
734
+ .universal-card-video__default-cover {
735
+ width: 100%;
736
+ height: 100%;
737
+ background: linear-gradient(135deg, #2b2f36 0%, #1f2329 100%);
738
+ }
739
+ .universal-card-video__play-btn {
740
+ position: absolute;
741
+ left: 50%;
742
+ top: 50%;
743
+ width: 40px;
744
+ height: 40px;
745
+ margin: -20px 0 0 -20px;
746
+ display: flex;
747
+ justify-content: center;
748
+ align-items: center;
749
+ color: #fff;
750
+ font-size: 18px;
751
+ border: 1px solid #fff;
752
+ border-radius: 50%;
753
+ background: rgba(0, 0, 0, 0.4);
754
+ box-sizing: border-box;
755
+ pointer-events: none;
756
+ }
757
+ .universal-card-video__duration {
758
+ position: absolute;
759
+ bottom: 6px;
760
+ right: 6px;
761
+ padding: 0 4px;
762
+ height: 16px;
763
+ display: flex;
764
+ justify-content: center;
765
+ align-items: center;
766
+ font-size: 10px;
767
+ color: #fff;
768
+ background-color: rgba(0, 0, 0, 0.55);
769
+ border: 1px solid rgba(255, 255, 255, 0.1);
770
+ border-radius: 4px;
771
+ user-select: none;
772
+ box-sizing: border-box;
773
+ }
774
+
775
+ /* ---- audio 音频 ---- */
776
+ /* 对齐飞书 .universal-card-audio__*:自定义播放条,非原生 controls。
777
+ * 顶层 audio = 块级圆角条;markdown_audio = --inline 胶囊(padding/圆角/扁平图标不同)。 */
778
+ .universal-card-audio__wrapper {
779
+ position: relative;
780
+ align-self: flex-start;
781
+ background: var(--universal-card-audio-bg, #f5f6f7);
782
+ cursor: pointer;
783
+ transition: background-color 0.3s ease;
784
+ border: 1px solid #dee0e3;
785
+ border-radius: 8px;
786
+ padding: 12px;
787
+ box-sizing: border-box;
788
+ max-width: 100%;
789
+ }
790
+ .universal-card-audio__wrapper--disabled {
791
+ background: #eff0f1;
792
+ cursor: default;
793
+ opacity: 0.7;
794
+ }
795
+ .universal-card-audio__wrapper:hover:not(.universal-card-audio__wrapper--disabled) {
796
+ background: var(--universal-card-audio-hover-bg, var(--universal-card-audio-bg, #eff0f1));
797
+ }
798
+ /* markdown 内嵌:行内容胶囊(真机 --inline) */
799
+ .universal-card-audio__wrapper--inline {
800
+ display: inline-flex;
801
+ margin: 0 3px;
802
+ padding: 4px 7px;
803
+ border-radius: 30px;
804
+ }
805
+ .universal-card-audio__native {
806
+ display: none;
807
+ }
808
+ .universal-card-audio__component {
809
+ max-width: 100%;
810
+ position: relative;
811
+ }
812
+ .universal-card-audio__control {
813
+ width: 100%;
814
+ display: flex;
815
+ align-items: center;
816
+ column-gap: 12px;
817
+ box-sizing: border-box;
818
+ user-select: none;
819
+ color: #8f959e;
820
+ }
821
+ .universal-card-audio__wrapper--inline .universal-card-audio__control {
822
+ position: relative;
823
+ column-gap: 0;
824
+ padding-left: calc(var(--universal-card-audio-icon-size, 0) + 2px);
825
+ height: var(--universal-card-audio-icon-size, 16px);
826
+ }
827
+ .universal-card-audio__ctrl {
828
+ flex-grow: 0;
829
+ flex-shrink: 0;
830
+ width: var(--universal-card-audio-icon-size, 20px);
831
+ height: var(--universal-card-audio-icon-size, 20px);
832
+ cursor: pointer;
833
+ display: inline-flex;
834
+ align-items: center;
835
+ justify-content: center;
836
+ color: var(--universal-card-audio-fill-color, #1f2329);
837
+ }
838
+ .universal-card-audio__wrapper--inline .universal-card-audio__ctrl {
839
+ position: absolute;
840
+ left: 0;
841
+ top: 50%;
842
+ transform: translateY(-50%);
843
+ }
844
+ .universal-card-audio__ctrl-icon {
845
+ font-size: var(--universal-card-audio-icon-size, 20px);
846
+ line-height: 1;
847
+ display: inline-flex;
848
+ color: inherit;
849
+ position: relative;
850
+ }
851
+ .universal-card-audio__wrapper--inline .universal-card-audio__ctrl-icon {
852
+ left: 8%;
853
+ transform: scale(0.85);
854
+ }
855
+ .universal-card-audio__icon {
856
+ display: inline-flex;
857
+ color: inherit;
858
+ }
859
+ .universal-card-audio__icon--pause { display: none; }
860
+ /* 播放中:隐藏播放钮、显示暂停钮(由 hydrate 给 wrapper 加 --playing) */
861
+ .universal-card-audio__wrapper--playing .universal-card-audio__icon--play { display: none; }
862
+ .universal-card-audio__wrapper--playing .universal-card-audio__icon--pause { display: inline-flex; }
863
+ .universal-card-audio__ctrl-icon svg,
864
+ .universal-card-audio__icon svg {
865
+ display: block;
866
+ width: 1em;
867
+ height: 1em;
868
+ }
869
+ .universal-card-audio__slider {
870
+ position: relative;
871
+ flex-grow: 1;
872
+ min-width: 32px;
873
+ height: 6px;
874
+ cursor: pointer;
875
+ }
876
+ .universal-card-audio__slider-bg {
877
+ position: absolute;
878
+ left: 0;
879
+ top: 50%;
880
+ height: 1px;
881
+ background-color: rgba(31, 35, 41, 0.3);
882
+ margin-top: -1px;
883
+ width: 100%;
884
+ }
885
+ .universal-card-audio__process {
886
+ background-color: var(--universal-card-audio-fill-color, #1f2329);
887
+ width: 0;
888
+ height: 100%;
889
+ left: 0;
890
+ }
891
+ .universal-card-audio__slider-strip {
892
+ position: absolute;
893
+ width: 16px;
894
+ height: 16px;
895
+ margin-top: -8px;
896
+ margin-left: -8px;
897
+ border-radius: 8px;
898
+ box-sizing: border-box;
899
+ background-color: #fff;
900
+ top: 50%;
901
+ left: 0;
902
+ cursor: pointer;
903
+ box-shadow: 0 0 8px 0 rgba(31, 35, 41, 0.16);
904
+ transform: scale(0.5);
905
+ transition: transform 0.3s ease;
906
+ }
907
+ .universal-card-audio__wrapper:hover:not(.universal-card-audio__wrapper--disabled) .universal-card-audio__slider-strip {
908
+ transform: scale(1);
909
+ }
910
+ .universal-card-audio__time {
911
+ color: var(--universal-card-audio-fill-color, #1f2329);
912
+ position: relative;
913
+ width: 38px;
914
+ flex-grow: 0;
915
+ flex-shrink: 0;
916
+ font-size: var(--universal-card-audio-time-font-size, 12px);
917
+ font-weight: 500;
918
+ text-align: center;
919
+ }
920
+ .universal-card-audio__wrapper--inline .universal-card-audio__time {
921
+ width: calc(var(--universal-card-audio-time-font-size, 12px) * 3);
922
+ }
923
+
924
+ /* ---- chart 图表 ---- */
925
+ /* 挂载容器:aspect-ratio / height 由内联 style 给(来自 aspect_ratio)。
926
+ VChart 水合后会往 __vchart 里塞 <canvas>;水合前显示 loading 占位。 */
927
+ .universal-card-chart {
928
+ position: relative;
929
+ width: 100%;
930
+ box-sizing: border-box;
931
+ overflow: hidden;
932
+ }
933
+ .universal-card-chart__vchart {
934
+ position: relative;
935
+ width: 100%;
936
+ height: 100%;
937
+ display: block;
938
+ }
939
+ .universal-card-chart__vchart canvas { display: block; }
940
+ .universal-card-chart__loading,
941
+ .universal-card-chart__placeholder {
942
+ display: flex; align-items: center; justify-content: center;
943
+ width: 100%; height: 100%;
944
+ color: #8f959e; font-size: 12px;
945
+ background: #f5f6f7; border: 1px dashed #dee0e3; border-radius: 4px;
946
+ box-sizing: border-box;
947
+ }
948
+
949
+ /* ---- table 表格 ---- */
950
+ .universal-card-table {
951
+ width: 100%;
952
+ box-sizing: border-box;
953
+ border: 1px solid #dee0e3;
954
+ border-radius: 6px;
955
+ overflow: hidden;
956
+ }
957
+ .universal-card-table__scroll { width: 100%; overflow-x: auto; }
958
+ .universal-card-table__table {
959
+ width: 100%;
960
+ border-collapse: collapse;
961
+ table-layout: auto;
962
+ font-size: 14px;
963
+ color: #1f2329;
964
+ }
965
+ .universal-card-table__th,
966
+ .universal-card-table__td {
967
+ padding: 8px 12px;
968
+ border-bottom: 1px solid #dee0e3;
969
+ border-right: 1px solid #eff0f1;
970
+ vertical-align: middle;
971
+ box-sizing: border-box;
972
+ }
973
+ .universal-card-table__th:last-child,
974
+ .universal-card-table__td:last-child { border-right: none; }
975
+ .universal-card-table__tbody tr:last-child .universal-card-table__td { border-bottom: none; }
976
+ .universal-card-table__th {
977
+ font-size: 14px;
978
+ line-height: 22px;
979
+ white-space: nowrap;
980
+ color: #1f2329;
981
+ }
982
+ .universal-card-table__th-text--bold { font-weight: 600; }
983
+ .universal-card-table__cell {
984
+ display: flex;
985
+ align-items: center;
986
+ gap: 4px;
987
+ word-break: break-word;
988
+ }
989
+ .universal-card-table__tags { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; }
990
+
991
+ /* 暗色主题下的表格/图表占位 */
992
+ .universal-card-root.theme-dark .universal-card-table { border-color: #2e2e30; }
993
+ .universal-card-root.theme-dark .universal-card-table__th,
994
+ .universal-card-root.theme-dark .universal-card-table__td { border-color: #2e2e30; color: #d6d6d6; }
995
+ .universal-card-root.theme-dark .universal-card-table__th { color: #ebebeb; }
996
+ .universal-card-root.theme-dark .universal-card-chart__loading,
997
+ .universal-card-root.theme-dark .universal-card-chart__placeholder {
998
+ background: #232323; border-color: #2e2e30; color: #8a8a8a;
999
+ }
1000
+
1001
+ /* ---- 暗色主题(可选):给 .universal-card-root 加 .theme-dark 即可 ----
1002
+ 暗色高光图同样由 JS 注入;如需纯 CSS 暗色,可自行覆盖 background-image。 */
1003
+ .universal-card-root.theme-dark {
1004
+ color: #ebebeb;
1005
+ background-color: #1a1a1a;
1006
+ border-color: #2e2e30;
1007
+ }
1008
+ .universal-card-root.theme-dark .universal-card-markdown { color: #d6d6d6; }
1009
+ .universal-card-root.theme-dark .universal-card-hr { background-color: #2e2e30; }
1010
+ .universal-card-root.theme-dark .universal-card-note { color: #8a8a8a; }