@fairys/mocker-cli 0.0.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.
Files changed (65) hide show
  1. package/README.md +36 -0
  2. package/bin/fairys-mocker +22 -0
  3. package/esm/base.d.ts +28 -0
  4. package/esm/base.js +80 -0
  5. package/esm/ci.d.ts +2 -0
  6. package/esm/ci.js +49 -0
  7. package/esm/connect.d.ts +15 -0
  8. package/esm/connect.js +38 -0
  9. package/esm/controller/base.d.ts +2 -0
  10. package/esm/controller/base.js +3 -0
  11. package/esm/controller/index.d.ts +3 -0
  12. package/esm/controller/index.js +3 -0
  13. package/esm/controller/mock.router.d.ts +21 -0
  14. package/esm/controller/mock.router.js +497 -0
  15. package/esm/controller/proxy.router.d.ts +18 -0
  16. package/esm/controller/proxy.router.js +503 -0
  17. package/esm/index.d.ts +5 -0
  18. package/esm/index.js +5 -0
  19. package/esm/main.d.ts +15 -0
  20. package/esm/main.js +38 -0
  21. package/esm/plugins/rsbuild.d.ts +2 -0
  22. package/esm/plugins/rsbuild.js +12 -0
  23. package/esm/router/base.d.ts +12 -0
  24. package/esm/router/base.js +23 -0
  25. package/esm/router/index.d.ts +3 -0
  26. package/esm/router/index.js +3 -0
  27. package/esm/router/mock.d.ts +7 -0
  28. package/esm/router/mock.js +32 -0
  29. package/esm/router/proxy.d.ts +14 -0
  30. package/esm/router/proxy.js +67 -0
  31. package/esm/utils/decorator.d.ts +18 -0
  32. package/esm/utils/decorator.js +55 -0
  33. package/esm/utils/index.d.ts +2 -0
  34. package/esm/utils/index.js +2 -0
  35. package/esm/utils/mcok.proxy.d.ts +36 -0
  36. package/esm/utils/mcok.proxy.js +141 -0
  37. package/esm/utils/utils.d.ts +20 -0
  38. package/esm/utils/utils.js +31 -0
  39. package/package.json +52 -0
  40. package/public/_fairys_mocker/favicon.png +0 -0
  41. package/public/_fairys_mocker/index.html +1 -0
  42. package/public/_fairys_mocker/static/css/index.2ba69ff5.css +1 -0
  43. package/public/_fairys_mocker/static/js/514.950758f1.js +2 -0
  44. package/public/_fairys_mocker/static/js/514.950758f1.js.LICENSE.txt +5 -0
  45. package/public/_fairys_mocker/static/js/index.f70ed1dc.js +1 -0
  46. package/public/_fairys_mocker/static/js/lib-react.2748fa4b.js +2 -0
  47. package/public/_fairys_mocker/static/js/lib-react.2748fa4b.js.LICENSE.txt +49 -0
  48. package/src/base.ts +125 -0
  49. package/src/ci.ts +61 -0
  50. package/src/connect.ts +62 -0
  51. package/src/controller/base.ts +4 -0
  52. package/src/controller/index.ts +3 -0
  53. package/src/controller/mock.router.ts +175 -0
  54. package/src/controller/proxy.router.ts +182 -0
  55. package/src/index.ts +5 -0
  56. package/src/main.ts +59 -0
  57. package/src/plugins/rsbuild.ts +14 -0
  58. package/src/router/base.ts +36 -0
  59. package/src/router/index.ts +3 -0
  60. package/src/router/mock.ts +38 -0
  61. package/src/router/proxy.ts +89 -0
  62. package/src/utils/decorator.ts +90 -0
  63. package/src/utils/index.ts +2 -0
  64. package/src/utils/mcok.proxy.ts +162 -0
  65. package/src/utils/utils.ts +46 -0
@@ -0,0 +1,14 @@
1
+ import express from 'express';
2
+ import { ProxyItem } from "@fairys/create-mock-data";
3
+ import { BaseRouter } from "./base.js";
4
+ import { RequestHandler } from "http-proxy-middleware";
5
+ /**代理 路由器实例*/
6
+ export declare class ProxyRouter extends BaseRouter<ProxyItem> {
7
+ /**代理 路由器实例*/
8
+ router: express.Router | null;
9
+ wsProxyList: RequestHandler[];
10
+ /**加载代理路由*/
11
+ load: (proxyList: ProxyItem[]) => void;
12
+ /**销毁路由器实例*/
13
+ destroy: (msg?: string) => void;
14
+ }
@@ -0,0 +1,67 @@
1
+ import express from "express";
2
+ import { BaseRouter } from "./base.js";
3
+ import { createProxyMiddleware } from "http-proxy-middleware";
4
+ import chalk from "chalk";
5
+ import { fairysMockerBase } from "../base.js";
6
+ class ProxyRouter extends BaseRouter {
7
+ router = null;
8
+ wsProxyList = [];
9
+ load = (proxyList)=>{
10
+ const _that = this;
11
+ this.destroy();
12
+ const router = this.router = express.Router();
13
+ this.isEnabled = true;
14
+ for(let index = 0; index < proxyList.length; index++){
15
+ const proxyItem = proxyList[index];
16
+ let protocol = 'http';
17
+ let _target = proxyItem.target;
18
+ let _path = new RegExp(proxyItem.path);
19
+ if (/^(http:|https:|ws:|wss:)/.test(proxyItem.target)) {
20
+ const [_protocol] = proxyItem.target.split(":");
21
+ protocol = _protocol;
22
+ }
23
+ if ('ws' !== protocol && 'wss' !== protocol && proxyItem.ws) {
24
+ protocol = 'ws';
25
+ const [_protocol, ...rest] = proxyItem.target.split(":");
26
+ _target = [
27
+ protocol,
28
+ ...rest
29
+ ].join(":");
30
+ }
31
+ console.log(chalk.hex('#AF52DE')(chalk.bold(` 🍇 proxy代理启动:\t${chalk.yellow(protocol)}\t${proxyItem.path} ===> ${_target}\t`)));
32
+ if (!proxyItem.path.startsWith('^')) _path = new RegExp('^' + proxyItem.path);
33
+ if (proxyItem.ws) {
34
+ const wsProxy = createProxyMiddleware({
35
+ target: proxyItem.target,
36
+ pathRewrite: proxyItem.pathRewrite,
37
+ ws: proxyItem.ws,
38
+ changeOrigin: true
39
+ });
40
+ _that.wsProxyList.push(wsProxy);
41
+ router.all(_path, wsProxy);
42
+ if (fairysMockerBase.server) fairysMockerBase.server?.on('upgrade', wsProxy.upgrade);
43
+ } else router.all(_path, createProxyMiddleware({
44
+ target: proxyItem.target,
45
+ pathRewrite: proxyItem.pathRewrite,
46
+ ws: proxyItem.ws,
47
+ changeOrigin: true
48
+ }));
49
+ }
50
+ console.log('');
51
+ this.useRouter();
52
+ };
53
+ destroy = (msg)=>{
54
+ if (this.router) {
55
+ this.router.stack = [];
56
+ this.isEnabled = false;
57
+ }
58
+ const wsProxyList = this.wsProxyList;
59
+ if (Array.isArray(wsProxyList) && wsProxyList.length && fairysMockerBase.server) for(let index = 0; index < wsProxyList.length; index++){
60
+ const wsProxy = wsProxyList[index];
61
+ fairysMockerBase.server.off('upgrade', wsProxy.upgrade);
62
+ }
63
+ if (msg) console.log(chalk.red(msg));
64
+ console.log('');
65
+ };
66
+ }
67
+ export { ProxyRouter };
@@ -0,0 +1,18 @@
1
+ export type ClassStruct<TInstanceType extends unknown = unknown> = new (...args: any[]) => TInstanceType;
2
+ export interface RouteItemType {
3
+ method: 'get' | 'delete' | 'post' | 'put' | 'patch' | 'head' | 'options';
4
+ path: string;
5
+ funName?: string | symbol;
6
+ }
7
+ export interface ControllerItemType {
8
+ prefix?: string;
9
+ }
10
+ /**控制器参数*/
11
+ export declare const controllerMap: WeakMap<object, ControllerItemType>;
12
+ /**路由方法参数*/
13
+ export declare const routesMap: WeakMap<object, RouteItemType>;
14
+ export declare function Controller(prefix: string): (target: any, context: ClassDecoratorContext) => void;
15
+ export declare function Post(path: string): (target: any, context: ClassMethodDecoratorContext) => void;
16
+ export declare function Get(path: string): (target: any, context: ClassMethodDecoratorContext) => void;
17
+ export declare function MethodPath(path: string, method?: RouteItemType['method']): (target: any, context: ClassMethodDecoratorContext) => void;
18
+ export declare function registerRoutes(instance: unknown): void;
@@ -0,0 +1,55 @@
1
+ import { fairysMockerBase } from "../base.js";
2
+ const controllerMap = new WeakMap();
3
+ const routesMap = new WeakMap();
4
+ function Controller(prefix) {
5
+ return (target, context)=>{
6
+ controllerMap.set(target, {
7
+ prefix
8
+ });
9
+ };
10
+ }
11
+ function Post(path) {
12
+ return (target, context)=>{
13
+ if ('method' === context.kind) routesMap.set(target, {
14
+ method: 'post',
15
+ path,
16
+ funName: context.name
17
+ });
18
+ };
19
+ }
20
+ function Get(path) {
21
+ return (target, context)=>{
22
+ if ('method' === context.kind) routesMap.set(target, {
23
+ method: 'get',
24
+ path,
25
+ funName: context.name
26
+ });
27
+ };
28
+ }
29
+ function MethodPath(path, method = 'post') {
30
+ return (target, context)=>{
31
+ if ('method' === context.kind) routesMap.set(target, {
32
+ method: method.toLowerCase(),
33
+ path,
34
+ funName: context.name
35
+ });
36
+ };
37
+ }
38
+ function registerRoutes(instance) {
39
+ const fairysRouter = fairysMockerBase.fairysMockerRouter;
40
+ if (!fairysRouter) return void console.log('请先初始化内置路由');
41
+ const proto = Object.getPrototypeOf(instance);
42
+ const controllerAPIRootPath = controllerMap.get(proto.constructor);
43
+ const controllerMethods = Object.getOwnPropertyNames(proto).filter((i)=>"constructor" !== i);
44
+ for(let index = 0; index < controllerMethods.length; index++){
45
+ const controllerMethod = controllerMethods[index];
46
+ const _requestHandle = proto[controllerMethod];
47
+ const boundRequestHandle = _requestHandle.bind(instance);
48
+ const routeItem = routesMap.get(_requestHandle);
49
+ if (routeItem) {
50
+ const fullPath = (controllerAPIRootPath?.prefix || '') + routeItem.path;
51
+ fairysRouter[routeItem.method](fullPath, (req, res)=>boundRequestHandle(req, res));
52
+ }
53
+ }
54
+ }
55
+ export { Controller, Get, MethodPath, Post, controllerMap, registerRoutes, routesMap };
@@ -0,0 +1,2 @@
1
+ export * from "./utils.js";
2
+ export * from "./decorator.js";
@@ -0,0 +1,2 @@
1
+ export * from "./utils.js";
2
+ export * from "./decorator.js";
@@ -0,0 +1,36 @@
1
+ import { ProxyList, DefineMockList } from "@fairys/create-mock-data";
2
+ export declare const getProxyFile: (rootDir?: string, dir?: string, fileName?: string) => {
3
+ proxyList: any;
4
+ rootDir: string;
5
+ dir: string;
6
+ fileName: string;
7
+ cache: string;
8
+ } | undefined;
9
+ export declare const createProxyFile: (proxyList: ProxyList, rootDir?: string, dir?: string, fileName?: string) => {
10
+ proxyConfig: Record<string, Omit<import("@fairys/create-mock-data").ProxyItem, "path">>;
11
+ rootDir: string;
12
+ dir: string;
13
+ fileName: string;
14
+ cache: string;
15
+ };
16
+ export declare const getMcokFile: (rootDir?: string, dir?: string, fileName?: string) => {
17
+ mockList: any;
18
+ rootDir: string;
19
+ dir: string;
20
+ fileName: string;
21
+ cache: string;
22
+ } | undefined;
23
+ export declare const createMockFile: (mockList: DefineMockList, rootDir?: string, dir?: string, fileName?: string) => {
24
+ mockConfig: {
25
+ body: any;
26
+ delay: number;
27
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
28
+ status: string;
29
+ url: string;
30
+ listCount: number;
31
+ }[];
32
+ rootDir: string;
33
+ dir: string;
34
+ fileName: string;
35
+ cache: string;
36
+ };
@@ -0,0 +1,141 @@
1
+ import node_path from "node:path";
2
+ import node_fs from "node:fs";
3
+ import { utils } from "./utils.js";
4
+ import { createMockData, createProxyData } from "@fairys/create-mock-data";
5
+ const getProxyFile = (rootDir, dir, fileName)=>{
6
+ const _rootDir = rootDir?.trim() || utils.rootDir;
7
+ const _dir = dir?.trim() || utils.dir;
8
+ const _fileName = fileName?.trim() || utils.proxyFile;
9
+ const proxyDir = node_path.join(_rootDir, _dir);
10
+ const cacheFilePath = node_path.join(proxyDir, _fileName + '.cache.json');
11
+ if (node_fs.existsSync(cacheFilePath)) {
12
+ const cacheFileContent = node_fs.readFileSync(cacheFilePath, 'utf-8');
13
+ const cacheData = JSON.parse(cacheFileContent);
14
+ const proxyList = cacheData.proxyList || [];
15
+ return {
16
+ proxyList,
17
+ rootDir: _rootDir,
18
+ dir: _dir,
19
+ fileName: _fileName,
20
+ cache: _fileName + '.cache.json'
21
+ };
22
+ }
23
+ };
24
+ const createProxyFile = (proxyList, rootDir, dir, fileName)=>{
25
+ const _rootDir = rootDir?.trim() || utils.rootDir;
26
+ const _dir = dir?.trim() || utils.dir;
27
+ const _fileName = fileName?.trim() || utils.proxyFile;
28
+ const proxyDir = node_path.join(_rootDir, _dir);
29
+ if (!node_fs.existsSync(proxyDir)) node_fs.mkdirSync(proxyDir, {
30
+ recursive: true
31
+ });
32
+ const proxyConfig = createProxyData(proxyList);
33
+ const proxyFilePath = node_path.join(proxyDir, `${_fileName}.ts`);
34
+ const proxyFileContent = `// 代理配置文件
35
+ // 自动生成于 ${new Date().toISOString()}
36
+
37
+ /**
38
+ * 代理配置参数
39
+ */
40
+ export type ProxyItem = Record<string,{
41
+ /**转发地址*/
42
+ target: string,
43
+ /**路径重写*/
44
+ pathRewrite?: Record<string, string>,
45
+ /**是否开启ws*/
46
+ ws?: boolean
47
+ }>
48
+
49
+ export const proxyConfig: ProxyItem = ${JSON.stringify(proxyConfig, null, 2)};
50
+ export default proxyConfig;
51
+ `;
52
+ node_fs.writeFileSync(proxyFilePath, proxyFileContent);
53
+ const cacheFilePath = node_path.join(proxyDir, _fileName + '.cache.json');
54
+ const cacheFileContent = JSON.stringify({
55
+ proxyList,
56
+ rootDir: _rootDir,
57
+ dir: _dir,
58
+ fileName: _fileName,
59
+ cache: _fileName + '.cache.json'
60
+ }, null, 2);
61
+ node_fs.writeFileSync(cacheFilePath, cacheFileContent);
62
+ return {
63
+ proxyConfig,
64
+ rootDir: _rootDir,
65
+ dir: _dir,
66
+ fileName: _fileName,
67
+ cache: _fileName + '.cache.json'
68
+ };
69
+ };
70
+ const getMcokFile = (rootDir, dir, fileName)=>{
71
+ const _rootDir = rootDir?.trim() || utils.rootDir;
72
+ const _dir = dir?.trim() || utils.dir;
73
+ const _fileName = fileName?.trim() || utils.file;
74
+ const mockDir = node_path.join(_rootDir, _dir);
75
+ const cacheFilePath = node_path.join(mockDir, _fileName + '.cache.json');
76
+ if (node_fs.existsSync(cacheFilePath)) {
77
+ const cacheFileContent = node_fs.readFileSync(cacheFilePath, 'utf-8');
78
+ const cacheData = JSON.parse(cacheFileContent);
79
+ const mockList = cacheData.mockList || [];
80
+ return {
81
+ mockList,
82
+ rootDir: _rootDir,
83
+ dir: _dir,
84
+ fileName: _fileName,
85
+ cache: _fileName + '.cache.json'
86
+ };
87
+ }
88
+ };
89
+ const createMockFile = (mockList, rootDir, dir, fileName)=>{
90
+ const _rootDir = rootDir?.trim() || utils.rootDir;
91
+ const _dir = dir?.trim() || utils.dir;
92
+ const _fileName = fileName?.trim() || utils.file;
93
+ const mockDir = node_path.join(_rootDir, _dir);
94
+ if (!node_fs.existsSync(mockDir)) node_fs.mkdirSync(mockDir, {
95
+ recursive: true
96
+ });
97
+ const mockConfig = createMockData(mockList);
98
+ const mockFilePath = node_path.join(mockDir, `${_fileName}.ts`);
99
+ const mockFileContent = `// Mock 配置文件
100
+ // 自动生成于 ${new Date().toISOString()}
101
+
102
+ export interface MockerItem {
103
+ /**该接口允许的 请求方法,默认同时支持 GET 和 POST*/
104
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
105
+ /**状态码*/
106
+ status: string;
107
+ //配置响应延迟时间, 如果传入的是一个数组,则代表延迟时间的范围
108
+ delay: number | [number, number];
109
+ /**响应体(可以自定义返回格式)*/
110
+ body: any;
111
+ /**接口地址*/
112
+ url: string;
113
+ /**列表数据条数(仅 list 格式有效)*/
114
+ listCount?: number;
115
+ }
116
+
117
+ /**mock配置 列表*/
118
+ export type DefineMockList = MockerItem[];
119
+
120
+ export const mockList: DefineMockList = ${JSON.stringify(mockConfig, null, 2)};
121
+ export default mockList;
122
+ `;
123
+ node_fs.writeFileSync(mockFilePath, mockFileContent);
124
+ const cacheFilePath = node_path.join(mockDir, _fileName + '.cache.json');
125
+ const cacheFileContent = JSON.stringify({
126
+ mockList,
127
+ rootDir: _rootDir,
128
+ dir: _dir,
129
+ fileName: _fileName,
130
+ cache: _fileName + '.cache.json'
131
+ }, null, 2);
132
+ node_fs.writeFileSync(cacheFilePath, cacheFileContent);
133
+ return {
134
+ mockConfig,
135
+ rootDir: _rootDir,
136
+ dir: _dir,
137
+ fileName: _fileName,
138
+ cache: _fileName + '.cache.json'
139
+ };
140
+ };
141
+ export { createMockFile, createProxyFile, getMcokFile, getProxyFile };
@@ -0,0 +1,20 @@
1
+ declare class Utils {
2
+ /**根目录*/
3
+ rootDir: string;
4
+ /**目录名*/
5
+ dir: string;
6
+ /**文件名*/
7
+ file: string;
8
+ /**代理文件名*/
9
+ proxyFile: string;
10
+ /**设置根目录*/
11
+ setRootDir: (value?: string) => void;
12
+ /**设置目录名*/
13
+ setDir: (value?: string) => void;
14
+ /**设置文件名*/
15
+ setFile: (value?: string) => void;
16
+ /**设置代理文件名*/
17
+ setProxyFile: (value?: string) => void;
18
+ }
19
+ export declare const utils: Utils;
20
+ export {};
@@ -0,0 +1,31 @@
1
+ import chalk from "chalk";
2
+ import node_fs from "node:fs";
3
+ import node_path from "node:path";
4
+ class Utils {
5
+ rootDir = process.cwd();
6
+ dir = 'mock';
7
+ file = 'index.mock';
8
+ proxyFile = 'proxy';
9
+ setRootDir = (value)=>{
10
+ if (value && node_fs.existsSync(value)) this.rootDir = value;
11
+ else {
12
+ if (value) {
13
+ console.log('');
14
+ console.log(chalk.red(`设置的根目录不存在:${value}`));
15
+ console.log('');
16
+ }
17
+ this.rootDir = process.env.FAIRYS_MOCKER_ROOT_DIR || node_path.join(process.cwd());
18
+ }
19
+ };
20
+ setDir = (value)=>{
21
+ this.dir = value || process.env.FAIRYS_MOCKER_DIR || 'mock';
22
+ };
23
+ setFile = (value)=>{
24
+ this.file = value || process.env.FAIRYS_MOCKER_FILE || 'index.mock';
25
+ };
26
+ setProxyFile = (value)=>{
27
+ this.proxyFile = value || process.env.FAIRYS_MOCKER_PROXY_FILE || 'proxy';
28
+ };
29
+ }
30
+ const utils = new Utils();
31
+ export { utils };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@fairys/mocker-cli",
3
+ "version": "0.0.1",
4
+ "description": "Fairys Mocker CLI for mock data generation",
5
+ "author": "SunLxy <1011771396@qq.com>",
6
+ "homepage": "https://github.com/autumn-fairy-tales/fairys-mocker",
7
+ "main": "esm/index.js",
8
+ "types": "esm/index.d.ts",
9
+ "module": "esm/index.js",
10
+ "license": "ISC",
11
+ "type": "module",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/autumn-fairy-tales/fairys-mocker.git",
18
+ "directory": "packages/mocker-cli"
19
+ },
20
+ "scripts": {
21
+ "start": "node --trace-deprecation bin/fairys-mocker",
22
+ "build": "carefrees-rslib build --node --esm",
23
+ "watch": "carefrees-rslib build --watch --node --esm"
24
+ },
25
+ "bin": {
26
+ "fairys-mocker": "bin/fairys-mocker"
27
+ },
28
+ "dependencies": {
29
+ "@fairys/create-mock-data": "^0.0.1",
30
+ "body-parser": "2.2.2",
31
+ "chalk": "^5.6.2",
32
+ "connect": "^3.7.0",
33
+ "cors": "^2.8.5",
34
+ "detect-port": "^2.1.0",
35
+ "express": "^5.2.1",
36
+ "finalhandler": "^2.1.1",
37
+ "http-proxy-middleware": "^3.0.5",
38
+ "yargs-parser": "^22.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/cors": "^2.8.19",
42
+ "@types/express": "^5.0.6",
43
+ "@types/finalhandler": "^1.2.4",
44
+ "@types/yargs-parser": "^21.0.3"
45
+ },
46
+ "files": [
47
+ "bin",
48
+ "public",
49
+ "esm",
50
+ "src"
51
+ ]
52
+ }
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html><head><link rel="icon" href="/_fairys_mocker/favicon.png"><title>Fairys Mocker</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/_fairys_mocker/static/js/lib-react.2748fa4b.js"></script><script defer src="/_fairys_mocker/static/js/514.950758f1.js"></script><script defer src="/_fairys_mocker/static/js/index.f70ed1dc.js"></script><link href="/_fairys_mocker/static/css/index.2ba69ff5.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
@@ -0,0 +1 @@
1
+ @media (prefers-color-scheme:dark){.w-tc-editor{--color-fg-default:#c9d1d9;--color-canvas-subtle:#161b22;--color-prettylights-syntax-comment:#8b949e;--color-prettylights-syntax-entity-tag:#7ee787;--color-prettylights-syntax-entity:#d2a8ff;--color-prettylights-syntax-sublimelinter-gutter-mark:#484f58;--color-prettylights-syntax-constant:#79c0ff;--color-prettylights-syntax-string:#a5d6ff;--color-prettylights-syntax-keyword:#ff7b72;--color-prettylights-syntax-markup-bold:#c9d1d9}}@media (prefers-color-scheme:light){.w-tc-editor{--color-fg-default:#24292f;--color-canvas-subtle:#f6f8fa;--color-prettylights-syntax-comment:#6e7781;--color-prettylights-syntax-entity-tag:#116329;--color-prettylights-syntax-entity:#8250df;--color-prettylights-syntax-sublimelinter-gutter-mark:#8c959f;--color-prettylights-syntax-constant:#0550ae;--color-prettylights-syntax-string:#0a3069;--color-prettylights-syntax-keyword:#cf222e;--color-prettylights-syntax-markup-bold:#24292f}}.w-tc-editor[data-color-mode*=dark],[data-color-mode*=dark] .w-tc-editor,[data-color-mode*=dark] .w-tc-editor-var,body[data-color-mode*=dark]{--color-fg-default:#c9d1d9;--color-canvas-subtle:#161b22;--color-prettylights-syntax-comment:#8b949e;--color-prettylights-syntax-entity-tag:#7ee787;--color-prettylights-syntax-entity:#d2a8ff;--color-prettylights-syntax-sublimelinter-gutter-mark:#484f58;--color-prettylights-syntax-constant:#79c0ff;--color-prettylights-syntax-string:#a5d6ff;--color-prettylights-syntax-keyword:#ff7b72;--color-prettylights-syntax-markup-bold:#c9d1d9}.w-tc-editor[data-color-mode*=light],[data-color-mode*=light] .w-tc-editor,[data-color-mode*=light] .w-tc-editor-var,body[data-color-mode*=light]{--color-fg-default:#24292f;--color-canvas-subtle:#f6f8fa;--color-prettylights-syntax-comment:#6e7781;--color-prettylights-syntax-entity-tag:#116329;--color-prettylights-syntax-entity:#8250df;--color-prettylights-syntax-sublimelinter-gutter-mark:#8c959f;--color-prettylights-syntax-constant:#0550ae;--color-prettylights-syntax-string:#0a3069;--color-prettylights-syntax-keyword:#cf222e;--color-prettylights-syntax-markup-bold:#24292f}.w-tc-editor{background-color:var(--color-canvas-subtle);color:var(--color-fg-default);font-family:inherit;font-size:12px}.w-tc-editor-text,.w-tc-editor-preview{min-height:16px}.w-tc-editor-preview pre{white-space:inherit;font-family:inherit;font-size:inherit;margin:0;padding:0}.w-tc-editor-preview pre code{font-family:inherit}.w-tc-editor code[class*=language-] .token.cdata,.w-tc-editor pre[class*=language-] .token.cdata,.w-tc-editor code[class*=language-] .token.comment,.w-tc-editor pre[class*=language-] .token.comment,.w-tc-editor code[class*=language-] .token.doctype,.w-tc-editor pre[class*=language-] .token.doctype,.w-tc-editor code[class*=language-] .token.prolog,.w-tc-editor pre[class*=language-] .token.prolog{color:var(--color-prettylights-syntax-comment)}.w-tc-editor code[class*=language-] .token.punctuation,.w-tc-editor pre[class*=language-] .token.punctuation{color:var(--color-prettylights-syntax-sublimelinter-gutter-mark)}.w-tc-editor code[class*=language-] .namespace,.w-tc-editor pre[class*=language-] .namespace{opacity:.7}.w-tc-editor code[class*=language-] .token.boolean,.w-tc-editor pre[class*=language-] .token.boolean,.w-tc-editor code[class*=language-] .token.constant,.w-tc-editor pre[class*=language-] .token.constant,.w-tc-editor code[class*=language-] .token.deleted,.w-tc-editor pre[class*=language-] .token.deleted,.w-tc-editor code[class*=language-] .token.number,.w-tc-editor pre[class*=language-] .token.number,.w-tc-editor code[class*=language-] .token.symbol,.w-tc-editor pre[class*=language-] .token.symbol{color:var(--color-prettylights-syntax-entity-tag)}.w-tc-editor code[class*=language-] .token.builtin,.w-tc-editor pre[class*=language-] .token.builtin,.w-tc-editor code[class*=language-] .token.char,.w-tc-editor pre[class*=language-] .token.char,.w-tc-editor code[class*=language-] .token.inserted,.w-tc-editor pre[class*=language-] .token.inserted,.w-tc-editor code[class*=language-] .token.selector,.w-tc-editor pre[class*=language-] .token.selector,.w-tc-editor code[class*=language-] .token.string,.w-tc-editor pre[class*=language-] .token.string,.w-tc-editor code[class*=language-] .style .token.string,.w-tc-editor pre[class*=language-] .style .token.string,.w-tc-editor code[class*=language-] .token.entity,.w-tc-editor pre[class*=language-] .token.entity,.w-tc-editor code[class*=language-] .token.property,.w-tc-editor pre[class*=language-] .token.property,.w-tc-editor code[class*=language-] .token.operator,.w-tc-editor pre[class*=language-] .token.operator,.w-tc-editor code[class*=language-] .token.url,.w-tc-editor pre[class*=language-] .token.url{color:var(--color-prettylights-syntax-constant)}.w-tc-editor code[class*=language-] .token.atrule,.w-tc-editor pre[class*=language-] .token.atrule,.w-tc-editor code[class*=language-] .token.property-access .token.method,.w-tc-editor pre[class*=language-] .token.property-access .token.method,.w-tc-editor code[class*=language-] .token.keyword,.w-tc-editor pre[class*=language-] .token.keyword{color:var(--color-prettylights-syntax-keyword)}.w-tc-editor code[class*=language-] .token.function,.w-tc-editor pre[class*=language-] .token.function{color:var(--color-prettylights-syntax-string)}.w-tc-editor code[class*=language-] .token.important,.w-tc-editor pre[class*=language-] .token.important,.w-tc-editor code[class*=language-] .token.regex,.w-tc-editor pre[class*=language-] .token.regex,.w-tc-editor code[class*=language-] .token.variable,.w-tc-editor pre[class*=language-] .token.variable{color:var(--color-prettylights-syntax-string-regexp)}.w-tc-editor code[class*=language-] .token.bold,.w-tc-editor pre[class*=language-] .token.bold,.w-tc-editor code[class*=language-] .token.important,.w-tc-editor pre[class*=language-] .token.important{color:var(--color-prettylights-syntax-markup-bold)}.w-tc-editor code[class*=language-] .token.tag,.w-tc-editor pre[class*=language-] .token.tag{color:var(--color-prettylights-syntax-entity-tag)}.w-tc-editor code[class*=language-] .token.attr-value,.w-tc-editor pre[class*=language-] .token.attr-value,.w-tc-editor code[class*=language-] .token.attr-name,.w-tc-editor pre[class*=language-] .token.attr-name{color:var(--color-prettylights-syntax-constant)}.w-tc-editor code[class*=language-] .token.selector .class,.w-tc-editor pre[class*=language-] .token.selector .class,.w-tc-editor code[class*=language-] .token.class-name,.w-tc-editor pre[class*=language-] .token.class-name{color:var(--color-prettylights-syntax-entity)}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:#fb2c36;--color-red-600:#e40014;--color-orange-500:#fe6e00;--color-green-500:#00c758;--color-green-600:#00a544;--color-blue-400:#54a2ff;--color-blue-500:#3080ff;--color-blue-600:#155dfc;--color-gray-500:#6a7282;--color-gray-600:#4a5565;--color-zinc-50:#fafafa;--color-zinc-100:#f4f4f5;--color-zinc-200:#e4e4e7;--color-zinc-300:#d4d4d8;--color-zinc-400:#9f9fa9;--color-zinc-500:#71717b;--color-zinc-600:#52525c;--color-zinc-700:#3f3f46;--color-zinc-800:#27272a;--color-zinc-900:#18181b;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--radius-md:.375rem;--radius-lg:.5rem;--ease-in-out:cubic-bezier(.4,0,.2,1);--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}@supports (color:color(display-p3 0 0 0)){:root,:host{--color-red-500:color(display-p3 .903738 .262579 .253307);--color-red-600:color(display-p3 .830323 .140383 .133196);--color-orange-500:color(display-p3 .946589 .449788 .0757345);--color-green-500:color(display-p3 .308734 .774754 .374307);--color-green-600:color(display-p3 .243882 .640824 .294808);--color-blue-400:color(display-p3 .397443 .62813 .992116);--color-blue-500:color(display-p3 .266422 .491219 .988624);--color-blue-600:color(display-p3 .174493 .358974 .950247);--color-gray-500:color(display-p3 .421287 .446085 .504784);--color-gray-600:color(display-p3 .297358 .332176 .39043);--color-zinc-50:color(display-p3 .980256 .980256 .980256);--color-zinc-100:color(display-p3 .956385 .956385 .959079);--color-zinc-200:color(display-p3 .894477 .894477 .905114);--color-zinc-300:color(display-p3 .831087 .831083 .846819);--color-zinc-400:color(display-p3 .622604 .622563 .659842);--color-zinc-500:color(display-p3 .442983 .442931 .480324);--color-zinc-600:color(display-p3 .321166 .321093 .358668);--color-zinc-700:color(display-p3 .246478 .246448 .273934);--color-zinc-800:color(display-p3 .152895 .152887 .16466);--color-zinc-900:color(display-p3 .0937957 .093793 .104806)}}@supports (color:lab(0% 0 0)){:root,:host{--color-red-500:lab(55.4814% 75.0732 48.8528);--color-red-600:lab(48.4493% 77.4328 61.5452);--color-orange-500:lab(64.272% 57.1788 90.3583);--color-green-500:lab(70.5521% -66.5147 45.8073);--color-green-600:lab(59.0978% -58.6621 41.2579);--color-blue-400:lab(65.0361% -1.42065 -56.9802);--color-blue-500:lab(54.1736% 13.3369 -74.6839);--color-blue-600:lab(44.0605% 29.0279 -86.0352);--color-gray-500:lab(47.7841% -.393182 -10.0268);--color-gray-600:lab(35.6337% -1.58697 -10.8425);--color-zinc-50:lab(98.26% 0 0);--color-zinc-100:lab(96.1634% .0993311 -.364041);--color-zinc-200:lab(90.6853% .399232 -1.45452);--color-zinc-300:lab(84.9837% .601262 -2.17986);--color-zinc-400:lab(65.6464% 1.53497 -5.42429);--color-zinc-500:lab(47.8878% 1.65477 -5.77283);--color-zinc-600:lab(35.1166% 1.78212 -6.1173);--color-zinc-700:lab(26.8019% 1.35387 -4.68303);--color-zinc-800:lab(15.7305% .613764 -2.16959);--color-zinc-900:lab(8.30603% .618205 -2.16572)}}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::-webkit-file-upload-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::-webkit-file-upload-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:-webkit-any([multiple],[size])) optgroup{font-weight:bolder}:where(select:-moz-any([multiple],[size])) optgroup{font-weight:bolder}:where(select:-webkit-any([multiple],[size])) optgroup{font-weight:bolder}:where(select:-moz-any([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:-webkit-any([multiple],[size])) optgroup option{padding-inline-start:20px}:where(select:-moz-any([multiple],[size])) optgroup option{padding-inline-start:20px}:where(select:-webkit-any([multiple],[size])) optgroup option{padding-inline-start:20px}:where(select:-moz-any([multiple],[size])) optgroup option{padding-inline-start:20px}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::-webkit-file-upload-button{margin-inline-end:4px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-year-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-month-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-day-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-hour-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-minute-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-second-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-millisecond-field{padding-block-start:0;padding-block-end:0}::-webkit-datetime-edit-meridiem-field{padding-block-start:0;padding-block-end:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button{-webkit-appearance:button;-moz-appearance:button;appearance:button}input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-file-upload-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.-top-px{top:-1px}.z-10{z-index:10}.z-50{z-index:50}.z-90{z-index:90}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-3{margin-top:calc(var(--spacing)*3)}.mr-2{margin-right:calc(var(--spacing)*2)}.mr-4{margin-right:calc(var(--spacing)*4)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.box-border{box-sizing:border-box}.block{display:block}.flex{display:flex}.hidden{display:none}.h-full{height:100%}.max-h-\[80\%\]{max-height:80%}.min-h-\[300px\]{min-height:300px}.w-3{width:calc(var(--spacing)*3)}.w-\[250px\]{width:250px}.w-\[400px\]{width:400px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.min-w-full{min-width:100%}.flex-1{flex:1}.border-collapse{border-collapse:collapse}.translate-x-0{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-4{--tw-translate-x:calc(var(--spacing)*4);translate:var(--tw-translate-x)var(--tw-translate-y)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*1)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-blue-500{border-color:var(--color-blue-500)}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-300{border-color:var(--color-zinc-300)}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.bg-black\/30{background-color:color-mix(in oklab,var(--color-black)30%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-500{background-color:var(--color-gray-500)}.bg-green-500{background-color:var(--color-green-500)}.bg-red-500{background-color:var(--color-red-500)}.bg-white{background-color:var(--color-white)}.bg-white\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.bg-white\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.bg-zinc-50{background-color:var(--color-zinc-50)}.bg-zinc-100{background-color:var(--color-zinc-100)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.py-8{padding-block:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-green-500{color:var(--color-green-500)}.text-orange-500{color:var(--color-orange-500)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-700{color:var(--color-zinc-700)}.text-zinc-800{color:var(--color-zinc-800)}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur, )var(--tw-backdrop-brightness, )var(--tw-backdrop-contrast, )var(--tw-backdrop-grayscale, )var(--tw-backdrop-hue-rotate, )var(--tw-backdrop-invert, )var(--tw-backdrop-opacity, )var(--tw-backdrop-saturate, )var(--tw-backdrop-sepia, );backdrop-filter:var(--tw-backdrop-blur, )var(--tw-backdrop-brightness, )var(--tw-backdrop-contrast, )var(--tw-backdrop-grayscale, )var(--tw-backdrop-hue-rotate, )var(--tw-backdrop-invert, )var(--tw-backdrop-opacity, )var(--tw-backdrop-saturate, )var(--tw-backdrop-sepia, )}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}@media (hover:hover){.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}.hover\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:text-zinc-700:hover{color:var(--color-zinc-700)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset, )0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}@media (min-width:40rem){.sm\:p-6{padding:calc(var(--spacing)*6)}}@media (prefers-color-scheme:dark){.dark\:border-zinc-600{border-color:var(--color-zinc-600)}.dark\:border-zinc-700{border-color:var(--color-zinc-700)}.dark\:bg-black{background-color:var(--color-black)}.dark\:bg-zinc-700{background-color:var(--color-zinc-700)}.dark\:bg-zinc-800{background-color:var(--color-zinc-800)}.dark\:bg-zinc-900{background-color:var(--color-zinc-900)}.dark\:bg-zinc-900\/90{background-color:#18181be6}@supports (color:color-mix(in lab, red, red)){.dark\:bg-zinc-900\/90{background-color:color-mix(in oklab,var(--color-zinc-900)90%,transparent)}}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-white{color:var(--color-white)}.dark\:text-zinc-100{color:var(--color-zinc-100)}.dark\:text-zinc-200{color:var(--color-zinc-200)}.dark\:text-zinc-300{color:var(--color-zinc-300)}.dark\:text-zinc-400{color:var(--color-zinc-400)}@media (hover:hover){.dark\:hover\:bg-zinc-600:hover{background-color:var(--color-zinc-600)}.dark\:hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.dark\:hover\:text-zinc-200:hover{color:var(--color-zinc-200)}}}}html,body,#root{height:100%;overflow:hidden}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}