Multimedix commited on
Commit
eff97db
·
verified ·
1 Parent(s): af472be

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +895 -19
index.html CHANGED
@@ -1,19 +1,895 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Fokus & Flow - Produktivitäts-Dashboard</title>
7
+
8
+ <!-- Google Fonts -->
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap" rel="stylesheet">
12
+
13
+ <!-- Font Awesome -->
14
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
15
+
16
+ <style>
17
+ :root {
18
+ /* Light Theme Variables */
19
+ --bg-color: #f3f4f6;
20
+ --text-color: #1f2937;
21
+ --card-bg: #ffffff;
22
+ --primary-color: #6366f1; /* Indigo */
23
+ --secondary-color: #a855f7; /* Purple */
24
+ --accent-color: #10b981; /* Emerald */
25
+ --danger-color: #ef4444;
26
+ --border-color: #e5e7eb;
27
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
28
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
29
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
30
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
31
+ --font-main: 'Outfit', sans-serif;
32
+ }
33
+
34
+ [data-theme="dark"] {
35
+ /* Dark Theme Variables */
36
+ --bg-color: #0f172a;
37
+ --text-color: #f3f4f6;
38
+ --card-bg: #1e293b;
39
+ --primary-color: #818cf8;
40
+ --secondary-color: #c084fc;
41
+ --accent-color: #34d399;
42
+ --danger-color: #f87171;
43
+ --border-color: #334155;
44
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
45
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.3);
46
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.3);
47
+ }
48
+
49
+ * {
50
+ margin: 0;
51
+ padding: 0;
52
+ box-sizing: border-box;
53
+ }
54
+
55
+ body {
56
+ font-family: var(--font-main);
57
+ background-color: var(--bg-color);
58
+ color: var(--text-color);
59
+ transition: var(--transition);
60
+ min-height: 100vh;
61
+ display: flex;
62
+ flex-direction: column;
63
+ overflow-x: hidden;
64
+ }
65
+
66
+ /* --- Header --- */
67
+ header {
68
+ background: rgba(255, 255, 255, 0.0);
69
+ backdrop-filter: blur(10px);
70
+ padding: 1rem 2rem;
71
+ display: flex;
72
+ justify-content: space-between;
73
+ align-items: center;
74
+ position: sticky;
75
+ top: 0;
76
+ z-index: 100;
77
+ border-bottom: 1px solid var(--border-color);
78
+ background-color: var(--card-bg);
79
+ }
80
+
81
+ .logo {
82
+ font-size: 1.5rem;
83
+ font-weight: 700;
84
+ background: linear-gradient(to right, var(--primary-color), var(--secondary-color));
85
+ -webkit-background-clip: text;
86
+ background-clip: text;
87
+ color: transparent;
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 0.5rem;
91
+ }
92
+
93
+ .anycoder-link {
94
+ font-size: 0.9rem;
95
+ font-weight: 600;
96
+ color: var(--text-color);
97
+ text-decoration: none;
98
+ padding: 0.5rem 1rem;
99
+ border-radius: 2rem;
100
+ background: linear-gradient(90deg, rgba(99, 102, 241, 0.1), rgba(168, 85, 247, 0.1));
101
+ border: 1px solid var(--border-color);
102
+ transition: var(--transition);
103
+ }
104
+
105
+ .anycoder-link:hover {
106
+ transform: translateY(-2px);
107
+ box-shadow: var(--shadow-md);
108
+ background: linear-gradient(90deg, rgba(99, 102, 241, 0.2), rgba(168, 85, 247, 0.2));
109
+ }
110
+
111
+ .theme-toggle {
112
+ background: none;
113
+ border: none;
114
+ color: var(--text-color);
115
+ font-size: 1.2rem;
116
+ cursor: pointer;
117
+ padding: 0.5rem;
118
+ border-radius: 50%;
119
+ transition: var(--transition);
120
+ }
121
+
122
+ .theme-toggle:hover {
123
+ background-color: rgba(128, 128, 128, 0.1);
124
+ }
125
+
126
+ /* --- Main Layout --- */
127
+ main {
128
+ flex: 1;
129
+ padding: 2rem;
130
+ max-width: 1200px;
131
+ margin: 0 auto;
132
+ width: 100%;
133
+ display: grid;
134
+ grid-template-columns: repeat(12, 1fr);
135
+ gap: 2rem;
136
+ }
137
+
138
+ .card {
139
+ background-color: var(--card-bg);
140
+ border-radius: 1.5rem;
141
+ padding: 1.5rem;
142
+ box-shadow: var(--shadow-md);
143
+ border: 1px solid var(--border-color);
144
+ transition: var(--transition);
145
+ display: flex;
146
+ flex-direction: column;
147
+ }
148
+
149
+ .card:hover {
150
+ box-shadow: var(--shadow-lg);
151
+ transform: translateY(-2px);
152
+ }
153
+
154
+ h2 {
155
+ font-size: 1.25rem;
156
+ margin-bottom: 1.5rem;
157
+ font-weight: 600;
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 0.5rem;
161
+ }
162
+
163
+ /* --- Pomodoro Timer (Left Large) --- */
164
+ .timer-section {
165
+ grid-column: span 12;
166
+ text-align: center;
167
+ align-items: center;
168
+ justify-content: center;
169
+ position: relative;
170
+ overflow: hidden;
171
+ }
172
+
173
+ @media (min-width: 768px) {
174
+ .timer-section {
175
+ grid-column: span 7;
176
+ }
177
+ }
178
+
179
+ .timer-display {
180
+ position: relative;
181
+ width: 280px;
182
+ height: 280px;
183
+ margin: 0 auto 1.5rem;
184
+ }
185
+
186
+ .progress-ring {
187
+ transform: rotate(-90deg);
188
+ transform-origin: 50% 50%;
189
+ }
190
+
191
+ .progress-ring__circle {
192
+ stroke-dasharray: 816; /* 2 * PI * r (r=130) */
193
+ stroke-dashoffset: 816;
194
+ transition: stroke-dashoffset 1s linear;
195
+ stroke: var(--primary-color);
196
+ }
197
+
198
+ .timer-text {
199
+ position: absolute;
200
+ top: 50%;
201
+ left: 50%;
202
+ transform: translate(-50%, -50%);
203
+ font-size: 4rem;
204
+ font-weight: 700;
205
+ font-variant-numeric: tabular-nums;
206
+ }
207
+
208
+ .timer-label {
209
+ position: absolute;
210
+ top: 70%;
211
+ left: 50%;
212
+ transform: translate(-50%, -50%);
213
+ font-size: 1rem;
214
+ color: var(--secondary-color);
215
+ text-transform: uppercase;
216
+ letter-spacing: 2px;
217
+ }
218
+
219
+ .timer-controls {
220
+ display: flex;
221
+ gap: 1rem;
222
+ justify-content: center;
223
+ flex-wrap: wrap;
224
+ }
225
+
226
+ .btn {
227
+ padding: 0.75rem 1.5rem;
228
+ border-radius: 0.75rem;
229
+ border: none;
230
+ font-weight: 600;
231
+ cursor: pointer;
232
+ transition: var(--transition);
233
+ font-family: var(--font-main);
234
+ display: flex;
235
+ align-items: center;
236
+ gap: 0.5rem;
237
+ }
238
+
239
+ .btn-primary {
240
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
241
+ color: white;
242
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
243
+ }
244
+
245
+ .btn-primary:hover {
246
+ filter: brightness(1.1);
247
+ box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);
248
+ }
249
+
250
+ .btn-outline {
251
+ background: transparent;
252
+ border: 2px solid var(--border-color);
253
+ color: var(--text-color);
254
+ }
255
+
256
+ .btn-outline:hover {
257
+ border-color: var(--primary-color);
258
+ color: var(--primary-color);
259
+ }
260
+
261
+ .mode-selector {
262
+ display: flex;
263
+ justify-content: center;
264
+ gap: 0.5rem;
265
+ margin-bottom: 2rem;
266
+ background: var(--bg-color);
267
+ padding: 0.5rem;
268
+ border-radius: 1rem;
269
+ width: fit-content;
270
+ margin-left: auto;
271
+ margin-right: auto;
272
+ }
273
+
274
+ .mode-btn {
275
+ padding: 0.5rem 1rem;
276
+ border-radius: 0.5rem;
277
+ border: none;
278
+ background: transparent;
279
+ color: var(--text-color);
280
+ cursor: pointer;
281
+ font-size: 0.9rem;
282
+ transition: var(--transition);
283
+ }
284
+
285
+ .mode-btn.active {
286
+ background-color: var(--card-bg);
287
+ color: var(--primary-color);
288
+ box-shadow: var(--shadow-sm);
289
+ font-weight: 600;
290
+ }
291
+
292
+ /* --- Tasks (Right Column) --- */
293
+ .tasks-section {
294
+ grid-column: span 12;
295
+ }
296
+
297
+ @media (min-width: 768px) {
298
+ .tasks-section {
299
+ grid-column: span 5;
300
+ }
301
+ }
302
+
303
+ .task-input-group {
304
+ display: flex;
305
+ gap: 0.5rem;
306
+ margin-bottom: 1.5rem;
307
+ }
308
+
309
+ .task-input {
310
+ flex: 1;
311
+ padding: 0.75rem;
312
+ border-radius: 0.75rem;
313
+ border: 1px solid var(--border-color);
314
+ background-color: var(--bg-color);
315
+ color: var(--text-color);
316
+ outline: none;
317
+ font-family: var(--font-main);
318
+ transition: var(--transition);
319
+ }
320
+
321
+ .task-input:focus {
322
+ border-color: var(--primary-color);
323
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
324
+ }
325
+
326
+ .task-list {
327
+ list-style: none;
328
+ overflow-y: auto;
329
+ max-height: 300px;
330
+ padding-right: 0.5rem;
331
+ }
332
+
333
+ /* Custom Scrollbar */
334
+ .task-list::-webkit-scrollbar {
335
+ width: 6px;
336
+ }
337
+ .task-list::-webkit-scrollbar-track {
338
+ background: transparent;
339
+ }
340
+ .task-list::-webkit-scrollbar-thumb {
341
+ background-color: var(--border-color);
342
+ border-radius: 20px;
343
+ }
344
+
345
+ .task-item {
346
+ display: flex;
347
+ align-items: center;
348
+ justify-content: space-between;
349
+ padding: 0.75rem;
350
+ background-color: var(--bg-color);
351
+ border-radius: 0.75rem;
352
+ margin-bottom: 0.5rem;
353
+ border: 1px solid transparent;
354
+ transition: var(--transition);
355
+ animation: slideIn 0.3s ease;
356
+ }
357
+
358
+ @keyframes slideIn {
359
+ from { opacity: 0; transform: translateY(10px); }
360
+ to { opacity: 1; transform: translateY(0); }
361
+ }
362
+
363
+ .task-item:hover {
364
+ border-color: var(--primary-color);
365
+ }
366
+
367
+ .task-content {
368
+ display: flex;
369
+ align-items: center;
370
+ gap: 0.75rem;
371
+ flex: 1;
372
+ cursor: pointer;
373
+ }
374
+
375
+ .custom-checkbox {
376
+ width: 20px;
377
+ height: 20px;
378
+ border: 2px solid var(--primary-color);
379
+ border-radius: 6px;
380
+ display: flex;
381
+ align-items: center;
382
+ justify-content: center;
383
+ transition: var(--transition);
384
+ }
385
+
386
+ .task-item.completed .custom-checkbox {
387
+ background-color: var(--primary-color);
388
+ }
389
+
390
+ .custom-checkbox i {
391
+ color: white;
392
+ font-size: 0.7rem;
393
+ opacity: 0;
394
+ transform: scale(0);
395
+ transition: var(--transition);
396
+ }
397
+
398
+ .task-item.completed .custom-checkbox i {
399
+ opacity: 1;
400
+ transform: scale(1);
401
+ }
402
+
403
+ .task-text {
404
+ transition: var(--transition);
405
+ }
406
+
407
+ .task-item.completed .task-text {
408
+ text-decoration: line-through;
409
+ color: #9ca3af;
410
+ }
411
+
412
+ .delete-btn {
413
+ background: none;
414
+ border: none;
415
+ color: #9ca3af;
416
+ cursor: pointer;
417
+ padding: 0.5rem;
418
+ transition: var(--transition);
419
+ }
420
+
421
+ .delete-btn:hover {
422
+ color: var(--danger-color);
423
+ }
424
+
425
+ /* --- Breathing Exercise (Bottom Left) --- */
426
+ .breathing-section {
427
+ grid-column: span 12;
428
+ display: flex;
429
+ flex-direction: column;
430
+ align-items: center;
431
+ justify-content: center;
432
+ min-height: 300px;
433
+ position: relative;
434
+ }
435
+
436
+ @media (min-width: 768px) {
437
+ .breathing-section {
438
+ grid-column: span 6;
439
+ }
440
+ }
441
+
442
+ .breath-circle-container {
443
+ position: relative;
444
+ width: 200px;
445
+ height: 200px;
446
+ display: flex;
447
+ align-items: center;
448
+ justify-content: center;
449
+ margin-top: 1rem;
450
+ }
451
+
452
+ .breath-circle {
453
+ width: 100%;
454
+ height: 100%;
455
+ background: radial-gradient(circle, var(--accent-color) 0%, transparent 70%);
456
+ border-radius: 50%;
457
+ opacity: 0.6;
458
+ transform: scale(0.5);
459
+ filter: blur(10px);
460
+ }
461
+
462
+ .breath-circle.animating {
463
+ animation: breathAnim 12s infinite ease-in-out;
464
+ }
465
+
466
+ @keyframes breathAnim {
467
+ 0% { transform: scale(0.5); opacity: 0.4; } /* Start Inhale */
468
+ 33% { transform: scale(1.2); opacity: 0.8; } /* End Inhale / Start Hold */
469
+ 66% { transform: scale(1.2); opacity: 0.8; } /* End Hold / Start Exhale */
470
+ 100% { transform: scale(0.5); opacity: 0.4; } /* End Exhale */
471
+ }
472
+
473
+ .breath-instruction {
474
+ position: absolute;
475
+ font-size: 1.5rem;
476
+ font-weight: 600;
477
+ color: var(--text-color);
478
+ text-align: center;
479
+ }
480
+
481
+ .breath-controls {
482
+ margin-top: 2rem;
483
+ }
484
+
485
+ /* --- Stats (Bottom Right) --- */
486
+ .stats-section {
487
+ grid-column: span 12;
488
+ }
489
+
490
+ @media (min-width: 768px) {
491
+ .stats-section {
492
+ grid-column: span 6;
493
+ }
494
+ }
495
+
496
+ .stats-grid {
497
+ display: grid;
498
+ grid-template-columns: 1fr 1fr;
499
+ gap: 1rem;
500
+ height: 100%;
501
+ }
502
+
503
+ .stat-item {
504
+ background-color: var(--bg-color);
505
+ padding: 1.5rem;
506
+ border-radius: 1rem;
507
+ text-align: center;
508
+ display: flex;
509
+ flex-direction: column;
510
+ justify-content: center;
511
+ align-items: center;
512
+ gap: 0.5rem;
513
+ }
514
+
515
+ .stat-value {
516
+ font-size: 2.5rem;
517
+ font-weight: 700;
518
+ color: var(--primary-color);
519
+ }
520
+
521
+ .stat-label {
522
+ font-size: 0.9rem;
523
+ color: #6b7280;
524
+ }
525
+
526
+ .stat-icon {
527
+ font-size: 1.5rem;
528
+ color: var(--secondary-color);
529
+ margin-bottom: 0.5rem;
530
+ }
531
+
532
+ /* Footer */
533
+ footer {
534
+ text-align: center;
535
+ padding: 2rem;
536
+ color: #6b7280;
537
+ font-size: 0.9rem;
538
+ margin-top: auto;
539
+ }
540
+
541
+ /* Mobile Responsiveness Tweaks */
542
+ @media (max-width: 640px) {
543
+ header {
544
+ flex-direction: column;
545
+ gap: 1rem;
546
+ }
547
+ .timer-display {
548
+ width: 240px;
549
+ height: 240px;
550
+ }
551
+ .timer-text {
552
+ font-size: 3.5rem;
553
+ }
554
+ }
555
+ </style>
556
+ </head>
557
+ <body>
558
+
559
+ <header>
560
+ <div class="logo">
561
+ <i class="fa-solid fa-layer-group"></i> Fokus & Flow
562
+ </div>
563
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
564
+ <button class="theme-toggle" id="themeToggle" aria-label="Thema wechseln">
565
+ <i class="fa-solid fa-moon"></i>
566
+ </button>
567
+ </header>
568
+
569
+ <main>
570
+ <!-- Timer Section -->
571
+ <section class="card timer-section">
572
+ <div class="mode-selector">
573
+ <button class="mode-btn active" onclick="setMode('focus')">Fokus</button>
574
+ <button class="mode-btn" onclick="setMode('shortBreak')">Kurze Pause</button>
575
+ <button class="mode-btn" onclick="setMode('longBreak')">Lange Pause</button>
576
+ </div>
577
+
578
+ <div class="timer-display">
579
+ <svg class="progress-ring" width="280" height="280">
580
+ <circle class="progress-ring__circle-bg" stroke="var(--border-color)" stroke-width="12" fill="transparent" r="130" cx="140" cy="140" />
581
+ <circle class="progress-ring__circle" id="progressCircle" stroke-width="12" fill="transparent" r="130" cx="140" cy="140" stroke-linecap="round" />
582
+ </svg>
583
+ <div class="timer-text" id="timerText">25:00</div>
584
+ <div class="timer-label" id="timerLabel">Bereit</div>
585
+ </div>
586
+
587
+ <div class="timer-controls">
588
+ <button class="btn btn-primary" id="startBtn">
589
+ <i class="fa-solid fa-play"></i> Start
590
+ </button>
591
+ <button class="btn btn-outline" id="resetBtn">
592
+ <i class="fa-solid fa-rotate-right"></i> Reset
593
+ </button>
594
+ </div>
595
+ </section>
596
+
597
+ <!-- Tasks Section -->
598
+ <section class="card tasks-section">
599
+ <h2><i class="fa-solid fa-list-check" style="color: var(--secondary-color)"></i> Aufgaben</h2>
600
+ <div class="task-input-group">
601
+ <input type="text" class="task-input" id="taskInput" placeholder="Neue Aufgabe hinzufügen...">
602
+ <button class="btn btn-primary" id="addTaskBtn">
603
+ <i class="fa-solid fa-plus"></i>
604
+ </button>
605
+ </div>
606
+ <ul class="task-list" id="taskList">
607
+ <!-- Tasks will be added here -->
608
+ </ul>
609
+ </section>
610
+
611
+ <!-- Breathing Section -->
612
+ <section class="card breathing-section">
613
+ <h2><i class="fa-solid fa-lungs" style="color: var(--accent-color)"></i> Atmen & Entspannen</h2>
614
+ <div class="breath-circle-container">
615
+ <div class="breath-circle" id="breathCircle"></div>
616
+ <div class="breath-instruction" id="breathText">Starten</div>
617
+ </div>
618
+ <div class="breath-controls">
619
+ <button class="btn btn-outline" id="breathBtn">Übung starten</button>
620
+ </div>
621
+ </section>
622
+
623
+ <!-- Stats Section -->
624
+ <section class="card stats-section">
625
+ <h2><i class="fa-solid fa-chart-simple" style="color: var(--primary-color)"></i> Tagesstatistik</h2>
626
+ <div class="stats-grid">
627
+ <div class="stat-item">
628
+ <i class="fa-solid fa-clock stat-icon"></i>
629
+ <div class="stat-value" id="totalTime">0</div>
630
+ <div class="stat-label">Minuten Fokus</div>
631
+ </div>
632
+ <div class="stat-item">
633
+ <i class="fa-solid fa-check-double stat-icon"></i>
634
+ <div class="stat-value" id="completedTasks">0</div>
635
+ <div class="stat-label">Aufgaben erledigt</div>
636
+ </div>
637
+ </div>
638
+ </section>
639
+ </main>
640
+
641
+ <footer>
642
+ &copy; 2023 Fokus & Flow. Alle Rechte vorbehalten.
643
+ </footer>
644
+
645
+ <script>
646
+ // --- Theme Logic ---
647
+ const themeToggle = document.getElementById('themeToggle');
648
+ const body = document.body;
649
+ const icon = themeToggle.querySelector('i');
650
+
651
+ // Check local storage
652
+ if (localStorage.getItem('theme') === 'dark') {
653
+ body.setAttribute('data-theme', 'dark');
654
+ icon.classList.replace('fa-moon', 'fa-sun');
655
+ }
656
+
657
+ themeToggle.addEventListener('click', () => {
658
+ if (body.getAttribute('data-theme') === 'dark') {
659
+ body.removeAttribute('data-theme');
660
+ localStorage.setItem('theme', 'light');
661
+ icon.classList.replace('fa-sun', 'fa-moon');
662
+ } else {
663
+ body.setAttribute('data-theme', 'dark');
664
+ localStorage.setItem('theme', 'dark');
665
+ icon.classList.replace('fa-moon', 'fa-sun');
666
+ }
667
+ });
668
+
669
+ // --- Timer Logic ---
670
+ let timerInterval;
671
+ let timeLeft = 25 * 60;
672
+ let totalTime = 25 * 60;
673
+ let isRunning = false;
674
+ let totalMinutesFocused = 0;
675
+
676
+ const timerText = document.getElementById('timerText');
677
+ const timerLabel = document.getElementById('timerLabel');
678
+ const progressCircle = document.getElementById('progressCircle');
679
+ const startBtn = document.getElementById('startBtn');
680
+ const resetBtn = document.getElementById('resetBtn');
681
+ const modeBtns = document.querySelectorAll('.mode-btn');
682
+
683
+ // Circle Config
684
+ const radius = progressCircle.r.baseVal.value;
685
+ const circumference = radius * 2 * Math.PI;
686
+ progressCircle.style.strokeDasharray = `${circumference} ${circumference}`;
687
+ progressCircle.style.strokeDashoffset = 0;
688
+
689
+ function setProgress(percent) {
690
+ const offset = circumference - (percent / 100) * circumference;
691
+ progressCircle.style.strokeDashoffset = offset;
692
+ }
693
+
694
+ function updateDisplay() {
695
+ const minutes = Math.floor(timeLeft / 60);
696
+ const seconds = timeLeft % 60;
697
+ timerText.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
698
+
699
+ const percent = (timeLeft / totalTime) * 100;
700
+ setProgress(percent);
701
+ }
702
+
703
+ function setMode(mode) {
704
+ stopTimer();
705
+ modeBtns.forEach(btn => btn.classList.remove('active'));
706
+
707
+ if (mode === 'focus') {
708
+ timeLeft = 25 * 60;
709
+ totalTime = 25 * 60;
710
+ timerLabel.textContent = 'Fokus Zeit';
711
+ modeBtns[0].classList.add('active');
712
+ document.documentElement.style.setProperty('--primary-color', '#6366f1');
713
+ } else if (mode === 'shortBreak') {
714
+ timeLeft = 5 * 60;
715
+ totalTime = 5 * 60;
716
+ timerLabel.textContent = 'Kurze Pause';
717
+ modeBtns[1].classList.add('active');
718
+ document.documentElement.style.setProperty('--primary-color', '#10b981');
719
+ } else if (mode === 'longBreak') {
720
+ timeLeft = 15 * 60;
721
+ totalTime = 15 * 60;
722
+ timerLabel.textContent = 'Lange Pause';
723
+ modeBtns[2].classList.add('active');
724
+ document.documentElement.style.setProperty('--primary-color', '#a855f7');
725
+ }
726
+ updateDisplay();
727
+ setProgress(100); // Reset circle full
728
+ }
729
+
730
+ function startTimer() {
731
+ if (isRunning) {
732
+ stopTimer();
733
+ return;
734
+ }
735
+
736
+ isRunning = true;
737
+ startBtn.innerHTML = '<i class="fa-solid fa-pause"></i> Pause';
738
+ timerLabel.textContent = 'Läuft...';
739
+
740
+ timerInterval = setInterval(() => {
741
+ timeLeft--;
742
+ updateDisplay();
743
+
744
+ if (modeBtns[0].classList.contains('active')) {
745
+ // Only count stats if in focus mode
746
+ // Simple logic: update stats every minute or at end?
747
+ // Let's update continuously for visual feedback or just store end result.
748
+ // For simplicity, we increment stats at the end of a session.
749
+ }
750
+
751
+ if (timeLeft <= 0) {
752
+ stopTimer();
753
+ timerLabel.textContent = 'Fertig!';
754
+ // Play sound or alert could go here
755
+ if (modeBtns[0].classList.contains('active')) {
756
+ totalMinutesFocused += (totalTime / 60);
757
+ document.getElementById('totalTime').textContent = Math.round(totalMinutesFocused);
758
+ }
759
+ }
760
+ }, 1000);
761
+ }
762
+
763
+ function stopTimer() {
764
+ isRunning = false;
765
+ clearInterval(timerInterval);
766
+ startBtn.innerHTML = '<i class="fa-solid fa-play"></i> Start';
767
+ if(timeLeft > 0) timerLabel.textContent = 'Pausiert';
768
+ }
769
+
770
+ startBtn.addEventListener('click', startTimer);
771
+ resetBtn.addEventListener('click', () => {
772
+ stopTimer();
773
+ const activeMode = document.querySelector('.mode-btn.active').textContent;
774
+ if (activeMode.includes('Fokus')) setMode('focus');
775
+ else if (activeMode.includes('Kurze')) setMode('shortBreak');
776
+ else setMode('longBreak');
777
+ });
778
+
779
+ // --- Task Logic ---
780
+ const taskInput = document.getElementById('taskInput');
781
+ const addTaskBtn = document.getElementById('addTaskBtn');
782
+ const taskList = document.getElementById('taskList');
783
+ const completedStats = document.getElementById('completedTasks');
784
+ let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
785
+
786
+ function renderTasks() {
787
+ taskList.innerHTML = '';
788
+ let completedCount = 0;
789
+
790
+ tasks.forEach((task, index) => {
791
+ if (task.completed) completedCount++;
792
+
793
+ const li = document.createElement('li');
794
+ li.className = `task-item ${task.completed ? 'completed' : ''}`;
795
+
796
+ li.innerHTML = `
797
+ <div class="task-content" onclick="toggleTask(${index})">
798
+ <div class="custom-checkbox">
799
+ <i class="fa-solid fa-check"></i>
800
+ </div>
801
+ <span class="task-text">${task.text}</span>
802
+ </div>
803
+ <button class="delete-btn" onclick="deleteTask(${index})">
804
+ <i class="fa-solid fa-trash"></i>
805
+ </button>
806
+ `;
807
+ taskList.appendChild(li);
808
+ });
809
+
810
+ completedStats.textContent = completedCount;
811
+ localStorage.setItem('tasks', JSON.stringify(tasks));
812
+ }
813
+
814
+ function addTask() {
815
+ const text = taskInput.value.trim();
816
+ if (text) {
817
+ tasks.push({ text, completed: false });
818
+ taskInput.value = '';
819
+ renderTasks();
820
+ }
821
+ }
822
+
823
+ window.toggleTask = (index) => {
824
+ tasks[index].completed = !tasks[index].completed;
825
+ renderTasks();
826
+ };
827
+
828
+ window.deleteTask = (index) => {
829
+ tasks.splice(index, 1);
830
+ renderTasks();
831
+ };
832
+
833
+ addTaskBtn.addEventListener('click', addTask);
834
+ taskInput.addEventListener('keypress', (e) => {
835
+ if (e.key === 'Enter') addTask();
836
+ });
837
+
838
+ // --- Breathing Logic ---
839
+ const breathBtn = document.getElementById('breathBtn');
840
+ const breathCircle = document.getElementById('breathCircle');
841
+ const breathText = document.getElementById('breathText');
842
+ let isBreathing = false;
843
+ let breathTimeout;
844
+
845
+ // The CSS animation is 12s long: 4s inhale, 4s hold, 4s exhale
846
+ function breathCycle() {
847
+ if (!isBreathing) return;
848
+
849
+ breathText.textContent = "Einatmen";
850
+
851
+ setTimeout(() => {
852
+ if (!isBreathing) return;
853
+ breathText.textContent = "Halten";
854
+ }, 4000);
855
+
856
+ setTimeout(() => {
857
+ if (!isBreathing) return;
858
+ breathText.textContent = "Ausatmen";
859
+ }, 8000);
860
+ }
861
+
862
+ breathBtn.addEventListener('click', () => {
863
+ if (isBreathing) {
864
+ // Stop
865
+ isBreathing = false;
866
+ breathCircle.classList.remove('animating');
867
+ breathBtn.textContent = "Übung starten";
868
+ breathBtn.classList.remove('btn-primary');
869
+ breathBtn.classList.add('btn-outline');
870
+ breathText.textContent = "Starten";
871
+ // Reset animation
872
+ const newOne = breathCircle.cloneNode(true);
873
+ breathCircle.parentNode.replaceChild(newOne, breathCircle);
874
+ } else {
875
+ // Start
876
+ isBreathing = true;
877
+ breathCircle.classList.add('animating');
878
+ breathBtn.textContent = "Beenden";
879
+ breathBtn.classList.remove('btn-outline');
880
+ breathBtn.classList.add('btn-primary');
881
+
882
+ breathCycle(); // First immediate cycle
883
+ // Sync with CSS animation duration (12s)
884
+ setInterval(() => {
885
+ if(isBreathing) breathCycle();
886
+ }, 12000);
887
+ }
888
+ });
889
+
890
+ // Initialize
891
+ renderTasks();
892
+ setMode('focus'); // Init display
893
+ </script>
894
+ </body>
895
+ </html>