trackops 1.0.0 → 1.0.1

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.
@@ -0,0 +1,266 @@
1
+ /* ═══════════════════════════════════════════════════════
2
+ BASE — Reset + Layout + Tipografía global
3
+ ═══════════════════════════════════════════════════════ */
4
+
5
+ /* ── Google Fonts se cargan en index.html ── */
6
+
7
+ *, *::before, *::after {
8
+ box-sizing: border-box;
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ html {
14
+ font-size: 16px;
15
+ scroll-behavior: smooth;
16
+ -webkit-text-size-adjust: 100%;
17
+ }
18
+
19
+ body {
20
+ font-family: var(--font-ui);
21
+ font-size: var(--text-base);
22
+ color: var(--text-primary);
23
+ background-color: var(--surface-0);
24
+ line-height: 1.55;
25
+ min-height: 100dvh;
26
+ overflow-x: hidden;
27
+ -webkit-font-smoothing: antialiased;
28
+ -moz-osx-font-smoothing: grayscale;
29
+ }
30
+
31
+ /* ── Accesibilidad: Skip link ── */
32
+ .skip-link {
33
+ position: absolute;
34
+ top: -100%;
35
+ left: var(--space-4);
36
+ z-index: var(--z-onboard);
37
+ padding: var(--space-2) var(--space-4);
38
+ background: var(--accent);
39
+ color: white;
40
+ font-weight: 700;
41
+ font-size: var(--text-sm);
42
+ border-radius: var(--radius-md);
43
+ text-decoration: none;
44
+ transition: top var(--duration-base) var(--ease-out);
45
+ }
46
+ .skip-link:focus {
47
+ top: var(--space-4);
48
+ }
49
+
50
+ /* ── Accesibilidad: Visually hidden ── */
51
+ .sr-only {
52
+ position: absolute;
53
+ width: 1px;
54
+ height: 1px;
55
+ padding: 0;
56
+ margin: -1px;
57
+ overflow: hidden;
58
+ clip: rect(0,0,0,0);
59
+ white-space: nowrap;
60
+ border: 0;
61
+ }
62
+
63
+ /* ── Layout principal: sidebar fija + contenido ── */
64
+ .app-shell {
65
+ display: grid;
66
+ grid-template-columns: var(--sidebar-width) 1fr;
67
+ grid-template-rows: var(--topbar-height) 1fr;
68
+ grid-template-areas:
69
+ "sidebar topbar"
70
+ "sidebar content";
71
+ min-height: 100dvh;
72
+ }
73
+
74
+ #sidebar {
75
+ grid-area: sidebar;
76
+ position: fixed;
77
+ top: 0;
78
+ left: 0;
79
+ width: var(--sidebar-width);
80
+ height: 100dvh;
81
+ z-index: var(--z-sidebar);
82
+ overflow-y: auto;
83
+ overflow-x: hidden;
84
+ }
85
+
86
+ #topbar {
87
+ grid-area: topbar;
88
+ position: sticky;
89
+ top: 0;
90
+ z-index: var(--z-topbar);
91
+ }
92
+
93
+ #view-container {
94
+ grid-area: content;
95
+ padding: var(--content-pad);
96
+ min-height: calc(100dvh - var(--topbar-height));
97
+ overflow-y: auto;
98
+ }
99
+
100
+ /* ── Tipografía ── */
101
+ h1, h2, h3, h4, h5, h6 {
102
+ font-family: var(--font-heading);
103
+ font-weight: 700;
104
+ line-height: 1.15;
105
+ letter-spacing: -0.02em;
106
+ color: var(--text-primary);
107
+ }
108
+
109
+ h1 { font-size: var(--text-3xl); }
110
+ h2 { font-size: var(--text-2xl); }
111
+ h3 { font-size: var(--text-xl); }
112
+ h4 { font-size: var(--text-lg); }
113
+ h5 { font-size: var(--text-md); }
114
+ h6 { font-size: var(--text-base); }
115
+
116
+ p { margin: 0; }
117
+
118
+ code, pre, .mono {
119
+ font-family: var(--font-mono);
120
+ }
121
+
122
+ a {
123
+ color: var(--accent);
124
+ text-decoration: none;
125
+ transition: color var(--duration-fast) var(--ease-out);
126
+ }
127
+ a:hover { color: var(--accent-hover); }
128
+
129
+ button, input, textarea, select {
130
+ font: inherit;
131
+ color: inherit;
132
+ }
133
+ button { cursor: pointer; border: none; background: none; }
134
+
135
+ img, svg { display: block; max-width: 100%; }
136
+
137
+ ul, ol { list-style: none; }
138
+
139
+ /* ── Scrollbars personalizadas (idénticas a la web) ── */
140
+ ::-webkit-scrollbar { width: 5px; height: 5px; }
141
+ ::-webkit-scrollbar-track { background: var(--surface-1); }
142
+ ::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: var(--radius-full); }
143
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
144
+
145
+ /* ── Focus outline accesible ── */
146
+ :focus-visible {
147
+ outline: 2px solid var(--accent);
148
+ outline-offset: 2px;
149
+ border-radius: var(--radius-xs);
150
+ }
151
+
152
+ /* ── Selección de texto ── */
153
+ ::selection {
154
+ background: var(--accent);
155
+ color: white;
156
+ }
157
+
158
+ /* ── Animaciones de entrada ── */
159
+ @keyframes fadeInUp {
160
+ from { opacity: 0; transform: translateY(12px); }
161
+ to { opacity: 1; transform: translateY(0); }
162
+ }
163
+
164
+ @keyframes fadeIn {
165
+ from { opacity: 0; }
166
+ to { opacity: 1; }
167
+ }
168
+
169
+ @keyframes pulse {
170
+ 0%, 100% { opacity: 1; }
171
+ 50% { opacity: 0.5; }
172
+ }
173
+
174
+ @keyframes spin {
175
+ to { transform: rotate(360deg); }
176
+ }
177
+
178
+ @keyframes slideInRight {
179
+ from { opacity: 0; transform: translateX(20px); }
180
+ to { opacity: 1; transform: translateX(0); }
181
+ }
182
+
183
+ @keyframes slideInLeft {
184
+ from { opacity: 0; transform: translateX(-20px); }
185
+ to { opacity: 1; transform: translateX(0); }
186
+ }
187
+
188
+ @keyframes dash {
189
+ to { stroke-dashoffset: 0; }
190
+ }
191
+
192
+ @keyframes barGrow {
193
+ from { transform: scaleX(0); }
194
+ to { transform: scaleX(1); }
195
+ }
196
+
197
+ @keyframes heightGrow {
198
+ from { transform: scaleY(0); }
199
+ to { transform: scaleY(1); }
200
+ }
201
+
202
+ /* ── Clases de utilidad ── */
203
+ .view-enter { animation: fadeInUp var(--duration-slow) var(--ease-out) both; }
204
+ .stagger-1 { animation-delay: 0.05s; }
205
+ .stagger-2 { animation-delay: 0.10s; }
206
+ .stagger-3 { animation-delay: 0.15s; }
207
+ .stagger-4 { animation-delay: 0.20s; }
208
+ .stagger-5 { animation-delay: 0.25s; }
209
+
210
+ .truncate {
211
+ overflow: hidden;
212
+ text-overflow: ellipsis;
213
+ white-space: nowrap;
214
+ }
215
+
216
+ .eyebrow {
217
+ font-size: var(--text-xs);
218
+ font-weight: 700;
219
+ letter-spacing: 0.12em;
220
+ text-transform: uppercase;
221
+ color: var(--accent);
222
+ }
223
+
224
+ .label-sm {
225
+ font-size: var(--text-xs);
226
+ font-weight: 600;
227
+ letter-spacing: 0.06em;
228
+ text-transform: uppercase;
229
+ color: var(--text-muted);
230
+ }
231
+
232
+ .text-muted { color: var(--text-muted); }
233
+ .text-second { color: var(--text-secondary); }
234
+ .text-accent { color: var(--accent); }
235
+ .text-success { color: var(--success); }
236
+ .text-warning { color: var(--warning); }
237
+ .text-danger { color: var(--danger); }
238
+
239
+ /* ── Responsive: sidebar colapsable en pantallas menores a 1024px ── */
240
+ @media (max-width: 1024px) {
241
+ .app-shell {
242
+ grid-template-columns: 1fr;
243
+ grid-template-areas:
244
+ "topbar"
245
+ "content";
246
+ }
247
+ #sidebar {
248
+ transform: translateX(-100%);
249
+ transition: transform var(--duration-slow) var(--ease-out);
250
+ }
251
+ #sidebar.is-open {
252
+ transform: translateX(0);
253
+ box-shadow: var(--shadow-xl);
254
+ }
255
+ #view-container {
256
+ padding: var(--space-4);
257
+ }
258
+ }
259
+
260
+ /* ── Divider ── */
261
+ .divider {
262
+ height: 1px;
263
+ background: var(--border);
264
+ border: none;
265
+ margin: var(--space-4) 0;
266
+ }
@@ -0,0 +1,327 @@
1
+ /* ═══════════════════════════════════════════════════════
2
+ CHARTS — Gráficas SVG custom, bar charts, donut
3
+ ═══════════════════════════════════════════════════════ */
4
+
5
+ /* ───────────────────────────────────
6
+ CHART CARD CONTAINER
7
+ ─────────────────────────────────── */
8
+ .chart-card {
9
+ background: var(--surface-2);
10
+ border: 1px solid var(--border);
11
+ border-radius: var(--radius-xl);
12
+ padding: var(--space-5);
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: var(--space-4);
16
+ }
17
+
18
+ .chart-title {
19
+ font-size: var(--text-sm);
20
+ font-weight: 700;
21
+ color: var(--text-primary);
22
+ margin: 0;
23
+ }
24
+ .chart-subtitle {
25
+ font-size: var(--text-xs);
26
+ color: var(--text-muted);
27
+ }
28
+
29
+ /* ───────────────────────────────────
30
+ BAR CHARTS HORIZONTALES
31
+ ─────────────────────────────────── */
32
+ .bar-chart {
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: var(--space-3);
36
+ }
37
+
38
+ .bar-row {
39
+ display: grid;
40
+ grid-template-columns: 110px 1fr 36px;
41
+ align-items: center;
42
+ gap: var(--space-3);
43
+ }
44
+
45
+ .bar-label {
46
+ font-size: var(--text-xs);
47
+ font-weight: 600;
48
+ color: var(--text-secondary);
49
+ white-space: nowrap;
50
+ overflow: hidden;
51
+ text-overflow: ellipsis;
52
+ }
53
+
54
+ .bar-track {
55
+ height: 8px;
56
+ background: var(--surface-3);
57
+ border-radius: var(--radius-full);
58
+ overflow: hidden;
59
+ position: relative;
60
+ }
61
+
62
+ .bar-fill {
63
+ height: 100%;
64
+ border-radius: var(--radius-full);
65
+ background: linear-gradient(90deg, var(--accent), #818CF8);
66
+ transform-origin: left;
67
+ animation: barGrow 0.8s var(--ease-out) both;
68
+ }
69
+
70
+ .bar-fill.fill-success { background: linear-gradient(90deg, var(--success), #34D399); }
71
+ .bar-fill.fill-warning { background: linear-gradient(90deg, var(--warning), #FCD34D); }
72
+ .bar-fill.fill-danger { background: linear-gradient(90deg, var(--danger), #F87171); }
73
+ .bar-fill.fill-info { background: linear-gradient(90deg, var(--info), #60A5FA); }
74
+
75
+ .bar-value {
76
+ font-size: var(--text-xs);
77
+ font-weight: 700;
78
+ color: var(--text-secondary);
79
+ text-align: right;
80
+ font-family: var(--font-mono);
81
+ }
82
+
83
+ /* ───────────────────────────────────
84
+ ACTIVIDAD VERTICAL (barras semanales)
85
+ ─────────────────────────────────── */
86
+ .activity-chart {
87
+ display: flex;
88
+ align-items: flex-end;
89
+ gap: var(--space-2);
90
+ height: 120px;
91
+ }
92
+
93
+ .activity-bar-col {
94
+ flex: 1;
95
+ display: flex;
96
+ flex-direction: column;
97
+ align-items: center;
98
+ justify-content: flex-end;
99
+ gap: var(--space-1);
100
+ height: 100%;
101
+ }
102
+
103
+ .activity-bar {
104
+ width: 100%;
105
+ min-height: 4px;
106
+ border-radius: var(--radius-xs) var(--radius-xs) 2px 2px;
107
+ background: linear-gradient(180deg, var(--accent) 0%, rgba(99,102,241,0.4) 100%);
108
+ transform-origin: bottom;
109
+ animation: heightGrow 0.9s var(--ease-out) both;
110
+ transition: background var(--duration-fast);
111
+ }
112
+ .activity-bar:hover {
113
+ background: linear-gradient(180deg, var(--accent-hover) 0%, rgba(129,140,248,0.5) 100%);
114
+ }
115
+
116
+ .activity-bar-label {
117
+ font-size: 0.65rem;
118
+ font-family: var(--font-mono);
119
+ color: var(--text-muted);
120
+ text-align: center;
121
+ }
122
+
123
+ /* ───────────────────────────────────
124
+ DONUT CHART SVG
125
+ ─────────────────────────────────── */
126
+ .donut-svg {
127
+ overflow: visible;
128
+ }
129
+
130
+ .donut-track {
131
+ fill: none;
132
+ stroke: var(--surface-3);
133
+ stroke-width: 12;
134
+ }
135
+
136
+ .donut-arc {
137
+ fill: none;
138
+ stroke-width: 12;
139
+ stroke-linecap: round;
140
+ stroke-dashoffset: 0;
141
+ transform-origin: center;
142
+ transform: rotate(-90deg);
143
+ transition: stroke-dasharray 1.2s var(--ease-out);
144
+ }
145
+
146
+ .donut-arc.arc-completed { stroke: var(--success); }
147
+ .donut-arc.arc-progress { stroke: var(--accent); }
148
+ .donut-arc.arc-blocked { stroke: var(--danger); }
149
+ .donut-arc.arc-review { stroke: var(--warning); }
150
+
151
+ /* ───────────────────────────────────
152
+ PHASE PROGRESS BARS
153
+ ─────────────────────────────────── */
154
+ .phase-chart {
155
+ display: flex;
156
+ flex-direction: column;
157
+ gap: var(--space-4);
158
+ }
159
+
160
+ .phase-row {
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: var(--space-2);
164
+ }
165
+
166
+ .phase-row-header {
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: space-between;
170
+ }
171
+
172
+ .phase-name {
173
+ font-size: var(--text-xs);
174
+ font-weight: 700;
175
+ color: var(--text-secondary);
176
+ }
177
+
178
+ .phase-progress {
179
+ font-size: var(--text-xs);
180
+ font-family: var(--font-mono);
181
+ color: var(--text-muted);
182
+ }
183
+
184
+ .phase-track {
185
+ height: 6px;
186
+ background: var(--surface-3);
187
+ border-radius: var(--radius-full);
188
+ overflow: hidden;
189
+ }
190
+
191
+ .phase-fill {
192
+ height: 100%;
193
+ border-radius: var(--radius-full);
194
+ transform-origin: left;
195
+ animation: barGrow 1s var(--ease-out) both;
196
+ }
197
+
198
+ .phase-fill.done { background: var(--success); }
199
+ .phase-fill.active { background: linear-gradient(90deg, var(--accent) 0%, var(--accent-hover) 100%); }
200
+ .phase-fill.partial { background: var(--warning); }
201
+
202
+ /* ───────────────────────────────────
203
+ MINI SPARKLINE (para KPI cards)
204
+ ─────────────────────────────────── */
205
+ .sparkline-svg {
206
+ width: 100%;
207
+ height: 40px;
208
+ overflow: visible;
209
+ }
210
+
211
+ .sparkline-path {
212
+ fill: none;
213
+ stroke: var(--accent);
214
+ stroke-width: 2;
215
+ stroke-linecap: round;
216
+ stroke-linejoin: round;
217
+ }
218
+
219
+ .sparkline-area {
220
+ fill: url(#sparkGrad);
221
+ opacity: 0.3;
222
+ }
223
+
224
+ /* ───────────────────────────────────
225
+ TIME ENTRIES TIMELINE (mini)
226
+ ─────────────────────────────────── */
227
+ .time-entries {
228
+ display: flex;
229
+ flex-direction: column;
230
+ gap: var(--space-2);
231
+ }
232
+
233
+ .time-entry {
234
+ display: flex;
235
+ align-items: center;
236
+ justify-content: space-between;
237
+ gap: var(--space-3);
238
+ padding: var(--space-2) var(--space-3);
239
+ border-radius: var(--radius-md);
240
+ background: var(--surface-3);
241
+ border: 1px solid var(--border);
242
+ font-size: var(--text-xs);
243
+ }
244
+
245
+ .time-entry-task {
246
+ flex: 1;
247
+ min-width: 0;
248
+ overflow: hidden;
249
+ text-overflow: ellipsis;
250
+ white-space: nowrap;
251
+ color: var(--text-secondary);
252
+ font-weight: 600;
253
+ }
254
+
255
+ .time-entry-duration {
256
+ font-family: var(--font-mono);
257
+ font-weight: 700;
258
+ color: var(--text-primary);
259
+ white-space: nowrap;
260
+ }
261
+
262
+ .time-entry-date {
263
+ color: var(--text-muted);
264
+ font-family: var(--font-mono);
265
+ white-space: nowrap;
266
+ }
267
+
268
+ /* ───────────────────────────────────
269
+ HEALTH RAIL (KPI health)
270
+ ─────────────────────────────────── */
271
+ .health-grid {
272
+ display: grid;
273
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
274
+ gap: var(--space-3);
275
+ }
276
+
277
+ .health-card {
278
+ background: var(--surface-3);
279
+ border: 1px solid var(--border);
280
+ border-radius: var(--radius-md);
281
+ padding: var(--space-4);
282
+ display: flex;
283
+ flex-direction: column;
284
+ gap: var(--space-2);
285
+ }
286
+
287
+ .health-card-label {
288
+ font-size: var(--text-xs);
289
+ font-weight: 700;
290
+ letter-spacing: 0.06em;
291
+ text-transform: uppercase;
292
+ color: var(--text-muted);
293
+ }
294
+
295
+ .health-card-value {
296
+ font-family: var(--font-heading);
297
+ font-size: var(--text-2xl);
298
+ font-weight: 800;
299
+ letter-spacing: -0.04em;
300
+ line-height: 1;
301
+ color: var(--text-primary);
302
+ }
303
+
304
+ .health-card-value.good { color: var(--success); }
305
+ .health-card-value.warn { color: var(--warning); }
306
+ .health-card-value.bad { color: var(--danger); }
307
+
308
+ /* ───────────────────────────────────
309
+ CHART TOOLTIP
310
+ ─────────────────────────────────── */
311
+ .chart-tooltip {
312
+ position: absolute;
313
+ background: var(--surface-2);
314
+ border: 1px solid var(--border-strong);
315
+ border-radius: var(--radius-md);
316
+ padding: var(--space-2) var(--space-3);
317
+ font-size: var(--text-xs);
318
+ font-weight: 600;
319
+ color: var(--text-primary);
320
+ pointer-events: none;
321
+ white-space: nowrap;
322
+ box-shadow: var(--shadow-md);
323
+ opacity: 0;
324
+ transition: opacity var(--duration-fast);
325
+ z-index: var(--z-panel);
326
+ }
327
+ .chart-tooltip.is-visible { opacity: 1; }