@taskon/widget-react 0.0.1 → 0.0.2

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.
Files changed (66) hide show
  1. package/README.md +118 -64
  2. package/dist/CommunityTaskList.css +2694 -2951
  3. package/dist/EligibilityInfo.css +2221 -1332
  4. package/dist/LeaderboardWidget.css +403 -198
  5. package/dist/PageBuilder.css +57 -0
  6. package/dist/Quest.css +1347 -1477
  7. package/dist/TaskOnProvider.css +337 -29
  8. package/dist/ThemeProvider.css +228 -0
  9. package/dist/UserCenterWidget.css +168 -0
  10. package/dist/UserCenterWidget2.css +4917 -0
  11. package/dist/WidgetShell.css +417 -130
  12. package/dist/chunks/{CommunityTaskList-CrH6r4Av.js → CommunityTaskList-2nFy6l6m.js} +2612 -2074
  13. package/dist/chunks/{EligibilityInfo-DesW9-k9.js → EligibilityInfo-CKTl_cdU.js} +2714 -4077
  14. package/dist/chunks/{LeaderboardWidget-BSGpHKTk.js → LeaderboardWidget-DyoiiNS6.js} +288 -349
  15. package/dist/chunks/PageBuilder-DHM3Il6f.js +150 -0
  16. package/dist/chunks/{Quest-uSIVq78I.js → Quest-Dqx4OCat.js} +1380 -726
  17. package/dist/chunks/TaskOnProvider-CxtFIs3n.js +2072 -0
  18. package/dist/chunks/{WidgetShell-NlOgn1x5.js → ThemeProvider-CulHkqqY.js} +1397 -103
  19. package/dist/chunks/UserCenterWidget-SE5hqpnZ.js +8335 -0
  20. package/dist/chunks/UserCenterWidget-XL6LZRZM.js +3259 -0
  21. package/dist/chunks/{Table-CWGf2FKV.js → WidgetShell-8xn-Jivw.js} +237 -27
  22. package/dist/chunks/communitytask-es-CBNnS4o2.js +521 -0
  23. package/dist/chunks/communitytask-ja-GRf9cbdx.js +521 -0
  24. package/dist/chunks/communitytask-ko-Bf24PQKI.js +521 -0
  25. package/dist/chunks/communitytask-ru-CZm2CPoV.js +521 -0
  26. package/dist/chunks/leaderboardwidget-es-vKjrjQaz.js +146 -0
  27. package/dist/chunks/leaderboardwidget-ja-Q6u0HxKG.js +146 -0
  28. package/dist/chunks/leaderboardwidget-ko-CG6SWgxf.js +146 -0
  29. package/dist/chunks/leaderboardwidget-ru-DCcHcJGz.js +146 -0
  30. package/dist/chunks/quest-es-Dyyy0zaw.js +863 -0
  31. package/dist/chunks/quest-ja-Depog33y.js +863 -0
  32. package/dist/chunks/quest-ko-BMu3uRQJ.js +863 -0
  33. package/dist/chunks/quest-ru-xne814Rw.js +863 -0
  34. package/dist/chunks/taskwidget-es-Do9b3Mqw.js +245 -0
  35. package/dist/chunks/taskwidget-ja-CqSu-yWA.js +245 -0
  36. package/dist/chunks/taskwidget-ko-EHgXFV4B.js +245 -0
  37. package/dist/chunks/taskwidget-ru-CMbLQDK4.js +245 -0
  38. package/dist/chunks/useIsMobile-D6Ybur-6.js +30 -0
  39. package/dist/chunks/usercenter-es-Dz3Wp2vV.js +512 -0
  40. package/dist/chunks/usercenter-ja-CKE4DJC6.js +512 -0
  41. package/dist/chunks/usercenter-ko-Dtpkn2qb.js +512 -0
  42. package/dist/chunks/usercenter-ru-DnBGee45.js +512 -0
  43. package/dist/community-task.d.ts +29 -388
  44. package/dist/community-task.js +2 -7
  45. package/dist/core.d.ts +95 -28
  46. package/dist/core.js +11 -12
  47. package/dist/index.d.ts +260 -602
  48. package/dist/index.js +28 -7361
  49. package/dist/leaderboard.d.ts +5 -496
  50. package/dist/leaderboard.js +2 -15
  51. package/dist/page-builder.d.ts +20 -0
  52. package/dist/page-builder.js +4 -0
  53. package/dist/quest.d.ts +20 -292
  54. package/dist/quest.js +2 -5
  55. package/dist/user-center.d.ts +56 -0
  56. package/dist/user-center.js +4 -0
  57. package/package.json +22 -3
  58. package/dist/Table.css +0 -389
  59. package/dist/chunks/TaskOnProvider-QMwxGL44.js +0 -1435
  60. package/dist/chunks/ThemeProvider-Cs8IUVQj.js +0 -1118
  61. package/dist/chunks/leaderboardwidget-ja-Bj6gz6y1.js +0 -119
  62. package/dist/chunks/leaderboardwidget-ko-f1cLO9ic.js +0 -119
  63. package/dist/chunks/useWidgetLocale-BVcopbZS.js +0 -74
  64. package/dist/chunks/usercenter-ja-DBj_dtuz.js +0 -329
  65. package/dist/chunks/usercenter-ko-DYTkHAld.js +0 -329
  66. package/dist/index.css +0 -3662
@@ -5,21 +5,23 @@
5
5
  */
6
6
 
7
7
  /* ==================== 容器 ==================== */
8
+
8
9
  .taskon-textarea-wrap {
9
10
  position: relative;
10
11
  font-size: 0;
11
12
  }
12
13
 
13
14
  /* ==================== 文本域 ==================== */
15
+
14
16
  .taskon-textarea {
15
17
  width: 100%;
16
18
  min-height: 100px;
17
19
  padding: 12px;
18
20
  padding-bottom: 36px; /* 给计数器留空间 */
19
21
  border-radius: 6px;
20
- border: 1px solid rgba(255, 255, 255, 0.1);
21
- background: rgba(255, 255, 255, 0.04);
22
- color: var(--taskon-color-text, #fff);
22
+ border: 1px solid var(--taskon-color-border);
23
+ background: var(--taskon-color-bg-surface-subtle);
24
+ color: var(--taskon-color-text);
23
25
  font-size: 14px;
24
26
  line-height: 1.5;
25
27
  resize: none;
@@ -28,7 +30,7 @@
28
30
  }
29
31
 
30
32
  .taskon-textarea:focus {
31
- border-color: var(--taskon-color-primary, #cbff01);
33
+ border-color: var(--taskon-color-primary);
32
34
  }
33
35
 
34
36
  .taskon-textarea:disabled {
@@ -37,14 +39,15 @@
37
39
  }
38
40
 
39
41
  .taskon-textarea--error {
40
- border-color: #eb5757;
42
+ border-color: var(--taskon-color-error);
41
43
  }
42
44
 
43
45
  .taskon-textarea::placeholder {
44
- color: var(--taskon-color-text-tertiary, #666);
46
+ color: var(--taskon-color-text-tertiary);
45
47
  }
46
48
 
47
49
  /* ==================== 字数统计 ==================== */
50
+
48
51
  .taskon-textarea-count {
49
52
  position: absolute;
50
53
  right: 20px;
@@ -52,28 +55,11 @@
52
55
  font-weight: 400;
53
56
  font-size: 14px;
54
57
  line-height: 20px;
55
- color: rgba(255, 255, 255, 0.6);
58
+ color: var(--taskon-color-text-tertiary);
56
59
  }
57
60
 
58
61
  .taskon-textarea-count-current {
59
- color: #fff;
60
- }
61
-
62
- /* ==================== 响应式 ==================== */
63
- @media (max-width: 750px) {
64
- .taskon-textarea {
65
- min-height: 26.667vw;
66
- padding: 3.2vw;
67
- padding-bottom: 8vw; /* 给计数器留空间 */
68
- font-size: 3.733vw;
69
- }
70
-
71
- .taskon-textarea-count {
72
- right: 2.933vw;
73
- bottom: 2.667vw;
74
- font-size: 2.933vw;
75
- line-height: 2.667vw;
76
- }
62
+ color: var(--taskon-color-text);
77
63
  }
78
64
  /**
79
65
  * TitleExpress 组件样式
@@ -81,9 +67,10 @@
81
67
  */
82
68
 
83
69
  /* 可点击链接 - 统一蓝色加下划线样式 */
70
+
84
71
  .taskon-title-express-link {
85
72
  display: inline;
86
- color: #54aeff;
73
+ color: var(--taskon-color-link);
87
74
  cursor: pointer;
88
75
  text-decoration: underline;
89
76
  transition: opacity 0.2s ease;
@@ -94,29 +81,31 @@
94
81
  }
95
82
 
96
83
  /* 可复制文本 */
84
+
97
85
  .taskon-title-express-copy {
98
86
  display: inline;
99
- color: var(--taskon-color-secondary, #cbff01);
87
+ color: var(--taskon-color-secondary);
100
88
  cursor: pointer;
101
89
  }
102
90
 
103
91
  /* Radix Popover 内容 */
92
+
104
93
  .taskon-title-express-popover-content {
105
94
  display: flex;
106
95
  align-items: center;
107
96
  justify-content: center;
108
97
  gap: 6px;
109
98
  padding: 8px 12px;
110
- background: var(--taskon-color-bg-popover, #2a2a2a);
111
- border-radius: 8px;
99
+ background: var(--taskon-color-bg-floating);
100
+ border-radius: var(--taskon-border-radius-sm);
112
101
  border: none;
113
102
  outline: none;
114
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
103
+ box-shadow: 0 4px 12px var(--taskon-color-bg-mask);
115
104
  cursor: pointer;
116
105
  font-size: 14px;
117
106
  font-weight: 500;
118
107
  line-height: 18px;
119
- color: var(--taskon-color-text, #fff);
108
+ color: var(--taskon-color-text);
120
109
  z-index: 9999;
121
110
  animation: taskon-popover-fade-in 0.15s ease;
122
111
  }
@@ -126,10 +115,11 @@
126
115
  }
127
116
 
128
117
  .taskon-title-express-popover-content:hover {
129
- background: var(--taskon-color-bg-popover-hover, #3a3a3a);
118
+ background: var(--taskon-color-bg-surface);
130
119
  }
131
120
 
132
121
  /* 复制图标 */
122
+
133
123
  .taskon-title-express-copy-icon {
134
124
  width: 14px;
135
125
  height: 14px;
@@ -137,11 +127,13 @@
137
127
  }
138
128
 
139
129
  /* Radix Popover 箭头 */
130
+
140
131
  .taskon-title-express-popover-arrow {
141
- fill: var(--taskon-color-bg-popover, #2a2a2a);
132
+ fill: var(--taskon-color-bg-floating);
142
133
  }
143
134
 
144
135
  /* 动画 */
136
+
145
137
  @keyframes taskon-popover-fade-in {
146
138
  from {
147
139
  opacity: 0;
@@ -152,1815 +144,2712 @@
152
144
  transform: translateY(0);
153
145
  }
154
146
  }
147
+ /**
148
+ * CardDescExpress 组件样式
149
+ * @module components/CardDescExpress
150
+ *
151
+ * @description
152
+ * 对齐原版 TextPreview + Quill 富文本渲染思路:
153
+ * - 容器层控制截断与基础排版
154
+ * - 内容层按 Quill 语义处理列表/缩进/对齐
155
+ */
155
156
 
156
- /* 响应式样式(移动端) */
157
- @media (max-width: 750px) {
158
- .taskon-title-express-popover-content {
159
- padding: 2.13vw 3.2vw;
160
- font-size: 3.73vw;
161
- line-height: 4.8vw;
162
- border-radius: 2.13vw;
163
- gap: 1.6vw;
164
- }
157
+ .taskon-card-desc-rich {
158
+ max-height: 60px;
159
+ overflow: hidden;
160
+ font-size: 14px;
161
+ line-height: 21px;
162
+ color: var(--taskon-color-text-tertiary);
163
+ white-space: pre-wrap;
164
+ overflow-wrap: break-word;
165
+ word-break: break-word;
166
+ }
165
167
 
166
- .taskon-title-express-copy-icon {
167
- width: 3.73vw;
168
- height: 3.73vw;
169
- }
168
+ .taskon-card-desc-rich--no-max-height {
169
+ margin-top: 0;
170
+ max-height: none;
171
+ overflow: visible;
170
172
  }
171
- /**
172
- * TipPopover 组件样式
173
- * 设计原则:组件内部不包含 margin,需要间距由外部控制
174
- */
175
173
 
176
- .taskon-tip-popover-trigger {
177
- display: inline-flex;
178
- align-items: center;
179
- justify-content: center;
174
+ /* ========== 基础防护(降低宿主 reset 影响) ========== */
175
+
176
+ .taskon-card-desc-rich,
177
+ .taskon-card-desc-rich *,
178
+ .taskon-card-desc-rich *::before,
179
+ .taskon-card-desc-rich *::after {
180
+ box-sizing: border-box;
181
+ }
182
+
183
+ /* ========== 基础块元素(对齐 Quill 编辑器语义) ========== */
184
+
185
+ .taskon-card-desc-rich p,
186
+ .taskon-card-desc-rich ol,
187
+ .taskon-card-desc-rich ul,
188
+ .taskon-card-desc-rich pre,
189
+ .taskon-card-desc-rich blockquote,
190
+ .taskon-card-desc-rich h1,
191
+ .taskon-card-desc-rich h2,
192
+ .taskon-card-desc-rich h3,
193
+ .taskon-card-desc-rich h4,
194
+ .taskon-card-desc-rich h5,
195
+ .taskon-card-desc-rich h6 {
196
+ display: block;
197
+ margin: 0;
180
198
  padding: 0;
181
- border: none;
182
- background: transparent;
183
- cursor: pointer;
184
- color: var(--taskon-text-tertiary, rgba(255, 255, 255, 0.4));
185
- outline: none;
199
+ counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
186
200
  }
187
201
 
188
- .taskon-tip-popover-trigger:hover,
189
- .taskon-tip-popover-trigger:focus {
190
- color: var(--taskon-text-tertiary, rgba(255, 255, 255, 0.4));
191
- background: transparent;
192
- outline: none;
202
+ .taskon-card-desc-rich h1 {
203
+ font-size: 2rem;
204
+ line-height: 33px;
205
+ font-weight: 700;
206
+ color: var(--taskon-color-text);
193
207
  }
194
208
 
195
- /* Custom children trigger - reset button styles */
196
- .taskon-tip-popover-trigger--custom {
197
- cursor: pointer;
209
+ .taskon-card-desc-rich h2 {
210
+ font-size: 1.5em;
198
211
  }
199
212
 
200
- .taskon-tip-popover-content {
201
- max-width: 266px;
202
- padding: 12px 16px;
203
- border-radius: 8px;
204
- border: none;
205
- outline: none;
206
- background: var(--taskon-bg-elevated, #2a2a2a);
207
- color: var(--taskon-text-primary, #fff);
208
- font-size: 13px;
209
- line-height: 1.5;
210
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
211
- /* z-index 需要大于 Dialog (9999) 才能在弹窗中正常显示 */
212
- z-index: 10000;
213
- animation: taskon-tip-popover-fade-in 0.15s ease;
213
+ .taskon-card-desc-rich h3 {
214
+ font-size: 1.17em;
214
215
  }
215
216
 
216
- .taskon-tip-popover-content:focus {
217
- outline: none;
217
+ .taskon-card-desc-rich h4 {
218
+ font-size: 1em;
218
219
  }
219
220
 
220
- .taskon-tip-popover-arrow {
221
- fill: var(--taskon-bg-elevated, #2a2a2a);
221
+ .taskon-card-desc-rich h5 {
222
+ font-size: 0.83em;
222
223
  }
223
224
 
224
- @keyframes taskon-tip-popover-fade-in {
225
- from {
226
- opacity: 0;
227
- transform: scale(0.96);
228
- }
229
- to {
230
- opacity: 1;
231
- transform: scale(1);
232
- }
225
+ .taskon-card-desc-rich h6 {
226
+ font-size: 0.67em;
233
227
  }
234
228
 
235
- /* Mobile styles */
236
- @media (max-width: 750px) {
237
- .taskon-tip-popover-content {
238
- max-width: 60vw;
239
- padding: 2.5vw 3.5vw;
240
- font-size: 3vw;
241
- }
229
+ /* ========== 列表(核心:确保圆点/编号稳定可见) ========== */
230
+
231
+ .taskon-card-desc-rich ol,
232
+ .taskon-card-desc-rich ul {
233
+ margin: 0.5em 0;
234
+ padding-left: 1.5em;
242
235
  }
243
- /**
244
- * PowTask Styles
245
- * @description POW 任务样式
246
- * 遵循 Widget 命名规范:.taskon-{widget-name}-{element}
247
- */
248
236
 
249
- /* ============================================
250
- * POW Task Container
251
- * ============================================ */
252
- .taskon-pow-task {
253
- /* 继承 TaskCardBase 的样式 */
237
+ .taskon-card-desc-rich ol > li,
238
+ .taskon-card-desc-rich ul > li {
239
+ list-style-type: none;
254
240
  }
255
241
 
256
- /* ============================================
257
- * POW Description
258
- * ============================================ */
259
- .taskon-pow-desc {
260
- font-size: 14px;
261
- line-height: 21px;
262
- color: rgba(255, 255, 255, 0.8);
263
- word-break: break-word;
242
+ .taskon-card-desc-rich li {
243
+ display: list-item;
264
244
  }
265
245
 
266
- .taskon-pow-desc a {
267
- color: var(--taskon-primary-color, #3b82f6);
268
- text-decoration: none;
246
+ .taskon-card-desc-rich ul > li::before {
247
+ content: "\2022";
269
248
  }
270
249
 
271
- .taskon-pow-desc a:hover {
272
- text-decoration: underline;
250
+ .taskon-card-desc-rich ul[data-checked="true"],
251
+ .taskon-card-desc-rich ul[data-checked="false"] {
252
+ pointer-events: none;
273
253
  }
274
254
 
275
- /* ============================================
276
- * POW Input Area
277
- * ============================================ */
278
- .taskon-pow-input-area {
279
- margin-top: 15px;
255
+ .taskon-card-desc-rich ul[data-checked="true"] > li *,
256
+ .taskon-card-desc-rich ul[data-checked="false"] > li * {
257
+ pointer-events: all;
280
258
  }
281
259
 
282
- /* ============================================
283
- * URL Input Row
284
- * ============================================ */
285
- .taskon-pow-url-row {
286
- display: flex;
287
- align-items: center;
288
- gap: 15px;
260
+ .taskon-card-desc-rich ul[data-checked="true"] > li::before,
261
+ .taskon-card-desc-rich ul[data-checked="false"] > li::before {
262
+ cursor: pointer;
263
+ pointer-events: all;
289
264
  }
290
265
 
291
- .taskon-pow-input {
292
- flex: 1;
293
- padding: 10px 12px;
294
- border: 1px solid rgba(255, 255, 255, 0.2);
295
- border-radius: 6px;
296
- background: rgba(255, 255, 255, 0.05);
297
- color: #fff;
298
- font-size: 14px;
299
- outline: none;
300
- transition: border-color 0.2s ease;
266
+ .taskon-card-desc-rich ul[data-checked="true"] > li::before {
267
+ content: "\2611";
301
268
  }
302
269
 
303
- .taskon-pow-input:focus {
304
- border-color: var(--taskon-primary-color, #3b82f6);
270
+ .taskon-card-desc-rich ul[data-checked="false"] > li::before {
271
+ content: "\2610";
305
272
  }
306
273
 
307
- .taskon-pow-input:disabled {
308
- opacity: 0.5;
309
- cursor: not-allowed;
274
+ .taskon-card-desc-rich li::before {
275
+ display: inline-block;
276
+ width: 1.2em;
277
+ white-space: nowrap;
310
278
  }
311
279
 
312
- .taskon-pow-input::placeholder {
313
- color: rgba(255, 255, 255, 0.4);
280
+ .taskon-card-desc-rich li:not(.ql-direction-rtl)::before {
281
+ margin-right: 0.3em;
282
+ margin-left: -1.5em;
283
+ text-align: right;
314
284
  }
315
285
 
316
- /* ============================================
317
- * Text Input Row
318
- * ============================================ */
319
- .taskon-pow-text-row {
320
- display: flex;
321
- align-items: flex-end;
322
- gap: 15px;
286
+ .taskon-card-desc-rich li.ql-direction-rtl::before {
287
+ margin-right: -1.5em;
288
+ margin-left: 0.3em;
323
289
  }
324
290
 
325
- .taskon-pow-text-row .taskon-textarea-wrap {
326
- flex: 1;
291
+ .taskon-card-desc-rich ol li:not(.ql-direction-rtl),
292
+ .taskon-card-desc-rich ul li:not(.ql-direction-rtl) {
293
+ padding-left: 1.5em;
327
294
  }
328
295
 
329
- /* ============================================
330
- * Image Upload Area - 与 Vue 版本 PowImageUploader 一致
331
- * ============================================ */
332
- .taskon-pow-image-uploader {
333
- margin-top: 20px;
334
- display: flex;
335
- align-items: center;
296
+ .taskon-card-desc-rich ol li.ql-direction-rtl,
297
+ .taskon-card-desc-rich ul li.ql-direction-rtl {
298
+ padding-right: 1.5em;
336
299
  }
337
300
 
338
- .taskon-pow-image-upload-area {
339
- flex: 1;
340
- position: relative;
341
- display: flex;
342
- flex-direction: column;
343
- align-items: center;
344
- justify-content: center;
345
- min-height: 128px;
346
- text-align: center;
347
- font-size: 0;
348
- overflow: hidden;
349
- border: 1px solid rgba(255, 255, 255, 0.2);
350
- border-radius: 8px;
351
- background: rgba(255, 255, 255, 0.05);
352
- cursor: pointer;
353
- transition: border-color 0.2s ease;
301
+ .taskon-card-desc-rich ol li {
302
+ counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
303
+ counter-increment: list-0;
354
304
  }
355
305
 
356
- .taskon-pow-image-upload-area:hover:not(.taskon-pow-image-upload-area--disabled) {
357
- border-color: var(--taskon-primary-color, #3b82f6);
306
+ .taskon-card-desc-rich ol li::before {
307
+ content: counter(list-0, decimal) ". ";
358
308
  }
359
309
 
360
- .taskon-pow-image-upload-area:focus {
361
- outline: none;
362
- border-color: var(--taskon-primary-color, #3b82f6);
310
+ .taskon-card-desc-rich ol li.ql-indent-1 {
311
+ counter-increment: list-1;
312
+ counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
363
313
  }
364
314
 
365
- .taskon-pow-image-upload-area--disabled {
366
- opacity: 0.5;
367
- cursor: not-allowed;
315
+ .taskon-card-desc-rich ol li.ql-indent-1::before {
316
+ content: counter(list-1, lower-alpha) ". ";
368
317
  }
369
318
 
370
- .taskon-pow-image-upload-icon {
371
- width: 18px;
372
- height: 18px;
373
- color: rgba(255, 255, 255, 0.6);
319
+ .taskon-card-desc-rich ol li.ql-indent-2 {
320
+ counter-increment: list-2;
321
+ counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
374
322
  }
375
323
 
376
- .taskon-pow-image-upload-tip {
377
- margin-top: 13px;
378
- font-size: 14px;
379
- line-height: 20px;
380
- letter-spacing: 0.04em;
381
- text-transform: uppercase;
382
- white-space: pre-wrap;
383
- color: rgba(255, 255, 255, 0.6);
324
+ .taskon-card-desc-rich ol li.ql-indent-2::before {
325
+ content: counter(list-2, lower-roman) ". ";
384
326
  }
385
327
 
386
- .taskon-pow-image-preview {
387
- border-radius: 4px;
388
- margin: 20px 0;
389
- max-width: 100%;
390
- max-height: 300px;
328
+ .taskon-card-desc-rich ol li.ql-indent-3 {
329
+ counter-increment: list-3;
330
+ counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
391
331
  }
392
332
 
393
- /* Hover mask overlay */
394
- .taskon-pow-image-mask {
395
- display: none;
396
- position: absolute;
397
- inset: 0;
398
- z-index: 2;
399
- align-items: center;
400
- justify-content: center;
401
- flex-direction: column;
402
- background: rgba(0, 0, 0, 0.8);
333
+ .taskon-card-desc-rich ol li.ql-indent-3::before {
334
+ content: counter(list-3, decimal) ". ";
403
335
  }
404
336
 
405
- .taskon-pow-image-upload-area:hover .taskon-pow-image-mask,
406
- .taskon-pow-image-upload-area:focus .taskon-pow-image-mask {
407
- display: flex;
337
+ .taskon-card-desc-rich ol li.ql-indent-4 {
338
+ counter-increment: list-4;
339
+ counter-reset: list-5 list-6 list-7 list-8 list-9;
408
340
  }
409
341
 
410
- .taskon-pow-image-mask .taskon-pow-image-upload-icon {
411
- color: #fff;
342
+ .taskon-card-desc-rich ol li.ql-indent-4::before {
343
+ content: counter(list-4, lower-alpha) ". ";
412
344
  }
413
345
 
414
- .taskon-pow-image-mask .taskon-pow-image-upload-tip {
415
- color: #fff;
416
- opacity: 1;
346
+ .taskon-card-desc-rich ol li.ql-indent-5 {
347
+ counter-increment: list-5;
348
+ counter-reset: list-6 list-7 list-8 list-9;
417
349
  }
418
350
 
419
- /* Progress bar at bottom */
420
- .taskon-pow-image-progress-bar {
421
- z-index: 3;
422
- position: absolute;
423
- right: 0;
424
- bottom: 0;
425
- left: 0;
426
- background: rgba(255, 255, 255, 0.1);
427
- height: 6px;
351
+ .taskon-card-desc-rich ol li.ql-indent-5::before {
352
+ content: counter(list-5, lower-roman) ". ";
428
353
  }
429
354
 
430
- .taskon-pow-image-progress-fill {
431
- background: var(--taskon-primary-color, #3b82f6);
432
- height: 100%;
433
- border-radius: 4px;
434
- transition: width 0.2s ease;
355
+ .taskon-card-desc-rich ol li.ql-indent-6 {
356
+ counter-increment: list-6;
357
+ counter-reset: list-7 list-8 list-9;
435
358
  }
436
359
 
437
- /* ============================================
438
- * Error Message
439
- * ============================================ */
440
- .taskon-pow-error {
441
- margin-top: 10px;
442
- font-size: 14px;
443
- color: #ef4444;
360
+ .taskon-card-desc-rich ol li.ql-indent-6::before {
361
+ content: counter(list-6, decimal) ". ";
444
362
  }
445
363
 
446
- /* ============================================
447
- * Average Review Time
448
- * ============================================ */
449
- /* 与 Vue 版本 AverageReview.vue 样式一致 */
450
- .taskon-pow-review-time {
451
- margin-top: 10px;
452
- color: rgba(255, 212, 101, 0.6);
453
- font-size: 13px;
454
- font-weight: 500;
455
- line-height: 16px;
364
+ .taskon-card-desc-rich ol li.ql-indent-7 {
365
+ counter-increment: list-7;
366
+ counter-reset: list-8 list-9;
456
367
  }
457
368
 
458
- /* ============================================
459
- * Responsive Styles
460
- * ============================================ */
461
- @media (max-width: 750px) {
462
- .taskon-pow-url-row,
463
- .taskon-pow-text-row {
464
- flex-direction: column;
465
- gap: 10px;
466
- }
369
+ .taskon-card-desc-rich ol li.ql-indent-7::before {
370
+ content: counter(list-7, lower-alpha) ". ";
371
+ }
467
372
 
468
- .taskon-pow-input {
469
- width: 100%;
470
- }
373
+ .taskon-card-desc-rich ol li.ql-indent-8 {
374
+ counter-increment: list-8;
375
+ counter-reset: list-9;
376
+ }
471
377
 
472
- .taskon-pow-url-row .taskon-verify-btn,
473
- .taskon-pow-text-row .taskon-verify-btn {
474
- width: 100%;
475
- }
378
+ .taskon-card-desc-rich ol li.ql-indent-8::before {
379
+ content: counter(list-8, lower-roman) ". ";
380
+ }
476
381
 
477
- .taskon-pow-image-uploader {
478
- margin-top: 2.67vw;
479
- }
382
+ .taskon-card-desc-rich ol li.ql-indent-9 {
383
+ counter-increment: list-9;
384
+ }
480
385
 
481
- .taskon-pow-image-upload-area {
482
- min-height: 17.07vw;
483
- }
386
+ .taskon-card-desc-rich ol li.ql-indent-9::before {
387
+ content: counter(list-9, decimal) ". ";
388
+ }
484
389
 
485
- .taskon-pow-image-upload-icon {
486
- width: 2.4vw;
487
- height: 2.4vw;
488
- }
390
+ /* ========== 缩进与对齐(对齐 Quill class 语义) ========== */
489
391
 
490
- .taskon-pow-image-upload-tip {
491
- margin-top: 1.33vw;
492
- font-size: 1.6vw;
493
- line-height: 2.67vw;
494
- }
392
+ .taskon-card-desc-rich .ql-indent-1:not(.ql-direction-rtl) {
393
+ padding-left: 3em;
394
+ }
495
395
 
496
- .taskon-pow-image-preview {
497
- max-height: 32vw;
498
- }
396
+ .taskon-card-desc-rich li.ql-indent-1:not(.ql-direction-rtl) {
397
+ padding-left: 4.5em;
499
398
  }
500
- /**
501
- * ContractInteractiveTask Styles
502
- */
503
399
 
504
- .taskon-contract-task {
505
- /* 继承 TaskCardBase 样式 */
400
+ .taskon-card-desc-rich .ql-indent-1.ql-direction-rtl.ql-align-right {
401
+ padding-right: 3em;
506
402
  }
507
403
 
508
- .taskon-contract-desc {
509
- font-size: 14px;
510
- line-height: 21px;
511
- color: rgba(255, 255, 255, 0.8);
512
- word-break: break-word;
404
+ .taskon-card-desc-rich li.ql-indent-1.ql-direction-rtl.ql-align-right {
405
+ padding-right: 4.5em;
513
406
  }
514
407
 
515
- .taskon-contract-desc a {
516
- color: var(--taskon-primary-color, #3b82f6);
517
- text-decoration: none;
408
+ .taskon-card-desc-rich .ql-indent-2:not(.ql-direction-rtl) {
409
+ padding-left: 6em;
518
410
  }
519
411
 
520
- .taskon-contract-desc a:hover {
521
- text-decoration: underline;
412
+ .taskon-card-desc-rich li.ql-indent-2:not(.ql-direction-rtl) {
413
+ padding-left: 7.5em;
522
414
  }
523
- /* ============================================
524
- DynamicPoints Component Styles
525
- 与 Vue 版本 BaseDynamicPoint.vue 样式一致
526
- ============================================ */
527
415
 
528
- .taskon-dynamic-points {
529
- display: inline-flex;
530
- align-items: center;
531
- gap: 8px;
532
- padding: 8px 12px;
533
- background: rgba(255, 255, 255, 0.04);
534
- border-radius: 8px;
416
+ .taskon-card-desc-rich .ql-indent-2.ql-direction-rtl.ql-align-right {
417
+ padding-right: 6em;
535
418
  }
536
419
 
537
- .taskon-dynamic-points-value-wrap {
538
- display: flex;
539
- align-items: center;
540
- gap: 8px;
541
- flex-shrink: 0;
420
+ .taskon-card-desc-rich li.ql-indent-2.ql-direction-rtl.ql-align-right {
421
+ padding-right: 7.5em;
542
422
  }
543
423
 
544
- .taskon-dynamic-points-value {
545
- font-size: 16px;
546
- font-weight: 600;
547
- color: var(--taskon-task-text-primary, #fff);
424
+ .taskon-card-desc-rich .ql-indent-3:not(.ql-direction-rtl) {
425
+ padding-left: 9em;
548
426
  }
549
427
 
550
- .taskon-dynamic-points-value--highlight {
551
- color: #00ffa3 !important;
428
+ .taskon-card-desc-rich li.ql-indent-3:not(.ql-direction-rtl) {
429
+ padding-left: 10.5em;
552
430
  }
553
431
 
554
- .taskon-dynamic-points-max {
555
- font-size: 14px;
556
- font-weight: 500;
557
- color: var(--taskon-task-text-secondary, rgba(255, 255, 255, 0.6));
558
- text-transform: capitalize;
432
+ .taskon-card-desc-rich .ql-indent-3.ql-direction-rtl.ql-align-right {
433
+ padding-right: 9em;
559
434
  }
560
435
 
561
- .taskon-dynamic-points-info {
562
- display: inline-flex;
563
- align-items: center;
564
- justify-content: center;
565
- color: var(--taskon-task-text-secondary, rgba(255, 255, 255, 0.6));
566
- cursor: pointer;
436
+ .taskon-card-desc-rich li.ql-indent-3.ql-direction-rtl.ql-align-right {
437
+ padding-right: 10.5em;
567
438
  }
568
439
 
569
- .taskon-dynamic-points-info:hover {
570
- color: var(--taskon-task-text-primary, #fff);
440
+ .taskon-card-desc-rich .ql-indent-4:not(.ql-direction-rtl) {
441
+ padding-left: 12em;
571
442
  }
572
443
 
573
- .taskon-dynamic-points-refresh {
574
- display: inline-flex;
575
- align-items: center;
576
- justify-content: center;
577
- width: 24px;
578
- height: 24px;
579
- padding: 0;
580
- margin-left: 4px;
581
- background: transparent;
582
- border: none;
583
- border-radius: 4px;
584
- color: #54aeff;
585
- cursor: pointer;
586
- transition: opacity 0.2s, transform 0.2s;
587
- }
588
-
589
- .taskon-dynamic-points-refresh:hover:not(:disabled) {
590
- opacity: 0.8;
591
- }
592
-
593
- .taskon-dynamic-points-refresh--disabled {
594
- opacity: 0.6;
595
- cursor: not-allowed;
444
+ .taskon-card-desc-rich li.ql-indent-4:not(.ql-direction-rtl) {
445
+ padding-left: 13.5em;
596
446
  }
597
447
 
598
- .taskon-dynamic-points-refresh--animating {
599
- filter: drop-shadow(0 0 4px rgba(84, 174, 255, 0.8));
600
- }
601
-
602
- .taskon-dynamic-points-refresh-icon {
603
- width: 16px;
604
- height: 16px;
448
+ .taskon-card-desc-rich .ql-indent-4.ql-direction-rtl.ql-align-right {
449
+ padding-right: 12em;
605
450
  }
606
451
 
607
- .taskon-dynamic-points-refresh-icon--spin {
608
- animation: taskon-spin 1s linear infinite;
452
+ .taskon-card-desc-rich li.ql-indent-4.ql-direction-rtl.ql-align-right {
453
+ padding-right: 13.5em;
609
454
  }
610
455
 
611
- @keyframes taskon-spin {
612
- from {
613
- transform: rotate(0deg);
614
- }
615
- to {
616
- transform: rotate(360deg);
617
- }
456
+ .taskon-card-desc-rich .ql-indent-5:not(.ql-direction-rtl) {
457
+ padding-left: 15em;
618
458
  }
619
459
 
620
- .taskon-dynamic-points-cooldown {
621
- font-size: 14px;
622
- font-weight: 500;
623
- color: #54aeff !important;
624
- font-family: Menlo, Consolas, "Liberation Mono", "Courier New", Courier, monospace;
460
+ .taskon-card-desc-rich li.ql-indent-5:not(.ql-direction-rtl) {
461
+ padding-left: 16.5em;
625
462
  }
626
- /**
627
- * SwapDexTask Styles
628
- * 与原版 Vue SwapDexContractInteractive + SwapDexVolumeRules 样式一致
629
- */
630
463
 
631
- .taskon-swap-task {
632
- /* 继承 TaskCardBase 样式 */
464
+ .taskon-card-desc-rich .ql-indent-5.ql-direction-rtl.ql-align-right {
465
+ padding-right: 15em;
633
466
  }
634
467
 
635
- /* Content wrapper */
636
- .taskon-swap-content {
637
- display: flex;
638
- flex-direction: column;
639
- gap: 16px;
468
+ .taskon-card-desc-rich li.ql-indent-5.ql-direction-rtl.ql-align-right {
469
+ padding-right: 16.5em;
640
470
  }
641
471
 
642
- /* Rules section - 动态积分规则区域 */
643
- .taskon-swap-rules-section {
644
- display: flex;
645
- flex-direction: column;
646
- gap: 8px;
472
+ .taskon-card-desc-rich .ql-indent-6:not(.ql-direction-rtl) {
473
+ padding-left: 18em;
647
474
  }
648
475
 
649
- .taskon-swap-rules-title {
650
- font-size: 14px;
651
- font-weight: 500;
652
- color: rgba(255, 255, 255, 0.6);
653
- margin-bottom: 8px;
476
+ .taskon-card-desc-rich li.ql-indent-6:not(.ql-direction-rtl) {
477
+ padding-left: 19.5em;
654
478
  }
655
479
 
656
- .taskon-swap-rules-content {
657
- display: flex;
658
- flex-wrap: wrap;
659
- align-items: center;
660
- gap: 4px;
661
- padding: 12px;
662
- border-radius: 8px;
663
- background: rgba(255, 255, 255, 0.05);
664
- font-size: 14px;
665
- font-weight: 500;
666
- color: rgba(255, 255, 255, 0.6);
480
+ .taskon-card-desc-rich .ql-indent-6.ql-direction-rtl.ql-align-right {
481
+ padding-right: 18em;
667
482
  }
668
483
 
669
- .taskon-swap-rules-highlight {
670
- color: var(--taskon-secondary-color, #00ffa3);
484
+ .taskon-card-desc-rich li.ql-indent-6.ql-direction-rtl.ql-align-right {
485
+ padding-right: 19.5em;
671
486
  }
672
487
 
673
- .taskon-swap-rules-point-name {
674
- color: rgba(255, 255, 255, 0.4);
488
+ .taskon-card-desc-rich .ql-indent-7:not(.ql-direction-rtl) {
489
+ padding-left: 21em;
675
490
  }
676
491
 
677
- /* Instructions section - 任务描述区域 */
678
- .taskon-swap-instructions-section {
679
- display: flex;
680
- flex-direction: column;
681
- gap: 8px;
492
+ .taskon-card-desc-rich li.ql-indent-7:not(.ql-direction-rtl) {
493
+ padding-left: 22.5em;
682
494
  }
683
495
 
684
- .taskon-swap-instructions-title {
685
- font-size: 14px;
686
- font-weight: 500;
687
- color: rgba(255, 255, 255, 0.6);
688
- margin-bottom: 8px;
496
+ .taskon-card-desc-rich .ql-indent-7.ql-direction-rtl.ql-align-right {
497
+ padding-right: 21em;
689
498
  }
690
499
 
691
- .taskon-swap-instructions-content {
692
- padding: 12px;
693
- border-radius: 8px;
694
- background: rgba(255, 255, 255, 0.05);
500
+ .taskon-card-desc-rich li.ql-indent-7.ql-direction-rtl.ql-align-right {
501
+ padding-right: 22.5em;
695
502
  }
696
503
 
697
- .taskon-swap-desc {
698
- font-size: 14px;
699
- line-height: 21px;
700
- color: rgba(255, 255, 255, 0.8);
701
- word-break: break-word;
504
+ .taskon-card-desc-rich .ql-indent-8:not(.ql-direction-rtl) {
505
+ padding-left: 24em;
702
506
  }
703
507
 
704
- .taskon-swap-desc a {
705
- color: var(--taskon-primary-color, #3b82f6);
706
- text-decoration: none;
508
+ .taskon-card-desc-rich li.ql-indent-8:not(.ql-direction-rtl) {
509
+ padding-left: 25.5em;
707
510
  }
708
511
 
709
- .taskon-swap-desc a:hover {
710
- text-decoration: underline;
512
+ .taskon-card-desc-rich .ql-indent-8.ql-direction-rtl.ql-align-right {
513
+ padding-right: 24em;
711
514
  }
712
- /**
713
- * OuterPointAPITask Styles
714
- * 与 Vue 版本 OuterPointVerify + CustomizedSubmitDialog 样式一致
715
- */
716
515
 
717
- .taskon-outer-point-api-task {
718
- /* 继承 TaskCardBase 样式 */
516
+ .taskon-card-desc-rich li.ql-indent-8.ql-direction-rtl.ql-align-right {
517
+ padding-right: 25.5em;
719
518
  }
720
519
 
721
- /* ==================== Description Area ==================== */
722
- .taskon-outer-point-api-desc {
723
- font-size: 14px;
724
- line-height: 21px;
725
- color: rgba(255, 255, 255, 0.8);
726
- word-break: break-word;
520
+ .taskon-card-desc-rich .ql-indent-9:not(.ql-direction-rtl) {
521
+ padding-left: 27em;
727
522
  }
728
523
 
729
- .taskon-outer-point-api-desc a {
730
- color: var(--taskon-primary-color, #3b82f6);
731
- text-decoration: none;
524
+ .taskon-card-desc-rich li.ql-indent-9:not(.ql-direction-rtl) {
525
+ padding-left: 28.5em;
732
526
  }
733
527
 
734
- .taskon-outer-point-api-desc a:hover {
735
- text-decoration: underline;
528
+ .taskon-card-desc-rich .ql-indent-9.ql-direction-rtl.ql-align-right {
529
+ padding-right: 27em;
736
530
  }
737
531
 
738
- /* ==================== Customized Param Dialog ==================== */
739
- .taskon-outer-point-api-dialog {
740
- display: flex;
741
- flex-direction: column;
742
- gap: 16px;
532
+ .taskon-card-desc-rich li.ql-indent-9.ql-direction-rtl.ql-align-right {
533
+ padding-right: 28.5em;
743
534
  }
744
535
 
745
- /* Dialog title */
746
- .taskon-outer-point-api-dialog-title {
747
- font-size: 18px;
748
- font-weight: 600;
749
- color: #fff;
750
- margin: 0;
536
+ .taskon-card-desc-rich .ql-direction-rtl {
537
+ direction: rtl;
538
+ text-align: inherit;
751
539
  }
752
540
 
753
- /* Warning message */
754
- .taskon-outer-point-api-dialog-warning {
755
- display: flex;
756
- align-items: center;
757
- gap: 8px;
758
- padding: 12px;
759
- border-radius: 8px;
760
- background: rgba(255, 171, 0, 0.1);
761
- color: #ffab00;
762
- font-size: 14px;
763
- line-height: 20px;
541
+ .taskon-card-desc-rich .ql-align-center {
542
+ text-align: center;
764
543
  }
765
544
 
766
- .taskon-outer-point-api-dialog-warning-icon {
767
- flex-shrink: 0;
768
- width: 20px;
769
- height: 20px;
545
+ .taskon-card-desc-rich .ql-align-right {
546
+ text-align: right;
770
547
  }
771
548
 
772
- /* Description text */
773
- .taskon-outer-point-api-dialog-desc {
774
- font-size: 14px;
775
- line-height: 20px;
776
- color: rgba(255, 255, 255, 0.6);
549
+ .taskon-card-desc-rich .ql-align-justify {
550
+ text-align: justify;
777
551
  }
778
552
 
779
- /* Input area */
780
- .taskon-outer-point-api-dialog-input-wrap {
781
- display: flex;
782
- flex-direction: column;
783
- gap: 8px;
784
- }
553
+ /* ========== 常见富文本元素 ========== */
785
554
 
786
- .taskon-outer-point-api-dialog-label {
787
- font-size: 14px;
788
- font-weight: 500;
789
- color: rgba(255, 255, 255, 0.8);
555
+ .taskon-card-desc-rich a {
556
+ color: var(--taskon-color-link);
557
+ text-decoration: underline;
790
558
  }
791
559
 
792
- .taskon-outer-point-api-dialog-input {
793
- width: 100%;
794
- padding: 10px 12px;
795
- border-radius: 8px;
796
- border: 1px solid rgba(255, 255, 255, 0.15);
797
- background: rgba(255, 255, 255, 0.05);
798
- color: #fff;
799
- font-size: 14px;
800
- line-height: 20px;
801
- outline: none;
802
- transition: border-color 0.2s ease;
803
- box-sizing: border-box;
560
+ .taskon-card-desc-rich a:hover {
561
+ opacity: 0.8;
804
562
  }
805
563
 
806
- .taskon-outer-point-api-dialog-input::placeholder {
807
- color: rgba(255, 255, 255, 0.3);
564
+ .taskon-card-desc-rich strong,
565
+ .taskon-card-desc-rich b {
566
+ font-weight: 600;
567
+ color: var(--taskon-color-text);
808
568
  }
809
569
 
810
- .taskon-outer-point-api-dialog-input:focus {
811
- border-color: var(--taskon-primary-color, #3b82f6);
570
+ .taskon-card-desc-rich em,
571
+ .taskon-card-desc-rich i {
572
+ font-style: italic;
812
573
  }
813
574
 
814
- .taskon-outer-point-api-dialog-input--error {
815
- border-color: #ff4d4f;
575
+ .taskon-card-desc-rich u,
576
+ .taskon-card-desc-rich ins {
577
+ text-decoration: underline;
816
578
  }
817
579
 
818
- .taskon-outer-point-api-dialog-error {
819
- font-size: 12px;
820
- color: #ff4d4f;
580
+ .taskon-card-desc-rich code {
581
+ padding: 0.2em 0.4em;
582
+ font-size: 0.9em;
583
+ background: var(--taskon-color-bg-surface-strong);
584
+ border-radius: 3px;
821
585
  }
822
586
 
823
- /* Action buttons */
824
- .taskon-outer-point-api-dialog-actions {
825
- display: flex;
826
- justify-content: flex-end;
827
- gap: 12px;
828
- margin-top: 8px;
587
+ .taskon-card-desc-rich pre {
588
+ margin: 0.5em 0;
589
+ padding: 0.75em 1em;
590
+ overflow-x: auto;
591
+ text-wrap: initial;
592
+ background: var(--taskon-color-bg-surface-subtle);
593
+ border-radius: 6px;
829
594
  }
830
595
 
831
- .taskon-outer-point-api-dialog-btn {
832
- padding: 8px 24px;
833
- border-radius: 8px;
834
- font-size: 14px;
835
- font-weight: 500;
836
- cursor: pointer;
837
- transition: all 0.2s ease;
838
- border: none;
596
+ .taskon-card-desc-rich blockquote {
597
+ margin: 0.5em 0;
598
+ padding-left: 1em;
599
+ color: var(--taskon-color-text-tertiary);
600
+ border-left: 3px solid var(--taskon-color-link);
839
601
  }
840
602
 
841
- .taskon-outer-point-api-dialog-btn--cancel {
842
- background: rgba(255, 255, 255, 0.1);
843
- color: rgba(255, 255, 255, 0.8);
603
+ .taskon-card-desc-rich img {
604
+ max-width: 100%;
605
+ height: auto;
606
+ border-radius: 6px;
844
607
  }
845
608
 
846
- .taskon-outer-point-api-dialog-btn--cancel:hover {
847
- background: rgba(255, 255, 255, 0.15);
609
+ .taskon-card-desc-rich iframe {
610
+ display: block;
611
+ width: 100%;
612
+ max-width: 100%;
848
613
  }
614
+ /**
615
+ * TaskVerifyFailedDialog styles
616
+ * @description Match Vue ErrorInfo content rhythm and readability.
617
+ */
849
618
 
850
- .taskon-outer-point-api-dialog-btn--confirm {
851
- background: var(--taskon-primary-color, #3b82f6);
852
- color: #fff;
853
- }
619
+ /*
620
+ * Responsive base styles
621
+ *
622
+ * Keep mobile breakpoints and fallback patterns centralized here.
623
+ * Components should reuse these mixins instead of duplicating query logic.
624
+ */
854
625
 
855
- .taskon-outer-point-api-dialog-btn--confirm:hover {
856
- opacity: 0.9;
857
- }
626
+ /*
627
+ * Desktop-up mixin:
628
+ * 1) Enable desktop enhancement in wider containers
629
+ * 2) Keep viewport media query as fallback
630
+ */
858
631
 
859
- .taskon-outer-point-api-dialog-btn--confirm:disabled {
860
- opacity: 0.5;
861
- cursor: not-allowed;
632
+ .taskon-task-verify-failed-dialog-message {
633
+ margin-top: var(--taskon-spacing-sm);
634
+ font-size: var(--taskon-font-size-lg);
635
+ line-height: 1.25;
636
+ color: var(--taskon-color-text-tertiary);
637
+ white-space: pre-wrap;
862
638
  }
863
639
  /**
864
- * TaskWidget Styles
865
- * @description 任务列表组件样式(与 taskon-website BaseTask.vue 保持一致)
640
+ * PowTask Styles
641
+ * @description POW 任务样式
642
+ * 遵循 Widget 命名规范:.taskon-{widget-name}-{element}
643
+ */
644
+
645
+ /*
646
+ * Responsive base styles
866
647
  *
867
- * 命名规范:.taskon-task-{component}-{element}--{modifier}
648
+ * Keep mobile breakpoints and fallback patterns centralized here.
649
+ * Components should reuse these mixins instead of duplicating query logic.
650
+ */
651
+
652
+ /*
653
+ * Desktop-up mixin:
654
+ * 1) Enable desktop enhancement in wider containers
655
+ * 2) Keep viewport media query as fallback
868
656
  */
869
657
 
870
658
  /* ============================================
871
- CSS Variables (可被项目方覆盖)
872
- ============================================ */
873
- :root {
874
- /* Task card colors (dark theme, same as taskon-website) */
875
- --taskon-task-bg: #1d2123;
876
- --taskon-task-border: #1d2123;
877
- --taskon-task-border-hover: #41494b;
878
- --taskon-task-radius: 10px;
879
-
880
- /* Text colors */
881
- --taskon-task-text: #ffffff;
882
- --taskon-task-text-secondary: #9ca3af;
883
- --taskon-task-text-muted: #6b7280;
884
-
885
- /* Status colors */
886
- --taskon-color-primary: #3b82f6;
887
- --taskon-color-success: #22c55e;
888
- --taskon-color-warning: #f59e0b;
889
- --taskon-color-error: #ef4444;
890
-
891
- /* Recurrence badge color */
892
- --taskon-recurrence-color: #9aff73;
893
-
894
- /* Spacing */
895
- --taskon-task-spacing-xs: 4px;
896
- --taskon-task-spacing-sm: 8px;
897
- --taskon-task-spacing-md: 12px;
898
- --taskon-task-spacing-lg: 16px;
899
- --taskon-task-spacing-xl: 24px;
900
-
901
- /* Transitions */
902
- --taskon-task-transition: 0.2s ease;
659
+ * POW Task Container
660
+ * ============================================ */
661
+
662
+ .taskon-pow-task {
663
+ /* 继承 TaskCardBase 的样式 */
903
664
  }
904
665
 
905
666
  /* ============================================
906
- TaskList Styles
907
- Vue 版本 TaskList.vue + TaskType.vue 一致
908
- ============================================ */
909
- .taskon-task-list {
910
- display: flex;
911
- flex-direction: column;
912
- gap: var(--taskon-task-spacing-lg);
913
- }
667
+ * POW Input Area
668
+ * ============================================ */
914
669
 
915
- /* Progress section */
916
- .taskon-task-list-progress-wrap {
917
- margin-bottom: var(--taskon-task-spacing-sm);
670
+ .taskon-pow-input-area {
671
+ margin-top: var(--taskon-spacing-md);
918
672
  }
919
673
 
920
- /* Section styles */
921
- .taskon-task-list-section {
674
+ /* ============================================
675
+ * URL Input Row
676
+ * ============================================ */
677
+
678
+ .taskon-pow-url-row {
922
679
  display: flex;
923
680
  flex-direction: column;
681
+ align-items: stretch;
682
+ gap: var(--taskon-spacing-sm);
924
683
  }
925
684
 
926
- .taskon-task-list-section-header {
927
- display: flex;
928
- justify-content: space-between;
929
- align-items: center;
930
- margin-top: 30px;
931
- margin-bottom: 22px;
685
+ .taskon-pow-input {
686
+ flex: 1;
687
+ width: 100%;
688
+ padding: var(--taskon-spacing-sm)
689
+ var(--taskon-spacing-md);
690
+ border: 1px solid var(--taskon-color-border);
691
+ border-radius: var(--taskon-border-radius);
692
+ background: var(--taskon-color-bg-surface-subtle);
693
+ color: var(--taskon-color-text);
694
+ font-size: var(--taskon-font-size);
695
+ outline: none;
696
+ transition: border-color 0.2s ease;
932
697
  }
933
698
 
934
- .taskon-task-list-section-label {
935
- display: flex;
936
- align-items: center;
937
- gap: 6px;
699
+ .taskon-pow-input:focus {
700
+ border-color: var(--taskon-color-primary);
938
701
  }
939
702
 
940
- .taskon-task-list-section-title {
941
- font-size: 22px;
942
- font-weight: 600;
943
- line-height: 21px;
944
- color: var(--taskon-task-text);
703
+ .taskon-pow-input:disabled {
704
+ opacity: 0.5;
705
+ cursor: not-allowed;
945
706
  }
946
707
 
947
- .taskon-task-list-section-hint {
948
- font-size: 14px;
949
- color: rgba(255, 255, 255, 0.6);
708
+ .taskon-pow-input::placeholder {
709
+ color: var(--taskon-color-text-disabled);
950
710
  }
951
711
 
952
- .taskon-task-list-section-hint-em {
953
- font-weight: 600;
954
- color: rgba(0, 255, 163, 1);
955
- }
712
+ /* ============================================
713
+ * Text Input Row
714
+ * ============================================ */
956
715
 
957
- .taskon-task-list-items {
716
+ .taskon-pow-text-row {
958
717
  display: flex;
959
718
  flex-direction: column;
960
- gap: 20px;
719
+ align-items: stretch;
720
+ gap: var(--taskon-spacing-sm);
961
721
  }
962
722
 
963
- /* First section header doesn't need top margin */
964
- .taskon-task-list-section:first-child .taskon-task-list-section-header {
965
- margin-top: 0;
723
+ .taskon-pow-text-row .taskon-textarea-wrap {
724
+ flex: 1;
966
725
  }
967
726
 
968
- /* Empty state */
969
- .taskon-task-list-empty {
970
- padding: var(--taskon-task-spacing-xl);
971
- text-align: center;
972
- color: var(--taskon-task-text-muted);
973
- }
727
+ /* ============================================
728
+ * Image Upload Area - 与 Vue 版本 PowImageUploader 一致
729
+ * ============================================ */
974
730
 
975
- /* Mobile responsive */
976
- @media (max-width: 750px) {
977
- .taskon-task-list-section-header {
978
- display: block;
979
- margin-top: 5.6vw;
980
- margin-bottom: 4vw;
981
- }
982
-
983
- .taskon-task-list-section-label {
984
- flex-wrap: wrap;
985
- gap: 1.6vw;
986
- }
731
+ .taskon-pow-image-uploader {
732
+ margin-top: var(--taskon-spacing-md);
733
+ display: flex;
734
+ align-items: center;
735
+ }
987
736
 
988
- .taskon-task-list-section-title {
989
- font-size: 4.8vw;
990
- line-height: 6vw;
991
- }
737
+ .taskon-pow-url-row .taskon-verify-btn,
738
+ .taskon-pow-text-row .taskon-verify-btn {
739
+ width: 100%;
740
+ }
992
741
 
993
- .taskon-completed-count {
994
- margin-top: 2.67vw;
995
- justify-content: flex-start;
996
- }
742
+ .taskon-pow-image-upload-area {
743
+ flex: 1;
744
+ position: relative;
745
+ display: flex;
746
+ flex-direction: column;
747
+ align-items: center;
748
+ justify-content: center;
749
+ min-height: 128px;
750
+ text-align: center;
751
+ font-size: 0;
752
+ overflow: hidden;
753
+ border: 1px solid var(--taskon-color-border);
754
+ border-radius: var(--taskon-border-radius);
755
+ background: var(--taskon-color-bg-surface-subtle);
756
+ cursor: pointer;
757
+ transition: border-color 0.2s ease;
758
+ }
997
759
 
998
- .taskon-completed-count-check {
999
- width: 3.2vw;
1000
- height: 2.4vw;
1001
- margin-right: 2.13vw;
1002
- }
760
+ .taskon-pow-image-upload-area:hover:not(.taskon-pow-image-upload-area--disabled) {
761
+ border-color: var(--taskon-color-primary);
762
+ }
1003
763
 
1004
- .taskon-completed-count-text {
1005
- font-size: 3.47vw;
1006
- line-height: 4.4vw;
1007
- }
764
+ .taskon-pow-image-upload-area:focus {
765
+ outline: none;
766
+ border-color: var(--taskon-color-primary);
767
+ }
1008
768
 
1009
- .taskon-task-list-items {
1010
- gap: 3.07vw;
1011
- }
769
+ .taskon-pow-image-upload-area--disabled {
770
+ opacity: 0.5;
771
+ cursor: not-allowed;
1012
772
  }
1013
773
 
1014
- /* ============================================
1015
- TaskProgress Styles
1016
- ============================================ */
1017
- .taskon-task-progress {
1018
- display: flex;
1019
- flex-direction: column;
1020
- gap: var(--taskon-task-spacing-sm);
774
+ .taskon-pow-image-upload-icon {
775
+ width: 18px;
776
+ height: 18px;
777
+ color: var(--taskon-color-text-tertiary);
1021
778
  }
1022
779
 
1023
- .taskon-task-progress-bar {
1024
- height: 6px;
1025
- background: rgba(255, 255, 255, 0.1);
1026
- border-radius: 3px;
1027
- overflow: hidden;
780
+ .taskon-pow-image-upload-tip {
781
+ margin-top: 13px;
782
+ font-size: var(--taskon-font-size);
783
+ line-height: 1.43;
784
+ letter-spacing: 0.04em;
785
+ text-transform: uppercase;
786
+ white-space: pre-wrap;
787
+ color: var(--taskon-color-text-tertiary);
1028
788
  }
1029
789
 
1030
- .taskon-task-progress-bar-fill {
1031
- height: 100%;
1032
- background: var(--taskon-color-primary);
1033
- border-radius: 3px;
1034
- transition: width var(--taskon-task-transition);
790
+ .taskon-pow-image-preview {
791
+ border-radius: var(--taskon-border-radius-sm);
792
+ margin: var(--taskon-spacing-lg) 0;
793
+ max-width: 100%;
794
+ max-height: 300px;
1035
795
  }
1036
796
 
1037
- .taskon-task-progress--completed .taskon-task-progress-bar-fill {
1038
- background: var(--taskon-color-success);
797
+ /* Hover mask overlay */
798
+
799
+ .taskon-pow-image-mask {
800
+ display: none;
801
+ position: absolute;
802
+ inset: 0;
803
+ z-index: 2;
804
+ align-items: center;
805
+ justify-content: center;
806
+ flex-direction: column;
807
+ background: var(--taskon-color-bg-mask);
1039
808
  }
1040
809
 
1041
- .taskon-task-progress-text {
810
+ .taskon-pow-image-upload-area:hover .taskon-pow-image-mask,
811
+ .taskon-pow-image-upload-area:focus .taskon-pow-image-mask {
1042
812
  display: flex;
1043
- align-items: center;
1044
- gap: var(--taskon-task-spacing-xs);
1045
- font-size: 13px;
1046
- color: var(--taskon-task-text-secondary);
1047
813
  }
1048
814
 
1049
- .taskon-task-progress--completed .taskon-task-progress-text {
1050
- color: var(--taskon-color-success);
815
+ .taskon-pow-image-mask .taskon-pow-image-upload-icon {
816
+ color: var(--taskon-color-secondary);
1051
817
  }
1052
818
 
1053
- .taskon-task-progress-icon {
1054
- display: inline-flex;
1055
- align-items: center;
1056
- justify-content: center;
819
+ .taskon-pow-image-mask .taskon-pow-image-upload-tip {
820
+ color: var(--taskon-color-secondary);
821
+ opacity: 1;
1057
822
  }
1058
823
 
1059
- /* ============================================
1060
- TaskItem Styles
1061
- ============================================ */
1062
- .taskon-task-item {
1063
- position: relative;
1064
- padding: 16px 20px;
1065
- background: var(--taskon-task-bg);
1066
- border-radius: var(--taskon-task-radius);
1067
- border: 1px solid var(--taskon-task-border);
1068
- transition: border-color var(--taskon-task-transition);
824
+ /* Progress bar at bottom */
825
+
826
+ .taskon-pow-image-progress-bar {
827
+ z-index: 3;
828
+ position: absolute;
829
+ right: 0;
830
+ bottom: 0;
831
+ left: 0;
832
+ background: var(--taskon-color-bg-surface-strong);
833
+ height: 6px;
1069
834
  }
1070
835
 
1071
- .taskon-task-item:hover {
1072
- border-color: var(--taskon-task-border-hover);
836
+ .taskon-pow-image-progress-fill {
837
+ background: var(--taskon-color-primary);
838
+ height: 100%;
839
+ border-radius: var(--taskon-border-radius-sm);
840
+ transition: width 0.2s ease;
1073
841
  }
1074
842
 
1075
843
  /* ============================================
1076
- 左上角浮标:周期标签 / 冷却倒计时
1077
- Vue 版本 RecurrenceStatus.vue 样式一致
1078
- ============================================ */
1079
- .taskon-task-item-recurrence {
1080
- position: absolute;
1081
- top: -6px;
1082
- left: 12px;
1083
- /* 与 Vue 版本一致:使用 SVG 背景 */
1084
- background: url("data:image/svg+xml,%3csvg%20width='69'%20height='20'%20viewBox='0%200%2069%2020'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20filter='url(%23filter0_i_10913_141293)'%3e%3cpath%20d='M67.9996%204.5C67.9996%202.5%2066.7705%201%2064.1369%201H3.42655C0.791465%201%200%203%200%204.64199L67.9996%204.5Z'%20fill='%2328491F'/%3e%3c/g%3e%3cg%20filter='url(%23filter1_d_10913_141293)'%3e%3cpath%20d='M2.99902%201H11.242H65.999V1C64.6983%201%2063.6439%202.05443%2063.6439%203.35514V13C63.6439%2015.2091%2061.853%2017%2059.6439%2017H11.1205C8.91138%2017%207.12052%2015.2091%207.12052%2013V5.1215C7.12052%202.84526%205.27526%201%202.99902%201V1Z'%20fill='%232D422A'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_i_10913_141293'%20x='0'%20y='1'%20width='67.9996'%20height='4.64197'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='BackgroundImageFix'%20result='shape'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='4.1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='arithmetic'%20k2='-1'%20k3='1'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.8%200'/%3e%3cfeBlend%20mode='normal'%20in2='shape'%20result='effect1_innerShadow_10913_141293'/%3e%3c/filter%3e%3cfilter%20id='filter1_d_10913_141293'%20x='1.99902'%20y='0'%20width='67'%20height='20'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dx='1'%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='out'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.25%200'/%3e%3cfeBlend%20mode='normal'%20in2='BackgroundImageFix'%20result='effect1_dropShadow_10913_141293'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='effect1_dropShadow_10913_141293'%20result='shape'/%3e%3c/filter%3e%3c/defs%3e%3c/svg%3e") no-repeat center center;
1085
- background-size: cover;
1086
- /* 固定尺寸与 Vue 版本一致 */
1087
- width: 78px;
1088
- height: 20px;
1089
- /* 文字样式 */
1090
- color: var(--taskon-recurrence-color);
1091
- font-size: 12px;
1092
- line-height: 16px;
1093
- font-weight: 500;
1094
- text-align: center;
1095
- display: flex;
1096
- align-items: center;
1097
- justify-content: center;
844
+ * Error Message
845
+ * ============================================ */
846
+
847
+ .taskon-pow-error {
848
+ margin-top: 10px;
849
+ font-size: var(--taskon-font-size);
850
+ color: var(--taskon-color-error);
851
+ overflow-wrap: anywhere;
852
+ word-break: break-word;
1098
853
  }
1099
854
 
1100
- /* 冷却倒计时样式 - 继承标签样式 */
1101
- .taskon-task-item-recurrence .taskon-cooldown-timer {
1102
- color: var(--taskon-recurrence-color);
1103
- font-size: 12px;
1104
- line-height: 16px;
855
+ /* ============================================
856
+ * Average Review Time
857
+ * ============================================ */
858
+
859
+ /* 与 Vue 版本 AverageReview.vue 样式一致 */
860
+
861
+ .taskon-pow-review-time {
862
+ margin-top: 10px;
863
+ color: var(--taskon-color-warning);
864
+ font-size: var(--taskon-font-size-sm);
1105
865
  font-weight: 500;
866
+ line-height: 1.33;
1106
867
  }
1107
868
 
1108
869
  /* ============================================
1109
- 第一行:图标 + 标题 + 右侧内容
870
+ * Desktop 增强
871
+ * ============================================ */
872
+
873
+ @supports (container-type: inline-size) {
874
+ @container (min-width: 751px) {
875
+ .taskon-pow-url-row {
876
+ flex-direction: row;
877
+ align-items: center;
878
+ gap: var(--taskon-spacing-md);
879
+ }
880
+
881
+ .taskon-pow-text-row {
882
+ flex-direction: row;
883
+ align-items: flex-end;
884
+ gap: var(--taskon-spacing-md);
885
+ }
886
+
887
+ .taskon-pow-url-row .taskon-verify-btn,
888
+ .taskon-pow-text-row .taskon-verify-btn {
889
+ width: auto;
890
+ }
891
+
892
+ .taskon-pow-image-uploader {
893
+ margin-top: var(--taskon-spacing-lg);
894
+ }
895
+ }
896
+ }
897
+
898
+ @supports not (container-type: inline-size) {
899
+ @media (min-width: 751px) {
900
+ .taskon-pow-url-row {
901
+ flex-direction: row;
902
+ align-items: center;
903
+ gap: var(--taskon-spacing-md);
904
+ }
905
+
906
+ .taskon-pow-text-row {
907
+ flex-direction: row;
908
+ align-items: flex-end;
909
+ gap: var(--taskon-spacing-md);
910
+ }
911
+
912
+ .taskon-pow-url-row .taskon-verify-btn,
913
+ .taskon-pow-text-row .taskon-verify-btn {
914
+ width: auto;
915
+ }
916
+
917
+ .taskon-pow-image-uploader {
918
+ margin-top: var(--taskon-spacing-lg);
919
+ }
920
+ }
921
+ }
922
+ /* ============================================
923
+ DynamicPoints Component Styles
924
+ 与 Vue 版本 BaseDynamicPoint.vue 样式一致
1110
925
  ============================================ */
1111
- .taskon-task-item-row {
1112
- display: flex;
1113
- align-items: center;
1114
- }
1115
926
 
1116
- /* Left section: Icon + Title */
1117
- .taskon-task-item-left {
1118
- display: flex;
927
+ .taskon-dynamic-points {
928
+ display: inline-flex;
1119
929
  align-items: center;
1120
- flex: 1;
1121
- min-width: 0;
930
+ gap: var(--taskon-spacing-sm);
931
+ padding: var(--taskon-spacing-sm) var(--taskon-spacing-md);
932
+ background: var(--taskon-color-bg-surface-subtle);
933
+ border-radius: var(--taskon-border-radius);
1122
934
  }
1123
935
 
1124
- .taskon-task-item-icon {
1125
- flex-shrink: 0;
936
+ .taskon-dynamic-points-value-wrap {
1126
937
  display: flex;
1127
938
  align-items: center;
1128
- justify-content: center;
1129
- margin-right: 16px;
1130
- color: var(--taskon-task-text-secondary);
939
+ gap: var(--taskon-spacing-sm);
940
+ flex-shrink: 0;
1131
941
  }
1132
942
 
1133
- .taskon-task-item--completed .taskon-task-item-icon {
1134
- color: var(--taskon-color-success);
943
+ .taskon-dynamic-points-value {
944
+ font-size: var(--taskon-font-size-lg);
945
+ font-weight: 600;
946
+ color: var(--taskon-color-text);
1135
947
  }
1136
948
 
1137
- /* Title wrapper - 与 Vue 版本 TitleRow 结构一致 */
1138
- /* 普通 block flow,标题 inline,TotalEarnPoint 作为 block div 自然换行 */
1139
- .taskon-task-item-title-wrap {
1140
- flex: 1;
1141
- min-width: 0;
949
+ .taskon-dynamic-points-value--highlight {
950
+ color: var(--taskon-color-secondary);
1142
951
  }
1143
952
 
1144
- .taskon-task-item-title {
1145
- display: inline;
1146
- font-size: 18px;
953
+ .taskon-dynamic-points-max {
954
+ font-size: var(--taskon-font-size);
1147
955
  font-weight: 500;
1148
- color: var(--taskon-task-text);
1149
- line-height: 23px;
1150
- overflow-wrap: break-word;
956
+ color: var(--taskon-color-text-tertiary);
957
+ text-transform: capitalize;
1151
958
  }
1152
959
 
1153
- /* Title as link - 参考 Vue 版本 TitleRow.vue 的 OutLink 样式 */
1154
- .taskon-task-item-title--link {
1155
- color: #54aeff;
1156
- text-decoration: underline;
1157
- transition: opacity var(--taskon-task-transition);
960
+ .taskon-dynamic-points-info {
961
+ display: inline-flex;
962
+ align-items: center;
963
+ justify-content: center;
964
+ color: var(--taskon-color-text-tertiary);
965
+ cursor: pointer;
1158
966
  }
1159
967
 
1160
- .taskon-task-item-title--link:hover {
1161
- opacity: 0.8;
968
+ .taskon-dynamic-points-info:hover {
969
+ color: var(--taskon-color-text);
1162
970
  }
1163
971
 
1164
- .taskon-task-item--completed .taskon-task-item-title {
1165
- color: var(--taskon-task-text-secondary);
972
+ .taskon-dynamic-points-refresh {
973
+ display: inline-flex;
974
+ align-items: center;
975
+ justify-content: center;
976
+ width: 24px;
977
+ height: 24px;
978
+ padding: 0;
979
+ margin-left: var(--taskon-spacing-xs);
980
+ background: transparent;
981
+ border: none;
982
+ border-radius: var(--taskon-border-radius-sm);
983
+ color: var(--taskon-color-link);
984
+ cursor: pointer;
985
+ transition: opacity 0.2s, transform 0.2s;
1166
986
  }
1167
987
 
1168
- /* Links in title - 统一蓝色加下划线样式 */
1169
- .taskon-task-item-link {
1170
- color: #54aeff;
1171
- text-decoration: underline;
1172
- transition: opacity var(--taskon-task-transition);
988
+ .taskon-dynamic-points-refresh:hover:not(:disabled) {
989
+ opacity: 0.8;
1173
990
  }
1174
991
 
1175
- .taskon-task-item-link:hover {
1176
- opacity: 0.8;
992
+ .taskon-dynamic-points-refresh--disabled {
993
+ opacity: 0.6;
994
+ cursor: not-allowed;
1177
995
  }
1178
996
 
1179
- /* Title tip icon */
1180
- .taskon-task-item-title-tip {
1181
- display: inline-flex;
1182
- align-items: center;
1183
- justify-content: center;
1184
- margin-left: 6px;
1185
- color: rgba(255, 255, 255, 0.4);
1186
- cursor: help;
1187
- flex-shrink: 0;
997
+ .taskon-dynamic-points-refresh--animating {
998
+ filter: drop-shadow(0 0 4px var(--taskon-color-link));
1188
999
  }
1189
1000
 
1190
- .taskon-task-item-title-tip:hover {
1191
- color: rgba(255, 255, 255, 0.6);
1001
+ .taskon-dynamic-points-refresh-icon {
1002
+ width: 16px;
1003
+ height: 16px;
1192
1004
  }
1193
1005
 
1194
- /* Right section: Points + Total + Verify */
1195
- .taskon-task-item-right {
1196
- display: flex;
1006
+ .taskon-dynamic-points-refresh-icon--spin {
1007
+ animation: taskon-spin 1s linear infinite;
1008
+ }
1009
+
1010
+ @keyframes taskon-spin {
1011
+ from {
1012
+ transform: rotate(0deg);
1013
+ }
1014
+ to {
1015
+ transform: rotate(360deg);
1016
+ }
1017
+ }
1018
+
1019
+ .taskon-dynamic-points-cooldown {
1020
+ font-size: var(--taskon-font-size);
1021
+ font-weight: 500;
1022
+ color: var(--taskon-color-link);
1023
+ }
1024
+ /**
1025
+ * SwapDexTask Styles
1026
+ * 与原版 Vue SwapDexContractInteractive + SwapDexVolumeRules 样式一致
1027
+ */
1028
+
1029
+ .taskon-swap-task {
1030
+ /* 继承 TaskCardBase 样式 */
1031
+ }
1032
+
1033
+ /* Content wrapper */
1034
+
1035
+ .taskon-swap-content {
1036
+ display: flex;
1037
+ flex-direction: column;
1038
+ gap: var(--taskon-spacing-md);
1039
+ }
1040
+
1041
+ /* Rules section - 动态积分规则区域 */
1042
+
1043
+ .taskon-swap-rules-section {
1044
+ display: flex;
1045
+ flex-direction: column;
1046
+ gap: var(--taskon-spacing-sm);
1047
+ }
1048
+
1049
+ .taskon-swap-rules-title {
1050
+ font-size: var(--taskon-font-size);
1051
+ font-weight: 500;
1052
+ color: var(--taskon-color-text-tertiary);
1053
+ margin-bottom: var(--taskon-spacing-sm);
1054
+ }
1055
+
1056
+ .taskon-swap-rules-content {
1057
+ display: flex;
1058
+ flex-wrap: wrap;
1059
+ align-items: center;
1060
+ gap: var(--taskon-spacing-xs);
1061
+ padding: var(--taskon-spacing-md);
1062
+ border-radius: var(--taskon-border-radius);
1063
+ background: var(--taskon-color-bg-surface-subtle);
1064
+ font-size: var(--taskon-font-size);
1065
+ font-weight: 500;
1066
+ color: var(--taskon-color-text-tertiary);
1067
+ }
1068
+
1069
+ .taskon-swap-rules-highlight {
1070
+ color: var(--taskon-color-secondary);
1071
+ }
1072
+
1073
+ .taskon-swap-rules-point-name {
1074
+ color: var(--taskon-color-text-secondary);
1075
+ }
1076
+
1077
+ .taskon-swap-rules-max {
1078
+ color: var(--taskon-color-text-tertiary);
1079
+ }
1080
+
1081
+ /* Instructions section - 任务描述区域 */
1082
+
1083
+ .taskon-swap-instructions-section {
1084
+ display: flex;
1085
+ flex-direction: column;
1086
+ gap: var(--taskon-spacing-sm);
1087
+ }
1088
+
1089
+ .taskon-swap-instructions-title {
1090
+ font-size: var(--taskon-font-size);
1091
+ font-weight: 500;
1092
+ color: var(--taskon-color-text-tertiary);
1093
+ margin-bottom: var(--taskon-spacing-sm);
1094
+ }
1095
+
1096
+ .taskon-swap-instructions-content {
1097
+ padding: var(--taskon-spacing-md);
1098
+ border-radius: var(--taskon-border-radius);
1099
+ background: var(--taskon-color-bg-surface-subtle);
1100
+ }
1101
+ /**
1102
+ * OuterPointAPITask Styles
1103
+ * 与 Vue 版本 OuterPointVerify + CustomizedSubmitDialog 样式一致
1104
+ */
1105
+
1106
+ .taskon-outer-point-api-task {
1107
+ /* 继承 TaskCardBase 样式 */
1108
+ }
1109
+
1110
+ /* ==================== Customized Param Dialog ==================== */
1111
+
1112
+ .taskon-outer-point-api-dialog {
1113
+ display: flex;
1114
+ flex-direction: column;
1115
+ gap: var(--taskon-spacing-md);
1116
+ }
1117
+
1118
+ /* Dialog title */
1119
+
1120
+ .taskon-outer-point-api-dialog-title {
1121
+ font-size: var(--taskon-font-size-xl);
1122
+ font-weight: 600;
1123
+ color: var(--taskon-color-text);
1124
+ margin: 0;
1125
+ }
1126
+
1127
+ /* Warning message */
1128
+
1129
+ .taskon-outer-point-api-dialog-warning {
1130
+ display: flex;
1131
+ align-items: center;
1132
+ gap: var(--taskon-spacing-sm);
1133
+ padding: var(--taskon-spacing-md);
1134
+ border-radius: var(--taskon-border-radius);
1135
+ background: var(--taskon-color-warning-bg);
1136
+ color: var(--taskon-color-warning);
1137
+ font-size: var(--taskon-font-size);
1138
+ line-height: 1.43;
1139
+ }
1140
+
1141
+ .taskon-outer-point-api-dialog-warning-icon {
1142
+ flex-shrink: 0;
1143
+ width: 20px;
1144
+ height: 20px;
1145
+ }
1146
+
1147
+ /* Description text */
1148
+
1149
+ .taskon-outer-point-api-dialog-desc {
1150
+ font-size: var(--taskon-font-size);
1151
+ line-height: 1.43;
1152
+ color: var(--taskon-color-text-tertiary);
1153
+ }
1154
+
1155
+ /* Input area */
1156
+
1157
+ .taskon-outer-point-api-dialog-input-wrap {
1158
+ display: flex;
1159
+ flex-direction: column;
1160
+ gap: var(--taskon-spacing-sm);
1161
+ }
1162
+
1163
+ .taskon-outer-point-api-dialog-label {
1164
+ font-size: var(--taskon-font-size);
1165
+ font-weight: 500;
1166
+ color: var(--taskon-color-text-secondary);
1167
+ }
1168
+
1169
+ .taskon-outer-point-api-dialog-input {
1170
+ width: 100%;
1171
+ padding: var(--taskon-spacing-sm)
1172
+ var(--taskon-spacing-md);
1173
+ border-radius: var(--taskon-border-radius);
1174
+ border: 1px solid var(--taskon-color-border);
1175
+ background: var(--taskon-color-bg-surface-subtle);
1176
+ color: var(--taskon-color-text);
1177
+ font-size: var(--taskon-font-size);
1178
+ line-height: 1.43;
1179
+ outline: none;
1180
+ transition: border-color 0.2s ease;
1181
+ box-sizing: border-box;
1182
+ }
1183
+
1184
+ .taskon-outer-point-api-dialog-input::placeholder {
1185
+ color: var(--taskon-color-text-disabled);
1186
+ }
1187
+
1188
+ .taskon-outer-point-api-dialog-input:focus {
1189
+ border-color: var(--taskon-color-primary);
1190
+ }
1191
+
1192
+ .taskon-outer-point-api-dialog-input--error {
1193
+ border-color: var(--taskon-color-error);
1194
+ }
1195
+
1196
+ .taskon-outer-point-api-dialog-error {
1197
+ font-size: var(--taskon-font-size-sm);
1198
+ color: var(--taskon-color-error);
1199
+ overflow-wrap: anywhere;
1200
+ word-break: break-word;
1201
+ }
1202
+
1203
+ /* Action buttons */
1204
+
1205
+ .taskon-outer-point-api-dialog-actions {
1206
+ display: flex;
1207
+ justify-content: flex-end;
1208
+ gap: var(--taskon-spacing-md);
1209
+ margin-top: var(--taskon-spacing-sm);
1210
+ }
1211
+
1212
+ .taskon-outer-point-api-dialog-btn {
1213
+ padding: var(--taskon-spacing-sm) var(--taskon-spacing-lg);
1214
+ border-radius: var(--taskon-border-radius);
1215
+ font-size: var(--taskon-font-size);
1216
+ font-weight: 500;
1217
+ cursor: pointer;
1218
+ transition: all 0.2s ease;
1219
+ border: none;
1220
+ }
1221
+
1222
+ .taskon-outer-point-api-dialog-btn--cancel {
1223
+ background: var(--taskon-color-bg-surface-strong);
1224
+ color: var(--taskon-color-text-secondary);
1225
+ }
1226
+
1227
+ .taskon-outer-point-api-dialog-btn--cancel:hover {
1228
+ background: var(--taskon-color-bg-inset);
1229
+ }
1230
+
1231
+ .taskon-outer-point-api-dialog-btn--confirm {
1232
+ background: var(--taskon-color-primary);
1233
+ color: var(--taskon-color-text-on-primary);
1234
+ }
1235
+
1236
+ .taskon-outer-point-api-dialog-btn--confirm:hover {
1237
+ opacity: 0.9;
1238
+ }
1239
+
1240
+ .taskon-outer-point-api-dialog-btn--confirm:disabled {
1241
+ opacity: 0.5;
1242
+ cursor: not-allowed;
1243
+ }
1244
+ /**
1245
+ * TaskWidget Styles
1246
+ * @description 任务列表组件样式(与 taskon-website BaseTask.vue 保持一致)
1247
+ *
1248
+ * 命名规范:.taskon-task-{component}-{element}--{modifier}
1249
+ */
1250
+
1251
+ /*
1252
+ * Responsive base styles
1253
+ *
1254
+ * Keep mobile breakpoints and fallback patterns centralized here.
1255
+ * Components should reuse these mixins instead of duplicating query logic.
1256
+ */
1257
+
1258
+ /*
1259
+ * Desktop-up mixin:
1260
+ * 1) Enable desktop enhancement in wider containers
1261
+ * 2) Keep viewport media query as fallback
1262
+ */
1263
+
1264
+ /* ============================================
1265
+ TaskList Styles
1266
+ 与 Vue 版本 TaskList.vue + TaskType.vue 一致
1267
+ ============================================ */
1268
+
1269
+ .taskon-task-list {
1270
+ display: flex;
1271
+ flex-direction: column;
1272
+ gap: var(--taskon-spacing-md);
1273
+ }
1274
+
1275
+ /* Progress section */
1276
+
1277
+ .taskon-task-list-progress-wrap {
1278
+ margin-bottom: var(--taskon-spacing-sm);
1279
+ }
1280
+
1281
+ /* Section styles */
1282
+
1283
+ .taskon-task-list-section {
1284
+ display: flex;
1285
+ flex-direction: column;
1286
+ }
1287
+
1288
+ .taskon-task-list-section-header {
1289
+ display: block;
1290
+ margin-top: var(--taskon-spacing-lg);
1291
+ margin-bottom: var(--taskon-spacing-md);
1292
+ }
1293
+
1294
+ .taskon-task-list-section-label {
1295
+ display: flex;
1296
+ align-items: center;
1297
+ flex-wrap: wrap;
1298
+ gap: var(--taskon-spacing-sm);
1299
+ }
1300
+
1301
+ .taskon-task-list-section-title {
1302
+ font-size: var(--taskon-font-size-xxl);
1303
+ font-weight: 600;
1304
+ line-height: 1;
1305
+ color: var(--taskon-color-text);
1306
+ }
1307
+
1308
+ .taskon-task-list-section-hint {
1309
+ font-size: var(--taskon-font-size);
1310
+ color: var(--taskon-color-text-tertiary);
1311
+ }
1312
+
1313
+ .taskon-task-list-section-hint-em {
1314
+ font-weight: 600;
1315
+ color: var(--taskon-color-secondary);
1316
+ }
1317
+
1318
+ .taskon-task-list-items {
1319
+ display: flex;
1320
+ flex-direction: column;
1321
+ gap: var(--taskon-spacing-md);
1322
+ }
1323
+
1324
+ /* First section header doesn't need top margin */
1325
+
1326
+ .taskon-task-list-section:first-child .taskon-task-list-section-header {
1327
+ margin-top: 0;
1328
+ }
1329
+
1330
+ /* Empty state */
1331
+
1332
+ .taskon-task-list-empty {
1333
+ padding: var(--taskon-spacing-lg);
1334
+ text-align: center;
1335
+ color: var(--taskon-color-text-disabled);
1336
+ }
1337
+
1338
+ .taskon-completed-count {
1339
+ margin-top: var(--taskon-spacing-sm);
1340
+ justify-content: flex-start;
1341
+ }
1342
+
1343
+ @supports (container-type: inline-size) {
1344
+ @container (min-width: 751px) {
1345
+ .taskon-task-list-section-header {
1346
+ display: flex;
1347
+ justify-content: space-between;
1348
+ align-items: center;
1349
+ margin-top: 30px;
1350
+ margin-bottom: 22px;
1351
+ }
1352
+
1353
+ .taskon-task-list-section-label {
1354
+ flex-wrap: nowrap;
1355
+ gap: 6px;
1356
+ }
1357
+
1358
+ .taskon-completed-count {
1359
+ margin-top: 0;
1360
+ }
1361
+
1362
+ .taskon-task-list-items {
1363
+ gap: 20px;
1364
+ }
1365
+ }
1366
+ }
1367
+
1368
+ @supports not (container-type: inline-size) {
1369
+ @media (min-width: 751px) {
1370
+ .taskon-task-list-section-header {
1371
+ display: flex;
1372
+ justify-content: space-between;
1373
+ align-items: center;
1374
+ margin-top: 30px;
1375
+ margin-bottom: 22px;
1376
+ }
1377
+
1378
+ .taskon-task-list-section-label {
1379
+ flex-wrap: nowrap;
1380
+ gap: 6px;
1381
+ }
1382
+
1383
+ .taskon-completed-count {
1384
+ margin-top: 0;
1385
+ }
1386
+
1387
+ .taskon-task-list-items {
1388
+ gap: 20px;
1389
+ }
1390
+ }
1391
+ }
1392
+
1393
+ /* ============================================
1394
+ TaskProgress Styles
1395
+ ============================================ */
1396
+
1397
+ .taskon-task-progress {
1398
+ display: flex;
1399
+ flex-direction: column;
1400
+ gap: var(--taskon-spacing-sm);
1401
+ }
1402
+
1403
+ .taskon-task-progress-bar {
1404
+ height: 6px;
1405
+ background: var(--taskon-color-bg-surface-strong);
1406
+ border-radius: var(--taskon-border-radius-sm);
1407
+ overflow: hidden;
1408
+ }
1409
+
1410
+ .taskon-task-progress-bar-fill {
1411
+ height: 100%;
1412
+ background: var(--taskon-color-primary);
1413
+ border-radius: var(--taskon-border-radius-sm);
1414
+ transition: width 0.2s ease;
1415
+ }
1416
+
1417
+ .taskon-task-progress--completed .taskon-task-progress-bar-fill {
1418
+ background: var(--taskon-color-success);
1419
+ }
1420
+
1421
+ .taskon-task-progress-text {
1422
+ display: flex;
1423
+ align-items: center;
1424
+ gap: var(--taskon-spacing-xs);
1425
+ font-size: var(--taskon-font-size-sm);
1426
+ color: var(--taskon-color-text-tertiary);
1427
+ }
1428
+
1429
+ .taskon-task-progress--completed .taskon-task-progress-text {
1430
+ color: var(--taskon-color-success);
1431
+ }
1432
+
1433
+ .taskon-task-progress-icon {
1434
+ display: inline-flex;
1435
+ align-items: center;
1436
+ justify-content: center;
1437
+ }
1438
+
1439
+ /* ============================================
1440
+ TaskItem Styles
1441
+ ============================================ */
1442
+
1443
+ .taskon-task-item {
1444
+ position: relative;
1445
+ padding: var(--taskon-spacing-md);
1446
+ background: var(--taskon-color-bg-surface-subtle);
1447
+ border-radius: var(--taskon-border-radius-lg);
1448
+ border: 1px solid var(--taskon-color-border-secondary);
1449
+ transition: border-color 0.2s ease;
1450
+ }
1451
+
1452
+ .taskon-task-item:hover {
1453
+ border-color: var(--taskon-color-border);
1454
+ }
1455
+
1456
+ /* ============================================
1457
+ 左上角浮标:周期标签 / 冷却倒计时
1458
+ 与 Vue 版本 RecurrenceStatus.vue 样式一致
1459
+ ============================================ */
1460
+
1461
+ .taskon-task-item-recurrence {
1462
+ position: absolute;
1463
+ top: -6px;
1464
+ left: 12px;
1465
+ /* 与 Vue 版本一致:使用 SVG 背景 */
1466
+ background: url("data:image/svg+xml,%3csvg%20width='69'%20height='20'%20viewBox='0%200%2069%2020'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20filter='url(%23filter0_i_10913_141293)'%3e%3cpath%20d='M67.9996%204.5C67.9996%202.5%2066.7705%201%2064.1369%201H3.42655C0.791465%201%200%203%200%204.64199L67.9996%204.5Z'%20fill='%2328491F'/%3e%3c/g%3e%3cg%20filter='url(%23filter1_d_10913_141293)'%3e%3cpath%20d='M2.99902%201H11.242H65.999V1C64.6983%201%2063.6439%202.05443%2063.6439%203.35514V13C63.6439%2015.2091%2061.853%2017%2059.6439%2017H11.1205C8.91138%2017%207.12052%2015.2091%207.12052%2013V5.1215C7.12052%202.84526%205.27526%201%202.99902%201V1Z'%20fill='%232D422A'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_i_10913_141293'%20x='0'%20y='1'%20width='67.9996'%20height='4.64197'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='BackgroundImageFix'%20result='shape'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='4.1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='arithmetic'%20k2='-1'%20k3='1'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.8%200'/%3e%3cfeBlend%20mode='normal'%20in2='shape'%20result='effect1_innerShadow_10913_141293'/%3e%3c/filter%3e%3cfilter%20id='filter1_d_10913_141293'%20x='1.99902'%20y='0'%20width='67'%20height='20'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dx='1'%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='out'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.25%200'/%3e%3cfeBlend%20mode='normal'%20in2='BackgroundImageFix'%20result='effect1_dropShadow_10913_141293'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='effect1_dropShadow_10913_141293'%20result='shape'/%3e%3c/filter%3e%3c/defs%3e%3c/svg%3e") no-repeat center center;
1467
+ background-size: cover;
1468
+ /* 固定尺寸与 Vue 版本一致 */
1469
+ width: 78px;
1470
+ height: 20px;
1471
+ /* 文字样式 */
1472
+ color: var(--taskon-color-primary);
1473
+ font-size: var(--taskon-font-size-sm);
1474
+ line-height: 1.33;
1475
+ font-weight: 500;
1476
+ text-align: center;
1477
+ display: flex;
1478
+ align-items: center;
1479
+ justify-content: center;
1480
+ }
1481
+
1482
+ /* 冷却倒计时样式 - 继承标签样式 */
1483
+
1484
+ .taskon-task-item-recurrence .taskon-cooldown-timer {
1485
+ color: var(--taskon-color-primary);
1486
+ font-size: var(--taskon-font-size-sm);
1487
+ line-height: 1.33;
1488
+ font-weight: 500;
1489
+ }
1490
+
1491
+ /* ============================================
1492
+ 第一行:图标 + 标题 + 右侧内容
1493
+ ============================================ */
1494
+
1495
+ .taskon-task-item-row {
1496
+ display: flex;
1497
+ align-items: flex-start;
1498
+ gap: 8px;
1499
+ }
1500
+
1501
+ /* Left section: Icon + Title */
1502
+
1503
+ .taskon-task-item-left {
1504
+ display: flex;
1505
+ align-items: center;
1506
+ flex: 1;
1507
+ min-width: 0;
1508
+ }
1509
+
1510
+ .taskon-task-item-icon {
1511
+ flex-shrink: 0;
1512
+ display: flex;
1513
+ align-items: center;
1514
+ justify-content: center;
1515
+ margin-right: 10px;
1516
+ color: var(--taskon-color-text-tertiary);
1517
+ }
1518
+
1519
+ .taskon-task-item--completed .taskon-task-item-icon {
1520
+ color: var(--taskon-color-success);
1521
+ }
1522
+
1523
+ /* Title wrapper - 与 Vue 版本 TitleRow 结构一致 */
1524
+
1525
+ /* 普通 block flow,标题 inline,TotalEarnPoint 作为 block div 自然换行 */
1526
+
1527
+ .taskon-task-item-title-wrap {
1528
+ flex: 1;
1529
+ min-width: 0;
1530
+ }
1531
+
1532
+ .taskon-task-item-title {
1533
+ display: inline;
1534
+ font-size: var(--taskon-font-size-xl);
1535
+ font-weight: 500;
1536
+ color: var(--taskon-color-text);
1537
+ line-height: 1.28;
1538
+ overflow-wrap: break-word;
1539
+ }
1540
+
1541
+ /* Title as link - 参考 Vue 版本 TitleRow.vue 的 OutLink 样式 */
1542
+
1543
+ .taskon-task-item-title--link {
1544
+ color: var(--taskon-color-link);
1545
+ text-decoration: underline;
1546
+ transition: opacity 0.2s ease;
1547
+ }
1548
+
1549
+ .taskon-task-item-title--link:hover {
1550
+ opacity: 0.8;
1551
+ }
1552
+
1553
+ .taskon-task-item--completed .taskon-task-item-title {
1554
+ color: var(--taskon-color-text-tertiary);
1555
+ }
1556
+
1557
+ /* Links in title - 统一蓝色加下划线样式 */
1558
+
1559
+ .taskon-task-item-link {
1560
+ color: var(--taskon-color-link);
1561
+ text-decoration: underline;
1562
+ transition: opacity 0.2s ease;
1563
+ }
1564
+
1565
+ .taskon-task-item-link:hover {
1566
+ opacity: 0.8;
1567
+ }
1568
+
1569
+ /* Title tip icon */
1570
+
1571
+ .taskon-task-item-title-tip {
1572
+ display: inline-flex;
1573
+ align-items: center;
1574
+ justify-content: center;
1575
+ margin-left: 6px;
1576
+ color: var(--taskon-color-text-disabled);
1577
+ cursor: help;
1578
+ flex-shrink: 0;
1579
+ }
1580
+
1581
+ .taskon-task-item-title-tip:hover {
1582
+ color: var(--taskon-color-text-tertiary);
1583
+ }
1584
+
1585
+ /* Right section: Points + Total + Verify */
1586
+
1587
+ .taskon-task-item-right {
1588
+ display: flex;
1589
+ flex-direction: column;
1590
+ align-items: flex-end;
1591
+ gap: 6px;
1592
+ flex-shrink: 0;
1593
+ margin-left: 8px;
1594
+ }
1595
+
1596
+ /* Points display - 参考 TaskPoint.vue */
1597
+
1598
+ .taskon-task-item-points {
1599
+ min-width: 40px;
1600
+ height: 34px;
1601
+ padding: 0 10px;
1602
+ display: flex;
1603
+ align-items: center;
1604
+ justify-content: center;
1605
+ gap: 2px;
1606
+ background: var(--taskon-color-bg-surface-subtle);
1607
+ border-radius: var(--taskon-border-radius-sm);
1608
+ font-size: var(--taskon-font-size-lg);
1609
+ font-weight: 500;
1610
+ }
1611
+
1612
+ .taskon-task-item-points-value {
1613
+ color: var(--taskon-color-text);
1614
+ }
1615
+
1616
+ /* Points value when task is completed - green color like Vue version */
1617
+
1618
+ .taskon-task-item-points-value--completed {
1619
+ color: var(--taskon-color-secondary);
1620
+ }
1621
+
1622
+ .taskon-task-item-points-time {
1623
+ font-size: var(--taskon-font-size-sm);
1624
+ color: var(--taskon-color-text-tertiary);
1625
+ }
1626
+
1627
+ /* Tip icon next to points (margin controlled externally) */
1628
+
1629
+ .taskon-task-item-tip {
1630
+ margin-left: 10px;
1631
+ }
1632
+
1633
+ /* Total points */
1634
+
1635
+ .taskon-task-item-total-points {
1636
+ font-size: var(--taskon-font-size-sm);
1637
+ color: var(--taskon-color-text-disabled);
1638
+ }
1639
+
1640
+ /* ============================================
1641
+ TotalEarnPoint Styles
1642
+ 与 Vue 版本 TotalEarnPoint.vue 样式一致
1643
+ ============================================ */
1644
+
1645
+ .taskon-task-item-total-earn {
1646
+ display: flex;
1647
+ align-items: center;
1648
+ }
1649
+
1650
+ .taskon-task-item-total-earn-text {
1651
+ color: var(--taskon-color-text-tertiary);
1652
+ font-size: var(--taskon-font-size);
1653
+ }
1654
+
1655
+ .taskon-task-item-total-earn-value {
1656
+ color: var(--taskon-color-primary);
1657
+ font-size: var(--taskon-font-size);
1658
+ margin: 0 4px;
1659
+ }
1660
+
1661
+ /* ============================================
1662
+ 第二行:内容区域(始终显示)
1663
+ ============================================ */
1664
+
1665
+ .taskon-task-item-body {
1666
+ margin-left: 36px;
1667
+ margin-top: 10px;
1668
+ }
1669
+
1670
+ .taskon-task-item-content {
1671
+ display: flex;
1672
+ flex-direction: column;
1673
+ gap: var(--taskon-spacing-md);
1674
+ }
1675
+
1676
+ .taskon-task-item-desc {
1677
+ font-size: var(--taskon-font-size);
1678
+ line-height: 1.5;
1679
+ color: var(--taskon-color-text-tertiary);
1680
+ word-break: break-word;
1681
+ white-space: pre-wrap;
1682
+ }
1683
+
1684
+ /* Description fields */
1685
+
1686
+ .taskon-task-item-fields {
1687
+ display: flex;
1688
+ flex-direction: column;
1689
+ gap: var(--taskon-spacing-xs);
1690
+ }
1691
+
1692
+ .taskon-task-item-field {
1693
+ display: flex;
1694
+ align-items: baseline;
1695
+ gap: var(--taskon-spacing-sm);
1696
+ font-size: var(--taskon-font-size-sm);
1697
+ }
1698
+
1699
+ .taskon-task-item-field-key {
1700
+ color: var(--taskon-color-text-disabled);
1701
+ flex-shrink: 0;
1702
+ }
1703
+
1704
+ .taskon-task-item-field-value {
1705
+ color: var(--taskon-color-text);
1706
+ word-break: break-all;
1707
+ }
1708
+
1709
+ .taskon-task-item-field-value--link {
1710
+ color: var(--taskon-color-link);
1711
+ text-decoration: underline;
1712
+ transition: opacity 0.2s ease;
1713
+ }
1714
+
1715
+ .taskon-task-item-field-value--link:hover {
1716
+ opacity: 0.8;
1717
+ }
1718
+
1719
+ /* Action link */
1720
+
1721
+ .taskon-task-item-action-link {
1722
+ display: inline-flex;
1723
+ align-items: center;
1724
+ padding: var(--taskon-spacing-sm) var(--taskon-spacing-md);
1725
+ font-size: var(--taskon-font-size-sm);
1726
+ font-weight: 500;
1727
+ color: var(--taskon-color-primary);
1728
+ background: transparent;
1729
+ border: 1px solid var(--taskon-color-primary);
1730
+ border-radius: var(--taskon-border-radius);
1731
+ text-decoration: none;
1732
+ transition: all 0.2s ease;
1733
+ align-self: flex-start;
1734
+ }
1735
+
1736
+ .taskon-task-item-action-link:hover {
1737
+ background: var(--taskon-color-primary);
1738
+ color: var(--taskon-color-text-on-primary);
1739
+ }
1740
+
1741
+ /* Spinner animation */
1742
+
1743
+ @keyframes taskon-spin {
1744
+ from {
1745
+ transform: rotate(0deg);
1746
+ }
1747
+ to {
1748
+ transform: rotate(360deg);
1749
+ }
1750
+ }
1751
+
1752
+ .taskon-task-item-spinner {
1753
+ animation: taskon-spin 1s linear infinite;
1754
+ }
1755
+
1756
+ /* ============================================
1757
+ TaskIcon Styles
1758
+ ============================================ */
1759
+
1760
+ .taskon-task-icon {
1761
+ display: inline-flex;
1197
1762
  align-items: center;
1198
- gap: var(--taskon-task-spacing-md);
1763
+ justify-content: center;
1199
1764
  flex-shrink: 0;
1200
- margin-left: 10px;
1201
1765
  }
1202
1766
 
1203
- /* Points display - 参考 TaskPoint.vue */
1204
- .taskon-task-item-points {
1205
- min-width: 40px;
1767
+ .taskon-task-icon-img {
1768
+ border-radius: 50%;
1769
+ object-fit: cover;
1770
+ }
1771
+
1772
+ /* ============================================
1773
+ CooldownTimer Styles
1774
+ ============================================ */
1775
+
1776
+ .taskon-cooldown-timer {
1777
+ display: inline-flex;
1778
+ align-items: center;
1779
+ gap: var(--taskon-spacing-xs);
1780
+ font-size: var(--taskon-font-size-sm);
1781
+ color: var(--taskon-color-warning);
1782
+ }
1783
+
1784
+ /* ============================================
1785
+ VerifyButton Styles
1786
+ ============================================ */
1787
+
1788
+ .taskon-verify-btn {
1789
+ display: inline-flex;
1790
+ align-items: center;
1791
+ justify-content: center;
1792
+ gap: var(--taskon-spacing-xs);
1206
1793
  height: 34px;
1207
- padding: 0 10px;
1794
+ padding: 0 var(--taskon-spacing-md);
1795
+ font-size: var(--taskon-font-size);
1796
+ font-weight: 500;
1797
+ line-height: 1.43;
1798
+ color: var(--taskon-color-text);
1799
+ background: transparent;
1800
+ border: 1px solid var(--taskon-color-border);
1801
+ border-radius: var(--taskon-border-radius);
1802
+ cursor: pointer;
1803
+ transition: all 0.2s ease;
1804
+ white-space: nowrap;
1805
+ flex-shrink: 0;
1806
+ }
1807
+
1808
+ .taskon-verify-btn:hover:not(:disabled) {
1809
+ border-color: var(--taskon-color-text-disabled);
1810
+ }
1811
+
1812
+ .taskon-verify-btn:disabled {
1813
+ opacity: 0.5;
1814
+ cursor: not-allowed;
1815
+ }
1816
+
1817
+ .taskon-verify-btn--loading {
1818
+ pointer-events: none;
1819
+ }
1820
+
1821
+ .taskon-verify-btn-spinner {
1822
+ width: 16px;
1823
+ height: 16px;
1824
+ animation: taskon-spin 1s linear infinite;
1825
+ }
1826
+
1827
+ /* ============================================
1828
+ ExpandableContent Styles
1829
+ ============================================ */
1830
+
1831
+ .taskon-expandable {
1208
1832
  display: flex;
1833
+ flex-direction: column;
1834
+ }
1835
+
1836
+ .taskon-expandable-content {
1837
+ position: relative;
1838
+ }
1839
+
1840
+ .taskon-expandable-toggle {
1841
+ display: inline-flex;
1209
1842
  align-items: center;
1210
- justify-content: center;
1211
- gap: 2px;
1212
- background: rgba(255, 255, 255, 0.04);
1213
- border-radius: 6px;
1214
- font-size: 16px;
1843
+ gap: var(--taskon-spacing-xs);
1844
+ padding: 0;
1845
+ margin-top: var(--taskon-spacing-sm);
1846
+ font-size: var(--taskon-font-size-sm);
1215
1847
  font-weight: 500;
1848
+ color: var(--taskon-color-text);
1849
+ background: transparent;
1850
+ border: none;
1851
+ cursor: pointer;
1852
+ transition: opacity 0.2s ease;
1853
+ align-self: flex-start;
1854
+ }
1855
+
1856
+ .taskon-expandable-toggle:hover {
1857
+ opacity: 0.8;
1858
+ }
1859
+
1860
+ .taskon-expandable-toggle-text {
1861
+ line-height: 1;
1862
+ }
1863
+
1864
+ .taskon-expandable-toggle-icon {
1865
+ transition: transform 0.2s ease;
1866
+ flex-shrink: 0;
1867
+ }
1868
+
1869
+ .taskon-expandable-toggle-icon--expanded {
1870
+ transform: rotate(180deg);
1871
+ }
1872
+
1873
+ /* ============================================
1874
+ Desktop 增强
1875
+ ============================================ */
1876
+
1877
+ @supports (container-type: inline-size) {
1878
+ @container (min-width: 751px) {
1879
+ .taskon-task-item {
1880
+ padding: 16px 20px;
1881
+ }
1882
+
1883
+ .taskon-task-item-row {
1884
+ align-items: center;
1885
+ gap: 0;
1886
+ }
1887
+
1888
+ .taskon-task-item-body {
1889
+ margin-left: 50px;
1890
+ }
1891
+
1892
+ .taskon-task-item-icon {
1893
+ margin-right: 16px;
1894
+ }
1895
+
1896
+ .taskon-task-item-right {
1897
+ flex-direction: row;
1898
+ align-items: center;
1899
+ gap: 6px;
1900
+ margin-left: 8px;
1901
+ }
1902
+ }
1903
+ }
1904
+
1905
+ @supports not (container-type: inline-size) {
1906
+ @media (min-width: 751px) {
1907
+ .taskon-task-item {
1908
+ padding: 16px 20px;
1909
+ }
1910
+
1911
+ .taskon-task-item-row {
1912
+ align-items: center;
1913
+ gap: 0;
1914
+ }
1915
+
1916
+ .taskon-task-item-body {
1917
+ margin-left: 50px;
1918
+ }
1919
+
1920
+ .taskon-task-item-icon {
1921
+ margin-right: 16px;
1922
+ }
1923
+
1924
+ .taskon-task-item-right {
1925
+ flex-direction: row;
1926
+ align-items: center;
1927
+ gap: 6px;
1928
+ margin-left: 8px;
1929
+ }
1930
+ }
1931
+ }
1932
+
1933
+ /* ============================================
1934
+ TimeRange Styles
1935
+ 与 Vue 版本 TimeRange.vue 样式一致
1936
+ ============================================ */
1937
+
1938
+ .taskon-task-time-range {
1939
+ font-size: var(--taskon-font-size);
1940
+ line-height: 1.29;
1941
+ margin-top: 14px;
1942
+ }
1943
+
1944
+ .taskon-task-time-range-label {
1945
+ color: var(--taskon-color-text-tertiary);
1946
+ }
1947
+
1948
+ .taskon-task-time-range-value {
1949
+ display: inline-block;
1950
+ color: var(--taskon-color-warning);
1951
+ }
1952
+
1953
+ /* ============================================
1954
+ VerifyButton Cooldown Progress Bar
1955
+ 与 Vue 版本 VerifyButton.vue 冷却进度条样式一致
1956
+ ============================================ */
1957
+
1958
+ .taskon-verify-btn-wrap {
1959
+ position: relative;
1960
+ display: inline-block;
1961
+ overflow: hidden;
1962
+ border-radius: var(--taskon-border-radius);
1963
+ }
1964
+
1965
+ .taskon-verify-btn-progress {
1966
+ position: absolute;
1967
+ bottom: 0;
1968
+ left: 0;
1969
+ right: 0;
1970
+ height: 3px;
1216
1971
  }
1217
1972
 
1218
- .taskon-task-item-points-value {
1219
- color: #ffffff;
1973
+ .taskon-verify-btn-progress-bar {
1974
+ height: 100%;
1975
+ border-radius: var(--taskon-border-radius);
1976
+ background: linear-gradient(
1977
+ to right,
1978
+ var(--taskon-color-primary),
1979
+ var(--taskon-color-secondary)
1980
+ );
1220
1981
  }
1982
+ /**
1983
+ * RewardModuleDialog styles
1984
+ * Scope UserCenter module styles inside Quest popup
1985
+ */
1221
1986
 
1222
- /* Points value when task is completed - green color like Vue version */
1223
- .taskon-task-item-points-value--completed {
1224
- color: #00ffa3;
1987
+ .taskon-quest-reward-dialog .taskon-user-center {
1988
+ padding: 32px 0 0 0;
1989
+ background: transparent;
1990
+ border-radius: 0;
1991
+ gap: 24px;
1225
1992
  }
1226
1993
 
1227
- .taskon-task-item-points-time {
1228
- font-size: 12px;
1229
- color: rgba(255, 255, 255, 0.6);
1994
+ .taskon-quest-reward-dialog .taskon-my-rewards {
1995
+ gap: 24px;
1230
1996
  }
1231
1997
 
1232
- /* Tip icon next to points (margin controlled externally) */
1233
- .taskon-task-item-tip {
1234
- margin-left: 10px;
1998
+ .taskon-quest-reward-dialog .taskon-my-rewards__section {
1999
+ gap: 16px;
1235
2000
  }
1236
2001
 
1237
- /* Total points */
1238
- .taskon-task-item-total-points {
1239
- font-size: 12px;
1240
- color: var(--taskon-task-text-muted);
2002
+ .taskon-quest-reward-dialog .taskon-points-list {
2003
+ background: transparent;
1241
2004
  }
2005
+ /**
2006
+ * BlindBox 盲盒组件样式
2007
+ * @module widgets/Quest/components/BlindBox/styles/blind-box.css
2008
+ *
2009
+ * Migrated from Vue version with Tailwind classes converted to CSS
2010
+ */
1242
2011
 
1243
- /* ============================================
1244
- TotalEarnPoint Styles
1245
- Vue 版本 TotalEarnPoint.vue 样式一致
1246
- ============================================ */
1247
- .taskon-task-item-total-earn {
2012
+ /*
2013
+ * Responsive base styles
2014
+ *
2015
+ * Keep mobile breakpoints and fallback patterns centralized here.
2016
+ * Components should reuse these mixins instead of duplicating query logic.
2017
+ */
2018
+
2019
+ /*
2020
+ * Desktop-up mixin:
2021
+ * 1) Enable desktop enhancement in wider containers
2022
+ * 2) Keep viewport media query as fallback
2023
+ */
2024
+
2025
+ /* ============================================================================
2026
+ BlindBox Dialog - 开盲盒交互弹窗
2027
+ ============================================================================ */
2028
+
2029
+ .taskon-quest-blindbox-dialog {
2030
+ container-type: inline-size;
2031
+ position: relative;
2032
+ width: min(520px, 92vw);
2033
+ min-height: 500px;
2034
+ padding: 24px var(--taskon-spacing-lg) 40px;
1248
2035
  display: flex;
2036
+ flex-direction: column;
1249
2037
  align-items: center;
2038
+ overflow: hidden;
1250
2039
  }
1251
2040
 
1252
- .taskon-task-item-total-earn-text {
1253
- color: rgba(255, 255, 255, 0.6);
1254
- font-size: 14px;
2041
+ .taskon-quest-blindbox-dialog-title {
2042
+ margin: 0;
2043
+ font-size: 32px;
2044
+ font-weight: 600;
2045
+ line-height: 1.25;
2046
+ color: #fff;
2047
+ text-align: center;
1255
2048
  }
1256
2049
 
1257
- .taskon-task-item-total-earn-value {
1258
- color: #9aff73;
1259
- font-size: 14px;
1260
- margin: 0 4px;
2050
+ .taskon-quest-blindbox-dialog-subtitle {
2051
+ margin: 12px 0 20px;
2052
+ font-size: var(--taskon-font-size-lg);
2053
+ line-height: 1.5;
2054
+ color: rgba(255, 255, 255, 0.7);
2055
+ text-align: center;
1261
2056
  }
1262
2057
 
1263
- /* ============================================
1264
- 第二行:内容区域(始终显示)
1265
- ============================================ */
1266
- .taskon-task-item-body {
1267
- margin-left: 50px;
1268
- margin-top: 10px;
1269
- }
2058
+ /* Stage container - centered square area for animation */
1270
2059
 
1271
- .taskon-task-item-content {
2060
+ .taskon-quest-blindbox-stage {
2061
+ position: relative;
1272
2062
  display: flex;
1273
- flex-direction: column;
1274
- gap: var(--taskon-task-spacing-md);
2063
+ align-items: center;
2064
+ justify-content: center;
2065
+ width: 100%;
2066
+ max-width: 420px;
2067
+ margin: 0 auto auto;
2068
+ aspect-ratio: 1;
2069
+ overflow: visible;
2070
+ border-radius: 32px;
2071
+ background: transparent;
1275
2072
  }
1276
2073
 
1277
- .taskon-task-item-desc {
1278
- font-size: 14px;
1279
- line-height: 21px;
1280
- color: var(--taskon-task-text-secondary);
1281
- word-break: break-all;
1282
- white-space: pre-wrap;
1283
- }
2074
+ /* Background spinning light */
1284
2075
 
1285
- .taskon-task-item-desc span {
1286
- color: var(--taskon-task-text);
1287
- word-break: break-all;
2076
+ .taskon-quest-blindbox-bg {
2077
+ position: absolute;
2078
+ left: 50%;
2079
+ top: calc(40% + 20px);
2080
+ width: min(80%, 340px);
2081
+ transform: translate(-50%, -50%);
2082
+ pointer-events: none;
2083
+ opacity: 0.75;
2084
+ animation: taskon-blindbox-spin 14s linear infinite;
1288
2085
  }
1289
2086
 
1290
- /* Rich text content - 参考 Vue 版本 TextPreview.vue */
1291
- .taskon-task-item-rich-text {
1292
- font-size: 14px;
1293
- line-height: 21px;
1294
- color: var(--taskon-task-text-secondary);
1295
- word-break: break-word;
2087
+ .taskon-quest-blindbox-bg img {
2088
+ width: 100%;
2089
+ height: auto;
1296
2090
  }
1297
2091
 
1298
- .taskon-task-item-rich-text p {
1299
- margin: 0 0 0.5em 0;
2092
+ @keyframes taskon-blindbox-spin {
2093
+ from {
2094
+ transform: translate(-50%, -50%) rotate(0deg);
2095
+ }
2096
+ to {
2097
+ transform: translate(-50%, -50%) rotate(360deg);
2098
+ }
1300
2099
  }
1301
2100
 
1302
- .taskon-task-item-rich-text p:last-child {
1303
- margin-bottom: 0;
1304
- }
2101
+ /* Drop zone - collision detection area */
1305
2102
 
1306
- .taskon-task-item-rich-text a {
1307
- color: #54aeff;
1308
- text-decoration: underline;
2103
+ .taskon-quest-blindbox-dropzone {
2104
+ position: absolute;
2105
+ left: 50%;
2106
+ top: calc(40% + 20px);
2107
+ width: min(33%, 145px);
2108
+ height: min(33%, 145px);
2109
+ transform: translate(-50%, -50%);
2110
+ pointer-events: none;
1309
2111
  }
1310
2112
 
1311
- .taskon-task-item-rich-text a:hover {
1312
- opacity: 0.8;
1313
- }
2113
+ /* Chest container */
1314
2114
 
1315
- .taskon-task-item-rich-text strong,
1316
- .taskon-task-item-rich-text b {
1317
- font-weight: 600;
1318
- color: var(--taskon-task-text);
2115
+ .taskon-quest-blindbox-chest {
2116
+ position: absolute;
2117
+ left: 50%;
2118
+ top: 40%;
2119
+ width: min(75%, 350px);
2120
+ height: auto;
2121
+ transform: translate(-50%, -50%);
2122
+ pointer-events: none;
2123
+ transition: filter 0.2s ease;
1319
2124
  }
1320
2125
 
1321
- .taskon-task-item-rich-text em,
1322
- .taskon-task-item-rich-text i {
1323
- font-style: italic;
2126
+ .taskon-quest-blindbox-chest--highlighted {
2127
+ filter: drop-shadow(0 0 16px rgba(233, 168, 30, 0.55));
1324
2128
  }
1325
2129
 
1326
- .taskon-task-item-rich-text ul,
1327
- .taskon-task-item-rich-text ol {
1328
- margin: 0.5em 0;
1329
- padding-left: 1.5em;
2130
+ .taskon-quest-blindbox-chest--open {
2131
+ filter: drop-shadow(0 0 22px rgba(255, 205, 112, 0.75));
1330
2132
  }
1331
2133
 
1332
- .taskon-task-item-rich-text li {
1333
- margin: 0.25em 0;
2134
+ /* Ensure Lottie SVG fills container */
2135
+
2136
+ .taskon-quest-blindbox-chest svg {
2137
+ width: 100% !important;
2138
+ height: auto !important;
1334
2139
  }
1335
2140
 
1336
- .taskon-task-item-rich-text code {
1337
- background: rgba(255, 255, 255, 0.1);
1338
- padding: 0.2em 0.4em;
1339
- border-radius: 3px;
1340
- font-size: 0.9em;
2141
+ /* Key image */
2142
+
2143
+ .taskon-quest-blindbox-key {
2144
+ position: absolute;
2145
+ width: clamp(80px, 25%, 100px);
2146
+ transform: translate(-50%, -50%);
2147
+ cursor: grab;
2148
+ touch-action: none;
2149
+ user-select: none;
2150
+ transition: transform 0.2s ease, filter 0.2s ease;
2151
+ pointer-events: auto;
1341
2152
  }
1342
2153
 
1343
- .taskon-task-item-rich-text pre {
1344
- background: rgba(255, 255, 255, 0.05);
1345
- padding: 0.75em 1em;
1346
- border-radius: 6px;
1347
- overflow-x: auto;
1348
- margin: 0.5em 0;
2154
+ .taskon-quest-blindbox-key--dragging {
2155
+ transform: translate(-50%, -50%) scale(1.04);
2156
+ cursor: grabbing;
1349
2157
  }
1350
2158
 
1351
- .taskon-task-item-rich-text blockquote {
1352
- border-left: 3px solid var(--taskon-color-primary);
1353
- padding-left: 1em;
1354
- margin: 0.5em 0;
1355
- color: var(--taskon-task-text-muted);
2159
+ .taskon-quest-blindbox-key--hovering {
2160
+ filter: drop-shadow(0 0 18px rgba(255, 211, 103, 0.8));
1356
2161
  }
1357
2162
 
1358
- .taskon-task-item-rich-text img {
1359
- max-width: 100%;
1360
- height: auto;
1361
- border-radius: 6px;
2163
+ .taskon-quest-blindbox-key--disabled {
2164
+ pointer-events: none;
2165
+ opacity: 0.6;
1362
2166
  }
1363
2167
 
1364
- /* Description fields */
1365
- .taskon-task-item-fields {
2168
+ /* ============================================================================
2169
+ BlindBox Reward Dialog - 奖励结果展示弹窗
2170
+ ============================================================================ */
2171
+
2172
+ .taskon-quest-blindbox-reward {
2173
+ container-type: inline-size;
2174
+ position: relative;
2175
+ width: min(520px, 92vw);
2176
+ min-height: 500px;
2177
+ padding: 24px var(--taskon-spacing-lg) 40px;
1366
2178
  display: flex;
1367
2179
  flex-direction: column;
1368
- gap: var(--taskon-task-spacing-xs);
2180
+ align-items: center;
2181
+ text-align: center;
2182
+ color: #fff;
2183
+ overflow: hidden;
1369
2184
  }
1370
2185
 
1371
- .taskon-task-item-field {
1372
- display: flex;
1373
- align-items: baseline;
1374
- gap: var(--taskon-task-spacing-sm);
1375
- font-size: 13px;
1376
- }
2186
+ /* Title */
1377
2187
 
1378
- .taskon-task-item-field-key {
1379
- color: var(--taskon-task-text-muted);
1380
- flex-shrink: 0;
2188
+ .taskon-quest-blindbox-reward-title {
2189
+ font-size: 32px;
2190
+ font-weight: 600;
2191
+ line-height: 1.25;
2192
+ margin: 0;
1381
2193
  }
1382
2194
 
1383
- .taskon-task-item-field-value {
1384
- color: var(--taskon-task-text);
1385
- word-break: break-all;
1386
- }
2195
+ /* Subtitle */
1387
2196
 
1388
- .taskon-task-item-field-value--link {
1389
- color: #54aeff;
1390
- text-decoration: underline;
1391
- transition: opacity var(--taskon-task-transition);
2197
+ .taskon-quest-blindbox-reward-subtitle {
2198
+ margin-top: 12px;
2199
+ margin-bottom: 0;
2200
+ font-size: var(--taskon-font-size-lg);
2201
+ line-height: 1.5;
2202
+ color: rgba(255, 255, 255, 0.7);
1392
2203
  }
1393
2204
 
1394
- .taskon-task-item-field-value--link:hover {
1395
- opacity: 0.8;
1396
- }
2205
+ /* Rewards container - Green border and background like Vue version */
1397
2206
 
1398
- /* Action link */
1399
- .taskon-task-item-action-link {
2207
+ .taskon-quest-blindbox-reward-list {
1400
2208
  display: inline-flex;
2209
+ flex-wrap: wrap;
2210
+ justify-content: center;
1401
2211
  align-items: center;
1402
- padding: var(--taskon-task-spacing-sm) var(--taskon-task-spacing-md);
1403
- font-size: 13px;
1404
- font-weight: 500;
1405
- color: var(--taskon-color-primary);
1406
- background: transparent;
1407
- border: 1px solid var(--taskon-color-primary);
1408
- border-radius: 6px;
1409
- text-decoration: none;
1410
- transition: all var(--taskon-task-transition);
1411
- align-self: flex-start;
2212
+ margin-top: 20px;
2213
+ gap: var(--taskon-spacing-sm);
2214
+ padding: 12px var(--taskon-spacing-md);
2215
+ border-radius: var(--taskon-border-radius);
2216
+ border: 1px solid rgba(60, 232, 155, 0.2);
2217
+ background: rgba(0, 255, 163, 0.1);
1412
2218
  }
1413
2219
 
1414
- .taskon-task-item-action-link:hover {
1415
- background: var(--taskon-color-primary);
1416
- color: white;
1417
- }
2220
+ /* Single reward card - transparent background */
1418
2221
 
1419
- /* Spinner animation */
1420
- @keyframes taskon-spin {
1421
- from {
1422
- transform: rotate(0deg);
1423
- }
1424
- to {
1425
- transform: rotate(360deg);
1426
- }
2222
+ .taskon-quest-blindbox-reward-card {
2223
+ display: flex;
2224
+ flex-direction: column;
2225
+ align-items: center;
2226
+ justify-content: center;
2227
+ padding: 12px var(--taskon-spacing-md);
2228
+ background: transparent;
2229
+ border-radius: 0;
2230
+ min-width: 60px;
2231
+ min-height: 80px;
2232
+ gap: var(--taskon-spacing-sm);
1427
2233
  }
1428
2234
 
1429
- .taskon-task-item-spinner {
1430
- animation: taskon-spin 1s linear infinite;
2235
+ .taskon-quest-blindbox-reward-card-icon {
2236
+ width: 32px;
2237
+ height: 32px;
2238
+ object-fit: contain;
2239
+ border-radius: 50%;
1431
2240
  }
1432
2241
 
1433
- /* ============================================
1434
- TaskIcon Styles
1435
- ============================================ */
1436
- .taskon-task-icon {
1437
- display: inline-flex;
1438
- align-items: center;
1439
- justify-content: center;
1440
- flex-shrink: 0;
2242
+ /* Token amount with orange color and underline like Vue version */
2243
+
2244
+ .taskon-quest-blindbox-reward-card-amount {
2245
+ font-size: var(--taskon-font-size-xl);
2246
+ font-weight: 600;
2247
+ color: #fbb15a;
2248
+ text-decoration: underline;
1441
2249
  }
1442
2250
 
1443
- .taskon-task-icon-img {
1444
- border-radius: 50%;
1445
- object-fit: cover;
2251
+ .taskon-quest-blindbox-reward-card-name {
2252
+ font-size: var(--taskon-font-size);
2253
+ color: #fbb15a;
2254
+ text-decoration: underline;
1446
2255
  }
1447
2256
 
1448
- /* ============================================
1449
- CooldownTimer Styles
1450
- ============================================ */
1451
- .taskon-cooldown-timer {
1452
- display: inline-flex;
1453
- align-items: center;
1454
- gap: var(--taskon-task-spacing-xs);
1455
- font-size: 13px;
1456
- color: var(--taskon-color-warning);
2257
+ .taskon-quest-blindbox-reward-card-value {
2258
+ font-size: var(--taskon-font-size-sm);
2259
+ color: rgba(255, 255, 255, 0.5);
2260
+ margin-top: 2px;
1457
2261
  }
1458
2262
 
1459
- /* ============================================
1460
- VerifyButton Styles
1461
- ============================================ */
1462
- .taskon-verify-btn {
1463
- display: inline-flex;
1464
- align-items: center;
2263
+ /* Back button */
2264
+
2265
+ .taskon-quest-blindbox-reward-btn-wrap {
2266
+ display: flex;
1465
2267
  justify-content: center;
1466
- gap: 4px;
1467
- height: 34px;
1468
- padding: 0 12px;
1469
- font-size: 14px;
2268
+ margin-top: auto;
2269
+ padding-top: 40px;
2270
+ }
2271
+
2272
+ /* Back button - matches Vue g-button--light-border */
2273
+
2274
+ .taskon-quest-blindbox-reward-btn {
2275
+ height: 36px;
2276
+ padding: 0 24px;
2277
+ font-size: var(--taskon-font-size);
1470
2278
  font-weight: 500;
1471
- line-height: 20px;
1472
2279
  color: #fff;
1473
2280
  background: transparent;
1474
- border: 1px solid rgba(255, 255, 255, 0.1);
1475
- border-radius: 6px;
2281
+ border: 1px solid #fff;
2282
+ border-radius: var(--taskon-border-radius);
1476
2283
  cursor: pointer;
1477
- transition: all var(--taskon-task-transition);
1478
- white-space: nowrap;
1479
- flex-shrink: 0;
2284
+ transition: opacity 0.2s ease;
1480
2285
  }
1481
2286
 
1482
- .taskon-verify-btn:hover:not(:disabled) {
1483
- border-color: rgba(255, 255, 255, 0.3);
2287
+ .taskon-quest-blindbox-reward-btn:hover {
2288
+ opacity: 0.8;
1484
2289
  }
1485
2290
 
1486
- .taskon-verify-btn:disabled {
2291
+ .taskon-quest-blindbox-reward-btn:disabled {
1487
2292
  opacity: 0.5;
1488
2293
  cursor: not-allowed;
1489
2294
  }
1490
2295
 
1491
- .taskon-verify-btn--loading {
1492
- pointer-events: none;
1493
- }
1494
-
1495
- .taskon-verify-btn-spinner {
1496
- width: 16px;
1497
- height: 16px;
1498
- animation: taskon-spin 1s linear infinite;
1499
- }
2296
+ /* ============================================================================
2297
+ OperateFooter - 开盲盒按钮
2298
+ ============================================================================ */
1500
2299
 
1501
- /* ============================================
1502
- ExpandableContent Styles
1503
- ============================================ */
1504
- .taskon-expandable {
2300
+ .taskon-quest-footer-blindbox-btn {
1505
2301
  display: flex;
1506
- flex-direction: column;
1507
- }
1508
-
1509
- .taskon-expandable-content {
1510
- position: relative;
1511
- }
1512
-
1513
- .taskon-expandable-toggle {
1514
- display: inline-flex;
1515
2302
  align-items: center;
1516
- gap: 4px;
1517
- padding: 0;
1518
- margin-top: 8px;
1519
- font-size: 13px;
1520
- font-weight: 500;
1521
- color: #ffffff;
1522
- background: transparent;
2303
+ justify-content: center;
2304
+ gap: 8px;
2305
+ width: 100%;
2306
+ padding: 14px 24px;
2307
+ font-size: var(--taskon-font-size-lg);
2308
+ font-weight: 600;
2309
+ color: #000;
2310
+ background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
1523
2311
  border: none;
2312
+ border-radius: var(--taskon-border-radius-lg);
1524
2313
  cursor: pointer;
1525
- transition: opacity var(--taskon-task-transition);
1526
- align-self: flex-start;
1527
- }
1528
-
1529
- .taskon-expandable-toggle:hover {
1530
- opacity: 0.8;
2314
+ transition: all 0.2s ease;
1531
2315
  }
1532
2316
 
1533
- .taskon-expandable-toggle-text {
1534
- line-height: 1;
2317
+ .taskon-quest-footer-blindbox-btn:hover {
2318
+ transform: translateY(-1px);
2319
+ box-shadow: 0 4px 16px rgba(255, 215, 0, 0.4);
1535
2320
  }
1536
2321
 
1537
- .taskon-expandable-toggle-icon {
1538
- transition: transform var(--taskon-task-transition);
1539
- flex-shrink: 0;
2322
+ .taskon-quest-footer-blindbox-btn:active {
2323
+ transform: translateY(0);
1540
2324
  }
1541
2325
 
1542
- .taskon-expandable-toggle-icon--expanded {
1543
- transform: rotate(180deg);
2326
+ .taskon-quest-footer-blindbox-btn-icon {
2327
+ width: 24px;
2328
+ height: 24px;
1544
2329
  }
1545
2330
 
1546
- /* ============================================
1547
- Responsive Styles
1548
- ============================================ */
1549
- @media (max-width: 750px) {
1550
- .taskon-task-item {
1551
- padding: 4vw;
2331
+ @supports (container-type: inline-size) {
2332
+ @container (min-width: 751px) {
2333
+ .taskon-quest-blindbox-dialog {
2334
+ min-height: 540px;
2335
+ padding: 32px 40px 48px;
1552
2336
  }
1553
2337
 
1554
- .taskon-task-item-body {
1555
- margin-left: 9.333vw;
2338
+ .taskon-quest-blindbox-dialog-subtitle {
2339
+ margin-bottom: 28px;
1556
2340
  }
1557
2341
 
1558
- .taskon-task-item-icon {
1559
- margin-right: 2.667vw;
2342
+ .taskon-quest-blindbox-reward {
2343
+ min-height: 540px;
2344
+ padding: 32px 40px 48px;
1560
2345
  }
1561
2346
 
1562
- .taskon-task-item-right {
1563
- margin-left: 2.67vw;
2347
+ .taskon-quest-blindbox-reward-btn-wrap {
2348
+ padding-top: 56px;
1564
2349
  }
1565
-
1566
- .taskon-task-item-title {
1567
- font-weight: 400;
1568
- font-size: 3.733vw;
1569
- line-height: 4.667vw;
2350
+ }
1570
2351
  }
1571
2352
 
1572
- .taskon-task-item-desc {
1573
- font-size: 3.2vw;
1574
- line-height: 4vw;
2353
+ @supports not (container-type: inline-size) {
2354
+ @media (min-width: 751px) {
2355
+ .taskon-quest-blindbox-dialog {
2356
+ min-height: 540px;
2357
+ padding: 32px 40px 48px;
1575
2358
  }
1576
2359
 
1577
- .taskon-task-icon-img {
1578
- width: 6.667vw !important;
1579
- height: 6.667vw !important;
2360
+ .taskon-quest-blindbox-dialog-subtitle {
2361
+ margin-bottom: 28px;
1580
2362
  }
1581
2363
 
1582
- /* Points display mobile - 参考 TaskPoint.vue */
1583
- .taskon-task-item-points {
1584
- min-width: 6.8vw;
1585
- height: 6.67vw;
1586
- padding: 0 2vw;
1587
- font-size: 2.93vw;
1588
- border-radius: 0.91vw;
2364
+ .taskon-quest-blindbox-reward {
2365
+ min-height: 540px;
2366
+ padding: 32px 40px 48px;
1589
2367
  }
1590
2368
 
1591
- .taskon-task-item-points-time {
1592
- font-size: 1.85vw;
2369
+ .taskon-quest-blindbox-reward-btn-wrap {
2370
+ padding-top: 56px;
1593
2371
  }
1594
- }
2372
+ }
2373
+ }
2374
+ /**
2375
+ * Eligibility (资格验证) 组件样式
2376
+ * @description Standalone CSS for EligibilityInfo component, usable in any widget context.
2377
+ */
1595
2378
 
1596
- /* ============================================
1597
- TimeRange Styles
1598
- Vue 版本 TimeRange.vue 样式一致
1599
- ============================================ */
1600
- .taskon-task-time-range {
1601
- font-size: 14px;
1602
- line-height: 18px;
1603
- margin-top: 14px;
2379
+ /*
2380
+ * Responsive base styles
2381
+ *
2382
+ * Keep mobile breakpoints and fallback patterns centralized here.
2383
+ * Components should reuse these mixins instead of duplicating query logic.
2384
+ */
2385
+
2386
+ /*
2387
+ * Desktop-up mixin:
2388
+ * 1) Enable desktop enhancement in wider containers
2389
+ * 2) Keep viewport media query as fallback
2390
+ */
2391
+
2392
+ /* ============================================================================
2393
+ Eligibility 主容器
2394
+ ============================================================================ */
2395
+
2396
+ .taskon-quest-eligs {
2397
+ container-type: inline-size;
2398
+ margin-top: var(--taskon-spacing-md);
2399
+ padding: 0 var(--taskon-spacing-md);
2400
+ border: 1px solid var(--taskon-color-border);
2401
+ border-radius: var(--taskon-border-radius-lg);
1604
2402
  }
1605
2403
 
1606
- .taskon-task-time-range-label {
1607
- color: var(--taskon-task-text-secondary);
2404
+ /* 动画效果 - 用于引导用户注意 */
2405
+
2406
+ .taskon-quest-eligs--animate {
2407
+ animation: taskon-quest-eligs-glow 800ms ease-out infinite alternate;
1608
2408
  }
1609
2409
 
1610
- .taskon-task-time-range-value {
1611
- display: inline-block;
1612
- color: rgba(255, 212, 101, 1);
2410
+ @keyframes taskon-quest-eligs-glow {
2411
+ 0% {
2412
+ border-color: var(--taskon-color-border);
2413
+ }
2414
+ 100% {
2415
+ border-color: var(--taskon-color-primary);
2416
+ }
1613
2417
  }
1614
2418
 
1615
- /* ============================================
1616
- VerifyButton Cooldown Progress Bar
1617
- Vue 版本 VerifyButton.vue 冷却进度条样式一致
1618
- ============================================ */
1619
- .taskon-verify-btn-wrap {
1620
- position: relative;
1621
- display: inline-block;
1622
- overflow: hidden;
1623
- border-radius: 6px;
2419
+ /* ============================================================================
2420
+ 折叠头部
2421
+ ============================================================================ */
2422
+
2423
+ .taskon-quest-eligs-header {
2424
+ height: 60px;
2425
+ display: flex;
2426
+ align-items: center;
2427
+ gap: 10px;
2428
+ font-size: var(--taskon-font-size-lg);
2429
+ line-height: 1.25;
2430
+ cursor: pointer;
2431
+ user-select: none;
1624
2432
  }
1625
2433
 
1626
- .taskon-verify-btn-progress {
1627
- position: absolute;
1628
- bottom: 0;
1629
- left: 0;
1630
- right: 0;
1631
- height: 3px;
2434
+ .taskon-quest-eligs-header:hover {
2435
+ opacity: 0.9;
1632
2436
  }
1633
2437
 
1634
- .taskon-verify-btn-progress-bar {
1635
- height: 100%;
1636
- border-radius: 6px;
1637
- background: linear-gradient(to right, #cbff01, #00ffa3);
2438
+ /* 状态图标 */
2439
+
2440
+ .taskon-quest-eligs-header-status {
2441
+ flex-shrink: 0;
1638
2442
  }
1639
- /**
1640
- * BlindBox 盲盒组件样式
1641
- * @module widgets/Quest/components/BlindBox/styles/blind-box.css
1642
- *
1643
- * Migrated from Vue version with Tailwind classes converted to CSS
1644
- */
1645
2443
 
1646
- /* ============================================================================
1647
- BlindBox Dialog - 开盲盒交互弹窗
1648
- ============================================================================ */
2444
+ /* 头部文本 */
1649
2445
 
1650
- .taskon-quest-blindbox-dialog {
1651
- position: relative;
1652
- width: min(520px, 92vw);
1653
- overflow: hidden;
1654
- padding-top: 40px;
2446
+ .taskon-quest-eligs-header-text {
2447
+ flex: 1;
2448
+ color: var(--taskon-color-text);
1655
2449
  }
1656
2450
 
1657
- .taskon-quest-blindbox-dialog-title {
1658
- margin: 0 0 16px;
1659
- padding: 0 40px;
1660
- font-size: 22px;
1661
- font-weight: 600;
1662
- line-height: 1.4;
1663
- color: #fff;
2451
+ /* 高亮表达式 (all/any) */
2452
+
2453
+ .taskon-quest-eligs-header-express {
2454
+ color: var(--taskon-color-secondary);
1664
2455
  }
1665
2456
 
1666
- /* Stage container - centered square area for animation */
1667
- .taskon-quest-blindbox-stage {
1668
- position: relative;
2457
+ /* ============================================================================
2458
+ 刷新按钮
2459
+ ============================================================================ */
2460
+
2461
+ .taskon-quest-eligs-refresh {
1669
2462
  display: flex;
1670
2463
  align-items: center;
1671
2464
  justify-content: center;
1672
- width: 100%;
1673
- max-width: 420px;
1674
- margin: 0 auto;
1675
- aspect-ratio: 1;
1676
- overflow: visible;
1677
- border-radius: 32px;
2465
+ width: 32px;
2466
+ height: 32px;
2467
+ padding: 0;
2468
+ margin-left: auto;
1678
2469
  background: transparent;
2470
+ border: 1px solid var(--taskon-color-border);
2471
+ border-radius: var(--taskon-border-radius-sm);
2472
+ color: var(--taskon-color-text-secondary);
2473
+ cursor: pointer;
2474
+ transition: all 0.2s;
1679
2475
  }
1680
2476
 
1681
- /* Background spinning light */
1682
- .taskon-quest-blindbox-bg {
1683
- position: absolute;
1684
- left: 50%;
1685
- top: calc(40% + 20px);
1686
- width: min(80%, 340px);
1687
- transform: translate(-50%, -50%);
1688
- pointer-events: none;
1689
- opacity: 0.75;
1690
- animation: taskon-blindbox-spin 14s linear infinite;
2477
+ .taskon-quest-eligs-refresh:hover:not(:disabled) {
2478
+ border-color: var(--taskon-color-text-tertiary);
2479
+ color: var(--taskon-color-text);
1691
2480
  }
1692
2481
 
1693
- .taskon-quest-blindbox-bg img {
1694
- width: 100%;
1695
- height: auto;
2482
+ .taskon-quest-eligs-refresh:disabled {
2483
+ opacity: 0.5;
2484
+ cursor: not-allowed;
1696
2485
  }
1697
2486
 
1698
- @keyframes taskon-blindbox-spin {
1699
- from {
1700
- transform: translate(-50%, -50%) rotate(0deg);
1701
- }
2487
+ .taskon-quest-eligs-refresh--loading .taskon-quest-eligs-refresh-icon {
2488
+ animation: taskon-quest-eligs-spin 1s linear infinite;
2489
+ }
2490
+
2491
+ @keyframes taskon-quest-eligs-spin {
1702
2492
  to {
1703
- transform: translate(-50%, -50%) rotate(360deg);
2493
+ transform: rotate(360deg);
1704
2494
  }
1705
2495
  }
1706
2496
 
1707
- /* Drop zone - collision detection area */
1708
- .taskon-quest-blindbox-dropzone {
1709
- position: absolute;
1710
- left: 50%;
1711
- top: calc(40% + 20px);
1712
- width: min(33%, 145px);
1713
- height: min(33%, 145px);
1714
- transform: translate(-50%, -50%);
1715
- pointer-events: none;
2497
+ /* ============================================================================
2498
+ 箭头图标
2499
+ ============================================================================ */
2500
+
2501
+ .taskon-quest-eligs-header-arrow {
2502
+ flex-shrink: 0;
2503
+ width: 6px;
2504
+ height: 10px;
2505
+ color: var(--taskon-color-text-secondary);
2506
+ transform: rotate(90deg);
2507
+ transition: transform 0.3s;
2508
+ }
2509
+
2510
+ .taskon-quest-eligs-header-arrow--expanded {
2511
+ transform: rotate(-90deg);
2512
+ }
2513
+
2514
+ /* ============================================================================
2515
+ 列表
2516
+ ============================================================================ */
2517
+
2518
+ .taskon-quest-eligs-list {
2519
+ text-align: left;
2520
+ padding: var(--taskon-spacing-md) 0;
2521
+ margin: 0;
2522
+ list-style: none;
2523
+ border-top: 1px solid var(--taskon-color-border);
2524
+ }
2525
+
2526
+ /* 单项 */
2527
+
2528
+ .taskon-quest-eligs-item {
2529
+ line-height: 18px;
2530
+ }
2531
+
2532
+ .taskon-quest-eligs-item + .taskon-quest-eligs-item {
2533
+ margin-top: var(--taskon-spacing-md);
1716
2534
  }
1717
2535
 
1718
- /* Chest container */
1719
- .taskon-quest-blindbox-chest {
1720
- position: absolute;
1721
- left: 50%;
1722
- top: 40%;
1723
- width: min(75%, 350px);
1724
- height: auto;
1725
- transform: translate(-50%, -50%);
1726
- pointer-events: none;
1727
- transition: filter 0.2s ease;
2536
+ .taskon-quest-eligs-item-container {
2537
+ display: flex;
2538
+ align-items: flex-start;
1728
2539
  }
1729
2540
 
1730
- .taskon-quest-blindbox-chest--highlighted {
1731
- filter: drop-shadow(0 0 16px rgba(233, 168, 30, 0.55));
2541
+ /* 状态图标 */
2542
+
2543
+ .taskon-quest-eligs-item-icon {
2544
+ flex-shrink: 0;
2545
+ margin-right: var(--taskon-spacing-sm);
2546
+ margin-top: var(--taskon-spacing-xs);
2547
+ opacity: 0;
1732
2548
  }
1733
2549
 
1734
- .taskon-quest-blindbox-chest--open {
1735
- filter: drop-shadow(0 0 22px rgba(255, 205, 112, 0.75));
2550
+ .taskon-quest-eligs-item-icon-placeholder {
2551
+ flex-shrink: 0;
2552
+ width: 16px;
2553
+ height: 16px;
2554
+ margin-right: var(--taskon-spacing-sm);
2555
+ margin-top: var(--taskon-spacing-xs);
1736
2556
  }
1737
2557
 
1738
- /* Ensure Lottie SVG fills container */
1739
- .taskon-quest-blindbox-chest svg {
1740
- width: 100% !important;
1741
- height: auto !important;
2558
+ .taskon-quest-eligs-item--passed .taskon-quest-eligs-item-icon,
2559
+ .taskon-quest-eligs-item--failed .taskon-quest-eligs-item-icon {
2560
+ opacity: 1;
1742
2561
  }
1743
2562
 
1744
- /* Key image */
1745
- .taskon-quest-blindbox-key {
1746
- position: absolute;
1747
- width: clamp(80px, 16vw, 100px);
1748
- transform: translate(-50%, -50%);
1749
- cursor: grab;
1750
- touch-action: none;
1751
- user-select: none;
1752
- transition: transform 0.2s ease, filter 0.2s ease;
1753
- pointer-events: auto;
2563
+ .taskon-quest-eligs-item-icon--passed {
2564
+ color: var(--taskon-color-success);
1754
2565
  }
1755
2566
 
1756
- .taskon-quest-blindbox-key--dragging {
1757
- transform: translate(-50%, -50%) scale(1.04);
1758
- cursor: grabbing;
2567
+ .taskon-quest-eligs-item-icon--failed {
2568
+ color: var(--taskon-color-error);
1759
2569
  }
1760
2570
 
1761
- .taskon-quest-blindbox-key--hovering {
1762
- filter: drop-shadow(0 0 18px rgba(255, 211, 103, 0.8));
2571
+ .taskon-quest-eligs-header-status--passed {
2572
+ color: var(--taskon-color-success);
1763
2573
  }
1764
2574
 
1765
- .taskon-quest-blindbox-key--disabled {
1766
- pointer-events: none;
1767
- opacity: 0.6;
2575
+ .taskon-quest-eligs-header-status--failed {
2576
+ color: var(--taskon-color-error);
2577
+ }
2578
+
2579
+ /* 内容区 */
2580
+
2581
+ .taskon-quest-eligs-item-content {
2582
+ flex: 1;
2583
+ font-size: var(--taskon-font-size);
2584
+ line-height: 1.29;
2585
+ color: var(--taskon-color-text-secondary);
1768
2586
  }
1769
2587
 
1770
2588
  /* ============================================================================
1771
- BlindBox Reward Dialog - 奖励结果展示弹窗
2589
+ 类型组件样式
1772
2590
  ============================================================================ */
1773
2591
 
1774
- .taskon-quest-blindbox-reward {
2592
+ .taskon-quest-eligs-type {
2593
+ color: var(--taskon-color-text-secondary);
2594
+ }
2595
+
2596
+ .taskon-quest-eligs-type--tooltip {
1775
2597
  position: relative;
1776
- width: 510px;
1777
- max-width: 92vw;
1778
- padding: 64px 40px;
1779
- text-align: center;
1780
- color: #fff;
1781
- overflow: hidden;
2598
+ cursor: help;
1782
2599
  }
1783
2600
 
1784
- /* Light background effect */
1785
- .taskon-quest-blindbox-reward-light {
1786
- position: absolute;
1787
- top: 0;
1788
- left: 50%;
1789
- width: 120%;
1790
- max-width: none;
1791
- transform: translateX(-50%);
1792
- object-fit: contain;
1793
- pointer-events: none;
1794
- opacity: 0;
1795
- animation: taskon-blindbox-light-appear 2s ease-out forwards;
2601
+ /* 高亮文本 */
2602
+
2603
+ .taskon-quest-eligs-highlight {
2604
+ color: var(--taskon-color-primary);
1796
2605
  }
1797
2606
 
1798
- @keyframes taskon-blindbox-light-appear {
1799
- to {
1800
- opacity: 1;
1801
- }
2607
+ /* 链接样式 */
2608
+
2609
+ .taskon-quest-eligs-link {
2610
+ color: var(--taskon-color-link);
2611
+ text-decoration: underline;
1802
2612
  }
1803
2613
 
1804
- /* Title */
1805
- .taskon-quest-blindbox-reward-title {
1806
- font-size: 32px;
1807
- font-weight: 600;
1808
- line-height: 40px;
1809
- margin: 0;
2614
+ .taskon-quest-eligs-link:hover {
2615
+ opacity: 0.8;
1810
2616
  }
1811
2617
 
1812
- /* Subtitle */
1813
- .taskon-quest-blindbox-reward-subtitle {
1814
- margin-top: 12px;
1815
- font-size: 16px;
1816
- line-height: 1.5;
1817
- color: rgba(255, 255, 255, 0.7);
2618
+ /* Tooltip */
2619
+
2620
+ .taskon-quest-eligs-tooltip {
2621
+ position: absolute;
2622
+ top: 100%;
2623
+ left: 0;
2624
+ z-index: 10;
2625
+ margin-top: 4px;
2626
+ padding: 8px 12px;
2627
+ max-width: 300px;
2628
+ font-size: var(--taskon-font-size-sm);
2629
+ line-height: 1.33;
2630
+ color: var(--taskon-color-text);
2631
+ background-color: var(--taskon-color-bg-floating);
2632
+ border-radius: var(--taskon-border-radius-sm);
2633
+ box-shadow: 0 2px 8px var(--taskon-color-bg-mask);
2634
+ white-space: normal;
2635
+ word-break: break-word;
1818
2636
  }
1819
2637
 
1820
- /* Rewards container - Green border and background like Vue version */
1821
- .taskon-quest-blindbox-reward-list {
1822
- display: inline-flex;
1823
- flex-wrap: wrap;
1824
- justify-content: center;
1825
- align-items: center;
1826
- margin-top: 24px;
1827
- gap: 8px;
1828
- padding: 12px 16px;
1829
- border-radius: 8px;
1830
- border: 1px solid rgba(60, 232, 155, 0.2);
1831
- background: rgba(0, 255, 163, 0.1);
2638
+ /* ============================================================================
2639
+ 子条件容器
2640
+ ============================================================================ */
2641
+
2642
+ .taskon-quest-eligs-sub {
2643
+ width: 100%;
1832
2644
  }
1833
2645
 
1834
- /* Single reward card - transparent background */
1835
- .taskon-quest-blindbox-reward-card {
2646
+ .taskon-quest-eligs-sub-header {
1836
2647
  display: flex;
1837
- flex-direction: column;
1838
2648
  align-items: center;
1839
- justify-content: center;
1840
- padding: 12px 16px;
1841
- background: transparent;
1842
- border-radius: 0;
1843
- min-width: 60px;
1844
- min-height: 80px;
1845
- gap: 8px;
2649
+ justify-content: space-between;
2650
+ font-weight: 600;
2651
+ cursor: pointer;
1846
2652
  }
1847
2653
 
1848
- .taskon-quest-blindbox-reward-card-icon {
1849
- width: 32px;
1850
- height: 32px;
1851
- object-fit: contain;
1852
- border-radius: 50%;
2654
+ .taskon-quest-eligs-sub-header:hover {
2655
+ opacity: 0.9;
1853
2656
  }
1854
2657
 
1855
- /* Token amount with orange color and underline like Vue version */
1856
- .taskon-quest-blindbox-reward-card-amount {
1857
- font-size: 18px;
1858
- font-weight: 600;
1859
- color: #fbb15a;
1860
- text-decoration: underline;
2658
+ .taskon-quest-eligs-sub-label {
2659
+ flex: 1;
1861
2660
  }
1862
2661
 
1863
- .taskon-quest-blindbox-reward-card-name {
1864
- font-size: 14px;
1865
- color: #fbb15a;
1866
- text-decoration: underline;
2662
+ .taskon-quest-eligs-sub-arrow {
2663
+ flex-shrink: 0;
2664
+ width: 8px;
2665
+ height: 8px;
2666
+ color: var(--taskon-color-text-secondary);
2667
+ transform: rotate(-90deg);
2668
+ transition: transform 0.3s;
1867
2669
  }
1868
2670
 
1869
- .taskon-quest-blindbox-reward-card-value {
1870
- font-size: 12px;
1871
- color: rgba(255, 255, 255, 0.5);
1872
- margin-top: 2px;
2671
+ .taskon-quest-eligs-sub-arrow--expanded {
2672
+ transform: rotate(90deg);
1873
2673
  }
1874
2674
 
1875
- /* Back button */
1876
- .taskon-quest-blindbox-reward-btn-wrap {
2675
+ .taskon-quest-eligs-sub-list {
2676
+ margin-top: 10px;
2677
+ padding-left: 14px;
2678
+ list-style: disc;
1877
2679
  display: flex;
1878
- justify-content: center;
1879
- margin-top: 60px;
2680
+ flex-direction: column;
2681
+ gap: 8px;
1880
2682
  }
1881
2683
 
1882
- /* Back button - matches Vue g-button--light-border */
1883
- .taskon-quest-blindbox-reward-btn {
1884
- height: 36px;
1885
- padding: 0 24px;
1886
- font-size: 14px;
1887
- font-weight: 500;
1888
- color: #fff;
1889
- background: transparent;
1890
- border: 1px solid #fff;
1891
- border-radius: 8px;
1892
- cursor: pointer;
1893
- transition: opacity 0.2s ease;
2684
+ .taskon-quest-eligs-sub-list li {
2685
+ font-size: var(--taskon-font-size);
2686
+ line-height: 1.29;
2687
+ color: var(--taskon-color-text-secondary);
1894
2688
  }
1895
2689
 
1896
- .taskon-quest-blindbox-reward-btn:hover {
1897
- opacity: 0.8;
1898
- }
2690
+ @supports (container-type: inline-size) {
2691
+ @container (min-width: 751px) {
2692
+ .taskon-quest-eligs {
2693
+ margin-top: var(--taskon-spacing-lg);
2694
+ padding: 0 var(--taskon-spacing-md);
2695
+ }
1899
2696
 
1900
- .taskon-quest-blindbox-reward-btn:disabled {
1901
- opacity: 0.5;
1902
- cursor: not-allowed;
1903
- }
2697
+ .taskon-quest-eligs-list {
2698
+ padding: 20px 0;
2699
+ }
2700
+
2701
+ .taskon-quest-eligs-item + .taskon-quest-eligs-item {
2702
+ margin-top: var(--taskon-spacing-lg);
2703
+ }
2704
+
2705
+ .taskon-quest-eligs-item-icon,
2706
+ .taskon-quest-eligs-item-icon-placeholder {
2707
+ margin-top: var(--taskon-spacing-xs);
2708
+ margin-right: var(--taskon-spacing-sm);
2709
+ }
2710
+ }
2711
+ }
2712
+
2713
+ @supports not (container-type: inline-size) {
2714
+ @media (min-width: 751px) {
2715
+ .taskon-quest-eligs {
2716
+ margin-top: var(--taskon-spacing-lg);
2717
+ padding: 0 var(--taskon-spacing-md);
2718
+ }
2719
+
2720
+ .taskon-quest-eligs-list {
2721
+ padding: 20px 0;
2722
+ }
2723
+
2724
+ .taskon-quest-eligs-item + .taskon-quest-eligs-item {
2725
+ margin-top: var(--taskon-spacing-lg);
2726
+ }
2727
+
2728
+ .taskon-quest-eligs-item-icon,
2729
+ .taskon-quest-eligs-item-icon-placeholder {
2730
+ margin-top: var(--taskon-spacing-xs);
2731
+ margin-right: var(--taskon-spacing-sm);
2732
+ }
2733
+ }
2734
+ }
1904
2735
 
1905
2736
  /* ============================================================================
1906
- OperateFooter - 开盲盒按钮
2737
+ OnChainVerify Tooltip Styles
1907
2738
  ============================================================================ */
1908
2739
 
1909
- .taskon-quest-footer-blindbox-btn {
1910
- display: flex;
1911
- align-items: center;
1912
- justify-content: center;
1913
- gap: 8px;
1914
- width: 100%;
1915
- padding: 14px 24px;
1916
- font-size: 16px;
1917
- font-weight: 600;
1918
- color: #000;
1919
- background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
1920
- border: none;
1921
- border-radius: 12px;
2740
+ .taskon-quest-eligs-onchain-item {
2741
+ display: inline;
2742
+ }
2743
+
2744
+ .taskon-quest-eligs-onchain-link {
2745
+ position: relative;
2746
+ display: inline;
2747
+ text-decoration: underline;
1922
2748
  cursor: pointer;
1923
- transition: all 0.2s ease;
2749
+ color: var(--taskon-color-text);
1924
2750
  }
1925
2751
 
1926
- .taskon-quest-footer-blindbox-btn:hover {
1927
- transform: translateY(-1px);
1928
- box-shadow: 0 4px 16px rgba(255, 215, 0, 0.4);
2752
+ .taskon-quest-eligs-onchain-link:hover {
2753
+ color: var(--taskon-color-link);
1929
2754
  }
1930
2755
 
1931
- .taskon-quest-footer-blindbox-btn:active {
1932
- transform: translateY(0);
2756
+ .taskon-quest-eligs-onchain-tooltip {
2757
+ position: absolute;
2758
+ bottom: calc(100% + 8px);
2759
+ left: 0;
2760
+ min-width: 260px;
2761
+ padding: 12px 16px;
2762
+ background-color: var(--taskon-color-bg-surface);
2763
+ border: 1px solid var(--taskon-color-border);
2764
+ border-radius: var(--taskon-border-radius);
2765
+ box-shadow: 0 4px 16px var(--taskon-color-bg-mask);
2766
+ z-index: 100;
2767
+ font-size: var(--taskon-font-size);
2768
+ line-height: 1.5;
1933
2769
  }
1934
2770
 
1935
- .taskon-quest-footer-blindbox-btn-icon {
1936
- width: 24px;
1937
- height: 24px;
2771
+ .taskon-quest-eligs-onchain-tooltip::before {
2772
+ content: "";
2773
+ position: absolute;
2774
+ bottom: -6px;
2775
+ left: 16px;
2776
+ width: 12px;
2777
+ height: 12px;
2778
+ background-color: var(--taskon-color-bg-surface);
2779
+ border-right: 1px solid var(--taskon-color-border);
2780
+ border-bottom: 1px solid var(--taskon-color-border);
2781
+ transform: rotate(45deg);
2782
+ }
2783
+
2784
+ .taskon-quest-eligs-onchain-tooltip p {
2785
+ margin: 0 0 8px 0;
2786
+ color: var(--taskon-color-text-secondary);
2787
+ }
2788
+
2789
+ .taskon-quest-eligs-onchain-tooltip ul {
2790
+ margin: 0;
2791
+ padding: 0;
2792
+ list-style: disc;
2793
+ list-style-position: inside;
2794
+ }
2795
+
2796
+ .taskon-quest-eligs-onchain-tooltip ul li {
2797
+ margin: 4px 0;
2798
+ }
2799
+
2800
+ .taskon-quest-eligs-onchain-tooltip-link {
2801
+ color: var(--taskon-color-link);
2802
+ text-decoration: underline;
2803
+ font-size: var(--taskon-font-size);
2804
+ line-height: 1.29;
2805
+ }
2806
+
2807
+ .taskon-quest-eligs-onchain-tooltip-link:hover {
2808
+ color: var(--taskon-color-text);
1938
2809
  }
1939
2810
 
1940
2811
  /* ============================================================================
1941
- Mobile Responsive
2812
+ Poh / NFT / Copy Styles
1942
2813
  ============================================================================ */
1943
2814
 
1944
- @media (max-width: 768px) {
1945
- .taskon-quest-blindbox-dialog {
1946
- padding-top: 24px;
1947
- }
2815
+ .taskon-quest-eligs-poh-provider {
2816
+ font-weight: 500;
2817
+ }
1948
2818
 
1949
- .taskon-quest-blindbox-dialog-title {
1950
- padding: 0 24px;
1951
- font-size: 18px;
1952
- }
2819
+ .taskon-quest-eligs-nft-name {
2820
+ position: relative;
2821
+ display: inline;
2822
+ color: var(--taskon-color-secondary);
2823
+ cursor: pointer;
2824
+ text-decoration: underline;
2825
+ }
1953
2826
 
1954
- .taskon-quest-blindbox-reward {
1955
- padding: 48px 24px;
1956
- }
2827
+ .taskon-quest-eligs-nft-name:hover {
2828
+ color: var(--taskon-color-link);
2829
+ }
1957
2830
 
1958
- .taskon-quest-blindbox-reward-title {
1959
- font-size: 24px;
1960
- line-height: 32px;
1961
- }
2831
+ .taskon-quest-eligs-copied {
2832
+ position: absolute;
2833
+ bottom: calc(100% + 4px);
2834
+ left: 50%;
2835
+ transform: translateX(-50%);
2836
+ padding: 4px 8px;
2837
+ background-color: var(--taskon-color-bg-surface);
2838
+ border-radius: var(--taskon-border-radius-sm);
2839
+ font-size: var(--taskon-font-size-sm);
2840
+ color: var(--taskon-color-secondary);
2841
+ white-space: nowrap;
2842
+ pointer-events: none;
2843
+ animation: taskon-quest-eligs-fade-in 0.2s ease-out;
2844
+ }
1962
2845
 
1963
- .taskon-quest-blindbox-reward-btn-wrap {
1964
- margin-top: 40px;
2846
+ @keyframes taskon-quest-eligs-fade-in {
2847
+ from {
2848
+ opacity: 0;
2849
+ transform: translateX(-50%) translateY(4px);
2850
+ }
2851
+ to {
2852
+ opacity: 1;
2853
+ transform: translateX(-50%) translateY(0);
1965
2854
  }
1966
2855
  }