diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md new file mode 100644 index 0000000..a1e169c --- /dev/null +++ b/IMPLEMENTATION_PLAN.md @@ -0,0 +1,257 @@ +# EU-Utility V3 Implementation Plan + +Based on original Python/PyQt6 EU-Utility analysis. + +--- + +## Original Features Analysis + +### 1. Architecture +- **Original:** Python 3.11 + PyQt6 +- **New:** Rust + Tauri + React + TypeScript +- **Plugin System:** 25+ built-in plugins + +### 2. UI Structure +``` +Main Overlay (Semi-transparent, always on top) +├── Left Sidebar: Plugin tabs/icons +├── Center: Active plugin content +└── Bottom: Quick actions bar + +Floating Icon (Screen overlay) +├── Double-click: Toggle main overlay +├── Right-click: Context menu +└── Draggable position +``` + +### 3. Plugin Categories + +#### Dashboard & Utility +- [ ] Dashboard - Customizable start page with stats +- [ ] Calculator - Standard calculator +- [ ] Settings - Preferences configuration +- [ ] Plugin Store - Community marketplace + +#### Search & Information +- [ ] Universal Search - Nexus entities (items, mobs, locations) +- [ ] Nexus Search - Items and market data +- [ ] TP Runner - Teleporter route planner + +#### Calculators +- [ ] DPP Calculator - Damage Per PEC, weapon efficiency +- [ ] Crafting Calc - Blueprint calculator with success rates +- [ ] Enhancer Calc - Break rates and costs + +#### Trackers +- [ ] Loot Tracker - Hunting loot with ROI analysis +- [ ] Skill Scanner - OCR-based skill tracking +- [ ] Codex Tracker - Creature challenge progress +- [ ] Mission Tracker - Mission and objective tracking +- [ ] Global Tracker - Globals, HOFs, ATHs tracking +- [ ] Mining Helper - Claims and hotspot tracking +- [ ] Auction Tracker - Price and markup tracking +- [ ] Inventory Manager - TT value and item management +- [ ] Profession Scanner - Profession rank tracking + +#### Game Integration +- [ ] Game Reader - OCR for in-game menus/text +- [ ] Chat Logger - Log, search, filter chat + +#### External Integration +- [ ] Spotify Controller - Control playback + +--- + +## Hotkey Mapping + +| Hotkey | Action | Plugin | +|--------|--------|--------| +| Ctrl+Shift+U | Toggle main overlay | Global | +| Ctrl+Shift+H | Hide all overlays | Global | +| Ctrl+Shift+F | Universal Search | Search | +| Ctrl+Shift+N | Nexus Search | Search | +| Ctrl+Shift+C | Calculator | Utility | +| Ctrl+Shift+D | DPP Calculator | Calculator | +| Ctrl+Shift+E | Enhancer Calc | Calculator | +| Ctrl+Shift+B | Crafting Calc | Calculator | +| Ctrl+Shift+L | Loot Tracker | Tracker | +| Ctrl+Shift+S | Skill Scanner | Tracker | +| Ctrl+Shift+X | Codex Tracker | Tracker | +| Ctrl+Shift+R | Game Reader | Scanner | +| Ctrl+Shift+M | Spotify Controller | Media | +| Ctrl+Shift+Home | Dashboard | Overview | +| Ctrl+Shift+, | Settings | Configuration | + +--- + +## New UI Design (Windows Start Menu Style) + +### Main Overlay (Bottom Center) +``` +┌─────────────────────────────────────────────────────────┐ +│ [Logo] Search plugins, items... [Timer] [Expand] │ +├─────────────────────────────────────────────────────────┤ +│ │ +│ Quick Access [Session: 02:34:12] │ +│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ +│ │Calc│ │Loot│ │Skill│ │Price│ │Search│ │Settings│ │ +│ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ │ +│ │ +│ Pinned Plugins │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ [Icon] Loot Tracker [On] [Pin] │ +│ [Icon] Skill Scanner [On] [Pin] │ +│ [Icon] DPP Calculator [Off] [Pin] │ +│ │ +│ All Plugins │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ [Icon] Codex Tracker [Off] [Pin] │ +│ [Icon] Game Reader [Off] [Pin] │ +│ [Icon] Mining Helper [Off] [Pin] │ +│ │ +├─────────────────────────────────────────────────────────┤ +│ [Status: Online] Ctrl+Shift+U to toggle │ +└─────────────────────────────────────────────────────────┘ +``` + +### Design Elements +- **Background:** Dark glassmorphism (rgba(32, 32, 32, 0.95)) +- **Blur:** 32px backdrop blur +- **Border:** 1px rgba(255, 255, 255, 0.08) +- **Shadow:** 0 8px 32px rgba(0, 0, 0, 0.4) +- **Border Radius:** 32px (collapsed), 12px (expanded) +- **Position:** Bottom center of screen +- **Width:** 640px (compact), 720px (expanded) + +### Features +1. **Collapsible** - Click logo to expand/collapse +2. **Search** - Type to filter plugins instantly +3. **Pin System** - Pin favorite plugins to top +4. **Quick Access** - 6 shortcut icons always visible +5. **Plugin List** - All plugins with toggle switches +6. **Session Timer** - Live hunt duration +7. **Status Bar** - Online/offline indicator + +--- + +## Implementation Phases + +### Phase 1: Core Framework (COMPLETE) +- [x] Rust + Tauri setup +- [x] React + TypeScript frontend +- [x] Plugin system architecture +- [x] Event bus +- [x] Settings persistence +- [x] Hotkey system +- [x] Window management + +### Phase 2: UI Redesign (IN PROGRESS) +- [ ] Windows Start Menu overlay +- [ ] Collapsible search bar +- [ ] Plugin grid/list view +- [ ] Pin/unpin functionality +- [ ] Quick access icons +- [ ] Session timer display + +### Phase 3: Essential Plugins +- [ ] Dashboard +- [ ] Universal Search +- [ ] Calculator +- [ ] Loot Tracker +- [ ] Settings + +### Phase 4: Advanced Plugins +- [ ] DPP Calculator +- [ ] Skill Scanner (OCR) +- [ ] Codex Tracker +- [ ] Game Reader (OCR) + +### Phase 5: Full Feature Set +- [ ] All 25+ plugins +- [ ] Spotify integration +- [ ] Chat logger +- [ ] Plugin marketplace + +--- + +## Technical Decisions + +### Plugin System +```typescript +interface Plugin { + id: string; + name: string; + description: string; + category: 'dashboard' | 'search' | 'calculator' | 'tracker' | 'game' | 'media'; + icon: string; + version: string; + author: string; + hotkey?: string; + pinned: boolean; + active: boolean; + component: React.ComponentType; +} +``` + +### Data Storage +- SQLite for local data +- Tauri settings API +- Plugin data isolation + +### OCR Integration +- Tesseract for Windows (static link) +- EasyOCR fallback +- Screen region capture +- Text recognition pipeline + +### Screen Reading +- Window capture (game window) +- Region selection (drag to define) +- OCR text extraction +- HP bar detection +- Coordinate reading +- Mob name recognition + +--- + +## File Structure + +``` +src/ +├── components/ +│ ├── Layout.tsx +│ ├── Sidebar.tsx +│ ├── PluginGrid.tsx +│ ├── PluginList.tsx +│ ├── SearchBar.tsx +│ ├── QuickAccess.tsx +│ └── PinnedPlugins.tsx +├── plugins/ +│ ├── dashboard/ +│ ├── search/ +│ ├── calculator/ +│ ├── tracker/ +│ └── game/ +├── pages/ +│ ├── Dashboard.tsx +│ ├── Plugins.tsx +│ ├── Settings.tsx +│ └── Overlay.tsx +└── store/ + ├── appStore.ts + └── pluginStore.ts +``` + +--- + +## Next Steps + +1. **Implement new overlay UI** (Windows Start Menu style) +2. **Add pin/unpin functionality** +3. **Create plugin grid component** +4. **Build essential plugins** (Dashboard, Search, Calculator) +5. **Add OCR integration** for Game Reader + +--- + +*Implementation Plan - EU-Utility V3* diff --git a/src/pages/Overlay.tsx b/src/pages/Overlay.tsx index 1b7e759..46c0525 100644 --- a/src/pages/Overlay.tsx +++ b/src/pages/Overlay.tsx @@ -18,29 +18,146 @@ import { Maximize2, Minimize2, Grid, - Command + Command, + Pin, + PinOff, + MoreVertical } from 'lucide-react' -interface MenuItem { +interface Plugin { id: string + name: string + description: string icon: React.ReactNode - label: string - description?: string + category: 'dashboard' | 'search' | 'calculator' | 'tracker' | 'game' | 'media' | 'utility' hotkey?: string - onClick: () => void - category: 'tools' | 'plugins' | 'system' + pinned: boolean + active: boolean + onToggle: () => void + onPin: () => void } export default function Overlay() { const [isVisible, setIsVisible] = useState(false) const [isExpanded, setIsExpanded] = useState(false) const [searchQuery, setSearchQuery] = useState('') - const [activePlugins, setActivePlugins] = useState(['loot', 'skills']) const [sessionTime, setSessionTime] = useState(0) + const [currentPED, setCurrentPED] = useState(0) const inputRef = useRef(null) + // Plugin state + const [plugins, setPlugins] = useState([ + { + id: 'dashboard', + name: 'Dashboard', + description: 'Overview and statistics', + icon: , + category: 'dashboard', + hotkey: 'Ctrl+Shift+Home', + pinned: true, + active: true, + onToggle: () => togglePlugin('dashboard'), + onPin: () => togglePin('dashboard') + }, + { + id: 'search', + name: 'Universal Search', + description: 'Search items, mobs, locations', + icon: , + category: 'search', + hotkey: 'Ctrl+Shift+F', + pinned: true, + active: false, + onToggle: () => togglePlugin('search'), + onPin: () => togglePin('search') + }, + { + id: 'calculator', + name: 'Calculator', + description: 'Standard calculator', + icon: , + category: 'calculator', + hotkey: 'Ctrl+Shift+C', + pinned: true, + active: false, + onToggle: () => togglePlugin('calculator'), + onPin: () => togglePin('calculator') + }, + { + id: 'dpp-calc', + name: 'DPP Calculator', + description: 'Damage per PEC efficiency', + icon: , + category: 'calculator', + hotkey: 'Ctrl+Shift+D', + pinned: false, + active: false, + onToggle: () => togglePlugin('dpp-calc'), + onPin: () => togglePin('dpp-calc') + }, + { + id: 'loot-tracker', + name: 'Loot Tracker', + description: 'Track hunting sessions', + icon: , + category: 'tracker', + hotkey: 'Ctrl+Shift+L', + pinned: true, + active: false, + onToggle: () => togglePlugin('loot-tracker'), + onPin: () => togglePin('loot-tracker') + }, + { + id: 'skill-scanner', + name: 'Skill Scanner', + description: 'OCR skill tracking', + icon: , + category: 'tracker', + hotkey: 'Ctrl+Shift+S', + pinned: false, + active: false, + onToggle: () => togglePlugin('skill-scanner'), + onPin: () => togglePin('skill-scanner') + }, + { + id: 'codex-tracker', + name: 'Codex Tracker', + description: 'Creature challenges', + icon: , + category: 'tracker', + hotkey: 'Ctrl+Shift+X', + pinned: false, + active: false, + onToggle: () => togglePlugin('codex-tracker'), + onPin: () => togglePin('codex-tracker') + }, + { + id: 'game-reader', + name: 'Game Reader', + description: 'OCR text recognition', + icon: , + category: 'game', + hotkey: 'Ctrl+Shift+R', + pinned: false, + active: false, + onToggle: () => togglePlugin('game-reader'), + onPin: () => togglePin('game-reader') + }, + { + id: 'settings', + name: 'Settings', + description: 'Configure EU-Utility', + icon: , + category: 'utility', + hotkey: 'Ctrl+Shift+,', + pinned: false, + active: false, + onToggle: () => togglePlugin('settings'), + onPin: () => togglePin('settings') + } + ]) + useEffect(() => { - // Listen for overlay toggle const unlisten = listen('overlay:toggle', () => { setIsVisible(prev => { const newVisible = !prev @@ -51,7 +168,6 @@ export default function Overlay() { }) }) - // Session timer const timer = setInterval(() => { setSessionTime(prev => prev + 1) }, 1000) @@ -71,89 +187,44 @@ export default function Overlay() { const formatTime = (seconds: number) => { const h = Math.floor(seconds / 3600) const m = Math.floor((seconds % 3600) / 60) - const s = seconds % 60 return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}` } - const menuItems: MenuItem[] = [ - { - id: 'calculator', - icon: , - label: 'Calculator', - description: 'Quick calculations', - hotkey: 'Ctrl+Shift+C', - onClick: () => invoke('open_calculator'), - category: 'tools' - }, - { - id: 'loot-tracker', - icon: , - label: 'Loot Tracker', - description: 'Track hunting sessions', - hotkey: 'Ctrl+Shift+L', - onClick: () => togglePlugin('loot'), - category: 'plugins' - }, - { - id: 'skill-tracker', - icon: , - label: 'Skill Tracker', - description: 'Monitor skill gains', - onClick: () => togglePlugin('skills'), - category: 'plugins' - }, - { - id: 'price-check', - icon: , - label: 'Price Check', - description: 'Item market values', - onClick: () => invoke('open_price_checker'), - category: 'tools' - }, - { - id: 'dashboard', - icon: , - label: 'Dashboard', - description: 'Main application window', - onClick: () => invoke('show_main_window'), - category: 'system' - }, - { - id: 'settings', - icon: , - label: 'Settings', - description: 'Configure application', - onClick: () => invoke('show_settings_window'), - category: 'system' - }, - ] - - const togglePlugin = (pluginId: string) => { - setActivePlugins(prev => - prev.includes(pluginId) - ? prev.filter(id => id !== pluginId) - : [...prev, pluginId] - ) + const togglePlugin = (id: string) => { + setPlugins(prev => prev.map(p => + p.id === id ? { ...p, active: !p.active } : p + )) } - const filteredItems = searchQuery - ? menuItems.filter(item => - item.label.toLowerCase().includes(searchQuery.toLowerCase()) || - item.description?.toLowerCase().includes(searchQuery.toLowerCase()) - ) - : menuItems + const togglePin = (id: string) => { + setPlugins(prev => prev.map(p => + p.id === id ? { ...p, pinned: !p.pinned } : p + )) + } - const groupedItems = filteredItems.reduce((acc, item) => { - if (!acc[item.category]) acc[item.category] = [] - acc[item.category].push(item) - return acc - }, {} as Record) + const filteredPlugins = searchQuery + ? plugins.filter(p => + p.name.toLowerCase().includes(searchQuery.toLowerCase()) || + p.description.toLowerCase().includes(searchQuery.toLowerCase()) + ) + : plugins + + const pinnedPlugins = filteredPlugins.filter(p => p.pinned) + const unpinnedPlugins = filteredPlugins.filter(p => !p.pinned) + const activeCount = plugins.filter(p => p.active).length if (!isVisible) return null return ( -
- {/* Windows-Style Overlay Container */} +
- {/* Main Search Bar - Windows Style */} -
- {/* Search Input Row */} + {/* Header / Search Bar */}
- {/* Logo Icon - Windows Style */} -
setIsExpanded(!isExpanded)} + className="flex-shrink-0 w-10 h-10 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95" style={{ background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%)', boxShadow: '0 4px 12px rgba(99, 102, 241, 0.4)', }} - onClick={() => setIsExpanded(!isExpanded)} > -
+ {/* Search Input */}
@@ -200,21 +271,26 @@ export default function Overlay() { value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} onFocus={() => setIsExpanded(true)} - placeholder="Type to search plugins, tools..." - className="w-full bg-transparent border-none text-white text-base placeholder:text-white/40 focus:outline-none" - style={{ fontSize: '15px' }} + placeholder="Type to search plugins..." + className="w-full bg-transparent border-none text-white text-base focus:outline-none" + style={{ + fontSize: '15px', + color: 'rgba(255, 255, 255, 0.9)' + }} />
- {/* Right Side Actions */} + {/* Right Side */}
{/* Session Timer */}
- - {formatTime(sessionTime)} + + + {formatTime(sessionTime)} +
{/* Expand/Collapse */} @@ -223,9 +299,9 @@ export default function Overlay() { className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-white/10 transition-colors" > {isExpanded ? ( - + ) : ( - + )} @@ -234,102 +310,233 @@ export default function Overlay() { onClick={() => setIsVisible(false)} className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-white/10 transition-colors" > - +
- {/* Expanded Menu - Windows Start Menu Style */} + {/* Expanded Content */} {isExpanded && (
- {/* Quick Actions Grid */} + {/* Quick Access */}
- Quick Access -
- {activePlugins.length} active -
+ + Quick Access + + + {activeCount} active +
- {menuItems.slice(0, 6).map((item) => ( + {plugins.slice(0, 6).map((plugin) => ( ))}
- {/* Search Results or All Items */} -
- {Object.entries(groupedItems).map(([category, items]) => ( -
-
- - {category === 'tools' ? 'Tools' : category === 'plugins' ? 'Plugins' : 'System'} - -
-
- {items.map((item) => ( - - ))} -
-
- ))} + + - {filteredItems.length === 0 && ( -
+
{ + e.stopPropagation() + plugin.onToggle() + }} + > +
+
+
+
+ ))} +
+
+ )} + + {/* All Plugins */} +
+
+ + All Plugins + +
+ +
+ {unpinnedPlugins.map((plugin) => ( +
+
+
+ {plugin.icon} +
+
+
+ {plugin.name} +
+
+ {plugin.description} +
+
+
+ +
+ {plugin.hotkey && ( + + {plugin.hotkey} + + )} + + + +
{ + e.stopPropagation() + plugin.onToggle() + }} + > +
+
+
+
+ ))} +
+ + {filteredPlugins.length === 0 && ( +

No results found for "{searchQuery}"

@@ -338,17 +545,34 @@ export default function Overlay() { {/* Footer */}
-
- EU-Utility V3.0 +
+ + EU-Utility V3.0 +
-
+ +
Press - Ctrl+Shift+U + + Ctrl+Shift+U + to toggle
diff --git a/src/styles/index.css b/src/styles/index.css index 488d184..f231747 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -6,6 +6,24 @@ @tailwind components; @tailwind utilities; +:root { + --bg-primary: #0a0a0f; + --bg-secondary: #13131a; + --bg-card: #1a1a24; + --bg-hover: #252530; + + --text-primary: #ffffff; + --text-secondary: #94a3b8; + --text-muted: #64748b; + + --accent-primary: #6366f1; + --accent-secondary: #8b5cf6; + --accent-gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); + + --border-color: rgba(255, 255, 255, 0.08); + --glass-bg: rgba(19, 19, 26, 0.95); +} + * { margin: 0; padding: 0; @@ -18,249 +36,310 @@ html, body, #root { } body { - font-family: 'Inter', system-ui, -apple-system, sans-serif; - background: linear-gradient(135deg, #0a0a0f 0%, #13131a 50%, #0a0a0f 100%); - color: #e2e8f0; - overflow: hidden; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + background: var(--bg-primary); + color: var(--text-primary); + line-height: 1.5; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } -/* Custom scrollbar */ +/* Scrollbar */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { - background: rgba(30, 30, 46, 0.5); + background: var(--bg-secondary); border-radius: 3px; } ::-webkit-scrollbar-thumb { - background: rgba(99, 102, 241, 0.4); + background: var(--accent-primary); border-radius: 3px; + opacity: 0.5; } ::-webkit-scrollbar-thumb:hover { - background: rgba(99, 102, 241, 0.6); + opacity: 1; } /* Selection */ ::selection { background: rgba(99, 102, 241, 0.3); - color: #ffffff; -} - -/* Focus styles */ -*:focus { - outline: none; -} - -*:focus-visible { - outline: 2px solid rgba(99, 102, 241, 0.5); - outline-offset: 2px; } /* Animations */ @keyframes fadeIn { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } } -@keyframes slideIn { - from { - opacity: 0; - transform: translateX(-20px); - } - to { - opacity: 1; - transform: translateX(0); - } +@keyframes slideUp { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } } -@keyframes pulse-glow { - 0%, 100% { - box-shadow: 0 0 20px rgba(99, 102, 241, 0.2); - } - 50% { - box-shadow: 0 0 40px rgba(99, 102, 241, 0.4); - } -} - -@keyframes float { - 0%, 100% { - transform: translateY(0); - } - 50% { - transform: translateY(-5px); - } +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } } .animate-fade-in { animation: fadeIn 0.3s ease-out; } -.animate-slide-in { - animation: slideIn 0.3s ease-out; +.animate-slide-up { + animation: slideUp 0.4s ease-out; } -.animate-pulse-glow { - animation: pulse-glow 2s ease-in-out infinite; +.animate-pulse { + animation: pulse 2s ease-in-out infinite; } -.animate-float { - animation: float 3s ease-in-out infinite; +/* Layout */ +.min-h-screen { + min-height: 100vh; } -/* Glassmorphism utilities */ -.glass { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(10px); - border: 1px solid rgba(255, 255, 255, 0.1); +.flex { + display: flex; } -.glass-dark { - background: rgba(10, 10, 15, 0.8); - backdrop-filter: blur(20px); - border: 1px solid rgba(99, 102, 241, 0.2); +.flex-col { + flex-direction: column; } -/* Gradient text */ -.text-gradient { - background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; +.items-center { + align-items: center; } -/* Button styles */ -.btn-primary { - background: linear-gradient(135deg, #6366f1, #4f46e5); - color: white; - border: none; - padding: 0.5rem 1rem; - border-radius: 0.5rem; +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-4 { + gap: 1rem; +} + +.gap-6 { + gap: 1.5rem; +} + +.p-4 { + padding: 1rem; +} + +.p-6 { + padding: 1.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +/* Typography */ +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; + font-weight: 700; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; + font-weight: 600; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; +} + +.font-semibold { + font-weight: 600; +} + +.font-bold { + font-weight: 700; +} + +/* Colors */ +.text-white { + color: var(--text-primary); +} + +.text-gray-400 { + color: var(--text-secondary); +} + +.text-gray-500 { + color: var(--text-muted); +} + +.text-indigo-400 { + color: #818cf8; +} + +.text-emerald-400 { + color: #34d399; +} + +/* Backgrounds */ +.bg-primary { + background: var(--bg-primary); +} + +.bg-secondary { + background: var(--bg-secondary); +} + +.bg-card { + background: var(--bg-card); +} + +.bg-accent { + background: var(--accent-gradient); +} + +/* Cards */ +.card { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 1.5rem; + transition: all 0.2s ease; +} + +.card:hover { + border-color: rgba(99, 102, 241, 0.3); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); +} + +/* Buttons */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.625rem 1.25rem; + border-radius: 8px; font-weight: 500; - transition: all 0.2s; - box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3); + font-size: 0.875rem; + transition: all 0.2s ease; + cursor: pointer; + border: none; +} + +.btn-primary { + background: var(--accent-gradient); + color: white; + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4); } .btn-primary:hover { transform: translateY(-1px); - box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4); -} - -.btn-primary:active { - transform: translateY(0); + box-shadow: 0 6px 16px rgba(99, 102, 241, 0.5); } .btn-secondary { - background: rgba(255, 255, 255, 0.05); - color: #e2e8f0; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 0.5rem 1rem; - border-radius: 0.5rem; - font-weight: 500; - transition: all 0.2s; + background: var(--bg-hover); + color: var(--text-primary); + border: 1px solid var(--border-color); } .btn-secondary:hover { background: rgba(255, 255, 255, 0.1); - border-color: rgba(99, 102, 241, 0.3); + border-color: rgba(99, 102, 241, 0.5); } -/* Card styles */ -.card { - background: rgba(19, 19, 26, 0.8); - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: 12px; - transition: all 0.2s; -} - -.card:hover { - border-color: rgba(99, 102, 241, 0.2); - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); -} - -/* Input styles */ +/* Inputs */ input, select, textarea { + width: 100%; + padding: 0.625rem 0.875rem; background: rgba(0, 0, 0, 0.3); - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 0.5rem; - color: #e2e8f0; - padding: 0.5rem 0.75rem; - transition: all 0.2s; + border: 1px solid var(--border-color); + border-radius: 8px; + color: var(--text-primary); + font-size: 0.875rem; + transition: all 0.2s ease; } input:focus, select:focus, textarea:focus { - border-color: rgba(99, 102, 241, 0.5); + outline: none; + border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } input::placeholder { - color: rgba(148, 163, 184, 0.5); + color: var(--text-muted); } -/* Range input */ -input[type="range"] { - -webkit-appearance: none; - width: 100%; - height: 4px; - background: rgba(255, 255, 255, 0.1); - border-radius: 2px; - outline: none; +/* Grid */ +.grid { + display: grid; } -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - width: 16px; - height: 16px; - background: linear-gradient(135deg, #6366f1, #4f46e5); - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 10px rgba(99, 102, 241, 0.4); - transition: transform 0.2s; +.grid-cols-2 { + grid-template-columns: repeat(2, 1fr); } -input[type="range"]::-webkit-slider-thumb:hover { - transform: scale(1.2); +.grid-cols-3 { + grid-template-columns: repeat(3, 1fr); } -/* Toggle switch */ -.toggle { - appearance: none; - width: 44px; - height: 24px; - background: rgba(255, 255, 255, 0.1); - border-radius: 12px; - position: relative; - cursor: pointer; - transition: background 0.2s; +.grid-cols-4 { + grid-template-columns: repeat(4, 1fr); } -.toggle::after { - content: ''; - position: absolute; - width: 20px; - height: 20px; - background: white; - border-radius: 50%; - top: 2px; - left: 2px; - transition: transform 0.2s; +.gap-4 { + gap: 1rem; } -.toggle:checked { - background: #6366f1; +/* Icons */ +.icon { + width: 1.25rem; + height: 1.25rem; } -.toggle:checked::after { - transform: translateX(20px); +.icon-sm { + width: 1rem; + height: 1rem; +} + +.icon-lg { + width: 1.5rem; + height: 1.5rem; } /* Status indicators */ @@ -268,74 +347,133 @@ input[type="range"]::-webkit-slider-thumb:hover { width: 8px; height: 8px; border-radius: 50%; - display: inline-block; } .status-dot.online { background: #10b981; - box-shadow: 0 0 10px rgba(16, 185, 129, 0.5); + box-shadow: 0 0 8px rgba(16, 185, 129, 0.5); } .status-dot.offline { - background: #64748b; + background: var(--text-muted); } -.status-dot.warning { - background: #f59e0b; - box-shadow: 0 0 10px rgba(245, 158, 11, 0.5); +/* Glass effect */ +.glass { + background: var(--glass-bg); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.08); } -.status-dot.error { - background: #ef4444; - box-shadow: 0 0 10px rgba(239, 68, 68, 0.5); +/* Sidebar */ +.sidebar { + width: 260px; + background: var(--bg-secondary); + border-right: 1px solid var(--border-color); + padding: 1.5rem; } -/* Tooltip */ -.tooltip { - position: relative; +.sidebar-link { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + border-radius: 8px; + color: var(--text-secondary); + text-decoration: none; + transition: all 0.2s ease; } -.tooltip::after { - content: attr(data-tooltip); - position: absolute; - bottom: 100%; +.sidebar-link:hover, +.sidebar-link.active { + background: rgba(99, 102, 241, 0.1); + color: var(--text-primary); +} + +.sidebar-link.active { + background: rgba(99, 102, 241, 0.15); +} + +/* Main content */ +.main-content { + flex: 1; + padding: 2rem; + overflow-y: auto; +} + +/* Header */ +.header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 2rem; + padding-bottom: 1.5rem; + border-bottom: 1px solid var(--border-color); +} + +/* Utility classes */ +.rounded-lg { + border-radius: 8px; +} + +.rounded-xl { + border-radius: 12px; +} + +.rounded-full { + border-radius: 9999px; +} + +.shadow-lg { + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4); +} + +.w-full { + width: 100%; +} + +.h-full { + height: 100%; +} + +/* Overlay specific */ +.overlay-container { + position: fixed; + bottom: 40px; left: 50%; transform: translateX(-50%); - padding: 0.25rem 0.5rem; - background: rgba(0, 0, 0, 0.9); - color: white; - font-size: 0.75rem; - border-radius: 0.25rem; - white-space: nowrap; - opacity: 0; - pointer-events: none; - transition: opacity 0.2s; + z-index: 9999; } -.tooltip:hover::after { - opacity: 1; +.overlay-bar { + background: rgba(32, 32, 32, 0.95); + backdrop-filter: blur(32px); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); + padding: 8px 16px; + display: flex; + align-items: center; + gap: 12px; } -/* Draggable regions */ -[data-tauri-drag-region] { - cursor: move; - user-select: none; -} - -/* Line clamp */ -.line-clamp-2 { - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; -} - -/* Hide scrollbar but keep functionality */ -.scrollbar-hide { - -ms-overflow-style: none; - scrollbar-width: none; -} - -.scrollbar-hide::-webkit-scrollbar { - display: none; +/* Responsive */ +@media (max-width: 768px) { + .sidebar { + width: 100%; + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 100; + } + + .main-content { + padding-bottom: 100px; + } + + .grid-cols-4 { + grid-template-columns: repeat(2, 1fr); + } }