claude-dojo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -0
- package/bin/claude-dojo.js +85 -0
- package/client/dist/assets/index-C08_Q4bL.css +1 -0
- package/client/dist/assets/index-C3m65njK.js +4365 -0
- package/client/dist/index.html +15 -0
- package/client/dist/vite.svg +11 -0
- package/package.json +56 -0
- package/server/dist/claudeService.d.ts +20 -0
- package/server/dist/claudeService.js +341 -0
- package/server/dist/index.d.ts +1 -0
- package/server/dist/index.js +81 -0
- package/server/dist/routes/api.d.ts +2 -0
- package/server/dist/routes/api.js +267 -0
- package/server/dist/sessionManager.d.ts +32 -0
- package/server/dist/sessionManager.js +190 -0
- package/server/dist/types/index.d.ts +51 -0
- package/server/dist/types/index.js +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Agent Office - Apple-Inspired Claude Code Visualization
|
|
2
|
+
|
|
3
|
+
A beautifully designed visualization plugin for Claude Code that displays agents working in real-time with Apple's signature design aesthetic.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Design Philosophy
|
|
8
|
+
- **Flat Minimalist Design**: Clean, uncluttered interface inspired by Apple's design language
|
|
9
|
+
- **Smooth Animations**: Carefully crafted transitions using Apple's signature easing curves
|
|
10
|
+
- **Typography**: System fonts optimized for clarity and elegance
|
|
11
|
+
- **Color System**: Thoughtfully selected colors that work in both light and dark modes
|
|
12
|
+
- **Responsive**: Adapts seamlessly to different screen sizes
|
|
13
|
+
|
|
14
|
+
### Visualization Elements
|
|
15
|
+
|
|
16
|
+
#### Agent Cards
|
|
17
|
+
Each agent is represented by a card showing:
|
|
18
|
+
- **Avatar**: Emoji-based representation with animated glow effect when active
|
|
19
|
+
- **Role Badge**: Clear identification of agent type
|
|
20
|
+
- **Status Indicator**: Real-time status (Active, Idle, Thinking) with pulsing dot
|
|
21
|
+
- **Current Task**: What the agent is currently working on
|
|
22
|
+
- **Progress Bar**: Animated progress indicator with shimmer effect
|
|
23
|
+
- **Activity Timeline**: Recent actions with timestamps
|
|
24
|
+
|
|
25
|
+
#### Team Inbox
|
|
26
|
+
- **Message Center**: Consolidated view of important notifications
|
|
27
|
+
- **Badge Counter**: Unread message count
|
|
28
|
+
- **Interactive Items**: Hover effects and smooth transitions
|
|
29
|
+
|
|
30
|
+
## Design Details
|
|
31
|
+
|
|
32
|
+
### Color Palette
|
|
33
|
+
The plugin uses Apple's color system with role-specific colors:
|
|
34
|
+
- **Researcher**: Blue (#007AFF) - Analysis and discovery
|
|
35
|
+
- **Coder**: Purple (#5856D6) - Implementation work
|
|
36
|
+
- **Reviewer**: Green (#34C759) - Quality assurance
|
|
37
|
+
- **Explorer**: Pink (#FF2D55) - Navigation and exploration
|
|
38
|
+
- **Planner**: Teal (#00C7BE) - Strategic planning
|
|
39
|
+
- **Artist**: Orange (#FF9500) - Creative work
|
|
40
|
+
|
|
41
|
+
### Animations
|
|
42
|
+
All animations use Apple's signature timing functions:
|
|
43
|
+
- **Swift**: `cubic-bezier(0.4, 0.0, 0.2, 1)` - For quick interactions
|
|
44
|
+
- **Smooth**: `cubic-bezier(0.25, 0.1, 0.25, 1)` - For graceful transitions
|
|
45
|
+
|
|
46
|
+
### Typography
|
|
47
|
+
Uses the SF Pro system font stack with:
|
|
48
|
+
- Font smoothing for crisp text rendering
|
|
49
|
+
- Negative letter spacing for display sizes
|
|
50
|
+
- Hierarchical font sizes from 11px to 48px
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
### Opening the Visualization
|
|
55
|
+
|
|
56
|
+
Simply open `agent-office-plugin.html` in any modern web browser:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
open agent-office-plugin.html
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or drag the file into your browser window.
|
|
63
|
+
|
|
64
|
+
### Customization
|
|
65
|
+
|
|
66
|
+
#### Adding New Agents
|
|
67
|
+
|
|
68
|
+
Edit the `agents` array in the JavaScript section:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
{
|
|
72
|
+
id: 'your-agent',
|
|
73
|
+
name: 'Agent Name',
|
|
74
|
+
role: 'Agent Role',
|
|
75
|
+
emoji: '🎯',
|
|
76
|
+
status: 'active', // 'active', 'idle', or 'thinking'
|
|
77
|
+
currentTask: 'Description of current task',
|
|
78
|
+
progress: 45,
|
|
79
|
+
activities: [
|
|
80
|
+
{ time: '1m ago', text: 'Recent activity' },
|
|
81
|
+
{ time: '3m ago', text: 'Previous activity' }
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Custom Color Themes
|
|
87
|
+
|
|
88
|
+
Add a new color theme in the CSS:
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
.agent-card[data-agent="your-agent"] {
|
|
92
|
+
--agent-color: #YOUR_COLOR;
|
|
93
|
+
--agent-color-light: #LIGHTER_COLOR;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Integration Ideas
|
|
98
|
+
|
|
99
|
+
### Real-time Updates
|
|
100
|
+
To connect with Claude Code's actual agent system:
|
|
101
|
+
|
|
102
|
+
1. **WebSocket Connection**: Stream agent status updates
|
|
103
|
+
2. **Server-Sent Events**: Push updates from Claude Code
|
|
104
|
+
3. **Polling**: Periodically fetch agent status from an API endpoint
|
|
105
|
+
|
|
106
|
+
### Example Integration Structure
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
// Connect to Claude Code agent system
|
|
110
|
+
const ws = new WebSocket('ws://localhost:8080/agent-status');
|
|
111
|
+
|
|
112
|
+
ws.onmessage = (event) => {
|
|
113
|
+
const agentUpdate = JSON.parse(event.data);
|
|
114
|
+
updateAgentStatus(agentUpdate);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
function updateAgentStatus(update) {
|
|
118
|
+
const agent = agents.find(a => a.id === update.agentId);
|
|
119
|
+
if (agent) {
|
|
120
|
+
agent.status = update.status;
|
|
121
|
+
agent.currentTask = update.task;
|
|
122
|
+
agent.progress = update.progress;
|
|
123
|
+
renderAgents();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Browser Compatibility
|
|
129
|
+
|
|
130
|
+
- Chrome/Edge 90+
|
|
131
|
+
- Safari 14+
|
|
132
|
+
- Firefox 88+
|
|
133
|
+
|
|
134
|
+
Optimized for modern browsers with CSS Grid, custom properties, and smooth animations.
|
|
135
|
+
|
|
136
|
+
## Performance
|
|
137
|
+
|
|
138
|
+
- Lightweight: Pure HTML/CSS/JS, no frameworks
|
|
139
|
+
- Optimized animations using CSS transforms
|
|
140
|
+
- Efficient DOM updates
|
|
141
|
+
- Smooth 60fps animations
|
|
142
|
+
|
|
143
|
+
## Dark Mode
|
|
144
|
+
|
|
145
|
+
Automatically adapts to system preferences using `prefers-color-scheme` media query.
|
|
146
|
+
|
|
147
|
+
## Future Enhancements
|
|
148
|
+
|
|
149
|
+
- [ ] Agent collaboration visualization (connections between agents)
|
|
150
|
+
- [ ] Performance metrics dashboard
|
|
151
|
+
- [ ] Interactive agent controls (pause, resume, prioritize)
|
|
152
|
+
- [ ] Export activity logs
|
|
153
|
+
- [ ] Customizable themes
|
|
154
|
+
- [ ] Sound notifications
|
|
155
|
+
- [ ] Real-time code diff viewer
|
|
156
|
+
- [ ] Agent chat/messaging interface
|
|
157
|
+
|
|
158
|
+
## Credits
|
|
159
|
+
|
|
160
|
+
Designed with inspiration from Apple's Human Interface Guidelines and macOS Big Sur design language.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const rootDir = join(__dirname, '..');
|
|
11
|
+
|
|
12
|
+
console.log(`
|
|
13
|
+
╔═══════════════════════════════════════╗
|
|
14
|
+
║ Claude Dojo ║
|
|
15
|
+
║ Agent Dashboard ║
|
|
16
|
+
╚═══════════════════════════════════════╝
|
|
17
|
+
`);
|
|
18
|
+
|
|
19
|
+
// Check if we're in development or production mode
|
|
20
|
+
const isDev = process.argv.includes('--dev');
|
|
21
|
+
|
|
22
|
+
async function openBrowser(url) {
|
|
23
|
+
try {
|
|
24
|
+
const open = (await import('open')).default;
|
|
25
|
+
await open(url);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.log(`Open ${url} in your browser`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function startProduction() {
|
|
32
|
+
const serverPath = join(rootDir, 'server', 'dist', 'index.js');
|
|
33
|
+
|
|
34
|
+
if (!existsSync(serverPath)) {
|
|
35
|
+
console.error('Error: Server not built. Run "npm run build" first.');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('Starting Claude Dojo...\n');
|
|
40
|
+
|
|
41
|
+
// Set environment variable to suppress duplicate logs
|
|
42
|
+
process.env.CLAUDE_DOJO_CLI = '1';
|
|
43
|
+
|
|
44
|
+
// Import and run the server (it starts automatically)
|
|
45
|
+
await import(serverPath);
|
|
46
|
+
|
|
47
|
+
// Give server a moment to start, then open browser
|
|
48
|
+
setTimeout(async () => {
|
|
49
|
+
const port = process.env.PORT || 3001;
|
|
50
|
+
if (process.env.NO_BROWSER !== '1') {
|
|
51
|
+
await openBrowser(`http://localhost:${port}`);
|
|
52
|
+
}
|
|
53
|
+
console.log('\nPress Ctrl+C to stop\n');
|
|
54
|
+
}, 1000);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function startDevelopment() {
|
|
58
|
+
console.log('Starting in development mode...\n');
|
|
59
|
+
|
|
60
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
61
|
+
const child = spawn(npm, ['run', 'dev'], {
|
|
62
|
+
cwd: rootDir,
|
|
63
|
+
stdio: 'inherit',
|
|
64
|
+
shell: true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
child.on('error', (error) => {
|
|
68
|
+
console.error('Failed to start development server:', error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
child.on('close', (code) => {
|
|
73
|
+
process.exit(code || 0);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
process.on('SIGINT', () => child.kill('SIGINT'));
|
|
77
|
+
process.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Main
|
|
81
|
+
if (isDev) {
|
|
82
|
+
startDevelopment();
|
|
83
|
+
} else {
|
|
84
|
+
startProduction();
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--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: rgb(59 130 246 / .5);--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: }::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: rgb(59 130 246 / .5);--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-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings: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:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-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{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,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{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.-right-1{right:-4px}.-right-1\.5{right:-6px}.-top-1{top:-4px}.-top-1\.5{top:-6px}.bottom-4{bottom:16px}.left-4{left:16px}.right-0{right:0}.top-4{top:16px}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.my-2{margin-top:8px;margin-bottom:8px}.my-4{margin-top:16px;margin-bottom:16px}.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}.mb-4{margin-bottom:16px}.mt-1{margin-top:4px}.mt-2{margin-top:8px}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-1{height:4px}.h-1\.5{height:6px}.h-10{height:40px}.h-16{height:4rem}.h-2{height:8px}.h-2\.5{height:10px}.h-3{height:12px}.h-3\.5{height:.875rem}.h-4{height:16px}.h-5{height:20px}.h-8{height:32px}.h-full{height:100%}.h-screen{height:100vh}.max-h-40{max-height:10rem}.max-h-\[200px\]{max-height:200px}.min-h-\[24px\]{min-height:24px}.w-1{width:4px}.w-1\.5{width:6px}.w-10{width:40px}.w-16{width:4rem}.w-2{width:8px}.w-2\.5{width:10px}.w-3{width:12px}.w-3\.5{width:.875rem}.w-4{width:16px}.w-40{width:10rem}.w-5{width:20px}.w-8{width:32px}.w-\[420px\]{width:420px}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.min-w-0{min-width:0px}.max-w-\[100px\]{max-width:100px}.max-w-\[120px\]{max-width:120px}.max-w-\[85\%\]{max-width:85%}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.resize-none{resize:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:4px}.gap-1\.5{gap:6px}.gap-2{gap:8px}.gap-3{gap:12px}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(8px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(8px * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(16px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(16px * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:8px}.rounded-2xl{border-radius:20px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:12px}.rounded-md{border-radius:10px}.rounded-xl{border-radius:16px}.rounded-bl-md{border-bottom-left-radius:10px}.rounded-br-md{border-bottom-right-radius:10px}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-4{border-left-width:4px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-apple-accent{--tw-border-opacity: 1;border-color:rgb(10 132 255 / var(--tw-border-opacity, 1))}.border-apple-separator{--tw-border-opacity: 1;border-color:rgb(56 56 58 / var(--tw-border-opacity, 1))}.border-apple-yellow{--tw-border-opacity: 1;border-color:rgb(255 214 10 / var(--tw-border-opacity, 1))}.border-l-apple-green{--tw-border-opacity: 1;border-left-color:rgb(48 209 88 / var(--tw-border-opacity, 1))}.border-l-apple-red{--tw-border-opacity: 1;border-left-color:rgb(255 69 58 / var(--tw-border-opacity, 1))}.border-l-apple-yellow{--tw-border-opacity: 1;border-left-color:rgb(255 214 10 / var(--tw-border-opacity, 1))}.border-l-transparent{border-left-color:transparent}.border-t-transparent{border-top-color:transparent}.bg-apple-accent{--tw-bg-opacity: 1;background-color:rgb(10 132 255 / var(--tw-bg-opacity, 1))}.bg-apple-accent\/10{background-color:#0a84ff1a}.bg-apple-accent\/20{background-color:#0a84ff33}.bg-apple-accent\/30{background-color:#0a84ff4d}.bg-apple-accent\/90{background-color:#0a84ffe6}.bg-apple-bg-elevated{--tw-bg-opacity: 1;background-color:rgb(72 72 74 / var(--tw-bg-opacity, 1))}.bg-apple-bg-primary{--tw-bg-opacity: 1;background-color:rgb(28 28 30 / var(--tw-bg-opacity, 1))}.bg-apple-bg-secondary{--tw-bg-opacity: 1;background-color:rgb(44 44 46 / var(--tw-bg-opacity, 1))}.bg-apple-bg-tertiary{--tw-bg-opacity: 1;background-color:rgb(58 58 60 / var(--tw-bg-opacity, 1))}.bg-apple-green{--tw-bg-opacity: 1;background-color:rgb(48 209 88 / var(--tw-bg-opacity, 1))}.bg-apple-green\/10{background-color:#30d1581a}.bg-apple-green\/20{background-color:#30d15833}.bg-apple-red{--tw-bg-opacity: 1;background-color:rgb(255 69 58 / var(--tw-bg-opacity, 1))}.bg-apple-red\/20{background-color:#ff453a33}.bg-apple-separator{--tw-bg-opacity: 1;background-color:rgb(56 56 58 / var(--tw-bg-opacity, 1))}.bg-apple-text-secondary{--tw-bg-opacity: 1;background-color:rgb(152 152 157 / var(--tw-bg-opacity, 1))}.bg-apple-text-secondary\/20{background-color:#98989d33}.bg-apple-text-tertiary{--tw-bg-opacity: 1;background-color:rgb(99 99 102 / var(--tw-bg-opacity, 1))}.bg-apple-yellow{--tw-bg-opacity: 1;background-color:rgb(255 214 10 / var(--tw-bg-opacity, 1))}.bg-apple-yellow\/20{background-color:#ffd60a33}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-transparent{background-color:transparent}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:4px}.p-1\.5{padding:6px}.p-2{padding:8px}.p-3{padding:12px}.p-4{padding:16px}.p-6{padding:24px}.px-1{padding-left:4px;padding-right:4px}.px-1\.5{padding-left:6px;padding-right:6px}.px-2{padding-left:8px;padding-right:8px}.px-3{padding-left:12px;padding-right:12px}.px-4{padding-left:16px;padding-right:16px}.px-6{padding-left:24px;padding-right:24px}.py-0\.5{padding-top:2px;padding-bottom:2px}.py-1{padding-top:4px;padding-bottom:4px}.py-1\.5{padding-top:6px;padding-bottom:6px}.py-12{padding-top:48px;padding-bottom:48px}.py-2{padding-top:8px;padding-bottom:8px}.py-3{padding-top:12px;padding-bottom:12px}.py-4{padding-top:16px;padding-bottom:16px}.pb-2{padding-bottom:8px}.pb-4{padding-bottom:16px}.pt-2{padding-top:8px}.pt-3{padding-top:12px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-base{font-size:15px;line-height:20px;letter-spacing:-.24px}.text-lg{font-size:17px;line-height:22px;letter-spacing:-.41px}.text-sm{font-size:13px;line-height:18px;letter-spacing:-.08px}.text-xl{font-size:20px;line-height:24px;letter-spacing:.38px}.text-xs{font-size:11px;line-height:13px;letter-spacing:.07px}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.tracking-wider{letter-spacing:.05em}.text-apple-accent{--tw-text-opacity: 1;color:rgb(10 132 255 / var(--tw-text-opacity, 1))}.text-apple-green{--tw-text-opacity: 1;color:rgb(48 209 88 / var(--tw-text-opacity, 1))}.text-apple-red{--tw-text-opacity: 1;color:rgb(255 69 58 / var(--tw-text-opacity, 1))}.text-apple-text-primary{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-apple-text-secondary{--tw-text-opacity: 1;color:rgb(152 152 157 / var(--tw-text-opacity, 1))}.text-apple-text-tertiary{--tw-text-opacity: 1;color:rgb(99 99 102 / var(--tw-text-opacity, 1))}.text-apple-yellow{--tw-text-opacity: 1;color:rgb(255 214 10 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\/50{color:#ffffff80}.text-white\/70{color:#ffffffb3}.text-white\/80{color:#fffc}.text-white\/90{color:#ffffffe6}.opacity-0{opacity:0}.opacity-60{opacity:.6}.shadow-apple-lg{--tw-shadow: 0 10px 40px rgba(0, 0, 0, .4);--tw-shadow-colored: 0 10px 40px 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-apple-xl{--tw-shadow: 0 20px 60px rgba(0, 0, 0, .5);--tw-shadow-colored: 0 20px 60px 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 rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--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 rgb(0 0 0 / .05);--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:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-apple-accent{--tw-ring-opacity: 1;--tw-ring-color: rgb(10 132 255 / var(--tw-ring-opacity, 1))}.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-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)}.backdrop-blur-xl{--tw-backdrop-blur: blur(24px);-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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.glass{background:#2c2c2ecc;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}.transition-apple{transition:all .25s cubic-bezier(.25,.1,.25,1)}:root{--color-bg-primary: #1c1c1e;--color-bg-secondary: #2c2c2e;--color-bg-tertiary: #3a3a3c;--color-bg-elevated: #48484a;--color-accent: #0a84ff;--color-green: #30d158;--color-yellow: #ffd60a;--color-red: #ff453a;--color-text-primary: #ffffff;--color-text-secondary: #98989d;--color-separator: #38383a;--blur-lg: blur(20px);--blur-xl: blur(40px);--shadow-lg: 0 10px 40px rgba(0, 0, 0, .4);--radius-lg: 12px}*{box-sizing:border-box}html,body,#root{height:100%;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,SF Pro Display,SF Pro Text,system-ui,sans-serif;background-color:var(--color-bg-primary);color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#fff3;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#ffffff4d}::-moz-selection{background:#0a84ff66}::selection{background:#0a84ff66}*:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px}input,textarea{font-family:inherit}input::-moz-placeholder,textarea::-moz-placeholder{color:var(--color-text-secondary);opacity:.7}input::placeholder,textarea::placeholder{color:var(--color-text-secondary);opacity:.7}button{font-family:inherit;cursor:pointer}button:disabled{cursor:not-allowed;opacity:.5}code,pre,.font-mono{font-family:SF Mono,Monaco,Menlo,Courier New,monospace}@keyframes statusPulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.1)}}.status-pulse{animation:statusPulse 2s ease-in-out infinite}@keyframes thinkingDot{0%,20%{opacity:.3}50%{opacity:1}80%,to{opacity:.3}}.thinking-dot-1{animation:thinkingDot 1.4s ease-in-out infinite}.thinking-dot-2{animation:thinkingDot 1.4s ease-in-out infinite .2s}.thinking-dot-3{animation:thinkingDot 1.4s ease-in-out infinite .4s}.placeholder\:text-apple-text-tertiary::-moz-placeholder{--tw-text-opacity: 1;color:rgb(99 99 102 / var(--tw-text-opacity, 1))}.placeholder\:text-apple-text-tertiary::placeholder{--tw-text-opacity: 1;color:rgb(99 99 102 / var(--tw-text-opacity, 1))}.focus-within\:border-apple-accent:focus-within{--tw-border-opacity: 1;border-color:rgb(10 132 255 / var(--tw-border-opacity, 1))}.hover\:bg-apple-accent-hover:hover{--tw-bg-opacity: 1;background-color:rgb(64 156 255 / var(--tw-bg-opacity, 1))}.hover\:bg-apple-bg-elevated:hover{--tw-bg-opacity: 1;background-color:rgb(72 72 74 / var(--tw-bg-opacity, 1))}.hover\:bg-apple-bg-tertiary:hover{--tw-bg-opacity: 1;background-color:rgb(58 58 60 / var(--tw-bg-opacity, 1))}.hover\:bg-apple-red\/20:hover{background-color:#ff453a33}.hover\:bg-apple-red\/80:hover{background-color:#ff453acc}.hover\:text-apple-accent-hover:hover{--tw-text-opacity: 1;color:rgb(64 156 255 / var(--tw-text-opacity, 1))}.hover\:text-apple-red:hover{--tw-text-opacity: 1;color:rgb(255 69 58 / var(--tw-text-opacity, 1))}.hover\:text-apple-red\/80:hover{color:#ff453acc}.hover\:text-apple-text-secondary:hover{--tw-text-opacity: 1;color:rgb(152 152 157 / var(--tw-text-opacity, 1))}.focus\:border-none:focus{border-style:none}.focus\:border-apple-accent:focus{--tw-border-opacity: 1;border-color:rgb(10 132 255 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:visible{visibility:visible}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width: 640px){.sm\:block{display:block}}
|