Docfile commited on
Commit
c06c855
·
verified ·
1 Parent(s): affe748

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +87 -67
templates/index.html CHANGED
@@ -7,7 +7,6 @@
7
  <title>Mariam AI - Assistant Français Intelligent</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js"></script>
10
- <!-- MathJax retiré -->
11
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
12
  <style>
13
  @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');
@@ -29,48 +28,48 @@
29
  font-family: 'Plus Jakarta Sans', sans-serif;
30
  background-color: #fafafa;
31
  scroll-behavior: smooth;
32
- -webkit-tap-highlight-color: transparent; /* Remove blue tap highlight on mobile */
 
 
 
 
 
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  .glassmorphism {
36
  background: rgba(255, 255, 255, 0.95);
37
  backdrop-filter: blur(10px);
38
- -webkit-backdrop-filter: blur(10px); /* Safari */
39
  border: 1px solid rgba(255, 255, 255, 0.3);
40
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
41
  }
42
 
43
- .card-hover {
44
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
45
- }
46
-
47
- .card-hover:hover {
48
- transform: translateY(-4px);
49
- box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
50
- }
51
 
52
- .gradient-text {
53
- background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 100%);
54
- -webkit-background-clip: text;
55
- background-clip: text;
56
- -webkit-text-fill-color: transparent;
57
- text-fill-color: transparent; /* Standard property */
58
- }
59
 
60
- .loading-dot {
61
- animation: bounce 1.4s infinite;
62
- }
63
  .loading-dot:nth-child(2) { animation-delay: 0.2s; }
64
  .loading-dot:nth-child(3) { animation-delay: 0.4s; }
65
  @keyframes bounce { 0%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-6px); } }
66
 
67
- .custom-radio:checked+span {
68
- background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 100%);
69
- color: white;
70
- border-color: var(--primary);
71
- }
72
 
73
- /* Styles pour les messages d'alerte */
74
  .alert-message { display: flex; align-items: flex-start; padding: 1rem; border-radius: 0.5rem; border-width: 1px; border-style: solid; }
75
  .alert-message i { margin-right: 0.75rem; font-size: 1.25rem; margin-top: 0.125rem; flex-shrink: 0; }
76
  .alert-message div p:first-child { font-weight: 500; }
@@ -103,19 +102,19 @@
103
  .image-preview-item:hover .remove-image { opacity: 1; }
104
  .remove-image:hover { background-color: rgba(0, 0, 0, 0.8); transform: scale(1.1); }
105
 
106
- /* Style Prose (Zone de sortie) */
107
- .prose { white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; color: #2d3748; line-height: 1.7; font-size: 0.95rem; /* légèrement plus petit par défaut */ }
108
- @media (min-width: 640px) { .prose { font-size: 1rem; } } /* Taille normale sur sm+ */
109
  .prose h1, .prose h2, .prose h3, .prose h4 { color: var(--primary-dark); margin-top: 1.5em; margin-bottom: 0.5em; font-weight: 600; }
110
  .prose p { margin-bottom: 1em; }
111
  .prose ul, .prose ol { padding-left: 1.5em; margin-bottom: 1em; }
112
  .prose blockquote { border-left: 4px solid var(--primary); padding-left: 1em; font-style: italic; color: var(--secondary); margin: 1em 0; }
113
- .prose code { background-color: #edf2f7; /* gray-200 */ padding: 0.2em 0.4em; border-radius: 0.25rem; font-size: 0.9em; }
114
- .prose pre { background-color: #1a202c; /* gray-900 */ color: #e2e8f0; /* gray-200 */ padding: 1em; border-radius: 0.375rem; overflow-x: auto; }
115
  .prose pre code { background-color: transparent; padding: 0; border-radius: 0; font-size: 0.875em; }
116
 
117
  /* Loader */
118
- .loader { display: inline-block; position: relative; width: 64px; height: 16px; /* Smaller */ }
119
  .loader div { position: absolute; top: 6px; width: 10px; height: 10px; border-radius: 50%; background: var(--primary); animation-timing-function: cubic-bezier(0, 1, 1, 0); }
120
  .loader div:nth-child(1) { left: 6px; animation: loader1 0.6s infinite; }
121
  .loader div:nth-child(2) { left: 6px; animation: loader2 0.6s infinite; }
@@ -150,36 +149,32 @@
150
 
151
  <body class="min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 text-gray-800">
152
  <nav class="glassmorphism sticky top-0 z-50 border-b border-blue-100">
153
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
154
- <div class="container mx-auto px-4 sm:px-6 py-3 sm:py-4"> <!-- Ajustement padding nav -->
155
  <div class="flex items-center justify-between">
156
  <div class="flex items-center space-x-3 sm:space-x-4">
157
  <div class="bg-gradient-to-r from-blue-600 to-blue-800 rounded-lg p-2 shadow-lg transform hover:scale-110 transition-transform duration-300">
158
- <i class="fas fa-robot text-white text-lg sm:text-xl"></i> <!-- Taille icône -->
159
  </div>
160
- <h1 class="text-xl sm:text-2xl font-bold gradient-text">Mariam AI</h1> <!-- Taille titre -->
161
  </div>
162
- <div class="text-xs sm:text-sm text-blue-900 font-medium bg-blue-50 py-1 px-3 sm:px-4 rounded-full shadow-sm hidden sm:block">Assistant Français</div> <!-- Masqué sur xs -->
163
- <div class="text-xs text-blue-900 font-medium bg-blue-50 py-1 px-3 rounded-full shadow-sm sm:hidden">Assistant</div> <!-- Version courte pour xs -->
164
  </div>
165
  </div>
166
  </nav>
167
 
168
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
169
- <main class="container mx-auto px-4 sm:px-6 py-8 sm:py-12"> <!-- Ajustement padding main -->
170
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 sm:gap-8">
171
  <!-- Section Travail Argumentatif -->
172
  <div class="card-hover glassmorphism rounded-2xl overflow-hidden scale-in">
173
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
174
- <div class="p-6 sm:p-8"> <!-- Ajustement padding carte -->
175
  <div class="flex items-center space-x-3 sm:space-x-4 mb-6 sm:mb-8">
176
  <div class="bg-blue-100 rounded-lg p-2 sm:p-3 transform rotate-3">
177
  <i class="fas fa-pen-fancy text-blue-600 text-lg sm:text-xl"></i>
178
  </div>
179
  <h2 class="text-xl sm:text-2xl font-bold text-gray-800">Travail Argumentatif</h2>
180
  </div>
181
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
182
- <form id="francais-form" class="space-y-6 sm:space-y-8"> <!-- Ajustement espacement -->
183
  <div class="space-y-2">
184
  <label for="sujet-francais" class="block text-sm font-medium text-gray-700 flex items-center">
185
  <i class="fas fa-book-open mr-2 text-blue-500"></i>Sujet <span class="text-red-500 ml-1">*</span>
@@ -189,14 +184,13 @@
189
  class="w-full px-3 py-2 sm:px-4 sm:py-3 rounded-xl border-2 border-gray-200 focus:border-blue-500 focus:outline-none transition-all duration-200 resize-none text-base"
190
  placeholder="Entrez votre sujet ici..." required></textarea>
191
  </div>
192
- <div class="text-xs text-gray-400 text-right" id="character-count">0 caractères</div>
193
  </div>
194
 
195
  <div class="space-y-3">
196
  <label class="block text-sm font-medium text-gray-700 flex items-center">
197
  <i class="fas fa-tasks mr-2 text-blue-500"></i>Type d'argumentation
198
  </label>
199
- <!-- Grid s'adapte déjà bien (2 cols par défaut, 4 sur sm+) -->
200
  <div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4">
201
  <label class="relative">
202
  <input type="radio" name="choix" value="Etaye" class="custom-radio absolute opacity-0 w-full h-full cursor-pointer" checked>
@@ -239,7 +233,7 @@
239
  <span class="text-sm">Utiliser DeepThink</span>
240
  <div class="deepthink-tooltip">
241
  <i class="fas fa-info-circle text-gray-400 ml-1"></i>
242
- <span class="tooltip-text">Modèle avancé (Pro). Plus lent, meilleure qualité. Limité: 1/jour.</span>
243
  </div>
244
  </label>
245
  <span id="deepthink-status" class="text-xs text-gray-500 ml-2"></span>
@@ -253,8 +247,7 @@
253
  </div>
254
  </button>
255
  </form>
256
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
257
- <div id="francais-output" class="mt-6 sm:mt-8 p-4 sm:p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[150px]"> <!-- Ajustement padding et min-height -->
258
  <!-- Le contenu généré sera inséré ici -->
259
  </div>
260
  </div>
@@ -262,8 +255,7 @@
262
 
263
  <!-- Section Étude de texte -->
264
  <div class="card-hover glassmorphism rounded-2xl overflow-hidden scale-in" style="animation-delay: 0.1s;">
265
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
266
- <div class="p-6 sm:p-8"> <!-- Ajustement padding carte -->
267
  <div class="flex items-center space-x-3 sm:space-x-4 mb-6 sm:mb-8">
268
  <div class="bg-blue-100 rounded-lg p-2 sm:p-3 transform -rotate-3">
269
  <i class="fas fa-file-alt text-blue-600 text-lg sm:text-xl"></i>
@@ -297,8 +289,7 @@
297
  </div>
298
  </button>
299
  </form>
300
- <!-- CORRECTION: Remplacement {* *} par <!-- -->
301
- <div id="etude-texte-output" class="mt-6 sm:mt-8 p-4 sm:p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[150px]"> <!-- Ajustement padding et min-height -->
302
  <!-- Le contenu analysé sera inséré ici -->
303
  </div>
304
  </div>
@@ -452,10 +443,10 @@
452
  return;
453
  }
454
 
455
- sauvegardes.forEach((sauvegarde) => { // Removed unused index
456
  const date = new Date(sauvegarde.date);
457
- const formattedDate = date.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }); // Shorter date
458
- const displayTitle = (sauvegarde.titre || "Sans titre").length > 40 ? sauvegarde.titre.substring(0, 37) + '...' : (sauvegarde.titre || "Sans titre"); // Shorter title
459
 
460
  const sauvegardeDiv = document.createElement('div');
461
  sauvegardeDiv.dataset.originalDate = sauvegarde.date;
@@ -490,7 +481,7 @@
490
  sauvegardeDiv.querySelector('.copy-btn').addEventListener('click', (e) => {
491
  e.stopPropagation();
492
  navigator.clipboard.writeText(sauvegarde.contenu || '').then(() => {
493
- const icon = e.currentTarget.querySelector('i'); icon.className = 'fas fa-check text-green-500 text-xs sm:text-sm'; setTimeout(() => { icon.className = 'fas fa-copy text-xs sm:text-sm'; }, 1500); // Shorter duration
494
  }).catch(err => { console.error('Copy error:', err); displayNotification("Erreur copie", "error"); });
495
  });
496
 
@@ -548,7 +539,7 @@
548
  e.preventDefault();
549
  const originalButtonContent = submitButton.innerHTML;
550
  submitButton.disabled = true;
551
- submitButton.innerHTML = `<div class="flex items-center justify-center"><div class="loader"><div></div><div></div><div></div><div></div></div><span class="ml-2 text-sm sm:text-base">Génération...</span></div>`; // Responsive text
552
 
553
  const sujetValue = sujetTextarea.value.trim();
554
  const isDeepThinkChecked = deepThinkCheckbox.checked;
@@ -564,10 +555,10 @@
564
  const lastUsedDateStr = localStorage.getItem(DEEPTHINK_STORAGE_KEY);
565
  const todayStr = new Date().toISOString().split('T')[0];
566
  if (lastUsedDateStr === todayStr) {
567
- output.innerHTML = `<div class="alert-message alert-warning"><i class="fas fa-exclamation-triangle"></i><div><p>Limite atteinte</p><p>DeepThink déjà utilisé.</p></div></div>`; // Shorter message
568
  checkDeepThinkAvailability(); submitButton.disabled = false; submitButton.innerHTML = originalButtonContent; return;
569
  }
570
- } catch(e) { /* Proceed without check if localStorage fails */ }
571
  }
572
  output.innerHTML = `<div class="flex justify-center items-center p-6"><div class="loader"><div></div><div></div><div></div><div></div></div></div>`;
573
 
@@ -579,8 +570,8 @@
579
 
580
  try { output.innerHTML = marked.parse(result.output || ''); } catch (e) { output.innerHTML = "Erreur d'affichage."; console.error(e); }
581
 
582
- const titreSauvegarde = sujetValue.substring(0, 40) + (sujetValue.length > 40 ? '...' : ''); // Even shorter title
583
- const deepThinkSuffix = isDeepThinkChecked ? ' [DT]' : ''; // Shorter suffix
584
  sauvegarderReponse(titreSauvegarde + deepThinkSuffix, result.output);
585
 
586
  if (isDeepThinkChecked) {
@@ -605,7 +596,7 @@
605
  e.preventDefault();
606
  const originalButtonContent = submitButton.innerHTML;
607
  submitButton.disabled = true;
608
- submitButton.innerHTML = `<div class="flex items-center justify-center"><div class="loader"><div></div><div></div><div></div><div></div></div><span class="ml-2 text-sm sm:text-base">Analyse...</span></div>`; // Responsive text
609
 
610
  if (uploadedFiles.size === 0) {
611
  output.innerHTML = `<div class="alert-message alert-warning"><i class="fas fa-exclamation-triangle"></i><div><p>Aucune image</p><p>Ajoutez au moins une image.</p></div></div>`;
@@ -621,7 +612,7 @@
621
 
622
  try { output.innerHTML = marked.parse(result.output || ''); } catch (e) { output.innerHTML = "Erreur d'affichage."; console.error(e); }
623
 
624
- const titre = `Analyse img ${new Date().toLocaleDateString('fr-FR', { month: 'short', day: 'numeric' })}`; // Shorter title
625
  sauvegarderReponse(titre, result.output);
626
  } catch (error) {
627
  console.error("Erreur soumission (img):", error);
@@ -641,7 +632,7 @@
641
  }
642
  function enhanceTextareaFocus() {
643
  const textarea = document.getElementById('sujet-francais'); const counter = document.getElementById('character-count'); if(!textarea || !counter) return;
644
- textarea.addEventListener('input', () => { const length = textarea.value.length; counter.textContent = `${length}c`; textarea.classList.remove('border-red-500'); }); // Shorter counter
645
  }
646
  function enhanceRadioButtons() {
647
  document.querySelectorAll('input[type="radio"] + span').forEach(label => {
@@ -669,6 +660,35 @@
669
  checkDeepThinkAvailability();
670
  afficherSauvegardes();
671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  // Welcome Message
673
  try {
674
  const showWelcome = sessionStorage.getItem('welcomeShown') !== 'true';
@@ -679,7 +699,7 @@
679
  const welcomeMsg = welcomeContainer.firstElementChild;
680
  setTimeout(() => { welcomeMsg.classList.remove('opacity-0', 'translate-y-4'); }, 500);
681
  welcomeMsg.querySelector('.close-welcome').addEventListener('click', () => closeWelcomeMessage(welcomeMsg));
682
- setTimeout(() => { if (document.body.contains(welcomeMsg)) closeWelcomeMessage(welcomeMsg); }, 6000); // Shorter duration
683
  sessionStorage.setItem('welcomeShown', 'true');
684
  }
685
  } catch(e) { console.warn("SessionStorage (Welcome):", e); }
 
7
  <title>Mariam AI - Assistant Français Intelligent</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js"></script>
 
10
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
11
  <style>
12
  @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');
 
28
  font-family: 'Plus Jakarta Sans', sans-serif;
29
  background-color: #fafafa;
30
  scroll-behavior: smooth;
31
+ -webkit-tap-highlight-color: transparent;
32
+ /* MODIFICATION: Empêcher la sélection de texte par défaut */
33
+ -webkit-user-select: none; /* Safari */
34
+ -moz-user-select: none; /* Firefox */
35
+ -ms-user-select: none; /* IE/Edge */
36
+ user-select: none; /* Standard */
37
  }
38
 
39
+ /* MODIFICATION: Réactiver la sélection pour les champs modifiables */
40
+ input, textarea {
41
+ -webkit-user-select: text; /* Safari */
42
+ -moz-user-select: text; /* Firefox */
43
+ -ms-user-select: text; /* IE/Edge */
44
+ user-select: text; /* Standard */
45
+ }
46
+ /* Optionnel: Si vous voulez autoriser la sélection dans les zones de sortie */
47
+ /* #francais-output, #etude-texte-output, .backup-content {
48
+ -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text;
49
+ } */
50
+
51
+
52
  .glassmorphism {
53
  background: rgba(255, 255, 255, 0.95);
54
  backdrop-filter: blur(10px);
55
+ -webkit-backdrop-filter: blur(10px);
56
  border: 1px solid rgba(255, 255, 255, 0.3);
57
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
58
  }
59
 
60
+ .card-hover { transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); }
61
+ .card-hover:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08); }
 
 
 
 
 
 
62
 
63
+ .gradient-text { background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; text-fill-color: transparent; }
 
 
 
 
 
 
64
 
65
+ .loading-dot { animation: bounce 1.4s infinite; }
 
 
66
  .loading-dot:nth-child(2) { animation-delay: 0.2s; }
67
  .loading-dot:nth-child(3) { animation-delay: 0.4s; }
68
  @keyframes bounce { 0%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-6px); } }
69
 
70
+ .custom-radio:checked+span { background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 100%); color: white; border-color: var(--primary); }
 
 
 
 
71
 
72
+ /* Styles alertes */
73
  .alert-message { display: flex; align-items: flex-start; padding: 1rem; border-radius: 0.5rem; border-width: 1px; border-style: solid; }
74
  .alert-message i { margin-right: 0.75rem; font-size: 1.25rem; margin-top: 0.125rem; flex-shrink: 0; }
75
  .alert-message div p:first-child { font-weight: 500; }
 
102
  .image-preview-item:hover .remove-image { opacity: 1; }
103
  .remove-image:hover { background-color: rgba(0, 0, 0, 0.8); transform: scale(1.1); }
104
 
105
+ /* Style Prose */
106
+ .prose { white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; color: #2d3748; line-height: 1.7; font-size: 0.95rem; }
107
+ @media (min-width: 640px) { .prose { font-size: 1rem; } }
108
  .prose h1, .prose h2, .prose h3, .prose h4 { color: var(--primary-dark); margin-top: 1.5em; margin-bottom: 0.5em; font-weight: 600; }
109
  .prose p { margin-bottom: 1em; }
110
  .prose ul, .prose ol { padding-left: 1.5em; margin-bottom: 1em; }
111
  .prose blockquote { border-left: 4px solid var(--primary); padding-left: 1em; font-style: italic; color: var(--secondary); margin: 1em 0; }
112
+ .prose code { background-color: #edf2f7; padding: 0.2em 0.4em; border-radius: 0.25rem; font-size: 0.9em; }
113
+ .prose pre { background-color: #1a202c; color: #e2e8f0; padding: 1em; border-radius: 0.375rem; overflow-x: auto; }
114
  .prose pre code { background-color: transparent; padding: 0; border-radius: 0; font-size: 0.875em; }
115
 
116
  /* Loader */
117
+ .loader { display: inline-block; position: relative; width: 64px; height: 16px; }
118
  .loader div { position: absolute; top: 6px; width: 10px; height: 10px; border-radius: 50%; background: var(--primary); animation-timing-function: cubic-bezier(0, 1, 1, 0); }
119
  .loader div:nth-child(1) { left: 6px; animation: loader1 0.6s infinite; }
120
  .loader div:nth-child(2) { left: 6px; animation: loader2 0.6s infinite; }
 
149
 
150
  <body class="min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 text-gray-800">
151
  <nav class="glassmorphism sticky top-0 z-50 border-b border-blue-100">
152
+ <div class="container mx-auto px-4 sm:px-6 py-3 sm:py-4">
 
153
  <div class="flex items-center justify-between">
154
  <div class="flex items-center space-x-3 sm:space-x-4">
155
  <div class="bg-gradient-to-r from-blue-600 to-blue-800 rounded-lg p-2 shadow-lg transform hover:scale-110 transition-transform duration-300">
156
+ <i class="fas fa-robot text-white text-lg sm:text-xl"></i>
157
  </div>
158
+ <h1 class="text-xl sm:text-2xl font-bold gradient-text">Mariam AI</h1>
159
  </div>
160
+ <div class="text-xs sm:text-sm text-blue-900 font-medium bg-blue-50 py-1 px-3 sm:px-4 rounded-full shadow-sm hidden sm:block">Assistant Français</div>
161
+ <div class="text-xs text-blue-900 font-medium bg-blue-50 py-1 px-3 rounded-full shadow-sm sm:hidden">Assistant</div>
162
  </div>
163
  </div>
164
  </nav>
165
 
166
+ <main class="container mx-auto px-4 sm:px-6 py-8 sm:py-12">
 
167
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 sm:gap-8">
168
  <!-- Section Travail Argumentatif -->
169
  <div class="card-hover glassmorphism rounded-2xl overflow-hidden scale-in">
170
+ <div class="p-6 sm:p-8">
 
171
  <div class="flex items-center space-x-3 sm:space-x-4 mb-6 sm:mb-8">
172
  <div class="bg-blue-100 rounded-lg p-2 sm:p-3 transform rotate-3">
173
  <i class="fas fa-pen-fancy text-blue-600 text-lg sm:text-xl"></i>
174
  </div>
175
  <h2 class="text-xl sm:text-2xl font-bold text-gray-800">Travail Argumentatif</h2>
176
  </div>
177
+ <form id="francais-form" class="space-y-6 sm:space-y-8">
 
178
  <div class="space-y-2">
179
  <label for="sujet-francais" class="block text-sm font-medium text-gray-700 flex items-center">
180
  <i class="fas fa-book-open mr-2 text-blue-500"></i>Sujet <span class="text-red-500 ml-1">*</span>
 
184
  class="w-full px-3 py-2 sm:px-4 sm:py-3 rounded-xl border-2 border-gray-200 focus:border-blue-500 focus:outline-none transition-all duration-200 resize-none text-base"
185
  placeholder="Entrez votre sujet ici..." required></textarea>
186
  </div>
187
+ <div class="text-xs text-gray-400 text-right" id="character-count">0c</div>
188
  </div>
189
 
190
  <div class="space-y-3">
191
  <label class="block text-sm font-medium text-gray-700 flex items-center">
192
  <i class="fas fa-tasks mr-2 text-blue-500"></i>Type d'argumentation
193
  </label>
 
194
  <div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4">
195
  <label class="relative">
196
  <input type="radio" name="choix" value="Etaye" class="custom-radio absolute opacity-0 w-full h-full cursor-pointer" checked>
 
233
  <span class="text-sm">Utiliser DeepThink</span>
234
  <div class="deepthink-tooltip">
235
  <i class="fas fa-info-circle text-gray-400 ml-1"></i>
236
+ <span class="tooltip-text">Modèle avancé (Gemini Pro). Plus lent, meilleure qualité. Limité: 1/jour.</span>
237
  </div>
238
  </label>
239
  <span id="deepthink-status" class="text-xs text-gray-500 ml-2"></span>
 
247
  </div>
248
  </button>
249
  </form>
250
+ <div id="francais-output" class="mt-6 sm:mt-8 p-4 sm:p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[150px]">
 
251
  <!-- Le contenu généré sera inséré ici -->
252
  </div>
253
  </div>
 
255
 
256
  <!-- Section Étude de texte -->
257
  <div class="card-hover glassmorphism rounded-2xl overflow-hidden scale-in" style="animation-delay: 0.1s;">
258
+ <div class="p-6 sm:p-8">
 
259
  <div class="flex items-center space-x-3 sm:space-x-4 mb-6 sm:mb-8">
260
  <div class="bg-blue-100 rounded-lg p-2 sm:p-3 transform -rotate-3">
261
  <i class="fas fa-file-alt text-blue-600 text-lg sm:text-xl"></i>
 
289
  </div>
290
  </button>
291
  </form>
292
+ <div id="etude-texte-output" class="mt-6 sm:mt-8 p-4 sm:p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[150px]">
 
293
  <!-- Le contenu analysé sera inséré ici -->
294
  </div>
295
  </div>
 
443
  return;
444
  }
445
 
446
+ sauvegardes.forEach((sauvegarde) => {
447
  const date = new Date(sauvegarde.date);
448
+ const formattedDate = date.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });
449
+ const displayTitle = (sauvegarde.titre || "Sans titre").length > 40 ? sauvegarde.titre.substring(0, 37) + '...' : (sauvegarde.titre || "Sans titre");
450
 
451
  const sauvegardeDiv = document.createElement('div');
452
  sauvegardeDiv.dataset.originalDate = sauvegarde.date;
 
481
  sauvegardeDiv.querySelector('.copy-btn').addEventListener('click', (e) => {
482
  e.stopPropagation();
483
  navigator.clipboard.writeText(sauvegarde.contenu || '').then(() => {
484
+ const icon = e.currentTarget.querySelector('i'); icon.className = 'fas fa-check text-green-500 text-xs sm:text-sm'; setTimeout(() => { icon.className = 'fas fa-copy text-xs sm:text-sm'; }, 1500);
485
  }).catch(err => { console.error('Copy error:', err); displayNotification("Erreur copie", "error"); });
486
  });
487
 
 
539
  e.preventDefault();
540
  const originalButtonContent = submitButton.innerHTML;
541
  submitButton.disabled = true;
542
+ submitButton.innerHTML = `<div class="flex items-center justify-center"><div class="loader"><div></div><div></div><div></div><div></div></div><span class="ml-2 text-sm sm:text-base">Génération...</span></div>`;
543
 
544
  const sujetValue = sujetTextarea.value.trim();
545
  const isDeepThinkChecked = deepThinkCheckbox.checked;
 
555
  const lastUsedDateStr = localStorage.getItem(DEEPTHINK_STORAGE_KEY);
556
  const todayStr = new Date().toISOString().split('T')[0];
557
  if (lastUsedDateStr === todayStr) {
558
+ output.innerHTML = `<div class="alert-message alert-warning"><i class="fas fa-exclamation-triangle"></i><div><p>Limite atteinte</p><p>DeepThink déjà utilisé.</p></div></div>`;
559
  checkDeepThinkAvailability(); submitButton.disabled = false; submitButton.innerHTML = originalButtonContent; return;
560
  }
561
+ } catch(e) { /* Proceed without check */ }
562
  }
563
  output.innerHTML = `<div class="flex justify-center items-center p-6"><div class="loader"><div></div><div></div><div></div><div></div></div></div>`;
564
 
 
570
 
571
  try { output.innerHTML = marked.parse(result.output || ''); } catch (e) { output.innerHTML = "Erreur d'affichage."; console.error(e); }
572
 
573
+ const titreSauvegarde = sujetValue.substring(0, 40) + (sujetValue.length > 40 ? '...' : '');
574
+ const deepThinkSuffix = isDeepThinkChecked ? ' [DT]' : '';
575
  sauvegarderReponse(titreSauvegarde + deepThinkSuffix, result.output);
576
 
577
  if (isDeepThinkChecked) {
 
596
  e.preventDefault();
597
  const originalButtonContent = submitButton.innerHTML;
598
  submitButton.disabled = true;
599
+ submitButton.innerHTML = `<div class="flex items-center justify-center"><div class="loader"><div></div><div></div><div></div><div></div></div><span class="ml-2 text-sm sm:text-base">Analyse...</span></div>`;
600
 
601
  if (uploadedFiles.size === 0) {
602
  output.innerHTML = `<div class="alert-message alert-warning"><i class="fas fa-exclamation-triangle"></i><div><p>Aucune image</p><p>Ajoutez au moins une image.</p></div></div>`;
 
612
 
613
  try { output.innerHTML = marked.parse(result.output || ''); } catch (e) { output.innerHTML = "Erreur d'affichage."; console.error(e); }
614
 
615
+ const titre = `Analyse img ${new Date().toLocaleDateString('fr-FR', { month: 'short', day: 'numeric' })}`;
616
  sauvegarderReponse(titre, result.output);
617
  } catch (error) {
618
  console.error("Erreur soumission (img):", error);
 
632
  }
633
  function enhanceTextareaFocus() {
634
  const textarea = document.getElementById('sujet-francais'); const counter = document.getElementById('character-count'); if(!textarea || !counter) return;
635
+ textarea.addEventListener('input', () => { const length = textarea.value.length; counter.textContent = `${length}c`; textarea.classList.remove('border-red-500'); });
636
  }
637
  function enhanceRadioButtons() {
638
  document.querySelectorAll('input[type="radio"] + span').forEach(label => {
 
660
  checkDeepThinkAvailability();
661
  afficherSauvegardes();
662
 
663
+ // MODIFICATION: Empêcher le menu contextuel (clic droit)
664
+ document.addEventListener('contextmenu', function(event) {
665
+ // Optionnel: Autoriser le clic droit sur les inputs/textareas
666
+ // if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
667
+ // return;
668
+ // }
669
+ event.preventDefault();
670
+ });
671
+
672
+ // MODIFICATION: Empêcher le début de sélection (complément CSS)
673
+ document.addEventListener('selectstart', function(event) {
674
+ // Autoriser la sélection dans les inputs et textareas
675
+ if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
676
+ return;
677
+ }
678
+ // Optionnel: Autoriser la sélection dans les zones de sortie générées
679
+ // const outputIds = ['francais-output', 'etude-texte-output'];
680
+ // let parent = event.target.closest('.prose'); // Check if selection starts within a prose element
681
+ // if (parent && outputIds.includes(parent.id)) {
682
+ // return;
683
+ // }
684
+ // Optionnel: Autoriser la sélection dans les sauvegardes affichées
685
+ // if (event.target.closest('.backup-content')) {
686
+ // return;
687
+ // }
688
+
689
+ event.preventDefault();
690
+ });
691
+
692
  // Welcome Message
693
  try {
694
  const showWelcome = sessionStorage.getItem('welcomeShown') !== 'true';
 
699
  const welcomeMsg = welcomeContainer.firstElementChild;
700
  setTimeout(() => { welcomeMsg.classList.remove('opacity-0', 'translate-y-4'); }, 500);
701
  welcomeMsg.querySelector('.close-welcome').addEventListener('click', () => closeWelcomeMessage(welcomeMsg));
702
+ setTimeout(() => { if (document.body.contains(welcomeMsg)) closeWelcomeMessage(welcomeMsg); }, 6000);
703
  sessionStorage.setItem('welcomeShown', 'true');
704
  }
705
  } catch(e) { console.warn("SessionStorage (Welcome):", e); }