ankigammon 1.0.6__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 (61) hide show
  1. ankigammon/__init__.py +7 -0
  2. ankigammon/__main__.py +6 -0
  3. ankigammon/analysis/__init__.py +13 -0
  4. ankigammon/analysis/score_matrix.py +391 -0
  5. ankigammon/anki/__init__.py +6 -0
  6. ankigammon/anki/ankiconnect.py +216 -0
  7. ankigammon/anki/apkg_exporter.py +111 -0
  8. ankigammon/anki/card_generator.py +1325 -0
  9. ankigammon/anki/card_styles.py +1054 -0
  10. ankigammon/gui/__init__.py +8 -0
  11. ankigammon/gui/app.py +192 -0
  12. ankigammon/gui/dialogs/__init__.py +10 -0
  13. ankigammon/gui/dialogs/export_dialog.py +594 -0
  14. ankigammon/gui/dialogs/import_options_dialog.py +201 -0
  15. ankigammon/gui/dialogs/input_dialog.py +762 -0
  16. ankigammon/gui/dialogs/note_dialog.py +93 -0
  17. ankigammon/gui/dialogs/settings_dialog.py +420 -0
  18. ankigammon/gui/dialogs/update_dialog.py +373 -0
  19. ankigammon/gui/format_detector.py +377 -0
  20. ankigammon/gui/main_window.py +1611 -0
  21. ankigammon/gui/resources/down-arrow.svg +3 -0
  22. ankigammon/gui/resources/icon.icns +0 -0
  23. ankigammon/gui/resources/icon.ico +0 -0
  24. ankigammon/gui/resources/icon.png +0 -0
  25. ankigammon/gui/resources/style.qss +402 -0
  26. ankigammon/gui/resources.py +26 -0
  27. ankigammon/gui/update_checker.py +259 -0
  28. ankigammon/gui/widgets/__init__.py +8 -0
  29. ankigammon/gui/widgets/position_list.py +166 -0
  30. ankigammon/gui/widgets/smart_input.py +268 -0
  31. ankigammon/models.py +356 -0
  32. ankigammon/parsers/__init__.py +7 -0
  33. ankigammon/parsers/gnubg_match_parser.py +1094 -0
  34. ankigammon/parsers/gnubg_parser.py +468 -0
  35. ankigammon/parsers/sgf_parser.py +290 -0
  36. ankigammon/parsers/xg_binary_parser.py +1097 -0
  37. ankigammon/parsers/xg_text_parser.py +688 -0
  38. ankigammon/renderer/__init__.py +5 -0
  39. ankigammon/renderer/animation_controller.py +391 -0
  40. ankigammon/renderer/animation_helper.py +191 -0
  41. ankigammon/renderer/color_schemes.py +145 -0
  42. ankigammon/renderer/svg_board_renderer.py +791 -0
  43. ankigammon/settings.py +315 -0
  44. ankigammon/thirdparty/__init__.py +7 -0
  45. ankigammon/thirdparty/xgdatatools/__init__.py +17 -0
  46. ankigammon/thirdparty/xgdatatools/xgimport.py +160 -0
  47. ankigammon/thirdparty/xgdatatools/xgstruct.py +1032 -0
  48. ankigammon/thirdparty/xgdatatools/xgutils.py +118 -0
  49. ankigammon/thirdparty/xgdatatools/xgzarc.py +260 -0
  50. ankigammon/utils/__init__.py +13 -0
  51. ankigammon/utils/gnubg_analyzer.py +590 -0
  52. ankigammon/utils/gnuid.py +577 -0
  53. ankigammon/utils/move_parser.py +204 -0
  54. ankigammon/utils/ogid.py +326 -0
  55. ankigammon/utils/xgid.py +387 -0
  56. ankigammon-1.0.6.dist-info/METADATA +352 -0
  57. ankigammon-1.0.6.dist-info/RECORD +61 -0
  58. ankigammon-1.0.6.dist-info/WHEEL +5 -0
  59. ankigammon-1.0.6.dist-info/entry_points.txt +2 -0
  60. ankigammon-1.0.6.dist-info/licenses/LICENSE +21 -0
  61. ankigammon-1.0.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1054 @@
1
+ """Shared card styling constants for Anki exports."""
2
+
3
+ # Model name for XG cards
4
+ MODEL_NAME = "XG Backgammon Decision"
5
+
6
+ # CSS for card styling with dark mode support
7
+ CARD_CSS = """
8
+ .card {
9
+ font-family: Arial, Helvetica, sans-serif;
10
+ font-size: 16px;
11
+ text-align: center;
12
+ color: var(--text-fg);
13
+ background-color: var(--canvas);
14
+ max-width: 800px;
15
+ margin: 0 auto;
16
+ padding: 20px;
17
+ }
18
+
19
+ .position-svg svg,
20
+ .position-svg-container svg {
21
+ max-width: 100%;
22
+ height: auto;
23
+ border: 2px solid var(--border);
24
+ border-radius: 8px;
25
+ margin: 10px 0;
26
+ display: block;
27
+ }
28
+
29
+ /* Landscape mode optimizations for mobile devices */
30
+ @media screen and (orientation: landscape) and (max-height: 600px) {
31
+ .card {
32
+ padding: 5px 5px;
33
+ max-width: 100%;
34
+ }
35
+
36
+ /* Card front - maximize board size */
37
+ .card-front .position-svg svg {
38
+ max-height: 90vh;
39
+ width: auto;
40
+ margin: 2px auto;
41
+ border-width: 1px;
42
+ }
43
+
44
+ /* Card back - slightly smaller board to fit analysis */
45
+ .card-back .position-svg svg,
46
+ .card-back .position-svg-container svg,
47
+ .card-back #animated-board svg {
48
+ max-height: 85vh;
49
+ width: auto;
50
+ margin: 2px auto;
51
+ border-width: 1px;
52
+ }
53
+
54
+ .metadata {
55
+ margin: 3px 0;
56
+ padding: 5px;
57
+ font-size: 13px;
58
+ }
59
+
60
+ .question h3 {
61
+ font-size: 16px;
62
+ margin: 6px 0 5px;
63
+ }
64
+
65
+ .mcq-option {
66
+ padding: 8px 12px;
67
+ margin: 4px 0;
68
+ font-size: 14px;
69
+ }
70
+
71
+ .mcq-hint {
72
+ margin-top: 6px;
73
+ font-size: 12px;
74
+ }
75
+
76
+ .answer {
77
+ margin: 6px 0;
78
+ padding: 8px;
79
+ }
80
+
81
+ .answer h3 {
82
+ font-size: 15px;
83
+ margin: 0 0 5px;
84
+ }
85
+
86
+ .best-move-notation {
87
+ font-size: 15px;
88
+ }
89
+
90
+ .moves-table {
91
+ font-size: 13px;
92
+ }
93
+
94
+ .moves-table th,
95
+ .moves-table td {
96
+ padding: 5px 8px;
97
+ }
98
+
99
+ .analysis h4 {
100
+ font-size: 15px;
101
+ margin-bottom: 6px;
102
+ }
103
+
104
+ .winning-chances {
105
+ padding: 8px;
106
+ margin: 8px auto;
107
+ }
108
+
109
+ .winning-chances h4 {
110
+ font-size: 15px;
111
+ margin-bottom: 6px;
112
+ }
113
+ }
114
+
115
+ /* Very small landscape screens (phones in landscape) */
116
+ @media screen and (orientation: landscape) and (max-height: 450px) {
117
+ .card {
118
+ padding: 5px 4px;
119
+ }
120
+
121
+ /* Card front - maximize board size even on small screens */
122
+ .card-front .position-svg svg {
123
+ max-height: 90vh;
124
+ width: auto;
125
+ margin: 2px auto;
126
+ border-width: 1px;
127
+ }
128
+
129
+ /* Card back - balance board with content */
130
+ .card-back .position-svg svg,
131
+ .card-back .position-svg-container svg,
132
+ .card-back #animated-board svg {
133
+ max-height: 80vh;
134
+ width: auto;
135
+ margin: 2px auto;
136
+ border-width: 1px;
137
+ }
138
+
139
+ .metadata {
140
+ margin: 2px 0;
141
+ padding: 4px;
142
+ font-size: 12px;
143
+ }
144
+
145
+ .question h3 {
146
+ font-size: 14px;
147
+ margin: 4px 0 3px;
148
+ }
149
+
150
+ .mcq-option {
151
+ padding: 6px 10px;
152
+ margin: 3px 0;
153
+ font-size: 13px;
154
+ }
155
+
156
+ .answer {
157
+ margin: 4px 0;
158
+ padding: 6px;
159
+ }
160
+
161
+ .moves-table {
162
+ font-size: 12px;
163
+ }
164
+
165
+ .moves-table th,
166
+ .moves-table td {
167
+ padding: 4px 6px;
168
+ }
169
+ }
170
+
171
+ .position-viewer {
172
+ position: relative;
173
+ }
174
+
175
+ .position-svg-container {
176
+ min-height: 200px;
177
+ }
178
+
179
+ .metadata {
180
+ font-size: 14px;
181
+ color: var(--text-fg);
182
+ margin: 10px 0;
183
+ padding: 10px;
184
+ background-color: var(--canvas-elevated);
185
+ border: 1px solid var(--border);
186
+ border-radius: 4px;
187
+ display: flex;
188
+ align-items: center;
189
+ justify-content: center;
190
+ }
191
+
192
+ .question h3 {
193
+ font-size: 20px;
194
+ margin: 20px 0 10px;
195
+ color: var(--text-fg);
196
+ }
197
+
198
+ .options {
199
+ text-align: left;
200
+ margin: 15px auto;
201
+ max-width: 500px;
202
+ }
203
+
204
+ .option {
205
+ padding: 10px;
206
+ margin: 8px 0;
207
+ background-color: var(--canvas-elevated);
208
+ border: 1px solid var(--border);
209
+ border-radius: 4px;
210
+ font-size: 16px;
211
+ }
212
+
213
+ .option strong {
214
+ color: #4da6ff;
215
+ margin-right: 10px;
216
+ }
217
+
218
+ /* Image MCQ variant */
219
+ .option-grid {
220
+ display: grid;
221
+ grid-template-columns: repeat(3, 1fr);
222
+ gap: 15px;
223
+ margin: 20px auto;
224
+ max-width: 900px;
225
+ }
226
+
227
+ .option-image {
228
+ position: relative;
229
+ border: 2px solid var(--border);
230
+ border-radius: 8px;
231
+ padding: 5px;
232
+ background-color: var(--canvas-elevated);
233
+ }
234
+
235
+ .option-image.empty {
236
+ background-color: var(--canvas-inset);
237
+ min-height: 200px;
238
+ }
239
+
240
+ .option-letter {
241
+ position: absolute;
242
+ top: 10px;
243
+ left: 10px;
244
+ background-color: #4da6ff;
245
+ color: white;
246
+ font-weight: bold;
247
+ font-size: 18px;
248
+ width: 30px;
249
+ height: 30px;
250
+ border-radius: 50%;
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ z-index: 10;
255
+ }
256
+
257
+ .option-image img {
258
+ width: 100%;
259
+ height: auto;
260
+ border-radius: 4px;
261
+ }
262
+
263
+ .option-move {
264
+ text-align: center;
265
+ font-size: 14px;
266
+ font-weight: bold;
267
+ color: var(--text-fg);
268
+ padding: 5px;
269
+ margin-top: 5px;
270
+ background-color: var(--canvas);
271
+ border-radius: 4px;
272
+ }
273
+
274
+ /* Card back */
275
+ .answer {
276
+ margin: 20px 0;
277
+ padding: 15px;
278
+ background-color: rgba(76, 175, 80, 0.15);
279
+ border: 2px solid #4caf50;
280
+ border-radius: 8px;
281
+ }
282
+
283
+ .answer h3 {
284
+ color: #66bb6a;
285
+ margin: 0 0 10px;
286
+ }
287
+
288
+ .answer-letter {
289
+ font-size: 28px;
290
+ font-weight: bold;
291
+ color: #66bb6a;
292
+ }
293
+
294
+ .best-move-notation {
295
+ font-size: 18px;
296
+ font-weight: bold;
297
+ color: #66bb6a;
298
+ margin: 10px 0;
299
+ }
300
+
301
+ /* Note Section */
302
+ .note-section {
303
+ margin: 20px 0;
304
+ padding: 15px;
305
+ background-color: rgba(249, 226, 175, 0.15);
306
+ border: 2px solid #f9e2af;
307
+ border-radius: 8px;
308
+ text-align: left;
309
+ }
310
+
311
+ .note-section h4 {
312
+ color: #c9952a;
313
+ margin: 0 0 10px;
314
+ font-size: 16px;
315
+ }
316
+
317
+ .night_mode .note-section h4 {
318
+ color: #f9e2af;
319
+ }
320
+
321
+ .note-content {
322
+ color: var(--text-fg);
323
+ font-size: 14px;
324
+ line-height: 1.6;
325
+ white-space: pre-wrap;
326
+ }
327
+
328
+ /* Winning Chances Display */
329
+ .winning-chances {
330
+ margin: 20px auto;
331
+ padding: 15px;
332
+ background-color: var(--canvas-elevated);
333
+ border: 2px solid var(--border);
334
+ border-radius: 8px;
335
+ text-align: left;
336
+ width: auto;
337
+ display: inline-block;
338
+ }
339
+
340
+ .winning-chances h4 {
341
+ font-size: 18px;
342
+ color: var(--text-fg);
343
+ margin: 0 0 12px 0;
344
+ text-align: center;
345
+ }
346
+
347
+ .chances-grid {
348
+ display: flex;
349
+ flex-direction: column;
350
+ gap: 10px;
351
+ }
352
+
353
+ .chances-row {
354
+ display: flex;
355
+ justify-content: space-between;
356
+ align-items: center;
357
+ padding: 8px 12px;
358
+ background-color: var(--canvas);
359
+ border: 1px solid var(--border);
360
+ border-radius: 4px;
361
+ }
362
+
363
+ .chances-label {
364
+ font-size: 15px;
365
+ font-weight: 500;
366
+ color: var(--text-fg);
367
+ display: flex;
368
+ align-items: center;
369
+ gap: 6px;
370
+ }
371
+
372
+ .chances-values {
373
+ font-size: 15px;
374
+ display: flex;
375
+ align-items: center;
376
+ gap: 8px;
377
+ }
378
+
379
+ .chances-values strong {
380
+ font-size: 16px;
381
+ color: #4da6ff;
382
+ }
383
+
384
+ .chances-detail {
385
+ font-size: 13px;
386
+ color: #999;
387
+ }
388
+
389
+ /* Analysis Container - for side-by-side layout */
390
+ .analysis-container {
391
+ display: flex;
392
+ gap: 20px;
393
+ align-items: flex-start;
394
+ justify-content: center;
395
+ margin: 20px 0;
396
+ }
397
+
398
+ /* Stack analysis sections vertically in landscape mode for better fit */
399
+ @media screen and (orientation: landscape) and (max-height: 600px) {
400
+ .analysis-container {
401
+ flex-direction: column;
402
+ gap: 10px;
403
+ margin: 10px 0;
404
+ }
405
+
406
+ .note-section {
407
+ margin: 10px 0;
408
+ padding: 8px;
409
+ }
410
+
411
+ .note-section h4 {
412
+ font-size: 14px;
413
+ margin-bottom: 6px;
414
+ }
415
+
416
+ .note-content {
417
+ font-size: 12px;
418
+ }
419
+
420
+ .source-info {
421
+ margin-top: 10px;
422
+ padding: 6px;
423
+ font-size: 11px;
424
+ }
425
+
426
+ .mcq-feedback-container {
427
+ margin: 8px 0;
428
+ padding: 8px;
429
+ font-size: 14px;
430
+ }
431
+
432
+ .feedback-icon {
433
+ font-size: 28px;
434
+ }
435
+ }
436
+
437
+ .analysis {
438
+ margin: 20px 0;
439
+ text-align: center;
440
+ }
441
+
442
+ .analysis h4 {
443
+ font-size: 18px;
444
+ color: var(--text-fg);
445
+ margin-bottom: 10px;
446
+ margin-top: 0;
447
+ }
448
+
449
+ /* Side-by-side sections for cube decisions */
450
+ .analysis-section,
451
+ .chances-section {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: center;
455
+ flex-shrink: 0;
456
+ }
457
+
458
+ .analysis-section h4,
459
+ .chances-section h4 {
460
+ font-size: 18px;
461
+ color: var(--text-fg);
462
+ margin: 0 0 10px 0;
463
+ text-align: center;
464
+ }
465
+
466
+ .click-hint {
467
+ font-size: 12px;
468
+ color: #999;
469
+ font-weight: normal;
470
+ font-style: italic;
471
+ }
472
+
473
+ .moves-table {
474
+ width: auto;
475
+ border-collapse: collapse;
476
+ margin: 10px auto;
477
+ text-align: left;
478
+ }
479
+
480
+ .moves-table th,
481
+ .moves-table td {
482
+ padding: 10px;
483
+ text-align: left;
484
+ border-bottom: 1px solid var(--border);
485
+ }
486
+
487
+ .moves-table th {
488
+ background-color: var(--canvas-elevated);
489
+ font-weight: bold;
490
+ color: var(--text-fg);
491
+ }
492
+
493
+ .moves-table tr.best-move {
494
+ background-color: rgba(76, 175, 80, 0.15);
495
+ font-weight: bold;
496
+ }
497
+
498
+ .moves-table tr.best-move td {
499
+ color: #66bb6a;
500
+ }
501
+
502
+ .move-row {
503
+ cursor: pointer;
504
+ transition: background-color 0.2s ease;
505
+ }
506
+
507
+ .move-row:hover {
508
+ background-color: rgba(100, 150, 255, 0.1) !important;
509
+ }
510
+
511
+ .move-row.selected {
512
+ background-color: rgba(100, 150, 255, 0.2) !important;
513
+ border-left: 3px solid #4da6ff;
514
+ }
515
+
516
+ .move-row.best-move.selected {
517
+ background-color: rgba(76, 175, 80, 0.25) !important;
518
+ border-left: 3px solid #66bb6a;
519
+ }
520
+
521
+ /* Move Notation and Inline W/G/B Display */
522
+ .move-notation {
523
+ font-weight: bold;
524
+ font-size: 15px;
525
+ margin-bottom: 4px;
526
+ }
527
+
528
+ .move-wgb-inline {
529
+ font-size: 12px;
530
+ line-height: 1.5;
531
+ margin-top: 6px;
532
+ }
533
+
534
+ .wgb-line {
535
+ display: flex;
536
+ align-items: center;
537
+ gap: 4px;
538
+ margin: 2px 0;
539
+ }
540
+
541
+ .wgb-line strong {
542
+ color: #4da6ff;
543
+ font-size: 13px;
544
+ }
545
+
546
+ .wgb-detail {
547
+ color: #999;
548
+ font-size: 11px;
549
+ margin-left: 2px;
550
+ }
551
+
552
+ .source-info {
553
+ margin-top: 20px;
554
+ padding: 10px;
555
+ background-color: var(--canvas-elevated);
556
+ border: 1px solid var(--border);
557
+ border-radius: 4px;
558
+ font-size: 12px;
559
+ color: var(--text-fg);
560
+ text-align: left;
561
+ }
562
+
563
+ .source-info code {
564
+ background-color: var(--canvas-inset);
565
+ padding: 2px 6px;
566
+ border-radius: 3px;
567
+ font-family: monospace;
568
+ font-size: 11px;
569
+ }
570
+
571
+ /* Position viewer controls */
572
+ .position-label {
573
+ display: flex;
574
+ justify-content: space-between;
575
+ align-items: center;
576
+ margin: 10px 0;
577
+ padding: 8px 12px;
578
+ background-color: var(--canvas-elevated);
579
+ border: 1px solid var(--border);
580
+ border-radius: 4px;
581
+ }
582
+
583
+ #position-status {
584
+ font-size: 14px;
585
+ font-weight: bold;
586
+ color: var(--text-fg);
587
+ }
588
+
589
+ button.toggle-btn,
590
+ button.toggle-btn:link,
591
+ button.toggle-btn:visited {
592
+ padding: 6px 12px;
593
+ background-color: #4da6ff;
594
+ color: #ffffff;
595
+ border: none;
596
+ border-radius: 4px;
597
+ cursor: pointer;
598
+ font-size: 12px;
599
+ font-weight: bold;
600
+ transition: background-color 0.2s ease;
601
+ text-decoration: none;
602
+ }
603
+
604
+ button.toggle-btn:hover {
605
+ background-color: #3d8fcc;
606
+ color: #ffffff;
607
+ }
608
+
609
+ button.toggle-btn:active {
610
+ background-color: #2d7fbc;
611
+ color: #ffffff;
612
+ }
613
+
614
+ /* ===================================================================
615
+ INTERACTIVE MCQ STYLES
616
+ =================================================================== */
617
+
618
+ /* Front Side: Clickable Options */
619
+ .mcq-option {
620
+ cursor: pointer;
621
+ padding: 12px 16px;
622
+ margin: 10px 0;
623
+ background-color: var(--canvas-elevated);
624
+ border: 2px solid var(--border);
625
+ border-radius: 6px;
626
+ font-size: 16px;
627
+ transition: all 0.2s ease;
628
+ user-select: none; /* Prevent text selection on click */
629
+ }
630
+
631
+ .mcq-option:hover {
632
+ background-color: rgba(100, 150, 255, 0.1);
633
+ border-color: #4da6ff;
634
+ transform: translateX(4px);
635
+ }
636
+
637
+ .mcq-option.selected-flash {
638
+ background-color: rgba(100, 150, 255, 0.3);
639
+ border-color: #4da6ff;
640
+ border-width: 3px;
641
+ }
642
+
643
+ /* Hint text below options */
644
+ .mcq-hint {
645
+ margin-top: 20px;
646
+ font-size: 13px;
647
+ color: #999;
648
+ font-style: italic;
649
+ text-align: center;
650
+ }
651
+
652
+ /* Back Side: Feedback Messages */
653
+ .mcq-feedback-container {
654
+ margin: 20px 0;
655
+ padding: 20px;
656
+ border-radius: 8px;
657
+ font-size: 16px;
658
+ }
659
+
660
+ .mcq-feedback-correct,
661
+ .mcq-feedback-close,
662
+ .mcq-feedback-incorrect,
663
+ .mcq-feedback-neutral {
664
+ display: flex;
665
+ align-items: center;
666
+ gap: 15px;
667
+ }
668
+
669
+ .feedback-icon {
670
+ font-size: 40px;
671
+ font-weight: bold;
672
+ flex-shrink: 0;
673
+ }
674
+
675
+ .feedback-text {
676
+ flex-grow: 1;
677
+ }
678
+
679
+ /* Correct feedback (green) */
680
+ .mcq-feedback-correct {
681
+ background-color: rgba(76, 175, 80, 0.15);
682
+ border: 2px solid #4caf50;
683
+ padding: 15px 20px;
684
+ }
685
+
686
+ .mcq-feedback-correct .feedback-icon {
687
+ color: #4caf50;
688
+ }
689
+
690
+ .mcq-feedback-correct .feedback-text {
691
+ color: #2e7d32;
692
+ }
693
+
694
+ /* Close feedback (orange/yellow - nearly correct) */
695
+ .mcq-feedback-close {
696
+ background-color: rgba(255, 152, 0, 0.15);
697
+ border: 2px solid #ff9800;
698
+ padding: 15px 20px;
699
+ }
700
+
701
+ .mcq-feedback-close .feedback-icon {
702
+ color: #ff9800;
703
+ }
704
+
705
+ .mcq-feedback-close .feedback-text {
706
+ color: #ef6c00;
707
+ }
708
+
709
+ /* Incorrect feedback (red) */
710
+ .mcq-feedback-incorrect {
711
+ background-color: rgba(244, 67, 54, 0.15);
712
+ border: 2px solid #f44336;
713
+ padding: 15px 20px;
714
+ }
715
+
716
+ .mcq-feedback-incorrect .feedback-icon {
717
+ color: #f44336;
718
+ }
719
+
720
+ .mcq-feedback-incorrect .feedback-text {
721
+ color: #c62828;
722
+ }
723
+
724
+ .feedback-separator {
725
+ margin: 0 12px;
726
+ color: #999;
727
+ font-weight: bold;
728
+ }
729
+
730
+ /* Neutral feedback (no selection) */
731
+ .mcq-feedback-neutral {
732
+ background-color: rgba(158, 158, 158, 0.1);
733
+ border: 2px solid #9e9e9e;
734
+ padding: 15px;
735
+ }
736
+
737
+ .mcq-feedback-neutral .feedback-text {
738
+ color: var(--text-fg);
739
+ }
740
+
741
+ /* Dark mode adjustments */
742
+ .night_mode .mcq-feedback-correct {
743
+ background-color: rgba(76, 175, 80, 0.25);
744
+ }
745
+
746
+ .night_mode .mcq-feedback-close {
747
+ background-color: rgba(255, 152, 0, 0.25);
748
+ }
749
+
750
+ .night_mode .mcq-feedback-incorrect {
751
+ background-color: rgba(244, 67, 54, 0.25);
752
+ }
753
+
754
+ .night_mode .mcq-feedback-neutral {
755
+ background-color: rgba(158, 158, 158, 0.2);
756
+ }
757
+
758
+ /* Highlight user's selected move in analysis table */
759
+ tr.user-correct {
760
+ background-color: rgba(76, 175, 80, 0.15) !important;
761
+ border-left: 3px solid #4caf50;
762
+ }
763
+
764
+ tr.user-close {
765
+ background-color: rgba(255, 152, 0, 0.15) !important;
766
+ border-left: 3px solid #ff9800;
767
+ }
768
+
769
+ tr.user-incorrect {
770
+ background-color: rgba(244, 67, 54, 0.15) !important;
771
+ border-left: 3px solid #f44336;
772
+ }
773
+
774
+ .night_mode tr.user-correct {
775
+ background-color: rgba(76, 175, 80, 0.25) !important;
776
+ }
777
+
778
+ .night_mode tr.user-close {
779
+ background-color: rgba(255, 152, 0, 0.25) !important;
780
+ }
781
+
782
+ .night_mode tr.user-incorrect {
783
+ background-color: rgba(244, 67, 54, 0.25) !important;
784
+ }
785
+
786
+ /* ===================================================================
787
+ ANIMATION STYLES
788
+ =================================================================== */
789
+
790
+ /* Position viewer animation container */
791
+ .position-viewer {
792
+ position: relative;
793
+ overflow: hidden;
794
+ }
795
+
796
+ .position-svg-container {
797
+ transition: opacity 0.3s ease-in-out;
798
+ }
799
+
800
+ /* Smooth fade transitions for position switching */
801
+ .position-svg-container.fade-out {
802
+ opacity: 0;
803
+ }
804
+
805
+ .position-svg-container.fade-in {
806
+ opacity: 1;
807
+ }
808
+
809
+ /* Animation controls */
810
+ .animation-controls {
811
+ margin: 15px 0;
812
+ }
813
+
814
+ button.animate-btn {
815
+ padding: 8px 16px;
816
+ background-color: #ff9800;
817
+ color: #ffffff;
818
+ border: none;
819
+ border-radius: 4px;
820
+ cursor: pointer;
821
+ font-size: 14px;
822
+ font-weight: bold;
823
+ transition: background-color 0.2s ease;
824
+ text-decoration: none;
825
+ }
826
+
827
+ button.animate-btn:hover {
828
+ background-color: #f57c00;
829
+ color: #ffffff;
830
+ }
831
+
832
+ button.animate-btn:active {
833
+ background-color: #e65100;
834
+ color: #ffffff;
835
+ }
836
+
837
+ button.animate-btn:disabled {
838
+ background-color: #ccc;
839
+ cursor: not-allowed;
840
+ }
841
+
842
+ /* Checker animation styles */
843
+ .checker {
844
+ transition: all 0.3s ease-in-out;
845
+ }
846
+
847
+ /* Support for GSAP animations */
848
+ .checker-animated {
849
+ will-change: transform, opacity;
850
+ }
851
+
852
+ /* Animation overlay for temporary animation layer */
853
+ #anim-svg-temp {
854
+ pointer-events: none;
855
+ z-index: 100;
856
+ }
857
+
858
+ /* Smooth transitions for SVG visibility */
859
+ .position-svg-container[style*="display: none"] {
860
+ display: none !important;
861
+ }
862
+
863
+ .position-svg-container[style*="display: block"] {
864
+ display: block !important;
865
+ }
866
+
867
+ /* ===================================================================
868
+ SCORE MATRIX STYLES
869
+ =================================================================== */
870
+
871
+ .score-matrix {
872
+ margin: 30px auto 20px;
873
+ text-align: center;
874
+ }
875
+
876
+ .score-matrix h3 {
877
+ font-size: 18px;
878
+ color: var(--text-fg);
879
+ margin-bottom: 15px;
880
+ }
881
+
882
+ .score-matrix h3 .ply-indicator {
883
+ font-size: 14px;
884
+ opacity: 0.6;
885
+ font-weight: normal;
886
+ }
887
+
888
+ .score-matrix-table {
889
+ border-collapse: collapse;
890
+ margin: 0 auto;
891
+ font-size: 13px;
892
+ background-color: var(--canvas-elevated);
893
+ border: 2px solid var(--border);
894
+ border-radius: 6px;
895
+ overflow: hidden;
896
+ }
897
+
898
+ .score-matrix-table th {
899
+ background-color: var(--canvas-elevated);
900
+ color: var(--text-fg);
901
+ font-weight: bold;
902
+ padding: 8px 12px;
903
+ border: 1px solid var(--border);
904
+ }
905
+
906
+ .score-matrix-table td {
907
+ padding: 8px 12px;
908
+ border: 1px solid var(--border);
909
+ text-align: center;
910
+ min-width: 70px;
911
+ }
912
+
913
+ /* Cube action color coding */
914
+ .score-matrix-table .action-double-take {
915
+ background-color: rgba(76, 175, 80, 0.3);
916
+ }
917
+
918
+ .score-matrix-table .action-double-pass {
919
+ background-color: rgba(255, 152, 0, 0.3);
920
+ }
921
+
922
+ .score-matrix-table .action-no-double {
923
+ background-color: rgba(33, 150, 243, 0.3);
924
+ }
925
+
926
+ .score-matrix-table .action-too-good {
927
+ background-color: rgba(156, 39, 176, 0.3);
928
+ }
929
+
930
+ .score-matrix-table .action-no-alternatives {
931
+ background-color: rgba(158, 158, 158, 0.15);
932
+ color: #999;
933
+ }
934
+
935
+ /* Low error cells - more transparent to show it's a close decision */
936
+ .score-matrix-table .action-double-take.low-error {
937
+ background-color: rgba(76, 175, 80, 0.12);
938
+ }
939
+
940
+ .score-matrix-table .action-double-pass.low-error {
941
+ background-color: rgba(255, 152, 0, 0.12);
942
+ }
943
+
944
+ .score-matrix-table .action-no-double.low-error {
945
+ background-color: rgba(33, 150, 243, 0.12);
946
+ }
947
+
948
+ .score-matrix-table .action-too-good.low-error {
949
+ background-color: rgba(156, 39, 176, 0.12);
950
+ }
951
+
952
+ /* Current score cell highlight */
953
+ .score-matrix-table .current-score {
954
+ border: 3px solid #FFD700;
955
+ box-shadow: 0 0 8px rgba(255, 215, 0, 0.6);
956
+ }
957
+
958
+ /* Matrix cell content */
959
+ .score-matrix-table .action {
960
+ font-weight: bold;
961
+ font-size: 14px;
962
+ margin-bottom: 4px;
963
+ }
964
+
965
+ .score-matrix-table .errors {
966
+ font-size: 11px;
967
+ color: #666;
968
+ }
969
+
970
+ .night_mode .score-matrix-table .errors {
971
+ color: #aaa;
972
+ }
973
+
974
+ /* Dark mode adjustments */
975
+ .night_mode .score-matrix-table .action-double-take {
976
+ background-color: rgba(76, 175, 80, 0.4);
977
+ }
978
+
979
+ .night_mode .score-matrix-table .action-double-pass {
980
+ background-color: rgba(255, 152, 0, 0.4);
981
+ }
982
+
983
+ .night_mode .score-matrix-table .action-no-double {
984
+ background-color: rgba(33, 150, 243, 0.4);
985
+ }
986
+
987
+ .night_mode .score-matrix-table .action-too-good {
988
+ background-color: rgba(156, 39, 176, 0.4);
989
+ }
990
+
991
+ .night_mode .score-matrix-table .action-no-alternatives {
992
+ background-color: rgba(158, 158, 158, 0.25);
993
+ color: #bbb;
994
+ }
995
+
996
+ /* Dark mode low error cells */
997
+ .night_mode .score-matrix-table .action-double-take.low-error {
998
+ background-color: rgba(76, 175, 80, 0.15);
999
+ }
1000
+
1001
+ .night_mode .score-matrix-table .action-double-pass.low-error {
1002
+ background-color: rgba(255, 152, 0, 0.15);
1003
+ }
1004
+
1005
+ .night_mode .score-matrix-table .action-no-double.low-error {
1006
+ background-color: rgba(33, 150, 243, 0.15);
1007
+ }
1008
+
1009
+ .night_mode .score-matrix-table .action-too-good.low-error {
1010
+ background-color: rgba(156, 39, 176, 0.15);
1011
+ }
1012
+
1013
+ /* Score matrix optimizations for landscape mode */
1014
+ @media screen and (orientation: landscape) and (max-height: 600px) {
1015
+ .score-matrix {
1016
+ margin: 15px auto 10px;
1017
+ }
1018
+
1019
+ .score-matrix h3 {
1020
+ font-size: 14px;
1021
+ margin-bottom: 8px;
1022
+ }
1023
+
1024
+ .score-matrix h3 .ply-indicator {
1025
+ font-size: 11px;
1026
+ }
1027
+
1028
+ .score-matrix-table {
1029
+ font-size: 11px;
1030
+ }
1031
+
1032
+ .score-matrix-table th,
1033
+ .score-matrix-table td {
1034
+ padding: 4px 6px;
1035
+ min-width: 50px;
1036
+ }
1037
+
1038
+ .score-matrix-table .action {
1039
+ font-size: 12px;
1040
+ margin-bottom: 2px;
1041
+ }
1042
+
1043
+ .score-matrix-table .errors {
1044
+ font-size: 10px;
1045
+ }
1046
+ }
1047
+
1048
+ /* Hide score matrix on very small landscape screens to prevent scrolling */
1049
+ @media screen and (orientation: landscape) and (max-height: 450px) {
1050
+ .score-matrix {
1051
+ display: none;
1052
+ }
1053
+ }
1054
+ """