roadmap-kit 1.0.1 → 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.
@@ -8,8 +8,10 @@ import {
8
8
  HelpCircle, GitCommit, Bot, Wrench, Activity, Grid, Play,
9
9
  ArrowRight, Minus as MinusIcon, PlusCircle, MinusCircle, GitBranch,
10
10
  Globe, Command, Columns, List, Link2, MessageSquare, Timer,
11
- BarChart3, FileDown, History, Bell, Keyboard, Filter
11
+ BarChart3, FileDown, History, Bell, Keyboard, Filter, Palette,
12
+ Sun, Moon
12
13
  } from 'lucide-react';
14
+ import { themes, DEFAULT_THEME, getTheme } from './themes.js';
13
15
 
14
16
  // ============ TOAST NOTIFICATION SYSTEM ============
15
17
  const ToastContext = createContext();
@@ -75,6 +77,86 @@ const useToast = () => {
75
77
  return context.toast;
76
78
  };
77
79
 
80
+ // ============ THEME SYSTEM ============
81
+ const ThemeContext = createContext();
82
+
83
+ function ThemeProvider({ children, initialTheme = DEFAULT_THEME, initialColorMode = 'light' }) {
84
+ const [currentTheme, setCurrentTheme] = useState(initialTheme);
85
+ const [colorMode, setColorModeState] = useState(initialColorMode);
86
+
87
+ // Apply theme and color mode to document
88
+ useEffect(() => {
89
+ document.documentElement.setAttribute('data-theme', currentTheme);
90
+ // Apply light/dark class
91
+ if (colorMode === 'dark') {
92
+ document.documentElement.classList.add('dark');
93
+ document.documentElement.classList.remove('light');
94
+ } else {
95
+ document.documentElement.classList.add('light');
96
+ document.documentElement.classList.remove('dark');
97
+ }
98
+ }, [currentTheme, colorMode]);
99
+
100
+ const setTheme = useCallback(async (themeId) => {
101
+ if (!themes[themeId]) return;
102
+ setCurrentTheme(themeId);
103
+
104
+ // Save to server
105
+ try {
106
+ await fetch('/api/auth/profile', {
107
+ method: 'PUT',
108
+ headers: { 'Content-Type': 'application/json' },
109
+ body: JSON.stringify({ theme: themeId })
110
+ });
111
+ } catch (err) {
112
+ console.error('Error saving theme:', err);
113
+ }
114
+ }, []);
115
+
116
+ const setColorMode = useCallback(async (mode) => {
117
+ if (!['light', 'dark'].includes(mode)) return;
118
+ setColorModeState(mode);
119
+
120
+ // Save to server
121
+ try {
122
+ await fetch('/api/auth/profile', {
123
+ method: 'PUT',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify({ colorMode: mode })
126
+ });
127
+ } catch (err) {
128
+ console.error('Error saving color mode:', err);
129
+ }
130
+ }, []);
131
+
132
+ const toggleColorMode = useCallback(() => {
133
+ setColorMode(colorMode === 'dark' ? 'light' : 'dark');
134
+ }, [colorMode, setColorMode]);
135
+
136
+ const value = useMemo(() => ({
137
+ theme: currentTheme,
138
+ themeConfig: getTheme(currentTheme),
139
+ setTheme,
140
+ themes,
141
+ colorMode,
142
+ setColorMode,
143
+ toggleColorMode,
144
+ isDark: colorMode === 'dark'
145
+ }), [currentTheme, setTheme, colorMode, setColorMode, toggleColorMode]);
146
+
147
+ return (
148
+ <ThemeContext.Provider value={value}>
149
+ {children}
150
+ </ThemeContext.Provider>
151
+ );
152
+ }
153
+
154
+ const useTheme = () => {
155
+ const context = useContext(ThemeContext);
156
+ if (!context) throw new Error('useTheme must be used within ThemeProvider');
157
+ return context;
158
+ };
159
+
78
160
  // ============ GLOBAL SEARCH MODAL ============
79
161
  function GlobalSearchModal({ isOpen, onClose, roadmap, onNavigate, t }) {
80
162
  const [query, setQuery] = useState('');
@@ -237,9 +319,9 @@ function useKeyboardShortcuts(handlers) {
237
319
  return;
238
320
  }
239
321
 
240
- // Number keys 1-7 for tab navigation
322
+ // Number keys 1-8 for tab navigation
241
323
  if (!e.ctrlKey && !e.metaKey && !e.altKey) {
242
- if (e.key >= '1' && e.key <= '7') {
324
+ if (e.key >= '1' && e.key <= '8') {
243
325
  e.preventDefault();
244
326
  handlers.onTabChange?.(parseInt(e.key) - 1);
245
327
  return;
@@ -1207,6 +1289,9 @@ function App() {
1207
1289
  const [loginError, setLoginError] = useState(null);
1208
1290
  const [teamMembers, setTeamMembers] = useState([]); // Users for task assignment
1209
1291
 
1292
+ // Theme
1293
+ const { setTheme } = useTheme();
1294
+
1210
1295
  // Confirmation modal state
1211
1296
  const [confirmModal, setConfirmModal] = useState({
1212
1297
  show: false,
@@ -1280,6 +1365,14 @@ function App() {
1280
1365
  authEnabled: data.authEnabled,
1281
1366
  user: data.user || null
1282
1367
  });
1368
+ // Sync theme and color mode from user
1369
+ if (data.user?.theme) {
1370
+ document.documentElement.setAttribute('data-theme', data.user.theme);
1371
+ }
1372
+ if (data.user?.colorMode) {
1373
+ document.documentElement.classList.remove('light', 'dark');
1374
+ document.documentElement.classList.add(data.user.colorMode);
1375
+ }
1283
1376
  if (data.authenticated || !data.authEnabled) {
1284
1377
  loadRoadmap();
1285
1378
  loadTeamMembers();
@@ -1307,6 +1400,14 @@ function App() {
1307
1400
  authEnabled: true,
1308
1401
  user: data.user
1309
1402
  });
1403
+ // Sync theme and color mode from user
1404
+ if (data.user?.theme) {
1405
+ document.documentElement.setAttribute('data-theme', data.user.theme);
1406
+ }
1407
+ if (data.user?.colorMode) {
1408
+ document.documentElement.classList.remove('light', 'dark');
1409
+ document.documentElement.classList.add(data.user.colorMode);
1410
+ }
1310
1411
  loadRoadmap();
1311
1412
  } else {
1312
1413
  setLoginError(data.error || 'Error de autenticacion');
@@ -1339,8 +1440,31 @@ function App() {
1339
1440
  return;
1340
1441
  }
1341
1442
  }
1342
- if (!response.ok) throw new Error('No se pudo cargar roadmap.json');
1343
1443
  const data = await response.json();
1444
+ // Handle case when roadmap.json doesn't exist - redirect to setup
1445
+ if (data.exists === false || data.redirectToSetup) {
1446
+ setRoadmap({ project_info: { name: '', description: '', stack: [] }, features: [] });
1447
+ setActiveTab('setup');
1448
+ setLoading(false);
1449
+ return;
1450
+ }
1451
+ if (!response.ok) throw new Error('No se pudo cargar roadmap.json');
1452
+ // Recalculate progress on load to ensure consistency
1453
+ if (data.features) {
1454
+ data.features.forEach(feature => {
1455
+ if (feature.tasks?.length > 0) {
1456
+ const completed = feature.tasks.filter(t => t.status === 'completed').length;
1457
+ feature.progress = Math.round((completed / feature.tasks.length) * 100);
1458
+ } else {
1459
+ feature.progress = 0;
1460
+ }
1461
+ });
1462
+ const allTasks = data.features.flatMap(f => f.tasks || []);
1463
+ if (allTasks.length > 0) {
1464
+ const totalCompleted = allTasks.filter(t => t.status === 'completed').length;
1465
+ data.project_info.total_progress = Math.round((totalCompleted / allTasks.length) * 100);
1466
+ }
1467
+ }
1344
1468
  setRoadmap(data);
1345
1469
  setHasChanges(false);
1346
1470
  } catch (err) {
@@ -1597,13 +1721,13 @@ function App() {
1597
1721
  if (error) {
1598
1722
  return (
1599
1723
  <div className="min-h-screen flex items-center justify-center bg-black p-4">
1600
- <div className="terminal-card p-8 max-w-md w-full">
1724
+ <div className="theme-card p-8 max-w-md w-full">
1601
1725
  <div className="flex items-center gap-3 mb-6">
1602
- <div className="led led-red" />
1726
+ <div className="led theme-led theme-led-danger" />
1603
1727
  <span className="font-mono text-alert text-sm tracking-wider">ERROR</span>
1604
1728
  </div>
1605
1729
  <p className="font-mono text-gray-400 text-sm mb-6">{error}</p>
1606
- <button onClick={loadRoadmap} className="btn-terminal w-full">
1730
+ <button onClick={loadRoadmap} className="theme-btn-primary w-full">
1607
1731
  RETRY
1608
1732
  </button>
1609
1733
  </div>
@@ -1621,7 +1745,7 @@ function App() {
1621
1745
  {/* <div className="scanlines" /> */}
1622
1746
 
1623
1747
  {/* Sidebar */}
1624
- <aside className={`fixed left-0 top-0 h-full sidebar-terminal z-50 transition-all duration-300 ${sidebarCollapsed ? 'w-16' : 'w-64'}`}>
1748
+ <aside className={`fixed left-0 top-0 h-full theme-sidebar z-50 transition-all duration-300 ${sidebarCollapsed ? 'w-16' : 'w-64'}`}>
1625
1749
  <div className="flex flex-col h-full">
1626
1750
  {/* Logo */}
1627
1751
  <div className="p-4 border-b border-matrix/10">
@@ -1646,8 +1770,8 @@ function App() {
1646
1770
  <span className="font-mono text-[10px] text-gray-500 tracking-widest">{language === 'es' ? 'PROGRESO' : 'PROGRESS'}</span>
1647
1771
  <span className="font-display text-2xl text-matrix">{projectInfo.total_progress || 0}%</span>
1648
1772
  </div>
1649
- <div className="progress-brutal">
1650
- <div className="progress-brutal-fill" style={{ width: `${projectInfo.total_progress || 0}%` }} />
1773
+ <div className="theme-progress">
1774
+ <div className="theme-progress-fill" style={{ width: `${projectInfo.total_progress || 0}%` }} />
1651
1775
  </div>
1652
1776
  </div>
1653
1777
  <div className="grid grid-cols-3 gap-2 text-center">
@@ -1676,7 +1800,7 @@ function App() {
1676
1800
  <button
1677
1801
  key={item.id}
1678
1802
  onClick={() => setActiveTab(item.id)}
1679
- className={`nav-terminal w-full flex items-center gap-3 px-4 py-3 transition-all ${
1803
+ className={`theme-nav-item w-full flex items-center gap-3 px-4 py-3 transition-all ${
1680
1804
  isActive ? 'active' : 'text-gray-500 hover:text-gray-300 hover:bg-white/[0.02]'
1681
1805
  } ${sidebarCollapsed ? 'justify-center px-2' : 'pl-8'}`}
1682
1806
  >
@@ -1699,7 +1823,7 @@ function App() {
1699
1823
  </div>
1700
1824
  )}
1701
1825
  {hasChanges && !sidebarCollapsed && (
1702
- <button onClick={saveRoadmap} disabled={saving} className="btn-terminal w-full flex items-center justify-center gap-2">
1826
+ <button onClick={saveRoadmap} disabled={saving} className="theme-btn-primary w-full flex items-center justify-center gap-2">
1703
1827
  {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
1704
1828
  {t('common.save')}
1705
1829
  </button>
@@ -1772,7 +1896,7 @@ function App() {
1772
1896
  </header>
1773
1897
 
1774
1898
  {/* Content Area */}
1775
- <div className="p-6 pb-24 grid-bg min-h-[calc(100vh-120px)]">
1899
+ <div className="p-6 pb-24 theme-grid-bg min-h-[calc(100vh-120px)]">
1776
1900
  {activeTab === 'features' && (
1777
1901
  <FeaturesTab
1778
1902
  features={filteredFeatures}
@@ -2256,7 +2380,7 @@ function AIGeneratorModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
2256
2380
  - Notificaciones por email
2257
2381
  - Integración con Stripe para pagos
2258
2382
  - API REST documentada con Swagger`}
2259
- className="w-full h-64 input-terminal p-4 text-sm resize-none"
2383
+ className="w-full h-64 theme-input p-4 text-sm resize-none"
2260
2384
  spellCheck={false}
2261
2385
  />
2262
2386
  <p className="mt-2 font-mono text-[10px] text-gray-600">
@@ -2268,7 +2392,7 @@ function AIGeneratorModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
2268
2392
  <button
2269
2393
  onClick={analyzeWithAI}
2270
2394
  disabled={analyzing || !requirements.trim() || (!claudeStatus.available && !claudeStatus.checking)}
2271
- className="btn-terminal flex-1 py-3 disabled:opacity-50 flex items-center justify-center gap-2"
2395
+ className="theme-btn-primary flex-1 py-3 disabled:opacity-50 flex items-center justify-center gap-2"
2272
2396
  >
2273
2397
  <Sparkles className="w-4 h-4" />
2274
2398
  GENERAR CON IA
@@ -2350,7 +2474,7 @@ function AIGeneratorModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
2350
2474
  <div className="flex gap-3">
2351
2475
  <button
2352
2476
  onClick={mergeResults}
2353
- className="btn-terminal flex-1 py-3 flex items-center justify-center gap-2"
2477
+ className="theme-btn-primary flex-1 py-3 flex items-center justify-center gap-2"
2354
2478
  >
2355
2479
  <Plus className="w-4 h-4" />
2356
2480
  AÑADIR AL ROADMAP
@@ -2533,13 +2657,13 @@ function FeaturesTab({
2533
2657
  placeholder={t ? t('common.search') : "search tasks..."}
2534
2658
  value={searchTerm}
2535
2659
  onChange={(e) => setSearchTerm(e.target.value)}
2536
- className="input-terminal w-full pl-10 pr-4 py-2.5 text-sm"
2660
+ className="theme-input w-full pl-10 pr-4 py-2.5 text-sm"
2537
2661
  />
2538
2662
  </div>
2539
2663
  <select
2540
2664
  value={statusFilter}
2541
2665
  onChange={(e) => setStatusFilter(e.target.value)}
2542
- className="input-terminal px-4 py-2.5 text-sm cursor-pointer"
2666
+ className="theme-input px-4 py-2.5 text-sm cursor-pointer"
2543
2667
  >
2544
2668
  <option value="all">{language === 'es' ? 'TODOS' : 'ALL STATUS'}</option>
2545
2669
  <option value="pending">{language === 'es' ? 'PENDIENTE' : 'PENDING'}</option>
@@ -2568,17 +2692,17 @@ function FeaturesTab({
2568
2692
  {/* Advanced Filters Toggle */}
2569
2693
  <button
2570
2694
  onClick={() => setShowFilters(!showFilters)}
2571
- className={`btn-terminal flex items-center gap-2 ${showFilters ? 'border-cyber/50 text-cyber' : ''}`}
2695
+ className={`theme-btn-primary flex items-center gap-2 ${showFilters ? 'border-cyber/50 text-cyber' : ''}`}
2572
2696
  >
2573
2697
  <Filter className="w-4 h-4" />
2574
2698
  {language === 'es' ? 'FILTROS' : 'FILTERS'}
2575
2699
  </button>
2576
2700
 
2577
- <button onClick={() => setShowAddFeature(true)} className="btn-terminal flex items-center gap-2">
2701
+ <button onClick={() => setShowAddFeature(true)} className="theme-btn-primary flex items-center gap-2">
2578
2702
  <Plus className="w-4 h-4" />
2579
2703
  {language === 'es' ? 'NUEVA FEATURE' : 'NEW FEATURE'}
2580
2704
  </button>
2581
- <button onClick={() => setShowAIGenerator(true)} className="btn-terminal flex items-center gap-2 bg-gradient-to-r from-cyber/20 to-matrix/20 border-cyber/50 hover:border-cyber">
2705
+ <button onClick={() => setShowAIGenerator(true)} className="theme-btn-primary flex items-center gap-2 bg-gradient-to-r from-cyber/20 to-matrix/20 border-cyber/50 hover:border-cyber">
2582
2706
  <Sparkles className="w-4 h-4 text-cyber" />
2583
2707
  AI
2584
2708
  </button>
@@ -2592,7 +2716,7 @@ function FeaturesTab({
2592
2716
  <select
2593
2717
  value={priorityFilter}
2594
2718
  onChange={(e) => setPriorityFilter(e.target.value)}
2595
- className="input-terminal px-3 py-1.5 text-xs cursor-pointer"
2719
+ className="theme-input px-3 py-1.5 text-xs cursor-pointer"
2596
2720
  >
2597
2721
  <option value="all">{language === 'es' ? 'TODAS' : 'ALL'}</option>
2598
2722
  <option value="high">{language === 'es' ? 'ALTA' : 'HIGH'}</option>
@@ -2605,7 +2729,7 @@ function FeaturesTab({
2605
2729
  <select
2606
2730
  value={assigneeFilter}
2607
2731
  onChange={(e) => setAssigneeFilter(e.target.value)}
2608
- className="input-terminal px-3 py-1.5 text-xs cursor-pointer"
2732
+ className="theme-input px-3 py-1.5 text-xs cursor-pointer"
2609
2733
  >
2610
2734
  <option value="all">{language === 'es' ? 'TODOS' : 'ALL'}</option>
2611
2735
  <option value="">{language === 'es' ? 'SIN ASIGNAR' : 'UNASSIGNED'}</option>
@@ -2654,7 +2778,7 @@ function FeaturesTab({
2654
2778
  )}
2655
2779
 
2656
2780
  {features.length === 0 && viewMode === 'list' && (
2657
- <div className="terminal-card p-12 text-center">
2781
+ <div className="theme-card p-12 text-center">
2658
2782
  <Search className="w-10 h-10 mx-auto mb-4 text-gray-700" />
2659
2783
  <p className="font-mono text-gray-600 text-sm">{language === 'es' ? 'NO HAY TAREAS' : 'NO TASKS FOUND'}</p>
2660
2784
  </div>
@@ -2684,7 +2808,7 @@ function FeatureCard({ feature, onUpdateTaskStatus, onAddTask, showAddTask, setS
2684
2808
  {/* Progress Ring */}
2685
2809
  <div className="relative w-14 h-14 flex-shrink-0">
2686
2810
  <svg className="w-full h-full -rotate-90" viewBox="0 0 36 36">
2687
- <circle cx="18" cy="18" r="15" fill="none" stroke="#1a1a1a" strokeWidth="3" />
2811
+ <circle cx="18" cy="18" r="15" fill="none" stroke="var(--bg-secondary)" strokeWidth="3" />
2688
2812
  <circle
2689
2813
  cx="18" cy="18" r="15" fill="none"
2690
2814
  stroke="url(#progressGradient)"
@@ -2695,8 +2819,8 @@ function FeatureCard({ feature, onUpdateTaskStatus, onAddTask, showAddTask, setS
2695
2819
  />
2696
2820
  <defs>
2697
2821
  <linearGradient id="progressGradient" x1="0%" y1="0%" x2="100%" y2="0%">
2698
- <stop offset="0%" stopColor="#00ff88" />
2699
- <stop offset="100%" stopColor="#00d4ff" />
2822
+ <stop offset="0%" stopColor="var(--accent-primary)" />
2823
+ <stop offset="100%" stopColor="var(--accent-tertiary)" />
2700
2824
  </linearGradient>
2701
2825
  </defs>
2702
2826
  </svg>
@@ -2726,8 +2850,8 @@ function FeatureCard({ feature, onUpdateTaskStatus, onAddTask, showAddTask, setS
2726
2850
  <span>{feature.tasks.filter(t => t.status === 'completed').length} / {feature.tasks.length} TASKS</span>
2727
2851
  <span>{feature.progress}%</span>
2728
2852
  </div>
2729
- <div className="progress-brutal">
2730
- <div className="progress-brutal-fill" style={{ width: `${feature.progress}%` }} />
2853
+ <div className="theme-progress">
2854
+ <div className="theme-progress-fill" style={{ width: `${feature.progress}%` }} />
2731
2855
  </div>
2732
2856
  </div>
2733
2857
 
@@ -2764,8 +2888,8 @@ function TaskList({ tasks = [], featureId = '', onUpdateStatus, team = [], onAss
2764
2888
  };
2765
2889
 
2766
2890
  const statusConfig = {
2767
- completed: { led: 'led-green', label: 'DONE', color: 'text-matrix' },
2768
- in_progress: { led: 'led-amber', label: 'ACTIVE', color: 'text-signal' },
2891
+ completed: { led: 'theme-led theme-led-success', label: 'DONE', color: 'text-matrix' },
2892
+ in_progress: { led: 'theme-led theme-led-warning', label: 'ACTIVE', color: 'text-signal' },
2769
2893
  pending: { led: 'led-gray', label: 'QUEUE', color: 'text-gray-500' }
2770
2894
  };
2771
2895
 
@@ -2970,7 +3094,7 @@ function TaskList({ tasks = [], featureId = '', onUpdateStatus, team = [], onAss
2970
3094
  const member = team.find(m => m.id === e.target.value);
2971
3095
  onAssignTask?.(featureId, task.id, e.target.value, member?.name || '');
2972
3096
  }}
2973
- className="input-terminal px-3 py-1.5 text-[11px]"
3097
+ className="theme-input px-3 py-1.5 text-[11px]"
2974
3098
  >
2975
3099
  <option value="">Sin asignar</option>
2976
3100
  {team.map((member) => (
@@ -3063,27 +3187,27 @@ function MetricsTab({ roadmap, language }) {
3063
3187
  <div className="space-y-6 animate-fade-in">
3064
3188
  {/* Summary Cards */}
3065
3189
  <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
3066
- <div className="terminal-card p-5">
3190
+ <div className="theme-card p-5">
3067
3191
  <div className="font-mono text-[10px] text-gray-500 mb-2">{language === 'es' ? 'TOTAL TAREAS' : 'TOTAL TASKS'}</div>
3068
3192
  <div className="font-display text-3xl text-white">{stats.total}</div>
3069
3193
  </div>
3070
- <div className="terminal-card p-5 border-matrix/20">
3194
+ <div className="theme-card p-5 border-matrix/20">
3071
3195
  <div className="font-mono text-[10px] text-gray-500 mb-2">{language === 'es' ? 'COMPLETADAS' : 'COMPLETED'}</div>
3072
3196
  <div className="font-display text-3xl text-matrix">{stats.completed}</div>
3073
3197
  <div className="font-mono text-[10px] text-matrix/60 mt-1">{completionRate}%</div>
3074
3198
  </div>
3075
- <div className="terminal-card p-5 border-signal/20">
3199
+ <div className="theme-card p-5 border-signal/20">
3076
3200
  <div className="font-mono text-[10px] text-gray-500 mb-2">{language === 'es' ? 'EN PROGRESO' : 'IN PROGRESS'}</div>
3077
3201
  <div className="font-display text-3xl text-signal">{stats.inProgress}</div>
3078
3202
  </div>
3079
- <div className="terminal-card p-5">
3203
+ <div className="theme-card p-5">
3080
3204
  <div className="font-mono text-[10px] text-gray-500 mb-2">{language === 'es' ? 'PENDIENTES' : 'PENDING'}</div>
3081
3205
  <div className="font-display text-3xl text-gray-500">{stats.pending}</div>
3082
3206
  </div>
3083
3207
  </div>
3084
3208
 
3085
3209
  {/* Progress Overview */}
3086
- <div className="terminal-card p-5">
3210
+ <div className="theme-card p-5">
3087
3211
  <h3 className="font-mono text-sm text-white mb-4">{language === 'es' ? 'PROGRESO GENERAL' : 'OVERALL PROGRESS'}</h3>
3088
3212
  <div className="relative h-8 bg-void-100 border border-white/5 overflow-hidden">
3089
3213
  <div
@@ -3104,7 +3228,7 @@ function MetricsTab({ roadmap, language }) {
3104
3228
  </div>
3105
3229
 
3106
3230
  {/* By Priority */}
3107
- <div className="terminal-card p-5">
3231
+ <div className="theme-card p-5">
3108
3232
  <h3 className="font-mono text-sm text-white mb-4">{language === 'es' ? 'POR PRIORIDAD' : 'BY PRIORITY'}</h3>
3109
3233
  <div className="grid grid-cols-3 gap-4">
3110
3234
  <div className="p-4 bg-alert/5 border border-alert/20">
@@ -3132,7 +3256,7 @@ function MetricsTab({ roadmap, language }) {
3132
3256
  </div>
3133
3257
 
3134
3258
  {/* By Feature */}
3135
- <div className="terminal-card p-5">
3259
+ <div className="theme-card p-5">
3136
3260
  <h3 className="font-mono text-sm text-white mb-4">{language === 'es' ? 'POR FEATURE' : 'BY FEATURE'}</h3>
3137
3261
  <div className="space-y-3">
3138
3262
  {stats.byFeature.map((feature, idx) => (
@@ -3156,7 +3280,7 @@ function MetricsTab({ roadmap, language }) {
3156
3280
  </div>
3157
3281
 
3158
3282
  {/* Export Options */}
3159
- <div className="terminal-card p-5">
3283
+ <div className="theme-card p-5">
3160
3284
  <h3 className="font-mono text-sm text-white mb-4">{language === 'es' ? 'EXPORTAR DATOS' : 'EXPORT DATA'}</h3>
3161
3285
  <div className="flex gap-3">
3162
3286
  <button
@@ -3176,7 +3300,7 @@ function MetricsTab({ roadmap, language }) {
3176
3300
  a.download = 'roadmap-export.csv';
3177
3301
  a.click();
3178
3302
  }}
3179
- className="btn-terminal flex items-center gap-2"
3303
+ className="theme-btn-primary flex items-center gap-2"
3180
3304
  >
3181
3305
  <FileDown className="w-4 h-4" />
3182
3306
  CSV
@@ -3190,7 +3314,7 @@ function MetricsTab({ roadmap, language }) {
3190
3314
  a.download = 'roadmap-backup.json';
3191
3315
  a.click();
3192
3316
  }}
3193
- className="btn-terminal flex items-center gap-2"
3317
+ className="theme-btn-primary flex items-center gap-2"
3194
3318
  >
3195
3319
  <FileDown className="w-4 h-4" />
3196
3320
  JSON
@@ -3216,23 +3340,23 @@ function ResourcesTab({ resources }) {
3216
3340
  <div className="space-y-6 animate-fade-in">
3217
3341
  {/* Summary */}
3218
3342
  <div className="grid grid-cols-3 gap-4">
3219
- <div className="terminal-card p-5">
3343
+ <div className="theme-card p-5">
3220
3344
  <div className="flex items-center gap-3 mb-3">
3221
- <div className="led led-green" />
3345
+ <div className="led theme-led theme-led-success" />
3222
3346
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">UI COMPONENTS</span>
3223
3347
  </div>
3224
3348
  <div className="metric-display text-3xl text-matrix">{ui_components.length}</div>
3225
3349
  </div>
3226
- <div className="terminal-card p-5">
3350
+ <div className="theme-card p-5">
3227
3351
  <div className="flex items-center gap-3 mb-3">
3228
- <div className="led led-amber" />
3352
+ <div className="led theme-led theme-led-warning" />
3229
3353
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">UTILITIES</span>
3230
3354
  </div>
3231
3355
  <div className="metric-display text-3xl text-signal">{utilities.length}</div>
3232
3356
  </div>
3233
- <div className="terminal-card p-5">
3357
+ <div className="theme-card p-5">
3234
3358
  <div className="flex items-center gap-3 mb-3">
3235
- <div className="led led-green" />
3359
+ <div className="led theme-led theme-led-success" />
3236
3360
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">DB TABLES</span>
3237
3361
  </div>
3238
3362
  <div className="metric-display text-3xl text-cyber">{database_tables.length}</div>
@@ -3241,7 +3365,7 @@ function ResourcesTab({ resources }) {
3241
3365
 
3242
3366
  {/* UI Components */}
3243
3367
  {ui_components.length > 0 && (
3244
- <div className="terminal-card p-5">
3368
+ <div className="theme-card p-5">
3245
3369
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4"># UI_COMPONENTS</h3>
3246
3370
  <div className="space-y-3">
3247
3371
  {ui_components.map((comp, idx) => (
@@ -3265,7 +3389,7 @@ function ResourcesTab({ resources }) {
3265
3389
 
3266
3390
  {/* Utilities */}
3267
3391
  {utilities.length > 0 && (
3268
- <div className="terminal-card p-5">
3392
+ <div className="theme-card p-5">
3269
3393
  <h3 className="font-mono text-sm text-signal tracking-wider mb-4"># UTILITIES</h3>
3270
3394
  <div className="space-y-3">
3271
3395
  {utilities.map((util, idx) => (
@@ -3302,7 +3426,7 @@ function ResourcesTab({ resources }) {
3302
3426
 
3303
3427
  {/* Database Tables */}
3304
3428
  {database_tables.length > 0 && (
3305
- <div className="terminal-card p-5">
3429
+ <div className="theme-card p-5">
3306
3430
  <h3 className="font-mono text-sm text-cyber tracking-wider mb-4"># DATABASE_TABLES</h3>
3307
3431
  <div className="space-y-3">
3308
3432
  {database_tables.map((table, idx) => (
@@ -3369,8 +3493,8 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3369
3493
 
3370
3494
  const statusConfig = {
3371
3495
  pending: { led: 'led-gray', label: 'PENDING', color: 'text-gray-500' },
3372
- in_progress: { led: 'led-amber', label: 'IN PROGRESS', color: 'text-signal' },
3373
- resolved: { led: 'led-green', label: 'RESOLVED', color: 'text-matrix' }
3496
+ in_progress: { led: 'theme-led theme-led-warning', label: 'IN PROGRESS', color: 'text-signal' },
3497
+ resolved: { led: 'theme-led theme-led-success', label: 'RESOLVED', color: 'text-matrix' }
3374
3498
  };
3375
3499
 
3376
3500
  // Update debt status
@@ -3458,30 +3582,30 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3458
3582
  <div className="grid grid-cols-3 gap-4">
3459
3583
  <button
3460
3584
  onClick={() => setFilterSeverity(filterSeverity === 'high' ? 'all' : 'high')}
3461
- className={`terminal-card p-5 transition-all ${filterSeverity === 'high' ? 'border-alert glow-alert' : 'border-alert/30 hover:border-alert/50'}`}
3585
+ className={`theme-card p-5 transition-all ${filterSeverity === 'high' ? 'border-alert glow-alert' : 'border-alert/30 hover:border-alert/50'}`}
3462
3586
  >
3463
3587
  <div className="flex items-center gap-3 mb-3">
3464
- <div className="led led-red" />
3588
+ <div className="led theme-led theme-led-danger" />
3465
3589
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">HIGH</span>
3466
3590
  </div>
3467
3591
  <div className="metric-display text-3xl text-alert">{bySeverity.high.length}</div>
3468
3592
  </button>
3469
3593
  <button
3470
3594
  onClick={() => setFilterSeverity(filterSeverity === 'medium' ? 'all' : 'medium')}
3471
- className={`terminal-card p-5 transition-all ${filterSeverity === 'medium' ? 'border-signal glow-signal' : 'border-signal/30 hover:border-signal/50'}`}
3595
+ className={`theme-card p-5 transition-all ${filterSeverity === 'medium' ? 'border-signal glow-signal' : 'border-signal/30 hover:border-signal/50'}`}
3472
3596
  >
3473
3597
  <div className="flex items-center gap-3 mb-3">
3474
- <div className="led led-amber" />
3598
+ <div className="led theme-led theme-led-warning" />
3475
3599
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">MEDIUM</span>
3476
3600
  </div>
3477
3601
  <div className="metric-display text-3xl text-signal">{bySeverity.medium.length}</div>
3478
3602
  </button>
3479
3603
  <button
3480
3604
  onClick={() => setFilterSeverity(filterSeverity === 'low' ? 'all' : 'low')}
3481
- className={`terminal-card p-5 transition-all ${filterSeverity === 'low' ? 'border-cyber glow-cyber' : 'border-cyber/30 hover:border-cyber/50'}`}
3605
+ className={`theme-card p-5 transition-all ${filterSeverity === 'low' ? 'border-cyber glow-cyber' : 'border-cyber/30 hover:border-cyber/50'}`}
3482
3606
  >
3483
3607
  <div className="flex items-center gap-3 mb-3">
3484
- <div className="led led-green" />
3608
+ <div className="led theme-led theme-led-success" />
3485
3609
  <span className="font-mono text-[10px] text-gray-500 tracking-wider">LOW</span>
3486
3610
  </div>
3487
3611
  <div className="metric-display text-3xl text-cyber">{bySeverity.low.length}</div>
@@ -3494,7 +3618,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3494
3618
  <select
3495
3619
  value={filterStatus}
3496
3620
  onChange={(e) => setFilterStatus(e.target.value)}
3497
- className="input-terminal px-3 py-2 text-xs"
3621
+ className="theme-input px-3 py-2 text-xs"
3498
3622
  >
3499
3623
  <option value="all">ALL STATUS</option>
3500
3624
  <option value="pending">PENDING</option>
@@ -3514,7 +3638,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3514
3638
  </span>
3515
3639
  <button
3516
3640
  onClick={() => setShowAddDebt(true)}
3517
- className="ml-auto btn-terminal flex items-center gap-2"
3641
+ className="ml-auto theme-btn-primary flex items-center gap-2"
3518
3642
  >
3519
3643
  <Plus className="w-4 h-4" />
3520
3644
  ADD DEBT
@@ -3533,7 +3657,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3533
3657
 
3534
3658
  {/* Debt Items */}
3535
3659
  {filteredDebts.length > 0 ? (
3536
- <div className="terminal-card p-5">
3660
+ <div className="theme-card p-5">
3537
3661
  <h3 className="font-mono text-sm text-signal tracking-wider mb-4"># TECHNICAL_DEBT</h3>
3538
3662
  <div className="space-y-2">
3539
3663
  {filteredDebts.map((debt) => {
@@ -3734,7 +3858,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3734
3858
  </div>
3735
3859
  </div>
3736
3860
  ) : (
3737
- <div className="terminal-card p-12 text-center">
3861
+ <div className="theme-card p-12 text-center">
3738
3862
  <CheckCircle2 className="w-10 h-10 mx-auto mb-4 text-matrix" />
3739
3863
  <p className="font-mono text-sm text-gray-600">
3740
3864
  {allDebts.length === 0 ? 'NO TECHNICAL DEBT REGISTERED' : 'NO ITEMS MATCH FILTERS'}
@@ -3742,7 +3866,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3742
3866
  {allDebts.length === 0 && (
3743
3867
  <button
3744
3868
  onClick={() => setShowAddDebt(true)}
3745
- className="btn-terminal mt-4 inline-flex items-center gap-2"
3869
+ className="theme-btn-primary mt-4 inline-flex items-center gap-2"
3746
3870
  >
3747
3871
  <Plus className="w-4 h-4" />
3748
3872
  ADD FIRST DEBT
@@ -3752,7 +3876,7 @@ function DebtTab({ roadmap, setRoadmap, setHasChanges }) {
3752
3876
  )}
3753
3877
 
3754
3878
  {/* Debt Schema Info */}
3755
- <div className="terminal-card p-4">
3879
+ <div className="theme-card p-4">
3756
3880
  <details>
3757
3881
  <summary className="font-mono text-[10px] text-gray-600 cursor-pointer hover:text-white">
3758
3882
  JSON SCHEMA FOR TECHNICAL DEBT
@@ -3826,7 +3950,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3826
3950
  };
3827
3951
 
3828
3952
  return (
3829
- <form onSubmit={handleSubmit} className="terminal-card p-5 space-y-4">
3953
+ <form onSubmit={handleSubmit} className="theme-card p-5 space-y-4">
3830
3954
  <h3 className="font-mono text-sm text-signal tracking-wider">
3831
3955
  {isEdit ? '# EDIT DEBT' : '# NEW TECHNICAL DEBT'}
3832
3956
  </h3>
@@ -3838,7 +3962,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3838
3962
  <select
3839
3963
  value={featureId}
3840
3964
  onChange={(e) => { setFeatureId(e.target.value); setTaskId(''); }}
3841
- className="input-terminal w-full px-3 py-2 text-sm"
3965
+ className="theme-input w-full px-3 py-2 text-sm"
3842
3966
  required
3843
3967
  >
3844
3968
  <option value="">Select feature...</option>
@@ -3852,7 +3976,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3852
3976
  <select
3853
3977
  value={taskId}
3854
3978
  onChange={(e) => setTaskId(e.target.value)}
3855
- className="input-terminal w-full px-3 py-2 text-sm"
3979
+ className="theme-input w-full px-3 py-2 text-sm"
3856
3980
  required
3857
3981
  disabled={!featureId}
3858
3982
  >
@@ -3872,7 +3996,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3872
3996
  onChange={(e) => setDescription(e.target.value)}
3873
3997
  placeholder="Describe the technical debt..."
3874
3998
  rows={2}
3875
- className="input-terminal w-full px-3 py-2 text-sm resize-none"
3999
+ className="theme-input w-full px-3 py-2 text-sm resize-none"
3876
4000
  required
3877
4001
  />
3878
4002
  </div>
@@ -3880,7 +4004,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3880
4004
  <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
3881
4005
  <div>
3882
4006
  <label className="font-mono text-[10px] text-gray-500 tracking-wider mb-2 block">SEVERITY</label>
3883
- <select value={severity} onChange={(e) => setSeverity(e.target.value)} className="input-terminal w-full px-3 py-2 text-sm">
4007
+ <select value={severity} onChange={(e) => setSeverity(e.target.value)} className="theme-input w-full px-3 py-2 text-sm">
3884
4008
  <option value="high">HIGH</option>
3885
4009
  <option value="medium">MEDIUM</option>
3886
4010
  <option value="low">LOW</option>
@@ -3888,7 +4012,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3888
4012
  </div>
3889
4013
  <div>
3890
4014
  <label className="font-mono text-[10px] text-gray-500 tracking-wider mb-2 block">PRIORITY</label>
3891
- <select value={priority} onChange={(e) => setPriority(e.target.value)} className="input-terminal w-full px-3 py-2 text-sm">
4015
+ <select value={priority} onChange={(e) => setPriority(e.target.value)} className="theme-input w-full px-3 py-2 text-sm">
3892
4016
  <option value="critical">CRITICAL</option>
3893
4017
  <option value="high">HIGH</option>
3894
4018
  <option value="medium">MEDIUM</option>
@@ -3902,12 +4026,12 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3902
4026
  value={estimatedEffort}
3903
4027
  onChange={(e) => setEstimatedEffort(e.target.value)}
3904
4028
  placeholder="e.g. 2h, 1d"
3905
- className="input-terminal w-full px-3 py-2 text-sm"
4029
+ className="theme-input w-full px-3 py-2 text-sm"
3906
4030
  />
3907
4031
  </div>
3908
4032
  <div>
3909
4033
  <label className="font-mono text-[10px] text-gray-500 tracking-wider mb-2 block">ASSIGNED</label>
3910
- <select value={assignedTo} onChange={(e) => setAssignedTo(e.target.value)} className="input-terminal w-full px-3 py-2 text-sm">
4034
+ <select value={assignedTo} onChange={(e) => setAssignedTo(e.target.value)} className="theme-input w-full px-3 py-2 text-sm">
3911
4035
  <option value="">Unassigned</option>
3912
4036
  {team.map(m => (
3913
4037
  <option key={m.id} value={m.name}>{m.name}</option>
@@ -3923,7 +4047,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3923
4047
  onChange={(e) => setImpact(e.target.value)}
3924
4048
  placeholder="What happens if not fixed?"
3925
4049
  rows={2}
3926
- className="input-terminal w-full px-3 py-2 text-sm resize-none"
4050
+ className="theme-input w-full px-3 py-2 text-sm resize-none"
3927
4051
  />
3928
4052
  </div>
3929
4053
 
@@ -3934,7 +4058,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3934
4058
  onChange={(e) => setSolution(e.target.value)}
3935
4059
  placeholder="How to fix this?"
3936
4060
  rows={2}
3937
- className="input-terminal w-full px-3 py-2 text-sm resize-none"
4061
+ className="theme-input w-full px-3 py-2 text-sm resize-none"
3938
4062
  />
3939
4063
  </div>
3940
4064
 
@@ -3946,7 +4070,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3946
4070
  value={affectedFiles}
3947
4071
  onChange={(e) => setAffectedFiles(e.target.value)}
3948
4072
  placeholder="src/file1.js, src/file2.js"
3949
- className="input-terminal w-full px-3 py-2 text-sm"
4073
+ className="theme-input w-full px-3 py-2 text-sm"
3950
4074
  />
3951
4075
  </div>
3952
4076
  <div>
@@ -3956,7 +4080,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3956
4080
  value={tags}
3957
4081
  onChange={(e) => setTags(e.target.value)}
3958
4082
  placeholder="security, performance"
3959
- className="input-terminal w-full px-3 py-2 text-sm"
4083
+ className="theme-input w-full px-3 py-2 text-sm"
3960
4084
  />
3961
4085
  </div>
3962
4086
  </div>
@@ -3965,7 +4089,7 @@ function DebtForm({ features, team, initialData, onSave, onCancel, isEdit }) {
3965
4089
  <button type="button" onClick={onCancel} className="px-4 py-2 border border-white/10 text-gray-500 font-mono text-xs hover:text-white transition-all">
3966
4090
  CANCEL
3967
4091
  </button>
3968
- <button type="submit" className="btn-terminal flex-1 py-2">
4092
+ <button type="submit" className="theme-btn-primary flex-1 py-2">
3969
4093
  {isEdit ? 'UPDATE' : 'ADD DEBT'}
3970
4094
  </button>
3971
4095
  </div>
@@ -3980,7 +4104,7 @@ function InfoTab({ projectInfo }) {
3980
4104
  return (
3981
4105
  <div className="space-y-6 animate-fade-in">
3982
4106
  {/* Stack */}
3983
- <div className="terminal-card p-5">
4107
+ <div className="theme-card p-5">
3984
4108
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4"># STACK</h3>
3985
4109
  <div className="flex flex-wrap gap-2">
3986
4110
  {(projectInfo.stack || []).map((tech, idx) => (
@@ -3996,7 +4120,7 @@ function InfoTab({ projectInfo }) {
3996
4120
 
3997
4121
  {/* Architecture */}
3998
4122
  {projectInfo.architecture && (
3999
- <div className="terminal-card p-5">
4123
+ <div className="theme-card p-5">
4000
4124
  <h3 className="font-mono text-sm text-cyber tracking-wider mb-4"># ARCHITECTURE</h3>
4001
4125
  <p className="font-mono text-xs text-gray-400 leading-relaxed">{projectInfo.architecture}</p>
4002
4126
  </div>
@@ -4004,7 +4128,7 @@ function InfoTab({ projectInfo }) {
4004
4128
 
4005
4129
  {/* Conventions */}
4006
4130
  {Object.keys(conventions).length > 0 && (
4007
- <div className="terminal-card p-5">
4131
+ <div className="theme-card p-5">
4008
4132
  <h3 className="font-mono text-sm text-signal tracking-wider mb-4"># CONVENTIONS</h3>
4009
4133
  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
4010
4134
  {conventions.naming && (
@@ -4054,7 +4178,7 @@ function InfoTab({ projectInfo }) {
4054
4178
 
4055
4179
  {/* Purpose */}
4056
4180
  {projectInfo.purpose && (
4057
- <div className="terminal-card p-5">
4181
+ <div className="theme-card p-5">
4058
4182
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4"># PURPOSE</h3>
4059
4183
  <p className="font-mono text-xs text-gray-400 leading-relaxed">{projectInfo.purpose}</p>
4060
4184
  </div>
@@ -4071,6 +4195,267 @@ function InfoTab({ projectInfo }) {
4071
4195
  );
4072
4196
  }
4073
4197
 
4198
+ // ============ APPEARANCE SECTION ============
4199
+ function AppearanceSection({ language }) {
4200
+ const { theme: currentTheme, setTheme, colorMode, setColorMode, isDark } = useTheme();
4201
+ const [saving, setSaving] = useState(false);
4202
+ const [savingMode, setSavingMode] = useState(false);
4203
+ const toast = useToast();
4204
+
4205
+ const handleThemeChange = async (themeId) => {
4206
+ if (themeId === currentTheme) return;
4207
+ setSaving(true);
4208
+ try {
4209
+ await setTheme(themeId);
4210
+ toast.success(language === 'es' ? 'Tema actualizado' : 'Theme updated');
4211
+ } catch (err) {
4212
+ toast.error(language === 'es' ? 'Error al guardar el tema' : 'Error saving theme');
4213
+ }
4214
+ setSaving(false);
4215
+ };
4216
+
4217
+ const handleColorModeChange = async (mode) => {
4218
+ if (mode === colorMode) return;
4219
+ setSavingMode(true);
4220
+ try {
4221
+ await setColorMode(mode);
4222
+ toast.success(language === 'es' ? 'Modo de color actualizado' : 'Color mode updated');
4223
+ } catch (err) {
4224
+ toast.error(language === 'es' ? 'Error al guardar el modo' : 'Error saving mode');
4225
+ }
4226
+ setSavingMode(false);
4227
+ };
4228
+
4229
+ // Theme preview SVG components
4230
+ const GlassPreview = () => (
4231
+ <svg viewBox="0 0 120 80" className="w-full h-full">
4232
+ {/* Background */}
4233
+ <rect width="120" height="80" fill="#f1f5f9" />
4234
+ {/* Sidebar */}
4235
+ <rect x="0" y="0" width="30" height="80" fill="#ffffff" fillOpacity="0.7" />
4236
+ <rect x="4" y="8" width="22" height="4" rx="2" fill="#10b981" />
4237
+ <rect x="4" y="16" width="22" height="3" rx="1.5" fill="#e2e8f0" />
4238
+ <rect x="4" y="22" width="22" height="3" rx="1.5" fill="#e2e8f0" />
4239
+ <rect x="4" y="28" width="22" height="3" rx="1.5" fill="#e2e8f0" />
4240
+ {/* Cards */}
4241
+ <rect x="36" y="8" width="38" height="28" rx="4" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1" />
4242
+ <rect x="40" y="12" width="20" height="3" rx="1.5" fill="#1e293b" />
4243
+ <rect x="40" y="18" width="30" height="2" rx="1" fill="#94a3b8" />
4244
+ <rect x="40" y="24" width="30" height="4" rx="2" fill="#e2e8f0" />
4245
+ <rect x="40" y="24" width="18" height="4" rx="2" fill="#10b981" />
4246
+ <rect x="80" y="8" width="34" height="28" rx="4" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1" />
4247
+ <rect x="84" y="12" width="16" height="3" rx="1.5" fill="#1e293b" />
4248
+ <rect x="84" y="18" width="26" height="2" rx="1" fill="#94a3b8" />
4249
+ {/* Bottom cards */}
4250
+ <rect x="36" y="44" width="78" height="28" rx="4" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1" />
4251
+ <rect x="40" y="48" width="24" height="3" rx="1.5" fill="#1e293b" />
4252
+ <rect x="40" y="54" width="70" height="2" rx="1" fill="#94a3b8" />
4253
+ <rect x="40" y="60" width="70" height="2" rx="1" fill="#94a3b8" />
4254
+ </svg>
4255
+ );
4256
+
4257
+ const MatrixPreview = () => (
4258
+ <svg viewBox="0 0 120 80" className="w-full h-full">
4259
+ {/* Background with grid */}
4260
+ <rect width="120" height="80" fill="#0a0a0a" />
4261
+ <defs>
4262
+ <pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse">
4263
+ <path d="M 10 0 L 0 0 0 10" fill="none" stroke="#00ff88" strokeWidth="0.2" strokeOpacity="0.1" />
4264
+ </pattern>
4265
+ </defs>
4266
+ <rect width="120" height="80" fill="url(#grid)" />
4267
+ {/* Sidebar */}
4268
+ <rect x="0" y="0" width="30" height="80" fill="#050505" />
4269
+ <line x1="30" y1="0" x2="30" y2="80" stroke="#00ff88" strokeWidth="0.5" strokeOpacity="0.3" />
4270
+ <rect x="0" y="8" width="2" height="6" fill="#00ff88" />
4271
+ <rect x="6" y="9" width="20" height="4" fill="#00ff88" fillOpacity="0.2" />
4272
+ <text x="8" y="12.5" fill="#00ff88" fontSize="3" fontFamily="monospace">&gt; MENU</text>
4273
+ <rect x="6" y="16" width="20" height="3" fill="#333" />
4274
+ <rect x="6" y="22" width="20" height="3" fill="#333" />
4275
+ <rect x="6" y="28" width="20" height="3" fill="#333" />
4276
+ {/* Cards */}
4277
+ <rect x="36" y="8" width="38" height="28" fill="#0d0d0d" stroke="#00ff88" strokeWidth="0.5" strokeOpacity="0.3" />
4278
+ <line x1="36" y1="8" x2="74" y2="8" stroke="#00ff88" strokeWidth="1" strokeOpacity="0.5" />
4279
+ <rect x="40" y="14" width="20" height="3" fill="#e0e0e0" />
4280
+ <rect x="40" y="20" width="30" height="2" fill="#555" />
4281
+ <rect x="40" y="26" width="30" height="4" fill="#1a1a1a" stroke="#333" strokeWidth="0.5" />
4282
+ <rect x="40" y="26" width="18" height="4" fill="#00ff88" />
4283
+ <rect x="80" y="8" width="34" height="28" fill="#0d0d0d" stroke="#00ff88" strokeWidth="0.5" strokeOpacity="0.3" />
4284
+ <line x1="80" y1="8" x2="114" y2="8" stroke="#00ff88" strokeWidth="1" strokeOpacity="0.5" />
4285
+ <rect x="84" y="14" width="16" height="3" fill="#e0e0e0" />
4286
+ <rect x="84" y="20" width="26" height="2" fill="#555" />
4287
+ {/* Bottom card */}
4288
+ <rect x="36" y="44" width="78" height="28" fill="#0d0d0d" stroke="#00ff88" strokeWidth="0.5" strokeOpacity="0.3" />
4289
+ <line x1="36" y1="44" x2="114" y2="44" stroke="#00ff88" strokeWidth="1" strokeOpacity="0.5" />
4290
+ <rect x="40" y="50" width="24" height="3" fill="#e0e0e0" />
4291
+ <rect x="40" y="56" width="70" height="2" fill="#555" />
4292
+ <rect x="40" y="62" width="70" height="2" fill="#555" />
4293
+ </svg>
4294
+ );
4295
+
4296
+ const themeOptions = [
4297
+ {
4298
+ id: 'glass',
4299
+ name: 'Glass',
4300
+ description: language === 'es' ? 'Interfaz moderna y limpia' : 'Modern and clean interface',
4301
+ preview: GlassPreview
4302
+ },
4303
+ {
4304
+ id: 'matrix',
4305
+ name: 'Matrix',
4306
+ description: language === 'es' ? 'Estética cyberpunk terminal' : 'Cyberpunk terminal aesthetic',
4307
+ preview: MatrixPreview
4308
+ }
4309
+ ];
4310
+
4311
+ return (
4312
+ <div className="theme-card p-6">
4313
+ <div className="flex items-center gap-3 mb-6">
4314
+ <div className="w-10 h-10 rounded-theme-md flex items-center justify-center" style={{ background: 'var(--accent-primary)', opacity: 0.15 }}>
4315
+ <Palette className="w-5 h-5" style={{ color: 'var(--accent-primary)' }} />
4316
+ </div>
4317
+ <div>
4318
+ <h3 className="font-heading text-lg" style={{ color: 'var(--text-primary)' }}>
4319
+ {language === 'es' ? 'Apariencia' : 'Appearance'}
4320
+ </h3>
4321
+ <p className="text-sm" style={{ color: 'var(--text-muted)' }}>
4322
+ {language === 'es' ? 'Personaliza el aspecto del dashboard' : 'Customize the dashboard appearance'}
4323
+ </p>
4324
+ </div>
4325
+ </div>
4326
+
4327
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
4328
+ {themeOptions.map((themeOpt) => {
4329
+ const isSelected = currentTheme === themeOpt.id;
4330
+ const Preview = themeOpt.preview;
4331
+
4332
+ return (
4333
+ <button
4334
+ key={themeOpt.id}
4335
+ onClick={() => handleThemeChange(themeOpt.id)}
4336
+ disabled={saving}
4337
+ className={`group relative p-4 text-left transition-all rounded-theme-lg ${
4338
+ isSelected
4339
+ ? 'ring-2'
4340
+ : 'hover:ring-1'
4341
+ }`}
4342
+ style={{
4343
+ background: 'var(--bg-card)',
4344
+ border: '1px solid var(--border-color)',
4345
+ ringColor: isSelected ? 'var(--accent-primary)' : 'var(--border-color-strong)'
4346
+ }}
4347
+ >
4348
+ {/* Preview */}
4349
+ <div
4350
+ className="w-full aspect-[3/2] mb-4 overflow-hidden rounded-theme-md"
4351
+ style={{ border: '1px solid var(--border-color)' }}
4352
+ >
4353
+ <Preview />
4354
+ </div>
4355
+
4356
+ {/* Info */}
4357
+ <div className="flex items-center justify-between">
4358
+ <div>
4359
+ <h4 className="font-heading font-medium" style={{ color: 'var(--text-primary)' }}>
4360
+ {themeOpt.name}
4361
+ </h4>
4362
+ <p className="text-xs mt-0.5" style={{ color: 'var(--text-muted)' }}>
4363
+ {themeOpt.description}
4364
+ </p>
4365
+ </div>
4366
+
4367
+ {/* Radio indicator */}
4368
+ <div
4369
+ className={`w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all ${
4370
+ isSelected ? 'border-transparent' : ''
4371
+ }`}
4372
+ style={{
4373
+ borderColor: isSelected ? 'var(--accent-primary)' : 'var(--border-color-strong)',
4374
+ background: isSelected ? 'var(--accent-primary)' : 'transparent'
4375
+ }}
4376
+ >
4377
+ {isSelected && (
4378
+ <Check className="w-3 h-3" style={{ color: 'var(--text-inverse)' }} />
4379
+ )}
4380
+ </div>
4381
+ </div>
4382
+
4383
+ {/* Loading overlay */}
4384
+ {saving && isSelected && (
4385
+ <div className="absolute inset-0 flex items-center justify-center rounded-theme-lg" style={{ background: 'rgba(0,0,0,0.5)' }}>
4386
+ <Loader2 className="w-6 h-6 animate-spin" style={{ color: 'var(--accent-primary)' }} />
4387
+ </div>
4388
+ )}
4389
+ </button>
4390
+ );
4391
+ })}
4392
+ </div>
4393
+
4394
+ {/* Color Mode Toggle */}
4395
+ <div className="mt-6 pt-6" style={{ borderTop: '1px solid var(--border-color)' }}>
4396
+ <div className="flex items-center justify-between">
4397
+ <div className="flex items-center gap-3">
4398
+ {isDark ? (
4399
+ <Moon className="w-5 h-5" style={{ color: 'var(--accent-primary)' }} />
4400
+ ) : (
4401
+ <Sun className="w-5 h-5" style={{ color: 'var(--accent-secondary)' }} />
4402
+ )}
4403
+ <div>
4404
+ <h4 className="font-heading font-medium" style={{ color: 'var(--text-primary)' }}>
4405
+ {language === 'es' ? 'Modo de color' : 'Color Mode'}
4406
+ </h4>
4407
+ <p className="text-xs" style={{ color: 'var(--text-muted)' }}>
4408
+ {language === 'es'
4409
+ ? isDark ? 'Modo oscuro activado' : 'Modo claro activado'
4410
+ : isDark ? 'Dark mode enabled' : 'Light mode enabled'}
4411
+ </p>
4412
+ </div>
4413
+ </div>
4414
+
4415
+ <div className="flex gap-2">
4416
+ <button
4417
+ onClick={() => handleColorModeChange('light')}
4418
+ disabled={savingMode}
4419
+ className={`px-4 py-2 rounded-theme-md transition-all flex items-center gap-2 ${
4420
+ !isDark ? 'ring-2' : ''
4421
+ }`}
4422
+ style={{
4423
+ background: !isDark ? 'var(--accent-primary)' : 'var(--bg-secondary)',
4424
+ color: !isDark ? 'var(--text-inverse)' : 'var(--text-secondary)',
4425
+ ringColor: 'var(--accent-primary)'
4426
+ }}
4427
+ >
4428
+ <Sun className="w-4 h-4" />
4429
+ <span className="text-sm font-medium">{language === 'es' ? 'Claro' : 'Light'}</span>
4430
+ </button>
4431
+ <button
4432
+ onClick={() => handleColorModeChange('dark')}
4433
+ disabled={savingMode}
4434
+ className={`px-4 py-2 rounded-theme-md transition-all flex items-center gap-2 ${
4435
+ isDark ? 'ring-2' : ''
4436
+ }`}
4437
+ style={{
4438
+ background: isDark ? 'var(--accent-primary)' : 'var(--bg-secondary)',
4439
+ color: isDark ? 'var(--text-inverse)' : 'var(--text-secondary)',
4440
+ ringColor: 'var(--accent-primary)'
4441
+ }}
4442
+ >
4443
+ <Moon className="w-4 h-4" />
4444
+ <span className="text-sm font-medium">{language === 'es' ? 'Oscuro' : 'Dark'}</span>
4445
+ </button>
4446
+ </div>
4447
+ </div>
4448
+ </div>
4449
+
4450
+ <p className="text-xs mt-4" style={{ color: 'var(--text-muted)' }}>
4451
+ {language === 'es'
4452
+ ? 'El tema y modo se guardan automáticamente en tu perfil'
4453
+ : 'Theme and mode are automatically saved to your profile'}
4454
+ </p>
4455
+ </div>
4456
+ );
4457
+ }
4458
+
4074
4459
  // ============ SETTINGS TAB ============
4075
4460
  function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfirm, showAlert, t, language, changeLanguage }) {
4076
4461
  const [copiedItem, setCopiedItem] = useState(null);
@@ -4408,6 +4793,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4408
4793
  // Settings sub-tabs configuration
4409
4794
  const settingsTabs = [
4410
4795
  { id: 'profile', label: t('settings.profile'), icon: User, show: !!authState?.user },
4796
+ { id: 'appearance', label: language === 'es' ? 'APARIENCIA' : 'APPEARANCE', icon: Palette, show: true },
4411
4797
  { id: 'users', label: t('settings.users'), icon: Lock, show: isAdmin },
4412
4798
  { id: 'history', label: t('settings.history'), icon: Clock, show: true },
4413
4799
  { id: 'files', label: t('settings.files'), icon: FileCode, show: true },
@@ -4446,7 +4832,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4446
4832
 
4447
4833
  {/* PROFILE TAB */}
4448
4834
  {settingsSubTab === 'profile' && authState?.user && (
4449
- <div className="terminal-card p-5 space-y-5">
4835
+ <div className="theme-card p-5 space-y-5">
4450
4836
  <div className="flex items-center gap-3 mb-2">
4451
4837
  <div className="w-12 h-12 border border-cyber/30 bg-cyber/10 flex items-center justify-center font-display text-cyber text-xl">
4452
4838
  {authState.user.name?.charAt(0).toUpperCase() || 'U'}
@@ -4483,7 +4869,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4483
4869
  type="text"
4484
4870
  value={profileData.name}
4485
4871
  onChange={(e) => setProfileData(prev => ({ ...prev, name: e.target.value }))}
4486
- className="w-full input-terminal px-3 py-2 text-sm"
4872
+ className="w-full theme-input px-3 py-2 text-sm"
4487
4873
  placeholder="Your name"
4488
4874
  />
4489
4875
  </div>
@@ -4493,7 +4879,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4493
4879
  type="email"
4494
4880
  value={profileData.email}
4495
4881
  onChange={(e) => setProfileData(prev => ({ ...prev, email: e.target.value }))}
4496
- className="w-full input-terminal px-3 py-2 text-sm"
4882
+ className="w-full theme-input px-3 py-2 text-sm"
4497
4883
  placeholder="your@email.com"
4498
4884
  />
4499
4885
  </div>
@@ -4508,7 +4894,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4508
4894
  type="password"
4509
4895
  value={profileData.currentPassword}
4510
4896
  onChange={(e) => setProfileData(prev => ({ ...prev, currentPassword: e.target.value }))}
4511
- className="w-full input-terminal px-3 py-2 text-sm"
4897
+ className="w-full theme-input px-3 py-2 text-sm"
4512
4898
  placeholder="Required"
4513
4899
  />
4514
4900
  </div>
@@ -4518,7 +4904,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4518
4904
  type="password"
4519
4905
  value={profileData.newPassword}
4520
4906
  onChange={(e) => setProfileData(prev => ({ ...prev, newPassword: e.target.value }))}
4521
- className="w-full input-terminal px-3 py-2 text-sm"
4907
+ className="w-full theme-input px-3 py-2 text-sm"
4522
4908
  placeholder="Min 6 chars"
4523
4909
  />
4524
4910
  </div>
@@ -4528,7 +4914,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4528
4914
  type="password"
4529
4915
  value={profileData.confirmPassword}
4530
4916
  onChange={(e) => setProfileData(prev => ({ ...prev, confirmPassword: e.target.value }))}
4531
- className="w-full input-terminal px-3 py-2 text-sm"
4917
+ className="w-full theme-input px-3 py-2 text-sm"
4532
4918
  placeholder="Repeat"
4533
4919
  />
4534
4920
  </div>
@@ -4538,7 +4924,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4538
4924
  <button
4539
4925
  onClick={updateProfile}
4540
4926
  disabled={savingProfile}
4541
- className="btn-terminal py-2 px-6 disabled:opacity-50 flex items-center gap-2"
4927
+ className="theme-btn-primary py-2 px-6 disabled:opacity-50 flex items-center gap-2"
4542
4928
  >
4543
4929
  {savingProfile ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
4544
4930
  SAVE CHANGES
@@ -4546,9 +4932,14 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4546
4932
  </div>
4547
4933
  )}
4548
4934
 
4935
+ {/* APPEARANCE TAB */}
4936
+ {settingsSubTab === 'appearance' && (
4937
+ <AppearanceSection language={language} />
4938
+ )}
4939
+
4549
4940
  {/* HISTORY TAB */}
4550
4941
  {settingsSubTab === 'history' && (
4551
- <div className="terminal-card p-5">
4942
+ <div className="theme-card p-5">
4552
4943
  <div className="flex items-center justify-between mb-4">
4553
4944
  <div>
4554
4945
  <h3 className="font-mono text-sm text-white">VERSION HISTORY</h3>
@@ -4559,7 +4950,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4559
4950
  <button
4560
4951
  onClick={loadVersions}
4561
4952
  disabled={loadingVersions}
4562
- className="btn-terminal py-2 px-4 text-xs"
4953
+ className="theme-btn-primary py-2 px-4 text-xs"
4563
4954
  >
4564
4955
  {loadingVersions ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCw className="w-4 h-4" />}
4565
4956
  </button>
@@ -4571,7 +4962,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4571
4962
  <Clock className="w-10 h-10 mx-auto mb-3 text-gray-800" />
4572
4963
  <p className="font-mono text-xs text-gray-600">NO VERSIONS YET</p>
4573
4964
  <p className="font-mono text-[10px] text-gray-700 mt-1">Versions are saved automatically when you save changes</p>
4574
- <button onClick={loadVersions} className="mt-4 btn-terminal py-2 px-4 text-xs">
4965
+ <button onClick={loadVersions} className="mt-4 theme-btn-primary py-2 px-4 text-xs">
4575
4966
  LOAD HISTORY
4576
4967
  </button>
4577
4968
  </div>
@@ -4636,7 +5027,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4636
5027
  <button
4637
5028
  onClick={() => restoreVersion(selectedVersion.id)}
4638
5029
  disabled={restoringVersion}
4639
- className="btn-terminal py-2 px-4 text-xs flex items-center gap-2"
5030
+ className="theme-btn-primary py-2 px-4 text-xs flex items-center gap-2"
4640
5031
  >
4641
5032
  {restoringVersion ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCw className="w-4 h-4" />}
4642
5033
  RESTORE THIS VERSION
@@ -4778,7 +5169,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4778
5169
  {settingsSubTab === 'users' && isAdmin && (
4779
5170
  <div className="space-y-5">
4780
5171
  {/* Auth Settings */}
4781
- <div className="terminal-card p-5">
5172
+ <div className="theme-card p-5">
4782
5173
  <div className="flex items-center justify-between">
4783
5174
  <div>
4784
5175
  <h3 className="font-mono text-sm text-white">Authentication Required</h3>
@@ -4794,7 +5185,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4794
5185
  </div>
4795
5186
 
4796
5187
  {/* Add User */}
4797
- <div className="terminal-card p-5">
5188
+ <div className="theme-card p-5">
4798
5189
  <h3 className="font-mono text-sm text-white mb-4">ADD NEW USER</h3>
4799
5190
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-3">
4800
5191
  <input
@@ -4802,26 +5193,26 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4802
5193
  placeholder="Name *"
4803
5194
  value={newUser.name}
4804
5195
  onChange={(e) => setNewUser(prev => ({ ...prev, name: e.target.value }))}
4805
- className="input-terminal px-3 py-2 text-sm"
5196
+ className="theme-input px-3 py-2 text-sm"
4806
5197
  />
4807
5198
  <input
4808
5199
  type="email"
4809
5200
  placeholder="Email *"
4810
5201
  value={newUser.email}
4811
5202
  onChange={(e) => setNewUser(prev => ({ ...prev, email: e.target.value }))}
4812
- className="input-terminal px-3 py-2 text-sm"
5203
+ className="theme-input px-3 py-2 text-sm"
4813
5204
  />
4814
5205
  <input
4815
5206
  type="password"
4816
5207
  placeholder="Password *"
4817
5208
  value={newUser.password}
4818
5209
  onChange={(e) => setNewUser(prev => ({ ...prev, password: e.target.value }))}
4819
- className="input-terminal px-3 py-2 text-sm"
5210
+ className="theme-input px-3 py-2 text-sm"
4820
5211
  />
4821
5212
  <select
4822
5213
  value={newUser.role}
4823
5214
  onChange={(e) => setNewUser(prev => ({ ...prev, role: e.target.value }))}
4824
- className="input-terminal px-3 py-2 text-sm"
5215
+ className="theme-input px-3 py-2 text-sm"
4825
5216
  >
4826
5217
  <option value="member">Member</option>
4827
5218
  <option value="admin">Admin</option>
@@ -4835,14 +5226,14 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4835
5226
  <button
4836
5227
  onClick={createUser}
4837
5228
  disabled={!newUser.name.trim() || !newUser.email.trim() || !newUser.password.trim()}
4838
- className="btn-terminal py-2 px-4 disabled:opacity-50"
5229
+ className="theme-btn-primary py-2 px-4 disabled:opacity-50"
4839
5230
  >
4840
5231
  <Plus className="w-4 h-4 inline mr-1" /> CREATE USER
4841
5232
  </button>
4842
5233
  </div>
4843
5234
 
4844
5235
  {/* Users List */}
4845
- <div className="terminal-card p-5">
5236
+ <div className="theme-card p-5">
4846
5237
  <h3 className="font-mono text-sm text-white mb-4">REGISTERED USERS ({users.length})</h3>
4847
5238
  {loadingUsers ? (
4848
5239
  <div className="py-8 text-center">
@@ -4895,9 +5286,9 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4895
5286
  {settingsSubTab === 'files' && (
4896
5287
  <div className="space-y-5">
4897
5288
  {/* Deploy */}
4898
- <div className="terminal-card p-5">
5289
+ <div className="theme-card p-5">
4899
5290
  <div className="flex items-center gap-3 mb-4">
4900
- <div className="led led-green" />
5291
+ <div className="led theme-led theme-led-success" />
4901
5292
  <div>
4902
5293
  <h3 className="font-mono text-sm text-matrix tracking-wider">DEPLOY CONFIG</h3>
4903
5294
  <p className="font-mono text-[10px] text-gray-600">Copy files to project root</p>
@@ -4920,7 +5311,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4920
5311
  Also create .cursorrules (for Cursor IDE)
4921
5312
  </label>
4922
5313
 
4923
- <button onClick={deployToProject} disabled={deploying} className="btn-terminal flex items-center gap-2">
5314
+ <button onClick={deployToProject} disabled={deploying} className="theme-btn-primary flex items-center gap-2">
4924
5315
  {deploying ? <Loader2 className="w-4 h-4 animate-spin" /> : <Rocket className="w-4 h-4" />}
4925
5316
  DEPLOY FILES
4926
5317
  </button>
@@ -4942,7 +5333,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4942
5333
  </div>
4943
5334
 
4944
5335
  {/* .clinerules */}
4945
- <div className="terminal-card">
5336
+ <div className="theme-card">
4946
5337
  <button
4947
5338
  onClick={() => setClineruleExpanded(!clineruleExpanded)}
4948
5339
  className="w-full p-4 flex items-center justify-between hover:bg-white/[0.01] transition-colors"
@@ -4978,7 +5369,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4978
5369
  <textarea
4979
5370
  value={clinerules}
4980
5371
  onChange={(e) => setClinerules(e.target.value)}
4981
- className="w-full h-[400px] input-terminal p-4 text-xs resize-none"
5372
+ className="w-full h-[400px] theme-input p-4 text-xs resize-none"
4982
5373
  spellCheck={false}
4983
5374
  />
4984
5375
  ) : (
@@ -4991,7 +5382,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
4991
5382
  </div>
4992
5383
 
4993
5384
  {/* roadmap.json */}
4994
- <div className="terminal-card">
5385
+ <div className="theme-card">
4995
5386
  <button
4996
5387
  onClick={() => setJsonExpanded(!jsonExpanded)}
4997
5388
  className="w-full p-4 flex items-center justify-between hover:bg-white/[0.01] transition-colors"
@@ -5051,7 +5442,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
5051
5442
  <textarea
5052
5443
  value={jsonContent}
5053
5444
  onChange={(e) => { setJsonContent(e.target.value); setJsonError(null); }}
5054
- className="w-full h-[400px] input-terminal p-4 text-xs resize-none"
5445
+ className="w-full h-[400px] theme-input p-4 text-xs resize-none"
5055
5446
  spellCheck={false}
5056
5447
  />
5057
5448
  <p className="mt-2 font-mono text-[10px] text-gray-600">
@@ -5071,7 +5462,7 @@ function SettingsTab({ roadmap, setRoadmap, setHasChanges, authState, showConfir
5071
5462
 
5072
5463
  {/* LANGUAGE TAB */}
5073
5464
  {settingsSubTab === 'language' && (
5074
- <div className="terminal-card p-5">
5465
+ <div className="theme-card p-5">
5075
5466
  <h3 className="font-mono text-sm text-white mb-2">{t('settings.language')}</h3>
5076
5467
  <p className="font-mono text-[10px] text-gray-600 mb-6">
5077
5468
  {language === 'es' ? 'Selecciona el idioma de la interfaz' : 'Select interface language'}
@@ -5188,7 +5579,7 @@ function HelpTab({ t, language }) {
5188
5579
  {/* Templates */}
5189
5580
  {activeSection === 'templates' && (
5190
5581
  <div className="space-y-6">
5191
- <div className="terminal-card p-5">
5582
+ <div className="theme-card p-5">
5192
5583
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4">{t('help.referenceFiles')}</h3>
5193
5584
  <p className="font-mono text-[11px] text-gray-500 mb-4">{t('help.sharePaths')}</p>
5194
5585
  <div className="space-y-2">
@@ -5212,7 +5603,7 @@ function HelpTab({ t, language }) {
5212
5603
  </div>
5213
5604
  </div>
5214
5605
 
5215
- <div className="terminal-card p-5">
5606
+ <div className="theme-card p-5">
5216
5607
  <h3 className="font-mono text-sm text-cyber tracking-wider mb-4">{t('help.aiInstructions')}</h3>
5217
5608
  <div className="bg-void-100 border border-white/5 p-4 font-mono text-[11px] text-gray-400 overflow-x-auto">
5218
5609
  <pre className="whitespace-pre-wrap">{`Read the example files in:
@@ -5247,7 +5638,7 @@ Then generate a roadmap.json for my project following this structure:
5247
5638
  </div>
5248
5639
  </div>
5249
5640
 
5250
- <div className="terminal-card p-5 border-matrix/20">
5641
+ <div className="theme-card p-5 border-matrix/20">
5251
5642
  <div className="flex items-center justify-between mb-3">
5252
5643
  <h4 className="font-mono text-sm text-matrix">{t('help.quickPrompt')}</h4>
5253
5644
  <button
@@ -5276,7 +5667,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5276
5667
  {/* Commits */}
5277
5668
  {activeSection === 'commits' && (
5278
5669
  <div className="space-y-6">
5279
- <div className="terminal-card p-5">
5670
+ <div className="theme-card p-5">
5280
5671
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4">{t('help.commitFormat')}</h3>
5281
5672
  <p className="font-mono text-[11px] text-gray-500 mb-4">{t('help.commitFormatDesc')}</p>
5282
5673
  <div className="bg-void-100 border border-white/5 p-4 mb-6">
@@ -5314,7 +5705,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5314
5705
  </div>
5315
5706
  </div>
5316
5707
 
5317
- <div className="terminal-card p-5">
5708
+ <div className="theme-card p-5">
5318
5709
  <h4 className="font-mono text-xs text-gray-400 mb-4">{t('help.examples')}</h4>
5319
5710
  <div className="space-y-3">
5320
5711
  {[
@@ -5330,7 +5721,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5330
5721
  </div>
5331
5722
  </div>
5332
5723
 
5333
- <div className="terminal-card p-5 border-cyber/20">
5724
+ <div className="theme-card p-5 border-cyber/20">
5334
5725
  <h4 className="font-mono text-sm text-cyber tracking-wider mb-3">{t('help.syncWithGit')}</h4>
5335
5726
  <p className="font-mono text-[11px] text-gray-500 mb-3">{t('help.afterCommits')}</p>
5336
5727
  <div className="bg-void-100 border border-white/5 p-3">
@@ -5346,7 +5737,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5346
5737
  {/* AI Workflow */}
5347
5738
  {activeSection === 'ai' && (
5348
5739
  <div className="space-y-6">
5349
- <div className="terminal-card p-5">
5740
+ <div className="theme-card p-5">
5350
5741
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4">{t('help.recommendedWorkflow')}</h3>
5351
5742
  <div className="space-y-2">
5352
5743
  {[
@@ -5363,7 +5754,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5363
5754
  </div>
5364
5755
 
5365
5756
  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
5366
- <div className="terminal-card p-5 border-matrix/20">
5757
+ <div className="theme-card p-5 border-matrix/20">
5367
5758
  <h4 className="font-mono text-xs text-matrix tracking-wider mb-4 flex items-center gap-2">
5368
5759
  <CheckCircle2 className="w-4 h-4" /> {t('help.aiMustDo')}
5369
5760
  </h4>
@@ -5376,7 +5767,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5376
5767
  </ul>
5377
5768
  </div>
5378
5769
 
5379
- <div className="terminal-card p-5 border-alert/20">
5770
+ <div className="theme-card p-5 border-alert/20">
5380
5771
  <h4 className="font-mono text-xs text-alert tracking-wider mb-4 flex items-center gap-2">
5381
5772
  <X className="w-4 h-4" /> {t('help.aiMustNot')}
5382
5773
  </h4>
@@ -5395,7 +5786,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5395
5786
  {/* Troubleshooting */}
5396
5787
  {activeSection === 'troubleshooting' && (
5397
5788
  <div className="space-y-4">
5398
- <div className="terminal-card p-5">
5789
+ <div className="theme-card p-5">
5399
5790
  <h3 className="font-mono text-sm text-signal tracking-wider mb-4">{t('help.troubleshooting')}</h3>
5400
5791
  <div className="space-y-4">
5401
5792
  {[
@@ -5415,7 +5806,7 @@ Then help me create/improve the roadmap.json for my project following that forma
5415
5806
  </div>
5416
5807
  </div>
5417
5808
 
5418
- <div className="terminal-card p-5">
5809
+ <div className="theme-card p-5">
5419
5810
  <h4 className="font-mono text-xs text-gray-400 mb-4">{t('help.fileSummary')}</h4>
5420
5811
  <div className="overflow-x-auto">
5421
5812
  <table className="w-full font-mono text-[11px]">
@@ -5716,7 +6107,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5716
6107
  return (
5717
6108
  <div className="space-y-6 animate-fade-in">
5718
6109
  {/* Setup Complete Header */}
5719
- <div className="terminal-card p-8 border-matrix/50 text-center">
6110
+ <div className="theme-card p-8 border-matrix/50 text-center">
5720
6111
  <div className="w-20 h-20 mx-auto border-2 border-matrix/50 flex items-center justify-center mb-6 glow-matrix">
5721
6112
  <CheckCircle2 className="w-10 h-10 text-matrix" />
5722
6113
  </div>
@@ -5729,7 +6120,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5729
6120
  </div>
5730
6121
 
5731
6122
  {/* Roadmap Status Card */}
5732
- <div className="terminal-card p-5">
6123
+ <div className="theme-card p-5">
5733
6124
  <h3 className="font-mono text-sm text-white tracking-wider mb-4">
5734
6125
  {t ? t('setup.roadmapStatus') : 'ROADMAP STATUS'}
5735
6126
  </h3>
@@ -5772,7 +6163,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5772
6163
  <div className="flex gap-3">
5773
6164
  <button
5774
6165
  onClick={() => window.location.hash = '#features'}
5775
- className="btn-terminal flex-1 py-3 flex items-center justify-center gap-2"
6166
+ className="theme-btn-primary flex-1 py-3 flex items-center justify-center gap-2"
5776
6167
  >
5777
6168
  <Zap className="w-4 h-4" />
5778
6169
  {t ? t('setup.goToDashboard') : 'GO TO DASHBOARD'}
@@ -5788,7 +6179,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5788
6179
 
5789
6180
  {/* Project Info Summary */}
5790
6181
  {roadmap?.project_info && (
5791
- <div className="terminal-card p-5">
6182
+ <div className="theme-card p-5">
5792
6183
  <h3 className="font-mono text-sm text-cyber tracking-wider mb-4"># {roadmap.project_info.name || 'PROJECT'}</h3>
5793
6184
  {roadmap.project_info.description && (
5794
6185
  <p className="font-mono text-xs text-gray-400 mb-4">{roadmap.project_info.description}</p>
@@ -5811,7 +6202,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5811
6202
  return (
5812
6203
  <div className="space-y-6 animate-fade-in">
5813
6204
  {/* Header */}
5814
- <div className="terminal-card p-5 border-matrix/30">
6205
+ <div className="theme-card p-5 border-matrix/30">
5815
6206
  <div className="flex items-center gap-4">
5816
6207
  <div className="w-14 h-14 border border-matrix/50 flex items-center justify-center glow-matrix">
5817
6208
  <Sparkles className="w-7 h-7 text-matrix" />
@@ -5864,7 +6255,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5864
6255
  {/* Step 1: Choose Connection Mode */}
5865
6256
  {activeStep === 1 && (
5866
6257
  <div className="space-y-4">
5867
- <div className="terminal-card p-6">
6258
+ <div className="theme-card p-6">
5868
6259
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4"># {t ? t('setup.chooseConnection') : 'CHOOSE CONNECTION MODE'}</h3>
5869
6260
  <p className="font-mono text-xs text-gray-500 mb-6">
5870
6261
  {t ? t('setup.chooseConnectionDesc') : 'Choose how to connect with Claude to generate your project configuration.'}
@@ -5881,7 +6272,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5881
6272
  }`}
5882
6273
  >
5883
6274
  <div className="flex items-center gap-3 mb-3">
5884
- <div className={`led ${claudeCodeStatus.available ? 'led-green' : claudeCodeStatus.checking ? 'led-amber' : 'led-red'}`} />
6275
+ <div className={`led ${claudeCodeStatus.available ? 'theme-led theme-led-success' : claudeCodeStatus.checking ? 'theme-led theme-led-warning' : 'theme-led theme-led-danger'}`} />
5885
6276
  <span className="font-mono text-sm text-white">CLAUDE CODE</span>
5886
6277
  <span className="font-mono text-[9px] px-2 py-0.5 bg-matrix/20 text-matrix border border-matrix/30">
5887
6278
  {t ? t('setup.recommended') : 'RECOMMENDED'}
@@ -5918,7 +6309,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5918
6309
  }`}
5919
6310
  >
5920
6311
  <div className="flex items-center gap-3 mb-3">
5921
- <div className={`led ${apiKeyStatus.hasKey ? 'led-green' : 'led-gray'}`} />
6312
+ <div className={`led ${apiKeyStatus.hasKey ? 'theme-led theme-led-success' : 'led-gray'}`} />
5922
6313
  <span className="font-mono text-sm text-white">API KEY</span>
5923
6314
  </div>
5924
6315
  <p className="font-mono text-[11px] text-gray-500 mb-3">
@@ -5941,7 +6332,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5941
6332
 
5942
6333
  {/* Claude Code selected but not available */}
5943
6334
  {generationMode === 'claude-code' && !claudeCodeStatus.checking && !claudeCodeStatus.available && (
5944
- <div className="terminal-card p-5 border-signal/30">
6335
+ <div className="theme-card p-5 border-signal/30">
5945
6336
  <h4 className="font-mono text-xs text-signal tracking-wider mb-3">INSTALAR CLAUDE CODE</h4>
5946
6337
  <p className="font-mono text-[11px] text-gray-500 mb-4">
5947
6338
  Para usar tu suscripción, necesitas tener Claude Code instalado y autenticado.
@@ -5965,7 +6356,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5965
6356
 
5966
6357
  {/* API mode selected - show key input */}
5967
6358
  {generationMode === 'api' && (
5968
- <div className="terminal-card p-5">
6359
+ <div className="theme-card p-5">
5969
6360
  <h4 className="font-mono text-xs text-cyber tracking-wider mb-3">CONFIGURAR API KEY</h4>
5970
6361
  <p className="font-mono text-[11px] text-gray-500 mb-4">
5971
6362
  Obtén una API key en{' '}
@@ -5981,7 +6372,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5981
6372
  <span className="text-matrix">{apiKeyStatus.maskedKey}</span>
5982
6373
  </div>
5983
6374
  <div className="flex gap-3">
5984
- <button onClick={() => setActiveStep(2)} className="btn-terminal flex-1">
6375
+ <button onClick={() => setActiveStep(2)} className="theme-btn-primary flex-1">
5985
6376
  CONTINUE →
5986
6377
  </button>
5987
6378
  <button
@@ -5999,12 +6390,12 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
5999
6390
  placeholder="sk-ant-api03-..."
6000
6391
  value={apiKey}
6001
6392
  onChange={(e) => setApiKey(e.target.value)}
6002
- className="input-terminal w-full px-4 py-3 text-sm"
6393
+ className="theme-input w-full px-4 py-3 text-sm"
6003
6394
  />
6004
6395
  <button
6005
6396
  onClick={saveApiKey}
6006
6397
  disabled={!apiKey.trim()}
6007
- className="btn-terminal w-full py-3 disabled:opacity-50"
6398
+ className="theme-btn-primary w-full py-3 disabled:opacity-50"
6008
6399
  >
6009
6400
  SAVE API KEY
6010
6401
  </button>
@@ -6015,7 +6406,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6015
6406
 
6016
6407
  {/* Continue button for Claude Code mode */}
6017
6408
  {generationMode === 'claude-code' && claudeCodeStatus.available && (
6018
- <button onClick={() => setActiveStep(2)} className="btn-terminal w-full py-4">
6409
+ <button onClick={() => setActiveStep(2)} className="theme-btn-primary w-full py-4">
6019
6410
  CONTINUE WITH CLAUDE CODE →
6020
6411
  </button>
6021
6412
  )}
@@ -6027,7 +6418,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6027
6418
  <div className="space-y-4">
6028
6419
  {/* Roadmap Validation Status */}
6029
6420
  {hasExistingRoadmap && (
6030
- <div className={`terminal-card p-5 ${validateRoadmap.valid ? 'border-matrix/50' : validateRoadmap.issues.length > 0 ? 'border-alert/30' : 'border-signal/30'}`}>
6421
+ <div className={`theme-card p-5 ${validateRoadmap.valid ? 'border-matrix/50' : validateRoadmap.issues.length > 0 ? 'border-alert/30' : 'border-signal/30'}`}>
6031
6422
  <div className="flex items-start gap-4">
6032
6423
  <div className={`w-12 h-12 border flex items-center justify-center ${
6033
6424
  validateRoadmap.valid ? 'border-matrix/50 bg-matrix/10' :
@@ -6105,7 +6496,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6105
6496
  <div className="flex gap-3">
6106
6497
  <button
6107
6498
  onClick={() => setActiveStep(4)}
6108
- className="btn-terminal px-6 py-2 flex items-center gap-2"
6499
+ className="theme-btn-primary px-6 py-2 flex items-center gap-2"
6109
6500
  >
6110
6501
  <CheckCircle2 className="w-4 h-4" />
6111
6502
  CONTINUE TO DASHBOARD
@@ -6149,10 +6540,13 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6149
6540
  )}
6150
6541
 
6151
6542
  {/* Project Scan Results */}
6152
- <div className="terminal-card">
6153
- <button
6543
+ <div className="theme-card">
6544
+ <div
6154
6545
  onClick={() => setScanExpanded(!scanExpanded)}
6155
- className="w-full p-4 flex items-center justify-between hover:bg-white/[0.01] transition-colors"
6546
+ className="w-full p-4 flex items-center justify-between hover:bg-white/[0.01] transition-colors cursor-pointer"
6547
+ role="button"
6548
+ tabIndex={0}
6549
+ onKeyDown={(e) => e.key === 'Enter' && setScanExpanded(!scanExpanded)}
6156
6550
  >
6157
6551
  <div className="flex items-center gap-3">
6158
6552
  <FolderOpen className="w-4 h-4 text-cyber" />
@@ -6173,7 +6567,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6173
6567
  </button>
6174
6568
  <ChevronDown className={`w-4 h-4 text-gray-600 transition-transform ${scanExpanded ? 'rotate-180' : ''}`} />
6175
6569
  </div>
6176
- </button>
6570
+ </div>
6177
6571
 
6178
6572
  {scanExpanded && projectScan && (
6179
6573
  <div className="px-4 pb-4 border-t border-white/5">
@@ -6229,7 +6623,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6229
6623
  </div>
6230
6624
 
6231
6625
  {/* Requirements Input */}
6232
- <div className="terminal-card p-6">
6626
+ <div className="theme-card p-6">
6233
6627
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-2"># REQUIREMENTS</h3>
6234
6628
  <p className="font-mono text-[10px] text-gray-500 mb-4">
6235
6629
  Describe las características, funcionalidades o mejoras que quieres implementar. Claude analizará tu proyecto y generará un roadmap estructurado.
@@ -6247,13 +6641,13 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6247
6641
  value={requirements}
6248
6642
  onChange={(e) => setRequirements(e.target.value)}
6249
6643
  rows={10}
6250
- className="input-terminal w-full px-4 py-3 text-sm resize-none mb-4"
6644
+ className="theme-input w-full px-4 py-3 text-sm resize-none mb-4"
6251
6645
  />
6252
6646
 
6253
6647
  <button
6254
6648
  onClick={analyzeWithAI}
6255
6649
  disabled={generating || !requirements.trim()}
6256
- className="btn-terminal w-full py-3 flex items-center justify-center gap-2 disabled:opacity-50"
6650
+ className="theme-btn-primary w-full py-3 flex items-center justify-center gap-2 disabled:opacity-50"
6257
6651
  >
6258
6652
  {generating ? (
6259
6653
  <>
@@ -6280,7 +6674,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6280
6674
  <div className="space-y-4">
6281
6675
  {/* Analysis Summary */}
6282
6676
  {generatedResult.analysis && (
6283
- <div className="terminal-card p-4 border-cyber/30">
6677
+ <div className="theme-card p-4 border-cyber/30">
6284
6678
  <h4 className="font-mono text-xs text-cyber tracking-wider mb-3 flex items-center gap-2">
6285
6679
  <Info className="w-4 h-4" /> ANALYSIS SUMMARY
6286
6680
  </h4>
@@ -6312,7 +6706,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6312
6706
  </div>
6313
6707
  )}
6314
6708
 
6315
- <div className="terminal-card p-6">
6709
+ <div className="theme-card p-6">
6316
6710
  <h3 className="font-mono text-sm text-matrix tracking-wider mb-4"># GENERATED ROADMAP</h3>
6317
6711
 
6318
6712
  <div className="grid grid-cols-2 gap-4 mb-6">
@@ -6373,14 +6767,14 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6373
6767
  <button onClick={() => setActiveStep(2)} className="px-4 py-2 border border-white/10 text-gray-500 font-mono text-xs hover:text-white transition-all">
6374
6768
  ← BACK
6375
6769
  </button>
6376
- <button onClick={applyGenerated} className="btn-terminal flex-1 py-3">
6770
+ <button onClick={applyGenerated} className="theme-btn-primary flex-1 py-3">
6377
6771
  APPLY & DEPLOY
6378
6772
  </button>
6379
6773
  </div>
6380
6774
  </div>
6381
6775
 
6382
6776
  {/* JSON Preview */}
6383
- <div className="terminal-card p-4">
6777
+ <div className="theme-card p-4">
6384
6778
  <details>
6385
6779
  <summary className="font-mono text-xs text-gray-500 cursor-pointer hover:text-white">
6386
6780
  VIEW GENERATED JSON
@@ -6395,7 +6789,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6395
6789
 
6396
6790
  {/* Step 4: Complete */}
6397
6791
  {activeStep === 4 && (
6398
- <div className="terminal-card p-8 text-center">
6792
+ <div className="theme-card p-8 text-center">
6399
6793
  <div className="w-20 h-20 mx-auto mb-6 border-2 border-matrix flex items-center justify-center glow-matrix">
6400
6794
  <CheckCircle2 className="w-10 h-10 text-matrix" />
6401
6795
  </div>
@@ -6407,7 +6801,7 @@ function SetupTab({ roadmap, setRoadmap, setHasChanges, loadRoadmap, t, language
6407
6801
  <button onClick={() => { setActiveStep(1); setGeneratedResult(null); }} className="px-4 py-2 border border-white/10 text-gray-500 font-mono text-xs hover:text-white transition-all">
6408
6802
  START OVER
6409
6803
  </button>
6410
- <button onClick={() => window.location.reload()} className="btn-terminal px-6 py-2">
6804
+ <button onClick={() => window.location.reload()} className="theme-btn-primary px-6 py-2">
6411
6805
  VIEW DASHBOARD
6412
6806
  </button>
6413
6807
  </div>
@@ -6445,7 +6839,7 @@ function AddTaskForm({ onAdd, onCancel, team = [], t, language }) {
6445
6839
  placeholder={t ? t('features.taskName') : "Task name"}
6446
6840
  value={name}
6447
6841
  onChange={(e) => setName(e.target.value)}
6448
- className="input-terminal w-full px-3 py-2 text-sm"
6842
+ className="theme-input w-full px-3 py-2 text-sm"
6449
6843
  autoFocus
6450
6844
  />
6451
6845
  <textarea
@@ -6453,10 +6847,10 @@ function AddTaskForm({ onAdd, onCancel, team = [], t, language }) {
6453
6847
  value={description}
6454
6848
  onChange={(e) => setDescription(e.target.value)}
6455
6849
  rows={2}
6456
- className="input-terminal w-full px-3 py-2 text-sm resize-none"
6850
+ className="theme-input w-full px-3 py-2 text-sm resize-none"
6457
6851
  />
6458
6852
  <div className="flex items-center gap-3 flex-wrap">
6459
- <select value={priority} onChange={(e) => setPriority(e.target.value)} className="input-terminal px-3 py-2 text-sm">
6853
+ <select value={priority} onChange={(e) => setPriority(e.target.value)} className="theme-input px-3 py-2 text-sm">
6460
6854
  <option value="high">{t ? t('common.high').toUpperCase() : 'HIGH'}</option>
6461
6855
  <option value="medium">{t ? t('common.medium').toUpperCase() : 'MEDIUM'}</option>
6462
6856
  <option value="low">{t ? t('common.low').toUpperCase() : 'LOW'}</option>
@@ -6465,7 +6859,7 @@ function AddTaskForm({ onAdd, onCancel, team = [], t, language }) {
6465
6859
  <select
6466
6860
  value={assignedTo}
6467
6861
  onChange={(e) => setAssignedTo(e.target.value)}
6468
- className="input-terminal px-3 py-2 text-sm"
6862
+ className="theme-input px-3 py-2 text-sm"
6469
6863
  >
6470
6864
  <option value="">{t ? t('features.unassigned') : 'Unassigned'}</option>
6471
6865
  {team.map(member => (
@@ -6477,7 +6871,7 @@ function AddTaskForm({ onAdd, onCancel, team = [], t, language }) {
6477
6871
  <button type="button" onClick={onCancel} className="px-4 py-2 font-mono text-xs text-gray-500 hover:text-white transition-all">
6478
6872
  {t ? t('common.cancel').toUpperCase() : 'CANCEL'}
6479
6873
  </button>
6480
- <button type="submit" disabled={!name.trim()} className="btn-terminal px-4 py-2 disabled:opacity-50">
6874
+ <button type="submit" disabled={!name.trim()} className="theme-btn-primary px-4 py-2 disabled:opacity-50">
6481
6875
  {t ? t('common.add').toUpperCase() : 'ADD'}
6482
6876
  </button>
6483
6877
  </div>
@@ -6518,7 +6912,7 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6518
6912
  placeholder="e.g. user-auth"
6519
6913
  value={id}
6520
6914
  onChange={(e) => setId(e.target.value)}
6521
- className="input-terminal w-full px-4 py-2.5 mt-2 text-sm"
6915
+ className="theme-input w-full px-4 py-2.5 mt-2 text-sm"
6522
6916
  />
6523
6917
  </div>
6524
6918
  <div>
@@ -6528,7 +6922,7 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6528
6922
  placeholder={t ? t('features.featureName') : "Feature name"}
6529
6923
  value={name}
6530
6924
  onChange={(e) => setName(e.target.value)}
6531
- className="input-terminal w-full px-4 py-2.5 mt-2 text-sm"
6925
+ className="theme-input w-full px-4 py-2.5 mt-2 text-sm"
6532
6926
  autoFocus
6533
6927
  />
6534
6928
  </div>
@@ -6539,12 +6933,12 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6539
6933
  value={description}
6540
6934
  onChange={(e) => setDescription(e.target.value)}
6541
6935
  rows={3}
6542
- className="input-terminal w-full px-4 py-2.5 mt-2 text-sm resize-none"
6936
+ className="theme-input w-full px-4 py-2.5 mt-2 text-sm resize-none"
6543
6937
  />
6544
6938
  </div>
6545
6939
  <div>
6546
6940
  <label className="font-mono text-[10px] text-gray-500 tracking-wider">{t ? t('features.priority').toUpperCase() : 'PRIORITY'}</label>
6547
- <select value={priority} onChange={(e) => setPriority(e.target.value)} className="input-terminal w-full px-4 py-2.5 mt-2 text-sm">
6941
+ <select value={priority} onChange={(e) => setPriority(e.target.value)} className="theme-input w-full px-4 py-2.5 mt-2 text-sm">
6548
6942
  <option value="high">{t ? t('common.high').toUpperCase() : 'HIGH'}</option>
6549
6943
  <option value="medium">{t ? t('common.medium').toUpperCase() : 'MEDIUM'}</option>
6550
6944
  <option value="low">{t ? t('common.low').toUpperCase() : 'LOW'}</option>
@@ -6556,7 +6950,7 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6556
6950
  <select
6557
6951
  value={assignedTo}
6558
6952
  onChange={(e) => setAssignedTo(e.target.value)}
6559
- className="input-terminal w-full px-4 py-2.5 mt-2 text-sm"
6953
+ className="theme-input w-full px-4 py-2.5 mt-2 text-sm"
6560
6954
  >
6561
6955
  <option value="">{t ? t('features.unassigned') : 'Unassigned'}</option>
6562
6956
  {team.map(member => (
@@ -6569,7 +6963,7 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6569
6963
  <button type="button" onClick={onClose} className="flex-1 py-2.5 border border-white/20 text-gray-500 font-mono text-xs hover:bg-white/5 transition-all">
6570
6964
  {t ? t('common.cancel').toUpperCase() : 'CANCEL'}
6571
6965
  </button>
6572
- <button type="submit" disabled={!name.trim()} className="btn-terminal flex-1 py-2.5 disabled:opacity-50">
6966
+ <button type="submit" disabled={!name.trim()} className="theme-btn-primary flex-1 py-2.5 disabled:opacity-50">
6573
6967
  {language === 'es' ? 'CREAR' : 'CREATE'}
6574
6968
  </button>
6575
6969
  </div>
@@ -6581,7 +6975,7 @@ function AddFeatureForm({ onAdd, onClose, team = [], t, language }) {
6581
6975
  function Modal({ children, onClose }) {
6582
6976
  return (
6583
6977
  <div className="fixed inset-0 z-50 flex items-center justify-center p-4 modal-overlay animate-fade-in" onClick={onClose}>
6584
- <div className="terminal-card p-6 max-w-md w-full" onClick={e => e.stopPropagation()}>
6978
+ <div className="theme-card p-6 max-w-md w-full" onClick={e => e.stopPropagation()}>
6585
6979
  {children}
6586
6980
  </div>
6587
6981
  </div>
@@ -6618,7 +7012,7 @@ function ThemeModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
6618
7012
 
6619
7013
  return (
6620
7014
  <div className="fixed inset-0 z-50 flex items-center justify-center p-4 modal-overlay animate-fade-in" onClick={onClose}>
6621
- <div className="terminal-card p-6 max-w-lg w-full" onClick={e => e.stopPropagation()}>
7015
+ <div className="theme-card p-6 max-w-lg w-full" onClick={e => e.stopPropagation()}>
6622
7016
  {/* Header */}
6623
7017
  <div className="flex items-center justify-between mb-6">
6624
7018
  <div className="flex items-center gap-3">
@@ -6683,14 +7077,14 @@ function ThemeModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
6683
7077
  }
6684
7078
  }}
6685
7079
  placeholder="#00ff88"
6686
- className="input-terminal px-3 py-2 text-sm w-32 font-mono"
7080
+ className="theme-input px-3 py-2 text-sm w-32 font-mono"
6687
7081
  />
6688
7082
  <input
6689
7083
  type="text"
6690
7084
  value={currentTheme.name}
6691
7085
  onChange={(e) => updateTheme({ ...currentTheme, name: e.target.value })}
6692
7086
  placeholder="Theme name"
6693
- className="input-terminal px-3 py-2 text-sm flex-1 font-mono"
7087
+ className="theme-input px-3 py-2 text-sm flex-1 font-mono"
6694
7088
  />
6695
7089
  </div>
6696
7090
  </div>
@@ -6707,7 +7101,7 @@ function ThemeModal({ roadmap, setRoadmap, setHasChanges, onClose }) {
6707
7101
  </div>
6708
7102
  <div className="flex-1">
6709
7103
  <div className="font-mono text-xs text-white">{roadmap?.project_info?.name || 'Project'}</div>
6710
- <div className="progress-brutal mt-2 h-2">
7104
+ <div className="theme-progress mt-2 h-2">
6711
7105
  <div
6712
7106
  className="h-full transition-all"
6713
7107
  style={{
@@ -6761,9 +7155,9 @@ function LoginScreen({ onLogin, error }) {
6761
7155
  </div>
6762
7156
 
6763
7157
  {/* Login Form */}
6764
- <div className="terminal-card p-6">
7158
+ <div className="theme-card p-6">
6765
7159
  <div className="flex items-center gap-3 mb-6">
6766
- <div className="led led-amber" />
7160
+ <div className="led theme-led theme-led-warning" />
6767
7161
  <span className="font-mono text-xs text-signal tracking-wider">AUTHENTICATION REQUIRED</span>
6768
7162
  </div>
6769
7163
 
@@ -6777,7 +7171,7 @@ function LoginScreen({ onLogin, error }) {
6777
7171
  value={email}
6778
7172
  onChange={(e) => setEmail(e.target.value)}
6779
7173
  placeholder="admin@localhost"
6780
- className="input-terminal w-full pl-10 pr-4 py-3 text-sm"
7174
+ className="theme-input w-full pl-10 pr-4 py-3 text-sm"
6781
7175
  autoComplete="email"
6782
7176
  autoFocus
6783
7177
  />
@@ -6793,7 +7187,7 @@ function LoginScreen({ onLogin, error }) {
6793
7187
  value={password}
6794
7188
  onChange={(e) => setPassword(e.target.value)}
6795
7189
  placeholder="••••••••"
6796
- className="input-terminal w-full pl-10 pr-4 py-3 text-sm"
7190
+ className="theme-input w-full pl-10 pr-4 py-3 text-sm"
6797
7191
  autoComplete="current-password"
6798
7192
  />
6799
7193
  </div>
@@ -6806,7 +7200,7 @@ function LoginScreen({ onLogin, error }) {
6806
7200
  </div>
6807
7201
  )}
6808
7202
 
6809
- <button type="submit" disabled={loading || !email.trim() || !password.trim()} className="btn-terminal w-full py-3 flex items-center justify-center gap-2 disabled:opacity-50">
7203
+ <button type="submit" disabled={loading || !email.trim() || !password.trim()} className="theme-btn-primary w-full py-3 flex items-center justify-center gap-2 disabled:opacity-50">
6810
7204
  {loading ? (
6811
7205
  <>
6812
7206
  <Loader2 className="w-4 h-4 animate-spin" />
@@ -6968,11 +7362,13 @@ Update \`roadmap.json\` with:
6968
7362
  // Wrap App with providers
6969
7363
  function AppWithProviders() {
6970
7364
  return (
6971
- <ToastProvider>
6972
- <ActivityProvider>
6973
- <App />
6974
- </ActivityProvider>
6975
- </ToastProvider>
7365
+ <ThemeProvider>
7366
+ <ToastProvider>
7367
+ <ActivityProvider>
7368
+ <App />
7369
+ </ActivityProvider>
7370
+ </ToastProvider>
7371
+ </ThemeProvider>
6976
7372
  );
6977
7373
  }
6978
7374