aicodeswitch 1.1.2 → 1.2.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/bin/update.js
CHANGED
|
@@ -2,16 +2,17 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const https = require('https');
|
|
5
|
+
const http = require('http');
|
|
5
6
|
const { spawn } = require('child_process');
|
|
6
7
|
const chalk = require('chalk');
|
|
7
8
|
const ora = require('ora');
|
|
8
9
|
const boxen = require('boxen');
|
|
10
|
+
const tar = require('tar');
|
|
9
11
|
|
|
10
12
|
const AICOSWITCH_DIR = path.join(os.homedir(), '.aicodeswitch');
|
|
11
13
|
const RELEASES_DIR = path.join(AICOSWITCH_DIR, 'releases');
|
|
12
14
|
const CURRENT_FILE = path.join(AICOSWITCH_DIR, 'current');
|
|
13
15
|
const PACKAGE_NAME = 'aicodeswitch';
|
|
14
|
-
const NPM_REGISTRY = 'https://registry.npmjs.org';
|
|
15
16
|
|
|
16
17
|
// 确保目录存在
|
|
17
18
|
const ensureDir = (dirPath) => {
|
|
@@ -96,40 +97,67 @@ const getLatestVersion = () => {
|
|
|
96
97
|
});
|
|
97
98
|
};
|
|
98
99
|
|
|
99
|
-
//
|
|
100
|
-
const
|
|
100
|
+
// 下载 tarball 文件
|
|
101
|
+
const downloadTarball = (url, destPath) => {
|
|
101
102
|
return new Promise((resolve, reject) => {
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
'
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
103
|
+
const urlObj = new URL(url);
|
|
104
|
+
const protocol = urlObj.protocol === 'http:' ? http : https;
|
|
105
|
+
|
|
106
|
+
const requestOptions = {
|
|
107
|
+
hostname: urlObj.hostname,
|
|
108
|
+
port: urlObj.port,
|
|
109
|
+
path: urlObj.pathname + urlObj.search,
|
|
110
|
+
method: 'GET',
|
|
111
|
+
headers: {
|
|
112
|
+
'User-Agent': 'aicodeswitch'
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const req = protocol.request(requestOptions, (res) => {
|
|
117
|
+
if (res.statusCode !== 200) {
|
|
118
|
+
reject(new Error(`Failed to download: HTTP ${res.statusCode}`));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
123
|
+
res.pipe(fileStream);
|
|
124
|
+
|
|
125
|
+
fileStream.on('finish', () => {
|
|
126
|
+
fileStream.close();
|
|
127
|
+
resolve(destPath);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
fileStream.on('error', (err) => {
|
|
131
|
+
fs.unlink(destPath, () => {});
|
|
132
|
+
reject(err);
|
|
133
|
+
});
|
|
116
134
|
});
|
|
117
135
|
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
const packageDir = path.join(targetDir, 'node_modules', PACKAGE_NAME);
|
|
122
|
-
if (fs.existsSync(packageDir)) {
|
|
123
|
-
resolve(packageDir);
|
|
124
|
-
} else {
|
|
125
|
-
reject(new Error('Package installation directory not found'));
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
reject(new Error(`npm install failed: ${stderr}`));
|
|
136
|
+
req.on('error', (err) => {
|
|
137
|
+
if (fs.existsSync(destPath)) {
|
|
138
|
+
fs.unlink(destPath, () => {});
|
|
129
139
|
}
|
|
140
|
+
reject(err);
|
|
130
141
|
});
|
|
131
142
|
|
|
132
|
-
|
|
143
|
+
req.setTimeout(60000, () => {
|
|
144
|
+
req.destroy();
|
|
145
|
+
if (fs.existsSync(destPath)) {
|
|
146
|
+
fs.unlink(destPath, () => {});
|
|
147
|
+
}
|
|
148
|
+
reject(new Error('Download timeout'));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
req.end();
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// 解压 tarball 到指定目录
|
|
156
|
+
const extractTarball = (tarballPath, destDir) => {
|
|
157
|
+
return tar.x({
|
|
158
|
+
file: tarballPath,
|
|
159
|
+
cwd: destDir,
|
|
160
|
+
strip: 1, // 去掉 package 目录层级
|
|
133
161
|
});
|
|
134
162
|
};
|
|
135
163
|
|
|
@@ -159,6 +187,37 @@ const restart = () => {
|
|
|
159
187
|
});
|
|
160
188
|
};
|
|
161
189
|
|
|
190
|
+
// 清理旧版本的下载文件(保留最近 3 个版本)
|
|
191
|
+
const cleanupOldVersions = () => {
|
|
192
|
+
try {
|
|
193
|
+
if (!fs.existsSync(RELEASES_DIR)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const versions = fs.readdirSync(RELEASES_DIR)
|
|
198
|
+
.filter(item => {
|
|
199
|
+
const itemPath = path.join(RELEASES_DIR, item);
|
|
200
|
+
return fs.statSync(itemPath).isDirectory();
|
|
201
|
+
})
|
|
202
|
+
.sort((a, b) => {
|
|
203
|
+
// 按版本号降序排序
|
|
204
|
+
return compareVersions(b, a);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// 保留最近 3 个版本,删除其他版本
|
|
208
|
+
if (versions.length > 3) {
|
|
209
|
+
const versionsToDelete = versions.slice(3);
|
|
210
|
+
versionsToDelete.forEach(version => {
|
|
211
|
+
const versionPath = path.join(RELEASES_DIR, version);
|
|
212
|
+
fs.rmSync(versionPath, { recursive: true, force: true });
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
} catch (err) {
|
|
216
|
+
// 清理失败不影响更新流程
|
|
217
|
+
console.error(chalk.yellow(`Warning: Failed to cleanup old versions: ${err.message}`));
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
162
221
|
// 主更新逻辑
|
|
163
222
|
const update = async () => {
|
|
164
223
|
console.log('\n');
|
|
@@ -182,7 +241,6 @@ const update = async () => {
|
|
|
182
241
|
if (comparison <= 0) {
|
|
183
242
|
console.log(chalk.yellow(`\n✓ You are already on the latest version (${chalk.bold(currentVersion)})\n`));
|
|
184
243
|
process.exit(0);
|
|
185
|
-
return;
|
|
186
244
|
}
|
|
187
245
|
|
|
188
246
|
console.log(chalk.cyan(`\n📦 Update available: ${chalk.bold(currentVersion)} → ${chalk.bold(latestVersion)}\n`));
|
|
@@ -190,34 +248,58 @@ const update = async () => {
|
|
|
190
248
|
// 确保目录存在
|
|
191
249
|
ensureDir(RELEASES_DIR);
|
|
192
250
|
|
|
193
|
-
//
|
|
194
|
-
const
|
|
195
|
-
|
|
251
|
+
// 创建版本目录
|
|
252
|
+
const versionDir = path.join(RELEASES_DIR, latestVersion);
|
|
253
|
+
ensureDir(versionDir);
|
|
254
|
+
|
|
255
|
+
// 下载 tarball
|
|
256
|
+
const downloadSpinner = ora({
|
|
257
|
+
text: chalk.cyan('Downloading from npm...'),
|
|
196
258
|
color: 'cyan'
|
|
197
259
|
}).start();
|
|
198
260
|
|
|
199
|
-
const
|
|
200
|
-
ensureDir(versionDir);
|
|
261
|
+
const tarballPath = path.join(versionDir, 'package.tgz');
|
|
201
262
|
|
|
202
263
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
264
|
+
await downloadTarball(latestInfo.tarball, tarballPath);
|
|
265
|
+
downloadSpinner.succeed(chalk.green('Download completed'));
|
|
205
266
|
} catch (err) {
|
|
206
|
-
|
|
267
|
+
downloadSpinner.fail(chalk.red('Download failed'));
|
|
207
268
|
console.log(chalk.red(`Error: ${err.message}\n`));
|
|
208
269
|
process.exit(1);
|
|
209
|
-
return;
|
|
210
270
|
}
|
|
211
271
|
|
|
212
|
-
//
|
|
213
|
-
const
|
|
214
|
-
|
|
272
|
+
// 解压 tarball
|
|
273
|
+
const extractSpinner = ora({
|
|
274
|
+
text: chalk.cyan('Extracting package...'),
|
|
275
|
+
color: 'cyan'
|
|
276
|
+
}).start();
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
await extractTarball(tarballPath, versionDir);
|
|
280
|
+
extractSpinner.succeed(chalk.green('Package extracted'));
|
|
281
|
+
} catch (err) {
|
|
282
|
+
extractSpinner.fail(chalk.red('Extraction failed'));
|
|
283
|
+
console.log(chalk.red(`Error: ${err.message}\n`));
|
|
284
|
+
process.exit(1);
|
|
285
|
+
} finally {
|
|
286
|
+
// 删除 tarball 文件
|
|
287
|
+
if (fs.existsSync(tarballPath)) {
|
|
288
|
+
fs.unlinkSync(tarballPath);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// 更新 current 文件
|
|
293
|
+
updateCurrentFile(versionDir);
|
|
294
|
+
|
|
295
|
+
// 清理旧版本
|
|
296
|
+
cleanupOldVersions();
|
|
215
297
|
|
|
216
298
|
// 显示更新成功信息
|
|
217
299
|
console.log(boxen(
|
|
218
300
|
chalk.green.bold('✨ Update Successful!\n\n') +
|
|
219
301
|
chalk.white('Version: ') + chalk.cyan.bold(latestVersion) + '\n' +
|
|
220
|
-
chalk.white('Location: ') + chalk.gray(
|
|
302
|
+
chalk.white('Location: ') + chalk.gray(versionDir) + '\n\n' +
|
|
221
303
|
chalk.gray('Restarting server with the new version...'),
|
|
222
304
|
{
|
|
223
305
|
padding: 1,
|
|
@@ -234,7 +316,6 @@ const update = async () => {
|
|
|
234
316
|
console.log(chalk.yellow(`\n⚠️ Update completed, but restart failed: ${err.message}`));
|
|
235
317
|
console.log(chalk.cyan('Please manually run: ') + chalk.yellow('aicos restart\n'));
|
|
236
318
|
process.exit(1);
|
|
237
|
-
return;
|
|
238
319
|
}
|
|
239
320
|
|
|
240
321
|
process.exit(0);
|
package/dist/server/database.js
CHANGED
|
@@ -292,19 +292,13 @@ class DatabaseManager {
|
|
|
292
292
|
getLogs() {
|
|
293
293
|
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
294
294
|
var _a, e_1, _b, _c;
|
|
295
|
-
const
|
|
296
|
-
let count = 0;
|
|
295
|
+
const allLogs = [];
|
|
297
296
|
try {
|
|
298
|
-
for (var _d = true, _e = __asyncValues(this.logDb.iterator(
|
|
297
|
+
for (var _d = true, _e = __asyncValues(this.logDb.iterator()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
299
298
|
_c = _f.value;
|
|
300
299
|
_d = false;
|
|
301
300
|
const [, value] = _c;
|
|
302
|
-
|
|
303
|
-
logs.push(JSON.parse(value));
|
|
304
|
-
}
|
|
305
|
-
count++;
|
|
306
|
-
if (logs.length >= limit)
|
|
307
|
-
break;
|
|
301
|
+
allLogs.push(JSON.parse(value));
|
|
308
302
|
}
|
|
309
303
|
}
|
|
310
304
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
@@ -314,7 +308,10 @@ class DatabaseManager {
|
|
|
314
308
|
}
|
|
315
309
|
finally { if (e_1) throw e_1.error; }
|
|
316
310
|
}
|
|
317
|
-
|
|
311
|
+
// Sort by timestamp in descending order (newest first)
|
|
312
|
+
allLogs.sort((a, b) => b.timestamp - a.timestamp);
|
|
313
|
+
// Apply offset and limit
|
|
314
|
+
return allLogs.slice(offset, offset + limit);
|
|
318
315
|
});
|
|
319
316
|
}
|
|
320
317
|
clearLogs() {
|
|
@@ -340,19 +337,13 @@ class DatabaseManager {
|
|
|
340
337
|
getAccessLogs() {
|
|
341
338
|
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
342
339
|
var _a, e_2, _b, _c;
|
|
343
|
-
const
|
|
344
|
-
let count = 0;
|
|
340
|
+
const allLogs = [];
|
|
345
341
|
try {
|
|
346
|
-
for (var _d = true, _e = __asyncValues(this.accessLogDb.iterator(
|
|
342
|
+
for (var _d = true, _e = __asyncValues(this.accessLogDb.iterator()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
347
343
|
_c = _f.value;
|
|
348
344
|
_d = false;
|
|
349
345
|
const [, value] = _c;
|
|
350
|
-
|
|
351
|
-
logs.push(JSON.parse(value));
|
|
352
|
-
}
|
|
353
|
-
count++;
|
|
354
|
-
if (logs.length >= limit)
|
|
355
|
-
break;
|
|
346
|
+
allLogs.push(JSON.parse(value));
|
|
356
347
|
}
|
|
357
348
|
}
|
|
358
349
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
@@ -362,7 +353,10 @@ class DatabaseManager {
|
|
|
362
353
|
}
|
|
363
354
|
finally { if (e_2) throw e_2.error; }
|
|
364
355
|
}
|
|
365
|
-
|
|
356
|
+
// Sort by timestamp in descending order (newest first)
|
|
357
|
+
allLogs.sort((a, b) => b.timestamp - a.timestamp);
|
|
358
|
+
// Apply offset and limit
|
|
359
|
+
return allLogs.slice(offset, offset + limit);
|
|
366
360
|
});
|
|
367
361
|
}
|
|
368
362
|
clearAccessLogs() {
|
|
@@ -380,19 +374,13 @@ class DatabaseManager {
|
|
|
380
374
|
getErrorLogs() {
|
|
381
375
|
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
382
376
|
var _a, e_3, _b, _c;
|
|
383
|
-
const
|
|
384
|
-
let count = 0;
|
|
377
|
+
const allLogs = [];
|
|
385
378
|
try {
|
|
386
|
-
for (var _d = true, _e = __asyncValues(this.errorLogDb.iterator(
|
|
379
|
+
for (var _d = true, _e = __asyncValues(this.errorLogDb.iterator()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
387
380
|
_c = _f.value;
|
|
388
381
|
_d = false;
|
|
389
382
|
const [, value] = _c;
|
|
390
|
-
|
|
391
|
-
logs.push(JSON.parse(value));
|
|
392
|
-
}
|
|
393
|
-
count++;
|
|
394
|
-
if (logs.length >= limit)
|
|
395
|
-
break;
|
|
383
|
+
allLogs.push(JSON.parse(value));
|
|
396
384
|
}
|
|
397
385
|
}
|
|
398
386
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
@@ -402,7 +390,10 @@ class DatabaseManager {
|
|
|
402
390
|
}
|
|
403
391
|
finally { if (e_3) throw e_3.error; }
|
|
404
392
|
}
|
|
405
|
-
|
|
393
|
+
// Sort by timestamp in descending order (newest first)
|
|
394
|
+
allLogs.sort((a, b) => b.timestamp - a.timestamp);
|
|
395
|
+
// Apply offset and limit
|
|
396
|
+
return allLogs.slice(offset, offset + limit);
|
|
406
397
|
});
|
|
407
398
|
}
|
|
408
399
|
clearErrorLogs() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.app{display:flex;width:100%;height:100%}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:20px;box-shadow:0 8px 32px var(--shadow-primary),0 0 20px #0478574d;margin:16px;position:relative;z-index:1;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1)}.logo{padding:28px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden}.logo:before{content:"✨";position:absolute;top:12px;left:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:after{content:"🌟";position:absolute;top:12px;right:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:hover:before,.logo:focus:before{animation:sparkle 3s ease-in-out infinite}.logo:hover:after,.logo:focus:after{animation:sparkle 3s ease-in-out infinite 1.5s}@keyframes sparkle{0%,to{transform:scale(1) rotate(0);opacity:.7}50%{transform:scale(1.2) rotate(180deg);opacity:1}}.logo h2{font-size:22px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease}.logo:hover h2,.logo:focus h2{animation:logoGlow 4s ease-in-out infinite}@keyframes logoGlow{0%,to{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3)}50%{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 30px rgba(4,120,87,.5),0 0 40px rgba(4,120,87,.3)}}.nav-menu{list-style:none;padding:16px 0;margin:0}.nav-menu li{margin:8px 12px}.nav-menu a{display:block;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a;transform:translate(4px);box-shadow:0 4px 12px #0f172a33}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));box-shadow:0 4px 16px var(--shadow-primary)}.main-content{flex:1;padding:24px;overflow-y:auto;background:var(--bg-primary);position:relative;z-index:1;margin:16px 16px 16px 0;border-radius:20px}.main-content:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background-image:radial-gradient(circle at 20% 80%,rgba(255,206,92,.1) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(134,204,202,.1) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(255,113,206,.05) 0%,transparent 50%);pointer-events:none}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 8px 32px var(--shadow-secondary),0 0 16px #0478571a;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary),var(--accent-primary));border-radius:20px 20px 0 0;background-size:200% 100%;transition:all .3s ease}.card:hover:before{animation:gradientShift 3s ease-in-out infinite}@keyframes gradientShift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.card:hover{transform:translateY(-2px);box-shadow:0 12px 40px #6a7bb433,0 8px 24px #ff71ce26}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;box-shadow:0 2px 8px #0000001a;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:hover{transform:translateY(-1px);box-shadow:0 4px 16px #00000026}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 25px #04785766}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden;box-shadow:0 4px 16px #6a7bb41a}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;justify-content:center;align-items:center;z-index:1000;animation:modalFadeIn .3s ease-out}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-radius:24px;padding:32px;min-width:500px;max-width:90%;max-height:90%;overflow-y:auto;box-shadow:0 20px 60px var(--shadow-primary),0 8px 32px var(--shadow-secondary);border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.modal-header h2{font-size:20px;color:var(--text-primary)}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;box-shadow:0 2px 8px #0000001a;margin-top:-40px;margin-right:-24px}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:center;gap:12px;padding:12px;background:#ffffff14;border-radius:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);transition:all .3s ease-out}.theme-toggle:hover{background:#ffffff1f}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;box-shadow:0 2px 8px var(--shadow-primary),0 0 8px #04785780;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid transparent;transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary);border-bottom-color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:hidden}
|
|
1
|
+
.app{display:flex;width:100%;height:100%}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:20px;box-shadow:0 8px 32px var(--shadow-primary),0 0 20px #0478574d;margin:16px;position:relative;z-index:1;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1)}.logo{padding:28px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden}.logo:before{content:"✨";position:absolute;top:12px;left:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:after{content:"🌟";position:absolute;top:12px;right:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:hover:before,.logo:focus:before{animation:sparkle 3s ease-in-out infinite}.logo:hover:after,.logo:focus:after{animation:sparkle 3s ease-in-out infinite 1.5s}@keyframes sparkle{0%,to{transform:scale(1) rotate(0);opacity:.7}50%{transform:scale(1.2) rotate(180deg);opacity:1}}.logo h2{font-size:22px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease}.logo:hover h2,.logo:focus h2{animation:logoGlow 4s ease-in-out infinite}@keyframes logoGlow{0%,to{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3)}50%{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 30px rgba(4,120,87,.5),0 0 40px rgba(4,120,87,.3)}}.nav-menu{list-style:none;padding:16px 0;margin:0}.nav-menu li{margin:8px 12px}.nav-menu a{display:block;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a;transform:translate(4px);box-shadow:0 4px 12px #0f172a33}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));box-shadow:0 4px 16px var(--shadow-primary)}.main-content{flex:1;padding:24px;overflow-y:auto;background:var(--bg-primary);position:relative;z-index:1;margin:16px 16px 16px 0;border-radius:20px}.main-content:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background-image:radial-gradient(circle at 20% 80%,rgba(255,206,92,.1) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(134,204,202,.1) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(255,113,206,.05) 0%,transparent 50%);pointer-events:none}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 8px 32px var(--shadow-secondary),0 0 16px #0478571a;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary),var(--accent-primary));border-radius:20px 20px 0 0;background-size:200% 100%;transition:all .3s ease}.card:hover:before{animation:gradientShift 3s ease-in-out infinite}@keyframes gradientShift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.card:hover{transform:translateY(-2px);box-shadow:0 12px 40px #6a7bb433,0 8px 24px #ff71ce26}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;box-shadow:0 2px 8px #0000001a;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:hover{transform:translateY(-1px);box-shadow:0 4px 16px #00000026}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 25px #04785766}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden;box-shadow:0 4px 16px #6a7bb41a}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;justify-content:center;align-items:center;z-index:1000;animation:modalFadeIn .3s ease-out}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-radius:24px;padding:32px;min-width:500px;max-width:90%;max-height:90%;overflow-y:auto;box-shadow:0 20px 60px var(--shadow-primary),0 8px 32px var(--shadow-secondary);border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.modal-header h2{font-size:20px;color:var(--text-primary)}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;box-shadow:0 2px 8px #0000001a;margin-top:-40px;margin-right:-24px}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:center;gap:12px;padding:12px;background:#ffffff14;border-radius:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);transition:all .3s ease-out}.theme-toggle:hover{background:#ffffff1f}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;box-shadow:0 2px 8px var(--shadow-primary),0 0 8px #04785780;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid transparent;transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary);border-bottom-color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:hidden}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:8px}::-webkit-scrollbar-thumb{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));border-radius:8px;border:2px solid var(--bg-secondary);box-shadow:0 2px 4px #0000001a;transition:all .3s ease}::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,var(--accent-secondary),var(--accent-primary));box-shadow:0 4px 8px #0003;transform:scale(1.1)}::-webkit-scrollbar-thumb:active{background:var(--accent-primary);box-shadow:0 6px 12px #0000004d}::-webkit-scrollbar-corner{background:var(--bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--accent-primary) var(--bg-secondary)}::-webkit-scrollbar-button{display:none}html{scroll-behavior:smooth}
|