trackops 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +238 -0
  2. package/lib/init.js +2 -2
  3. package/lib/locale.js +41 -17
  4. package/lib/opera-bootstrap.js +68 -7
  5. package/lib/opera.js +10 -2
  6. package/lib/registry.js +18 -0
  7. package/lib/server.js +312 -207
  8. package/locales/en.json +4 -0
  9. package/locales/es.json +4 -0
  10. package/package.json +1 -1
  11. package/skills/trackops/SKILL.md +39 -4
  12. package/skills/trackops/agents/openai.yaml +2 -2
  13. package/skills/trackops/locales/en/SKILL.md +39 -4
  14. package/skills/trackops/locales/en/references/activation.md +15 -0
  15. package/skills/trackops/locales/en/references/troubleshooting.md +12 -0
  16. package/skills/trackops/references/activation.md +15 -0
  17. package/skills/trackops/references/troubleshooting.md +12 -0
  18. package/skills/trackops/skill.json +4 -4
  19. package/ui/css/base.css +19 -1
  20. package/ui/css/charts.css +106 -8
  21. package/ui/css/components.css +554 -17
  22. package/ui/css/onboarding.css +133 -0
  23. package/ui/css/panels.css +345 -406
  24. package/ui/css/terminal.css +125 -0
  25. package/ui/css/timeline.css +58 -0
  26. package/ui/css/tokens.css +170 -113
  27. package/ui/index.html +3 -0
  28. package/ui/js/api.js +49 -13
  29. package/ui/js/app.js +28 -32
  30. package/ui/js/charts.js +526 -0
  31. package/ui/js/filters.js +247 -0
  32. package/ui/js/icons.js +82 -57
  33. package/ui/js/keyboard.js +229 -0
  34. package/ui/js/onboarding.js +33 -42
  35. package/ui/js/router.js +20 -3
  36. package/ui/js/views/board.js +84 -114
  37. package/ui/js/views/dashboard.js +870 -0
  38. package/ui/js/views/projects.js +745 -0
  39. package/ui/js/views/scrum.js +476 -0
  40. package/ui/js/views/settings.js +197 -247
  41. package/ui/js/views/sidebar.js +37 -31
  42. package/ui/js/views/tasks.js +218 -101
  43. package/ui/js/views/timeline.js +265 -0
  44. package/ui/js/views/topbar.js +94 -107
  45. package/ui/app.js +0 -950
  46. package/ui/js/views/insights.js +0 -340
  47. package/ui/js/views/overview.js +0 -369
  48. package/ui/styles.css +0 -688
@@ -0,0 +1,125 @@
1
+ /* ═══════════════════════════════════════════════════════
2
+ TERMINAL — Terminal surface + Console logs panel
3
+ Always-dark styling regardless of theme
4
+ ═══════════════════════════════════════════════════════ */
5
+
6
+ /* ───────────────────────────────────
7
+ TERMINAL GLASS WRAPPER
8
+ ─────────────────────────────────── */
9
+ .terminal-wrapper {
10
+ background: var(--glass-bg-strong);
11
+ backdrop-filter: blur(var(--glass-blur));
12
+ -webkit-backdrop-filter: blur(var(--glass-blur));
13
+ border: 1px solid var(--glass-border);
14
+ border-radius: var(--radius-xl);
15
+ overflow: hidden;
16
+ }
17
+
18
+ /* ───────────────────────────────────
19
+ TERMINAL SURFACE
20
+ ─────────────────────────────────── */
21
+ .terminal-surface {
22
+ background: #060a14;
23
+ border: 1px solid rgba(255,255,255,0.05);
24
+ border-radius: var(--radius-lg);
25
+ overflow: hidden;
26
+ }
27
+ .terminal-header {
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: space-between;
31
+ padding: var(--space-2) var(--space-4);
32
+ background: rgba(255,255,255,0.03);
33
+ border-bottom: 1px solid rgba(255,255,255,0.04);
34
+ gap: var(--space-3);
35
+ }
36
+ .terminal-dots { display: flex; gap: var(--space-2); align-items: center; }
37
+ .terminal-dots span {
38
+ width: 10px; height: 10px;
39
+ border-radius: 50%;
40
+ }
41
+ .terminal-dots span:nth-child(1) { background: #EF4444; }
42
+ .terminal-dots span:nth-child(2) { background: #F59E0B; }
43
+ .terminal-dots span:nth-child(3) { background: #10B981; }
44
+ .terminal-title {
45
+ font-family: var(--font-mono);
46
+ font-size: var(--text-xs);
47
+ color: var(--text-muted);
48
+ flex: 1;
49
+ text-align: center;
50
+ }
51
+ .terminal-output {
52
+ margin: 0;
53
+ padding: var(--space-5);
54
+ font-family: var(--font-mono);
55
+ font-size: var(--text-xs);
56
+ line-height: 1.7;
57
+ color: #94D4BC;
58
+ min-height: 280px;
59
+ max-height: 460px;
60
+ overflow-y: auto;
61
+ white-space: pre-wrap;
62
+ word-break: break-all;
63
+ }
64
+
65
+ /* ───────────────────────────────────
66
+ CONSOLE LOGS PANEL
67
+ ─────────────────────────────────── */
68
+ .console-panel {
69
+ position: fixed;
70
+ bottom: 0;
71
+ left: var(--sidebar-width);
72
+ right: 0;
73
+ z-index: var(--z-panel);
74
+ background: #060a14;
75
+ border-top: 1px solid var(--border);
76
+ transition: transform var(--duration-slow) var(--ease-out);
77
+ transform: translateY(100%);
78
+ }
79
+ .console-panel.is-open {
80
+ transform: translateY(0);
81
+ }
82
+ .console-panel-header {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: space-between;
86
+ padding: var(--space-2) var(--space-4);
87
+ border-bottom: 1px solid rgba(255,255,255,0.04);
88
+ background: rgba(255,255,255,0.02);
89
+ }
90
+ .console-panel-title {
91
+ font-family: var(--font-mono);
92
+ font-size: var(--text-xs);
93
+ color: var(--text-muted);
94
+ display: flex;
95
+ align-items: center;
96
+ gap: var(--space-2);
97
+ }
98
+ .console-panel-actions {
99
+ display: flex;
100
+ gap: var(--space-2);
101
+ }
102
+ .console-logs {
103
+ overflow-y: auto;
104
+ max-height: 220px;
105
+ padding: var(--space-2) 0;
106
+ }
107
+ .console-log-entry {
108
+ display: grid;
109
+ grid-template-columns: auto auto 1fr;
110
+ gap: var(--space-3);
111
+ align-items: start;
112
+ padding: var(--space-1) var(--space-4);
113
+ font-family: var(--font-mono);
114
+ font-size: var(--text-xs);
115
+ line-height: 1.6;
116
+ border-bottom: 1px solid rgba(255,255,255,0.02);
117
+ }
118
+ .console-log-entry:hover { background: rgba(255,255,255,0.02); }
119
+ .console-log-time { color: var(--text-muted); white-space: nowrap; }
120
+ .log-level { font-weight: 700; white-space: nowrap; }
121
+ .log-error { color: var(--danger); }
122
+ .log-warn { color: var(--warning); }
123
+ .log-info { color: var(--info); }
124
+ .log-debug { color: var(--text-muted); }
125
+ .console-log-msg { color: var(--text-secondary); word-break: break-all; }
@@ -0,0 +1,58 @@
1
+ /* ═══════════════════════════════════════════════════════
2
+ TIMELINE — Vista de línea temporal con milestones
3
+ ═══════════════════════════════════════════════════════ */
4
+
5
+ .timeline-container {
6
+ background: var(--glass-bg);
7
+ backdrop-filter: blur(var(--glass-blur));
8
+ -webkit-backdrop-filter: blur(var(--glass-blur));
9
+ border: 1px solid var(--glass-border);
10
+ border-radius: var(--radius-xl);
11
+ padding: var(--space-4);
12
+ overflow: hidden;
13
+ }
14
+
15
+ .timeline-scroll {
16
+ overflow-x: auto;
17
+ overflow-y: visible;
18
+ scrollbar-width: thin;
19
+ scrollbar-color: var(--surface-3) transparent;
20
+ }
21
+
22
+ .timeline-scroll::-webkit-scrollbar {
23
+ height: 8px;
24
+ }
25
+ .timeline-scroll::-webkit-scrollbar-track {
26
+ background: transparent;
27
+ }
28
+ .timeline-scroll::-webkit-scrollbar-thumb {
29
+ background: var(--surface-3);
30
+ border-radius: var(--radius-full);
31
+ }
32
+ .timeline-scroll::-webkit-scrollbar-thumb:hover {
33
+ background: var(--border-strong);
34
+ }
35
+
36
+ .timeline-svg {
37
+ display: block;
38
+ }
39
+
40
+ .timeline-legend {
41
+ padding: var(--space-3) var(--space-4);
42
+ background: var(--glass-bg);
43
+ border: 1px solid var(--glass-border);
44
+ border-radius: var(--radius-lg);
45
+ }
46
+
47
+ /* ───────────────────────────────────
48
+ STATUS BAR COLORS
49
+ ─────────────────────────────────── */
50
+ .timeline-bar.status-pending { fill: var(--accent-blue); }
51
+ .timeline-bar.status-in_progress { fill: var(--accent-cyan); }
52
+ .timeline-bar.status-in_review { fill: var(--accent-yellow); }
53
+ .timeline-bar.status-completed { fill: var(--accent-green); }
54
+ .timeline-bar.status-blocked { fill: var(--accent-red); }
55
+
56
+ .timeline-milestone {
57
+ fill: var(--accent);
58
+ }
package/ui/css/tokens.css CHANGED
@@ -1,62 +1,97 @@
1
1
  /* ═══════════════════════════════════════════════════════
2
- TRACKOPS DESIGN TOKENS
3
- Coherentes con docs/index.html (identidad de marca web)
2
+ PROJECT-OPS DESIGN TOKENS
3
+ Grayscale + Glassmorphism Design System
4
4
  ═══════════════════════════════════════════════════════ */
5
5
 
6
6
  :root {
7
- /* ── Colores base (marca web) ── */
8
- --navy: #0A0F1E;
9
- --navy-90: #0d1326;
10
- --navy-80: #111827;
11
- --slate: #1E293B;
12
- --charcoal: #111111;
13
-
14
- /* ── Accent (indigo) ── */
15
- --accent: #6366F1;
16
- --accent-light: rgba(99, 102, 241, 0.15);
17
- --accent-glow: rgba(99, 102, 241, 0.30);
18
- --accent-hover: #818CF8;
19
-
20
- /* ── Superficies del dashboard ── */
21
- --surface-0: #0A0F1E; /* fondo global */
22
- --surface-1: #0d1326; /* sidebar + panel base */
23
- --surface-2: #111827; /* cards */
24
- --surface-3: #1a2234; /* hover cards */
25
- --surface-4: rgba(255,255,255,0.04); /* inset sutil */
26
-
27
- /* ── Texto ── */
28
- --text-primary: #F1F5F9;
29
- --text-secondary: #94A3B8;
30
- --text-muted: #475569;
31
- --text-accent: #818CF8;
32
-
33
- /* ── Bordes ── */
34
- --border: rgba(255,255,255,0.06);
35
- --border-strong: rgba(255,255,255,0.12);
36
- --border-accent: rgba(99,102,241,0.35);
37
-
38
- /* ── Estado ── */
39
- --success: #10B981;
40
- --success-light: rgba(16, 185, 129, 0.12);
41
- --warning: #F59E0B;
42
- --warning-light: rgba(245, 158, 11, 0.12);
43
- --danger: #EF4444;
44
- --danger-light: rgba(239, 68, 68, 0.12);
45
- --info: #3B82F6;
46
- --info-light: rgba(59, 130, 246, 0.12);
47
-
48
- /* ── Prioridades ── */
49
- --p0: #EF4444;
50
- --p1: #F59E0B;
51
- --p2: #6366F1;
52
- --p3: #475569;
53
-
54
- /* ── Fuentes (coherentes con marca web) ── */
7
+
8
+ /* ── Grayscale Foundation ── */
9
+ --gray-950: #0C0C0E;
10
+ --gray-900: #141416;
11
+ --gray-850: #1A1A1E;
12
+ --gray-800: #222228;
13
+ --gray-700: #2E2E36;
14
+ --gray-600: #3E3E48;
15
+ --gray-500: #5A5A66;
16
+ --gray-400: #8A8A96;
17
+ --gray-300: #B0B0BC;
18
+ --gray-200: #D0D0D8;
19
+ --gray-100: #E8E8EE;
20
+ --gray-50: #F4F4F8;
21
+
22
+ /* ── Data Accent Colors ── */
23
+ --accent-blue: #60A5FA;
24
+ --accent-cyan: #22D3EE;
25
+ --accent-green: #4ADE80;
26
+ --accent-yellow: #FACC15;
27
+ --accent-red: #F87171;
28
+ --accent-purple: #A78BFA;
29
+ --accent-orange: #FB923C;
30
+
31
+ /* ── Surfaces ── */
32
+ --surface-0: var(--gray-900);
33
+ --surface-1: rgba(26, 26, 30, 0.85);
34
+ --surface-2: rgba(34, 34, 40, 0.55);
35
+ --surface-3: rgba(46, 46, 54, 0.65);
36
+ --surface-4: rgba(255, 255, 255, 0.03);
37
+
38
+ /* ── Text ── */
39
+ --text-primary: var(--gray-50);
40
+ --text-secondary: var(--gray-400);
41
+ --text-muted: var(--gray-500);
42
+ --text-accent: var(--accent-blue);
43
+
44
+ /* ── Borders ── */
45
+ --border: rgba(255, 255, 255, 0.06);
46
+ --border-strong: rgba(255, 255, 255, 0.12);
47
+ --border-glass: rgba(255, 255, 255, 0.08);
48
+ --border-accent: rgba(96, 165, 250, 0.35);
49
+
50
+ /* ── Accent ── */
51
+ --accent: var(--accent-blue);
52
+ --accent-light: rgba(96, 165, 250, 0.12);
53
+ --accent-glow: rgba(96, 165, 250, 0.20);
54
+ --accent-hover: #93C5FD;
55
+
56
+ /* ── Status ── */
57
+ --success: var(--accent-green);
58
+ --success-light: rgba(74, 222, 128, 0.12);
59
+ --warning: var(--accent-yellow);
60
+ --warning-light: rgba(250, 204, 21, 0.12);
61
+ --danger: var(--accent-red);
62
+ --danger-light: rgba(248, 113, 113, 0.12);
63
+ --info: var(--accent-cyan);
64
+ --info-light: rgba(34, 211, 238, 0.12);
65
+
66
+ /* ── Priorities ── */
67
+ --p0: var(--accent-red);
68
+ --p1: var(--accent-yellow);
69
+ --p2: var(--accent-blue);
70
+ --p3: var(--gray-500);
71
+
72
+ /* ── Glass Token System ── */
73
+ --glass-blur: 20px;
74
+ --glass-blur-lg: 40px;
75
+ --glass-blur-sm: 12px;
76
+ --glass-bg: rgba(34, 34, 40, 0.55);
77
+ --glass-bg-strong: rgba(34, 34, 40, 0.72);
78
+ --glass-bg-subtle: rgba(34, 34, 40, 0.35);
79
+ --glass-border: rgba(255, 255, 255, 0.08);
80
+ --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.30);
81
+ --glass-inner: inset 0 1px 0 rgba(255, 255, 255, 0.05);
82
+
83
+ --glass-border-hover: rgba(255, 255, 255, 0.14);
84
+
85
+ --bg-gradient: radial-gradient(ellipse 80% 50% at 20% 20%, rgba(90, 90, 120, 0.15), transparent 50%),
86
+ radial-gradient(ellipse 60% 40% at 80% 80%, rgba(60, 60, 80, 0.12), transparent 50%),
87
+ var(--gray-950);
88
+
89
+ /* ── Fonts ── */
55
90
  --font-ui: 'Outfit', system-ui, -apple-system, sans-serif;
56
91
  --font-heading: 'Plus Jakarta Sans', 'Outfit', sans-serif;
57
92
  --font-mono: 'JetBrains Mono', 'Cascadia Code', Consolas, monospace;
58
93
 
59
- /* ── Tamaños de fuente (escala modular 1.25) ── */
94
+ /* ── Typography Scale (modular 1.25) ── */
60
95
  --text-xs: 0.75rem; /* 12px */
61
96
  --text-sm: 0.875rem; /* 14px */
62
97
  --text-base: 1rem; /* 16px */
@@ -66,7 +101,7 @@
66
101
  --text-2xl: 1.875rem; /* 30px */
67
102
  --text-3xl: 2.25rem; /* 36px */
68
103
 
69
- /* ── Border Radius (marca web usa 3rem = super) ── */
104
+ /* ── Border Radius ── */
70
105
  --radius-xs: 0.375rem; /* 6px */
71
106
  --radius-sm: 0.625rem; /* 10px */
72
107
  --radius-md: 0.875rem; /* 14px */
@@ -76,15 +111,15 @@
76
111
  --radius-super: 3rem; /* 48px */
77
112
  --radius-full: 9999px;
78
113
 
79
- /* ── Sombras ── */
80
- --shadow-sm: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
81
- --shadow-md: 0 4px 20px rgba(0,0,0,0.35), 0 2px 8px rgba(0,0,0,0.25);
82
- --shadow-lg: 0 12px 40px rgba(0,0,0,0.4), 0 4px 16px rgba(0,0,0,0.3);
83
- --shadow-xl: 0 24px 60px rgba(0,0,0,0.5), 0 8px 24px rgba(0,0,0,0.35);
84
- --shadow-accent: 0 8px 24px rgba(99,102,241,0.25);
85
- --shadow-glow: 0 0 40px rgba(99,102,241,0.15);
114
+ /* ── Shadows ── */
115
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
116
+ --shadow-md: 0 4px 20px rgba(0,0,0,0.35), 0 2px 8px rgba(0,0,0,0.25);
117
+ --shadow-lg: 0 12px 40px rgba(0,0,0,0.4), 0 4px 16px rgba(0,0,0,0.3);
118
+ --shadow-xl: 0 24px 60px rgba(0,0,0,0.5), 0 8px 24px rgba(0,0,0,0.35);
119
+ --shadow-accent: 0 8px 24px rgba(96,165,250,0.25);
120
+ --shadow-glow: 0 0 40px rgba(96,165,250,0.15);
86
121
 
87
- /* ── Espaciado ── */
122
+ /* ── Spacing ── */
88
123
  --space-1: 0.25rem; /* 4px */
89
124
  --space-2: 0.5rem; /* 8px */
90
125
  --space-3: 0.75rem; /* 12px */
@@ -97,11 +132,13 @@
97
132
  --space-16: 4rem; /* 64px */
98
133
 
99
134
  /* ── Layout ── */
100
- --sidebar-width: 272px;
101
- --topbar-height: 64px;
102
- --content-pad: 24px;
135
+ --sidebar-width: 68px;
136
+ --sidebar-width-collapsed: 68px;
137
+ --sidebar-width-expanded: 240px;
138
+ --topbar-height: 48px;
139
+ --content-pad: 24px;
103
140
 
104
- /* ── Transiciones ── */
141
+ /* ── Transitions ── */
105
142
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
106
143
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
107
144
  --ease-inout: cubic-bezier(0.4, 0, 0.2, 1);
@@ -119,58 +156,76 @@
119
156
  --z-toast: 50;
120
157
  --z-onboard: 60;
121
158
  }
122
- /* ───────────────────────────────────
123
- TEMA CLARO
124
- Activo con: html[data-theme="light"]
125
- ─────────────────────────────────── */
159
+
160
+ /* ═══════════════════════════════════════════════════════
161
+ LIGHT THEME
162
+ Active with: html[data-theme="light"]
163
+ ═══════════════════════════════════════════════════════ */
126
164
  [data-theme="light"] {
127
165
 
128
- /* ── Superficies ── */
129
- --surface-0: #F0F2F8; /* fondo global */
130
- --surface-1: #FFFFFF; /* sidebar + panel base */
131
- --surface-2: #F8F9FC; /* cards */
132
- --surface-3: #EEF0F7; /* hover / inset */
133
- --surface-4: rgba(0,0,0,0.04); /* inset sutil */
134
-
135
- /* ── Texto ── */
136
- --text-primary: #0D1117;
137
- --text-secondary: #4A5568;
138
- --text-muted: #9AA5B4;
139
- --text-accent: #4F46E5;
140
-
141
- /* ── Bordes ── */
142
- --border: rgba(0,0,0,0.08);
143
- --border-strong: rgba(0,0,0,0.14);
144
- --border-accent: rgba(99,102,241,0.3);
145
-
146
- /* ── Sombras (más suaves sobre fondos claros) ── */
166
+ /* ── Surfaces ── */
167
+ --surface-0: #EDEDF3;
168
+ --surface-1: rgba(255, 255, 255, 0.70);
169
+ --surface-2: rgba(255, 255, 255, 0.50);
170
+ --surface-3: rgba(255, 255, 255, 0.65);
171
+ --surface-4: rgba(0, 0, 0, 0.03);
172
+
173
+ /* ── Text ── */
174
+ --text-primary: #111118;
175
+ --text-secondary: #55556A;
176
+ --text-muted: #8888A0;
177
+ --text-accent: #3B82F6;
178
+
179
+ /* ── Borders ── */
180
+ --border: rgba(0, 0, 0, 0.06);
181
+ --border-strong: rgba(0, 0, 0, 0.14);
182
+ --border-glass: rgba(0, 0, 0, 0.08);
183
+ --border-accent: rgba(59, 130, 246, 0.3);
184
+
185
+ /* ── Accent ── */
186
+ --accent: #3B82F6;
187
+ --accent-hover: #60A5FA;
188
+ --accent-light: rgba(59, 130, 246, 0.10);
189
+ --accent-glow: rgba(59, 130, 246, 0.20);
190
+
191
+ /* ── Glass ── */
192
+ --glass-bg: rgba(255, 255, 255, 0.50);
193
+ --glass-bg-strong: rgba(255, 255, 255, 0.70);
194
+ --glass-bg-subtle: rgba(255, 255, 255, 0.35);
195
+ --glass-border: rgba(0, 0, 0, 0.08);
196
+ --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.10);
197
+ --glass-inner: inset 0 1px 0 rgba(255, 255, 255, 0.80);
198
+
199
+ --glass-border-hover: rgba(0, 0, 0, 0.14);
200
+
201
+ --bg-gradient: radial-gradient(ellipse 80% 50% at 20% 20%, rgba(180, 180, 200, 0.15), transparent 50%),
202
+ radial-gradient(ellipse 60% 40% at 80% 80%, rgba(160, 160, 180, 0.10), transparent 50%),
203
+ #EDEDF3;
204
+
205
+ /* ── Shadows (reduced opacity for light backgrounds) ── */
147
206
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.05);
148
207
  --shadow-md: 0 4px 20px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.06);
149
208
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.12), 0 4px 16px rgba(0,0,0,0.08);
150
209
  --shadow-xl: 0 24px 60px rgba(0,0,0,0.15), 0 8px 24px rgba(0,0,0,0.10);
151
- --shadow-accent: 0 8px 24px rgba(99,102,241,0.20);
152
-
153
- /* ── Accent ajustado para legibilidad en claro ── */
154
- --accent: #4F46E5;
155
- --accent-hover: #6366F1;
156
- --accent-light: rgba(79,70,229,0.10);
157
- --accent-glow: rgba(79,70,229,0.20);
158
-
159
- /* ── Estado (más saturados en claro) ── */
160
- --success-light: rgba(5,150,105,0.10);
161
- --warning-light: rgba(217,119,6,0.10);
162
- --danger-light: rgba(220,38,38,0.10);
163
- --info-light: rgba(37,99,235,0.10);
210
+ --shadow-accent: 0 8px 24px rgba(59,130,246,0.20);
211
+
212
+ /* ── Status (light overrides) ── */
213
+ --success-light: rgba(74,222,128,0.10);
214
+ --warning-light: rgba(250,204,21,0.10);
215
+ --danger-light: rgba(248,113,113,0.10);
216
+ --info-light: rgba(34,211,238,0.10);
164
217
  }
165
218
 
166
- /* Ajustes específicos que no se pueden resolver solo con tokens */
219
+ /* ═══════════════════════════════════════════════════════
220
+ LIGHT THEME – Component Overrides
221
+ ═══════════════════════════════════════════════════════ */
167
222
 
168
- /* Topbar en light */
223
+ /* Topbar */
169
224
  [data-theme="light"] .topbar {
170
225
  background: rgba(248,249,252,0.88);
171
226
  }
172
227
 
173
- /* Terminal siempre dark (legibilidad de código) */
228
+ /* Terminal always dark */
174
229
  [data-theme="light"] .terminal-surface,
175
230
  [data-theme="light"] .terminal-output,
176
231
  [data-theme="light"] .console-panel {
@@ -185,41 +240,43 @@
185
240
  background: rgba(255,255,255,0.02);
186
241
  }
187
242
 
188
- /* Time tracker card en light */
243
+ /* Time tracker card */
189
244
  [data-theme="light"] .time-tracker-card {
190
245
  background: linear-gradient(135deg, #f0f2fb 0%, #ffffff 100%);
191
- border-color: rgba(99,102,241,0.2);
246
+ border-color: rgba(96,165,250,0.2);
192
247
  }
193
248
 
194
- /* Onboarding backdrop en light */
249
+ /* Onboarding backdrop */
195
250
  [data-theme="light"] .onboarding-backdrop {
196
251
  background: rgba(0,0,0,0.45);
197
252
  }
198
253
 
199
- /* Sidebar logo icon sigue con gradiente oscuro */
254
+ /* Sidebar logo icon */
200
255
  [data-theme="light"] .sidebar-logo-icon {
201
- box-shadow: 0 4px 12px rgba(79,70,229,0.3);
256
+ box-shadow: 0 4px 12px rgba(59,130,246,0.3);
202
257
  }
203
258
 
204
- /* Topbar timer en light */
259
+ /* Topbar timer */
205
260
  [data-theme="light"] .topbar-timer {
206
- background: #F0F2F8;
261
+ background: #EDEDF3;
207
262
  border-color: rgba(0,0,0,0.10);
208
263
  }
209
264
 
210
- /* Modal en light */
265
+ /* Modal */
211
266
  [data-theme="light"] .modal {
212
267
  background: #FFFFFF;
213
268
  border-color: rgba(0,0,0,0.10);
214
269
  }
215
270
 
216
- /* Flash toast en light */
271
+ /* Flash toast */
217
272
  [data-theme="light"] .flash {
218
273
  background: #FFFFFF;
219
274
  border-color: rgba(0,0,0,0.10);
220
275
  }
221
276
 
222
- /* Transición suave al cambiar de tema */
277
+ /* ═══════════════════════════════════════════════════════
278
+ Theme Transition
279
+ ═══════════════════════════════════════════════════════ */
223
280
  html {
224
281
  transition:
225
282
  background-color var(--duration-slow) var(--ease-out),
package/ui/index.html CHANGED
@@ -27,6 +27,9 @@
27
27
  <link rel="stylesheet" href="/css/components.css" />
28
28
  <link rel="stylesheet" href="/css/panels.css" />
29
29
  <link rel="stylesheet" href="/css/charts.css" />
30
+ <link rel="stylesheet" href="/css/terminal.css" />
31
+ <link rel="stylesheet" href="/css/onboarding.css" />
32
+ <link rel="stylesheet" href="/css/timeline.css" />
30
33
  </head>
31
34
  <body>
32
35
 
package/ui/js/api.js CHANGED
@@ -79,24 +79,50 @@ export async function updateProjectLocale(locale) {
79
79
  });
80
80
  }
81
81
 
82
+ /**
83
+ * Obtiene el estado de un proyecto especifico (sin cambiar el proyecto activo)
84
+ * @param {string} projectId
85
+ */
86
+ export async function getProjectState(projectId) {
87
+ return call(`/api/state?project=${encodeURIComponent(projectId)}`, { projectAware: false });
88
+ }
89
+
90
+ /**
91
+ * Elimina un proyecto del registro (no borra archivos)
92
+ * @param {string} projectId
93
+ */
94
+ export async function removeProject(projectId) {
95
+ return call(`/api/projects/${encodeURIComponent(projectId)}`, {
96
+ method: 'DELETE',
97
+ projectAware: false,
98
+ });
99
+ }
100
+
101
+ export async function purgeUnavailableProjects() {
102
+ return call('/api/projects/purge-unavailable', {
103
+ method: 'POST',
104
+ projectAware: false,
105
+ });
106
+ }
107
+
82
108
  // ─────────────────────────────── ESTADO ─────────────────────────────────────
83
109
 
84
110
  /**
85
111
  * Obtiene el estado completo del proyecto activo
86
112
  */
87
- export async function getState() {
88
- return call('/api/state');
89
- }
90
-
91
- export async function getEnvStatus() {
92
- return call('/api/env');
93
- }
94
-
95
- export async function syncEnv() {
96
- return call('/api/env/sync', {
97
- method: 'POST',
98
- });
99
- }
113
+ export async function getState() {
114
+ return call('/api/state');
115
+ }
116
+
117
+ export async function getEnvStatus() {
118
+ return call('/api/env');
119
+ }
120
+
121
+ export async function syncEnv() {
122
+ return call('/api/env/sync', {
123
+ method: 'POST',
124
+ });
125
+ }
100
126
 
101
127
  // ─────────────────────────────── TAREAS ─────────────────────────────────────
102
128
 
@@ -202,6 +228,16 @@ export async function getTimeEntries() {
202
228
  return call('/api/time');
203
229
  }
204
230
 
231
+ // ─────────────────────────────── ANALYTICS ────────────────────────────────
232
+
233
+ /**
234
+ * Obtiene datos analiticos computados del proyecto
235
+ * @param {string} [range='30'] — Rango en dias (7, 30, 90, 'all')
236
+ */
237
+ export async function getAnalytics(range = '30') {
238
+ return call(`/api/analytics?range=${encodeURIComponent(range)}`);
239
+ }
240
+
205
241
  // ─────────────────────────────── SKILLS HUB ────────────────────────────────
206
242
 
207
243
  export async function fetchSkillsLocal() {