free-coding-models 0.5.0 → 0.5.1
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 +9 -1
- package/bin/free-coding-models.js +10 -0
- package/changelog/v0.5.1.md +24 -0
- package/package.json +7 -2
- package/src/core/router-daemon.js +166 -1
- package/src/core/utils.js +2 -0
- package/src/tui/cli-help.js +2 -0
- package/src/tui/render-table.js +1 -1
- package/web/README.md +8 -5
- package/web/dist/assets/index-ByGf4Kq-.js +14 -0
- package/web/dist/assets/index-Ds7wmHBv.css +1 -0
- package/web/dist/index.html +3 -6
- package/web/index.html +1 -4
- package/web/package.json +11 -0
- package/web/server.js +606 -211
- package/web/src/App.jsx +54 -12
- package/web/src/components/analytics/AnalyticsView.jsx +10 -4
- package/web/src/components/atoms/AILatencyCell.jsx +38 -0
- package/web/src/components/atoms/AILatencyCell.module.css +43 -0
- package/web/src/components/atoms/HealthCell.jsx +53 -0
- package/web/src/components/atoms/HealthCell.module.css +15 -0
- package/web/src/components/atoms/LastPingCell.jsx +35 -0
- package/web/src/components/atoms/LastPingCell.module.css +35 -0
- package/web/src/components/atoms/MoodCell.jsx +25 -0
- package/web/src/components/atoms/MoodCell.module.css +6 -0
- package/web/src/components/atoms/RankCell.jsx +9 -0
- package/web/src/components/atoms/RankCell.module.css +9 -0
- package/web/src/components/atoms/TPSCell.jsx +36 -0
- package/web/src/components/atoms/TPSCell.module.css +38 -0
- package/web/src/components/atoms/VerdictBadge.jsx +30 -7
- package/web/src/components/atoms/VerdictBadge.module.css +24 -15
- package/web/src/components/dashboard/ExportModal.jsx +9 -4
- package/web/src/components/dashboard/FilterBar.jsx +112 -10
- package/web/src/components/dashboard/FilterBar.module.css +86 -1
- package/web/src/components/dashboard/ModelTable.jsx +293 -52
- package/web/src/components/dashboard/ModelTable.module.css +131 -33
- package/web/src/components/dashboard/StatsBar.jsx +7 -5
- package/web/src/components/layout/Footer.jsx +1 -1
- package/web/src/components/layout/Header.jsx +43 -9
- package/web/src/components/layout/Header.module.css +38 -4
- package/web/src/components/layout/Sidebar.jsx +19 -11
- package/web/src/components/layout/Sidebar.module.css +15 -5
- package/web/src/components/settings/SettingsView.jsx +24 -6
- package/web/src/components/settings/SettingsView.module.css +0 -1
- package/web/src/global.css +70 -73
- package/web/src/hooks/useFilter.js +117 -25
- package/web/src/hooks/useSSE.js +33 -9
- package/web/src/hooks/useSocket.js +200 -0
- package/web/vite.config.js +41 -0
- package/web/dist/assets/index-CGN-0_A0.css +0 -1
- package/web/dist/assets/index-CvMUM9Jr.js +0 -11
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file web/src/hooks/useSocket.js
|
|
3
|
+
* @description Realtime model-data hook with Socket.IO primary, SSE fallback, and REST polling safety net.
|
|
4
|
+
*
|
|
5
|
+
* 📖 The dashboard runs locally, so freshness matters more than shaving every
|
|
6
|
+
* byte. Socket.IO gives the snappiest path in `pnpm dev:web`; SSE keeps Docker /
|
|
7
|
+
* daemon-style servers working without Socket.IO; REST polling guarantees the UI
|
|
8
|
+
* eventually recovers if both streaming transports are interrupted.
|
|
9
|
+
*
|
|
10
|
+
* @functions
|
|
11
|
+
* → useSocket(serverUrl) — Subscribe to live dashboard state
|
|
12
|
+
* @exports useSocket
|
|
13
|
+
*/
|
|
14
|
+
import { useState, useEffect, useRef, useCallback } from 'react'
|
|
15
|
+
import { io } from 'socket.io-client'
|
|
16
|
+
|
|
17
|
+
const REST_FALLBACK_INTERVAL_MS = 2_000
|
|
18
|
+
const STALE_UPDATE_MS = 4_000
|
|
19
|
+
const ACTIVITY_THROTTLE_MS = 1_000
|
|
20
|
+
|
|
21
|
+
function normalizePayload(data) {
|
|
22
|
+
if (!data) return null
|
|
23
|
+
if (Array.isArray(data)) return { models: data }
|
|
24
|
+
if (Array.isArray(data.models)) return data
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function sameOriginUrl(path, serverUrl) {
|
|
29
|
+
if (!serverUrl) return path
|
|
30
|
+
return `${serverUrl.replace(/\/$/, '')}${path}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useSocket(serverUrl = '') {
|
|
34
|
+
const [models, setModels] = useState([])
|
|
35
|
+
const [connected, setConnected] = useState(false)
|
|
36
|
+
const [transport, setTransport] = useState('connecting')
|
|
37
|
+
const [updateCount, setUpdateCount] = useState(0)
|
|
38
|
+
const [nextPingAt, setNextPingAt] = useState(null)
|
|
39
|
+
const [serverIsPinging, setServerIsPinging] = useState(false)
|
|
40
|
+
const [pendingPings, setPendingPings] = useState(0)
|
|
41
|
+
const [pingMode, setPingMode] = useState('speed')
|
|
42
|
+
const [globalBenchmarkRunning, setGlobalBenchmarkRunning] = useState(false)
|
|
43
|
+
const [globalBenchmarkTotal, setGlobalBenchmarkTotal] = useState(0)
|
|
44
|
+
const [globalBenchmarkCompleted, setGlobalBenchmarkCompleted] = useState(0)
|
|
45
|
+
|
|
46
|
+
const socketRef = useRef(null)
|
|
47
|
+
const esRef = useRef(null)
|
|
48
|
+
const pollRef = useRef(null)
|
|
49
|
+
const lastUpdateRef = useRef(0)
|
|
50
|
+
const lastActivityRef = useRef(0)
|
|
51
|
+
const mountedRef = useRef(false)
|
|
52
|
+
|
|
53
|
+
const applyPayload = useCallback((raw, source = 'unknown') => {
|
|
54
|
+
const data = normalizePayload(raw)
|
|
55
|
+
if (!data || !mountedRef.current) return
|
|
56
|
+
|
|
57
|
+
setModels(data.models ?? [])
|
|
58
|
+
setPingMode(data.pingMode ?? 'speed')
|
|
59
|
+
setNextPingAt(data.nextPingAt ?? null)
|
|
60
|
+
setServerIsPinging(Boolean(data.isPinging))
|
|
61
|
+
setPendingPings(Number.isFinite(data.pendingPings) ? data.pendingPings : 0)
|
|
62
|
+
setGlobalBenchmarkRunning(Boolean(data.globalBenchmarkRunning))
|
|
63
|
+
setGlobalBenchmarkTotal(Number.isFinite(data.globalBenchmarkTotal) ? data.globalBenchmarkTotal : 0)
|
|
64
|
+
setGlobalBenchmarkCompleted(Number.isFinite(data.globalBenchmarkCompleted) ? data.globalBenchmarkCompleted : 0)
|
|
65
|
+
setUpdateCount((count) => count + 1)
|
|
66
|
+
lastUpdateRef.current = Date.now()
|
|
67
|
+
if (source !== 'poll') {
|
|
68
|
+
setConnected(true)
|
|
69
|
+
setTransport(source)
|
|
70
|
+
}
|
|
71
|
+
}, [])
|
|
72
|
+
|
|
73
|
+
const fetchSnapshot = useCallback(async () => {
|
|
74
|
+
try {
|
|
75
|
+
const stateResponse = await fetch(sameOriginUrl('/api/state', serverUrl), { headers: { Accept: 'application/json' } })
|
|
76
|
+
if (stateResponse.ok) {
|
|
77
|
+
applyPayload(await stateResponse.json(), 'poll')
|
|
78
|
+
setConnected(true)
|
|
79
|
+
setTransport((current) => current === 'socket' || current === 'sse' ? current : 'poll')
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
} catch {}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(sameOriginUrl('/api/models', serverUrl), { headers: { Accept: 'application/json' } })
|
|
86
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
|
87
|
+
applyPayload(await response.json(), 'poll')
|
|
88
|
+
setConnected(true)
|
|
89
|
+
setTransport((current) => current === 'socket' || current === 'sse' ? current : 'poll')
|
|
90
|
+
} catch {
|
|
91
|
+
setConnected(false)
|
|
92
|
+
setTransport('offline')
|
|
93
|
+
}
|
|
94
|
+
}, [applyPayload, serverUrl])
|
|
95
|
+
|
|
96
|
+
const startSse = useCallback(() => {
|
|
97
|
+
if (esRef.current || !mountedRef.current) return
|
|
98
|
+
try {
|
|
99
|
+
const es = new EventSource(sameOriginUrl('/api/events', serverUrl))
|
|
100
|
+
esRef.current = es
|
|
101
|
+
es.onopen = () => {
|
|
102
|
+
if (!mountedRef.current) return
|
|
103
|
+
setConnected(true)
|
|
104
|
+
setTransport('sse')
|
|
105
|
+
}
|
|
106
|
+
const handleSsePayload = (event) => {
|
|
107
|
+
try { applyPayload(JSON.parse(event.data), 'sse') }
|
|
108
|
+
catch (err) { console.warn('[useSocket] SSE parse error:', err) }
|
|
109
|
+
}
|
|
110
|
+
es.onmessage = handleSsePayload
|
|
111
|
+
es.addEventListener('models', handleSsePayload)
|
|
112
|
+
es.onerror = () => {
|
|
113
|
+
es.close()
|
|
114
|
+
if (esRef.current === es) esRef.current = null
|
|
115
|
+
if (!socketRef.current?.connected) setConnected(false)
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
esRef.current = null
|
|
119
|
+
}
|
|
120
|
+
}, [applyPayload, serverUrl])
|
|
121
|
+
|
|
122
|
+
const sendActivity = useCallback(() => {
|
|
123
|
+
const now = Date.now()
|
|
124
|
+
if (now - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return
|
|
125
|
+
lastActivityRef.current = now
|
|
126
|
+
|
|
127
|
+
if (socketRef.current?.connected) {
|
|
128
|
+
socketRef.current.emit('client:activity')
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fetch(sameOriginUrl('/api/activity', serverUrl), { method: 'POST' }).catch(() => {})
|
|
133
|
+
}, [serverUrl])
|
|
134
|
+
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
mountedRef.current = true
|
|
137
|
+
|
|
138
|
+
const socket = io(serverUrl || undefined, {
|
|
139
|
+
transports: ['websocket', 'polling'],
|
|
140
|
+
reconnectionDelay: 500,
|
|
141
|
+
reconnectionDelayMax: 2500,
|
|
142
|
+
timeout: 1200,
|
|
143
|
+
})
|
|
144
|
+
socketRef.current = socket
|
|
145
|
+
|
|
146
|
+
socket.on('connect', () => {
|
|
147
|
+
setConnected(true)
|
|
148
|
+
setTransport('socket')
|
|
149
|
+
esRef.current?.close()
|
|
150
|
+
esRef.current = null
|
|
151
|
+
socket.emit('models:refresh')
|
|
152
|
+
socket.emit('client:activity')
|
|
153
|
+
})
|
|
154
|
+
socket.on('disconnect', () => {
|
|
155
|
+
if (!mountedRef.current) return
|
|
156
|
+
setConnected(false)
|
|
157
|
+
startSse()
|
|
158
|
+
})
|
|
159
|
+
socket.on('connect_error', () => {
|
|
160
|
+
if (!mountedRef.current) return
|
|
161
|
+
setConnected(false)
|
|
162
|
+
startSse()
|
|
163
|
+
})
|
|
164
|
+
socket.on('models:update', (data) => applyPayload(data, 'socket'))
|
|
165
|
+
|
|
166
|
+
pollRef.current = setInterval(() => {
|
|
167
|
+
const stale = Date.now() - lastUpdateRef.current > STALE_UPDATE_MS
|
|
168
|
+
if (!socket.connected || stale) void fetchSnapshot()
|
|
169
|
+
}, REST_FALLBACK_INTERVAL_MS)
|
|
170
|
+
|
|
171
|
+
void fetchSnapshot()
|
|
172
|
+
|
|
173
|
+
const activityEvents = ['keydown', 'pointerdown', 'mousemove', 'focus']
|
|
174
|
+
for (const eventName of activityEvents) window.addEventListener(eventName, sendActivity, { passive: true })
|
|
175
|
+
|
|
176
|
+
return () => {
|
|
177
|
+
mountedRef.current = false
|
|
178
|
+
for (const eventName of activityEvents) window.removeEventListener(eventName, sendActivity)
|
|
179
|
+
if (pollRef.current) clearInterval(pollRef.current)
|
|
180
|
+
socket.disconnect()
|
|
181
|
+
esRef.current?.close()
|
|
182
|
+
socketRef.current = null
|
|
183
|
+
esRef.current = null
|
|
184
|
+
}
|
|
185
|
+
}, [applyPayload, fetchSnapshot, sendActivity, serverUrl, startSse])
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
models,
|
|
189
|
+
connected,
|
|
190
|
+
transport,
|
|
191
|
+
updateCount,
|
|
192
|
+
nextPingAt,
|
|
193
|
+
isPinging: serverIsPinging,
|
|
194
|
+
pendingPings,
|
|
195
|
+
pingMode,
|
|
196
|
+
globalBenchmarkRunning,
|
|
197
|
+
globalBenchmarkTotal,
|
|
198
|
+
globalBenchmarkCompleted,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file web/vite.config.js
|
|
3
|
+
* @description Vite config with proxy for backend API + Socket.IO (with WebSocket upgrade).
|
|
4
|
+
*/
|
|
5
|
+
import { defineConfig } from 'vite'
|
|
6
|
+
import react from '@vitejs/plugin-react'
|
|
7
|
+
import { readFileSync } from 'node:fs'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
|
|
10
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
11
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
12
|
+
|
|
13
|
+
export default defineConfig({
|
|
14
|
+
plugins: [react()],
|
|
15
|
+
root: 'web',
|
|
16
|
+
build: {
|
|
17
|
+
outDir: 'dist',
|
|
18
|
+
emptyOutDir: true,
|
|
19
|
+
},
|
|
20
|
+
server: {
|
|
21
|
+
port: 5173,
|
|
22
|
+
proxy: {
|
|
23
|
+
'/api': {
|
|
24
|
+
target: 'http://localhost:3333',
|
|
25
|
+
changeOrigin: true,
|
|
26
|
+
},
|
|
27
|
+
'/socket.io': {
|
|
28
|
+
target: 'http://localhost:3333',
|
|
29
|
+
changeOrigin: true,
|
|
30
|
+
ws: true, // ← enable WebSocket upgrade
|
|
31
|
+
},
|
|
32
|
+
'/v1': {
|
|
33
|
+
target: 'http://localhost:3333',
|
|
34
|
+
changeOrigin: true,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
define: {
|
|
39
|
+
__APP_VERSION__: JSON.stringify(pkg.version),
|
|
40
|
+
},
|
|
41
|
+
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._header_1nuxz_1{z-index:100;background:var(--color-bg-card);-webkit-backdrop-filter:blur(20px)saturate(1.5);border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;gap:20px;height:60px;padding:0 24px;display:flex;position:sticky;top:0}._left_1nuxz_16{align-items:center;gap:12px;display:flex}._center_1nuxz_17{flex:1;max-width:480px}._right_1nuxz_18{align-items:center;gap:10px;display:flex}._logo_1nuxz_20{align-items:center;gap:8px;display:flex}._logoIcon_1nuxz_21{font-size:22px}._logoText_1nuxz_22{background:linear-gradient(135deg, var(--color-accent), #06b6d4);-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text;font-size:16px;font-weight:700}._version_1nuxz_27{font-size:11px;font-weight:500;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-accent-dim);border:1px solid var(--color-border);border-radius:999px;padding:2px 8px}._searchBar_1nuxz_33{background:var(--color-surface);border:1px solid var(--color-border);border-radius:10px;align-items:center;gap:8px;height:36px;padding:0 12px;transition:border-color .15s,box-shadow .15s;display:flex}._searchBar_1nuxz_33:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 3px var(--color-accent-glow)}._searchIcon_1nuxz_43{flex-shrink:0;font-size:14px}._searchInput_1nuxz_44{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._searchInput_1nuxz_44::placeholder{color:var(--color-text-dim)}._kbd_1nuxz_49{font-size:10px;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-bg);border:1px solid var(--color-border);border-radius:4px;flex-shrink:0;padding:2px 6px}._iconBtn_1nuxz_55{border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;padding:6px 8px;font-size:16px;transition:all .15s;display:inline-flex}._iconBtn_1nuxz_55:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._primaryBtn_1nuxz_62{border:1px solid var(--color-accent);background:var(--color-accent);color:#000;cursor:pointer;font-size:13px;font-weight:600;font-family:var(--font-sans);border-radius:6px;align-items:center;gap:6px;padding:6px 14px;transition:all .15s;display:inline-flex}._primaryBtn_1nuxz_62:hover{background:var(--color-accent-hover)}@media (width<=768px){._center_1nuxz_17{display:none}}._sidebar_16fei_1{z-index:200;background:var(--color-bg-elevated);border-right:1px solid var(--color-border);flex-direction:column;width:64px;padding:12px 0;transition:width .25s cubic-bezier(.16,1,.3,1);display:flex;position:fixed;top:0;bottom:0;left:0;overflow:hidden}._sidebar_16fei_1:hover{width:200px}._logo_16fei_16{white-space:nowrap;align-items:center;gap:10px;margin-bottom:16px;padding:8px 18px;display:flex;overflow:hidden}._logoIcon_16fei_25{flex-shrink:0;font-size:24px}._logoText_16fei_26{background:linear-gradient(135deg, var(--color-accent), #06b6d4);-webkit-text-fill-color:transparent;opacity:0;-webkit-background-clip:text;background-clip:text;font-size:16px;font-weight:800;transition:opacity .25s cubic-bezier(.16,1,.3,1)}._sidebar_16fei_1:hover ._logoText_16fei_26{opacity:1}._nav_16fei_38{flex-direction:column;flex:1;gap:4px;display:flex}._bottom_16fei_39{flex-direction:column;gap:4px;display:flex}._navItem_16fei_41{color:var(--color-text-muted);cursor:pointer;white-space:nowrap;font-family:var(--font-sans);background:0 0;border:none;align-items:center;gap:12px;padding:10px 20px;font-size:13px;font-weight:500;transition:all .15s cubic-bezier(.16,1,.3,1);display:flex;overflow:hidden}._navItem_16fei_41:hover{color:var(--color-text);background:var(--color-bg-hover)}._navIcon_16fei_61{text-align:center;flex-shrink:0;width:20px;font-size:16px}._navLabel_16fei_67{opacity:0;transition:opacity .25s cubic-bezier(.16,1,.3,1)}._sidebar_16fei_1:hover ._navLabel_16fei_67{opacity:1}._active_16fei_72{border-right:3px solid var(--color-accent);color:var(--color-accent)!important;background:var(--color-accent-dim)!important}._footer_1uw54_1{z-index:1;border-top:1px solid var(--color-border);color:var(--color-text-dim);justify-content:space-between;align-items:center;padding:16px 24px;font-size:12px;display:flex;position:relative}._left_1uw54_8 a,._right_1uw54_8 a{color:var(--color-text-dim);text-decoration:none}._left_1uw54_8 a:hover,._right_1uw54_8 a:hover{color:var(--color-accent)}._right_1uw54_8{gap:16px;display:flex}._statsBar_1q3n1_1{z-index:1;grid-template-columns:repeat(5,1fr);gap:14px;padding:20px 24px 0;display:grid;position:relative}._card_1q3n1_6{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:16px;align-items:center;gap:12px;padding:16px 18px;transition:all .25s cubic-bezier(.16,1,.3,1);display:flex}._card_1q3n1_6:hover{border-color:var(--color-border-hover);box-shadow:var(--shadow-md);transform:translateY(-2px)}._icon_1q3n1_21{font-size:28px}._body_1q3n1_22{flex:1}._value_1q3n1_23{font-size:22px;font-weight:800;font-family:var(--font-mono);line-height:1}._label_1q3n1_24{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-top:2px;font-size:11px;font-weight:500}@media (width<=1024px){._statsBar_1q3n1_1{grid-template-columns:repeat(3,1fr)}}@media (width<=768px){._statsBar_1q3n1_1{grid-template-columns:repeat(2,1fr)}}@media (width<=480px){._statsBar_1q3n1_1{grid-template-columns:1fr}}._filters_jhonm_1{z-index:1;flex-wrap:wrap;align-items:center;gap:20px;padding:16px 24px;display:flex;position:relative}._group_jhonm_6{align-items:center;gap:8px;display:flex}._filterLabel_jhonm_7{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:11px;font-weight:600}._tierRow_jhonm_11{gap:4px;display:flex}._tierBtn_jhonm_12{font-size:12px;font-weight:600;font-family:var(--font-mono);border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text-muted);cursor:pointer;border-radius:6px;padding:4px 10px;transition:all .15s}._tierBtn_jhonm_12:hover{background:var(--color-bg-hover);color:var(--color-text)}._active_jhonm_19{font-weight:700;background:var(--color-accent)!important;color:#000!important;border-color:var(--color-accent)!important}._providerSelect_jhonm_23{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border);font-size:12px;font-family:var(--font-sans);cursor:pointer;border-radius:6px;outline:none;padding:5px 10px}._providerSelect_jhonm_23:focus{border-color:var(--color-accent)}._spacer_jhonm_30{flex:1}._live_jhonm_31{color:var(--color-accent);text-transform:uppercase;letter-spacing:1px;align-items:center;gap:6px;font-size:11px;font-weight:700;display:flex}._liveDot_jhonm_36{background:var(--color-accent);border-radius:50%;width:8px;height:8px;animation:2s ease-in-out infinite _pulseDot_jhonm_1}@keyframes _pulseDot_jhonm_1{0%,to{box-shadow:0 0 0 0 var(--color-accent-glow)}50%{box-shadow:0 0 0 6px #0000}}._badge_1vsmk_1{text-align:center;border-radius:4px;min-width:32px;padding:2px 8px;font-family:JetBrains Mono,monospace;font-size:11px;font-weight:700;display:inline-block}._tier_splus_1vsmk_11{color:gold;background:#ffd70026;border:1px solid #ffd7004d}._tier_s_1vsmk_11{color:#ff8c00;background:#ff8c001f;border:1px solid #ff8c0040}._tier_aplus_1vsmk_13{color:#00c8ff;background:#00c8ff1a;border:1px solid #00c8ff33}._tier_a_1vsmk_13{color:#3ddc84;background:#3ddc841a;border:1px solid #3ddc8433}._tier_aminus_1vsmk_15{color:#7ecf7e;background:#7ecf7e1a;border:1px solid #7ecf7e33}._tier_bplus_1vsmk_16{color:#a8a8c8;background:#a8a8c81a;border:1px solid #a8a8c826}._tier_b_1vsmk_16{color:#808098;background:#8080981a;border:1px solid #80809826}._tier_c_1vsmk_18{color:#606078;background:#6060781a;border:1px solid #60607826}._dot_xhoha_1{vertical-align:middle;border-radius:50%;width:8px;height:8px;margin-right:6px;display:inline-block}._up_xhoha_9{background:#0f8;box-shadow:0 0 6px #0f86}._down_xhoha_10,._timeout_xhoha_11{background:#f44}._pending_xhoha_12{background:#555570;animation:1.5s ease-in-out infinite _pulse_xhoha_1}@keyframes _pulse_xhoha_1{0%,to{box-shadow:0 0 #76b90040}50%{box-shadow:0 0 0 6px #0000}}._badge_j5mmw_1{text-transform:uppercase;letter-spacing:.5px;border-radius:999px;padding:2px 8px;font-size:10px;font-weight:700;display:inline-block}._perfect_j5mmw_10{color:#0f8;background:#00ff881f;border:1px solid #00ff8840}._normal_j5mmw_11{color:#76b900;background:#76b9001f;border:1px solid #76b90040}._slow_j5mmw_12{color:#fa0;background:#ffaa001f;border:1px solid #ffaa0040}._spiky_j5mmw_13{color:#f60;background:#ff66001f;border:1px solid #ff660040}._veryslow_j5mmw_14{color:#f44;background:#ff44441f;border:1px solid #f443}._overloaded_j5mmw_15{color:#f22;background:#ff22221f;border:1px solid #f223}._unstable_j5mmw_16{color:#c00;background:#cc00001f;border:1px solid #c003}._notactive_j5mmw_17{color:#555570;background:#5555701f;border:1px solid #55557026}._pending_j5mmw_18{color:#444460;background:#4444601a;border:1px solid #44446026}._ratelimited_j5mmw_19{color:#fa0;background:#ffaa0026;border:1px solid #ffaa004d}._cell_1qs4d_1{align-items:center;gap:6px;display:flex}._bar_1qs4d_2{background:var(--color-surface);border-radius:3px;width:48px;height:6px;overflow:hidden}._fill_1qs4d_3{border-radius:3px;height:100%;transition:width .25s cubic-bezier(.16,1,.3,1)}._high_1qs4d_4{background:linear-gradient(90deg,#0f8,#76b900)}._mid_1qs4d_5{background:linear-gradient(90deg,#fa0,#ff8c00)}._low_1qs4d_6{background:linear-gradient(90deg,#f44,#c00)}._value_1qs4d_7{font-family:JetBrains Mono,monospace;font-size:12px;font-weight:600}._none_1qs4d_8{color:var(--color-text-dim)}._container_8mrfy_1{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px)saturate(1.5);border:1px solid var(--color-border);border-radius:16px;margin:16px 0;overflow:hidden}._table_8mrfy_10{border-collapse:collapse;width:100%;font-size:13px}._th_8mrfy_11{text-transform:uppercase;letter-spacing:.8px;color:var(--color-text-muted);background:var(--color-bg-elevated);border-bottom:1px solid var(--color-border);white-space:nowrap;-webkit-user-select:none;user-select:none;cursor:default;padding:12px 14px;font-size:11px;font-weight:700}._th_8mrfy_11:hover{color:var(--color-accent)}._table_8mrfy_10 td{border-bottom:1px solid var(--color-border);white-space:nowrap;padding:10px 14px}._table_8mrfy_10 tbody tr{cursor:pointer;transition:background .15s}._table_8mrfy_10 tbody tr:hover{background:var(--color-bg-hover)}._tdRank_8mrfy_20{text-align:center;font-family:var(--font-mono);color:var(--color-text-dim);font-weight:600}._rank1_8mrfy_21 td:first-child{border-left:3px solid gold}._rank2_8mrfy_22 td:first-child{border-left:3px solid silver}._rank3_8mrfy_23 td:first-child{border-left:3px solid #cd7f32}._modelCell_8mrfy_24{flex-direction:column;display:flex}._modelName_8mrfy_25{align-items:center;gap:4px;font-size:13px;font-weight:600;display:flex}._modelId_8mrfy_26{font-family:var(--font-mono);color:var(--color-text-dim);margin-top:1px;font-size:10px}._noKey_8mrfy_27{color:#fa0;background:#ffaa001f;border:1px solid #fa03;border-radius:3px;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:600}._providerPill_8mrfy_31{background:var(--color-accent-dim);color:var(--color-text-muted);border:1px solid var(--color-border);border-radius:999px;padding:2px 8px;font-size:11px;font-weight:500;display:inline-block}._swe_8mrfy_35{font-family:var(--font-mono);font-weight:600}._sweHigh_8mrfy_36{color:gold}._sweMid_8mrfy_37{color:#3ddc84}._sweLow_8mrfy_38{color:var(--color-text-dim)}._ctx_8mrfy_39{font-family:var(--font-mono);color:var(--color-text-muted);font-size:12px}._ping_8mrfy_40{font-family:var(--font-mono);font-weight:600}._pingFast_8mrfy_41{color:#0f8}._pingMedium_8mrfy_42{color:#fa0}._pingSlow_8mrfy_43{color:#f44}._pingNone_8mrfy_44{color:var(--color-text-dim)}._uptime_8mrfy_45{font-family:var(--font-mono);font-size:12px}._empty_8mrfy_46{text-align:center;color:var(--color-text-muted);padding:60px 0}._panel_uzr3l_1{z-index:300;background:var(--color-bg-elevated);border-left:1px solid var(--color-border);width:min(420px,90vw);box-shadow:var(--shadow-lg);transition:transform var(--transition-medium);position:fixed;top:0;bottom:0;right:0;overflow-y:auto;transform:translate(100%)}._header_uzr3l_16{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:20px 24px;display:flex}._title_uzr3l_24{margin:0;font-size:16px;font-weight:700}._closeBtn_uzr3l_30{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;font-size:22px;line-height:1}._closeBtn_uzr3l_30:hover{color:var(--color-text)}._body_uzr3l_43{padding:24px}._stat_uzr3l_47{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:10px 0;display:flex}._statLabel_uzr3l_55{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:12px;font-weight:600}._statValue_uzr3l_63,._ping_uzr3l_68{font-family:var(--font-mono);font-weight:600}._pingFast_uzr3l_73{color:#0f8}._pingMedium_uzr3l_74{color:#fa0}._pingSlow_uzr3l_75{color:#f44}._pingNone_uzr3l_76{color:var(--color-text-dim)}._chart_uzr3l_78{background:var(--color-surface);border-radius:var(--radius-md);border:1px solid var(--color-border);margin:20px 0;padding:16px}._chartTitle_uzr3l_86{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:12px;font-size:11px;font-weight:700}._chartEmpty_uzr3l_95{color:var(--color-text-dim);text-align:center;padding:20px}._overlay_1e3f5_1{z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0009;justify-content:center;align-items:center;animation:.2s ease-out _fadeIn_1e3f5_1;display:flex;position:fixed;inset:0}._overlay_1e3f5_1[hidden]{display:none}@keyframes _fadeIn_1e3f5_1{0%{opacity:0}to{opacity:1}}._modal_1e3f5_18{background:var(--color-bg-elevated);border:1px solid var(--color-border);border-radius:var(--radius-xl);width:min(500px,90vw);max-height:80vh;box-shadow:var(--shadow-lg);animation:_modalSlideIn_1e3f5_1 .3s var(--ease-out);overflow-y:auto}@keyframes _modalSlideIn_1e3f5_1{0%{opacity:0;transform:translateY(20px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}._modalHeader_1e3f5_33{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:20px 24px;display:flex}._modalTitle_1e3f5_40{margin:0;font-size:18px;font-weight:700}._modalClose_1e3f5_45{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;padding:0;font-size:24px;line-height:1}._modalClose_1e3f5_45:hover{color:var(--color-text)}._modalBody_1e3f5_57{padding:24px}._options_1e3f5_60{flex-direction:column;gap:10px;display:flex}._option_1e3f5_60{border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);cursor:pointer;transition:all var(--transition-fast);text-align:left;font-family:var(--font-sans);color:var(--color-text);align-items:center;gap:14px;width:100%;padding:14px 18px;display:flex}._option_1e3f5_60:hover{border-color:var(--color-accent);background:var(--color-accent-dim)}._optionIcon_1e3f5_84{flex-shrink:0;font-size:24px}._optionLabel_1e3f5_89{font-size:14px;font-weight:600;display:block}._optionDesc_1e3f5_94{color:var(--color-text-muted);margin-top:2px;font-size:11px;display:block}._page_17r6q_1{max-width:900px;padding:24px}._pageHeader_17r6q_6{margin-bottom:24px}._pageTitle_17r6q_10{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_17r6q_16{color:var(--color-text-muted);margin:0;font-size:13px;line-height:1.5}._pageSubtitle_17r6q_16 code{font-family:var(--font-mono);background:var(--color-surface);border-radius:4px;padding:2px 6px;font-size:12px}._loading_17r6q_31{text-align:center;color:var(--color-text-muted);padding:60px 0}._toolbar_17r6q_37{flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px;display:flex}._toolbarSearch_17r6q_45{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);flex:1;align-items:center;gap:8px;min-width:200px;height:36px;padding:0 12px;display:flex}._toolbarSearch_17r6q_45 svg{color:var(--color-text-dim);flex-shrink:0}._toolbarSearch_17r6q_45 input{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._toolbarSearch_17r6q_45 input::placeholder{color:var(--color-text-dim)}._toolbarActions_17r6q_77{gap:8px;display:flex}._toolbarBtn_17r6q_82{border:1px solid var(--color-border);border-radius:var(--radius-sm);cursor:pointer;background:var(--color-surface);color:var(--color-text);transition:all var(--transition-fast);font-size:13px;font-weight:500;font-family:var(--font-sans);align-items:center;gap:6px;padding:6px 14px;display:inline-flex}._toolbarBtn_17r6q_82:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._providers_17r6q_103{flex-direction:column;gap:12px;display:flex}._card_17r6q_109{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:var(--radius-lg);transition:border-color var(--transition-fast);overflow:hidden}._card_17r6q_109:hover{border-color:var(--color-border-hover)}._cardHeader_17r6q_122{cursor:pointer;transition:background var(--transition-fast);align-items:center;gap:12px;padding:16px 20px;display:flex}._cardHeader_17r6q_122:hover{background:var(--color-bg-hover)}._cardIcon_17r6q_135{border-radius:var(--radius-sm);background:var(--color-accent-dim);flex-shrink:0;justify-content:center;align-items:center;width:36px;height:36px;font-size:18px;display:flex}._cardInfo_17r6q_147{flex:1;min-width:0}._cardName_17r6q_152{font-size:14px;font-weight:700}._cardMeta_17r6q_157{color:var(--color-text-muted);margin-top:2px;font-size:11px}._cardStatus_17r6q_163{border-radius:999px;flex-shrink:0;padding:3px 10px;font-size:11px;font-weight:700}._statusConfigured_17r6q_171{background:var(--color-success-dim);color:var(--color-success)}._statusMissing_17r6q_176{background:var(--color-warning-dim);color:var(--color-warning)}._toggleIcon_17r6q_181{color:var(--color-text-dim);transition:transform var(--transition-fast);flex-shrink:0;font-size:18px}._toggleIconExpanded_17r6q_188{transform:rotate(180deg)}._cardBody_17r6q_192{max-height:0;transition:max-height var(--transition-medium);border-top:0 solid #0000;overflow:hidden}._cardExpanded_17r6q_199 ._cardBody_17r6q_192{border-top:1px solid var(--color-border);max-height:500px}._cardContent_17r6q_204{padding:16px 20px}._keyGroup_17r6q_208{margin-bottom:12px}._keyLabel_17r6q_212{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;font-size:11px;font-weight:600;display:block}._keyDisplay_17r6q_222{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-sm);align-items:center;gap:8px;margin-bottom:8px;padding:8px 12px;display:flex}._keyDisplayValue_17r6q_233{font-family:var(--font-mono);color:var(--color-text-muted);word-break:break-all;flex:1;font-size:13px}._keyDisplayActions_17r6q_241{flex-shrink:0;gap:4px;display:flex}._actionBtn_17r6q_247{border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-surface);color:var(--color-text);cursor:pointer;transition:all var(--transition-fast);justify-content:center;align-items:center;padding:4px 8px;font-size:12px;display:inline-flex}._actionBtn_17r6q_247:hover{background:var(--color-bg-hover)}._actionBtnDanger_17r6q_265{background:var(--color-danger-dim);color:var(--color-danger);border-color:#f443}._actionBtnDanger_17r6q_265:hover{background:#f443}._keyInputRow_17r6q_275{align-items:center;gap:8px;display:flex}._keyInput_17r6q_275{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-sm);font-size:13px;font-family:var(--font-mono);color:var(--color-text);transition:border-color var(--transition-fast);outline:none;flex:1;padding:8px 12px}._keyInput_17r6q_275:focus{border-color:var(--color-accent)}._keyInput_17r6q_275::placeholder{color:var(--color-text-dim)}._saveBtn_17r6q_302{border-radius:var(--radius-sm);background:var(--color-success-dim);color:var(--color-success);cursor:pointer;font-size:13px;font-weight:600;font-family:var(--font-sans);transition:all var(--transition-fast);border:1px solid #0f83;align-items:center;gap:6px;padding:8px 14px;display:inline-flex}._saveBtn_17r6q_302:hover{background:#00ff8826}._enabledRow_17r6q_322{border-top:1px solid var(--color-border);justify-content:space-between;align-items:center;margin-top:12px;padding-top:12px;display:flex}._enabledLabel_17r6q_331{color:var(--color-text-muted);font-size:12px;font-weight:500}._toggleSwitch_17r6q_337{cursor:pointer;width:44px;height:24px;position:relative}._toggleSwitch_17r6q_337 input{display:none}._toggleSlider_17r6q_348{background:var(--color-surface);border:1px solid var(--color-border);transition:all var(--transition-fast);border-radius:12px;position:absolute;inset:0}._toggleSlider_17r6q_348:after{content:"";background:var(--color-text-dim);width:16px;height:16px;transition:all var(--transition-fast);border-radius:50%;position:absolute;top:3px;left:3px}._toggleSwitch_17r6q_337 input:checked+._toggleSlider_17r6q_348{background:var(--color-accent-dim);border-color:var(--color-accent)}._toggleSwitch_17r6q_337 input:checked+._toggleSlider_17r6q_348:after{background:var(--color-accent);transform:translate(20px)}._page_1sl6l_1{padding:24px}._pageHeader_1sl6l_5{margin-bottom:24px}._pageTitle_1sl6l_9{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_1sl6l_15{color:var(--color-text-muted);margin:0;font-size:13px}._grid_1sl6l_21{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}._card_1sl6l_27{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:20px;overflow:hidden}._cardWide_1sl6l_36{grid-column:span 2}._cardTitle_1sl6l_40{margin:0 0 16px;font-size:14px;font-weight:700}._empty_1sl6l_49{color:var(--color-text-dim);text-align:center;padding:20px 0}._healthItem_1sl6l_55{border-bottom:1px solid var(--color-border);align-items:center;gap:12px;padding:8px 0;display:flex}._healthItem_1sl6l_55:last-child{border-bottom:none}._healthName_1sl6l_67{flex-shrink:0;width:120px;font-size:12px;font-weight:600}._healthBar_1sl6l_74{background:var(--color-surface);border-radius:4px;flex:1;height:8px;overflow:hidden}._healthFill_1sl6l_82{background:linear-gradient(90deg, var(--color-accent), var(--color-success));height:100%;transition:width var(--transition-medium);border-radius:4px}._healthPct_1sl6l_89{text-align:right;width:40px;font-family:var(--font-mono);font-size:12px;font-weight:600}._pctFast_1sl6l_97{color:#0f8}._pctMedium_1sl6l_98{color:#fa0}._pctSlow_1sl6l_99{color:#f44}._leaderItem_1sl6l_101{border-bottom:1px solid var(--color-border);align-items:center;gap:10px;padding:8px 0;display:flex}._leaderItem_1sl6l_101:last-child{border-bottom:none}._leaderRank_1sl6l_113{background:var(--color-surface);width:28px;height:28px;color:var(--color-text-dim);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;font-weight:700;display:flex}._rank1_1sl6l_127{color:gold;background:#ffd70026}._rank2_1sl6l_128{color:silver;background:#c0c0c026}._rank3_1sl6l_129{color:#cd7f32;background:#cd7f3226}._leaderName_1sl6l_131{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;font-weight:600;overflow:hidden}._leaderLatency_1sl6l_141{font-family:var(--font-mono);color:var(--color-success);flex-shrink:0;font-size:12px;font-weight:600}._tierItem_1sl6l_149{align-items:center;gap:10px;padding:6px 0;display:flex}._tierBadge_1sl6l_156{flex-shrink:0;width:40px}._tierBar_1sl6l_161{background:var(--color-surface);border-radius:5px;flex:1;height:10px;overflow:hidden}._tierFill_1sl6l_169{height:100%;transition:width var(--transition-medium);border-radius:5px}._tierCount_1sl6l_175{text-align:right;width:30px;font-family:var(--font-mono);color:var(--color-text-muted);font-size:12px}@media (width<=1024px){._grid_1sl6l_21{grid-template-columns:1fr}._cardWide_1sl6l_36{grid-column:span 1}}._container_156te_1{width:100%;padding:2rem}._wip_156te_6{text-align:center;flex-direction:column;justify-content:center;align-items:center;min-height:60vh;display:flex}._wip_156te_6 h1{color:var(--text-primary);margin-bottom:1rem;font-size:2rem;font-weight:700}._wip_156te_6 p{color:var(--text-secondary);font-size:1.125rem}._container_18l8h_1{z-index:10000;pointer-events:none;flex-direction:column;gap:8px;display:flex;position:fixed;top:20px;right:20px}._toast_tvk0q_1{pointer-events:auto;border-radius:var(--radius-md,10px);background:var(--color-bg-elevated);border:1px solid var(--color-border);box-shadow:var(--shadow-lg);align-items:center;gap:10px;min-width:280px;max-width:420px;padding:12px 18px;font-size:13px;font-weight:500;animation:.3s cubic-bezier(.16,1,.3,1) _slideIn_tvk0q_1;display:flex}._success_tvk0q_17{border-left:4px solid #0f8}._error_tvk0q_18{border-left:4px solid #f44}._warning_tvk0q_19{border-left:4px solid #fa0}._info_tvk0q_20{border-left:4px solid #06b6d4}._icon_tvk0q_21{flex-shrink:0;font-size:18px}._message_tvk0q_22{flex:1}._close_tvk0q_23{color:var(--color-text-dim);cursor:pointer;background:0 0;border:none;padding:0;font-size:16px;line-height:1}._exiting_tvk0q_32{animation:.3s cubic-bezier(.16,1,.3,1) forwards _slideOut_tvk0q_1}@keyframes _slideIn_tvk0q_1{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes _slideOut_tvk0q_1{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100%)}}:root{--color-bg:#0a0a0f;--color-bg-elevated:#12121a;--color-bg-card:#12121eb3;--color-bg-hover:#1e1e32cc;--color-bg-active:#282841e6;--color-surface:#1a1a2e;--color-border:#ffffff0f;--color-border-hover:#ffffff1f;--color-text:#e8e8f0;--color-text-muted:#8888a8;--color-text-dim:#555570;--color-accent:#76b900;--color-accent-hover:#8ad100;--color-accent-glow:#76b90040;--color-accent-dim:#76b90014;--color-danger:#f44;--color-danger-dim:#ff44441a;--color-warning:#fa0;--color-warning-dim:#ffaa001a;--color-success:#0f8;--color-success-dim:#00ff881a;--color-info:#06b6d4;--color-info-dim:#06b6d41a;--tier-splus:gold;--tier-s:#ff8c00;--tier-aplus:#00c8ff;--tier-a:#3ddc84;--tier-aminus:#7ecf7e;--tier-bplus:#a8a8c8;--tier-b:#808098;--tier-c:#606078;--verdict-perfect:#0f8;--verdict-normal:#76b900;--verdict-slow:#fa0;--verdict-spiky:#f60;--verdict-veryslow:#f44;--verdict-overloaded:#f22;--verdict-unstable:#c00;--verdict-notactive:#555570;--verdict-pending:#444460;--font-sans:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:"JetBrains Mono", "Fira Code", "Cascadia Code", monospace;--header-h:60px;--sidebar-w:64px;--sidebar-w-expanded:200px;--radius-sm:6px;--radius-md:10px;--radius-lg:16px;--radius-xl:20px;--shadow-sm:0 1px 3px #0000004d;--shadow-md:0 4px 12px #0006;--shadow-lg:0 8px 32px #00000080;--shadow-glow:0 0 30px var(--color-accent-glow);--ease-out:cubic-bezier(.16, 1, .3, 1);--transition-fast:.15s var(--ease-out);--transition-medium:.25s var(--ease-out);--transition-slow:.4s var(--ease-out)}[data-theme=light]{--color-bg:#f5f5fa;--color-bg-elevated:#fff;--color-bg-card:#ffffffd9;--color-bg-hover:#f0f0f8e6;--color-bg-active:#e6e6f2f2;--color-surface:#eeeef4;--color-border:#00000014;--color-border-hover:#00000026;--color-text:#1a1a2e;--color-text-muted:#668;--color-text-dim:#99a;--color-accent-glow:#76b90026;--color-accent-dim:#76b9000d;--color-danger-dim:#ff444414;--color-warning-dim:#ffaa0014;--color-success-dim:#00ff8814;--color-info-dim:#06b6d414;--shadow-sm:0 1px 3px #00000014;--shadow-md:0 4px 12px #0000001a;--shadow-lg:0 8px 32px #0000001f}*,:before,:after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px}body{font-family:var(--font-sans);background:var(--color-bg);color:var(--color-text);min-height:100vh;display:flex;position:relative;overflow-x:hidden}a{color:var(--color-accent);text-decoration:none}a:hover{color:var(--color-accent-hover)}code{font-family:var(--font-mono);background:var(--color-surface);border-radius:4px;padding:2px 6px;font-size:12px}.bg-grid{z-index:0;pointer-events:none;background-image:linear-gradient(#ffffff05 1px,#0000 1px),linear-gradient(90deg,#ffffff05 1px,#0000 1px);background-size:60px 60px;position:fixed;inset:0}.bg-glow{z-index:0;pointer-events:none;filter:blur(120px);opacity:.3;border-radius:50%;animation:20s ease-in-out infinite float;position:fixed}.bg-glow--1{background:radial-gradient(circle, var(--color-accent) 0%, transparent 70%);width:600px;height:600px;top:-200px;left:-200px}.bg-glow--2{background:radial-gradient(circle,#6366f1 0%,#0000 70%);width:400px;height:400px;animation-delay:-7s;top:50%;right:-150px}.bg-glow--3{background:radial-gradient(circle,#06b6d4 0%,#0000 70%);width:500px;height:500px;animation-delay:-14s;bottom:-200px;left:30%}@keyframes float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(30px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}[data-theme=light] .bg-glow{opacity:.12}[data-theme=light] .bg-grid{background-image:linear-gradient(#0000000a 1px,#0000 1px),linear-gradient(90deg,#0000000a 1px,#0000 1px)}.app-content{margin-left:var(--sidebar-w);z-index:1;min-height:100vh;transition:margin-left var(--transition-medium);flex-direction:column;flex:1;display:flex;position:relative}.view{flex-direction:column;flex:1;display:flex}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-text-dim)}@media (width<=768px){.app-content{margin-left:0}}
|