t Claude (claude-opus-4-5-thinking) commited on
Commit
b08752b
·
1 Parent(s): c0f39fc

style: unify UI/UX across question entry and quiz templates

Browse files

- Add CSS variables for consistent color scheme (--bg-dark, --accent-info, etc.)
- Unify note card/section styling with gradient backgrounds and hover effects
- Add consistent btn-pill styling with hover transforms
- Apply gradient backgrounds to modal headers
- Improve progress bar with gradient fill
- Add consistent transitions (--transition-fast, --transition-normal)
- Unify toolbar and button styling in notes modal
- Add shadow variables for consistent depth

Co-Authored-By: Claude (claude-opus-4-5-thinking) <noreply@anthropic.com>

templates/question_entry_v2.html CHANGED
@@ -5,48 +5,91 @@
5
  {% block head %}
6
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
7
  <style>
8
- .keyboard-hint { font-size: 0.8em; color: #6c757d; margin-top: 2px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  .status-buttons { display: flex; gap: 0.25rem; margin-top: 0.25rem; }
10
- .status-btn { flex: 1; font-size: 0.75rem; padding: 0.25rem 0.5rem; border: 1px solid #495057; background: transparent; color: #fff; border-radius: 0.25rem; cursor: pointer; transition: all 0.2s; }
11
- .status-btn.active { background: #0d6efd; border-color: #0d6efd; }
12
- .status-btn:hover { background: #495057; }
 
 
 
 
 
 
 
 
 
 
13
  .auto-extract-btn { min-width: 120px; }
14
 
15
  /* Subject pills */
16
- .subject-pill { transition: all 0.2s; }
17
- .subject-pill.active { transform: scale(1.05); box-shadow: 0 0 10px rgba(255,255,255,0.3); }
 
 
 
 
 
 
18
 
19
  /* Range toggles */
20
- .range-toggle { transition: all 0.2s; }
 
 
 
 
 
 
21
  .range-toggle.active { transform: scale(1.02); box-shadow: 0 0 8px rgba(255,255,255,0.2); }
22
- .range-toggle.active.btn-outline-primary { background: #0d6efd; color: #fff; }
23
- .range-toggle.active.btn-outline-warning { background: #ffc107; color: #000; }
24
- .range-toggle.active.btn-outline-danger { background: #dc3545; color: #fff; }
25
- .range-toggle.active.btn-outline-secondary { background: #6c757d; color: #fff; }
26
- .range-toggle.active.btn-outline-info { background: #0dcaf0; color: #000; }
27
 
28
  /* Range slider styling */
29
- .range-slider-row { background: #343a40; border-radius: 8px; padding: 12px; margin-bottom: 10px; }
30
- .range-slider-row:hover { background: #3d444b; }
31
  .dual-range-container { position: relative; height: 40px; }
32
- .dual-range-track { position: absolute; top: 50%; left: 0; right: 0; height: 8px; background: #495057; border-radius: 4px; transform: translateY(-50%); }
33
- .dual-range-highlight { position: absolute; top: 50%; height: 8px; background: linear-gradient(90deg, #0d6efd, #0dcaf0); border-radius: 4px; transform: translateY(-50%); }
34
  .dual-range-container input[type="range"] { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: none; background: transparent; pointer-events: none; }
35
- .dual-range-container input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 24px; background: #fff; border: 3px solid #0d6efd; border-radius: 50%; cursor: pointer; pointer-events: auto; box-shadow: 0 2px 6px rgba(0,0,0,0.3); transition: transform 0.15s; }
36
  .dual-range-container input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.15); }
37
- .dual-range-container input[type="range"]::-moz-range-thumb { width: 24px; height: 24px; background: #fff; border: 3px solid #0d6efd; border-radius: 50%; cursor: pointer; pointer-events: auto; box-shadow: 0 2px 6px rgba(0,0,0,0.3); }
38
 
39
  /* Tom Select Dark Theme */
40
  .ts-wrapper .ts-control, .ts-wrapper .ts-control input {
41
- background: #212529;
42
  color: #fff;
43
- border-color: #6c757d;
44
  }
45
 
46
  .ts-dropdown {
47
- background: #212529;
48
  color: #fff;
49
- border-color: #6c757d;
50
  }
51
 
52
  .ts-dropdown .option {
@@ -54,9 +97,9 @@
54
  }
55
 
56
  .ts-dropdown .option:hover, .ts-dropdown .active {
57
- background: #495057;
58
  }
59
-
60
  /* Notes Modal Styles */
61
  #notes-canvas-body {
62
  height: calc(100vh - 140px);
@@ -68,16 +111,16 @@
68
  #notes-canvas-container {
69
  height: 100%;
70
  background: #f8f9fa;
71
- border: 1px solid #495057;
72
  overflow: hidden;
73
  position: relative;
74
  display: flex;
75
  justify-content: center;
76
  align-items: center;
77
- touch-action: none; /* Prevent browser gestures from interfering */
78
  }
79
  #notes-canvas-container canvas {
80
- touch-action: none; /* Critical for stylus/touch drawing */
81
  }
82
  @media (max-width: 768px) {
83
  #question-reference-panel {
@@ -88,8 +131,8 @@
88
  display: flex;
89
  gap: 8px;
90
  padding: 12px 16px;
91
- background: linear-gradient(180deg, #2c3034, #212529);
92
- border-bottom: 1px solid #495057;
93
  flex-wrap: wrap;
94
  align-items: center;
95
  }
@@ -97,7 +140,7 @@
97
  display: flex;
98
  gap: 4px;
99
  padding: 0 8px;
100
- border-right: 1px solid #495057;
101
  }
102
  .notes-toolbar .tool-group:last-child {
103
  border-right: none;
@@ -108,6 +151,14 @@
108
  display: flex;
109
  align-items: center;
110
  justify-content: center;
 
 
 
 
 
 
 
 
111
  }
112
  .color-swatch {
113
  width: 28px;
@@ -115,23 +166,33 @@
115
  border-radius: 50%;
116
  cursor: pointer;
117
  border: 2px solid transparent;
118
- transition: transform 0.15s, border-color 0.15s;
119
  }
120
  .color-swatch:hover { transform: scale(1.1); }
121
- .color-swatch.active { border-color: #fff; transform: scale(1.15); box-shadow: 0 0 8px rgba(255,255,255,0.5); }
122
 
123
- /* Note Card Styles */
124
  .note-card {
125
- background: rgba(13, 202, 240, 0.1);
126
- border: 1px solid #0dcaf0;
127
- border-radius: 8px;
128
- padding: 8px;
129
  margin-bottom: 8px;
 
 
 
 
 
130
  }
131
  .note-thumbnail {
132
  max-height: 80px;
133
  object-fit: contain;
134
- border-radius: 4px;
 
 
 
 
 
135
  }
136
  .note-actions {
137
  display: flex;
@@ -142,7 +203,18 @@
142
  cursor: pointer;
143
  }
144
  .include-pdf-toggle input:checked + .form-check-label {
145
- color: #0dcaf0;
 
 
 
 
 
 
 
 
 
 
 
146
  }
147
  </style>
148
  {% endblock %}
@@ -223,16 +295,16 @@
223
  onchange="toggleNoteInPdf('{{ image.id }}', this.checked)">
224
  <label class="form-check-label small" for="include_note_{{ image.id }}">In PDF</label>
225
  </div>
226
- <button type="button" class="btn btn-sm btn-outline-info" onclick="openNotesModal('{{ image.id }}', '/image/processed/{{ session_id }}/{{ image.processed_filename }}', '{{ image.note_filename }}')" title="Edit Note">
227
  <i class="bi bi-pencil"></i>
228
  </button>
229
- <button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteNote('{{ image.id }}')" title="Delete Note">
230
  <i class="bi bi-trash"></i>
231
  </button>
232
  </div>
233
  </div>
234
  {% else %}
235
- <button type="button" class="btn btn-sm btn-outline-info w-100" onclick="openNotesModal('{{ image.id }}', '/image/processed/{{ session_id }}/{{ image.processed_filename }}', '')">
236
  <i class="bi bi-pencil-square me-1"></i>Add Revision Notes
237
  </button>
238
  {% endif %}
@@ -383,13 +455,13 @@
383
  <div class="modal fade" id="notesModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
384
  <div class="modal-dialog modal-fullscreen">
385
  <div class="modal-content bg-dark text-white">
386
- <div class="modal-header py-2 border-secondary">
387
  <h5 class="modal-title"><i class="bi bi-pencil-fill me-2"></i>Add Revision Notes</h5>
388
  <div class="d-flex gap-2">
389
- <button class="btn btn-success" onclick="saveNotes()">
390
  <i class="bi bi-check-lg me-1"></i>Save Notes
391
  </button>
392
- <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
393
  <i class="bi bi-x-lg me-1"></i>Cancel
394
  </button>
395
  </div>
@@ -519,7 +591,7 @@
519
  <div class="modal fade" id="manualClassificationModal" tabindex="-1">
520
  <div class="modal-dialog modal-lg">
521
  <div class="modal-content bg-dark text-white">
522
- <div class="modal-header border-secondary">
523
  <h5 class="modal-title"><i class="bi bi-list-check me-2"></i>Quick Classification</h5>
524
  <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
525
  </div>
@@ -602,7 +674,7 @@
602
  </div>
603
  </div>
604
  <div class="modal-footer border-secondary">
605
- <button type="button" class="btn btn-lg btn-primary w-100" onclick="startManualClassification()">
606
  <i class="bi bi-play-fill me-2"></i>Start Classification
607
  </button>
608
  </div>
@@ -614,11 +686,11 @@
614
  <div class="modal fade" id="topicSelectionModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
615
  <div class="modal-dialog modal-lg modal-dialog-centered">
616
  <div class="modal-content bg-dark text-white border-secondary">
617
- <div class="modal-header border-secondary py-2">
618
  <div class="d-flex align-items-center gap-3">
619
  <span class="badge bg-primary fs-6" id="topic_q_num">#1</span>
620
  <div class="progress flex-grow-1" style="width: 150px; height: 6px;">
621
- <div class="progress-bar" id="topic_progress_bar" role="progressbar" style="width: 0%"></div>
622
  </div>
623
  <small id="topic_progress" class="text-muted">1/10</small>
624
  </div>
@@ -668,10 +740,10 @@
668
  <div id="ai_error_msg" class="alert alert-danger d-none mt-2 py-2"></div>
669
  </div>
670
  <div class="modal-footer border-secondary py-2">
671
- <button type="button" class="btn btn-outline-secondary btn-lg px-4" onclick="prevTopicQuestion()">
672
  <i class="bi bi-chevron-left"></i>
673
  </button>
674
- <button type="button" class="btn btn-primary btn-lg px-5" onclick="nextTopicQuestion()">
675
  Next <i class="bi bi-chevron-right ms-1"></i>
676
  </button>
677
  </div>
 
5
  {% block head %}
6
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
7
  <style>
8
+ /* === UNIFIED DESIGN SYSTEM === */
9
+ :root {
10
+ --bg-dark: #212529;
11
+ --bg-card: #2b3035;
12
+ --bg-elevated: #343a40;
13
+ --bg-hover: #3d444b;
14
+ --border-subtle: #495057;
15
+ --border-muted: #6c757d;
16
+ --text-primary: #e9ecef;
17
+ --text-muted: #adb5bd;
18
+ --accent-primary: #0d6efd;
19
+ --accent-info: #0dcaf0;
20
+ --accent-success: #198754;
21
+ --accent-warning: #ffc107;
22
+ --accent-danger: #dc3545;
23
+ --transition-fast: 0.15s ease;
24
+ --transition-normal: 0.25s ease;
25
+ --shadow-sm: 0 2px 4px rgba(0,0,0,0.3);
26
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.4);
27
+ }
28
+
29
+ .keyboard-hint { font-size: 0.8em; color: var(--text-muted); margin-top: 2px; }
30
  .status-buttons { display: flex; gap: 0.25rem; margin-top: 0.25rem; }
31
+ .status-btn {
32
+ flex: 1;
33
+ font-size: 0.75rem;
34
+ padding: 0.25rem 0.5rem;
35
+ border: 1px solid var(--border-subtle);
36
+ background: transparent;
37
+ color: #fff;
38
+ border-radius: 20px;
39
+ cursor: pointer;
40
+ transition: all var(--transition-fast);
41
+ }
42
+ .status-btn.active { background: var(--accent-primary); border-color: var(--accent-primary); }
43
+ .status-btn:hover { background: var(--bg-hover); transform: translateY(-1px); }
44
  .auto-extract-btn { min-width: 120px; }
45
 
46
  /* Subject pills */
47
+ .subject-pill {
48
+ transition: all var(--transition-fast);
49
+ border-radius: 20px;
50
+ }
51
+ .subject-pill.active {
52
+ transform: scale(1.05);
53
+ box-shadow: 0 0 12px rgba(255,255,255,0.3);
54
+ }
55
 
56
  /* Range toggles */
57
+ .range-toggle {
58
+ transition: all var(--transition-fast);
59
+ border-radius: 20px;
60
+ }
61
+ .range-toggle:hover {
62
+ transform: translateY(-1px);
63
+ }
64
  .range-toggle.active { transform: scale(1.02); box-shadow: 0 0 8px rgba(255,255,255,0.2); }
65
+ .range-toggle.active.btn-outline-primary { background: var(--accent-primary); color: #fff; }
66
+ .range-toggle.active.btn-outline-warning { background: var(--accent-warning); color: #000; }
67
+ .range-toggle.active.btn-outline-danger { background: var(--accent-danger); color: #fff; }
68
+ .range-toggle.active.btn-outline-secondary { background: var(--border-muted); color: #fff; }
69
+ .range-toggle.active.btn-outline-info { background: var(--accent-info); color: #000; }
70
 
71
  /* Range slider styling */
72
+ .range-slider-row { background: var(--bg-elevated); border-radius: 10px; padding: 12px; margin-bottom: 10px; transition: all var(--transition-fast); }
73
+ .range-slider-row:hover { background: var(--bg-hover); }
74
  .dual-range-container { position: relative; height: 40px; }
75
+ .dual-range-track { position: absolute; top: 50%; left: 0; right: 0; height: 8px; background: var(--border-subtle); border-radius: 4px; transform: translateY(-50%); }
76
+ .dual-range-highlight { position: absolute; top: 50%; height: 8px; background: linear-gradient(90deg, var(--accent-primary), var(--accent-info)); border-radius: 4px; transform: translateY(-50%); }
77
  .dual-range-container input[type="range"] { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: none; background: transparent; pointer-events: none; }
78
+ .dual-range-container input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 24px; background: #fff; border: 3px solid var(--accent-primary); border-radius: 50%; cursor: pointer; pointer-events: auto; box-shadow: var(--shadow-sm); transition: transform var(--transition-fast); }
79
  .dual-range-container input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.15); }
80
+ .dual-range-container input[type="range"]::-moz-range-thumb { width: 24px; height: 24px; background: #fff; border: 3px solid var(--accent-primary); border-radius: 50%; cursor: pointer; pointer-events: auto; box-shadow: var(--shadow-sm); }
81
 
82
  /* Tom Select Dark Theme */
83
  .ts-wrapper .ts-control, .ts-wrapper .ts-control input {
84
+ background: var(--bg-dark);
85
  color: #fff;
86
+ border-color: var(--border-muted);
87
  }
88
 
89
  .ts-dropdown {
90
+ background: var(--bg-dark);
91
  color: #fff;
92
+ border-color: var(--border-muted);
93
  }
94
 
95
  .ts-dropdown .option {
 
97
  }
98
 
99
  .ts-dropdown .option:hover, .ts-dropdown .active {
100
+ background: var(--border-subtle);
101
  }
102
+
103
  /* Notes Modal Styles */
104
  #notes-canvas-body {
105
  height: calc(100vh - 140px);
 
111
  #notes-canvas-container {
112
  height: 100%;
113
  background: #f8f9fa;
114
+ border: 1px solid var(--border-subtle);
115
  overflow: hidden;
116
  position: relative;
117
  display: flex;
118
  justify-content: center;
119
  align-items: center;
120
+ touch-action: none;
121
  }
122
  #notes-canvas-container canvas {
123
+ touch-action: none;
124
  }
125
  @media (max-width: 768px) {
126
  #question-reference-panel {
 
131
  display: flex;
132
  gap: 8px;
133
  padding: 12px 16px;
134
+ background: linear-gradient(180deg, var(--bg-card), var(--bg-dark));
135
+ border-bottom: 1px solid var(--border-subtle);
136
  flex-wrap: wrap;
137
  align-items: center;
138
  }
 
140
  display: flex;
141
  gap: 4px;
142
  padding: 0 8px;
143
+ border-right: 1px solid var(--border-subtle);
144
  }
145
  .notes-toolbar .tool-group:last-child {
146
  border-right: none;
 
151
  display: flex;
152
  align-items: center;
153
  justify-content: center;
154
+ border-radius: 8px;
155
+ transition: all var(--transition-fast);
156
+ }
157
+ .notes-toolbar .btn:hover {
158
+ transform: translateY(-2px);
159
+ }
160
+ .notes-toolbar .btn.active {
161
+ box-shadow: 0 0 10px rgba(255,255,255,0.3);
162
  }
163
  .color-swatch {
164
  width: 28px;
 
166
  border-radius: 50%;
167
  cursor: pointer;
168
  border: 2px solid transparent;
169
+ transition: all var(--transition-fast);
170
  }
171
  .color-swatch:hover { transform: scale(1.1); }
172
+ .color-swatch.active { border-color: #fff; transform: scale(1.15); box-shadow: 0 0 10px rgba(255,255,255,0.5); }
173
 
174
+ /* --- UNIFIED NOTE CARD STYLES --- */
175
  .note-card {
176
+ background: linear-gradient(135deg, rgba(13, 202, 240, 0.08), rgba(13, 202, 240, 0.15));
177
+ border: 1px solid rgba(13, 202, 240, 0.3);
178
+ border-radius: 10px;
179
+ padding: 10px;
180
  margin-bottom: 8px;
181
+ transition: all var(--transition-fast);
182
+ }
183
+ .note-card:hover {
184
+ border-color: var(--accent-info);
185
+ box-shadow: 0 0 12px rgba(13, 202, 240, 0.15);
186
  }
187
  .note-thumbnail {
188
  max-height: 80px;
189
  object-fit: contain;
190
+ border-radius: 6px;
191
+ border: 1px solid rgba(13, 202, 240, 0.3);
192
+ transition: transform var(--transition-fast);
193
+ }
194
+ .note-thumbnail:hover {
195
+ transform: scale(1.05);
196
  }
197
  .note-actions {
198
  display: flex;
 
203
  cursor: pointer;
204
  }
205
  .include-pdf-toggle input:checked + .form-check-label {
206
+ color: var(--accent-info);
207
+ }
208
+
209
+ /* --- UNIFIED BUTTON STYLES --- */
210
+ .btn-pill {
211
+ border-radius: 50px;
212
+ font-weight: 500;
213
+ transition: all var(--transition-fast);
214
+ }
215
+ .btn-pill:hover {
216
+ transform: translateY(-1px);
217
+ box-shadow: var(--shadow-sm);
218
  }
219
  </style>
220
  {% endblock %}
 
295
  onchange="toggleNoteInPdf('{{ image.id }}', this.checked)">
296
  <label class="form-check-label small" for="include_note_{{ image.id }}">In PDF</label>
297
  </div>
298
+ <button type="button" class="btn btn-sm btn-outline-info btn-pill" onclick="openNotesModal('{{ image.id }}', '/image/processed/{{ session_id }}/{{ image.processed_filename }}', '{{ image.note_filename }}')" title="Edit Note">
299
  <i class="bi bi-pencil"></i>
300
  </button>
301
+ <button type="button" class="btn btn-sm btn-outline-danger btn-pill" onclick="deleteNote('{{ image.id }}')" title="Delete Note">
302
  <i class="bi bi-trash"></i>
303
  </button>
304
  </div>
305
  </div>
306
  {% else %}
307
+ <button type="button" class="btn btn-sm btn-outline-info btn-pill w-100" onclick="openNotesModal('{{ image.id }}', '/image/processed/{{ session_id }}/{{ image.processed_filename }}', '')">
308
  <i class="bi bi-pencil-square me-1"></i>Add Revision Notes
309
  </button>
310
  {% endif %}
 
455
  <div class="modal fade" id="notesModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
456
  <div class="modal-dialog modal-fullscreen">
457
  <div class="modal-content bg-dark text-white">
458
+ <div class="modal-header py-2 border-secondary" style="background: linear-gradient(180deg, var(--bg-card), var(--bg-dark));">
459
  <h5 class="modal-title"><i class="bi bi-pencil-fill me-2"></i>Add Revision Notes</h5>
460
  <div class="d-flex gap-2">
461
+ <button class="btn btn-success btn-pill px-3" onclick="saveNotes()">
462
  <i class="bi bi-check-lg me-1"></i>Save Notes
463
  </button>
464
+ <button type="button" class="btn btn-outline-secondary btn-pill" data-bs-dismiss="modal">
465
  <i class="bi bi-x-lg me-1"></i>Cancel
466
  </button>
467
  </div>
 
591
  <div class="modal fade" id="manualClassificationModal" tabindex="-1">
592
  <div class="modal-dialog modal-lg">
593
  <div class="modal-content bg-dark text-white">
594
+ <div class="modal-header border-secondary" style="background: linear-gradient(180deg, var(--bg-card), var(--bg-dark));">
595
  <h5 class="modal-title"><i class="bi bi-list-check me-2"></i>Quick Classification</h5>
596
  <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
597
  </div>
 
674
  </div>
675
  </div>
676
  <div class="modal-footer border-secondary">
677
+ <button type="button" class="btn btn-lg btn-primary btn-pill w-100" onclick="startManualClassification()">
678
  <i class="bi bi-play-fill me-2"></i>Start Classification
679
  </button>
680
  </div>
 
686
  <div class="modal fade" id="topicSelectionModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
687
  <div class="modal-dialog modal-lg modal-dialog-centered">
688
  <div class="modal-content bg-dark text-white border-secondary">
689
+ <div class="modal-header border-secondary py-2" style="background: linear-gradient(180deg, var(--bg-card), var(--bg-dark));">
690
  <div class="d-flex align-items-center gap-3">
691
  <span class="badge bg-primary fs-6" id="topic_q_num">#1</span>
692
  <div class="progress flex-grow-1" style="width: 150px; height: 6px;">
693
+ <div class="progress-bar" id="topic_progress_bar" role="progressbar" style="width: 0%; background: linear-gradient(90deg, var(--accent-primary), var(--accent-info));"></div>
694
  </div>
695
  <small id="topic_progress" class="text-muted">1/10</small>
696
  </div>
 
740
  <div id="ai_error_msg" class="alert alert-danger d-none mt-2 py-2"></div>
741
  </div>
742
  <div class="modal-footer border-secondary py-2">
743
+ <button type="button" class="btn btn-outline-secondary btn-lg btn-pill px-4" onclick="prevTopicQuestion()">
744
  <i class="bi bi-chevron-left"></i>
745
  </button>
746
+ <button type="button" class="btn btn-primary btn-lg btn-pill px-5" onclick="nextTopicQuestion()">
747
  Next <i class="bi bi-chevron-right ms-1"></i>
748
  </button>
749
  </div>
templates/quiz_v2.html CHANGED
@@ -4,14 +4,35 @@
4
 
5
  {% block head %}
6
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /* --- FORCE NO SCROLL ON PAGE --- */
8
  body, html {
9
  overflow: hidden;
10
  height: 100%;
11
- background-color: #212529;
12
  }
13
 
14
- /* --- MAIN CONTAINER (The Hammer) --- */
15
  .quiz-container {
16
  height: 88dvh;
17
  max-height: 88dvh;
@@ -19,23 +40,23 @@
19
  display: flex;
20
  flex-direction: column;
21
  margin: 0 auto;
22
- background-color: #2b3035;
23
  }
24
 
25
  /* --- 1. TOP PROGRESS --- */
26
  .progress-container {
27
  height: 5px;
28
- background-color: #343a40;
29
  flex-shrink: 0;
30
  }
31
  .progress-bar {
32
  height: 100%;
33
- background-color: #0d6efd;
34
  width: 0%;
35
- transition: width 0.3s;
36
  }
37
 
38
- /* --- 2. MIDDLE IMAGE AREA (Flexible) --- */
39
  .question-display {
40
  flex: 1;
41
  min-height: 0;
@@ -53,25 +74,25 @@
53
  width: auto;
54
  height: auto;
55
  object-fit: contain;
56
- border-radius: 6px;
57
  opacity: 0;
58
- transition: opacity 0.3s ease-in;
59
  }
60
  .question-image.loaded {
61
  opacity: 1;
62
  }
63
 
64
- /* Loading spinner for lazy load */
65
  .image-loading {
66
  position: absolute;
67
  display: none;
68
- color: #6c757d;
69
  }
70
  .image-loading.show {
71
  display: block;
72
  }
73
 
74
- /* --- 3. BOTTOM CONTROLS (Fixed Height) --- */
75
  .quiz-controls {
76
  flex-shrink: 0;
77
  height: 70px;
@@ -79,65 +100,98 @@
79
  grid-template-columns: 1fr auto 1fr;
80
  align-items: center;
81
  padding: 0 15px;
82
- background-color: #212529;
83
- border-top: 1px solid #495057;
84
  z-index: 50;
85
  }
86
 
87
- /* --- DETAILS PANEL (Overlay style) --- */
88
  .details-spoiler {
89
  display: none;
90
- background-color: #343a40;
91
- border-top: 1px solid #6c757d;
92
  max-height: 50%;
93
  overflow-y: auto;
94
  padding: 15px;
95
  font-size: 0.9rem;
96
- color: #e9ecef;
97
- }
98
- .details-spoiler .note-thumb {
99
- max-height: 200px;
100
- object-fit: contain;
101
- border-radius: 6px;
102
- border: 2px solid #0dcaf0;
103
- background: #fff;
104
  }
 
 
105
  .note-section {
106
- background: rgba(13, 202, 240, 0.1);
107
- border-radius: 8px;
108
- padding: 10px;
 
109
  margin-top: 10px;
 
 
 
 
 
110
  }
111
  .note-section h6 {
112
- color: #0dcaf0;
113
- margin-bottom: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
 
116
- /* --- BUTTON STYLES --- */
117
- .btn-pill { border-radius: 50px; }
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  /* --- OVERLAYS --- */
120
  .answer-overlay {
121
  position: absolute;
122
  top: 10px;
123
- padding: 5px 10px;
124
- border-radius: 15px;
125
  color: white;
126
- font-weight: bold;
127
  font-size: 0.8rem;
128
  z-index: 10;
129
  display: none;
130
- backdrop-filter: blur(2px);
131
- box-shadow: 0 2px 5px rgba(0,0,0,0.5);
 
132
  }
133
  #your-answer-overlay { left: 10px; background: rgba(13, 110, 253, 0.9); }
134
  #correct-answer-overlay { right: 10px; background: rgba(25, 135, 84, 0.9); }
135
 
136
  /* Bookmark button states */
 
 
 
137
  .bookmark-btn.bookmarked {
138
- background-color: #ffc107 !important;
139
- border-color: #ffc107 !important;
140
  color: #000 !important;
 
141
  }
142
  .bookmark-btn.bookmarked i::before {
143
  content: "\F147"; /* bi-bookmark-fill */
@@ -146,13 +200,15 @@
146
  /* Collection list in modal */
147
  .collection-item {
148
  cursor: pointer;
149
- transition: background-color 0.15s;
 
150
  }
151
  .collection-item:hover {
152
- background-color: #3d444b;
 
153
  }
154
  .collection-item.selected {
155
- background-color: #0d6efd;
156
  color: white;
157
  }
158
  </style>
@@ -220,7 +276,7 @@
220
  <div class="modal fade" id="bookmarkModal" tabindex="-1">
221
  <div class="modal-dialog modal-dialog-centered">
222
  <div class="modal-content bg-dark text-white">
223
- <div class="modal-header border-secondary">
224
  <h5 class="modal-title"><i class="bi bi-bookmark me-2"></i>Add to Collection</h5>
225
  <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
226
  </div>
@@ -231,7 +287,7 @@
231
  <div class="border-top border-secondary pt-3">
232
  <div class="input-group">
233
  <input type="text" id="new-collection-name" class="form-control bg-secondary text-white border-secondary" placeholder="New collection name...">
234
- <button class="btn btn-success" id="create-collection-btn">
235
  <i class="bi bi-plus-lg"></i> Create
236
  </button>
237
  </div>
@@ -239,7 +295,7 @@
239
  </div>
240
  <div class="modal-footer border-secondary">
241
  <span id="bookmark-status" class="text-muted small me-auto"></span>
242
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
243
  </div>
244
  </div>
245
  </div>
 
4
 
5
  {% block head %}
6
  <style>
7
+ /* === UNIFIED DESIGN SYSTEM === */
8
+ :root {
9
+ --bg-dark: #212529;
10
+ --bg-card: #2b3035;
11
+ --bg-elevated: #343a40;
12
+ --bg-hover: #3d444b;
13
+ --border-subtle: #495057;
14
+ --border-muted: #6c757d;
15
+ --text-primary: #e9ecef;
16
+ --text-muted: #adb5bd;
17
+ --accent-primary: #0d6efd;
18
+ --accent-info: #0dcaf0;
19
+ --accent-success: #198754;
20
+ --accent-warning: #ffc107;
21
+ --accent-danger: #dc3545;
22
+ --transition-fast: 0.15s ease;
23
+ --transition-normal: 0.25s ease;
24
+ --shadow-sm: 0 2px 4px rgba(0,0,0,0.3);
25
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.4);
26
+ }
27
+
28
  /* --- FORCE NO SCROLL ON PAGE --- */
29
  body, html {
30
  overflow: hidden;
31
  height: 100%;
32
+ background-color: var(--bg-dark);
33
  }
34
 
35
+ /* --- MAIN CONTAINER --- */
36
  .quiz-container {
37
  height: 88dvh;
38
  max-height: 88dvh;
 
40
  display: flex;
41
  flex-direction: column;
42
  margin: 0 auto;
43
+ background-color: var(--bg-card);
44
  }
45
 
46
  /* --- 1. TOP PROGRESS --- */
47
  .progress-container {
48
  height: 5px;
49
+ background-color: var(--bg-elevated);
50
  flex-shrink: 0;
51
  }
52
  .progress-bar {
53
  height: 100%;
54
+ background: linear-gradient(90deg, var(--accent-primary), var(--accent-info));
55
  width: 0%;
56
+ transition: width var(--transition-normal);
57
  }
58
 
59
+ /* --- 2. MIDDLE IMAGE AREA --- */
60
  .question-display {
61
  flex: 1;
62
  min-height: 0;
 
74
  width: auto;
75
  height: auto;
76
  object-fit: contain;
77
+ border-radius: 8px;
78
  opacity: 0;
79
+ transition: opacity var(--transition-normal);
80
  }
81
  .question-image.loaded {
82
  opacity: 1;
83
  }
84
 
85
+ /* Loading spinner */
86
  .image-loading {
87
  position: absolute;
88
  display: none;
89
+ color: var(--text-muted);
90
  }
91
  .image-loading.show {
92
  display: block;
93
  }
94
 
95
+ /* --- 3. BOTTOM CONTROLS --- */
96
  .quiz-controls {
97
  flex-shrink: 0;
98
  height: 70px;
 
100
  grid-template-columns: 1fr auto 1fr;
101
  align-items: center;
102
  padding: 0 15px;
103
+ background: linear-gradient(180deg, var(--bg-card), var(--bg-dark));
104
+ border-top: 1px solid var(--border-subtle);
105
  z-index: 50;
106
  }
107
 
108
+ /* --- DETAILS PANEL --- */
109
  .details-spoiler {
110
  display: none;
111
+ background-color: var(--bg-elevated);
112
+ border-top: 1px solid var(--border-muted);
113
  max-height: 50%;
114
  overflow-y: auto;
115
  padding: 15px;
116
  font-size: 0.9rem;
117
+ color: var(--text-primary);
 
 
 
 
 
 
 
118
  }
119
+
120
+ /* --- UNIFIED NOTE SECTION --- */
121
  .note-section {
122
+ background: linear-gradient(135deg, rgba(13, 202, 240, 0.08), rgba(13, 202, 240, 0.15));
123
+ border: 1px solid rgba(13, 202, 240, 0.3);
124
+ border-radius: 10px;
125
+ padding: 12px;
126
  margin-top: 10px;
127
+ transition: all var(--transition-fast);
128
+ }
129
+ .note-section:hover {
130
+ border-color: var(--accent-info);
131
+ box-shadow: 0 0 12px rgba(13, 202, 240, 0.15);
132
  }
133
  .note-section h6 {
134
+ color: var(--accent-info);
135
+ margin-bottom: 10px;
136
+ font-weight: 600;
137
+ font-size: 0.85rem;
138
+ text-transform: uppercase;
139
+ letter-spacing: 0.5px;
140
+ }
141
+ .note-section .note-thumb {
142
+ max-height: 200px;
143
+ width: 100%;
144
+ object-fit: contain;
145
+ border-radius: 8px;
146
+ border: 2px solid var(--accent-info);
147
+ background: #fff;
148
+ transition: transform var(--transition-fast);
149
+ }
150
+ .note-section .note-thumb:hover {
151
+ transform: scale(1.02);
152
  }
153
 
154
+ /* --- UNIFIED BUTTON STYLES --- */
155
+ .btn-pill {
156
+ border-radius: 50px;
157
+ font-weight: 500;
158
+ transition: all var(--transition-fast);
159
+ }
160
+ .btn-pill:hover {
161
+ transform: translateY(-1px);
162
+ box-shadow: var(--shadow-sm);
163
+ }
164
+ .btn-pill:active {
165
+ transform: translateY(0);
166
+ }
167
 
168
  /* --- OVERLAYS --- */
169
  .answer-overlay {
170
  position: absolute;
171
  top: 10px;
172
+ padding: 6px 12px;
173
+ border-radius: 20px;
174
  color: white;
175
+ font-weight: 600;
176
  font-size: 0.8rem;
177
  z-index: 10;
178
  display: none;
179
+ backdrop-filter: blur(4px);
180
+ box-shadow: var(--shadow-md);
181
+ transition: all var(--transition-fast);
182
  }
183
  #your-answer-overlay { left: 10px; background: rgba(13, 110, 253, 0.9); }
184
  #correct-answer-overlay { right: 10px; background: rgba(25, 135, 84, 0.9); }
185
 
186
  /* Bookmark button states */
187
+ .bookmark-btn {
188
+ transition: all var(--transition-fast);
189
+ }
190
  .bookmark-btn.bookmarked {
191
+ background-color: var(--accent-warning) !important;
192
+ border-color: var(--accent-warning) !important;
193
  color: #000 !important;
194
+ box-shadow: 0 0 10px rgba(255, 193, 7, 0.4);
195
  }
196
  .bookmark-btn.bookmarked i::before {
197
  content: "\F147"; /* bi-bookmark-fill */
 
200
  /* Collection list in modal */
201
  .collection-item {
202
  cursor: pointer;
203
+ transition: all var(--transition-fast);
204
+ border-radius: 6px;
205
  }
206
  .collection-item:hover {
207
+ background-color: var(--bg-hover);
208
+ transform: translateX(2px);
209
  }
210
  .collection-item.selected {
211
+ background-color: var(--accent-primary);
212
  color: white;
213
  }
214
  </style>
 
276
  <div class="modal fade" id="bookmarkModal" tabindex="-1">
277
  <div class="modal-dialog modal-dialog-centered">
278
  <div class="modal-content bg-dark text-white">
279
+ <div class="modal-header border-secondary" style="background: linear-gradient(180deg, var(--bg-card, #2b3035), var(--bg-dark, #212529));">
280
  <h5 class="modal-title"><i class="bi bi-bookmark me-2"></i>Add to Collection</h5>
281
  <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
282
  </div>
 
287
  <div class="border-top border-secondary pt-3">
288
  <div class="input-group">
289
  <input type="text" id="new-collection-name" class="form-control bg-secondary text-white border-secondary" placeholder="New collection name...">
290
+ <button class="btn btn-success btn-pill" id="create-collection-btn">
291
  <i class="bi bi-plus-lg"></i> Create
292
  </button>
293
  </div>
 
295
  </div>
296
  <div class="modal-footer border-secondary">
297
  <span id="bookmark-status" class="text-muted small me-auto"></span>
298
+ <button type="button" class="btn btn-secondary btn-pill" data-bs-dismiss="modal">Close</button>
299
  </div>
300
  </div>
301
  </div>