Docfile commited on
Commit
0cb856b
·
verified ·
1 Parent(s): ca9f82a

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +208 -531
templates/index.html CHANGED
@@ -1,538 +1,215 @@
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Math Solver - Version Gratuite</title>
7
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
8
- <link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css" rel="stylesheet">
9
- <style>
10
- :root {
11
- --primary-color: #4a6fa5;
12
- --secondary-color: #166088;
13
- --accent-color: #4fc3f7;
14
- --background-color: #f8f9fa;
15
- --text-color: #333;
16
- --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
17
- --code-bg: #2c323c;
18
- --output-bg: #f1f8f9;
19
- }
20
-
21
- body {
22
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
23
- line-height: 1.6;
24
- margin: 0;
25
- padding: 0;
26
- background-color: var(--background-color);
27
- color: var(--text-color);
28
- }
29
-
30
- .container {
31
- max-width: 1000px;
32
- margin: 0 auto;
33
- padding: 20px;
34
- }
35
-
36
- header {
37
- text-align: center;
38
- padding: 20px 0;
39
- margin-bottom: 30px;
40
- }
41
-
42
- .logo {
43
- font-size: 2.5rem;
44
- font-weight: bold;
45
- color: var(--primary-color);
46
- margin-bottom: 10px;
47
- }
48
-
49
- .subtitle {
50
- font-size: 1.2rem;
51
- color: var(--secondary-color);
52
- margin-bottom: 20px;
53
- }
54
-
55
- .content-box {
56
- background-color: white;
57
- border-radius: 10px;
58
- box-shadow: var(--box-shadow);
59
- padding: 30px;
60
- margin-bottom: 30px;
61
- text-align: center;
62
- }
63
-
64
- h1 {
65
- color: var(--primary-color);
66
- margin-top: 0;
67
- }
68
-
69
- .feature-list {
70
- list-style-type: none;
71
- padding: 0;
72
- margin: 30px 0;
73
- text-align: left;
74
- }
75
-
76
- .feature-list li {
77
- padding: 10px 0;
78
- margin-bottom: 10px;
79
- display: flex;
80
- align-items: center;
81
- }
82
-
83
- .feature-list i {
84
- color: var(--accent-color);
85
- margin-right: 10px;
86
- font-size: 1.2rem;
87
- }
88
-
89
- .cta-button {
90
- display: inline-block;
91
- background-color: var(--primary-color);
92
- color: white;
93
- padding: 12px 25px;
94
- border-radius: 5px;
95
- text-decoration: none;
96
- font-weight: bold;
97
- transition: all 0.3s ease;
98
- margin: 20px 10px;
99
- border: none;
100
- cursor: pointer;
101
- }
102
-
103
- .cta-button:hover {
104
- background-color: var(--secondary-color);
105
- transform: translateY(-2px);
106
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
107
- }
108
-
109
- .upgrade-section {
110
- margin-top: 30px;
111
- padding: 20px;
112
- border-top: 1px solid #ddd;
113
- }
114
-
115
- footer {
116
- text-align: center;
117
- padding: 20px 0;
118
- color: #666;
119
- font-size: 0.9rem;
120
- }
121
-
122
- #solution {
123
- background: #fff;
124
- padding: 20px;
125
- border-radius: 8px;
126
- text-align: left;
127
- line-height: 1.8;
128
- font-size: 16px;
129
- }
130
-
131
- .code-section {
132
- margin: 20px 0;
133
- border-radius: 8px;
134
- overflow: hidden;
135
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
136
- }
137
-
138
- .code-header {
139
- background-color: #343a40;
140
- color: white;
141
- padding: 8px 15px;
142
- font-size: 14px;
143
- font-family: 'Courier New', monospace;
144
- display: flex;
145
- justify-content: space-between;
146
- align-items: center;
147
- }
148
-
149
- .code-content {
150
- margin: 0;
151
- padding: 15px;
152
- background-color: var(--code-bg);
153
- color: #e6e6e6;
154
- overflow-x: auto;
155
- font-family: 'Courier New', monospace;
156
- font-size: 14px;
157
- line-height: 1.5;
158
- }
159
-
160
- .output-section {
161
- background-color: var(--output-bg);
162
- padding: 15px;
163
- border-radius: 0 0 8px 8px;
164
- border-top: 1px solid #ddd;
165
- color: #333;
166
- font-family: 'Courier New', monospace;
167
- font-size: 14px;
168
- white-space: pre-wrap;
169
- overflow-x: auto;
170
- }
171
-
172
- .step-section {
173
- margin: 25px 0;
174
- padding: 15px;
175
- background-color: #f9f9f9;
176
- border-left: 4px solid var(--primary-color);
177
- border-radius: 0 8px 8px 0;
178
- overflow-x: auto; /* Pour les formules LaTeX larges */
179
- }
180
-
181
- .latex-display {
182
- overflow-x: auto;
183
- padding: 10px 0;
184
- margin: 15px 0;
185
- text-align: center;
186
- }
187
-
188
- .thinking-indicator, .executing-indicator, .answering-indicator {
189
- display: flex;
190
- align-items: center;
191
- padding: 10px;
192
- margin: 10px 0;
193
- border-radius: 8px;
194
- font-size: 0.9rem;
195
- }
196
-
197
- .thinking-indicator {
198
- background-color: #e3f2fd;
199
- color: #1565c0;
200
- }
201
-
202
- .executing-indicator {
203
- background-color: #ede7f6;
204
- color: #5e35b1;
205
- }
206
-
207
- .answering-indicator {
208
- background-color: #e8f5e9;
209
- color: #2e7d32;
210
- }
211
-
212
- .indicator-icon {
213
- margin-right: 10px;
214
- animation: pulse 1.5s infinite ease-in-out;
215
- }
216
-
217
- @keyframes pulse {
218
- 0% { opacity: 0.6; }
219
- 50% { opacity: 1; }
220
- 100% { opacity: 0.6; }
221
- }
222
-
223
- /* Styles spécifiques à MathJax */
224
- .MathJax {
225
- overflow-x: auto !important;
226
- overflow-y: hidden !important;
227
- max-width: 100% !important;
228
- }
229
-
230
- .mjx-chtml {
231
- overflow-x: auto !important;
232
- overflow-y: hidden !important;
233
- max-width: 100% !important;
234
- }
235
-
236
- mjx-container {
237
- overflow-x: auto !important;
238
- overflow-y: hidden !important;
239
- max-width: 100% !important;
240
- min-width: 0 !important;
241
- padding: 2px 0;
242
- }
243
-
244
- @media (max-width: 768px) {
245
- .container {
246
- padding: 15px;
247
- }
248
-
249
- .content-box {
250
- padding: 20px;
251
- }
252
- }
253
- </style>
254
  </head>
255
  <body>
256
- <div class="container">
257
- <header>
258
- <div class="logo">Math Solver</div>
259
- <div class="subtitle">La solution intelligente pour vos problèmes mathématiques</div>
260
- </header>
261
-
262
- <div class="content-box">
263
- <h1>Version Gratuite</h1>
264
- <p>Vous utilisez actuellement la version gratuite de Math Solver qui vous permet de résoudre 3 problèmes par jour.</p>
265
-
266
- <div class="feature-list">
267
- <h2>Fonctionnalités disponibles :</h2>
268
- <ul class="feature-list">
269
- <li><i class="fas fa-check-circle"></i> Résolution de problèmes mathématiques basiques</li>
270
- <li><i class="fas fa-check-circle"></i> 3 résolutions gratuites par jour</li>
271
- <li><i class="fas fa-check-circle"></i> Explication des étapes de résolution</li>
272
- <li><i class="fas fa-times-circle"></i> <span style="color: #999;">Mode d'exécution de code avancé (version Pro)</span></li>
273
- <li><i class="fas fa-times-circle"></i> <span style="color: #999;">Résolutions illimitées (version Pro)</span></li>
274
- <li><i class="fas fa-times-circle"></i> <span style="color: #999;">Support prioritaire (version Pro)</span></li>
275
- </ul>
276
- </div>
277
-
278
- <div class="upload-section">
279
- <form id="imageForm" enctype="multipart/form-data">
280
- <input type="file" id="imageInput" name="image" accept="image/*" style="display: none;">
281
- <button type="button" id="uploadButton" class="cta-button" onclick="document.getElementById('imageInput').click()">
282
- <i class="fas fa-upload"></i> Télécharger une image
283
- </button>
284
- </form>
285
-
286
- <p id="uploadStatus"></p>
287
- <div id="imagePreview" style="display: none; margin: 20px auto; max-width: 500px;">
288
- <img id="preview" style="width: 100%; border-radius: 8px; box-shadow: var(--box-shadow);">
289
- </div>
290
-
291
- <button id="solveButton" class="cta-button" style="display: none; background-color: var(--secondary-color);">
292
- <i class="fas fa-calculator"></i> Résoudre ce problème
293
- </button>
294
- </div>
295
-
296
- <div id="solutionOutput" style="margin-top: 30px; text-align: left; display: none;">
297
- <h3>Solution :</h3>
298
- <div id="loadingIndicator" class="thinking-indicator" style="display: none;">
299
- <i class="fas fa-brain indicator-icon"></i>
300
- <span>Je réfléchis au problème...</span>
301
- </div>
302
- <div id="solution" style="background: #fff; padding: 20px; border-radius: 8px;"></div>
303
- </div>
304
-
305
- <div class="upgrade-section">
306
- <h2>Besoin de plus de puissance ?</h2>
307
- <p>Passez à la version Pro pour des fonctionnalités avancées et des résolutions illimitées.</p>
308
- <a href="#" class="cta-button">Passer à la version Pro</a>
309
- </div>
310
- </div>
311
-
312
- <footer>
313
- <p>&copy; 2025 Math Solver. Tous droits réservés.</p>
314
- </footer>
315
  </div>
316
-
317
- <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
318
- <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
319
-
320
- <!-- MathJax Configuration -->
321
- <script>
322
- window.MathJax = {
323
- tex: {
324
- inlineMath: [['$', '$'], ['\\(', '\\)']],
325
- displayMath: [['$$', '$$'], ['\\[', '\\]']],
326
- processEscapes: true,
327
- processEnvironments: true,
328
- packages: {'[+]': ['ams', 'noerrors', 'physics', 'cancel', 'color', 'mhchem', 'mathtools']}
329
- },
330
- options: {
331
- enableMenu: false,
332
- renderActions: {
333
- addMenu: [], // Disable menu
334
- checkLoading: []
335
- },
336
- ignoreHtmlClass: 'code-content',
337
- processHtmlClass: 'step-section|latex-display',
338
- skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
339
- },
340
- startup: {
341
- pageReady: function() {
342
- return MathJax.startup.defaultPageReady();
343
- }
344
- },
345
- loader: {
346
- load: ['[tex]/ams', '[tex]/noerrors', '[tex]/physics', '[tex]/cancel', '[tex]/color', '[tex]/mhchem', '[tex]/mathtools']
347
- },
348
- svg: {
349
- fontCache: 'global'
350
- }
351
- };
352
- </script>
353
- <script id="MathJax-script" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.js"></script>
354
-
355
- <script>
356
- // Variables to manage MathJax rendering state
357
- let mathJaxQueue = [];
358
- let isProcessingMathQueue = false;
359
-
360
- // Process MathJax queue with delay to avoid blocking UI
361
- async function processMathJaxQueue() {
362
- if (isProcessingMathQueue || mathJaxQueue.length === 0) return;
363
-
364
- isProcessingMathQueue = true;
365
- const element = mathJaxQueue.shift();
366
-
367
- try {
368
- await MathJax.typesetPromise([element]);
369
- } catch (e) {
370
- console.error('MathJax typesetting failed:', e);
371
- }
372
-
373
- isProcessingMathQueue = false;
374
- setTimeout(processMathJaxQueue, 100); // Small delay to allow UI updates
375
- }
376
-
377
- function addToMathJaxQueue(element) {
378
- mathJaxQueue.push(element);
379
- processMathJaxQueue();
380
- }
381
-
382
- document.getElementById('imageInput').addEventListener('change', function(event) {
383
- const file = event.target.files[0];
384
- if (file) {
385
- const reader = new FileReader();
386
- reader.onload = function(e) {
387
- document.getElementById('preview').src = e.target.result;
388
- document.getElementById('imagePreview').style.display = 'block';
389
- document.getElementById('solveButton').style.display = 'inline-block';
390
- document.getElementById('uploadStatus').textContent = `Image sélectionnée : ${file.name}`;
391
- }
392
- reader.readAsDataURL(file);
393
- }
394
- });
395
-
396
- document.getElementById('solveButton').addEventListener('click', function() {
397
- const formData = new FormData(document.getElementById('imageForm'));
398
- const solutionOutput = document.getElementById('solutionOutput');
399
- const loadingIndicator = document.getElementById('loadingIndicator');
400
- const solution = document.getElementById('solution');
401
-
402
- solutionOutput.style.display = 'block';
403
- loadingIndicator.style.display = 'flex';
404
- solution.innerHTML = '';
405
-
406
- // Reset MathJax queue
407
- mathJaxQueue = [];
408
- isProcessingMathQueue = false;
409
-
410
- fetch('/solved', {
411
- method: 'POST',
412
- body: formData
413
- })
414
- .then(response => {
415
- const reader = response.body.getReader();
416
- const decoder = new TextDecoder();
417
- let buffer = '';
418
-
419
- function processStream({ done, value }) {
420
- if (done) {
421
- loadingIndicator.style.display = 'none';
422
-
423
- // Final MathJax render at the end
424
- try {
425
- addToMathJaxQueue(solution);
426
- } catch (e) {
427
- console.error('Error in final MathJax rendering:', e);
428
- }
429
- return;
430
- }
431
-
432
- buffer += decoder.decode(value, { stream: true });
433
- const lines = buffer.split('\n\n');
434
- buffer = lines.pop(); // Keep the incomplete chunk for next time
435
-
436
- for (const line of lines) {
437
- if (line.startsWith('data: ')) {
438
- try {
439
- const data = JSON.parse(line.substr(6));
440
-
441
- if (data.mode === 'thinking') {
442
- loadingIndicator.className = 'thinking-indicator';
443
- loadingIndicator.innerHTML = '<i class="fas fa-brain indicator-icon"></i><span>Je réfléchis au problème...</span>';
444
- } else if (data.mode === 'answering') {
445
- loadingIndicator.className = 'answering-indicator';
446
- loadingIndicator.innerHTML = '<i class="fas fa-pencil-alt indicator-icon"></i><span>Rédaction de la solution...</span>';
447
- } else if (data.mode === 'executing_code') {
448
- loadingIndicator.className = 'executing-indicator';
449
- loadingIndicator.innerHTML = '<i class="fas fa-code indicator-icon"></i><span>Exécution de code pour la résolution...</span>';
450
- } else if (data.mode === 'code_result') {
451
- loadingIndicator.className = 'executing-indicator';
452
- loadingIndicator.innerHTML = '<i class="fas fa-terminal indicator-icon"></i><span>Traitement des résultats...</span>';
453
- }
454
-
455
- if (data.content) {
456
- const content = data.content;
457
-
458
- // Create a container for this new content
459
- const contentContainer = document.createElement('div');
460
-
461
- // Detect if this is code or output and format appropriately
462
- if (content.includes('```python')) {
463
- // This is code
464
- const codeHtml = content.replace(/```python\n([\s\S]*?)\n```/g, function(match, p1) {
465
- return `<div class="code-section">
466
- <div class="code-header">
467
- <span>Code Python</span>
468
- </div>
469
- <pre class="code-content"><code class="language-python">${p1}</code></pre>
470
- </div>`;
471
- });
472
- contentContainer.innerHTML = codeHtml;
473
- solution.appendChild(contentContainer);
474
-
475
- // Apply syntax highlighting
476
- contentContainer.querySelectorAll('pre code').forEach((block) => {
477
- hljs.highlightElement(block);
478
- });
479
- }
480
- else if (content.includes('Résultat d\'exécution:')) {
481
- // This is code output
482
- const outputHtml = content.replace(/Résultat d'exécution:\n```\n([\s\S]*?)\n```/g, function(match, p1) {
483
- return `<div class="output-section">${p1}</div>`;
484
- });
485
- contentContainer.innerHTML = outputHtml;
486
- solution.appendChild(contentContainer);
487
- }
488
- else {
489
- // Regular text, might contain LaTeX
490
- contentContainer.className = 'step-section';
491
- contentContainer.innerHTML = content;
492
- solution.appendChild(contentContainer);
493
-
494
- // Add to MathJax rendering queue
495
- addToMathJaxQueue(contentContainer);
496
- }
497
- }
498
-
499
- if (data.error) {
500
- const errorDiv = document.createElement('div');
501
- errorDiv.style.color = 'red';
502
- errorDiv.style.margin = '15px 0';
503
- errorDiv.style.padding = '10px';
504
- errorDiv.style.background = '#ffeeee';
505
- errorDiv.style.borderRadius = '5px';
506
- errorDiv.textContent = `Erreur: ${data.error}`;
507
- solution.appendChild(errorDiv);
508
- loadingIndicator.style.display = 'none';
509
- }
510
- } catch (e) {
511
- console.error('Error parsing JSON:', e, line);
512
- }
513
- }
514
- }
515
-
516
- // Scroll to bottom automatically
517
- window.scrollTo(0, document.body.scrollHeight);
518
-
519
- return reader.read().then(processStream);
520
- }
521
-
522
- return reader.read().then(processStream);
523
- })
524
- .catch(error => {
525
- const errorDiv = document.createElement('div');
526
- errorDiv.style.color = 'red';
527
- errorDiv.style.margin = '15px 0';
528
- errorDiv.style.padding = '10px';
529
- errorDiv.style.background = '#ffeeee';
530
- errorDiv.style.borderRadius = '5px';
531
- errorDiv.textContent = `Erreur de connexion: ${error}`;
532
- solution.appendChild(errorDiv);
533
- loadingIndicator.style.display = 'none';
534
- });
535
- });
536
- </script>
537
  </body>
538
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Math Solver Version Gratuite</title>
7
+ <!-- Font Awesome & Highlight.js -->
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
10
+ <!-- Stylesheet -->
11
+ <style>
12
+ :root {
13
+ --primary: #4a6fa5;
14
+ --secondary: #166088;
15
+ --accent: #4fc3f7;
16
+ --bg: #f8f9fa;
17
+ --text: #333;
18
+ --light: #fff;
19
+ --shadow: rgba(0,0,0,0.1);
20
+ }
21
+ * { box-sizing: border-box; }
22
+ body {
23
+ margin: 0;
24
+ font-family: 'Segoe UI', Tahoma, Geneva, sans-serif;
25
+ color: var(--text);
26
+ background: var(--bg);
27
+ line-height: 1.5;
28
+ }
29
+ header, main, footer { max-width: 900px; margin: 0 auto; padding: 1rem; }
30
+ header { text-align: center; padding-top: 2rem; }
31
+ .logo { font-size: 2.5rem; color: var(--primary); margin-bottom: .5rem; }
32
+ .subtitle { color: var(--secondary); font-size: 1.1rem; }
33
+
34
+ .card {
35
+ background: var(--light);
36
+ border-radius: 8px;
37
+ box-shadow: 0 4px 8px var(--shadow);
38
+ padding: 2rem;
39
+ margin: 2rem 0;
40
+ }
41
+ .card h2 { color: var(--primary); margin-top: 0; }
42
+
43
+ .features {
44
+ display: grid;
45
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
46
+ gap: 1rem;
47
+ list-style: none;
48
+ padding: 0;
49
+ margin: 1.5rem 0;
50
+ }
51
+ .features li {
52
+ display: flex;
53
+ align-items: center;
54
+ font-size: .95rem;
55
+ }
56
+ .features li i {
57
+ margin-right: .5rem;
58
+ color: var(--accent);
59
+ }
60
+ .features li.disabled i { color: #ccc; }
61
+ .features li.disabled span { color: #999; }
62
+
63
+ .btn {
64
+ display: inline-flex;
65
+ align-items: center;
66
+ gap: .5rem;
67
+ background: var(--primary);
68
+ color: var(--light);
69
+ padding: .75rem 1.5rem;
70
+ border: none;
71
+ border-radius: 4px;
72
+ font-weight: 600;
73
+ cursor: pointer;
74
+ transition: transform .2s, background .2s;
75
+ text-decoration: none;
76
+ }
77
+ .btn:hover { background: var(--secondary); transform: translateY(-2px); }
78
+ .btn.secondary { background: var(--secondary); }
79
+
80
+ /* Upload & Preview */
81
+ .upload { text-align: center; margin: 1.5rem 0; }
82
+ .upload input { display: none; }
83
+ .preview {
84
+ margin: 1rem auto;
85
+ max-width: 100%;
86
+ border-radius: 6px;
87
+ box-shadow: 0 4px 6px var(--shadow);
88
+ display: none;
89
+ }
90
+
91
+ /* Solution & Indicators */
92
+ .solution {
93
+ margin-top: 2rem;
94
+ display: none;
95
+ }
96
+ .indicator {
97
+ display: flex;
98
+ align-items: center;
99
+ gap: .5rem;
100
+ padding: .75rem;
101
+ border-radius: 4px;
102
+ font-size: .9rem;
103
+ }
104
+ .indicator.think { background: #e3f2fd; color: #1565c0; }
105
+ .indicator.exec { background: #ede7f6; color: #5e35b1; }
106
+ .indicator.answer{ background: #e8f5e9; color: #2e7d32; }
107
+ .indicator .fa { animation: pulse 1.4s infinite; }
108
+ @keyframes pulse { 0%,100% { opacity:.6; } 50% { opacity:1; } }
109
+
110
+ .step { background: #f9f9f9; border-left: 5px solid var(--primary); padding: 1rem; margin: 1rem 0; overflow-x:auto; }
111
+ pre { margin: 0; }
112
+ .code-block { margin: 1rem 0; border-radius: 6px; overflow: hidden; box-shadow: 0 2px 4px var(--shadow); }
113
+ .code-block header { background: #343a40; color:#fff; padding:.5rem 1rem; font-family: monospace; font-size:.9rem; }
114
+ .code-block pre { background: #2c323c; color: #e6e6e6; padding:1rem; font-family: monospace; font-size:.9rem; }
115
+ .output-block { background: var(--light); border-top:1px solid #ddd; padding:1rem; font-family: monospace; white-space: pre-wrap; }
116
+
117
+ footer { text-align: center; font-size:.85rem; color:#666; padding:2rem 1rem; }
118
+
119
+ @media(max-width:600px) {
120
+ .features { grid-template-columns: 1fr; }
121
+ .btn { width: 100%; justify-content: center; }
122
+ }
123
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  </head>
125
  <body>
126
+
127
+ <header>
128
+ <div class="logo">Math Solver</div>
129
+ <div class="subtitle">La solution intelligente pour vos problèmes mathématiques</div>
130
+ </header>
131
+
132
+ <main>
133
+ <section class="card">
134
+ <h2>Version Gratuite</h2>
135
+ <p>3 problèmes gratuits par jour avec explication pas-à-pas.</p>
136
+
137
+ <ul class="features">
138
+ <li><i class="fas fa-check-circle"></i> Problèmes basiques</li>
139
+ <li><i class="fas fa-check-circle"></i> 3 par jour</li>
140
+ <li><i class="fas fa-check-circle"></i> Explications détaillées</li>
141
+ <li class="disabled"><i class="fas fa-times-circle"></i><span>Code avancé (Pro)</span></li>
142
+ <li class="disabled"><i class="fas fa-times-circle"></i><span>Illimité (Pro)</span></li>
143
+ <li class="disabled"><i class="fas fa-times-circle"></i><span>Support prioritaire (Pro)</span></li>
144
+ </ul>
145
+
146
+ <div class="upload">
147
+ <input type="file" id="imgInput" accept="image/*">
148
+ <button class="btn" id="btnSelect"><i class="fas fa-upload"></i> Choisir une image</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  </div>
150
+ <img id="imgPreview" class="preview" alt="Aperçu du problème">
151
+ <button class="btn secondary" id="btnSolve" style="display:none;"><i class="fas fa-calculator"></i> Résoudre</button>
152
+
153
+ <div class="solution" id="solutionArea">
154
+ <div class="indicator think" id="indicator"><i class="fas fa-brain"></i><span>Je réfléchis...</span></div>
155
+ <div id="solutionContent"></div>
156
+ </div>
157
+
158
+ <div style="text-align:center; margin-top:2rem;">
159
+ <a href="#" class="btn">Passer à la version Pro</a>
160
+ </div>
161
+ </section>
162
+ </main>
163
+
164
+ <footer>&copy; 2025 Math Solver. Tous droits réservés.</footer>
165
+
166
+ <!-- Scripts -->
167
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
168
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
169
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
170
+ <script>
171
+ // Element references
172
+ const imgInput = document.getElementById('imgInput');
173
+ const preview = document.getElementById('imgPreview');
174
+ const btnSelect = document.getElementById('btnSelect');
175
+ const btnSolve = document.getElementById('btnSolve');
176
+ const solArea = document.getElementById('solutionArea');
177
+ const solCont = document.getElementById('solutionContent');
178
+ const indicator = document.getElementById('indicator');
179
+
180
+ btnSelect.addEventListener('click', () => imgInput.click());
181
+ imgInput.addEventListener('change', e => {
182
+ const file = e.target.files[0];
183
+ if (!file) return;
184
+ const url = URL.createObjectURL(file);
185
+ preview.src = url;
186
+ preview.style.display = 'block';
187
+ btnSolve.style.display = 'inline-flex';
188
+ });
189
+
190
+ btnSolve.addEventListener('click', () => {
191
+ solArea.style.display = 'block';
192
+ solCont.innerHTML = '';
193
+ indicator.className = 'indicator think';
194
+ indicator.querySelector('span').textContent = 'Je réfléchis...';
195
+
196
+ fetch('/solved', { method: 'POST', body: new FormData(document.querySelector('form')) })
197
+ .then(res => {
198
+ // streaming logic...
199
+ })
200
+ .catch(err => console.error(err));
201
+ });
202
+
203
+ function updateIndicator(mode) {
204
+ indicator.className = 'indicator ' + mode;
205
+ const icons = { think: 'fa-brain', exec: 'fa-code', answer: 'fa-paste' };
206
+ indicator.querySelector('i').className = 'fas ' + icons[mode];
207
+ indicator.querySelector('span').textContent = {
208
+ think: 'Je réfléchis...',
209
+ exec: 'Exécution du code...',
210
+ answer: 'Rédaction de la solution...',
211
+ }[mode];
212
+ }
213
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  </body>
215
+ </html>