codexmate 0.0.36 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,6 +15,7 @@
15
15
  [![Version](https://img.shields.io/npm/v/codexmate?style=flat-square&color=A179FF)](https://www.npmjs.com/package/codexmate)
16
16
  [![Build](https://img.shields.io/github/actions/workflow/status/SakuraByteCore/codexmate/release.yml?style=flat-square&color=44cc11)](https://github.com/SakuraByteCore/codexmate/actions/workflows/release.yml)
17
17
  [![Downloads](https://img.shields.io/npm/dt/codexmate?style=flat-square)](https://www.npmjs.com/package/codexmate)
18
+ [![Install](https://img.shields.io/badge/install-brew%20%7C%20curl%20%7C%20npm-0A0?style=flat-square)](#install-via-homebrew-macos--linux)
18
19
  [![Platform](https://img.shields.io/badge/platform-Termux%20%7C%20Linux%20%7C%20macOS%20%7C%20Windows-555?style=flat-square)](#quick-start)
19
20
  [![Node](https://img.shields.io/node/v/codexmate?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
20
21
  [![License](https://img.shields.io/npm/l/codexmate?style=flat-square)](LICENSE)
@@ -70,11 +71,19 @@ Unlike simple wrappers, Codex Mate acts as a **Local Agent Bridge**:
70
71
 
71
72
  ## Quick Start
72
73
 
74
+ ### Install via Homebrew (macOS / Linux)
75
+
76
+ ```bash
77
+ brew tap SakuraByteCore/codexmate
78
+ brew install codexmate
79
+ ```
80
+
81
+ Requires [Node.js](https://nodejs.org/) (`brew install node` if not present).
82
+
73
83
  ### Install via npm
74
84
 
75
85
  ```bash
76
86
  npm install -g codexmate
77
- codexmate setup
78
87
  codexmate run
79
88
  ```
80
89
 
@@ -102,7 +111,7 @@ flowchart TD
102
111
  CLI[CLI]
103
112
  WebUI[Web UI]
104
113
  MCP[MCP Server]
105
-
114
+
106
115
  subgraph Mate [Codex Mate Core]
107
116
  API[HTTP API]
108
117
  Config[Config Engine]
@@ -110,7 +119,7 @@ flowchart TD
110
119
  Skills[Skills Market]
111
120
  Tasks[Task Runner]
112
121
  end
113
-
122
+
114
123
  subgraph Local [Local Filesystem]
115
124
  CodexDir[~/.codex]
116
125
  ClaudeDir[~/.claude]
@@ -120,9 +129,9 @@ flowchart TD
120
129
 
121
130
  User --> CLI & WebUI & MCP
122
131
  CLI & WebUI & MCP --> API
123
-
132
+
124
133
  API --> Config & Session & Skills & Tasks
125
-
134
+
126
135
  Config --> CodexDir & ClaudeDir & ClawDir
127
136
  Session --> State
128
137
  Skills --> Local
package/README.zh.md CHANGED
@@ -15,6 +15,7 @@
15
15
  [![Version](https://img.shields.io/npm/v/codexmate?style=flat-square&color=A179FF)](https://www.npmjs.com/package/codexmate)
16
16
  [![Build](https://img.shields.io/github/actions/workflow/status/SakuraByteCore/codexmate/release.yml?style=flat-square&color=44cc11)](https://github.com/SakuraByteCore/codexmate/actions/workflows/release.yml)
17
17
  [![Downloads](https://img.shields.io/npm/dt/codexmate?style=flat-square)](https://www.npmjs.com/package/codexmate)
18
+ [![Install](https://img.shields.io/badge/install-brew%20%7C%20curl%20%7C%20npm-0A0?style=flat-square)](#homebrew-安装macos--linux)
18
19
  [![Platform](https://img.shields.io/badge/platform-Termux%20%7C%20Linux%20%7C%20macOS%20%7C%20Windows-555?style=flat-square)](#快速开始)
19
20
  [![Node](https://img.shields.io/node/v/codexmate?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
20
21
  [![License](https://img.shields.io/npm/l/codexmate?style=flat-square)](LICENSE)
@@ -70,11 +71,19 @@
70
71
 
71
72
  ## 快速开始
72
73
 
74
+ ### Homebrew 安装(macOS / Linux)
75
+
76
+ ```bash
77
+ brew tap SakuraByteCore/codexmate
78
+ brew install codexmate
79
+ ```
80
+
81
+ 需要 [Node.js](https://nodejs.org/)(如未安装可执行 `brew install node`)。
82
+
73
83
  ### 通过 npm 安装
74
84
 
75
85
  ```bash
76
86
  npm install -g codexmate
77
- codexmate setup
78
87
  codexmate run
79
88
  ```
80
89
 
@@ -102,7 +111,7 @@ flowchart TD
102
111
  CLI[CLI 命令]
103
112
  WebUI[Web 界面]
104
113
  MCP[MCP 服务]
105
-
114
+
106
115
  subgraph Mate [Codex Mate 核心]
107
116
  API[HTTP API]
108
117
  Config[配置引擎]
@@ -110,7 +119,7 @@ flowchart TD
110
119
  Skills[Skills 市场]
111
120
  Tasks[任务运行器]
112
121
  end
113
-
122
+
114
123
  subgraph Local [本地文件系统]
115
124
  CodexDir[~/.codex]
116
125
  ClaudeDir[~/.claude]
@@ -120,9 +129,9 @@ flowchart TD
120
129
 
121
130
  User --> CLI & WebUI & MCP
122
131
  CLI & WebUI & MCP --> API
123
-
132
+
124
133
  API --> Config & Session & Skills & Tasks
125
-
134
+
126
135
  Config --> CodexDir & ClaudeDir & ClawDir
127
136
  Session --> State
128
137
  Skills --> Local
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codexmate",
3
- "version": "0.0.36",
3
+ "version": "0.0.37",
4
4
  "description": "Codex/Claude Code/OpenClaw 配置、会话与任务编排 CLI + Web 工具",
5
5
  "main": "cli.js",
6
6
  "bin": {
package/web-ui/app.js CHANGED
@@ -31,7 +31,6 @@ document.addEventListener('DOMContentLoaded', () => {
31
31
  const appOptions = {
32
32
  data() {
33
33
  return {
34
- brandHovered: false,
35
34
  lang: 'zh',
36
35
  appVersion: '',
37
36
  mainTab: 'dashboard',
@@ -118,11 +118,11 @@
118
118
 
119
119
  <div :class="['app-shell', { standalone: sessionStandalone }]">
120
120
  <aside class="side-rail" v-if="!sessionStandalone">
121
- <div class="brand-block" tabindex="0" @mouseenter="brandHovered = true" @mouseleave="brandHovered = false" @focus="brandHovered = true" @blur="brandHovered = false">
121
+ <div class="brand-block">
122
122
  <div class="brand-head">
123
123
  <img class="brand-logo" src="/res/logo-pack.webp" alt="Codex Mate logo">
124
124
  <div class="brand-copy">
125
- <div class="brand-kicker">Codex Mate<transition name="brand-version-fade"><span v-if="appVersion && brandHovered" class="brand-version"> v{{ appVersion }}</span></transition></div>
125
+ <div class="brand-kicker">Codex Mate<span v-if="appVersion" class="brand-version"> v{{ appVersion }}</span></div>
126
126
  </div>
127
127
  </div>
128
128
  </div>
@@ -315,6 +315,10 @@
315
315
  </div>
316
316
  </button>
317
317
  </div>
318
+ <div id="side-tab-new" class="side-item side-item-ghost" tabindex="-1" aria-hidden="true">
319
+ <div class="side-item-title">New Tab</div>
320
+ <div class="side-item-meta"><span>&nbsp;</span></div>
321
+ </div>
318
322
  </div>
319
323
 
320
324
  <div class="side-rail-lang" role="group" :aria-label="t('lang.label')">
@@ -1,4 +1,4 @@
1
- <!-- Usage 统计 - 时光之河设计 -->
1
+ <!-- Usage 统计 - 流光设计 -->
2
2
  <div
3
3
  v-show="mainTab === 'usage'"
4
4
  class="mode-content"
@@ -71,24 +71,20 @@
71
71
  </div>
72
72
  </div>
73
73
 
74
- <!-- 波浪图:替换柱状图 -->
75
- <section v-if="sessionUsageWave.points && sessionUsageWave.points.length" class="usage-card usage-wave-section">
74
+ <!-- 波浪图 -->
75
+ <section v-if="sessionUsageWave.points && sessionUsageWave.points.length" class="usage-wave-section">
76
76
  <div class="usage-card-title">{{ t('usage.daily.title') }}</div>
77
77
  <div class="usage-wave-container">
78
78
  <svg class="usage-wave-chart" viewBox="0 0 800 140" preserveAspectRatio="none">
79
79
  <defs>
80
80
  <linearGradient :id="'wave-gradient-' + sessionsUsageTimeRange" x1="0" y1="0" x2="0" y2="1">
81
- <stop offset="0%" :stop-color="'var(--color-brand)'" stop-opacity="0.3"/>
81
+ <stop offset="0%" :stop-color="'var(--color-brand)'" stop-opacity="0.35"/>
82
82
  <stop offset="100%" :stop-color="'var(--color-brand)'" stop-opacity="0"/>
83
83
  </linearGradient>
84
84
  </defs>
85
- <!-- 填充区域 -->
86
85
  <path :d="sessionUsageWave.areaPath" :fill="'url(#wave-gradient-' + sessionsUsageTimeRange + ')'" class="usage-wave-area"/>
87
- <!-- 曲线 -->
88
86
  <path :d="sessionUsageWave.linePath" fill="none" :stroke="'var(--color-brand)'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="usage-wave-line"/>
89
- <!-- 悬停指示线 -->
90
- <line v-if="sessionsUsageSelectedDay" x1="0" :x2="sessionUsageWave.width" :y1="sessionUsageWave.hoverY" :y2="sessionUsageWave.hoverY" stroke="currentColor" stroke-width="1" stroke-dasharray="4 4" opacity="0.4" class="usage-wave-hover-line"/>
91
- <!-- 悬停点 -->
87
+ <line v-if="sessionsUsageSelectedDay" x1="0" :x2="sessionUsageWave.width" :y1="sessionUsageWave.hoverY" :y2="sessionUsageWave.hoverY" stroke="currentColor" stroke-width="1" stroke-dasharray="4 4" opacity="0.5" class="usage-wave-hover-line"/>
92
88
  <circle v-if="sessionsUsageSelectedDay" :cx="sessionUsageWave.hoverX" :cy="sessionUsageWave.hoverY" r="5" :fill="'var(--color-surface)'" :stroke="'var(--color-brand)'" stroke-width="2.5" class="usage-wave-hover-point"/>
93
89
  </svg>
94
90
  <div class="usage-wave-labels">
@@ -112,8 +108,8 @@
112
108
  </section>
113
109
 
114
110
  <div class="usage-chart-grid">
115
- <!-- 热力图:垂直活动条 -->
116
- <section class="usage-card usage-hourly-heatmap">
111
+ <!-- 热力图 -->
112
+ <section class="usage-card-hourly-heatmap">
117
113
  <div class="usage-card-title">{{ t('usage.hourlyHeatmap.title') }}</div>
118
114
  <div class="hourly-heatmap-wrapper">
119
115
  <div class="hourly-heatmap-header">
@@ -166,7 +162,7 @@
166
162
  </section>
167
163
 
168
164
  <!-- Top Paths -->
169
- <section class="usage-card usage-paths-section">
165
+ <section class="usage-paths-section">
170
166
  <div class="usage-card-title">{{ t('usage.paths.title') }}</div>
171
167
  <div v-if="!sessionUsageCharts.topPaths.length" class="usage-list-value">{{ t('usage.paths.empty') }}</div>
172
168
  <div v-else class="usage-list-paths">
@@ -1,5 +1,5 @@
1
1
  window.__CODEXMATE_WEB_UI_RENDER__ = (() => {
2
- const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, Transition: _Transition, withCtx: _withCtx, createVNode: _createVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, vShow: _vShow, withDirectives: _withDirectives, vModelSelect: _vModelSelect, vModelText: _vModelText, withKeys: _withKeys, withModifiers: _withModifiers, isMemoSame: _isMemoSame, withMemo: _withMemo, normalizeStyle: _normalizeStyle, vModelCheckbox: _vModelCheckbox, vModelDynamic: _vModelDynamic } = Vue
2
+ const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, vShow: _vShow, withDirectives: _withDirectives, vModelSelect: _vModelSelect, vModelText: _vModelText, withKeys: _withKeys, withModifiers: _withModifiers, isMemoSame: _isMemoSame, withMemo: _withMemo, normalizeStyle: _normalizeStyle, vModelCheckbox: _vModelCheckbox, vModelDynamic: _vModelDynamic } = Vue
3
3
 
4
4
  return function render(_ctx, _cache) {
5
5
  return (_openBlock(), _createElementBlock(_Fragment, null, [
@@ -165,14 +165,7 @@ return function render(_ctx, _cache) {
165
165
  key: 0,
166
166
  class: "side-rail"
167
167
  }, [
168
- _createElementVNode("div", {
169
- class: "brand-block",
170
- tabindex: "0",
171
- onMouseenter: $event => (_ctx.brandHovered = true),
172
- onMouseleave: $event => (_ctx.brandHovered = false),
173
- onFocus: $event => (_ctx.brandHovered = true),
174
- onBlur: $event => (_ctx.brandHovered = false)
175
- }, [
168
+ _createElementVNode("div", { class: "brand-block" }, [
176
169
  _createElementVNode("div", { class: "brand-head" }, [
177
170
  _createElementVNode("img", {
178
171
  class: "brand-logo",
@@ -182,21 +175,16 @@ return function render(_ctx, _cache) {
182
175
  _createElementVNode("div", { class: "brand-copy" }, [
183
176
  _createElementVNode("div", { class: "brand-kicker" }, [
184
177
  _createTextVNode("Codex Mate"),
185
- _createVNode(_Transition, { name: "brand-version-fade" }, {
186
- default: _withCtx(() => [
187
- (_ctx.appVersion && _ctx.brandHovered)
188
- ? (_openBlock(), _createElementBlock("span", {
189
- key: 0,
190
- class: "brand-version"
191
- }, " v" + _toDisplayString(_ctx.appVersion), 1 /* TEXT */))
192
- : _createCommentVNode("v-if", true)
193
- ]),
194
- _: 1 /* STABLE */
195
- })
178
+ (_ctx.appVersion)
179
+ ? (_openBlock(), _createElementBlock("span", {
180
+ key: 0,
181
+ class: "brand-version"
182
+ }, " v" + _toDisplayString(_ctx.appVersion), 1 /* TEXT */))
183
+ : _createCommentVNode("v-if", true)
196
184
  ])
197
185
  ])
198
186
  ])
199
- ], 40 /* PROPS, NEED_HYDRATION */, ["onMouseenter", "onMouseleave", "onFocus", "onBlur"]),
187
+ ]),
200
188
  _createElementVNode("div", { class: "side-rail-nav" }, [
201
189
  _createElementVNode("div", {
202
190
  class: "side-section",
@@ -437,7 +425,18 @@ return function render(_ctx, _cache) {
437
425
  : _createCommentVNode("v-if", true)
438
426
  ])
439
427
  ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["aria-current", "onPointerdown", "onClick"])
440
- ], 8 /* PROPS */, ["aria-label"])
428
+ ], 8 /* PROPS */, ["aria-label"]),
429
+ _createElementVNode("div", {
430
+ id: "side-tab-new",
431
+ class: "side-item side-item-ghost",
432
+ tabindex: "-1",
433
+ "aria-hidden": "true"
434
+ }, [
435
+ _createElementVNode("div", { class: "side-item-title" }, "New Tab"),
436
+ _createElementVNode("div", { class: "side-item-meta" }, [
437
+ _createElementVNode("span", null, " ")
438
+ ])
439
+ ])
441
440
  ]),
442
441
  _createElementVNode("div", {
443
442
  class: "side-rail-lang",
@@ -2668,7 +2667,7 @@ return function render(_ctx, _cache) {
2668
2667
  ], 512 /* NEED_PATCH */), [
2669
2668
  [_vShow, _ctx.mainTab === 'sessions']
2670
2669
  ]),
2671
- _createCommentVNode(" Usage 统计 - 时光之河设计 "),
2670
+ _createCommentVNode(" Usage 统计 - 流光设计 "),
2672
2671
  _withDirectives(_createElementVNode("div", {
2673
2672
  class: "mode-content",
2674
2673
  id: "panel-usage",
@@ -2848,11 +2847,11 @@ return function render(_ctx, _cache) {
2848
2847
  ])
2849
2848
  ])
2850
2849
  ]),
2851
- _createCommentVNode(" 波浪图:替换柱状图 "),
2850
+ _createCommentVNode(" 波浪图 "),
2852
2851
  (_ctx.sessionUsageWave.points && _ctx.sessionUsageWave.points.length)
2853
2852
  ? (_openBlock(), _createElementBlock("section", {
2854
2853
  key: 1,
2855
- class: "usage-card usage-wave-section"
2854
+ class: "usage-wave-section"
2856
2855
  }, [
2857
2856
  _createElementVNode("div", { class: "usage-card-title" }, _toDisplayString(_ctx.t('usage.daily.title')), 1 /* TEXT */),
2858
2857
  _createElementVNode("div", { class: "usage-wave-container" }, [
@@ -2872,7 +2871,7 @@ return function render(_ctx, _cache) {
2872
2871
  _createElementVNode("stop", {
2873
2872
  offset: "0%",
2874
2873
  "stop-color": 'var(--color-brand)',
2875
- "stop-opacity": "0.3"
2874
+ "stop-opacity": "0.35"
2876
2875
  }),
2877
2876
  _createElementVNode("stop", {
2878
2877
  offset: "100%",
@@ -2881,13 +2880,11 @@ return function render(_ctx, _cache) {
2881
2880
  })
2882
2881
  ], 8 /* PROPS */, ["id"])
2883
2882
  ]),
2884
- _createCommentVNode(" 填充区域 "),
2885
2883
  _createElementVNode("path", {
2886
2884
  d: _ctx.sessionUsageWave.areaPath,
2887
2885
  fill: 'url(#wave-gradient-' + _ctx.sessionsUsageTimeRange + ')',
2888
2886
  class: "usage-wave-area"
2889
2887
  }, null, 8 /* PROPS */, ["d", "fill"]),
2890
- _createCommentVNode(" 曲线 "),
2891
2888
  _createElementVNode("path", {
2892
2889
  d: _ctx.sessionUsageWave.linePath,
2893
2890
  fill: "none",
@@ -2897,7 +2894,6 @@ return function render(_ctx, _cache) {
2897
2894
  "stroke-linejoin": "round",
2898
2895
  class: "usage-wave-line"
2899
2896
  }, null, 8 /* PROPS */, ["d"]),
2900
- _createCommentVNode(" 悬停指示线 "),
2901
2897
  (_ctx.sessionsUsageSelectedDay)
2902
2898
  ? (_openBlock(), _createElementBlock("line", {
2903
2899
  key: 0,
@@ -2908,11 +2904,10 @@ return function render(_ctx, _cache) {
2908
2904
  stroke: "currentColor",
2909
2905
  "stroke-width": "1",
2910
2906
  "stroke-dasharray": "4 4",
2911
- opacity: "0.4",
2907
+ opacity: "0.5",
2912
2908
  class: "usage-wave-hover-line"
2913
2909
  }, null, 8 /* PROPS */, ["x2", "y1", "y2"]))
2914
2910
  : _createCommentVNode("v-if", true),
2915
- _createCommentVNode(" 悬停点 "),
2916
2911
  (_ctx.sessionsUsageSelectedDay)
2917
2912
  ? (_openBlock(), _createElementBlock("circle", {
2918
2913
  key: 1,
@@ -2956,8 +2951,8 @@ return function render(_ctx, _cache) {
2956
2951
  ]))
2957
2952
  : _createCommentVNode("v-if", true),
2958
2953
  _createElementVNode("div", { class: "usage-chart-grid" }, [
2959
- _createCommentVNode(" 热力图:垂直活动条 "),
2960
- _createElementVNode("section", { class: "usage-card usage-hourly-heatmap" }, [
2954
+ _createCommentVNode(" 热力图 "),
2955
+ _createElementVNode("section", { class: "usage-card-hourly-heatmap" }, [
2961
2956
  _createElementVNode("div", { class: "usage-card-title" }, _toDisplayString(_ctx.t('usage.hourlyHeatmap.title')), 1 /* TEXT */),
2962
2957
  _createElementVNode("div", { class: "hourly-heatmap-wrapper" }, [
2963
2958
  _createElementVNode("div", { class: "hourly-heatmap-header" }, [
@@ -3050,7 +3045,7 @@ return function render(_ctx, _cache) {
3050
3045
  ]))
3051
3046
  ]),
3052
3047
  _createCommentVNode(" Top Paths "),
3053
- _createElementVNode("section", { class: "usage-card usage-paths-section" }, [
3048
+ _createElementVNode("section", { class: "usage-paths-section" }, [
3054
3049
  _createElementVNode("div", { class: "usage-card-title" }, _toDisplayString(_ctx.t('usage.paths.title')), 1 /* TEXT */),
3055
3050
  (!_ctx.sessionUsageCharts.topPaths.length)
3056
3051
  ? (_openBlock(), _createElementBlock("div", {
@@ -415,6 +415,14 @@ body::after {
415
415
  word-break: break-word;
416
416
  }
417
417
 
418
+ .side-item-ghost {
419
+ opacity: 0;
420
+ pointer-events: none;
421
+ user-select: none;
422
+ cursor: default;
423
+ flex: 0 0 auto;
424
+ }
425
+
418
426
  @media (min-width: 721px) {
419
427
  body:not(.force-compact) #app > .top-tabs {
420
428
  display: none;
@@ -431,16 +439,6 @@ body::after {
431
439
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
432
440
  }
433
441
 
434
- .brand-block:focus-visible {
435
- outline: 2px solid rgba(0, 122, 255, 0.5);
436
- outline-offset: -2px;
437
- border-radius: 4px;
438
- }
439
-
440
- .brand-block:focus:not(:focus-visible) {
441
- outline: none;
442
- }
443
-
444
442
  .brand-head {
445
443
  display: flex;
446
444
  align-items: center;
@@ -484,7 +482,7 @@ body::after {
484
482
  }
485
483
 
486
484
  .brand-kicker {
487
- font-size: 13px;
485
+ font-size: 15px;
488
486
  line-height: 1.2;
489
487
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
490
488
  color: #1d1d1f;
@@ -502,10 +500,11 @@ body::after {
502
500
  }
503
501
 
504
502
  .brand-version {
505
- font-size: 12px;
503
+ font-size: 13px;
506
504
  font-weight: 400;
507
505
  color: #8e8e93;
508
506
  vertical-align: baseline;
507
+ -webkit-text-fill-color: #8e8e93;
509
508
  }
510
509
 
511
510
  .brand-version-fade-enter-active,
@@ -1,5 +1,5 @@
1
1
  /* ============================================
2
- Usage Tab — 时光之河设计
2
+ Usage Tab — 流光设计 (Flow of Light)
3
3
  ============================================ */
4
4
 
5
5
  /* ---- Toolbar ---- */
@@ -7,73 +7,80 @@
7
7
  display: flex;
8
8
  justify-content: space-between;
9
9
  align-items: center;
10
- gap: 12px;
10
+ gap: 16px;
11
11
  flex-wrap: wrap;
12
- margin-bottom: 20px;
12
+ margin-bottom: 28px;
13
13
  }
14
14
 
15
15
  .usage-toolbar-title {
16
- font-size: 18px;
16
+ font-size: 20px;
17
17
  font-weight: 600;
18
18
  color: var(--color-text-primary);
19
- letter-spacing: -0.02em;
19
+ letter-spacing: -0.03em;
20
20
  }
21
21
 
22
22
  .usage-range-group {
23
23
  display: flex;
24
- gap: 3px;
25
- padding: 4px;
26
- border-radius: 10px;
27
- background: var(--color-surface-alt);
28
- border: 1px solid var(--color-border-soft);
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);
29
31
  }
30
32
 
31
33
  .usage-range-btn {
32
34
  border: none;
33
35
  background: transparent;
34
36
  color: var(--color-text-tertiary);
35
- padding: 6px 14px;
36
- border-radius: 7px;
37
+ padding: 8px 16px;
38
+ border-radius: 9px;
37
39
  cursor: pointer;
38
40
  font-size: 13px;
39
41
  font-weight: 500;
40
42
  font-family: var(--font-family);
41
43
  white-space: nowrap;
42
- transition: all 150ms var(--ease-spring);
44
+ transition: all 180ms var(--ease-spring);
43
45
  outline: none;
44
46
  -webkit-tap-highlight-color: transparent;
45
47
  }
46
48
 
47
49
  .usage-range-btn:hover:not(:disabled) {
48
50
  color: var(--color-text-secondary);
49
- background: var(--color-surface);
51
+ background: rgba(200, 121, 99, 0.08);
50
52
  }
51
53
 
52
54
  .usage-range-btn:active:not(:disabled) {
53
- transform: scale(0.96);
55
+ transform: scale(0.95);
54
56
  }
55
57
 
56
58
  .usage-range-btn.active {
57
59
  color: #fff;
58
- background: var(--color-brand);
59
- box-shadow: 0 2px 8px rgba(200, 121, 99, 0.3);
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;
60
62
  }
61
63
 
62
64
  .usage-range-btn:disabled {
63
- opacity: 0.4;
65
+ opacity: 0.35;
64
66
  cursor: not-allowed;
65
67
  }
66
68
 
67
69
  .usage-range-btn-icon {
68
- padding: 6px 10px;
70
+ padding: 8px 12px;
69
71
  display: inline-flex;
70
72
  align-items: center;
71
73
  justify-content: center;
72
74
  }
73
75
 
74
76
  .usage-range-btn-icon svg {
75
- width: 15px;
76
- height: 15px;
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);
77
84
  }
78
85
 
79
86
  /* ---- Empty State (插画风格) ---- */
@@ -82,67 +89,87 @@
82
89
  flex-direction: column;
83
90
  align-items: center;
84
91
  justify-content: center;
85
- padding: 48px 20px;
92
+ padding: 64px 20px;
86
93
  text-align: center;
87
94
  }
88
95
 
89
96
  .usage-empty-illustration {
90
- width: 64px;
91
- height: 64px;
97
+ width: 72px;
98
+ height: 72px;
92
99
  color: var(--color-text-muted);
93
- opacity: 0.6;
94
- margin-bottom: 16px;
95
- animation: usage-empty-breathe 3s ease-in-out infinite;
100
+ opacity: 0.5;
101
+ margin-bottom: 20px;
102
+ animation: usage-empty-breathe 4s ease-in-out infinite;
96
103
  }
97
104
 
98
105
  @keyframes usage-empty-breathe {
99
- 0%, 100% { transform: scale(1); opacity: 0.5; }
100
- 50% { transform: scale(1.05); opacity: 0.7; }
106
+ 0%, 100% { transform: scale(1) translateY(0); opacity: 0.5; }
107
+ 50% { transform: scale(1.08) translateY(-4px); opacity: 0.7; }
101
108
  }
102
109
 
103
110
  .usage-empty-text {
104
- font-size: 13px;
111
+ font-size: 14px;
105
112
  color: var(--color-text-secondary);
106
- max-width: 280px;
113
+ max-width: 300px;
114
+ line-height: 1.6;
107
115
  }
108
116
 
109
- /* ---- Hero 区域 ---- */
117
+ /* ---- Hero 区域 (全宽沉浸式) ---- */
110
118
  .usage-hero {
111
- padding: 24px;
112
- margin-bottom: 20px;
113
- border-radius: 14px;
114
- background: var(--color-surface);
115
- border: 1px solid var(--color-border-soft);
116
- min-height: 140px;
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;
117
125
  display: flex;
118
126
  flex-direction: column;
119
127
  justify-content: center;
120
- gap: 16px;
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: -50%;
139
+ right: -20%;
140
+ width: 400px;
141
+ height: 400px;
142
+ background: radial-gradient(circle, rgba(200, 121, 99, 0.06) 0%, transparent 70%);
143
+ pointer-events: none;
121
144
  }
122
145
 
123
146
  .usage-hero-active {
124
147
  display: flex;
125
148
  flex-wrap: wrap;
126
149
  align-items: center;
127
- gap: 8px 12px;
128
- padding: 10px 16px;
129
- border-radius: 10px;
130
- background: var(--color-surface-alt);
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);
131
155
  font-size: 12px;
156
+ position: relative;
157
+ z-index: 1;
132
158
  }
133
159
 
134
160
  .usage-hero-active-dot {
135
- width: 6px;
136
- height: 6px;
161
+ width: 7px;
162
+ height: 7px;
137
163
  border-radius: 50%;
138
164
  background: var(--color-success);
139
165
  flex-shrink: 0;
140
- animation: usage-pulse 2s ease-in-out infinite;
166
+ animation: usage-pulse 2.2s ease-in-out infinite;
167
+ box-shadow: 0 0 12px rgba(75, 139, 106, 0.4);
141
168
  }
142
169
 
143
170
  @keyframes usage-pulse {
144
171
  0%, 100% { opacity: 1; transform: scale(1); }
145
- 50% { opacity: 0.4; transform: scale(0.9); }
172
+ 50% { opacity: 0.5; transform: scale(0.85); }
146
173
  }
147
174
 
148
175
  .usage-hero-active-label {
@@ -156,122 +183,162 @@
156
183
 
157
184
  .usage-hero-active-stat::before {
158
185
  content: '·';
159
- margin-right: 10px;
186
+ margin-right: 12px;
160
187
  color: var(--color-border-strong);
161
188
  }
162
189
 
163
190
  .usage-hero-metrics {
164
191
  text-align: center;
192
+ position: relative;
193
+ z-index: 1;
165
194
  }
166
195
 
167
196
  .usage-hero-main {
168
- font-size: 42px;
197
+ font-size: 52px;
169
198
  font-weight: 700;
170
199
  color: var(--color-text-primary);
171
200
  line-height: 1;
172
- letter-spacing: -0.03em;
201
+ letter-spacing: -0.04em;
173
202
  font-variant-numeric: tabular-nums;
174
- animation: usage-hero-count 0.8s ease-out;
203
+ animation: usage-hero-count 1s var(--ease-out-expo);
204
+ background: linear-gradient(135deg, var(--color-text-primary) 0%, var(--color-brand) 100%);
205
+ -webkit-background-clip: text;
206
+ -webkit-text-fill-color: transparent;
207
+ background-clip: text;
175
208
  }
176
209
 
177
210
  @keyframes usage-hero-count {
178
- from { opacity: 0; transform: translateY(10px); }
179
- to { opacity: 1; transform: translateY(0); }
211
+ from { opacity: 0; transform: translateY(16px) scale(0.95); }
212
+ to { opacity: 1; transform: translateY(0) scale(1); }
180
213
  }
181
214
 
182
215
  .usage-hero-sub {
183
- margin-top: 8px;
184
- font-size: 13px;
216
+ margin-top: 10px;
217
+ font-size: 14px;
185
218
  color: var(--color-text-tertiary);
186
219
  display: flex;
187
220
  align-items: center;
188
221
  justify-content: center;
189
- gap: 12px;
222
+ gap: 14px;
190
223
  flex-wrap: wrap;
191
224
  }
192
225
 
193
226
  .usage-hero-delta {
194
227
  font-size: 12px;
195
228
  font-weight: 600;
196
- padding: 2px 8px;
197
- border-radius: 12px;
229
+ padding: 3px 10px;
230
+ border-radius: 16px;
198
231
  }
199
232
 
200
233
  .usage-hero-delta.delta-up {
201
- color: var(--color-delta-up);
202
- background: rgba(76, 175, 80, 0.12);
234
+ color: var(--color-success);
235
+ background: linear-gradient(135deg, rgba(75, 139, 106, 0.15), rgba(75, 139, 106, 0.08));
203
236
  }
204
237
 
205
238
  .usage-hero-delta.delta-down {
206
- color: var(--color-delta-down);
207
- background: rgba(244, 67, 54, 0.12);
239
+ color: var(--color-error);
240
+ background: linear-gradient(135deg, rgba(196, 69, 54, 0.15), rgba(196, 69, 54, 0.08));
208
241
  }
209
242
 
210
- /* ---- 波浪图 ---- */
243
+ /* ---- 波浪图 (流体动画) ---- */
211
244
  .usage-wave-section {
212
245
  overflow: hidden;
246
+ border: none;
247
+ background: transparent;
248
+ padding: 0;
249
+ margin-bottom: 24px;
213
250
  }
214
251
 
215
252
  .usage-wave-container {
216
- margin-top: 12px;
253
+ margin-top: 16px;
217
254
  position: relative;
255
+ padding: 20px;
256
+ border-radius: 18px;
257
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
258
+ border: 1px solid rgba(137, 111, 94, 0.06);
259
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
260
+ backdrop-filter: blur(8px);
218
261
  }
219
262
 
220
263
  .usage-wave-chart {
221
264
  width: 100%;
222
- height: 140px;
265
+ height: 150px;
223
266
  display: block;
224
267
  }
225
268
 
226
269
  .usage-wave-area {
227
- transition: d 0.4s var(--ease-spring);
270
+ transition: d 600ms var(--ease-spring);
271
+ animation: usage-wave-pulse 4s ease-in-out infinite;
272
+ }
273
+
274
+ @keyframes usage-wave-pulse {
275
+ 0%, 100% { opacity: 1; }
276
+ 50% { opacity: 0.85; }
228
277
  }
229
278
 
230
279
  .usage-wave-line {
231
- transition: d 0.4s var(--ease-spring);
280
+ transition: d 600ms var(--ease-spring);
281
+ filter: drop-shadow(0 4px 12px rgba(200, 121, 99, 0.25));
232
282
  }
233
283
 
234
284
  .usage-wave-hover-line {
235
- transition: x1 0.2s, x2 0.2s, y1 0.2s, y2 0.2s;
285
+ transition: x1 200ms var(--ease-spring), x2 200ms var(--ease-spring),
286
+ y1 200ms var(--ease-spring), y2 200ms var(--ease-spring);
287
+ stroke-dasharray: 4 4;
288
+ animation: usage-hover-dash 20s linear infinite;
289
+ }
290
+
291
+ @keyframes usage-hover-dash {
292
+ to { stroke-dashoffset: -100; }
236
293
  }
237
294
 
238
295
  .usage-wave-hover-point {
239
- transition: cx 0.2s, cy 0.2s;
296
+ transition: cx 200ms var(--ease-spring), cy 200ms var(--ease-spring);
297
+ filter: drop-shadow(0 0 8px rgba(200, 121, 99, 0.4));
298
+ animation: usage-point-pulse 2s ease-in-out infinite;
299
+ }
300
+
301
+ @keyframes usage-point-pulse {
302
+ 0%, 100% { r: 5; }
303
+ 50% { r: 6.5; }
240
304
  }
241
305
 
242
306
  .usage-wave-labels {
243
307
  display: flex;
244
308
  justify-content: space-between;
245
- margin-top: 8px;
246
- padding: 0 4px;
309
+ margin-top: 12px;
310
+ padding: 0 8px;
247
311
  }
248
312
 
249
313
  .usage-wave-label {
250
- font-size: 10px;
314
+ font-size: 11px;
251
315
  color: var(--color-text-muted);
252
316
  cursor: pointer;
253
- padding: 2px 6px;
254
- border-radius: 4px;
255
- transition: all 0.15s ease-out;
317
+ padding: 4px 8px;
318
+ border-radius: 6px;
319
+ transition: all 180ms var(--ease-spring);
256
320
  -webkit-tap-highlight-color: transparent;
321
+ font-weight: 500;
257
322
  }
258
323
 
259
324
  .usage-wave-label:hover {
260
325
  color: var(--color-text-secondary);
261
- background: var(--color-surface-alt);
326
+ background: rgba(200, 121, 99, 0.08);
262
327
  }
263
328
 
264
329
  .usage-wave-label.active {
265
330
  color: var(--color-brand);
266
331
  font-weight: 600;
332
+ background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
267
333
  }
268
334
 
269
335
  /* ---- 日期详情 ---- */
270
336
  .usage-daydetail {
271
337
  margin-top: 16px;
272
- padding: 12px 16px;
273
- border-radius: 10px;
274
- background: var(--color-surface-alt);
338
+ padding: 14px 18px;
339
+ border-radius: 12px;
340
+ background: linear-gradient(135deg, rgba(247, 239, 232, 0.8), rgba(247, 239, 232, 0.4));
341
+ border: 1px solid rgba(137, 111, 94, 0.06);
275
342
  }
276
343
 
277
344
  .usage-daydetail-header {
@@ -284,7 +351,7 @@
284
351
 
285
352
  .usage-daydetail-date {
286
353
  font-weight: 600;
287
- font-size: 13px;
354
+ font-size: 14px;
288
355
  color: var(--color-text-primary);
289
356
  }
290
357
 
@@ -294,32 +361,41 @@
294
361
  }
295
362
 
296
363
  .usage-daydetail-compare {
297
- margin-top: 4px;
364
+ margin-top: 6px;
298
365
  font-size: 11px;
299
366
  color: var(--color-text-muted);
300
367
  }
301
368
 
302
- /* ---- 热力图 ---- */
369
+ /* ---- 热力图 (动态呼吸) ---- */
303
370
  .usage-card-hourly-heatmap {
304
371
  overflow-x: auto;
372
+ border: none;
373
+ background: transparent;
374
+ padding: 0;
305
375
  }
306
376
 
307
377
  .hourly-heatmap-wrapper {
308
378
  display: flex;
309
379
  flex-direction: column;
310
- gap: 2px;
311
- margin-top: 10px;
312
- min-width: 480px;
380
+ gap: 3px;
381
+ margin-top: 14px;
382
+ min-width: 500px;
383
+ padding: 16px;
384
+ border-radius: 18px;
385
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
386
+ border: 1px solid rgba(137, 111, 94, 0.06);
387
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
388
+ backdrop-filter: blur(8px);
313
389
  }
314
390
 
315
391
  .hourly-heatmap-header {
316
392
  display: flex;
317
- gap: 2px;
393
+ gap: 3px;
318
394
  align-items: flex-end;
319
395
  }
320
396
 
321
397
  .hourly-heatmap-corner {
322
- width: 32px;
398
+ width: 36px;
323
399
  flex-shrink: 0;
324
400
  }
325
401
 
@@ -334,83 +410,130 @@
334
410
 
335
411
  .hourly-heatmap-row {
336
412
  display: flex;
337
- gap: 2px;
413
+ gap: 3px;
338
414
  align-items: center;
339
415
  }
340
416
 
341
417
  .hourly-heatmap-weekday-label {
342
- width: 32px;
418
+ width: 36px;
343
419
  flex-shrink: 0;
344
- font-size: 10px;
420
+ font-size: 11px;
345
421
  color: var(--color-text-secondary);
346
422
  text-align: right;
347
- padding-right: 4px;
423
+ padding-right: 6px;
424
+ font-weight: 500;
348
425
  }
349
426
 
350
427
  .hourly-heatmap-cell {
351
428
  flex: 1;
352
429
  min-width: 0;
353
- height: 6px;
354
- border-radius: 3px;
355
- transition: background 0.15s ease-out;
430
+ height: 7px;
431
+ border-radius: 4px;
432
+ transition: all 200ms var(--ease-spring);
433
+ cursor: crosshair;
434
+ }
435
+
436
+ .hourly-heatmap-cell:hover {
437
+ transform: scaleY(1.4);
438
+ filter: brightness(1.1);
439
+ }
440
+
441
+ .hourly-heatmap-cell.level-0 {
442
+ background: var(--color-surface-alt);
443
+ }
444
+ .hourly-heatmap-cell.level-1 {
445
+ background: var(--color-heatmap-1);
446
+ animation: heatmap-breath-1 3s ease-in-out infinite;
447
+ }
448
+ .hourly-heatmap-cell.level-2 {
449
+ background: var(--color-heatmap-2);
450
+ animation: heatmap-breath-2 3s ease-in-out infinite;
451
+ }
452
+ .hourly-heatmap-cell.level-3 {
453
+ background: var(--color-heatmap-3);
454
+ animation: heatmap-breath-3 3s ease-in-out infinite;
455
+ }
456
+ .hourly-heatmap-cell.level-4 {
457
+ background: var(--color-heatmap-4);
458
+ animation: heatmap-breath-4 3s ease-in-out infinite;
459
+ box-shadow: 0 0 8px rgba(200, 121, 99, 0.3);
356
460
  }
357
461
 
358
- .hourly-heatmap-cell.level-0 { background: var(--color-surface-alt); }
359
- .hourly-heatmap-cell.level-1 { background: var(--color-heatmap-1); }
360
- .hourly-heatmap-cell.level-2 { background: var(--color-heatmap-2); }
361
- .hourly-heatmap-cell.level-3 { background: var(--color-heatmap-3); }
362
- .hourly-heatmap-cell.level-4 { background: var(--color-heatmap-4); }
462
+ @keyframes heatmap-breath-1 {
463
+ 0%, 100% { opacity: 1; }
464
+ 50% { opacity: 0.85; }
465
+ }
466
+ @keyframes heatmap-breath-2 {
467
+ 0%, 100% { opacity: 1; }
468
+ 50% { opacity: 0.9; }
469
+ }
470
+ @keyframes heatmap-breath-3 {
471
+ 0%, 100% { opacity: 1; }
472
+ 50% { opacity: 0.95; }
473
+ }
474
+ @keyframes heatmap-breath-4 {
475
+ 0%, 100% { opacity: 1; box-shadow: 0 0 8px rgba(200, 121, 99, 0.3); }
476
+ 50% { opacity: 0.9; box-shadow: 0 0 14px rgba(200, 121, 99, 0.5); }
477
+ }
363
478
 
364
479
  .hourly-heatmap-legend {
365
480
  display: flex;
366
481
  align-items: center;
367
- gap: 3px;
482
+ gap: 4px;
368
483
  justify-content: flex-end;
369
- margin-top: 10px;
484
+ margin-top: 12px;
370
485
  font-size: 10px;
371
486
  color: var(--color-text-muted);
372
487
  }
373
488
 
374
489
  .hourly-heatmap-legend .hourly-heatmap-cell {
375
- width: 11px;
376
- height: 11px;
490
+ width: 12px;
491
+ height: 12px;
492
+ border-radius: 3px;
377
493
  }
378
494
 
379
495
  .hourly-heatmap-legend-label {
380
- margin: 0 2px;
496
+ margin: 0 4px;
381
497
  }
382
498
 
383
- /* ---- 列表样式 ---- */
499
+ /* ---- 列表样式 (加大间距) ---- */
384
500
  .usage-list-compact {
385
501
  display: flex;
386
502
  flex-direction: column;
387
- gap: 4px;
503
+ gap: 6px;
388
504
  }
389
505
 
390
506
  .usage-list-compact-item {
391
507
  display: flex;
392
508
  align-items: flex-start;
393
- gap: 8px;
394
- padding: 8px 10px;
395
- border-radius: 8px;
509
+ gap: 10px;
510
+ padding: 10px 14px;
511
+ border-radius: 10px;
396
512
  cursor: pointer;
397
- transition: all 0.15s ease-out;
513
+ transition: all 180ms var(--ease-spring);
398
514
  -webkit-tap-highlight-color: transparent;
399
515
  }
400
516
 
401
517
  .usage-list-compact-item:hover {
402
- background: var(--color-surface-elevated);
518
+ background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(252,248,241,0.7));
519
+ transform: translateX(4px);
520
+ box-shadow: 0 2px 8px rgba(92, 68, 52, 0.06);
403
521
  }
404
522
 
405
523
  .usage-list-compact-item:active {
406
- transform: scale(0.98);
524
+ transform: translateX(2px) scale(0.98);
407
525
  }
408
526
 
409
527
  .usage-list-bullet {
410
528
  color: var(--color-brand);
411
- font-size: 14px;
529
+ font-size: 16px;
412
530
  line-height: 1.4;
413
531
  flex-shrink: 0;
532
+ opacity: 0.7;
533
+ }
534
+
535
+ .usage-list-compact-item:hover .usage-list-bullet {
536
+ opacity: 1;
414
537
  }
415
538
 
416
539
  .usage-list-compact-content {
@@ -419,7 +542,7 @@
419
542
  }
420
543
 
421
544
  .usage-list-title {
422
- font-size: 12px;
545
+ font-size: 13px;
423
546
  font-weight: 500;
424
547
  color: var(--color-text-primary);
425
548
  overflow: hidden;
@@ -430,50 +553,60 @@
430
553
  .usage-list-meta {
431
554
  font-size: 11px;
432
555
  color: var(--color-text-muted);
433
- margin-top: 2px;
556
+ margin-top: 3px;
434
557
  }
435
558
 
436
559
  .usage-list-value {
437
- font-size: 12px;
560
+ font-size: 13px;
438
561
  color: var(--color-text-secondary);
439
- padding: 8px 0;
562
+ padding: 10px 0;
440
563
  }
441
564
 
442
565
  /* ---- Path 列表 ---- */
443
566
  .usage-paths-section {
444
567
  grid-column: 1 / -1;
568
+ border: none;
569
+ background: transparent;
570
+ padding: 0;
445
571
  }
446
572
 
447
573
  .usage-list-paths {
448
574
  display: flex;
449
575
  flex-direction: column;
450
- gap: 6px;
576
+ gap: 8px;
577
+ padding: 16px;
578
+ border-radius: 18px;
579
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
580
+ border: 1px solid rgba(137, 111, 94, 0.06);
581
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
582
+ backdrop-filter: blur(8px);
451
583
  }
452
584
 
453
585
  .usage-list-path-row {
454
586
  display: flex;
455
587
  align-items: center;
456
- gap: 10px;
457
- padding: 8px 10px;
458
- border-radius: 8px;
459
- transition: background 0.15s ease-out;
588
+ gap: 12px;
589
+ padding: 10px 12px;
590
+ border-radius: 10px;
591
+ transition: all 180ms var(--ease-spring);
460
592
  }
461
593
 
462
594
  .usage-list-path-row:hover {
463
- background: var(--color-surface-alt);
595
+ background: rgba(255, 255, 255, 0.7);
596
+ transform: translateX(4px);
464
597
  }
465
598
 
466
599
  .usage-list-path-rank {
467
- width: 18px;
468
- height: 18px;
600
+ width: 22px;
601
+ height: 22px;
469
602
  display: flex;
470
603
  align-items: center;
471
604
  justify-content: center;
472
- font-size: 10px;
605
+ font-size: 11px;
473
606
  font-weight: 600;
474
607
  color: var(--color-brand);
475
- background: var(--color-surface-alt);
476
- border-radius: 4px;
608
+ background: linear-gradient(135deg, rgba(200, 121, 99, 0.12), rgba(200, 121, 99, 0.06));
609
+ border-radius: 6px;
477
610
  flex-shrink: 0;
478
611
  }
479
612
 
@@ -482,7 +615,7 @@
482
615
  display: flex;
483
616
  justify-content: space-between;
484
617
  align-items: center;
485
- gap: 10px;
618
+ gap: 12px;
486
619
  min-width: 0;
487
620
  }
488
621
 
@@ -496,34 +629,45 @@
496
629
  }
497
630
 
498
631
  .usage-list-path-stat {
499
- font-size: 13px;
632
+ font-size: 14px;
500
633
  font-weight: 600;
501
634
  color: var(--color-text-primary);
502
635
  font-variant-numeric: tabular-nums;
503
636
  flex-shrink: 0;
504
637
  }
505
638
 
506
- /* ---- 卡片 ---- */
639
+ /* ---- 卡片 (无边框浮动式) ---- */
507
640
  .usage-card {
508
- padding: 20px;
509
- border-radius: 14px;
510
- background: var(--color-surface);
511
- border: 1px solid var(--color-border-soft);
641
+ padding: 0;
642
+ border-radius: 0;
643
+ background: transparent;
644
+ border: none;
512
645
  margin-bottom: 0;
513
646
  }
514
647
 
515
648
  .usage-card-title {
516
- font-size: 14px;
649
+ font-size: 15px;
517
650
  font-weight: 600;
518
651
  color: var(--color-text-primary);
519
- margin-bottom: 4px;
652
+ margin-bottom: 0;
653
+ letter-spacing: -0.02em;
520
654
  }
521
655
 
522
- /* ---- 图表网格 ---- */
656
+ /* ---- 图表网格 (加大间距) ---- */
523
657
  .usage-chart-grid {
524
658
  display: grid;
525
659
  grid-template-columns: repeat(2, 1fr);
526
- gap: 12px;
660
+ gap: 20px;
661
+ }
662
+
663
+ /* 为非 paths 卡片添加容器 */
664
+ .usage-chart-grid > .usage-card:not(.usage-paths-section):not(.usage-wave-section):not(.usage-card-hourly-heatmap) {
665
+ padding: 16px;
666
+ border-radius: 18px;
667
+ background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(252,248,241,0.6));
668
+ border: 1px solid rgba(137, 111, 94, 0.06);
669
+ box-shadow: 0 4px 20px rgba(92, 68, 52, 0.05);
670
+ backdrop-filter: blur(8px);
527
671
  }
528
672
 
529
673
  /* ---- 内容区域 ---- */
@@ -532,7 +676,7 @@
532
676
  }
533
677
 
534
678
  .usage-content-loading {
535
- opacity: 0.7;
679
+ opacity: 0.6;
536
680
  pointer-events: none;
537
681
  }
538
682
 
@@ -542,15 +686,15 @@
542
686
  display: flex;
543
687
  align-items: flex-start;
544
688
  justify-content: flex-end;
545
- padding: 12px;
546
- z-index: 1;
689
+ padding: 16px;
690
+ z-index: 10;
547
691
  }
548
692
 
549
693
  .usage-spinner {
550
- width: 16px;
551
- height: 16px;
694
+ width: 18px;
695
+ height: 18px;
552
696
  border-radius: 50%;
553
- border: 2px solid var(--color-border-soft);
697
+ border: 2px solid rgba(137, 111, 94, 0.15);
554
698
  border-top-color: var(--color-brand);
555
699
  animation: usage-spin 0.8s linear infinite;
556
700
  }
@@ -566,7 +710,7 @@
566
710
  }
567
711
 
568
712
  .usage-hero-main {
569
- font-size: 36px;
713
+ font-size: 44px;
570
714
  }
571
715
  }
572
716
 
@@ -582,24 +726,28 @@
582
726
  }
583
727
 
584
728
  .usage-hero {
585
- padding: 20px;
586
- min-height: 120px;
729
+ padding: 24px 20px;
730
+ min-height: 140px;
587
731
  }
588
732
 
589
733
  .usage-hero-main {
590
- font-size: 32px;
734
+ font-size: 38px;
591
735
  }
592
736
 
593
737
  .usage-wave-chart {
594
- height: 100px;
738
+ height: 110px;
595
739
  }
596
740
 
597
741
  .usage-wave-labels {
598
- font-size: 9px;
742
+ font-size: 10px;
599
743
  }
600
744
 
601
745
  .hourly-heatmap-wrapper {
602
746
  min-width: 100%;
603
747
  overflow-x: auto;
604
748
  }
749
+
750
+ .usage-chart-grid {
751
+ gap: 16px;
752
+ }
605
753
  }