codexmate 0.0.41 → 0.0.43

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 (155) hide show
  1. package/README.md +168 -168
  2. package/README.zh.md +168 -168
  3. package/cli/agents-files.js +230 -230
  4. package/cli/analytics-export-args.js +68 -68
  5. package/cli/archive-helpers.js +453 -453
  6. package/cli/auth-profiles.js +375 -375
  7. package/cli/builtin-proxy.js +2144 -2144
  8. package/cli/claude-proxy.js +1022 -1022
  9. package/cli/config-bootstrap.js +407 -407
  10. package/cli/config-health.js +454 -454
  11. package/cli/doctor-core.js +903 -903
  12. package/cli/import-skills-url.js +356 -356
  13. package/cli/local-bridge.js +556 -556
  14. package/cli/openai-bridge.js +1984 -1984
  15. package/cli/openclaw-config.js +629 -629
  16. package/cli/session-convert-args.js +69 -69
  17. package/cli/session-convert-io.js +82 -82
  18. package/cli/session-convert.js +150 -150
  19. package/cli/session-usage.concurrent.js +28 -28
  20. package/cli/session-usage.js +304 -304
  21. package/cli/session-usage.models.js +176 -176
  22. package/cli/skills.js +1141 -1141
  23. package/cli/update.js +171 -171
  24. package/cli/zip-commands.js +510 -510
  25. package/cli.js +16495 -16458
  26. package/lib/automation.js +404 -404
  27. package/lib/cli-file-utils.js +151 -151
  28. package/lib/cli-models-utils.js +440 -440
  29. package/lib/cli-network-utils.js +190 -190
  30. package/lib/cli-path-utils.js +85 -85
  31. package/lib/cli-session-utils.js +121 -121
  32. package/lib/cli-sessions.js +427 -427
  33. package/lib/cli-utils.js +155 -155
  34. package/lib/cli-webhook.js +154 -154
  35. package/lib/download-artifacts.js +92 -92
  36. package/lib/mcp-stdio.js +453 -453
  37. package/lib/task-orchestrator.js +869 -869
  38. package/lib/text-diff.js +303 -303
  39. package/lib/win-tray.js +119 -119
  40. package/lib/workflow-engine.js +340 -340
  41. package/package.json +77 -77
  42. package/plugins/README.md +20 -20
  43. package/plugins/README.zh-CN.md +20 -20
  44. package/plugins/prompt-templates/comment-polish/index.mjs +25 -25
  45. package/plugins/prompt-templates/computed.mjs +311 -311
  46. package/plugins/prompt-templates/index.mjs +8 -8
  47. package/plugins/prompt-templates/manifest.mjs +18 -18
  48. package/plugins/prompt-templates/methods.mjs +553 -553
  49. package/plugins/prompt-templates/overview.mjs +91 -91
  50. package/plugins/prompt-templates/ownership.mjs +19 -19
  51. package/plugins/prompt-templates/rule-ack/index.mjs +21 -21
  52. package/plugins/prompt-templates/storage.mjs +64 -64
  53. package/plugins/registry.mjs +16 -16
  54. package/web-ui/app.js +705 -695
  55. package/web-ui/index.html +37 -37
  56. package/web-ui/logic.agents-diff.mjs +386 -386
  57. package/web-ui/logic.claude.mjs +172 -172
  58. package/web-ui/logic.codex.mjs +69 -69
  59. package/web-ui/logic.mjs +5 -5
  60. package/web-ui/logic.runtime.mjs +128 -128
  61. package/web-ui/logic.session-convert.mjs +70 -70
  62. package/web-ui/logic.sessions.mjs +782 -782
  63. package/web-ui/modules/api.mjs +90 -90
  64. package/web-ui/modules/app.computed.dashboard.mjs +252 -252
  65. package/web-ui/modules/app.computed.index.mjs +17 -17
  66. package/web-ui/modules/app.computed.main-tabs.mjs +214 -214
  67. package/web-ui/modules/app.computed.session.mjs +876 -876
  68. package/web-ui/modules/app.constants.mjs +15 -15
  69. package/web-ui/modules/app.methods.agents.mjs +651 -651
  70. package/web-ui/modules/app.methods.claude-config.mjs +412 -412
  71. package/web-ui/modules/app.methods.codex-config.mjs +869 -869
  72. package/web-ui/modules/app.methods.index.mjs +96 -96
  73. package/web-ui/modules/app.methods.install.mjs +205 -205
  74. package/web-ui/modules/app.methods.navigation.mjs +804 -804
  75. package/web-ui/modules/app.methods.openclaw-core.mjs +814 -814
  76. package/web-ui/modules/app.methods.openclaw-editing.mjs +420 -420
  77. package/web-ui/modules/app.methods.openclaw-persist.mjs +375 -375
  78. package/web-ui/modules/app.methods.providers.mjs +602 -601
  79. package/web-ui/modules/app.methods.runtime.mjs +426 -420
  80. package/web-ui/modules/app.methods.session-actions.mjs +617 -591
  81. package/web-ui/modules/app.methods.session-browser.mjs +1018 -1018
  82. package/web-ui/modules/app.methods.session-timeline.mjs +479 -479
  83. package/web-ui/modules/app.methods.session-trash.mjs +468 -468
  84. package/web-ui/modules/app.methods.startup-claude.mjs +557 -554
  85. package/web-ui/modules/app.methods.task-orchestration.mjs +556 -556
  86. package/web-ui/modules/app.methods.tool-config-permissions.mjs +90 -87
  87. package/web-ui/modules/app.methods.webhook.mjs +87 -87
  88. package/web-ui/modules/config-mode.computed.mjs +124 -124
  89. package/web-ui/modules/config-template-confirm-pref.mjs +33 -33
  90. package/web-ui/modules/i18n/locales/en.mjs +1187 -1140
  91. package/web-ui/modules/i18n/locales/ja.mjs +1178 -1130
  92. package/web-ui/modules/i18n/locales/vi.mjs +294 -239
  93. package/web-ui/modules/i18n/locales/zh.mjs +1190 -1143
  94. package/web-ui/modules/i18n.dict.mjs +14 -14
  95. package/web-ui/modules/i18n.mjs +111 -111
  96. package/web-ui/modules/plugins.computed.mjs +3 -3
  97. package/web-ui/modules/plugins.methods.mjs +3 -3
  98. package/web-ui/modules/plugins.storage.mjs +11 -11
  99. package/web-ui/modules/provider-url-display.mjs +17 -17
  100. package/web-ui/modules/sessions-filters-url.mjs +138 -138
  101. package/web-ui/modules/skills.computed.mjs +107 -107
  102. package/web-ui/modules/skills.methods.mjs +513 -513
  103. package/web-ui/partials/index/layout-footer.html +13 -13
  104. package/web-ui/partials/index/layout-header.html +478 -478
  105. package/web-ui/partials/index/modal-config-template-agents.html +185 -185
  106. package/web-ui/partials/index/modal-confirm-toast.html +32 -32
  107. package/web-ui/partials/index/modal-health-check.html +45 -45
  108. package/web-ui/partials/index/modal-openclaw-config.html +344 -344
  109. package/web-ui/partials/index/modal-skills.html +200 -200
  110. package/web-ui/partials/index/modal-webhook.html +42 -42
  111. package/web-ui/partials/index/modals-basic.html +263 -263
  112. package/web-ui/partials/index/panel-config-claude.html +187 -187
  113. package/web-ui/partials/index/panel-config-codex.html +205 -205
  114. package/web-ui/partials/index/panel-config-openclaw.html +89 -89
  115. package/web-ui/partials/index/panel-dashboard.html +171 -171
  116. package/web-ui/partials/index/panel-docs.html +114 -114
  117. package/web-ui/partials/index/panel-market.html +104 -104
  118. package/web-ui/partials/index/panel-orchestration.html +391 -391
  119. package/web-ui/partials/index/panel-plugins.html +253 -253
  120. package/web-ui/partials/index/panel-sessions.html +325 -319
  121. package/web-ui/partials/index/panel-settings.html +181 -181
  122. package/web-ui/partials/index/panel-trash.html +82 -82
  123. package/web-ui/partials/index/panel-usage.html +181 -181
  124. package/web-ui/res/json5.min.js +1 -1
  125. package/web-ui/res/vue.global.prod.js +13 -13
  126. package/web-ui/res/vue.runtime.global.prod.js +7 -7
  127. package/web-ui/res/web-ui-render.precompiled.js +7671 -7666
  128. package/web-ui/session-helpers.mjs +602 -602
  129. package/web-ui/source-bundle.cjs +305 -305
  130. package/web-ui/styles/base-theme.css +291 -291
  131. package/web-ui/styles/bridge-pool.css +266 -266
  132. package/web-ui/styles/controls-forms.css +532 -532
  133. package/web-ui/styles/dashboard.css +438 -438
  134. package/web-ui/styles/docs-panel.css +245 -245
  135. package/web-ui/styles/feedback.css +108 -108
  136. package/web-ui/styles/health-check-dialog.css +144 -144
  137. package/web-ui/styles/layout-shell.css +711 -711
  138. package/web-ui/styles/modals-core.css +499 -499
  139. package/web-ui/styles/navigation-panels.css +399 -399
  140. package/web-ui/styles/openclaw-structured.css +616 -616
  141. package/web-ui/styles/plugins-panel.css +564 -564
  142. package/web-ui/styles/responsive.css +501 -501
  143. package/web-ui/styles/sessions-list.css +683 -683
  144. package/web-ui/styles/sessions-preview.css +407 -407
  145. package/web-ui/styles/sessions-toolbar-trash.css +518 -518
  146. package/web-ui/styles/sessions-usage.css +849 -849
  147. package/web-ui/styles/settings-panel.css +419 -419
  148. package/web-ui/styles/skills-list.css +305 -305
  149. package/web-ui/styles/skills-market.css +723 -723
  150. package/web-ui/styles/task-orchestration.css +822 -822
  151. package/web-ui/styles/titles-cards.css +492 -486
  152. package/web-ui/styles/trash-panel.css +90 -90
  153. package/web-ui/styles/webhook.css +115 -115
  154. package/web-ui/styles.css +24 -24
  155. package/web-ui.html +17 -17
@@ -1,849 +1,849 @@
1
- /* ============================================
2
- Usage Tab — 流光设计 (Flow of Light)
3
- ============================================ */
4
-
5
- /* ---- Toolbar ---- */
6
- .usage-toolbar {
7
- display: flex;
8
- justify-content: space-between;
9
- align-items: center;
10
- gap: 16px;
11
- flex-wrap: wrap;
12
- margin-bottom: 28px;
13
- }
14
-
15
- .usage-toolbar-title {
16
- font-size: 20px;
17
- font-weight: 600;
18
- color: var(--color-text-primary);
19
- letter-spacing: -0.03em;
20
- }
21
-
22
- .usage-range-group {
23
- display: flex;
24
- gap: 2px;
25
- padding: 3px;
26
- border-radius: 12px;
27
- background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(247,239,232,0.7));
28
- border: 1px solid rgba(137, 111, 94, 0.08);
29
- box-shadow: 0 2px 12px rgba(92, 68, 52, 0.06);
30
- backdrop-filter: blur(8px);
31
- }
32
-
33
- .usage-range-btn {
34
- border: none;
35
- background: transparent;
36
- color: var(--color-text-tertiary);
37
- padding: 8px 16px;
38
- border-radius: 9px;
39
- cursor: pointer;
40
- font-size: 13px;
41
- font-weight: 500;
42
- font-family: var(--font-family);
43
- white-space: nowrap;
44
- transition: all 180ms var(--ease-spring);
45
- outline: none;
46
- -webkit-tap-highlight-color: transparent;
47
- }
48
-
49
- .usage-range-btn:hover:not(:disabled) {
50
- color: var(--color-text-secondary);
51
- background: rgba(200, 121, 99, 0.08);
52
- }
53
-
54
- .usage-range-btn:active:not(:disabled) {
55
- transform: scale(0.95);
56
- }
57
-
58
- .usage-range-btn.active {
59
- color: #fff;
60
- background: linear-gradient(135deg, var(--color-brand), var(--color-brand-dark));
61
- box-shadow: 0 4px 16px rgba(200, 121, 99, 0.35), 0 0 0 1px rgba(255,255,255,0.1) inset;
62
- }
63
-
64
- .usage-range-btn:disabled {
65
- opacity: 0.35;
66
- cursor: not-allowed;
67
- }
68
-
69
- .usage-range-btn-icon {
70
- padding: 8px 12px;
71
- display: inline-flex;
72
- align-items: center;
73
- justify-content: center;
74
- }
75
-
76
- .usage-range-btn-icon svg {
77
- width: 16px;
78
- height: 16px;
79
- }
80
-
81
- .usage-range-btn-icon:active {
82
- transform: rotate(180deg);
83
- transition: transform 400ms var(--ease-spring);
84
- }
85
-
86
- /* ---- Empty State (插画风格) ---- */
87
- .usage-empty-state {
88
- display: flex;
89
- flex-direction: column;
90
- align-items: center;
91
- justify-content: center;
92
- padding: 64px 20px;
93
- text-align: center;
94
- }
95
-
96
- .usage-empty-illustration {
97
- width: 72px;
98
- height: 72px;
99
- color: var(--color-text-muted);
100
- opacity: 0.5;
101
- margin-bottom: 20px;
102
- animation: usage-empty-breathe 4s ease-in-out infinite;
103
- }
104
-
105
- @keyframes usage-empty-breathe {
106
- 0%, 100% { transform: scale(1) translateY(0); opacity: 0.5; }
107
- 50% { transform: scale(1.08) translateY(-4px); opacity: 0.7; }
108
- }
109
-
110
- .usage-empty-text {
111
- font-size: 14px;
112
- color: var(--color-text-secondary);
113
- max-width: 300px;
114
- line-height: 1.6;
115
- }
116
-
117
- /* ---- Hero 区域 (全宽沉浸式) ---- */
118
- .usage-hero {
119
- padding: 32px 28px;
120
- margin-bottom: 24px;
121
- border-radius: 18px;
122
- background: linear-gradient(135deg, rgba(255,255,255,0.95), rgba(252,248,241,0.9));
123
- border: 1px solid rgba(137, 111, 94, 0.08);
124
- min-height: 160px;
125
- display: flex;
126
- flex-direction: column;
127
- justify-content: center;
128
- gap: 20px;
129
- box-shadow: 0 8px 32px rgba(92, 68, 52, 0.08), 0 0 0 1px rgba(255,255,255,0.5) inset;
130
- backdrop-filter: blur(10px);
131
- position: relative;
132
- overflow: hidden;
133
- }
134
-
135
- .usage-hero::before {
136
- content: '';
137
- position: absolute;
138
- top: -72px;
139
- right: 0;
140
- width: min(320px, 62%);
141
- height: min(320px, 62%);
142
- background: radial-gradient(circle, rgba(200, 121, 99, 0.06) 0%, transparent 70%);
143
- pointer-events: none;
144
- }
145
-
146
- .usage-hero-active {
147
- display: flex;
148
- flex-wrap: wrap;
149
- align-items: center;
150
- gap: 10px 16px;
151
- padding: 12px 18px;
152
- border-radius: 12px;
153
- background: linear-gradient(135deg, rgba(200, 121, 99, 0.08), rgba(200, 121, 99, 0.04));
154
- border: 1px solid rgba(200, 121, 99, 0.12);
155
- font-size: 12px;
156
- position: relative;
157
- z-index: 1;
158
- }
159
-
160
- .usage-hero-active-dot {
161
- width: 7px;
162
- height: 7px;
163
- border-radius: 50%;
164
- background: var(--color-success);
165
- flex-shrink: 0;
166
- animation: usage-pulse 2.2s ease-in-out infinite;
167
- box-shadow: 0 0 12px rgba(75, 139, 106, 0.4);
168
- }
169
-
170
- @keyframes usage-pulse {
171
- 0%, 100% { opacity: 1; transform: scale(1); }
172
- 50% { opacity: 0.5; transform: scale(0.85); }
173
- }
174
-
175
- .usage-hero-active-label {
176
- font-weight: 600;
177
- color: var(--color-text-primary);
178
- min-width: 0;
179
- overflow-wrap: anywhere;
180
- }
181
-
182
- .usage-hero-active-stat {
183
- color: var(--color-text-tertiary);
184
- min-width: 0;
185
- overflow-wrap: anywhere;
186
- }
187
-
188
- .usage-hero-active-stat::before {
189
- content: '·';
190
- margin-right: 12px;
191
- color: var(--color-border-strong);
192
- }
193
-
194
- .usage-hero-metrics {
195
- text-align: center;
196
- position: relative;
197
- z-index: 1;
198
- }
199
-
200
- .usage-hero-main {
201
- font-size: 52px;
202
- font-weight: 700;
203
- color: var(--color-text-primary);
204
- line-height: 1;
205
- letter-spacing: -0.04em;
206
- font-variant-numeric: tabular-nums;
207
- animation: usage-hero-count 1s var(--ease-out-expo);
208
- background: linear-gradient(135deg, var(--color-text-primary) 0%, var(--color-brand) 100%);
209
- -webkit-background-clip: text;
210
- -webkit-text-fill-color: transparent;
211
- background-clip: text;
212
- }
213
-
214
- @keyframes usage-hero-count {
215
- from { opacity: 0; transform: translateY(16px) scale(0.95); }
216
- to { opacity: 1; transform: translateY(0) scale(1); }
217
- }
218
-
219
- .usage-hero-sub {
220
- margin-top: 10px;
221
- font-size: 14px;
222
- color: var(--color-text-tertiary);
223
- display: flex;
224
- align-items: center;
225
- justify-content: center;
226
- gap: 14px;
227
- flex-wrap: wrap;
228
- min-width: 0;
229
- overflow-wrap: anywhere;
230
- text-align: center;
231
- }
232
-
233
- .usage-hero-sub > span {
234
- min-width: 0;
235
- max-width: 100%;
236
- overflow-wrap: anywhere;
237
- }
238
-
239
- .usage-hero-delta {
240
- font-size: 12px;
241
- font-weight: 600;
242
- padding: 3px 10px;
243
- border-radius: 16px;
244
- }
245
-
246
- .usage-hero-delta.delta-up {
247
- color: var(--color-success);
248
- background: linear-gradient(135deg, rgba(75, 139, 106, 0.15), rgba(75, 139, 106, 0.08));
249
- }
250
-
251
- .usage-hero-delta.delta-down {
252
- color: var(--color-error);
253
- background: linear-gradient(135deg, rgba(196, 69, 54, 0.15), rgba(196, 69, 54, 0.08));
254
- }
255
-
256
- /* ---- 波浪图 (流体动画) ---- */
257
- .usage-wave-section {
258
- overflow: hidden;
259
- border: none;
260
- background: transparent;
261
- padding: 0;
262
- margin-bottom: 24px;
263
- }
264
-
265
- .usage-wave-container {
266
- margin-top: 16px;
267
- position: relative;
268
- padding: 20px;
269
- border-radius: 18px;
270
- background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
271
- border: 1px solid rgba(137, 111, 94, 0.06);
272
- box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
273
- backdrop-filter: blur(8px);
274
- }
275
-
276
- .usage-wave-chart {
277
- width: 100%;
278
- height: 150px;
279
- display: block;
280
- }
281
-
282
- .usage-wave-area {
283
- transition: d 600ms var(--ease-spring);
284
- animation: usage-wave-pulse 4s ease-in-out infinite;
285
- }
286
-
287
- @keyframes usage-wave-pulse {
288
- 0%, 100% { opacity: 1; }
289
- 50% { opacity: 0.85; }
290
- }
291
-
292
- .usage-wave-line {
293
- transition: d 600ms var(--ease-spring);
294
- filter: drop-shadow(0 4px 12px rgba(200, 121, 99, 0.25));
295
- }
296
-
297
- .usage-wave-hover-line {
298
- transition: x1 200ms var(--ease-spring), x2 200ms var(--ease-spring),
299
- y1 200ms var(--ease-spring), y2 200ms var(--ease-spring);
300
- stroke-dasharray: 4 4;
301
- animation: usage-hover-dash 20s linear infinite;
302
- }
303
-
304
- @keyframes usage-hover-dash {
305
- to { stroke-dashoffset: -100; }
306
- }
307
-
308
- .usage-wave-hover-point {
309
- transition: cx 200ms var(--ease-spring), cy 200ms var(--ease-spring);
310
- filter: drop-shadow(0 0 8px rgba(200, 121, 99, 0.4));
311
- animation: usage-point-pulse 2s ease-in-out infinite;
312
- }
313
-
314
- @keyframes usage-point-pulse {
315
- 0%, 100% { r: 5; }
316
- 50% { r: 6.5; }
317
- }
318
-
319
- .usage-wave-labels {
320
- display: flex;
321
- justify-content: space-between;
322
- margin-top: 12px;
323
- padding: 0 8px;
324
- }
325
-
326
- .usage-wave-label {
327
- font-size: 11px;
328
- color: var(--color-text-muted);
329
- cursor: pointer;
330
- padding: 4px 8px;
331
- border-radius: 6px;
332
- transition: all 180ms var(--ease-spring);
333
- -webkit-tap-highlight-color: transparent;
334
- font-weight: 500;
335
- }
336
-
337
- .usage-wave-label:hover {
338
- color: var(--color-text-secondary);
339
- background: rgba(200, 121, 99, 0.08);
340
- }
341
-
342
- .usage-wave-label.active {
343
- color: var(--color-brand);
344
- font-weight: 600;
345
- background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
346
- }
347
-
348
- /* ---- 日期详情 ---- */
349
- .usage-daydetail {
350
- margin-top: 16px;
351
- padding: 14px 18px;
352
- border-radius: 12px;
353
- background: linear-gradient(135deg, rgba(247, 239, 232, 0.8), rgba(247, 239, 232, 0.4));
354
- border: 1px solid rgba(137, 111, 94, 0.06);
355
- }
356
-
357
- .usage-daydetail-header {
358
- display: flex;
359
- justify-content: space-between;
360
- align-items: center;
361
- flex-wrap: wrap;
362
- gap: 8px;
363
- }
364
-
365
- .usage-daydetail-date {
366
- font-weight: 600;
367
- font-size: 14px;
368
- color: var(--color-text-primary);
369
- }
370
-
371
- .usage-daydetail-stats {
372
- font-size: 12px;
373
- color: var(--color-text-secondary);
374
- }
375
-
376
- .usage-daydetail-compare {
377
- margin-top: 6px;
378
- font-size: 11px;
379
- color: var(--color-text-muted);
380
- }
381
-
382
- /* ---- 热力图 (动态呼吸) ---- */
383
- .usage-card-hourly-heatmap {
384
- overflow-x: auto;
385
- border: none;
386
- background: transparent;
387
- padding: 0;
388
- min-width: 0;
389
- }
390
-
391
- .hourly-heatmap-wrapper {
392
- display: flex;
393
- flex-direction: column;
394
- gap: 3px;
395
- margin-top: 14px;
396
- min-width: 500px;
397
- max-width: 100%;
398
- box-sizing: border-box;
399
- padding: 16px;
400
- border-radius: 18px;
401
- background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
402
- border: 1px solid rgba(137, 111, 94, 0.06);
403
- box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
404
- backdrop-filter: blur(8px);
405
- }
406
-
407
- .hourly-heatmap-header {
408
- display: flex;
409
- gap: 3px;
410
- align-items: flex-end;
411
- }
412
-
413
- .hourly-heatmap-corner {
414
- width: 36px;
415
- flex-shrink: 0;
416
- }
417
-
418
- .hourly-heatmap-hour-label {
419
- flex: 1;
420
- min-width: 0;
421
- font-size: 9px;
422
- color: var(--color-text-muted);
423
- text-align: center;
424
- line-height: 14px;
425
- }
426
-
427
- .hourly-heatmap-row {
428
- display: flex;
429
- gap: 3px;
430
- align-items: center;
431
- }
432
-
433
- .hourly-heatmap-weekday-label {
434
- width: 36px;
435
- flex-shrink: 0;
436
- font-size: 11px;
437
- color: var(--color-text-secondary);
438
- text-align: right;
439
- padding-right: 6px;
440
- font-weight: 500;
441
- }
442
-
443
- .hourly-heatmap-cell {
444
- flex: 1;
445
- min-width: 0;
446
- height: 7px;
447
- border-radius: 4px;
448
- transition: all 200ms var(--ease-spring);
449
- cursor: crosshair;
450
- }
451
-
452
- .hourly-heatmap-cell:hover {
453
- transform: scaleY(1.4);
454
- filter: brightness(1.1);
455
- }
456
-
457
- .hourly-heatmap-cell.level-0 {
458
- background: var(--color-surface-alt);
459
- }
460
- .hourly-heatmap-cell.level-1 {
461
- background: var(--color-heatmap-1);
462
- animation: heatmap-breath-1 3s ease-in-out infinite;
463
- }
464
- .hourly-heatmap-cell.level-2 {
465
- background: var(--color-heatmap-2);
466
- animation: heatmap-breath-2 3s ease-in-out infinite;
467
- }
468
- .hourly-heatmap-cell.level-3 {
469
- background: var(--color-heatmap-3);
470
- animation: heatmap-breath-3 3s ease-in-out infinite;
471
- }
472
- .hourly-heatmap-cell.level-4 {
473
- background: var(--color-heatmap-4);
474
- animation: heatmap-breath-4 3s ease-in-out infinite;
475
- box-shadow: 0 0 8px rgba(200, 121, 99, 0.3);
476
- }
477
-
478
- @keyframes heatmap-breath-1 {
479
- 0%, 100% { opacity: 1; }
480
- 50% { opacity: 0.85; }
481
- }
482
- @keyframes heatmap-breath-2 {
483
- 0%, 100% { opacity: 1; }
484
- 50% { opacity: 0.9; }
485
- }
486
- @keyframes heatmap-breath-3 {
487
- 0%, 100% { opacity: 1; }
488
- 50% { opacity: 0.95; }
489
- }
490
- @keyframes heatmap-breath-4 {
491
- 0%, 100% { opacity: 1; box-shadow: 0 0 8px rgba(200, 121, 99, 0.3); }
492
- 50% { opacity: 0.9; box-shadow: 0 0 14px rgba(200, 121, 99, 0.5); }
493
- }
494
-
495
- .hourly-heatmap-legend {
496
- display: flex;
497
- align-items: center;
498
- gap: 4px;
499
- justify-content: flex-end;
500
- margin-top: 12px;
501
- font-size: 10px;
502
- color: var(--color-text-muted);
503
- }
504
-
505
- .hourly-heatmap-legend .hourly-heatmap-cell {
506
- width: 12px;
507
- height: 12px;
508
- border-radius: 3px;
509
- }
510
-
511
- .hourly-heatmap-legend-label {
512
- margin: 0 4px;
513
- }
514
-
515
- /* ---- 列表样式 (加大间距) ---- */
516
- .usage-list-compact {
517
- display: flex;
518
- flex-direction: column;
519
- gap: 6px;
520
- }
521
-
522
- .usage-list-compact-item {
523
- display: flex;
524
- align-items: flex-start;
525
- gap: 10px;
526
- padding: 10px 14px;
527
- border-radius: 10px;
528
- cursor: pointer;
529
- transition: all 180ms var(--ease-spring);
530
- -webkit-tap-highlight-color: transparent;
531
- }
532
-
533
- .usage-list-compact-item:hover {
534
- background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(252,248,241,0.7));
535
- transform: translateX(4px);
536
- box-shadow: 0 2px 8px rgba(92, 68, 52, 0.06);
537
- }
538
-
539
- .usage-list-compact-item:active {
540
- transform: translateX(2px) scale(0.98);
541
- }
542
-
543
- .usage-list-bullet {
544
- color: var(--color-brand);
545
- font-size: 16px;
546
- line-height: 1.4;
547
- flex-shrink: 0;
548
- opacity: 0.7;
549
- }
550
-
551
- .usage-list-compact-item:hover .usage-list-bullet {
552
- opacity: 1;
553
- }
554
-
555
- .usage-list-compact-content {
556
- flex: 1;
557
- min-width: 0;
558
- }
559
-
560
- .usage-list-title {
561
- font-size: 13px;
562
- font-weight: 500;
563
- color: var(--color-text-primary);
564
- overflow: hidden;
565
- text-overflow: ellipsis;
566
- white-space: nowrap;
567
- }
568
-
569
- .usage-list-meta {
570
- font-size: 11px;
571
- color: var(--color-text-muted);
572
- margin-top: 3px;
573
- }
574
-
575
- .usage-list-value {
576
- font-size: 13px;
577
- color: var(--color-text-secondary);
578
- padding: 10px 0;
579
- }
580
-
581
- /* ---- Path 列表 ---- */
582
- .usage-paths-section {
583
- grid-column: 1 / -1;
584
- border: none;
585
- background: transparent;
586
- padding: 0;
587
- }
588
-
589
- .usage-list-paths {
590
- display: flex;
591
- flex-direction: column;
592
- gap: 8px;
593
- padding: 16px;
594
- border-radius: 18px;
595
- background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
596
- border: 1px solid rgba(137, 111, 94, 0.06);
597
- box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
598
- backdrop-filter: blur(8px);
599
- }
600
-
601
- .usage-list-path-row {
602
- display: flex;
603
- align-items: center;
604
- gap: 12px;
605
- padding: 10px 12px;
606
- border-radius: 10px;
607
- transition: all 180ms var(--ease-spring);
608
- }
609
-
610
- .usage-list-path-row:hover {
611
- background: rgba(255, 255, 255, 0.7);
612
- transform: translateX(4px);
613
- }
614
-
615
- .usage-list-path-rank {
616
- width: 22px;
617
- height: 22px;
618
- display: flex;
619
- align-items: center;
620
- justify-content: center;
621
- font-size: 11px;
622
- font-weight: 600;
623
- color: var(--color-brand);
624
- background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
625
- border-radius: 6px;
626
- flex-shrink: 0;
627
- }
628
-
629
- .usage-list-path-content {
630
- flex: 1;
631
- display: flex;
632
- justify-content: space-between;
633
- align-items: center;
634
- gap: 12px;
635
- min-width: 0;
636
- }
637
-
638
- .usage-list-path {
639
- font-size: 12px;
640
- color: var(--color-text-secondary);
641
- font-family: var(--font-family-mono);
642
- overflow: hidden;
643
- text-overflow: ellipsis;
644
- white-space: nowrap;
645
- }
646
-
647
- .usage-list-path-stat {
648
- font-size: 14px;
649
- font-weight: 600;
650
- color: var(--color-text-primary);
651
- font-variant-numeric: tabular-nums;
652
- flex-shrink: 0;
653
- }
654
-
655
- /* ---- 卡片 (无边框浮动式) ---- */
656
- .usage-card {
657
- padding: 0;
658
- border-radius: 0;
659
- background: transparent;
660
- border: none;
661
- margin-bottom: 0;
662
- }
663
-
664
- .usage-card-title {
665
- font-size: 15px;
666
- font-weight: 600;
667
- color: var(--color-text-primary);
668
- margin-bottom: 0;
669
- letter-spacing: -0.02em;
670
- }
671
-
672
- /* ---- 图表网格 (加大间距) ---- */
673
- .usage-chart-grid {
674
- display: grid;
675
- grid-template-columns: repeat(2, minmax(0, 1fr));
676
- gap: 20px;
677
- }
678
-
679
- .usage-chart-grid > * {
680
- min-width: 0;
681
- }
682
-
683
- /* 为非 paths 卡片添加容器 */
684
- .usage-chart-grid > .usage-card:not(.usage-paths-section):not(.usage-wave-section):not(.usage-card-hourly-heatmap) {
685
- padding: 16px;
686
- border-radius: 18px;
687
- background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
688
- border: 1px solid rgba(137, 111, 94, 0.06);
689
- box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
690
- backdrop-filter: blur(8px);
691
- }
692
-
693
- /* ---- 内容区域 ---- */
694
- .usage-content {
695
- position: relative;
696
- }
697
-
698
- .usage-content-loading {
699
- opacity: 0.6;
700
- pointer-events: none;
701
- }
702
-
703
- .usage-content-overlay {
704
- position: absolute;
705
- inset: 0;
706
- display: flex;
707
- align-items: flex-start;
708
- justify-content: flex-end;
709
- padding: 16px;
710
- z-index: 10;
711
- }
712
-
713
- .usage-spinner {
714
- width: 18px;
715
- height: 18px;
716
- border-radius: 50%;
717
- border: 2px solid rgba(137, 111, 94, 0.15);
718
- border-top-color: var(--color-brand);
719
- animation: usage-spin 0.8s linear infinite;
720
- }
721
-
722
- @keyframes usage-spin {
723
- to { transform: rotate(360deg); }
724
- }
725
-
726
- /* ---- 响应式 ---- */
727
- @media (max-width: 1100px) {
728
- .usage-chart-grid {
729
- grid-template-columns: 1fr;
730
- }
731
- }
732
-
733
- @media (max-width: 960px) {
734
-
735
- .usage-hero-main {
736
- font-size: 44px;
737
- }
738
- }
739
-
740
- @media (max-width: 640px) {
741
- .usage-toolbar {
742
- flex-direction: column;
743
- align-items: stretch;
744
- }
745
-
746
- .usage-range-group {
747
- justify-content: center;
748
- flex-wrap: wrap;
749
- }
750
-
751
- .usage-hero {
752
- padding: 22px 16px;
753
- min-height: 140px;
754
- gap: 16px;
755
- }
756
-
757
- .usage-hero::before {
758
- top: -56px;
759
- right: 0;
760
- width: 220px;
761
- height: 220px;
762
- }
763
-
764
- .usage-hero-active {
765
- padding: 10px 12px;
766
- gap: 8px 10px;
767
- }
768
-
769
- .usage-hero-main {
770
- font-size: clamp(32px, 10vw, 38px);
771
- line-height: 1.08;
772
- }
773
-
774
- .usage-wave-chart {
775
- height: 110px;
776
- }
777
-
778
- .usage-wave-labels {
779
- font-size: 10px;
780
- }
781
-
782
- .hourly-heatmap-wrapper {
783
- width: 100%;
784
- min-width: 100%;
785
- max-width: 100%;
786
- overflow-x: visible;
787
- padding: 12px;
788
- gap: 2px;
789
- }
790
-
791
- .usage-card-hourly-heatmap {
792
- overflow-x: visible;
793
- }
794
-
795
- .hourly-heatmap-header,
796
- .hourly-heatmap-row {
797
- gap: 2px;
798
- }
799
-
800
- .hourly-heatmap-corner,
801
- .hourly-heatmap-weekday-label {
802
- width: 28px;
803
- }
804
-
805
- .hourly-heatmap-weekday-label {
806
- font-size: 10px;
807
- padding-right: 4px;
808
- }
809
-
810
- .hourly-heatmap-hour-label {
811
- font-size: 8px;
812
- line-height: 12px;
813
- }
814
-
815
- .hourly-heatmap-cell {
816
- height: 8px;
817
- border-radius: 3px;
818
- }
819
-
820
- .usage-chart-grid {
821
- gap: 16px;
822
- }
823
- }
824
-
825
- @media (max-width: 420px) {
826
- .hourly-heatmap-wrapper {
827
- padding: 10px;
828
- gap: 1px;
829
- }
830
-
831
- .hourly-heatmap-header,
832
- .hourly-heatmap-row {
833
- gap: 1px;
834
- }
835
-
836
- .hourly-heatmap-corner,
837
- .hourly-heatmap-weekday-label {
838
- width: 24px;
839
- }
840
-
841
- .hourly-heatmap-weekday-label {
842
- font-size: 9px;
843
- padding-right: 3px;
844
- }
845
-
846
- .hourly-heatmap-hour-label {
847
- font-size: 7px;
848
- }
849
- }
1
+ /* ============================================
2
+ Usage Tab — 流光设计 (Flow of Light)
3
+ ============================================ */
4
+
5
+ /* ---- Toolbar ---- */
6
+ .usage-toolbar {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: center;
10
+ gap: 16px;
11
+ flex-wrap: wrap;
12
+ margin-bottom: 28px;
13
+ }
14
+
15
+ .usage-toolbar-title {
16
+ font-size: 20px;
17
+ font-weight: 600;
18
+ color: var(--color-text-primary);
19
+ letter-spacing: -0.03em;
20
+ }
21
+
22
+ .usage-range-group {
23
+ display: flex;
24
+ gap: 2px;
25
+ padding: 3px;
26
+ border-radius: 12px;
27
+ background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(247,239,232,0.7));
28
+ border: 1px solid rgba(137, 111, 94, 0.08);
29
+ box-shadow: 0 2px 12px rgba(92, 68, 52, 0.06);
30
+ backdrop-filter: blur(8px);
31
+ }
32
+
33
+ .usage-range-btn {
34
+ border: none;
35
+ background: transparent;
36
+ color: var(--color-text-tertiary);
37
+ padding: 8px 16px;
38
+ border-radius: 9px;
39
+ cursor: pointer;
40
+ font-size: 13px;
41
+ font-weight: 500;
42
+ font-family: var(--font-family);
43
+ white-space: nowrap;
44
+ transition: all 180ms var(--ease-spring);
45
+ outline: none;
46
+ -webkit-tap-highlight-color: transparent;
47
+ }
48
+
49
+ .usage-range-btn:hover:not(:disabled) {
50
+ color: var(--color-text-secondary);
51
+ background: rgba(200, 121, 99, 0.08);
52
+ }
53
+
54
+ .usage-range-btn:active:not(:disabled) {
55
+ transform: scale(0.95);
56
+ }
57
+
58
+ .usage-range-btn.active {
59
+ color: #fff;
60
+ background: linear-gradient(135deg, var(--color-brand), var(--color-brand-dark));
61
+ box-shadow: 0 4px 16px rgba(200, 121, 99, 0.35), 0 0 0 1px rgba(255,255,255,0.1) inset;
62
+ }
63
+
64
+ .usage-range-btn:disabled {
65
+ opacity: 0.35;
66
+ cursor: not-allowed;
67
+ }
68
+
69
+ .usage-range-btn-icon {
70
+ padding: 8px 12px;
71
+ display: inline-flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ }
75
+
76
+ .usage-range-btn-icon svg {
77
+ width: 16px;
78
+ height: 16px;
79
+ }
80
+
81
+ .usage-range-btn-icon:active {
82
+ transform: rotate(180deg);
83
+ transition: transform 400ms var(--ease-spring);
84
+ }
85
+
86
+ /* ---- Empty State (插画风格) ---- */
87
+ .usage-empty-state {
88
+ display: flex;
89
+ flex-direction: column;
90
+ align-items: center;
91
+ justify-content: center;
92
+ padding: 64px 20px;
93
+ text-align: center;
94
+ }
95
+
96
+ .usage-empty-illustration {
97
+ width: 72px;
98
+ height: 72px;
99
+ color: var(--color-text-muted);
100
+ opacity: 0.5;
101
+ margin-bottom: 20px;
102
+ animation: usage-empty-breathe 4s ease-in-out infinite;
103
+ }
104
+
105
+ @keyframes usage-empty-breathe {
106
+ 0%, 100% { transform: scale(1) translateY(0); opacity: 0.5; }
107
+ 50% { transform: scale(1.08) translateY(-4px); opacity: 0.7; }
108
+ }
109
+
110
+ .usage-empty-text {
111
+ font-size: 14px;
112
+ color: var(--color-text-secondary);
113
+ max-width: 300px;
114
+ line-height: 1.6;
115
+ }
116
+
117
+ /* ---- Hero 区域 (全宽沉浸式) ---- */
118
+ .usage-hero {
119
+ padding: 32px 28px;
120
+ margin-bottom: 24px;
121
+ border-radius: 18px;
122
+ background: linear-gradient(135deg, rgba(255,255,255,0.95), rgba(252,248,241,0.9));
123
+ border: 1px solid rgba(137, 111, 94, 0.08);
124
+ min-height: 160px;
125
+ display: flex;
126
+ flex-direction: column;
127
+ justify-content: center;
128
+ gap: 20px;
129
+ box-shadow: 0 8px 32px rgba(92, 68, 52, 0.08), 0 0 0 1px rgba(255,255,255,0.5) inset;
130
+ backdrop-filter: blur(10px);
131
+ position: relative;
132
+ overflow: hidden;
133
+ }
134
+
135
+ .usage-hero::before {
136
+ content: '';
137
+ position: absolute;
138
+ top: -72px;
139
+ right: 0;
140
+ width: min(320px, 62%);
141
+ height: min(320px, 62%);
142
+ background: radial-gradient(circle, rgba(200, 121, 99, 0.06) 0%, transparent 70%);
143
+ pointer-events: none;
144
+ }
145
+
146
+ .usage-hero-active {
147
+ display: flex;
148
+ flex-wrap: wrap;
149
+ align-items: center;
150
+ gap: 10px 16px;
151
+ padding: 12px 18px;
152
+ border-radius: 12px;
153
+ background: linear-gradient(135deg, rgba(200, 121, 99, 0.08), rgba(200, 121, 99, 0.04));
154
+ border: 1px solid rgba(200, 121, 99, 0.12);
155
+ font-size: 12px;
156
+ position: relative;
157
+ z-index: 1;
158
+ }
159
+
160
+ .usage-hero-active-dot {
161
+ width: 7px;
162
+ height: 7px;
163
+ border-radius: 50%;
164
+ background: var(--color-success);
165
+ flex-shrink: 0;
166
+ animation: usage-pulse 2.2s ease-in-out infinite;
167
+ box-shadow: 0 0 12px rgba(75, 139, 106, 0.4);
168
+ }
169
+
170
+ @keyframes usage-pulse {
171
+ 0%, 100% { opacity: 1; transform: scale(1); }
172
+ 50% { opacity: 0.5; transform: scale(0.85); }
173
+ }
174
+
175
+ .usage-hero-active-label {
176
+ font-weight: 600;
177
+ color: var(--color-text-primary);
178
+ min-width: 0;
179
+ overflow-wrap: anywhere;
180
+ }
181
+
182
+ .usage-hero-active-stat {
183
+ color: var(--color-text-tertiary);
184
+ min-width: 0;
185
+ overflow-wrap: anywhere;
186
+ }
187
+
188
+ .usage-hero-active-stat::before {
189
+ content: '·';
190
+ margin-right: 12px;
191
+ color: var(--color-border-strong);
192
+ }
193
+
194
+ .usage-hero-metrics {
195
+ text-align: center;
196
+ position: relative;
197
+ z-index: 1;
198
+ }
199
+
200
+ .usage-hero-main {
201
+ font-size: 52px;
202
+ font-weight: 700;
203
+ color: var(--color-text-primary);
204
+ line-height: 1;
205
+ letter-spacing: -0.04em;
206
+ font-variant-numeric: tabular-nums;
207
+ animation: usage-hero-count 1s var(--ease-out-expo);
208
+ background: linear-gradient(135deg, var(--color-text-primary) 0%, var(--color-brand) 100%);
209
+ -webkit-background-clip: text;
210
+ -webkit-text-fill-color: transparent;
211
+ background-clip: text;
212
+ }
213
+
214
+ @keyframes usage-hero-count {
215
+ from { opacity: 0; transform: translateY(16px) scale(0.95); }
216
+ to { opacity: 1; transform: translateY(0) scale(1); }
217
+ }
218
+
219
+ .usage-hero-sub {
220
+ margin-top: 10px;
221
+ font-size: 14px;
222
+ color: var(--color-text-tertiary);
223
+ display: flex;
224
+ align-items: center;
225
+ justify-content: center;
226
+ gap: 14px;
227
+ flex-wrap: wrap;
228
+ min-width: 0;
229
+ overflow-wrap: anywhere;
230
+ text-align: center;
231
+ }
232
+
233
+ .usage-hero-sub > span {
234
+ min-width: 0;
235
+ max-width: 100%;
236
+ overflow-wrap: anywhere;
237
+ }
238
+
239
+ .usage-hero-delta {
240
+ font-size: 12px;
241
+ font-weight: 600;
242
+ padding: 3px 10px;
243
+ border-radius: 16px;
244
+ }
245
+
246
+ .usage-hero-delta.delta-up {
247
+ color: var(--color-success);
248
+ background: linear-gradient(135deg, rgba(75, 139, 106, 0.15), rgba(75, 139, 106, 0.08));
249
+ }
250
+
251
+ .usage-hero-delta.delta-down {
252
+ color: var(--color-error);
253
+ background: linear-gradient(135deg, rgba(196, 69, 54, 0.15), rgba(196, 69, 54, 0.08));
254
+ }
255
+
256
+ /* ---- 波浪图 (流体动画) ---- */
257
+ .usage-wave-section {
258
+ overflow: hidden;
259
+ border: none;
260
+ background: transparent;
261
+ padding: 0;
262
+ margin-bottom: 24px;
263
+ }
264
+
265
+ .usage-wave-container {
266
+ margin-top: 16px;
267
+ position: relative;
268
+ padding: 20px;
269
+ border-radius: 18px;
270
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
271
+ border: 1px solid rgba(137, 111, 94, 0.06);
272
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
273
+ backdrop-filter: blur(8px);
274
+ }
275
+
276
+ .usage-wave-chart {
277
+ width: 100%;
278
+ height: 150px;
279
+ display: block;
280
+ }
281
+
282
+ .usage-wave-area {
283
+ transition: d 600ms var(--ease-spring);
284
+ animation: usage-wave-pulse 4s ease-in-out infinite;
285
+ }
286
+
287
+ @keyframes usage-wave-pulse {
288
+ 0%, 100% { opacity: 1; }
289
+ 50% { opacity: 0.85; }
290
+ }
291
+
292
+ .usage-wave-line {
293
+ transition: d 600ms var(--ease-spring);
294
+ filter: drop-shadow(0 4px 12px rgba(200, 121, 99, 0.25));
295
+ }
296
+
297
+ .usage-wave-hover-line {
298
+ transition: x1 200ms var(--ease-spring), x2 200ms var(--ease-spring),
299
+ y1 200ms var(--ease-spring), y2 200ms var(--ease-spring);
300
+ stroke-dasharray: 4 4;
301
+ animation: usage-hover-dash 20s linear infinite;
302
+ }
303
+
304
+ @keyframes usage-hover-dash {
305
+ to { stroke-dashoffset: -100; }
306
+ }
307
+
308
+ .usage-wave-hover-point {
309
+ transition: cx 200ms var(--ease-spring), cy 200ms var(--ease-spring);
310
+ filter: drop-shadow(0 0 8px rgba(200, 121, 99, 0.4));
311
+ animation: usage-point-pulse 2s ease-in-out infinite;
312
+ }
313
+
314
+ @keyframes usage-point-pulse {
315
+ 0%, 100% { r: 5; }
316
+ 50% { r: 6.5; }
317
+ }
318
+
319
+ .usage-wave-labels {
320
+ display: flex;
321
+ justify-content: space-between;
322
+ margin-top: 12px;
323
+ padding: 0 8px;
324
+ }
325
+
326
+ .usage-wave-label {
327
+ font-size: 11px;
328
+ color: var(--color-text-muted);
329
+ cursor: pointer;
330
+ padding: 4px 8px;
331
+ border-radius: 6px;
332
+ transition: all 180ms var(--ease-spring);
333
+ -webkit-tap-highlight-color: transparent;
334
+ font-weight: 500;
335
+ }
336
+
337
+ .usage-wave-label:hover {
338
+ color: var(--color-text-secondary);
339
+ background: rgba(200, 121, 99, 0.08);
340
+ }
341
+
342
+ .usage-wave-label.active {
343
+ color: var(--color-brand);
344
+ font-weight: 600;
345
+ background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
346
+ }
347
+
348
+ /* ---- 日期详情 ---- */
349
+ .usage-daydetail {
350
+ margin-top: 16px;
351
+ padding: 14px 18px;
352
+ border-radius: 12px;
353
+ background: linear-gradient(135deg, rgba(247, 239, 232, 0.8), rgba(247, 239, 232, 0.4));
354
+ border: 1px solid rgba(137, 111, 94, 0.06);
355
+ }
356
+
357
+ .usage-daydetail-header {
358
+ display: flex;
359
+ justify-content: space-between;
360
+ align-items: center;
361
+ flex-wrap: wrap;
362
+ gap: 8px;
363
+ }
364
+
365
+ .usage-daydetail-date {
366
+ font-weight: 600;
367
+ font-size: 14px;
368
+ color: var(--color-text-primary);
369
+ }
370
+
371
+ .usage-daydetail-stats {
372
+ font-size: 12px;
373
+ color: var(--color-text-secondary);
374
+ }
375
+
376
+ .usage-daydetail-compare {
377
+ margin-top: 6px;
378
+ font-size: 11px;
379
+ color: var(--color-text-muted);
380
+ }
381
+
382
+ /* ---- 热力图 (动态呼吸) ---- */
383
+ .usage-card-hourly-heatmap {
384
+ overflow-x: auto;
385
+ border: none;
386
+ background: transparent;
387
+ padding: 0;
388
+ min-width: 0;
389
+ }
390
+
391
+ .hourly-heatmap-wrapper {
392
+ display: flex;
393
+ flex-direction: column;
394
+ gap: 3px;
395
+ margin-top: 14px;
396
+ min-width: 500px;
397
+ max-width: 100%;
398
+ box-sizing: border-box;
399
+ padding: 16px;
400
+ border-radius: 18px;
401
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
402
+ border: 1px solid rgba(137, 111, 94, 0.06);
403
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
404
+ backdrop-filter: blur(8px);
405
+ }
406
+
407
+ .hourly-heatmap-header {
408
+ display: flex;
409
+ gap: 3px;
410
+ align-items: flex-end;
411
+ }
412
+
413
+ .hourly-heatmap-corner {
414
+ width: 36px;
415
+ flex-shrink: 0;
416
+ }
417
+
418
+ .hourly-heatmap-hour-label {
419
+ flex: 1;
420
+ min-width: 0;
421
+ font-size: 9px;
422
+ color: var(--color-text-muted);
423
+ text-align: center;
424
+ line-height: 14px;
425
+ }
426
+
427
+ .hourly-heatmap-row {
428
+ display: flex;
429
+ gap: 3px;
430
+ align-items: center;
431
+ }
432
+
433
+ .hourly-heatmap-weekday-label {
434
+ width: 36px;
435
+ flex-shrink: 0;
436
+ font-size: 11px;
437
+ color: var(--color-text-secondary);
438
+ text-align: right;
439
+ padding-right: 6px;
440
+ font-weight: 500;
441
+ }
442
+
443
+ .hourly-heatmap-cell {
444
+ flex: 1;
445
+ min-width: 0;
446
+ height: 7px;
447
+ border-radius: 4px;
448
+ transition: all 200ms var(--ease-spring);
449
+ cursor: crosshair;
450
+ }
451
+
452
+ .hourly-heatmap-cell:hover {
453
+ transform: scaleY(1.4);
454
+ filter: brightness(1.1);
455
+ }
456
+
457
+ .hourly-heatmap-cell.level-0 {
458
+ background: var(--color-surface-alt);
459
+ }
460
+ .hourly-heatmap-cell.level-1 {
461
+ background: var(--color-heatmap-1);
462
+ animation: heatmap-breath-1 3s ease-in-out infinite;
463
+ }
464
+ .hourly-heatmap-cell.level-2 {
465
+ background: var(--color-heatmap-2);
466
+ animation: heatmap-breath-2 3s ease-in-out infinite;
467
+ }
468
+ .hourly-heatmap-cell.level-3 {
469
+ background: var(--color-heatmap-3);
470
+ animation: heatmap-breath-3 3s ease-in-out infinite;
471
+ }
472
+ .hourly-heatmap-cell.level-4 {
473
+ background: var(--color-heatmap-4);
474
+ animation: heatmap-breath-4 3s ease-in-out infinite;
475
+ box-shadow: 0 0 8px rgba(200, 121, 99, 0.3);
476
+ }
477
+
478
+ @keyframes heatmap-breath-1 {
479
+ 0%, 100% { opacity: 1; }
480
+ 50% { opacity: 0.85; }
481
+ }
482
+ @keyframes heatmap-breath-2 {
483
+ 0%, 100% { opacity: 1; }
484
+ 50% { opacity: 0.9; }
485
+ }
486
+ @keyframes heatmap-breath-3 {
487
+ 0%, 100% { opacity: 1; }
488
+ 50% { opacity: 0.95; }
489
+ }
490
+ @keyframes heatmap-breath-4 {
491
+ 0%, 100% { opacity: 1; box-shadow: 0 0 8px rgba(200, 121, 99, 0.3); }
492
+ 50% { opacity: 0.9; box-shadow: 0 0 14px rgba(200, 121, 99, 0.5); }
493
+ }
494
+
495
+ .hourly-heatmap-legend {
496
+ display: flex;
497
+ align-items: center;
498
+ gap: 4px;
499
+ justify-content: flex-end;
500
+ margin-top: 12px;
501
+ font-size: 10px;
502
+ color: var(--color-text-muted);
503
+ }
504
+
505
+ .hourly-heatmap-legend .hourly-heatmap-cell {
506
+ width: 12px;
507
+ height: 12px;
508
+ border-radius: 3px;
509
+ }
510
+
511
+ .hourly-heatmap-legend-label {
512
+ margin: 0 4px;
513
+ }
514
+
515
+ /* ---- 列表样式 (加大间距) ---- */
516
+ .usage-list-compact {
517
+ display: flex;
518
+ flex-direction: column;
519
+ gap: 6px;
520
+ }
521
+
522
+ .usage-list-compact-item {
523
+ display: flex;
524
+ align-items: flex-start;
525
+ gap: 10px;
526
+ padding: 10px 14px;
527
+ border-radius: 10px;
528
+ cursor: pointer;
529
+ transition: all 180ms var(--ease-spring);
530
+ -webkit-tap-highlight-color: transparent;
531
+ }
532
+
533
+ .usage-list-compact-item:hover {
534
+ background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(252,248,241,0.7));
535
+ transform: translateX(4px);
536
+ box-shadow: 0 2px 8px rgba(92, 68, 52, 0.06);
537
+ }
538
+
539
+ .usage-list-compact-item:active {
540
+ transform: translateX(2px) scale(0.98);
541
+ }
542
+
543
+ .usage-list-bullet {
544
+ color: var(--color-brand);
545
+ font-size: 16px;
546
+ line-height: 1.4;
547
+ flex-shrink: 0;
548
+ opacity: 0.7;
549
+ }
550
+
551
+ .usage-list-compact-item:hover .usage-list-bullet {
552
+ opacity: 1;
553
+ }
554
+
555
+ .usage-list-compact-content {
556
+ flex: 1;
557
+ min-width: 0;
558
+ }
559
+
560
+ .usage-list-title {
561
+ font-size: 13px;
562
+ font-weight: 500;
563
+ color: var(--color-text-primary);
564
+ overflow: hidden;
565
+ text-overflow: ellipsis;
566
+ white-space: nowrap;
567
+ }
568
+
569
+ .usage-list-meta {
570
+ font-size: 11px;
571
+ color: var(--color-text-muted);
572
+ margin-top: 3px;
573
+ }
574
+
575
+ .usage-list-value {
576
+ font-size: 13px;
577
+ color: var(--color-text-secondary);
578
+ padding: 10px 0;
579
+ }
580
+
581
+ /* ---- Path 列表 ---- */
582
+ .usage-paths-section {
583
+ grid-column: 1 / -1;
584
+ border: none;
585
+ background: transparent;
586
+ padding: 0;
587
+ }
588
+
589
+ .usage-list-paths {
590
+ display: flex;
591
+ flex-direction: column;
592
+ gap: 8px;
593
+ padding: 16px;
594
+ border-radius: 18px;
595
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
596
+ border: 1px solid rgba(137, 111, 94, 0.06);
597
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
598
+ backdrop-filter: blur(8px);
599
+ }
600
+
601
+ .usage-list-path-row {
602
+ display: flex;
603
+ align-items: center;
604
+ gap: 12px;
605
+ padding: 10px 12px;
606
+ border-radius: 10px;
607
+ transition: all 180ms var(--ease-spring);
608
+ }
609
+
610
+ .usage-list-path-row:hover {
611
+ background: rgba(255, 255, 255, 0.7);
612
+ transform: translateX(4px);
613
+ }
614
+
615
+ .usage-list-path-rank {
616
+ width: 22px;
617
+ height: 22px;
618
+ display: flex;
619
+ align-items: center;
620
+ justify-content: center;
621
+ font-size: 11px;
622
+ font-weight: 600;
623
+ color: var(--color-brand);
624
+ background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
625
+ border-radius: 6px;
626
+ flex-shrink: 0;
627
+ }
628
+
629
+ .usage-list-path-content {
630
+ flex: 1;
631
+ display: flex;
632
+ justify-content: space-between;
633
+ align-items: center;
634
+ gap: 12px;
635
+ min-width: 0;
636
+ }
637
+
638
+ .usage-list-path {
639
+ font-size: 12px;
640
+ color: var(--color-text-secondary);
641
+ font-family: var(--font-family-mono);
642
+ overflow: hidden;
643
+ text-overflow: ellipsis;
644
+ white-space: nowrap;
645
+ }
646
+
647
+ .usage-list-path-stat {
648
+ font-size: 14px;
649
+ font-weight: 600;
650
+ color: var(--color-text-primary);
651
+ font-variant-numeric: tabular-nums;
652
+ flex-shrink: 0;
653
+ }
654
+
655
+ /* ---- 卡片 (无边框浮动式) ---- */
656
+ .usage-card {
657
+ padding: 0;
658
+ border-radius: 0;
659
+ background: transparent;
660
+ border: none;
661
+ margin-bottom: 0;
662
+ }
663
+
664
+ .usage-card-title {
665
+ font-size: 15px;
666
+ font-weight: 600;
667
+ color: var(--color-text-primary);
668
+ margin-bottom: 0;
669
+ letter-spacing: -0.02em;
670
+ }
671
+
672
+ /* ---- 图表网格 (加大间距) ---- */
673
+ .usage-chart-grid {
674
+ display: grid;
675
+ grid-template-columns: repeat(2, minmax(0, 1fr));
676
+ gap: 20px;
677
+ }
678
+
679
+ .usage-chart-grid > * {
680
+ min-width: 0;
681
+ }
682
+
683
+ /* 为非 paths 卡片添加容器 */
684
+ .usage-chart-grid > .usage-card:not(.usage-paths-section):not(.usage-wave-section):not(.usage-card-hourly-heatmap) {
685
+ padding: 16px;
686
+ border-radius: 18px;
687
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
688
+ border: 1px solid rgba(137, 111, 94, 0.06);
689
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
690
+ backdrop-filter: blur(8px);
691
+ }
692
+
693
+ /* ---- 内容区域 ---- */
694
+ .usage-content {
695
+ position: relative;
696
+ }
697
+
698
+ .usage-content-loading {
699
+ opacity: 0.6;
700
+ pointer-events: none;
701
+ }
702
+
703
+ .usage-content-overlay {
704
+ position: absolute;
705
+ inset: 0;
706
+ display: flex;
707
+ align-items: flex-start;
708
+ justify-content: flex-end;
709
+ padding: 16px;
710
+ z-index: 10;
711
+ }
712
+
713
+ .usage-spinner {
714
+ width: 18px;
715
+ height: 18px;
716
+ border-radius: 50%;
717
+ border: 2px solid rgba(137, 111, 94, 0.15);
718
+ border-top-color: var(--color-brand);
719
+ animation: usage-spin 0.8s linear infinite;
720
+ }
721
+
722
+ @keyframes usage-spin {
723
+ to { transform: rotate(360deg); }
724
+ }
725
+
726
+ /* ---- 响应式 ---- */
727
+ @media (max-width: 1100px) {
728
+ .usage-chart-grid {
729
+ grid-template-columns: 1fr;
730
+ }
731
+ }
732
+
733
+ @media (max-width: 960px) {
734
+
735
+ .usage-hero-main {
736
+ font-size: 44px;
737
+ }
738
+ }
739
+
740
+ @media (max-width: 640px) {
741
+ .usage-toolbar {
742
+ flex-direction: column;
743
+ align-items: stretch;
744
+ }
745
+
746
+ .usage-range-group {
747
+ justify-content: center;
748
+ flex-wrap: wrap;
749
+ }
750
+
751
+ .usage-hero {
752
+ padding: 22px 16px;
753
+ min-height: 140px;
754
+ gap: 16px;
755
+ }
756
+
757
+ .usage-hero::before {
758
+ top: -56px;
759
+ right: 0;
760
+ width: 220px;
761
+ height: 220px;
762
+ }
763
+
764
+ .usage-hero-active {
765
+ padding: 10px 12px;
766
+ gap: 8px 10px;
767
+ }
768
+
769
+ .usage-hero-main {
770
+ font-size: clamp(32px, 10vw, 38px);
771
+ line-height: 1.08;
772
+ }
773
+
774
+ .usage-wave-chart {
775
+ height: 110px;
776
+ }
777
+
778
+ .usage-wave-labels {
779
+ font-size: 10px;
780
+ }
781
+
782
+ .hourly-heatmap-wrapper {
783
+ width: 100%;
784
+ min-width: 100%;
785
+ max-width: 100%;
786
+ overflow-x: visible;
787
+ padding: 12px;
788
+ gap: 2px;
789
+ }
790
+
791
+ .usage-card-hourly-heatmap {
792
+ overflow-x: visible;
793
+ }
794
+
795
+ .hourly-heatmap-header,
796
+ .hourly-heatmap-row {
797
+ gap: 2px;
798
+ }
799
+
800
+ .hourly-heatmap-corner,
801
+ .hourly-heatmap-weekday-label {
802
+ width: 28px;
803
+ }
804
+
805
+ .hourly-heatmap-weekday-label {
806
+ font-size: 10px;
807
+ padding-right: 4px;
808
+ }
809
+
810
+ .hourly-heatmap-hour-label {
811
+ font-size: 8px;
812
+ line-height: 12px;
813
+ }
814
+
815
+ .hourly-heatmap-cell {
816
+ height: 8px;
817
+ border-radius: 3px;
818
+ }
819
+
820
+ .usage-chart-grid {
821
+ gap: 16px;
822
+ }
823
+ }
824
+
825
+ @media (max-width: 420px) {
826
+ .hourly-heatmap-wrapper {
827
+ padding: 10px;
828
+ gap: 1px;
829
+ }
830
+
831
+ .hourly-heatmap-header,
832
+ .hourly-heatmap-row {
833
+ gap: 1px;
834
+ }
835
+
836
+ .hourly-heatmap-corner,
837
+ .hourly-heatmap-weekday-label {
838
+ width: 24px;
839
+ }
840
+
841
+ .hourly-heatmap-weekday-label {
842
+ font-size: 9px;
843
+ padding-right: 3px;
844
+ }
845
+
846
+ .hourly-heatmap-hour-label {
847
+ font-size: 7px;
848
+ }
849
+ }