flashts 1.0.0 → 1.0.2
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/CHANGELOG.md +25 -0
- package/CONTRIBUTING.md +60 -0
- package/README.md +36 -66
- package/bin/cli.ts +2 -2
- package/client/dist/assets/index-BAlIRq-u.css +1 -0
- package/client/dist/assets/index-DM0EVhuB.js +21 -0
- package/client/{index.html → dist/index.html} +2 -1
- package/package.json +76 -66
- package/server/index.ts +11 -9
- package/client/README.md +0 -73
- package/client/bun.lock +0 -613
- package/client/eslint.config.js +0 -23
- package/client/package-lock.json +0 -3174
- package/client/package.json +0 -43
- package/client/postcss.config.js +0 -6
- package/client/src/App.css +0 -42
- package/client/src/App.tsx +0 -247
- package/client/src/assets/react.svg +0 -1
- package/client/src/components/CodeEditor.tsx +0 -206
- package/client/src/components/Console.tsx +0 -52
- package/client/src/components/FileTabs.tsx +0 -195
- package/client/src/components/LightningLogo.tsx +0 -33
- package/client/src/components/PackageInstaller.tsx +0 -300
- package/client/src/components/WelcomeScreen.tsx +0 -171
- package/client/src/index.css +0 -142
- package/client/src/main.tsx +0 -10
- package/client/tailwind.config.js +0 -32
- package/client/tsconfig.app.json +0 -28
- package/client/tsconfig.json +0 -7
- package/client/tsconfig.node.json +0 -26
- package/client/vite.config.ts +0 -7
- package/tmp/e656e349-2c39-4bc3-b334-6b5eb957e306/main.ts +0 -2
- /package/client/{public → dist}/favicon.svg +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to FlashTS will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 1.0.2
|
|
6
|
+
|
|
7
|
+
Initial release of the FlashTS CLI and Unified Playground.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **NPM Package**: FlashTS is now available as a globally installable CLI.
|
|
12
|
+
- **Unified Server**: The backend now serves the frontend, simplifying deployment and local usage.
|
|
13
|
+
- **Smart CLI**: New `flashts` command with support for `--port`, `--share`, and `--no-open`.
|
|
14
|
+
- **Public Sharing**: Integration with `localtunnel` to generate shareable links.
|
|
15
|
+
- **Tunnel Password Detection**: The CLI now automatically displays the public IP required for the tunnel landing page.
|
|
16
|
+
- **Multi-file Support**: Full support for projects with multiple files and relative imports.
|
|
17
|
+
- **IntelliSense**: Automatic type injection for NPM packages.
|
|
18
|
+
- **NPM Manager**: Built-in UI to search, install, and manage dependencies.
|
|
19
|
+
- **Welcome Screen**: New user onboarding experience.
|
|
20
|
+
|
|
21
|
+
### Technical Improvements
|
|
22
|
+
|
|
23
|
+
- Moved to a consolidated root `package.json` for better dependency management.
|
|
24
|
+
- Implemented Double-Sync VFS strategy in Monaco for seamless multi-file resolution.
|
|
25
|
+
- Added session-based execution isolation for better security.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Contributing to FlashTS
|
|
2
|
+
|
|
3
|
+
First off, thanks for taking the time to contribute! FlashTS is a complex tool involving a virtual filesystem, a custom execution engine, and a unified CLI.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
### Monorepo Structure
|
|
8
|
+
|
|
9
|
+
- `/client`: React 19 + Vite frontend.
|
|
10
|
+
- `/server`: Hono + Bun backend that handles execution and type serving.
|
|
11
|
+
- `/bin`: CLI entry point (`cli.ts`).
|
|
12
|
+
|
|
13
|
+
### How Execution Works
|
|
14
|
+
|
|
15
|
+
When you click **Run**, the frontend bundles all project files into a JSON payload and sends it to the server. The server then:
|
|
16
|
+
|
|
17
|
+
1. Creates an isolated session directory in `/tmp`.
|
|
18
|
+
2. Writes the files to disk.
|
|
19
|
+
3. Spawns a `bun run` process to execute the entry point.
|
|
20
|
+
4. Streams logs back to the console via Hono.
|
|
21
|
+
|
|
22
|
+
### Type Injection
|
|
23
|
+
|
|
24
|
+
FlashTS parses the dependency tree of installed NPM packages on the server and serves `.d.ts` files to the client, which are injected into Monaco's virtual filesystem (VFS).
|
|
25
|
+
|
|
26
|
+
## Local Development
|
|
27
|
+
|
|
28
|
+
1. **Clone the repo**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/your-repo/flashts.git
|
|
32
|
+
cd flashts
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. **Install all dependencies** (from the root)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bun install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
3. **Development Servers**
|
|
42
|
+
To work on the frontend and backend simultaneously:
|
|
43
|
+
- **Frontend**: `cd client && bun run dev`
|
|
44
|
+
- **Backend**: `cd server && bun run index.ts`
|
|
45
|
+
|
|
46
|
+
4. **Testing the CLI**
|
|
47
|
+
You can run the CLI locally using:
|
|
48
|
+
```bash
|
|
49
|
+
bun bin/cli.ts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Pull Request Process
|
|
53
|
+
|
|
54
|
+
1. Fork the repository.
|
|
55
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`).
|
|
56
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`).
|
|
57
|
+
4. Push to the branch (`git push origin feature/amazing-feature`).
|
|
58
|
+
5. Open a Pull Request.
|
|
59
|
+
|
|
60
|
+
---
|
package/README.md
CHANGED
|
@@ -1,87 +1,57 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/ZtaMDev/FlashTS/refs/heads/main/client/public/favicon.svg" alt="FlashTS" width="80" />
|
|
3
3
|
<h1>FlashTS</h1>
|
|
4
|
+
<p><b>High-performance TypeScript/JavaScript Playground powered by Bun</b></p>
|
|
4
5
|
</div>
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
## Features
|
|
9
|
-
|
|
10
|
-
- **Instant Execution**: Powered by Bun's high-performance runtime.
|
|
11
|
-
- **Multi-file Workspace**: Create complex projects with imports and modules.
|
|
12
|
-
- **Smart IntelliSense**: Automatic type injection for NPM packages via Monaco Editor.
|
|
13
|
-
- **Live NPM Manager**: Install and manage dependencies in real-time.
|
|
14
|
-
- **Safe Environment**: Session-based execution for isolated code running.
|
|
15
|
-
|
|
16
|
-
## Tech Stack
|
|
17
|
-
|
|
18
|
-
### Frontend (`/client`)
|
|
19
|
-
|
|
20
|
-
- **React 19 + Vite**: Modern, high-performance UI framework.
|
|
21
|
-
- **Monaco Editor**: The powerful editor behind VS Code, customized for FlashTS.
|
|
22
|
-
- **Tailwind CSS**: For a sleek, responsive, and maintainable design.
|
|
23
|
-
- **Lucide Icons**: Beautiful, consistent iconography.
|
|
24
|
-
- **React Resizable Panels**: Professional workspace layouts.
|
|
25
|
-
|
|
26
|
-
### Backend (`/server`)
|
|
27
|
-
|
|
28
|
-
- **Bun**: The fast all-in-one JavaScript runtime (Bundler, Runner, Package Manager).
|
|
29
|
-
- **Hono**: Ultrafast web framework for the API layer.
|
|
30
|
-
- **TypeScript VFS**: In-memory type resolution for project files.
|
|
31
|
-
|
|
32
|
-
## Getting Started
|
|
33
|
-
|
|
34
|
-
### Prerequisites
|
|
35
|
-
|
|
36
|
-
- [Bun](https://bun.sh/) installed on your system.
|
|
37
|
-
|
|
38
|
-
### Installation
|
|
39
|
-
|
|
40
|
-
1. **Setup Server**:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
cd server
|
|
44
|
-
bun install
|
|
45
|
-
bun run index.ts
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
2. **Setup Client**:
|
|
7
|
+
---
|
|
49
8
|
|
|
50
|
-
|
|
51
|
-
cd client
|
|
52
|
-
bun install
|
|
53
|
-
bun run dev
|
|
54
|
-
```
|
|
9
|
+
FlashTS is an ultra-fast, modern playground that brings a professional IDE-like experience to your browser. Create, run, and share TypeScript projects with full NPM module support instantly.
|
|
55
10
|
|
|
56
|
-
|
|
57
|
-
Navigate to `http://localhost:5173` in your browser.
|
|
11
|
+
## Quick Start (via NPM)
|
|
58
12
|
|
|
59
|
-
|
|
13
|
+
The fastest way to experience FlashTS is via our CLI.
|
|
60
14
|
|
|
61
|
-
|
|
15
|
+
```bash
|
|
16
|
+
# Run without installing
|
|
17
|
+
bunx flashts
|
|
62
18
|
|
|
63
|
-
|
|
19
|
+
# Or install globally
|
|
20
|
+
bun install -g flashts
|
|
21
|
+
flashts
|
|
22
|
+
```
|
|
64
23
|
|
|
65
|
-
|
|
66
|
-
2. Writes all your files to disk.
|
|
67
|
-
3. Spawns a Bun process to execute the active entry point.
|
|
68
|
-
4. Streams the output (stdout/stderr) back to the client console.
|
|
24
|
+
### Options
|
|
69
25
|
|
|
70
|
-
|
|
26
|
+
| Flag | Description |
|
|
27
|
+
| --------------------- | ----------------------------------------------------- |
|
|
28
|
+
| `-p, --port <number>` | Set a custom port (default: 3000) |
|
|
29
|
+
| `-s, --share` | Generate a shareable public link with tunnel password |
|
|
30
|
+
| `--no-open` | Prevent the browser from opening automatically |
|
|
71
31
|
|
|
72
|
-
|
|
32
|
+
## Key Features
|
|
73
33
|
|
|
74
|
-
|
|
34
|
+
- **Blazing Fast**: Powered by **Bun**, the all-in-one JavaScript runtime.
|
|
35
|
+
- **Multi-file Workspace**: Work on complex projects with relative imports (`import { x } from "./utils"`).
|
|
36
|
+
- **Smart IntelliSense**: Real-time type definitions for your NPM dependencies.
|
|
37
|
+
- **NPM Management**: Search and install packages directly from the UI.
|
|
38
|
+
- **Instant Sharing**: Generate public links to share your playground with others.
|
|
39
|
+
- **Premium UI**: Dark mode, responsive design, and smooth animations.
|
|
75
40
|
|
|
76
|
-
|
|
41
|
+
## Usage Tips
|
|
77
42
|
|
|
78
|
-
-
|
|
79
|
-
-
|
|
43
|
+
- **Run Shortcut**: `Ctrl + Shift + F` to execute the current file.
|
|
44
|
+
- **Package Manager**: `Ctrl + Shift + L` to quickly find and install new packages.
|
|
45
|
+
- **Sharing**: Use `flashts --share` to get a public URL and your tunnel password (IP).
|
|
80
46
|
|
|
81
47
|
## License
|
|
82
48
|
|
|
83
|
-
|
|
49
|
+
FlashTS is open-source software licensed under the [MIT License](LICENSE).
|
|
84
50
|
|
|
85
51
|
---
|
|
86
52
|
|
|
87
|
-
|
|
53
|
+
### Contributing & Development
|
|
54
|
+
|
|
55
|
+
Interested in how FlashTS works or want to contribute? Check out our [CONTRIBUTING.md](./CONTRIBUTING.md) for architecture details and local setup instructions.
|
|
56
|
+
|
|
57
|
+
Built by **ZMDev** because all online options are payed, not open source or doesn't support npm modules correctly.
|
package/bin/cli.ts
CHANGED
|
@@ -16,13 +16,13 @@ program
|
|
|
16
16
|
.option("--no-open", "Do not open the browser automatically")
|
|
17
17
|
.action(async (options: { port: string; share: any; open: any; }) => {
|
|
18
18
|
const port = parseInt(options.port);
|
|
19
|
-
const
|
|
19
|
+
const packageRoot = join(import.meta.dir, "..");
|
|
20
20
|
|
|
21
21
|
console.log(`\n⚡ ${pc.bold(pc.cyan("FlashTS"))} ${pc.dim("v1.0.0")}`);
|
|
22
22
|
console.log(`${pc.green("➜")} Local: ${pc.cyan(`http://localhost:${port}`)}`);
|
|
23
23
|
|
|
24
24
|
// Start the server process
|
|
25
|
-
const serverPath = join(
|
|
25
|
+
const serverPath = join(packageRoot, "server", "index.ts");
|
|
26
26
|
const serverProc = Bun.spawn(["bun", "run", serverPath], {
|
|
27
27
|
env: { ...process.env, PORT: port.toString() },
|
|
28
28
|
stdout: "inherit",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--font-sans);font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--font-mono);font-feature-settings:normal;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}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.left-1{left:.25rem}.top-0{top:0}.top-1{top:.25rem}.z-10{z-index:10}.z-50{z-index:50}.z-\[10000\]{z-index:10000}.z-\[20000\]{z-index:20000}.z-\[9999\]{z-index:9999}.mx-1{margin-left:.25rem;margin-right:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-auto{margin-top:auto;margin-bottom:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-2{margin-top:.5rem}.mt-auto{margin-top:auto}.flex{display:flex}.grid{display:grid}.hidden{display:none}.\!h-auto{height:auto!important}.h-1{height:.25rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-\[500px\]{max-height:500px}.max-h-\[90vh\]{max-height:90vh}.min-h-0{min-height:0}.w-10{width:2.5rem}.w-2{width:.5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-\[600px\]{width:600px}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.min-w-0{min-width:0}.max-w-2xl{max-width:42rem}.max-w-\[120px\]{max-width:120px}.max-w-sm{max-width:24rem}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.translate-x-0{--tw-translate-x:0px;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-5{--tw-translate-x:1.25rem;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:1s linear infinite spin}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-x{border-left-width:1px;border-right-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-accent-primary{border-color:var(--accent-primary)}.border-border-color{border-color:var(--border-color)}.border-transparent{border-color:#0000}.border-white\/10{border-color:#ffffff1a}.border-white\/5{border-color:#ffffff0d}.border-white\/50{border-color:#ffffff80}.border-t-transparent{border-top-color:#0000}.border-t-white{--tw-border-opacity:1;border-top-color:rgb(255 255 255/var(--tw-border-opacity,1))}.bg-\[\#09090b\]{--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.bg-\[\#0c0c0e\]{--tw-bg-opacity:1;background-color:rgb(12 12 14/var(--tw-bg-opacity,1))}.bg-\[\#1e1e20\]{--tw-bg-opacity:1;background-color:rgb(30 30 32/var(--tw-bg-opacity,1))}.bg-accent-primary{background-color:var(--accent-primary)}.bg-bg-primary{background-color:var(--bg-primary)}.bg-bg-secondary{background-color:var(--bg-secondary)}.bg-bg-tertiary{background-color:var(--bg-tertiary)}.bg-black\/20{background-color:#0003}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-black\/80{background-color:#000c}.bg-blue-500\/10{background-color:#3b82f61a}.bg-border-color{background-color:var(--border-color)}.bg-green-500\/10{background-color:#22c55e1a}.bg-orange-500\/10{background-color:#f973161a}.bg-purple-500\/10{background-color:#a855f71a}.bg-red-500\/10{background-color:#ef44441a}.bg-transparent{background-color:#0000}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/10{background-color:#ffffff1a}.bg-white\/20{background-color:#fff3}.bg-white\/5{background-color:#ffffff0d}.bg-gradient-to-r{background-image:linear-gradient(to right, var(--tw-gradient-stops))}.from-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.from-yellow-100{--tw-gradient-from:#fef9c3 var(--tw-gradient-from-position);--tw-gradient-to:#fef9c300 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.via-accent-primary{--tw-gradient-to:#fff0 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--accent-primary) var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-orange-100{--tw-gradient-to:#ffedd5 var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.\!p-0{padding:0!important}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pt-24{padding-top:6rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.font-mono{font-family:var(--font-mono)}.text-\[10px\]{font-size:10px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-medium{font-weight:500}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-accent-primary{color:var(--accent-primary)}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-text-primary{color:var(--text-primary)}.text-text-secondary{color:var(--text-secondary)}.text-transparent{color:#0000}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:#fffc}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.outline-none{outline-offset:2px;outline:2px solid #0000}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px);-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)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-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-\[background-color\,color\]{transition-property:background-color,color;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-property:all;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-property:transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--bg-primary:#09090b;--bg-secondary:#18181b;--bg-tertiary:#27272a;--accent-primary:#f59e0b;--accent-glow:#f59e0b80;--text-primary:#f4f4f5;--text-secondary:#a1a1aa;--border-color:#27272a;--font-mono:"JetBrains Mono", "Fira Code", source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;--font-sans:"Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif}*{box-sizing:border-box;margin:0;padding:0}body{background-color:var(--bg-primary);color:var(--text-primary);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--bg-tertiary);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#3f3f46}.glass{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);background:#18181b99;border:1px solid #ffffff0d}.flex-center{justify-content:center;align-items:center;display:flex}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@keyframes glow{0%{box-shadow:0 0 5px var(--accent-glow)}50%{box-shadow:0 0 20px var(--accent-glow)}to{box-shadow:0 0 5px var(--accent-glow)}}@keyframes modal-entrance{0%{opacity:0;filter:blur(10px);transform:scale(.9)translateY(20px)}60%{filter:blur();transform:scale(1.02)translateY(-5px)}to{opacity:1;transform:scale(1)translateY(0)}}.animate-modal{animation:.5s cubic-bezier(.34,1.56,.64,1) forwards modal-entrance}.btn-primary{color:#fff;cursor:pointer;background:linear-gradient(135deg,#f59e0b,#ea580c);border:none;border-radius:8px;align-items:center;gap:.5rem;padding:.5rem 1.5rem;font-weight:600;transition:all .2s;display:flex}.btn-primary:hover{box-shadow:0 4px 12px var(--accent-glow);transform:translateY(-1px)}.btn-primary:active{transform:translateY(0)}.panel-header{border-bottom:1px solid var(--border-color);background:var(--bg-secondary);height:48px;color:var(--text-secondary);-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;padding:0 1rem;font-size:.875rem;font-weight:500;display:flex}.placeholder\:text-white\/20::placeholder{color:#fff3}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:bg-accent-primary:hover{background-color:var(--accent-primary)}.hover\:bg-black\/30:hover{background-color:#0000004d}.hover\:bg-red-500\/20:hover{background-color:#ef444433}.hover\:bg-white\/10:hover{background-color:#ffffff1a}.hover\:bg-white\/20:hover{background-color:#fff3}.hover\:bg-white\/30:hover{background-color:#ffffff4d}.hover\:bg-white\/5:hover{background-color:#ffffff0d}.hover\:bg-white\/\[0\.08\]:hover{background-color:#ffffff14}.hover\:text-accent-primary:hover{color:var(--accent-primary)}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-text-primary:hover{color:var(--text-primary)}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.focus\:border-accent-primary:focus{border-color:var(--accent-primary)}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:bg-transparent:hover:disabled{background-color:#0000}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:text-text-primary{color:var(--text-primary)}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:w-32{width:8rem}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}}@media (min-width:768px){.md\:mb-8{margin-bottom:2rem}.md\:block{display:block}.md\:flex{display:flex}.md\:h-14{height:3.5rem}.md\:h-4{height:1rem}.md\:h-6{height:1.5rem}.md\:h-8{height:2rem}.md\:h-auto{height:auto}.md\:max-h-none{max-height:none}.md\:w-1{width:.25rem}.md\:w-12{width:3rem}.md\:w-14{width:3.5rem}.md\:w-4{width:1rem}.md\:w-6{width:1.5rem}.md\:w-8{width:2rem}.md\:translate-x-6{--tw-translate-x:1.5rem;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:gap-4{gap:1rem}.md\:gap-6{gap:1.5rem}.md\:rounded-2xl{border-radius:1rem}.md\:p-4{padding:1rem}.md\:p-6{padding:1.5rem}.md\:p-8{padding:2rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:py-3{padding-top:.75rem;padding-bottom:.75rem}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-\[10px\]{font-size:10px}.md\:text-base{font-size:1rem;line-height:1.5rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-xs{font-size:.75rem;line-height:1rem}}
|