antigravity-claude-proxy 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,6 @@
1
1
  <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <defs>
3
- <linearGradient id="favicon_grad" x1="0" y1="0" x2="32" y2="32" gradientUnits="userSpaceOnUse">
4
- <stop stop-color="#A855F7" />
5
- <stop offset="1" stop-color="#2563EB" />
6
- </linearGradient>
7
- </defs>
8
- <rect width="32" height="32" rx="6" fill="url(#favicon_grad)" />
9
- <text x="50%" y="50%" dominant-baseline="central" text-anchor="middle" fill="white" font-family="Inter, system-ui, sans-serif" font-weight="800" font-size="14">AG</text>
2
+ <rect width="32" height="32" rx="7" fill="#111214" />
3
+ <ellipse cx="16" cy="16" rx="12" ry="5.75" transform="rotate(-28 16 16)" stroke="#87857f" stroke-width="1.5" />
4
+ <circle cx="16" cy="16" r="4.5" fill="#eceae4" />
5
+ <circle cx="26" cy="10.4" r="2.6" fill="#d45bc2" />
10
6
  </svg>
package/public/index.html CHANGED
@@ -12,12 +12,18 @@
12
12
  <!-- Alpine.js must be deferred so stores register their listeners first -->
13
13
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
14
14
 
15
+ <!-- Fonts -->
16
+ <link rel="preconnect" href="https://fonts.googleapis.com">
17
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
18
+ <link rel="stylesheet"
19
+ href="https://fonts.googleapis.com/css2?family=B612:wght@400;700&family=B612+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400;500;600&display=swap">
20
+
15
21
  <!-- Compiled Tailwind CSS (includes DaisyUI) -->
16
22
  <link rel="stylesheet" href="css/style.css">
17
23
  </head>
18
24
 
19
25
  <body
20
- class="bg-space-950 text-gray-300 font-sans antialiased min-h-screen overflow-hidden selection:bg-neon-purple selection:text-white"
26
+ class="bg-space-950 text-gray-300 font-sans antialiased min-h-screen overflow-hidden "
21
27
  x-cloak x-data="app" x-init="if(window.UILogger) window.UILogger.debug('App initialized')">
22
28
 
23
29
  <!-- Toast Notification -->
@@ -29,10 +35,10 @@
29
35
  x-transition:leave="transition ease-in duration-200"
30
36
  x-transition:leave-start="opacity-100 translate-x-0 scale-100"
31
37
  x-transition:leave-end="opacity-0 translate-x-4 scale-95"
32
- class="alert shadow-lg border backdrop-blur-md pointer-events-auto min-w-[300px]" :class="{
33
- 'alert-info border-neon-cyan/20 bg-space-900/90 text-neon-cyan': $store.global.toast.type === 'info',
34
- 'alert-success border-neon-green/20 bg-space-900/90 text-neon-green': $store.global.toast.type === 'success',
35
- 'alert-error border-red-500/20 bg-space-900/90 text-red-400': $store.global.toast.type === 'error'
38
+ class="alert rounded-lg border bg-space-850 pointer-events-auto min-w-[300px] shadow-[0_8px_24px_-8px_rgba(0,0,0,0.6)]" :class="{
39
+ 'border-neon-cyan/30 text-gray-200 [&_svg]:text-neon-cyan': $store.global.toast.type === 'info',
40
+ 'border-neon-green/30 text-gray-200 [&_svg]:text-neon-green': $store.global.toast.type === 'success',
41
+ 'border-neon-red/30 text-gray-200 [&_svg]:text-neon-red': $store.global.toast.type === 'error'
36
42
  }">
37
43
  <div class="flex items-center gap-3">
38
44
  <!-- Icons based on type -->
@@ -54,7 +60,7 @@
54
60
  d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
55
61
  </svg>
56
62
  </template>
57
- <span x-text="$store.global.toast.message" class="font-mono text-sm"></span>
63
+ <span x-text="$store.global.toast.message" class="text-sm"></span>
58
64
  </div>
59
65
  </div>
60
66
  </template>
@@ -62,47 +68,47 @@
62
68
 
63
69
  <!-- Navbar -->
64
70
  <div
65
- class="h-14 border-b border-space-border flex items-center px-4 lg:px-6 justify-between bg-space-900/50 backdrop-blur-md z-50 relative">
71
+ class="app-topbar h-14 flex items-center px-3 lg:px-4 justify-between z-50 relative">
66
72
  <div class="flex items-center gap-3">
67
73
  <!-- Mobile Menu Button -->
68
- <button @click="toggleSidebar()" class="text-gray-400 hover:text-white focus:outline-none p-1 transition-colors">
69
- <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
70
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
74
+ <button @click="toggleSidebar()" class="text-gray-500 hover:text-white rounded-md p-1.5 hover:bg-space-800 transition-colors" aria-label="Toggle navigation">
75
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
76
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75" d="M4 7h16M4 12h16M4 17h10" />
71
77
  </svg>
72
78
  </button>
73
79
 
74
- <div
75
- class="w-8 h-8 rounded bg-gradient-to-br from-neon-purple to-blue-600 flex items-center justify-center text-white font-bold shadow-[0_0_15px_rgba(168,85,247,0.4)]">
76
- AG</div>
77
- <div class="flex flex-col">
78
- <span class="text-sm font-bold tracking-wide text-white"
79
- x-text="$store.global.t('systemName')">ANTIGRAVITY</span>
80
- <div class="flex items-center gap-1.5">
81
- <span class="text-[10px] text-gray-500 font-mono tracking-wider"
82
- x-text="$store.global.t('systemDesc')">CLAUDE PROXY SYSTEM</span>
83
- <span class="text-[10px] text-gray-500 font-mono tracking-wider"
84
- x-text="'v' + $store.global.version">v1.0.0</span>
85
- </div>
80
+ <!-- Brand: a body held in orbit -->
81
+ <svg class="w-7 h-7 shrink-0" viewBox="0 0 28 28" fill="none" aria-hidden="true">
82
+ <ellipse cx="14" cy="14" rx="11.5" ry="5.5" transform="rotate(-28 14 14)" stroke="#87857f" stroke-width="1.25"/>
83
+ <circle cx="14" cy="14" r="4" fill="#eceae4"/>
84
+ <circle cx="23.6" cy="8.6" r="2.2" fill="#d45bc2"/>
85
+ </svg>
86
+ <div class="flex items-baseline gap-2.5">
87
+ <span class="font-display text-[15px] font-bold text-white"
88
+ x-text="$store.global.t('systemName')">Antigravity</span>
89
+ <span class="hidden sm:inline text-xs text-gray-500"
90
+ x-text="$store.global.t('systemDesc')">Claude proxy</span>
91
+ <span class="hidden sm:inline text-xs text-gray-600 font-mono"
92
+ x-text="'v' + $store.global.version">v1.0.0</span>
86
93
  </div>
87
94
  </div>
88
95
 
89
- <div class="flex items-center gap-4">
96
+ <div class="flex items-center gap-3">
90
97
  <!-- Connection Pill -->
91
- <div class="flex items-center gap-2 px-3 py-1 rounded-full text-xs font-mono border transition-all duration-300"
98
+ <div class="flex items-center gap-2 px-2.5 py-1 rounded-full text-xs font-medium border border-space-border transition-colors duration-300"
92
99
  :class="connectionStatus === 'connected'
93
- ? 'bg-neon-green/10 border-neon-green/20 text-neon-green'
94
- : (connectionStatus === 'connecting' ? 'bg-yellow-500/10 border-yellow-500/20 text-yellow-500' : 'bg-red-500/10 border-red-500/20 text-red-500')">
100
+ ? 'text-gray-300'
101
+ : (connectionStatus === 'connecting' ? 'text-neon-yellow' : 'text-neon-red border-neon-red/30')">
95
102
  <div class="w-1.5 h-1.5 rounded-full"
96
- :class="connectionStatus === 'connected' ? 'bg-neon-green shadow-[0_0_8px_rgba(34,197,94,0.6)]' : (connectionStatus === 'connecting' ? 'bg-yellow-500 animate-pulse' : 'bg-red-500')">
103
+ :class="connectionStatus === 'connected' ? 'bg-neon-green' : (connectionStatus === 'connecting' ? 'bg-neon-yellow animate-pulse' : 'bg-neon-red')">
97
104
  </div>
98
105
  <span
99
106
  x-text="connectionStatus === 'connected' ? $store.global.t('online') : (connectionStatus === 'disconnected' ? $store.global.t('offline') : $store.global.t('connecting'))"></span>
100
107
  </div>
101
108
 
102
- <div class="h-4 w-px bg-space-border"></div>
103
-
109
+
104
110
  <!-- Refresh Button -->
105
- <button type="button" class="btn btn-ghost btn-xs btn-square text-gray-400 hover:text-white hover:bg-white/5"
111
+ <button type="button" class="btn btn-ghost btn-sm btn-square text-gray-500 hover:text-white hover:bg-space-800"
106
112
  @click="fetchData" :disabled="loading" :title="$store.global.t('refreshData')" aria-label="Refresh data">
107
113
  <svg class="w-4 h-4" :class="{'animate-spin': loading}" fill="none" stroke="currentColor"
108
114
  viewBox="0 0 24 24">
@@ -129,7 +135,7 @@
129
135
  style="display: none;"></div>
130
136
 
131
137
  <!-- Sidebar -->
132
- <div class="fixed top-14 bottom-0 left-0 z-40 bg-space-900 border-r border-space-border transition-all duration-300 shadow-2xl overflow-hidden lg:static lg:h-auto lg:shadow-none lg:flex-shrink-0"
138
+ <div class="app-sidebar fixed top-14 bottom-0 left-0 z-40 border-r border-space-border transition-all duration-300 shadow-2xl overflow-hidden lg:static lg:h-auto lg:shadow-none lg:flex-shrink-0"
133
139
  :class="{
134
140
  'translate-x-0': sidebarOpen,
135
141
  '-translate-x-full': !sidebarOpen,
@@ -140,7 +146,7 @@
140
146
  }">
141
147
 
142
148
  <!-- Inner Sidebar Content (Fixed Width to prevent squashing) -->
143
- <div class="w-64 flex flex-col h-full pt-6 pb-4 flex-shrink-0">
149
+ <div class="w-64 flex flex-col h-full pt-5 pb-4 flex-shrink-0">
144
150
  <!-- Mobile Menu Header -->
145
151
  <div class="flex items-center justify-between px-4 mb-6 lg:hidden">
146
152
  <span class="text-sm font-bold text-white" x-text="$store.global.t('menu')">Menu</span>
@@ -152,60 +158,60 @@
152
158
  </div>
153
159
 
154
160
  <!-- Desktop Header (Main) -->
155
- <div class="px-4 mb-2 text-xs font-bold text-gray-600 uppercase tracking-widest hidden lg:block"
161
+ <div class="nav-section-label hidden lg:block"
156
162
  x-text="$store.global.t('main')">Main</div>
157
163
 
158
- <nav class="flex flex-col gap-1">
164
+ <nav class="flex flex-col gap-0.5">
159
165
  <button
160
- class="nav-item flex items-center gap-3 px-6 py-3 text-sm font-medium text-gray-400 hover:text-white hover:bg-white/5"
166
+ class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
161
167
  :class="{'active': $store.global.activeTab === 'dashboard'}"
162
168
  @click="$store.global.activeTab = 'dashboard'">
163
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
164
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
169
+ <svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
170
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
165
171
  d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
166
172
  </svg>
167
173
  <span x-text="$store.global.t('dashboard')">Dashboard</span>
168
174
  </button>
169
175
  <button
170
- class="nav-item flex items-center gap-3 px-6 py-3 text-sm font-medium text-gray-400 hover:text-white hover:bg-white/5"
176
+ class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
171
177
  :class="{'active': $store.global.activeTab === 'models'}"
172
178
  @click="$store.global.activeTab = 'models'">
173
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
174
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
179
+ <svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
180
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
175
181
  d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
176
182
  </svg>
177
183
  <span x-text="$store.global.t('models')">Models</span>
178
184
  </button>
179
185
  <button
180
- class="nav-item flex items-center gap-3 px-6 py-3 text-sm font-medium text-gray-400 hover:text-white hover:bg-white/5"
186
+ class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
181
187
  :class="{'active': $store.global.activeTab === 'accounts'}"
182
188
  @click="$store.global.activeTab = 'accounts'">
183
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
184
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
189
+ <svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
190
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
185
191
  d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
186
192
  </svg>
187
193
  <span x-text="$store.global.t('accounts')">Accounts</span>
188
194
  </button>
189
195
  </nav>
190
196
 
191
- <div class="px-4 mt-8 mb-2 text-xs font-bold text-gray-600 uppercase tracking-widest"
197
+ <div class="nav-section-label mt-7"
192
198
  x-text="$store.global.t('system')">System</div>
193
- <nav class="flex flex-col gap-1">
199
+ <nav class="flex flex-col gap-0.5">
194
200
  <button
195
- class="nav-item flex items-center gap-3 px-6 py-3 text-sm font-medium text-gray-400 hover:text-white hover:bg-white/5"
201
+ class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
196
202
  :class="{'active': $store.global.activeTab === 'logs'}" @click="$store.global.activeTab = 'logs'">
197
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
198
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
203
+ <svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
204
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
199
205
  d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
200
206
  </svg>
201
207
  <span x-text="$store.global.t('logs')">Logs</span>
202
208
  </button>
203
209
  <button
204
- class="nav-item flex items-center gap-3 px-6 py-3 text-sm font-medium text-gray-400 hover:text-white hover:bg-white/5"
210
+ class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
205
211
  :class="{'active': $store.global.activeTab === 'settings'}"
206
212
  @click="$store.global.activeTab = 'settings'">
207
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
208
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
213
+ <svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
214
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
209
215
  d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
210
216
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
211
217
  d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
@@ -215,10 +221,10 @@
215
221
  </nav>
216
222
 
217
223
  <!-- Footer Info -->
218
- <div class="mt-auto px-6 text-xs text-gray-400 font-mono">
219
- <div class="flex justify-center">
224
+ <div class="mt-auto px-6 text-xs text-gray-500">
225
+ <div class="flex">
220
226
  <a href="https://github.com/badri-s2001/antigravity-claude-proxy" target="_blank" rel="noopener noreferrer"
221
- class="flex items-center gap-1.5 hover:text-neon-purple transition-colors">
227
+ class="flex items-center gap-1.5 hover:text-gray-200 transition-colors">
222
228
  <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
223
229
  <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
224
230
  </svg>
@@ -260,9 +266,9 @@
260
266
  </div>
261
267
 
262
268
  <!-- Add Account Modal -->
263
- <dialog id="add_account_modal" class="modal backdrop-blur-sm" x-data="addAccountModal">
264
- <div class="modal-box max-w-lg w-full bg-space-900 border border-space-border text-gray-300 shadow-[0_0_50px_rgba(0,0,0,0.5)] p-6">
265
- <h3 class="font-bold text-lg text-white mb-4" x-text="$store.global.t('addAccount')">Add New Account</h3>
269
+ <dialog id="add_account_modal" class="modal" x-data="addAccountModal">
270
+ <div class="modal-box max-w-lg w-full bg-space-900 border border-space-border text-gray-300 p-6">
271
+ <h3 class="font-semibold text-lg text-white mb-3" x-text="$store.global.t('addAccount')">Add New Account</h3>
266
272
 
267
273
  <div class="flex flex-col gap-4">
268
274
  <p class="text-sm text-gray-400 leading-relaxed" x-text="$store.global.t('connectGoogleDesc')">Connect a Google
@@ -288,23 +294,23 @@
288
294
  </button>
289
295
 
290
296
  <div class="text-center mt-2">
291
- <p class="text-xs text-gray-500 mb-2" x-text="$store.global.t('or')">OR</p>
297
+ <p class="text-xs text-gray-500 mb-2" x-text="$store.global.t('or')">or</p>
292
298
 
293
299
  <!-- Manual Mode (collapsible) -->
294
300
  <details class="group mb-2" @toggle="initManualAuth($event)">
295
- <summary class="text-xs text-gray-400 hover:text-neon-cyan cursor-pointer transition-colors inline-flex items-center gap-1">
301
+ <summary class="text-xs text-gray-400 hover:text-white cursor-pointer transition-colors inline-flex items-center gap-1">
296
302
  <svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
297
303
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
298
304
  </svg>
299
305
  <span x-text="$store.global.t('manualMode')">Manual Mode</span>
300
306
  </summary>
301
- <div class="mt-3 p-3 bg-black/50 rounded border border-space-border/30 text-xs">
307
+ <div class="mt-3 p-3 bg-space-950 rounded-md border border-space-border text-xs">
302
308
  <template x-if="authUrl">
303
309
  <div>
304
310
  <div class="flex items-center gap-2 mb-2">
305
311
  <input type="text" readonly :value="authUrl"
306
- class="input input-xs input-bordered flex-1 bg-space-800 text-gray-300 font-mono">
307
- <button class="btn btn-xs btn-ghost text-neon-cyan" @click="copyLink" :title="$store.global.t('linkCopied')">
312
+ class="input input-xs input-bordered flex-1 bg-space-850 border-space-border text-gray-300 font-mono">
313
+ <button class="btn btn-xs btn-ghost text-gray-400 hover:text-white" @click="copyLink" aria-label="Copy link" :title="$store.global.t('linkCopied')">
308
314
  <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
309
315
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
310
316
  </svg>
@@ -313,7 +319,7 @@
313
319
  <div class="flex items-center gap-2">
314
320
  <input type="text" x-model="callbackInput"
315
321
  :placeholder="$store.global.t('pasteCallbackPlaceholder')"
316
- class="input input-xs input-bordered flex-1 bg-space-800 text-gray-300 font-mono">
322
+ class="input input-xs input-bordered flex-1 bg-space-850 border-space-border text-gray-300 font-mono">
317
323
  <button class="btn btn-xs btn-success"
318
324
  @click="completeManualAuth"
319
325
  :disabled="!callbackInput || submitting"
@@ -331,13 +337,13 @@
331
337
 
332
338
  <!-- CLI Command -->
333
339
  <details class="group">
334
- <summary class="text-xs text-gray-400 hover:text-neon-cyan cursor-pointer transition-colors inline-flex items-center gap-1">
340
+ <summary class="text-xs text-gray-400 hover:text-white cursor-pointer transition-colors inline-flex items-center gap-1">
335
341
  <svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
336
342
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
337
343
  </svg>
338
344
  <span x-text="$store.global.t('useCliCommand')">Use CLI Command</span>
339
345
  </summary>
340
- <div class="mt-3 p-3 bg-black/50 rounded border border-space-border/30 font-mono text-xs text-gray-300">
346
+ <div class="mt-3 p-3 bg-space-950 rounded-md border border-space-border font-mono text-xs text-gray-300">
341
347
  <div class="flex items-center gap-2">
342
348
  <span class="text-gray-600">$</span>
343
349
  <code>npm run accounts:add</code>
@@ -349,7 +355,7 @@
349
355
 
350
356
  <div class="modal-action mt-6">
351
357
  <form method="dialog">
352
- <button type="submit" class="btn btn-ghost hover:bg-white/10" @click="resetState()" x-text="$store.global.t('close')">Close</button>
358
+ <button type="submit" class="btn btn-ghost btn-sm text-gray-400 hover:text-white hover:bg-space-800" @click="resetState()" x-text="$store.global.t('close')">Close</button>
353
359
  </form>
354
360
  </div>
355
361
  </div>
@@ -360,9 +366,9 @@
360
366
 
361
367
  <!-- OAuth Progress Modal -->
362
368
  <dialog id="oauth_progress_modal" class="modal" :class="{ 'modal-open': $store.global.oauthProgress.active }">
363
- <div class="modal-box bg-space-900 border border-neon-purple/50">
364
- <h3 class="font-bold text-lg text-white flex items-center gap-2">
365
- <svg class="w-6 h-6 text-neon-purple animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
369
+ <div class="modal-box bg-space-900 border border-space-border">
370
+ <h3 class="font-semibold text-lg text-white flex items-center gap-2">
371
+ <svg class="w-5 h-5 text-neon-purple animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
366
372
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
367
373
  </svg>
368
374
  <span x-text="$store.global.t('oauthWaiting')">Waiting for OAuth...</span>
@@ -372,14 +378,14 @@
372
378
  </p>
373
379
 
374
380
  <!-- Progress Bar -->
375
- <div class="w-full bg-space-800 rounded-full h-2 mb-4 overflow-hidden">
376
- <div class="bg-neon-purple h-2 rounded-full transition-all duration-500"
381
+ <div class="w-full bg-space-800 rounded-full h-1.5 mb-3 overflow-hidden">
382
+ <div class="bg-neon-purple h-1.5 rounded-full transition-all duration-500"
377
383
  :style="`width: ${($store.global.oauthProgress.current / $store.global.oauthProgress.max) * 100}%`">
378
384
  </div>
379
385
  </div>
380
386
 
381
387
  <!-- Progress Text -->
382
- <div class="flex justify-between text-xs text-gray-600 mb-4">
388
+ <div class="flex justify-between text-xs text-gray-500 font-mono mb-4">
383
389
  <span x-text="`${$store.global.oauthProgress.current} / ${$store.global.oauthProgress.max}s`"></span>
384
390
  <span x-text="`${Math.round(($store.global.oauthProgress.current / $store.global.oauthProgress.max) * 100)}%`"></span>
385
391
  </div>
@@ -26,13 +26,13 @@ const getThemeColor = (name) => window.utils.getThemeColor(name);
26
26
  // Color palette for different families and models
27
27
  const FAMILY_COLORS = {
28
28
  get claude() {
29
- return getThemeColor("--color-neon-purple");
29
+ return getThemeColor("--color-family-claude");
30
30
  },
31
31
  get gemini() {
32
- return getThemeColor("--color-neon-green");
32
+ return getThemeColor("--color-family-gemini");
33
33
  },
34
34
  get other() {
35
- return getThemeColor("--color-neon-cyan");
35
+ return getThemeColor("--color-family-other");
36
36
  },
37
37
  };
38
38
 
@@ -81,51 +81,25 @@ function isCanvasReady(canvas) {
81
81
  }
82
82
 
83
83
  /**
84
- * Create a Chart.js dataset with gradient fill
84
+ * Create a Chart.js dataset drawn as a plain instrument trace (no area fill)
85
85
  * @param {string} label - Dataset label
86
86
  * @param {Array} data - Data points
87
87
  * @param {string} color - Line color
88
- * @param {HTMLCanvasElement} canvas - Canvas element
89
88
  * @returns {object} Chart.js dataset configuration
90
89
  */
91
- window.DashboardCharts.createDataset = function (label, data, color, canvas) {
92
- let gradient;
93
-
94
- try {
95
- // Safely create gradient with fallback
96
- if (canvas && canvas.getContext) {
97
- const ctx = canvas.getContext("2d");
98
- if (ctx && ctx.createLinearGradient) {
99
- gradient = ctx.createLinearGradient(0, 0, 0, 200);
100
- gradient.addColorStop(0, window.DashboardCharts.hexToRgba(color, 0.12));
101
- gradient.addColorStop(
102
- 0.6,
103
- window.DashboardCharts.hexToRgba(color, 0.05)
104
- );
105
- gradient.addColorStop(1, "rgba(0, 0, 0, 0)");
106
- }
107
- }
108
- } catch (e) {
109
- if (window.UILogger) window.UILogger.debug("Gradient fallback:", e.message);
110
- gradient = null;
111
- }
112
-
113
- // Fallback to solid color if gradient creation failed
114
- const backgroundColor =
115
- gradient || window.DashboardCharts.hexToRgba(color, 0.08);
116
-
90
+ window.DashboardCharts.createDataset = function (label, data, color) {
117
91
  return {
118
92
  label,
119
93
  data,
120
94
  borderColor: color,
121
- backgroundColor: backgroundColor,
122
- borderWidth: 2.5,
123
- tension: 0.35,
124
- fill: true,
125
- pointRadius: 2.5,
126
- pointHoverRadius: 6,
95
+ backgroundColor: color,
96
+ borderWidth: 2,
97
+ tension: 0.25,
98
+ fill: false,
99
+ pointRadius: 2,
100
+ pointHoverRadius: 5,
127
101
  pointBackgroundColor: color,
128
- pointBorderColor: "rgba(9, 9, 11, 0.8)",
102
+ pointBorderColor: getThemeColor("--color-space-900") || "#111214",
129
103
  pointBorderWidth: 1.5,
130
104
  };
131
105
  };
@@ -214,9 +188,9 @@ window.DashboardCharts.updateCharts = function (component) {
214
188
  : 0;
215
189
 
216
190
  const familyColors = {
217
- claude: getThemeColor("--color-neon-purple") || "#a855f7",
218
- gemini: getThemeColor("--color-neon-green") || "#22c55e",
219
- unknown: getThemeColor("--color-neon-cyan") || "#06b6d4",
191
+ claude: getThemeColor("--color-family-claude") || "#4cc9d6",
192
+ gemini: getThemeColor("--color-family-gemini") || "#d9c39a",
193
+ unknown: getThemeColor("--color-family-other") || "#9aa7b0",
220
194
  };
221
195
 
222
196
  const data = [];
@@ -588,7 +562,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
588
562
  grid: { display: false },
589
563
  ticks: {
590
564
  color: getThemeColor("--color-text-muted"),
591
- font: { size: 10 },
565
+ font: { size: 10, family: '"B612 Mono", ui-monospace, monospace' },
592
566
  },
593
567
  },
594
568
  y: {
@@ -602,7 +576,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
602
576
  },
603
577
  ticks: {
604
578
  color: getThemeColor("--color-text-muted"),
605
- font: { size: 10 },
579
+ font: { size: 10, family: '"B612 Mono", ui-monospace, monospace' },
606
580
  },
607
581
  },
608
582
  },
@@ -49,6 +49,8 @@ window.Components.dashboard = () => ({
49
49
  this.$nextTick(() => {
50
50
  this.updateStats();
51
51
  this.updateCharts();
52
+ // History that arrived while another tab was active was skipped by the watcher below
53
+ this.syncHistory(this.$store.data.usageHistory);
52
54
  this.updateTrendChart();
53
55
  this.checkClaudeConfigStatus();
54
56
  });
@@ -71,15 +73,8 @@ window.Components.dashboard = () => ({
71
73
 
72
74
  // Watch for history updates from data-store (automatically loaded with account data)
73
75
  this.$watch('$store.data.usageHistory', (newHistory) => {
74
- if (this.$store.global.activeTab === 'dashboard' && newHistory && Object.keys(newHistory).length > 0) {
75
- // Optimization: Skip if data hasn't changed (prevents double render on load)
76
- if (this.historyData && JSON.stringify(newHistory) === JSON.stringify(this.historyData)) {
77
- return;
78
- }
79
-
80
- this.historyData = newHistory;
81
- this.processHistory(newHistory);
82
- this.stats.hasTrendData = true;
76
+ if (this.$store.global.activeTab === 'dashboard') {
77
+ this.syncHistory(newHistory);
83
78
  }
84
79
  });
85
80
 
@@ -89,22 +84,22 @@ window.Components.dashboard = () => ({
89
84
  this.$nextTick(() => {
90
85
  this.updateStats();
91
86
  this.updateCharts();
92
-
93
- // Optimization: Only process history if it hasn't been processed yet
94
- // The usageHistory watcher above will handle updates if data changes
95
- const history = Alpine.store('data').usageHistory;
96
- if (history && Object.keys(history).length > 0) {
97
- // Check if we already have this data to avoid redundant chart update
98
- if (!this.historyData || JSON.stringify(history) !== JSON.stringify(this.historyData)) {
99
- this.historyData = history;
100
- this.processHistory(history);
101
- this.stats.hasTrendData = true;
102
- }
103
- }
87
+ // The store may already hold history loaded before this component initialised
88
+ this.syncHistory(Alpine.store('data').usageHistory);
104
89
  });
105
90
  }
106
91
  },
107
92
 
93
+ // Process usage history unless it is empty or identical to what is already rendered
94
+ syncHistory(history) {
95
+ if (!history || Object.keys(history).length === 0) return;
96
+ if (JSON.stringify(history) === JSON.stringify(this.historyData)) return;
97
+
98
+ this.historyData = history;
99
+ this.processHistory(history);
100
+ this.stats.hasTrendData = true;
101
+ },
102
+
108
103
  processHistory(history) {
109
104
  // Build model tree from hierarchical data
110
105
  const tree = {};
@@ -6,16 +6,17 @@
6
6
  window.Components = window.Components || {};
7
7
 
8
8
  window.Components.models = () => ({
9
- // Color palette for per-account threshold markers
9
+ // Per-account threshold marker colours. They only tell accounts apart, so none of them
10
+ // reuses a status hue (green/amber/red); markers are flat ticks with no glow.
10
11
  thresholdColors: [
11
- { bg: '#eab308', shadow: 'rgba(234,179,8,0.5)' }, // yellow
12
- { bg: '#06b6d4', shadow: 'rgba(6,182,212,0.5)' }, // cyan
13
- { bg: '#a855f7', shadow: 'rgba(168,85,247,0.5)' }, // purple
14
- { bg: '#22c55e', shadow: 'rgba(34,197,94,0.5)' }, // green
15
- { bg: '#ef4444', shadow: 'rgba(239,68,68,0.5)' }, // red
16
- { bg: '#f97316', shadow: 'rgba(249,115,22,0.5)' }, // orange
17
- { bg: '#ec4899', shadow: 'rgba(236,72,153,0.5)' }, // pink
18
- { bg: '#8b5cf6', shadow: 'rgba(139,92,246,0.5)' }, // violet
12
+ { bg: '#eceae4', shadow: 'transparent' }, // lettering white
13
+ { bg: '#4cc9d6', shadow: 'transparent' }, // cyan
14
+ { bg: '#d9c39a', shadow: 'transparent' }, // sand
15
+ { bg: '#9aa7b0', shadow: 'transparent' }, // steel
16
+ { bg: '#7fdbe4', shadow: 'transparent' }, // pale cyan
17
+ { bg: '#bfa678', shadow: 'transparent' }, // khaki
18
+ { bg: '#c2a1bb', shadow: 'transparent' }, // dusty mauve
19
+ { bg: '#6f97a8', shadow: 'transparent' }, // slate blue
19
20
  ],
20
21
 
21
22
  getThresholdColor(index) {