GameSentenceMiner 2.17.6__py3-none-any.whl → 2.18.0__py3-none-any.whl

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 (51) hide show
  1. GameSentenceMiner/ai/ai_prompting.py +51 -51
  2. GameSentenceMiner/anki.py +236 -152
  3. GameSentenceMiner/gametext.py +7 -4
  4. GameSentenceMiner/gsm.py +49 -10
  5. GameSentenceMiner/locales/en_us.json +7 -3
  6. GameSentenceMiner/locales/ja_jp.json +8 -4
  7. GameSentenceMiner/locales/zh_cn.json +8 -4
  8. GameSentenceMiner/obs.py +238 -59
  9. GameSentenceMiner/ocr/owocr_helper.py +1 -1
  10. GameSentenceMiner/tools/ss_selector.py +7 -8
  11. GameSentenceMiner/ui/__init__.py +0 -0
  12. GameSentenceMiner/ui/anki_confirmation.py +187 -0
  13. GameSentenceMiner/{config_gui.py → ui/config_gui.py} +102 -37
  14. GameSentenceMiner/ui/screenshot_selector.py +215 -0
  15. GameSentenceMiner/util/configuration.py +124 -22
  16. GameSentenceMiner/util/db.py +22 -13
  17. GameSentenceMiner/util/downloader/download_tools.py +2 -2
  18. GameSentenceMiner/util/ffmpeg.py +24 -30
  19. GameSentenceMiner/util/get_overlay_coords.py +34 -34
  20. GameSentenceMiner/util/gsm_utils.py +31 -1
  21. GameSentenceMiner/util/text_log.py +11 -9
  22. GameSentenceMiner/vad.py +31 -12
  23. GameSentenceMiner/web/database_api.py +742 -123
  24. GameSentenceMiner/web/static/css/dashboard-shared.css +241 -0
  25. GameSentenceMiner/web/static/css/kanji-grid.css +94 -2
  26. GameSentenceMiner/web/static/css/overview.css +850 -0
  27. GameSentenceMiner/web/static/css/popups-shared.css +126 -0
  28. GameSentenceMiner/web/static/css/shared.css +97 -0
  29. GameSentenceMiner/web/static/css/stats.css +192 -597
  30. GameSentenceMiner/web/static/js/anki_stats.js +6 -4
  31. GameSentenceMiner/web/static/js/database.js +209 -5
  32. GameSentenceMiner/web/static/js/goals.js +610 -0
  33. GameSentenceMiner/web/static/js/kanji-grid.js +267 -4
  34. GameSentenceMiner/web/static/js/overview.js +1176 -0
  35. GameSentenceMiner/web/static/js/shared.js +25 -0
  36. GameSentenceMiner/web/static/js/stats.js +154 -1459
  37. GameSentenceMiner/web/stats.py +2 -2
  38. GameSentenceMiner/web/templates/anki_stats.html +5 -0
  39. GameSentenceMiner/web/templates/components/navigation.html +3 -1
  40. GameSentenceMiner/web/templates/database.html +73 -1
  41. GameSentenceMiner/web/templates/goals.html +376 -0
  42. GameSentenceMiner/web/templates/index.html +13 -11
  43. GameSentenceMiner/web/templates/overview.html +416 -0
  44. GameSentenceMiner/web/templates/stats.html +46 -251
  45. GameSentenceMiner/web/texthooking_page.py +18 -0
  46. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/METADATA +5 -1
  47. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/RECORD +51 -41
  48. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/WHEEL +0 -0
  49. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/entry_points.txt +0 -0
  50. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/licenses/LICENSE +0 -0
  51. {gamesentenceminer-2.17.6.dist-info → gamesentenceminer-2.18.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,850 @@
1
+ /* Overview Page Specific Styles */
2
+
3
+ /* Chart Container Styles */
4
+ .chart-container {
5
+ position: relative;
6
+ background: var(--bg-secondary);
7
+ padding: 20px;
8
+ border-radius: 8px;
9
+ box-shadow: 0 4px 12px var(--shadow-color);
10
+ margin-bottom: 30px;
11
+ border: 1px solid var(--border-color);
12
+ }
13
+
14
+ /* Heatmap Styles */
15
+ .heatmap-year {
16
+ margin-bottom: 30px;
17
+ }
18
+
19
+ .heatmap-year h3 {
20
+ margin-bottom: 20px;
21
+ color: var(--text-secondary);
22
+ }
23
+
24
+ .heatmap-streaks {
25
+ display: flex;
26
+ justify-content: flex-start;
27
+ gap: 40px;
28
+ margin-bottom: 20px;
29
+ font-size: 14px;
30
+ }
31
+
32
+ .heatmap-streak-item {
33
+ text-align: center;
34
+ }
35
+
36
+ .heatmap-streak-number {
37
+ font-size: 2em;
38
+ font-weight: bold;
39
+ color: var(--success-color);
40
+ margin-bottom: 5px;
41
+ }
42
+
43
+ .heatmap-streak-label {
44
+ color: var(--text-tertiary);
45
+ }
46
+
47
+ .heatmap-container-wrapper {
48
+ display: flex;
49
+ align-items: flex-start;
50
+ gap: 10px;
51
+ margin-bottom: 10px;
52
+ }
53
+
54
+ .heatmap-wrapper {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: flex-start;
58
+ width: 100%;
59
+ }
60
+
61
+ .heatmap-day-labels {
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 2px;
65
+ padding-top: 20px;
66
+ }
67
+
68
+ .heatmap-day-label {
69
+ width: 16px;
70
+ height: 16px;
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ font-size: 12px;
75
+ color: var(--text-tertiary);
76
+ font-weight: normal;
77
+ }
78
+
79
+ .heatmap-month-labels {
80
+ display: grid;
81
+ grid-template-columns: repeat(53, minmax(10px, 1fr));
82
+ gap: 2px;
83
+ margin-bottom: 5px;
84
+ height: 15px;
85
+ }
86
+
87
+ .heatmap-month-label {
88
+ font-size: 10px;
89
+ color: var(--text-tertiary);
90
+ text-align: left;
91
+ align-self: end;
92
+ }
93
+
94
+ .heatmap-grid {
95
+ display: grid;
96
+ grid-template-columns: repeat(53, minmax(10px, 1fr));
97
+ grid-template-rows: repeat(7, minmax(10px, 1fr));
98
+ gap: 2px;
99
+ width: 100%;
100
+ max-width: 100%;
101
+ aspect-ratio: 53/7;
102
+ }
103
+
104
+ .heatmap-cell {
105
+ width: 100%;
106
+ height: 100%;
107
+ background-color: var(--bg-tertiary);
108
+ border-radius: 2px;
109
+ position: relative;
110
+ cursor: pointer;
111
+ min-width: 10px;
112
+ min-height: 10px;
113
+ }
114
+
115
+ .heatmap-cell.level-1 { background-color: #c6e48b; }
116
+ .heatmap-cell.level-2 { background-color: #7bc96f; }
117
+ .heatmap-cell.level-3 { background-color: #239a3b; }
118
+ .heatmap-cell.level-4 { background-color: #196127; }
119
+
120
+ .heatmap-cell:hover {
121
+ stroke: #1f2328;
122
+ stroke-width: 1px;
123
+ }
124
+
125
+ .heatmap-legend {
126
+ display: flex;
127
+ align-items: center;
128
+ margin-top: 10px;
129
+ font-size: 12px;
130
+ color: #586069;
131
+ }
132
+
133
+ .heatmap-legend-item {
134
+ width: 12px;
135
+ height: 12px;
136
+ margin: 0 2px;
137
+ border-radius: 2px;
138
+ }
139
+
140
+ /* Dashboard Cards Styles */
141
+ .dashboard-container {
142
+ display: grid;
143
+ grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
144
+ gap: 30px;
145
+ margin-bottom: 40px;
146
+ }
147
+
148
+ .dashboard-card {
149
+ background: var(--bg-secondary);
150
+ border-radius: 12px;
151
+ box-shadow: 0 4px 16px var(--shadow-color);
152
+ border: 1px solid var(--border-color);
153
+ padding: 24px;
154
+ transition: all 0.3s ease;
155
+ position: relative;
156
+ overflow: hidden;
157
+ }
158
+
159
+ .dashboard-card:hover {
160
+ transform: translateY(-2px);
161
+ box-shadow: 0 8px 24px var(--shadow-color);
162
+ }
163
+
164
+ .dashboard-card::before {
165
+ content: '';
166
+ position: absolute;
167
+ top: 0;
168
+ left: 0;
169
+ right: 0;
170
+ height: 4px;
171
+ background: linear-gradient(90deg, var(--accent-color), var(--success-color));
172
+ border-radius: 12px 12px 0 0;
173
+ }
174
+
175
+ .dashboard-card.current-game::before {
176
+ background: linear-gradient(90deg, var(--accent-color), var(--info-color));
177
+ }
178
+
179
+ .dashboard-card.all-games::before {
180
+ background: linear-gradient(90deg, var(--success-color), var(--warning-color));
181
+ }
182
+
183
+ .dashboard-card.date-range::before {
184
+ background: linear-gradient(90deg, var(--info-color), var(--accent-color));
185
+ }
186
+
187
+ .dashboard-card.date-range {
188
+ margin-bottom: 30px;
189
+ }
190
+
191
+ .dashboard-card-header {
192
+ display: flex;
193
+ align-items: center;
194
+ justify-content: space-between;
195
+ margin-bottom: 20px;
196
+ }
197
+
198
+ .dashboard-card-title {
199
+ font-size: 20px;
200
+ font-weight: 600;
201
+ color: var(--text-primary);
202
+ margin: 0;
203
+ display: flex;
204
+ align-items: center;
205
+ gap: 10px;
206
+ }
207
+
208
+ .dashboard-card-icon {
209
+ font-size: 24px;
210
+ opacity: 0.8;
211
+ }
212
+
213
+ .dashboard-card-subtitle {
214
+ font-size: 14px;
215
+ color: var(--text-tertiary);
216
+ margin: 4px 0 0 0;
217
+ }
218
+
219
+ /* Stats Grid */
220
+ .dashboard-stats-grid {
221
+ display: grid;
222
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
223
+ gap: 16px;
224
+ margin-bottom: 20px;
225
+ }
226
+
227
+ .dashboard-stat-item {
228
+ text-align: center;
229
+ padding: 12px;
230
+ background: var(--bg-tertiary);
231
+ border-radius: 8px;
232
+ transition: all 0.2s ease;
233
+ position: relative;
234
+ cursor: pointer;
235
+ }
236
+
237
+ .dashboard-stat-item:hover {
238
+ background: var(--border-color);
239
+ transform: scale(1.02);
240
+ }
241
+
242
+ .dashboard-stat-value {
243
+ font-size: 24px;
244
+ font-weight: bold;
245
+ color: var(--text-primary);
246
+ margin-bottom: 4px;
247
+ display: block;
248
+ }
249
+
250
+ .dashboard-stat-label {
251
+ font-size: 12px;
252
+ color: var(--text-tertiary);
253
+ text-transform: uppercase;
254
+ letter-spacing: 0.5px;
255
+ font-weight: 500;
256
+ }
257
+
258
+ /* Progress Section */
259
+ .dashboard-progress-section {
260
+ margin-top: 20px;
261
+ padding-top: 20px;
262
+ border-top: 1px solid var(--border-color);
263
+ }
264
+
265
+ .dashboard-progress-title {
266
+ font-size: 14px;
267
+ font-weight: 600;
268
+ color: var(--text-secondary);
269
+ margin-bottom: 12px;
270
+ }
271
+
272
+ .dashboard-progress-items {
273
+ display: flex;
274
+ justify-content: space-between;
275
+ gap: 16px;
276
+ }
277
+
278
+ .dashboard-progress-item {
279
+ text-align: center;
280
+ flex: 1;
281
+ }
282
+
283
+ .dashboard-progress-value {
284
+ font-size: 18px;
285
+ font-weight: bold;
286
+ margin-bottom: 4px;
287
+ }
288
+
289
+ .dashboard-progress-value.positive {
290
+ color: var(--success-color);
291
+ }
292
+
293
+ .dashboard-progress-value.neutral {
294
+ color: var(--text-secondary);
295
+ }
296
+
297
+ .dashboard-progress-label {
298
+ font-size: 11px;
299
+ color: var(--text-tertiary);
300
+ text-transform: uppercase;
301
+ letter-spacing: 0.5px;
302
+ }
303
+
304
+ /* Streak Indicator */
305
+ .dashboard-streak-indicator {
306
+ display: inline-flex;
307
+ align-items: center;
308
+ gap: 4px;
309
+ font-size: 12px;
310
+ color: var(--success-color);
311
+ background: rgba(40, 167, 69, 0.1);
312
+ padding: 4px 8px;
313
+ border-radius: 12px;
314
+ font-weight: 500;
315
+ }
316
+
317
+ .dashboard-streak-indicator::before {
318
+ content: '🔥';
319
+ font-size: 14px;
320
+ }
321
+
322
+ /* Date Range Card */
323
+ .dashboard-date-range {
324
+ display: flex;
325
+ gap: 20px;
326
+ }
327
+
328
+ .dashboard-date-item {
329
+ flex: 1;
330
+ display: flex;
331
+ flex-direction: column;
332
+ gap: 6px;
333
+ }
334
+
335
+ .dashboard-date-item label {
336
+ font-size: 13px;
337
+ color: var(--text-secondary);
338
+ font-weight: 500;
339
+ }
340
+
341
+ .dashboard-date-input {
342
+ padding: 8px 12px;
343
+ border: 1px solid var(--border-color);
344
+ border-radius: 8px;
345
+ background: var(--bg-tertiary);
346
+ color: var(--text-primary);
347
+ font-size: 14px;
348
+ transition: all 0.2s ease;
349
+ }
350
+
351
+ .dashboard-date-input:focus {
352
+ outline: none;
353
+ border-color: var(--accent-color);
354
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.15);
355
+ }
356
+
357
+ /* Tooltip Styles */
358
+ /* Tooltip styles are now only in shared.css */
359
+
360
+ /* Loading State */
361
+ .dashboard-loading {
362
+ display: flex;
363
+ align-items: center;
364
+ justify-content: center;
365
+ min-height: 200px;
366
+ color: var(--text-tertiary);
367
+ }
368
+
369
+ .dashboard-loading .spinner {
370
+ margin-right: 10px;
371
+ }
372
+
373
+ /* Error State */
374
+ .dashboard-error {
375
+ text-align: center;
376
+ padding: 40px 20px;
377
+ color: var(--danger-color);
378
+ }
379
+
380
+ .dashboard-error-icon {
381
+ font-size: 48px;
382
+ margin-bottom: 16px;
383
+ opacity: 0.7;
384
+ }
385
+
386
+ .dashboard-error-message {
387
+ font-size: 16px;
388
+ margin-bottom: 16px;
389
+ }
390
+
391
+ .dashboard-retry-btn {
392
+ background-color: var(--accent-color);
393
+ color: white;
394
+ border: none;
395
+ padding: 10px 20px;
396
+ border-radius: 6px;
397
+ cursor: pointer;
398
+ font-size: 14px;
399
+ transition: all 0.3s ease;
400
+ }
401
+
402
+ .dashboard-retry-btn:hover {
403
+ background-color: #0056b3;
404
+ transform: translateY(-1px);
405
+ }
406
+
407
+ /* Popups */
408
+ .dashboard-popup,
409
+ .no-data-popup {
410
+ position: fixed;
411
+ top: 0;
412
+ left: 0;
413
+ right: 0;
414
+ bottom: 0;
415
+ display: flex;
416
+ align-items: center;
417
+ justify-content: center;
418
+ background: rgba(0, 0, 0, 0.4);
419
+ z-index: 2000;
420
+ }
421
+
422
+ .hidden {
423
+ display: none;
424
+ }
425
+
426
+ .dashboard-popup-content,
427
+ .no-data-content {
428
+ background: var(--bg-secondary);
429
+ border: 1px solid var(--border-color);
430
+ border-radius: 12px;
431
+ padding: 24px;
432
+ box-shadow: 0 8px 24px var(--shadow-color);
433
+ text-align: center;
434
+ max-width: 400px;
435
+ width: 90%;
436
+ }
437
+
438
+ .dashboard-popup-icon {
439
+ font-size: 32px;
440
+ margin-bottom: 12px;
441
+ }
442
+
443
+ .dashboard-popup-message,
444
+ .no-data-content p {
445
+ font-size: 14px;
446
+ color: var(--text-primary);
447
+ margin-bottom: 20px;
448
+ }
449
+
450
+ .dashboard-popup-btn,
451
+ #closeNoDataPopup {
452
+ background: var(--accent-color);
453
+ color: white;
454
+ border: none;
455
+ padding: 10px 18px;
456
+ border-radius: 8px;
457
+ font-size: 14px;
458
+ cursor: pointer;
459
+ transition: all 0.2s ease;
460
+ }
461
+
462
+ .dashboard-popup-btn:hover,
463
+ #closeNoDataPopup:hover {
464
+ background: #0056b3;
465
+ transform: translateY(-1px);
466
+ }
467
+
468
+ .dashboard-popup-content {
469
+ background: var(--bg-secondary);
470
+ border-radius: 12px;
471
+ box-shadow: 0 8px 24px var(--shadow-color);
472
+ border: 1px solid var(--border-color);
473
+ padding: 24px;
474
+ max-width: 320px;
475
+ text-align: center;
476
+ animation: popupFadeIn 0.3s ease;
477
+ }
478
+
479
+ .dashboard-popup-icon {
480
+ font-size: 36px;
481
+ margin-bottom: 12px;
482
+ }
483
+
484
+ .dashboard-popup-message {
485
+ font-size: 14px;
486
+ color: var(--danger-color);
487
+ margin-bottom: 20px;
488
+ font-weight: 500;
489
+ }
490
+
491
+ .dashboard-popup-btn {
492
+ padding: 10px 16px;
493
+ border-radius: 6px;
494
+ border: none;
495
+ background: var(--accent-color);
496
+ color: #fff;
497
+ font-size: 14px;
498
+ font-weight: 600;
499
+ cursor: pointer;
500
+ transition: all 0.2s ease;
501
+ }
502
+
503
+ .dashboard-popup-btn:hover {
504
+ background: var(--accent-color-hover, #0056b3);
505
+ transform: translateY(-1px);
506
+ }
507
+
508
+ @keyframes popupFadeIn {
509
+ from { transform: scale(0.95); opacity: 0; }
510
+ to { transform: scale(1); opacity: 1; }
511
+ }
512
+
513
+ .no-data-popup {
514
+ position: fixed;
515
+ inset: 0;
516
+ background: rgba(0,0,0,0.6);
517
+ display: flex;
518
+ justify-content: center;
519
+ align-items: center;
520
+ z-index: 2000;
521
+ }
522
+
523
+ .no-data-popup.hidden {
524
+ display: none;
525
+ }
526
+
527
+ .no-data-content {
528
+ background: var(--bg-secondary);
529
+ padding: 20px 30px;
530
+ border-radius: 10px;
531
+ text-align: center;
532
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
533
+ }
534
+
535
+ .no-data-content p {
536
+ margin-bottom: 16px;
537
+ color: var(--text-primary);
538
+ font-size: 15px;
539
+ }
540
+
541
+ .no-data-content button {
542
+ padding: 8px 16px;
543
+ background: var(--accent-color);
544
+ border: none;
545
+ border-radius: 6px;
546
+ color: #fff;
547
+ font-weight: 600;
548
+ cursor: pointer;
549
+ transition: all 0.2s ease;
550
+ }
551
+
552
+ .no-data-content button:hover {
553
+ background: #0056b3;
554
+ }
555
+
556
+ /* Goal Progress Chart Styles */
557
+ .goal-progress-chart {
558
+ background: var(--bg-secondary);
559
+ border-radius: 12px;
560
+ box-shadow: 0 4px 16px var(--shadow-color);
561
+ border: 1px solid var(--border-color);
562
+ padding: 24px;
563
+ transition: all 0.3s ease;
564
+ position: relative;
565
+ overflow: hidden;
566
+ }
567
+
568
+ .goal-progress-chart::before {
569
+ content: '';
570
+ position: absolute;
571
+ top: 0;
572
+ left: 0;
573
+ right: 0;
574
+ height: 4px;
575
+ background: linear-gradient(90deg, #2ee6e0, #3be62f, #e6dc2e);
576
+ border-radius: 12px 12px 0 0;
577
+ }
578
+
579
+ .goal-progress-chart:hover {
580
+ transform: translateY(-2px);
581
+ box-shadow: 0 8px 24px var(--shadow-color);
582
+ }
583
+
584
+ .goal-progress-grid {
585
+ display: grid;
586
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
587
+ gap: 24px;
588
+ margin-top: 20px;
589
+ }
590
+
591
+ .goal-progress-item {
592
+ background: var(--bg-tertiary);
593
+ border-radius: 8px;
594
+ padding: 20px;
595
+ border: 1px solid var(--border-color);
596
+ transition: all 0.3s ease;
597
+ }
598
+
599
+ .goal-progress-item:hover {
600
+ background: var(--border-color);
601
+ transform: scale(1.02);
602
+ }
603
+
604
+ .goal-progress-header {
605
+ display: flex;
606
+ justify-content: space-between;
607
+ align-items: center;
608
+ margin-bottom: 12px;
609
+ }
610
+
611
+ .goal-progress-label {
612
+ display: flex;
613
+ align-items: center;
614
+ gap: 8px;
615
+ font-weight: 600;
616
+ color: var(--text-primary);
617
+ font-size: 16px;
618
+ }
619
+
620
+ .goal-icon {
621
+ font-size: 20px;
622
+ opacity: 0.8;
623
+ }
624
+
625
+ .goal-progress-values {
626
+ display: flex;
627
+ align-items: center;
628
+ gap: 4px;
629
+ font-size: 14px;
630
+ font-weight: 600;
631
+ }
632
+
633
+ .goal-current {
634
+ color: var(--text-primary);
635
+ }
636
+
637
+ .goal-separator {
638
+ color: var(--text-tertiary);
639
+ margin: 0 4px;
640
+ }
641
+
642
+ .goal-target {
643
+ color: var(--text-secondary);
644
+ }
645
+
646
+ .goal-progress-bar {
647
+ height: 12px;
648
+ background: var(--bg-primary);
649
+ border-radius: 6px;
650
+ overflow: hidden;
651
+ margin-bottom: 12px;
652
+ border: 1px solid var(--border-color);
653
+ }
654
+
655
+ .goal-progress-fill {
656
+ height: 100%;
657
+ border-radius: 6px;
658
+ transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
659
+ background: var(--text-tertiary);
660
+ position: relative;
661
+ overflow: hidden;
662
+ }
663
+
664
+ .goal-progress-fill[data-percentage="100"] {
665
+ background: #2ee6e0;
666
+ }
667
+
668
+ .goal-progress-fill[data-percentage="75"] {
669
+ background: #3be62f;
670
+ }
671
+
672
+ .goal-progress-fill[data-percentage="50"] {
673
+ background: #3be62f;
674
+ }
675
+
676
+ .goal-progress-fill[data-percentage="25"] {
677
+ background: #e6dc2e;
678
+ }
679
+
680
+ .goal-progress-fill.completion-100 { background: #2ee6e0; }
681
+ .goal-progress-fill.completion-75 { background: #3be62f; }
682
+ .goal-progress-fill.completion-50 { background: #3be62f; }
683
+ .goal-progress-fill.completion-25 { background: #e6dc2e; }
684
+ .goal-progress-fill.completion-0 {
685
+ background: var(--text-tertiary);
686
+ }
687
+
688
+ [data-theme="dark"] .goal-progress-fill.completion-0 {
689
+ background: #333;
690
+ }
691
+
692
+ [data-theme="light"] .goal-progress-fill.completion-0 {
693
+ background: #fff;
694
+ border: 1px solid var(--border-color);
695
+ }
696
+
697
+ .goal-progress-info {
698
+ display: flex;
699
+ justify-content: space-between;
700
+ align-items: center;
701
+ font-size: 12px;
702
+ }
703
+
704
+ .goal-percentage {
705
+ font-weight: 600;
706
+ color: var(--text-primary);
707
+ }
708
+
709
+ .goal-projection {
710
+ color: var(--text-secondary);
711
+ font-style: italic;
712
+ }
713
+
714
+ /* Loading and Error States */
715
+ .goal-progress-loading {
716
+ display: flex;
717
+ align-items: center;
718
+ justify-content: center;
719
+ padding: 40px;
720
+ color: var(--text-tertiary);
721
+ }
722
+
723
+ .goal-progress-loading .spinner {
724
+ margin-right: 10px;
725
+ }
726
+
727
+ .goal-progress-error {
728
+ text-align: center;
729
+ padding: 40px 20px;
730
+ color: var(--danger-color);
731
+ }
732
+
733
+ .goal-progress-error-icon {
734
+ font-size: 48px;
735
+ margin-bottom: 16px;
736
+ opacity: 0.7;
737
+ }
738
+
739
+ .goal-progress-error-message {
740
+ font-size: 16px;
741
+ margin-bottom: 16px;
742
+ }
743
+
744
+ /* Responsive Design */
745
+ @media (max-width: 768px) {
746
+ .dashboard-container {
747
+ grid-template-columns: 1fr;
748
+ gap: 20px;
749
+ margin-bottom: 30px;
750
+ }
751
+
752
+ .dashboard-card {
753
+ padding: 20px;
754
+ }
755
+
756
+ .dashboard-stats-grid {
757
+ grid-template-columns: repeat(2, 1fr);
758
+ gap: 12px;
759
+ }
760
+
761
+ .dashboard-stat-value {
762
+ font-size: 20px;
763
+ }
764
+
765
+ .dashboard-progress-items {
766
+ flex-direction: column;
767
+ gap: 12px;
768
+ }
769
+
770
+ .dashboard-card-title {
771
+ font-size: 18px;
772
+ }
773
+
774
+ .dashboard-date-range {
775
+ flex-direction: column;
776
+ gap: 12px;
777
+ padding: 12px 16px;
778
+ }
779
+
780
+ .dashboard-date-item {
781
+ width: 100%;
782
+ }
783
+
784
+ .goal-progress-grid {
785
+ grid-template-columns: 1fr;
786
+ gap: 16px;
787
+ }
788
+
789
+ .goal-progress-item {
790
+ padding: 16px;
791
+ }
792
+
793
+ .goal-progress-header {
794
+ flex-direction: column;
795
+ align-items: flex-start;
796
+ gap: 8px;
797
+ }
798
+
799
+ .goal-progress-values {
800
+ font-size: 12px;
801
+ }
802
+
803
+ .goal-progress-label {
804
+ font-size: 14px;
805
+ }
806
+
807
+ .goal-progress-info {
808
+ flex-direction: column;
809
+ align-items: flex-start;
810
+ gap: 4px;
811
+ }
812
+ }
813
+
814
+ @media (max-width: 480px) {
815
+ .dashboard-stats-grid {
816
+ grid-template-columns: 1fr;
817
+ }
818
+
819
+ .dashboard-card {
820
+ padding: 16px;
821
+ }
822
+
823
+ .dashboard-stat-item {
824
+ padding: 16px;
825
+ }
826
+
827
+ .dashboard-stat-value {
828
+ font-size: 22px;
829
+ }
830
+
831
+ .goal-progress-chart {
832
+ padding: 16px;
833
+ }
834
+
835
+ .goal-progress-item {
836
+ padding: 12px;
837
+ }
838
+
839
+ .goal-icon {
840
+ font-size: 16px;
841
+ }
842
+
843
+ .goal-progress-label {
844
+ font-size: 13px;
845
+ }
846
+
847
+ .goal-progress-bar {
848
+ height: 10px;
849
+ }
850
+ }