Spaces:
				
			
			
	
			
			
		Build error
		
	
	
	
			
			
	
	
	
	
		
		
		Build error
		
	Update templates/index.html
Browse files- templates/index.html +352 -353
 
    	
        templates/index.html
    CHANGED
    
    | 
         @@ -83,14 +83,17 @@ 
     | 
|
| 83 | 
         
             
                    /* Styles pour les messages d'erreur/avertissement */
         
     | 
| 84 | 
         
             
                    .alert-message {
         
     | 
| 85 | 
         
             
                        display: flex;
         
     | 
| 86 | 
         
            -
                        align-items:  
     | 
| 87 | 
         
            -
                        space-x 
     | 
| 88 | 
         
             
                        padding: 1rem; /* p-4 */
         
     | 
| 89 | 
         
             
                        border-radius: 0.5rem; /* rounded-lg */
         
     | 
| 
         | 
|
| 
         | 
|
| 90 | 
         
             
                    }
         
     | 
| 91 | 
         
             
                    .alert-message i {
         
     | 
| 92 | 
         
             
                         margin-right: 0.75rem; /* space-x-3 equivalent */
         
     | 
| 93 | 
         
             
                         font-size: 1.25rem; /* text-xl */
         
     | 
| 
         | 
|
| 94 | 
         
             
                    }
         
     | 
| 95 | 
         
             
                    .alert-message div p:first-child {
         
     | 
| 96 | 
         
             
                        font-weight: 500; /* font-medium */
         
     | 
| 
         @@ -98,30 +101,31 @@ 
     | 
|
| 98 | 
         
             
                     .alert-message div p:last-child {
         
     | 
| 99 | 
         
             
                        font-size: 0.875rem; /* text-sm */
         
     | 
| 100 | 
         
             
                        margin-top: 0.25rem; /* mt-1 */
         
     | 
| 
         | 
|
| 101 | 
         
             
                    }
         
     | 
| 102 | 
         | 
| 103 | 
         
             
                    .alert-warning {
         
     | 
| 104 | 
         
            -
                         color: #92400e; /* text-amber-700  
     | 
| 105 | 
         
             
                         background-color: #fffbeb; /* bg-amber-50 */
         
     | 
| 106 | 
         
            -
                         border:  
     | 
| 107 | 
         
             
                    }
         
     | 
| 108 | 
         
             
                    .alert-warning i {
         
     | 
| 109 | 
         
             
                        color: var(--warning); /* text-amber-500 */
         
     | 
| 110 | 
         
             
                    }
         
     | 
| 111 | 
         
             
                    .alert-warning div p:last-child {
         
     | 
| 112 | 
         
            -
                         color: #b45309; /* text-amber-600  
     | 
| 113 | 
         
             
                    }
         
     | 
| 114 | 
         | 
| 115 | 
         
             
                    .alert-danger {
         
     | 
| 116 | 
         
            -
                         color: #991b1b; /* text-red-700  
     | 
| 117 | 
         
             
                         background-color: #fef2f2; /* bg-red-50 */
         
     | 
| 118 | 
         
            -
                         border:  
     | 
| 119 | 
         
             
                    }
         
     | 
| 120 | 
         
             
                    .alert-danger i {
         
     | 
| 121 | 
         
             
                         color: var(--danger); /* text-red-500 */
         
     | 
| 122 | 
         
             
                    }
         
     | 
| 123 | 
         
             
                     .alert-danger div p:last-child {
         
     | 
| 124 | 
         
            -
                         color: #b91c1c; /* text-red-600  
     | 
| 125 | 
         
             
                    }
         
     | 
| 126 | 
         | 
| 127 | 
         | 
| 
         @@ -159,16 +163,20 @@ 
     | 
|
| 159 | 
         
             
                        margin-top: 10px;
         
     | 
| 160 | 
         
             
                        max-height: 0;
         
     | 
| 161 | 
         
             
                        overflow: hidden;
         
     | 
| 162 | 
         
            -
                        transition: max-height 0.3s ease, opacity 0.3s ease;
         
     | 
| 163 | 
         
             
                        opacity: 0;
         
     | 
| 
         | 
|
| 164 | 
         
             
                    }
         
     | 
| 165 | 
         | 
| 166 | 
         
             
                    .backup-content-expanded {
         
     | 
| 167 | 
         
             
                        display: block;
         
     | 
| 168 | 
         
            -
                        max-height:  
     | 
| 169 | 
         
             
                        opacity: 1;
         
     | 
| 
         | 
|
| 
         | 
|
| 170 | 
         
             
                    }
         
     | 
| 171 | 
         | 
| 
         | 
|
| 172 | 
         
             
                    /* Styles for multiple image upload */
         
     | 
| 173 | 
         
             
                    .image-preview {
         
     | 
| 174 | 
         
             
                        display: flex;
         
     | 
| 
         @@ -344,6 +352,82 @@ 
     | 
|
| 344 | 
         
             
                            grid-template-columns: repeat(2, minmax(0, 1fr));
         
     | 
| 345 | 
         
             
                        }
         
     | 
| 346 | 
         
             
                    }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 347 | 
         
             
                </style>
         
     | 
| 348 | 
         
             
            </head>
         
     | 
| 349 | 
         | 
| 
         @@ -381,7 +465,7 @@ 
     | 
|
| 381 | 
         
             
                                        <div class="focus-ring">
         
     | 
| 382 | 
         
             
                                            <textarea id="sujet-francais" name="sujet" rows="4"
         
     | 
| 383 | 
         
             
                                                class="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-blue-500 focus:outline-none transition-all duration-200 resize-none"
         
     | 
| 384 | 
         
            -
                                                placeholder="Entrez votre sujet ici..." required></textarea> 
     | 
| 385 | 
         
             
                                        </div>
         
     | 
| 386 | 
         
             
                                        <div class="text-xs text-gray-400 text-right" id="character-count">0 caract猫res</div>
         
     | 
| 387 | 
         
             
                                    </div>
         
     | 
| 
         @@ -416,12 +500,10 @@ 
     | 
|
| 416 | 
         
             
                                                </span>
         
     | 
| 417 | 
         
             
                                            </label>
         
     | 
| 418 | 
         
             
                                            <label class="relative">
         
     | 
| 419 | 
         
            -
                                                 <!-- MODIFICATION ICI: disabled retir茅, span class mise 脿 jour, badge retir茅 -->
         
     | 
| 420 | 
         
             
                                                <input type="radio" name="choix" value="dissertation"
         
     | 
| 421 | 
         
             
                                                    class="custom-radio absolute opacity-0 w-full h-full cursor-pointer">
         
     | 
| 422 | 
         
             
                                                <span class="flex items-center justify-center p-3 border-2 border-gray-200 rounded-xl text-sm font-medium transition-all duration-200 hover:border-blue-400">
         
     | 
| 423 | 
         
             
                                                    Dissertation
         
     | 
| 424 | 
         
            -
                                                    <!-- <span class="coming-soon-badge">Bient么t</span> -->
         
     | 
| 425 | 
         
             
                                                </span>
         
     | 
| 426 | 
         
             
                                            </label>
         
     | 
| 427 | 
         
             
                                        </div>
         
     | 
| 
         @@ -451,6 +533,20 @@ 
     | 
|
| 451 | 
         
             
                                        </div>
         
     | 
| 452 | 
         
             
                                    </div>
         
     | 
| 453 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 454 | 
         
             
                                    <button type="submit"
         
     | 
| 455 | 
         
             
                                        class="w-full bg-gradient-to-r from-blue-600 to-blue-800 text-white px-6 py-4 rounded-xl font-medium hover:from-blue-700 hover:to-blue-900 transition-all duration-300 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg">
         
     | 
| 456 | 
         
             
                                        <div class="flex items-center justify-center space-x-3">
         
     | 
| 
         @@ -459,7 +555,7 @@ 
     | 
|
| 459 | 
         
             
                                        </div>
         
     | 
| 460 | 
         
             
                                    </button>
         
     | 
| 461 | 
         
             
                                </form>
         
     | 
| 462 | 
         
            -
                                <div id="francais-output" class="mt-8 p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[100px]"> 
     | 
| 463 | 
         
             
                                    <!-- Le contenu g茅n茅r茅 sera ins茅r茅 ici -->
         
     | 
| 464 | 
         
             
                                </div>
         
     | 
| 465 | 
         
             
                            </div>
         
     | 
| 
         @@ -481,7 +577,7 @@ 
     | 
|
| 481 | 
         
             
                                        </label>
         
     | 
| 482 | 
         
             
                                        <div class="border-3 border-dashed border-gray-300 rounded-xl p-8 text-center cursor-pointer hover:border-blue-400 transition-all duration-200 group"
         
     | 
| 483 | 
         
             
                                             id="drop-zone">
         
     | 
| 484 | 
         
            -
                                            <input type="file" id="image-upload" name="images" accept="image/*" class="hidden" multiple> 
     | 
| 485 | 
         
             
                                            <div class="space-y-4">
         
     | 
| 486 | 
         
             
                                                <div class="bg-blue-50 rounded-full w-16 h-16 flex items-center justify-center mx-auto transform transition-transform group-hover:scale-110 group-hover:rotate-6">
         
     | 
| 487 | 
         
             
                                                    <i class="fas fa-cloud-upload-alt text-3xl text-blue-500"></i>
         
     | 
| 
         @@ -491,7 +587,7 @@ 
     | 
|
| 491 | 
         
             
                                                <p class="text-xs text-gray-400">PNG, JPG, WEBP jusqu'脿 10MB</p>
         
     | 
| 492 | 
         
             
                                            </div>
         
     | 
| 493 | 
         
             
                                        </div>
         
     | 
| 494 | 
         
            -
                                        <div id="image-preview" class="image-preview"></div> 
     | 
| 495 | 
         
             
                                    </div>
         
     | 
| 496 | 
         | 
| 497 | 
         
             
                                    <button type="submit"
         
     | 
| 
         @@ -502,7 +598,7 @@ 
     | 
|
| 502 | 
         
             
                                        </div>
         
     | 
| 503 | 
         
             
                                    </button>
         
     | 
| 504 | 
         
             
                                </form>
         
     | 
| 505 | 
         
            -
                                 <div id="etude-texte-output" class="mt-8 p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[100px]"> 
     | 
| 506 | 
         
             
                                    <!-- Le contenu analys茅 sera ins茅r茅 ici -->
         
     | 
| 507 | 
         
             
                                </div>
         
     | 
| 508 | 
         
             
                            </div>
         
     | 
| 
         @@ -638,7 +734,9 @@ 
     | 
|
| 638 | 
         
             
                             previewElement.style.opacity = '0';
         
     | 
| 639 | 
         
             
                             previewElement.style.transform = 'scale(0.9)';
         
     | 
| 640 | 
         
             
                             setTimeout(() => {
         
     | 
| 641 | 
         
            -
                                  imagePreview. 
     | 
| 
         | 
|
| 
         | 
|
| 642 | 
         
             
                             }, 300);
         
     | 
| 643 | 
         
             
                        }
         
     | 
| 644 | 
         
             
                    }
         
     | 
| 
         @@ -646,13 +744,12 @@ 
     | 
|
| 646 | 
         
             
                    function sauvegarderReponse(titre, contenu) {
         
     | 
| 647 | 
         
             
                        const sauvegardes = JSON.parse(localStorage.getItem('mariam_ai_sauvegardes') || '[]');
         
     | 
| 648 | 
         
             
                        const dateSauvegarde = new Date().toISOString();
         
     | 
| 649 | 
         
            -
                        // Limiter la taille des sauvegardes si n茅cessaire
         
     | 
| 650 | 
         
             
                        const MAX_SAUVEGARDES = 20;
         
     | 
| 651 | 
         
             
                        if (sauvegardes.length >= MAX_SAUVEGARDES) {
         
     | 
| 652 | 
         
            -
                             sauvegardes.shift(); 
     | 
| 653 | 
         
             
                        }
         
     | 
| 654 | 
         
             
                        sauvegardes.push({
         
     | 
| 655 | 
         
            -
                            titre: titre || "Sauvegarde sans titre", 
     | 
| 656 | 
         
             
                            contenu,
         
     | 
| 657 | 
         
             
                            date: dateSauvegarde
         
     | 
| 658 | 
         
             
                        });
         
     | 
| 
         @@ -660,24 +757,22 @@ 
     | 
|
| 660 | 
         
             
                             localStorage.setItem('mariam_ai_sauvegardes', JSON.stringify(sauvegardes));
         
     | 
| 661 | 
         
             
                        } catch (e) {
         
     | 
| 662 | 
         
             
                            console.error("Erreur lors de la sauvegarde dans localStorage (peut-锚tre plein):", e);
         
     | 
| 663 | 
         
            -
                            // Afficher une erreur 脿 l'utilisateur si localStorage est plein
         
     | 
| 664 | 
         
             
                            displayNotification("Erreur de sauvegarde: Espace de stockage local plein.", "error");
         
     | 
| 665 | 
         
            -
                            return; 
     | 
| 666 | 
         
             
                        }
         
     | 
| 667 | 
         
            -
             
     | 
| 668 | 
         
            -
             
     | 
| 669 | 
         
             
                        displayNotification("Sauvegard茅 avec succ猫s", "success");
         
     | 
| 670 | 
         
            -
                        afficherSauvegardes(); 
     | 
| 671 | 
         
             
                    }
         
     | 
| 672 | 
         | 
| 673 | 
         
             
                    function displayNotification(message, type = 'success') {
         
     | 
| 674 | 
         
             
                         const notification = document.createElement('div');
         
     | 
| 675 | 
         
            -
                         const bgColor = type === 'success' ? 'bg-green-50 border-green-200 text-green-700' : 'bg-red-50 border-red-200 text-red-700';
         
     | 
| 676 | 
         
            -
                         const iconClass = type === 'success' ? 'fa-check-circle text-green-500' : 'fa-exclamation-circle text-red-500';
         
     | 
| 677 | 
         | 
| 678 | 
         
            -
             
     | 
| 
         | 
|
| 679 | 
         
             
                         notification.innerHTML = `
         
     | 
| 680 | 
         
            -
                            <i class="fas ${iconClass} mr- 
     | 
| 681 | 
         
             
                            <span class="text-sm font-medium">${message}</span>
         
     | 
| 682 | 
         
             
                        `;
         
     | 
| 683 | 
         
             
                        document.body.appendChild(notification);
         
     | 
| 
         @@ -690,7 +785,7 @@ 
     | 
|
| 690 | 
         
             
                                     document.body.removeChild(notification);
         
     | 
| 691 | 
         
             
                                }
         
     | 
| 692 | 
         
             
                            }, 300);
         
     | 
| 693 | 
         
            -
                        }, 3000);
         
     | 
| 694 | 
         
             
                    }
         
     | 
| 695 | 
         | 
| 696 | 
         | 
| 
         @@ -702,203 +797,173 @@ 
     | 
|
| 702 | 
         
             
                    }
         
     | 
| 703 | 
         | 
| 704 | 
         | 
| 705 | 
         
            -
            function afficherSauvegardes() {
         
     | 
| 706 | 
         
            -
             
     | 
| 707 | 
         
            -
             
     | 
| 708 | 
         
            -
             
     | 
| 709 | 
         
            -
             
     | 
| 710 | 
         
            -
             
     | 
| 711 | 
         
            -
             
     | 
| 712 | 
         
            -
             
     | 
| 713 | 
         
            -
             
     | 
| 714 | 
         
            -
             
     | 
| 715 | 
         
            -
             
     | 
| 716 | 
         
            -
             
     | 
| 717 | 
         
            -
             
     | 
| 718 | 
         
            -
             
     | 
| 719 | 
         
            -
             
     | 
| 720 | 
         
            -
             
     | 
| 721 | 
         
            -
             
     | 
| 722 | 
         
            -
                    return;
         
     | 
| 723 | 
         
            -
                }
         
     | 
| 724 | 
         
            -
             
     | 
| 725 | 
         
            -
                sauvegardes.forEach((sauvegarde, index) => {
         
     | 
| 726 | 
         
            -
                    const date = new Date(sauvegarde.date);
         
     | 
| 727 | 
         
            -
                    const formattedDate = date.toLocaleDateString('fr-FR', {
         
     | 
| 728 | 
         
            -
                        day: 'numeric',
         
     | 
| 729 | 
         
            -
                        month: 'short',
         
     | 
| 730 | 
         
            -
                        year: 'numeric',
         
     | 
| 731 | 
         
            -
                        hour: '2-digit',
         
     | 
| 732 | 
         
            -
                        minute: '2-digit'
         
     | 
| 733 | 
         
            -
                    });
         
     | 
| 734 | 
         
            -
             
     | 
| 735 | 
         
            -
                    // Tronquer le titre si trop long pour l'affichage initial
         
     | 
| 736 | 
         
            -
                    const displayTitle = sauvegarde.titre.length > 60 ? sauvegarde.titre.substring(0, 57) + '...' : sauvegarde.titre;
         
     | 
| 737 | 
         
            -
             
     | 
| 738 | 
         
            -
                    const sauvegardeDiv = document.createElement('div');
         
     | 
| 739 | 
         
            -
                    // Utilise l'index original (avant tri) pour la suppression si n茅cessaire, ou l'index apr猫s tri si la suppression se base sur l'茅l茅ment affich茅.
         
     | 
| 740 | 
         
            -
                    // Ici on utilise l'index apr猫s tri car on supprime de la liste tri茅e affich茅e.
         
     | 
| 741 | 
         
            -
                    sauvegardeDiv.dataset.index = index; // Utiliser cet index pour la suppression
         
     | 
| 742 | 
         
            -
                    sauvegardeDiv.className = 'bg-white rounded-lg shadow-md p-4 relative backup-item hover:bg-blue-50 transition-all duration-200';
         
     | 
| 743 | 
         
            -
                    sauvegardeDiv.innerHTML = `
         
     | 
| 744 | 
         
            -
                        <div class="flex items-start cursor-pointer item-header"> <!-- Ajout curseur et classe pour le clic -->
         
     | 
| 745 | 
         
            -
                            <div class="bg-blue-100 rounded-lg p-2 mr-3 flex-shrink-0"> <!-- flex-shrink-0 -->
         
     | 
| 746 | 
         
            -
                                <i class="fas fa-file-alt text-blue-600"></i>
         
     | 
| 747 | 
         
            -
                            </div>
         
     | 
| 748 | 
         
            -
                            <div class="flex-grow overflow-hidden"> <!-- overflow-hidden -->
         
     | 
| 749 | 
         
            -
                                <h3 class="text-lg font-semibold text-gray-800 truncate" title="${sauvegarde.titre}">${displayTitle}</h3> <!-- truncate et title -->
         
     | 
| 750 | 
         
            -
                                <p class="text-sm text-gray-600 mb-2 flex items-center">
         
     | 
| 751 | 
         
            -
                                    <i class="fas fa-clock text-xs mr-1 text-gray-400"></i>
         
     | 
| 752 | 
         
            -
                                    ${formattedDate}
         
     | 
| 753 | 
         
            -
                                </p>
         
     | 
| 754 | 
         
            -
                            </div>
         
     | 
| 755 | 
         
            -
                            <div class="flex space-x-2 ml-2 flex-shrink-0"> <!-- ml-2 et flex-shrink-0 -->
         
     | 
| 756 | 
         
            -
                                <button class="text-gray-400 hover:text-blue-600 focus:outline-none copy-btn p-1" title="Copier">
         
     | 
| 757 | 
         
            -
                                    <i class="fas fa-copy"></i>
         
     | 
| 758 | 
         
            -
                                </button>
         
     | 
| 759 | 
         
            -
                                <button class="text-gray-400 hover:text-red-600 focus:outline-none delete-btn p-1" title="Supprimer">
         
     | 
| 760 | 
         
            -
                                    <i class="fas fa-trash-alt"></i>
         
     | 
| 761 | 
         
            -
                                </button>
         
     | 
| 762 | 
         
            -
                            </div>
         
     | 
| 763 | 
         
            -
                        </div>
         
     | 
| 764 | 
         
            -
                        <div class="backup-content mt-4 text-sm text-gray-700 prose max-w-none border-t border-gray-100 pt-3">
         
     | 
| 765 | 
         
            -
                            <!-- Contenu charg茅 dynamiquement -->
         
     | 
| 766 | 
         
            -
                        </div>
         
     | 
| 767 | 
         
            -
                    `;
         
     | 
| 768 | 
         
            -
                    backupsList.appendChild(sauvegardeDiv);
         
     | 
| 769 | 
         
            -
             
     | 
| 770 | 
         
            -
                    // --- Event Listeners ---
         
     | 
| 771 | 
         
            -
                    const backupContentDiv = sauvegardeDiv.querySelector('.backup-content');
         
     | 
| 772 | 
         
            -
                    const headerDiv = sauvegardeDiv.querySelector('.item-header');
         
     | 
| 773 | 
         
            -
             
     | 
| 774 | 
         
            -
                    // Gestion de l'expansion/contraction du contenu au clic sur l'en-t锚te
         
     | 
| 775 | 
         
            -
                    headerDiv.addEventListener('click', (e) => {
         
     | 
| 776 | 
         
            -
                         // Basculer l'affichage du contenu actuel
         
     | 
| 777 | 
         
            -
                        const isExpanded = backupContentDiv.classList.contains('backup-content-expanded');
         
     | 
| 778 | 
         
            -
             
     | 
| 779 | 
         
            -
                        // Fermer tous les autres 茅l茅ments ouverts
         
     | 
| 780 | 
         
            -
                        document.querySelectorAll('.backup-content-expanded').forEach(content => {
         
     | 
| 781 | 
         
            -
                            if (content !== backupContentDiv) {
         
     | 
| 782 | 
         
            -
                                content.classList.remove('backup-content-expanded');
         
     | 
| 783 | 
         
            -
                                content.innerHTML = ''; // Vider le contenu des autres
         
     | 
| 784 | 
         
            -
                             }
         
     | 
| 785 | 
         
            -
                        });
         
     | 
| 786 | 
         
            -
             
     | 
| 787 | 
         
            -
                        if (!isExpanded) {
         
     | 
| 788 | 
         
            -
                            // Charger et afficher le contenu
         
     | 
| 789 | 
         
            -
                            backupContentDiv.innerHTML = marked.parse(sauvegarde.contenu);
         
     | 
| 790 | 
         
            -
                            backupContentDiv.classList.add('backup-content-expanded');
         
     | 
| 791 | 
         
            -
                            // Lancer MathJax seulement apr猫s que le contenu soit visible
         
     | 
| 792 | 
         
            -
                            setTimeout(() => {
         
     | 
| 793 | 
         
            -
                                MathJax.typesetPromise([backupContentDiv]).catch(function (err) {
         
     | 
| 794 | 
         
            -
                                     console.error('MathJax typesetting error:', err);
         
     | 
| 795 | 
         
            -
                                });
         
     | 
| 796 | 
         
            -
                            }, 50); // petit d茅lai pour s'assurer que l'茅l茅ment est rendu
         
     | 
| 797 | 
         
            -
                        } else {
         
     | 
| 798 | 
         
            -
                             // Cacher le contenu
         
     | 
| 799 | 
         
            -
                             backupContentDiv.classList.remove('backup-content-expanded');
         
     | 
| 800 | 
         
            -
                             backupContentDiv.innerHTML = ''; // Vider le contenu quand on ferme
         
     | 
| 801 | 
         
             
                        }
         
     | 
| 802 | 
         
            -
                    });
         
     | 
| 803 | 
         
            -
             
     | 
| 804 | 
         
            -
                    // Bouton de copie
         
     | 
| 805 | 
         
            -
                    const copyButton = sauvegardeDiv.querySelector('.copy-btn');
         
     | 
| 806 | 
         
            -
                    copyButton.addEventListener('click', (e) => {
         
     | 
| 807 | 
         
            -
                        e.stopPropagation(); // Emp锚che le clic de d茅clencher l'expansion
         
     | 
| 808 | 
         
            -
                        navigator.clipboard.writeText(sauvegarde.contenu).then(() => {
         
     | 
| 809 | 
         
            -
                            const icon = copyButton.querySelector('i');
         
     | 
| 810 | 
         
            -
                            icon.className = 'fas fa-check text-green-500'; // Ic么ne de succ猫s
         
     | 
| 811 | 
         
            -
                            setTimeout(() => {
         
     | 
| 812 | 
         
            -
                                icon.className = 'fas fa-copy'; // Retour 脿 l'ic么ne normale
         
     | 
| 813 | 
         
            -
                            }, 2000);
         
     | 
| 814 | 
         
            -
                        }).catch(err => {
         
     | 
| 815 | 
         
            -
                             console.error('Erreur de copie:', err);
         
     | 
| 816 | 
         
            -
                             displayNotification("Erreur lors de la copie", "error");
         
     | 
| 817 | 
         
            -
                        });
         
     | 
| 818 | 
         
            -
                    });
         
     | 
| 819 | 
         | 
| 820 | 
         
            -
             
     | 
| 821 | 
         
            -
             
     | 
| 822 | 
         
            -
             
     | 
| 823 | 
         
            -
             
     | 
| 824 | 
         
            -
             
     | 
| 825 | 
         
            -
             
     | 
| 826 | 
         
            -
             
     | 
| 827 | 
         
            -
             
     | 
| 828 | 
         
            -
             
     | 
| 829 | 
         
            -
             
     | 
| 830 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 831 | 
         | 
| 832 | 
         
            -
             
     | 
| 833 | 
         
            -
             
     | 
| 834 | 
         
            -
                        const originalIndex = originalSauvegardes.findIndex(s => s.date === itemToDelete.date && s.titre === itemToDelete.titre);
         
     | 
| 835 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 836 | 
         | 
| 837 | 
         
            -
             
     | 
| 838 | 
         
            -
                             
     | 
| 839 | 
         
            -
             
     | 
| 840 | 
         
            -
             
     | 
| 841 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 842 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 843 | 
         | 
| 844 | 
         
            -
             
     | 
| 845 | 
         
            -
             
     | 
| 846 | 
         
            -
             
     | 
| 847 | 
         
            -
             
     | 
| 848 | 
         
            -
             
     | 
| 849 | 
         
            -
             
     | 
| 850 | 
         
            -
             
     | 
| 851 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 852 | 
         
             
                                    </div>
         
     | 
| 853 | 
         
            -
             
     | 
| 854 | 
         
            -
                                 
     | 
| 855 | 
         
            -
                                <p class="text-gray-600 mb-6 text-sm">脢tes-vous s没r de vouloir supprimer cette sauvegarde ?</p>
         
     | 
| 856 | 
         
            -
                                <div class="flex justify-end space-x-3">
         
     | 
| 857 | 
         
            -
                                    <button class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 cancel-btn text-sm">Annuler</button>
         
     | 
| 858 | 
         
            -
                                    <button class="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 confirm-btn text-sm">Supprimer</button>
         
     | 
| 859 | 
         
            -
                                </div>
         
     | 
| 860 | 
         
            -
                            </div>
         
     | 
| 861 | 
         
            -
                        `;
         
     | 
| 862 | 
         
            -
                        document.body.appendChild(confirmationModal);
         
     | 
| 863 | 
         | 
| 864 | 
         
            -
             
     | 
| 865 | 
         
            -
             
     | 
| 866 | 
         
            -
             
     | 
| 867 | 
         
            -
             
     | 
| 868 | 
         
            -
             
     | 
| 869 | 
         
            -
             
     | 
| 870 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 871 | 
         
             
                        });
         
     | 
| 
         | 
|
| 872 | 
         | 
| 873 | 
         
            -
             
     | 
| 874 | 
         
            -
                          
     | 
| 875 | 
         
            -
             
     | 
| 876 | 
         
            -
             
     | 
| 877 | 
         
            -
             
     | 
| 878 | 
         
            -
             
     | 
| 879 | 
         
            -
             
     | 
| 880 | 
         
            -
             
     | 
| 881 | 
         
            -
            }
         
     | 
| 882 | 
         
            -
             
     | 
| 883 | 
         
            -
            function closeModal(modalElement) {
         
     | 
| 884 | 
         
            -
                 modalElement.style.opacity = '0';
         
     | 
| 885 | 
         
            -
                 setTimeout(() => {
         
     | 
| 886 | 
         
            -
                      if (document.body.contains(modalElement)) {
         
     | 
| 887 | 
         
            -
                         document.body.removeChild(modalElement);
         
     | 
| 888 | 
         
            -
                      }
         
     | 
| 889 | 
         
            -
                 }, 300);
         
     | 
| 890 | 
         
            -
            }
         
     | 
| 891 | 
         | 
| 892 | 
         | 
| 893 | 
         
             
                    async function submitFrancaisForm() {
         
     | 
| 894 | 
         
             
                        const form = document.getElementById('francais-form');
         
     | 
| 895 | 
         
             
                        const output = document.getElementById('francais-output');
         
     | 
| 896 | 
         
            -
                        const sujetTextarea = document.getElementById('sujet-francais'); 
     | 
| 
         | 
|
| 897 | 
         | 
| 898 | 
         
             
                        form.addEventListener('submit', async (e) => {
         
     | 
| 899 | 
         
             
                            e.preventDefault();
         
     | 
| 900 | 
         | 
| 901 | 
         
            -
                            // MODIFICATION: Validation c么t茅 client
         
     | 
| 902 | 
         
             
                            const sujetValue = sujetTextarea.value.trim();
         
     | 
| 903 | 
         
             
                            if (!sujetValue) {
         
     | 
| 904 | 
         
             
                                output.innerHTML = `
         
     | 
| 
         @@ -909,53 +974,56 @@ function closeModal(modalElement) { 
     | 
|
| 909 | 
         
             
                                        <p>Veuillez entrer un sujet avant de g茅n茅rer.</p>
         
     | 
| 910 | 
         
             
                                    </div>
         
     | 
| 911 | 
         
             
                                </div>`;
         
     | 
| 912 | 
         
            -
                                 sujetTextarea.focus(); 
     | 
| 913 | 
         
            -
                                 sujetTextarea.classList.add('border-red-500'); 
     | 
| 914 | 
         
            -
                                 setTimeout(() => sujetTextarea.classList.remove('border-red-500'), 3000); 
     | 
| 915 | 
         
            -
                                return; 
     | 
| 916 | 
         
             
                            }
         
     | 
| 917 | 
         | 
| 918 | 
         
            -
             
     | 
| 919 | 
         
             
                            output.innerHTML = `
         
     | 
| 920 | 
         
             
                            <div class="flex flex-col items-center justify-center py-8">
         
     | 
| 921 | 
         
             
                                <div class="loader mb-4">
         
     | 
| 922 | 
         
            -
                                    <div></div>
         
     | 
| 923 | 
         
            -
                                    <div></div>
         
     | 
| 924 | 
         
            -
                                    <div></div>
         
     | 
| 925 | 
         
            -
                                    <div></div>
         
     | 
| 926 | 
         
             
                                </div>
         
     | 
| 927 | 
         
             
                                <p class="text-sm font-medium text-gray-600">G茅n茅ration en cours...</p>
         
     | 
| 
         | 
|
| 928 | 
         
             
                            </div>`;
         
     | 
| 929 | 
         | 
| 930 | 
         
             
                            const formData = new FormData(form);
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 931 | 
         
             
                            try {
         
     | 
| 932 | 
         
             
                                const response = await fetch('/api/francais', {
         
     | 
| 933 | 
         
             
                                    method: 'POST',
         
     | 
| 934 | 
         
             
                                    body: formData
         
     | 
| 935 | 
         
             
                                });
         
     | 
| 936 | 
         | 
| 937 | 
         
            -
                                const result = await response.json(); 
     | 
| 938 | 
         | 
| 939 | 
         
             
                                if (!response.ok) {
         
     | 
| 940 | 
         
            -
                                     // Afficher l'erreur renvoy茅e par le serveur si disponible
         
     | 
| 941 | 
         
             
                                     throw new Error(result.output || `Erreur HTTP ${response.status}`);
         
     | 
| 942 | 
         
             
                                }
         
     | 
| 943 | 
         | 
| 944 | 
         
            -
             
     | 
| 945 | 
         
             
                                output.style.opacity = '0';
         
     | 
| 946 | 
         
            -
                                 
     | 
| 947 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 948 | 
         
             
                                    output.style.opacity = '1';
         
     | 
| 949 | 
         
            -
             
     | 
| 950 | 
         
            -
             
     | 
| 951 | 
         
            -
             
     | 
| 952 | 
         
            -
             
     | 
| 953 | 
         
            -
             
     | 
| 954 | 
         
            -
             
     | 
| 955 | 
         
            -
             
     | 
| 956 | 
         
            -
             
     | 
| 957 | 
         
            -
             
     | 
| 958 | 
         
            -
                                } 
     | 
| 
         | 
|
| 959 | 
         
             
                            } catch (error) {
         
     | 
| 960 | 
         
             
                                 console.error("Erreur lors de la soumission:", error);
         
     | 
| 961 | 
         
             
                                 output.innerHTML = `
         
     | 
| 
         @@ -973,13 +1041,12 @@ function closeModal(modalElement) { 
     | 
|
| 973 | 
         
             
                    async function submitEtudeTexteForm() {
         
     | 
| 974 | 
         
             
                        const form = document.getElementById('etude-texte-form');
         
     | 
| 975 | 
         
             
                        const output = document.getElementById('etude-texte-output');
         
     | 
| 976 | 
         
            -
                        const fileInput = document.getElementById('image-upload'); 
     | 
| 977 | 
         | 
| 978 | 
         
             
                        form.addEventListener('submit', async (e) => {
         
     | 
| 979 | 
         
             
                            e.preventDefault();
         
     | 
| 980 | 
         | 
| 981 | 
         
            -
             
     | 
| 982 | 
         
            -
                             if (fileInput.files.length === 0) {
         
     | 
| 983 | 
         
             
                                 output.innerHTML = `
         
     | 
| 984 | 
         
             
                                <div class="alert-message alert-warning">
         
     | 
| 985 | 
         
             
                                     <i class="fas fa-exclamation-triangle"></i>
         
     | 
| 
         @@ -988,68 +1055,52 @@ function closeModal(modalElement) { 
     | 
|
| 988 | 
         
             
                                         <p>Veuillez ajouter au moins une image pour l'analyse.</p>
         
     | 
| 989 | 
         
             
                                     </div>
         
     | 
| 990 | 
         
             
                                 </div>`;
         
     | 
| 991 | 
         
            -
                                return; 
     | 
| 992 | 
         
             
                            }
         
     | 
| 993 | 
         | 
| 994 | 
         
             
                            output.innerHTML = `
         
     | 
| 995 | 
         
             
                            <div class="flex flex-col items-center justify-center py-8">
         
     | 
| 996 | 
         
             
                                <div class="loader mb-4">
         
     | 
| 997 | 
         
            -
                                    <div></div>
         
     | 
| 998 | 
         
            -
                                    <div></div>
         
     | 
| 999 | 
         
            -
                                    <div></div>
         
     | 
| 1000 | 
         
            -
                                    <div></div>
         
     | 
| 1001 | 
         
             
                                </div>
         
     | 
| 1002 | 
         
             
                                <p class="text-sm font-medium text-gray-600">Analyse en cours...</p>
         
     | 
| 1003 | 
         
             
                                <p class="text-xs text-gray-400 mt-2">Cela peut prendre un moment</p>
         
     | 
| 1004 | 
         
             
                            </div>`;
         
     | 
| 1005 | 
         | 
| 1006 | 
         
             
                            const formData = new FormData();
         
     | 
| 1007 | 
         
            -
                             // Ajouter uniquement les fichiers valides de notre Map `uploadedFiles`
         
     | 
| 1008 | 
         
            -
                             if (uploadedFiles.size === 0) {
         
     | 
| 1009 | 
         
            -
                                  // Double v茅rification (normalement impossible si fileInput.files > 0)
         
     | 
| 1010 | 
         
            -
                                  output.innerHTML = `
         
     | 
| 1011 | 
         
            -
                                    <div class="alert-message alert-warning">
         
     | 
| 1012 | 
         
            -
                                        <i class="fas fa-exclamation-triangle"></i>
         
     | 
| 1013 | 
         
            -
                                        <div>
         
     | 
| 1014 | 
         
            -
                                            <p>Aucune image valide</p>
         
     | 
| 1015 | 
         
            -
                                            <p>Veuillez v茅rifier les images s茅lectionn茅es.</p>
         
     | 
| 1016 | 
         
            -
                                        </div>
         
     | 
| 1017 | 
         
            -
                                    </div>`;
         
     | 
| 1018 | 
         
            -
                                    return;
         
     | 
| 1019 | 
         
            -
                             }
         
     | 
| 1020 | 
         
             
                             uploadedFiles.forEach((file) => {
         
     | 
| 1021 | 
         
             
                                 formData.append('images', file, file.name);
         
     | 
| 1022 | 
         
             
                             });
         
     | 
| 1023 | 
         | 
| 1024 | 
         
            -
             
     | 
| 1025 | 
         
             
                            try {
         
     | 
| 1026 | 
         
             
                                const response = await fetch('/api/etude-texte', {
         
     | 
| 1027 | 
         
             
                                    method: 'POST',
         
     | 
| 1028 | 
         
            -
                                    body: formData 
     | 
| 1029 | 
         
             
                                });
         
     | 
| 1030 | 
         | 
| 1031 | 
         
            -
                                const result = await response.json(); 
     | 
| 1032 | 
         | 
| 1033 | 
         
             
                                if (!response.ok) {
         
     | 
| 1034 | 
         
            -
                                    // Afficher l'erreur renvoy茅e par le serveur si disponible
         
     | 
| 1035 | 
         
             
                                    throw new Error(result.output || `Erreur HTTP ${response.status}`);
         
     | 
| 1036 | 
         
             
                                }
         
     | 
| 1037 | 
         | 
| 1038 | 
         
            -
             
     | 
| 1039 | 
         
             
                                output.style.opacity = '0';
         
     | 
| 1040 | 
         
            -
                                 
     | 
| 1041 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1042 | 
         
             
                                    output.style.opacity = '1';
         
     | 
| 1043 | 
         
            -
             
     | 
| 1044 | 
         
            -
             
     | 
| 1045 | 
         
            -
             
     | 
| 1046 | 
         
            -
             
     | 
| 1047 | 
         
            -
             
     | 
| 1048 | 
         
            -
             
     | 
| 1049 | 
         
            -
                                      
     | 
| 1050 | 
         
            -
             
     | 
| 1051 | 
         
            -
             
     | 
| 1052 | 
         
            -
                                }, 100); // L茅ger d茅lai pour l'animation d'opacit茅
         
     | 
| 1053 | 
         
             
                            } catch (error) {
         
     | 
| 1054 | 
         
             
                                 console.error("Erreur lors de l'analyse:", error);
         
     | 
| 1055 | 
         
             
                                 output.innerHTML = `
         
     | 
| 
         @@ -1067,29 +1118,27 @@ function closeModal(modalElement) { 
     | 
|
| 1067 | 
         
             
                    // Animation des cartes au d茅filement
         
     | 
| 1068 | 
         
             
                    function animateOnScroll() {
         
     | 
| 1069 | 
         
             
                        const cards = document.querySelectorAll('.card-hover');
         
     | 
| 1070 | 
         
            -
                        // Si IntersectionObserver n'est pas support茅, on affiche directement
         
     | 
| 1071 | 
         
             
                        if (!('IntersectionObserver' in window)) {
         
     | 
| 1072 | 
         
             
                             cards.forEach(card => card.style.opacity = '1');
         
     | 
| 1073 | 
         
             
                             return;
         
     | 
| 1074 | 
         
             
                        }
         
     | 
| 1075 | 
         
            -
             
     | 
| 1076 | 
         
             
                        const observer = new IntersectionObserver((entries) => {
         
     | 
| 1077 | 
         
            -
                            entries.forEach((entry) => { 
     | 
| 1078 | 
         
             
                                if (entry.isIntersecting) {
         
     | 
| 1079 | 
         
            -
                                     
     | 
| 1080 | 
         
            -
                                     
     | 
| 1081 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1082 | 
         
             
                                }
         
     | 
| 1083 | 
         
             
                            });
         
     | 
| 1084 | 
         
            -
                        }, {
         
     | 
| 1085 | 
         
            -
                            threshold: 0.1 // D茅clenche quand 10% est visible
         
     | 
| 1086 | 
         
            -
                        });
         
     | 
| 1087 | 
         | 
| 1088 | 
         
             
                        cards.forEach(card => {
         
     | 
| 1089 | 
         
             
                            card.style.opacity = '0';
         
     | 
| 1090 | 
         
             
                            card.style.transform = 'translateY(30px)';
         
     | 
| 1091 | 
         
            -
                            //  
     | 
| 1092 | 
         
            -
                            // card.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out';
         
     | 
| 1093 | 
         
             
                            observer.observe(card);
         
     | 
| 1094 | 
         
             
                        });
         
     | 
| 1095 | 
         
             
                    }
         
     | 
| 
         @@ -1098,11 +1147,9 @@ function closeModal(modalElement) { 
     | 
|
| 1098 | 
         
             
                    function enhanceTextareaFocus() {
         
     | 
| 1099 | 
         
             
                        const textarea = document.getElementById('sujet-francais');
         
     | 
| 1100 | 
         
             
                        const counter = document.getElementById('character-count');
         
     | 
| 1101 | 
         
            -
             
     | 
| 1102 | 
         
             
                        textarea.addEventListener('input', () => {
         
     | 
| 1103 | 
         
             
                            const length = textarea.value.length;
         
     | 
| 1104 | 
         
             
                            counter.textContent = `${length} caract猫re${length !== 1 ? 's' : ''}`;
         
     | 
| 1105 | 
         
            -
                             // Enl猫ve la bordure d'erreur si l'utilisateur commence 脿 taper
         
     | 
| 1106 | 
         
             
                             textarea.classList.remove('border-red-500');
         
     | 
| 1107 | 
         
             
                        });
         
     | 
| 1108 | 
         
             
                    }
         
     | 
| 
         @@ -1112,43 +1159,33 @@ function closeModal(modalElement) { 
     | 
|
| 1112 | 
         
             
                         const radioGroups = document.querySelectorAll('input[type="radio"] + span');
         
     | 
| 1113 | 
         
             
                         radioGroups.forEach(label => {
         
     | 
| 1114 | 
         
             
                            const input = label.previousElementSibling;
         
     | 
| 1115 | 
         
            -
                            if (input.disabled) return; 
     | 
| 1116 | 
         | 
| 1117 | 
         
             
                            label.addEventListener('mouseenter', () => {
         
     | 
| 1118 | 
         
             
                                if (!input.checked) {
         
     | 
| 1119 | 
         
            -
             
     | 
| 
         | 
|
| 1120 | 
         
             
                                }
         
     | 
| 1121 | 
         
             
                            });
         
     | 
| 1122 | 
         
            -
             
     | 
| 1123 | 
         
             
                            label.addEventListener('mouseleave', () => {
         
     | 
| 1124 | 
         
            -
                                // Retirer les styles de survol seulement si non coch茅
         
     | 
| 1125 | 
         
             
                                 if (!input.checked) {
         
     | 
| 1126 | 
         
            -
             
     | 
| 1127 | 
         
             
                                 }
         
     | 
| 1128 | 
         
             
                            });
         
     | 
| 1129 | 
         
            -
             
     | 
| 1130 | 
         
            -
                             // Assurer que les styles sont retir茅s si un autre bouton est coch茅
         
     | 
| 1131 | 
         
             
                             input.addEventListener('change', () => {
         
     | 
| 1132 | 
         
            -
                                 // Retrouver tous les labels du m锚me groupe
         
     | 
| 1133 | 
         
             
                                 const groupName = input.name;
         
     | 
| 1134 | 
         
             
                                 document.querySelectorAll(`input[name="${groupName}"] + span`).forEach(otherLabel => {
         
     | 
| 1135 | 
         
             
                                     if (otherLabel !== label) {
         
     | 
| 1136 | 
         
            -
                                         otherLabel.classList.remove('border-blue-400', 'shadow-md', '-translate-y-0.5');
         
     | 
| 1137 | 
         
            -
                                         // R茅tablir la bordure par d茅faut si besoin
         
     | 
| 1138 | 
         
            -
                                         if (!otherLabel.previousElementSibling.checked) {
         
     | 
| 1139 | 
         
            -
                                             otherLabel.classList.remove('border-primary'); // Si jamais elle 茅tait l脿
         
     | 
| 1140 | 
         
            -
                                         }
         
     | 
| 1141 | 
         
             
                                     } else {
         
     | 
| 1142 | 
         
            -
             
     | 
| 1143 | 
         
            -
                                        // et retirer les styles de hover qui pourraient rester
         
     | 
| 1144 | 
         
            -
                                         label.classList.remove('shadow-md', '-translate-y-0.5');
         
     | 
| 1145 | 
         
             
                                     }
         
     | 
| 1146 | 
         
             
                                 });
         
     | 
| 1147 | 
         
             
                             });
         
     | 
| 1148 | 
         
             
                        });
         
     | 
| 1149 | 
         
             
                    }
         
     | 
| 1150 | 
         | 
| 1151 | 
         
            -
                    // Initialisation 
     | 
| 1152 | 
         
             
                    document.addEventListener('DOMContentLoaded', () => {
         
     | 
| 1153 | 
         
             
                        initializeFileUpload();
         
     | 
| 1154 | 
         
             
                        submitFrancaisForm();
         
     | 
| 
         @@ -1156,76 +1193,38 @@ function closeModal(modalElement) { 
     | 
|
| 1156 | 
         
             
                        animateOnScroll();
         
     | 
| 1157 | 
         
             
                        enhanceTextareaFocus();
         
     | 
| 1158 | 
         
             
                        enhanceRadioButtons();
         
     | 
| 1159 | 
         
            -
                        afficherSauvegardes(); 
     | 
| 1160 | 
         | 
| 1161 | 
         
            -
                        //  
     | 
| 1162 | 
         
             
                        window.MathJax = {
         
     | 
| 1163 | 
         
            -
                             tex: {
         
     | 
| 1164 | 
         
            -
             
     | 
| 1165 | 
         
            -
             
     | 
| 1166 | 
         
            -
                             },
         
     | 
| 1167 | 
         
            -
                             svg: {
         
     | 
| 1168 | 
         
            -
                                 fontCache: 'global'
         
     | 
| 1169 | 
         
            -
                             },
         
     | 
| 1170 | 
         
            -
                             options: {
         
     | 
| 1171 | 
         
            -
                                 skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
         
     | 
| 1172 | 
         
            -
                                 ignoreHtmlClass: 'tex2jax_ignore',
         
     | 
| 1173 | 
         
            -
                                 processHtmlClass: 'tex2jax_process'
         
     | 
| 1174 | 
         
            -
                             }
         
     | 
| 1175 | 
         
             
                        };
         
     | 
| 1176 | 
         | 
| 1177 | 
         
            -
             
     | 
| 1178 | 
         
            -
                        // Message de bienvenue (optionnel)
         
     | 
| 1179 | 
         
             
                        const showWelcome = sessionStorage.getItem('welcomeShown') !== 'true';
         
     | 
| 1180 | 
         
             
                        if (showWelcome) {
         
     | 
| 1181 | 
         
             
                             const welcomeMessageContainer = document.createElement('div');
         
     | 
| 1182 | 
         
             
                             welcomeMessageContainer.innerHTML = `
         
     | 
| 1183 | 
         
             
                                <div class="fixed bottom-6 right-6 bg-white rounded-xl shadow-lg p-5 transform transition-all duration-500 opacity-0 translate-y-4 max-w-xs z-[100]">
         
     | 
| 1184 | 
         
             
                                    <div class="flex items-start space-x-4">
         
     | 
| 1185 | 
         
            -
                                        <div class="bg-gradient-to-r from-blue-500 to-blue-700 rounded-full p-3 mt-1 flex-shrink-0">
         
     | 
| 1186 | 
         
            -
             
     | 
| 1187 | 
         
            -
                                        </div>
         
     | 
| 1188 | 
         
            -
                                        <div>
         
     | 
| 1189 | 
         
            -
                                            <p class="text-sm font-semibold text-gray-800">Bienvenue sur Mariam AI !</p>
         
     | 
| 1190 | 
         
            -
                                            <p class="text-xs text-gray-500 mt-1">Votre assistant est pr锚t. Posez un sujet ou analysez un texte.</p>
         
     | 
| 1191 | 
         
            -
                                        </div>
         
     | 
| 1192 | 
         
             
                                    </div>
         
     | 
| 1193 | 
         
            -
                                    <button class="absolute top-2 right-2 text-gray-400 hover:text-gray-600 focus:outline-none close-welcome p-1">
         
     | 
| 1194 | 
         
            -
             
     | 
| 1195 | 
         
            -
                                    </button>
         
     | 
| 1196 | 
         
            -
                                </div>
         
     | 
| 1197 | 
         
            -
                            `;
         
     | 
| 1198 | 
         
             
                             document.body.appendChild(welcomeMessageContainer);
         
     | 
| 1199 | 
         
             
                             const welcomeMessage = welcomeMessageContainer.firstElementChild;
         
     | 
| 1200 | 
         
            -
             
     | 
| 1201 | 
         
            -
                             
     | 
| 1202 | 
         
            -
             
     | 
| 1203 | 
         
            -
                              
     | 
| 1204 | 
         
            -
             
     | 
| 1205 | 
         
            -
                            const closeWelcomeButton = welcomeMessage.querySelector('.close-welcome');
         
     | 
| 1206 | 
         
            -
                             closeWelcomeButton.addEventListener('click', () => {
         
     | 
| 1207 | 
         
            -
                                closeWelcomeMessage(welcomeMessage);
         
     | 
| 1208 | 
         
            -
                             });
         
     | 
| 1209 | 
         
            -
             
     | 
| 1210 | 
         
            -
                            // Fermer automatiquement apr猫s un certain temps
         
     | 
| 1211 | 
         
            -
                             setTimeout(() => {
         
     | 
| 1212 | 
         
            -
                                if (document.body.contains(welcomeMessage)) {
         
     | 
| 1213 | 
         
            -
                                     closeWelcomeMessage(welcomeMessage);
         
     | 
| 1214 | 
         
            -
                                }
         
     | 
| 1215 | 
         
            -
                            }, 7000); // 7 secondes
         
     | 
| 1216 | 
         
            -
             
     | 
| 1217 | 
         
            -
                             sessionStorage.setItem('welcomeShown', 'true'); // Marquer comme vu pour cette session
         
     | 
| 1218 | 
         
             
                         }
         
     | 
| 1219 | 
         
            -
             
     | 
| 1220 | 
         
             
                         function closeWelcomeMessage(element) {
         
     | 
| 1221 | 
         
             
                             element.classList.add('opacity-0', 'translate-y-4');
         
     | 
| 1222 | 
         
            -
                             setTimeout(() => {
         
     | 
| 1223 | 
         
            -
                                  if (element.parentElement) {
         
     | 
| 1224 | 
         
            -
                                     element.parentElement.remove();
         
     | 
| 1225 | 
         
            -
                                  }
         
     | 
| 1226 | 
         
            -
                             }, 500); // Attend la fin de la transition
         
     | 
| 1227 | 
         
             
                         }
         
     | 
| 1228 | 
         
            -
             
     | 
| 1229 | 
         
             
                    });
         
     | 
| 1230 | 
         
             
                </script>
         
     | 
| 1231 | 
         
             
            </body>
         
     | 
| 
         | 
|
| 83 | 
         
             
                    /* Styles pour les messages d'erreur/avertissement */
         
     | 
| 84 | 
         
             
                    .alert-message {
         
     | 
| 85 | 
         
             
                        display: flex;
         
     | 
| 86 | 
         
            +
                        align-items: flex-start; /* Align items start for better text wrapping */
         
     | 
| 87 | 
         
            +
                        /* space-x-3 equivalent using margin on icon */
         
     | 
| 88 | 
         
             
                        padding: 1rem; /* p-4 */
         
     | 
| 89 | 
         
             
                        border-radius: 0.5rem; /* rounded-lg */
         
     | 
| 90 | 
         
            +
                        border-width: 1px;
         
     | 
| 91 | 
         
            +
                        border-style: solid;
         
     | 
| 92 | 
         
             
                    }
         
     | 
| 93 | 
         
             
                    .alert-message i {
         
     | 
| 94 | 
         
             
                         margin-right: 0.75rem; /* space-x-3 equivalent */
         
     | 
| 95 | 
         
             
                         font-size: 1.25rem; /* text-xl */
         
     | 
| 96 | 
         
            +
                         margin-top: 0.125rem; /* slight top margin for better alignment */
         
     | 
| 97 | 
         
             
                    }
         
     | 
| 98 | 
         
             
                    .alert-message div p:first-child {
         
     | 
| 99 | 
         
             
                        font-weight: 500; /* font-medium */
         
     | 
| 
         | 
|
| 101 | 
         
             
                     .alert-message div p:last-child {
         
     | 
| 102 | 
         
             
                        font-size: 0.875rem; /* text-sm */
         
     | 
| 103 | 
         
             
                        margin-top: 0.25rem; /* mt-1 */
         
     | 
| 104 | 
         
            +
                        line-height: 1.4; /* Improved line height for wrap */
         
     | 
| 105 | 
         
             
                    }
         
     | 
| 106 | 
         | 
| 107 | 
         
             
                    .alert-warning {
         
     | 
| 108 | 
         
            +
                         color: #92400e; /* text-amber-700 */
         
     | 
| 109 | 
         
             
                         background-color: #fffbeb; /* bg-amber-50 */
         
     | 
| 110 | 
         
            +
                         border-color: #fde68a /* border-amber-200 */
         
     | 
| 111 | 
         
             
                    }
         
     | 
| 112 | 
         
             
                    .alert-warning i {
         
     | 
| 113 | 
         
             
                        color: var(--warning); /* text-amber-500 */
         
     | 
| 114 | 
         
             
                    }
         
     | 
| 115 | 
         
             
                    .alert-warning div p:last-child {
         
     | 
| 116 | 
         
            +
                         color: #b45309; /* text-amber-600 */
         
     | 
| 117 | 
         
             
                    }
         
     | 
| 118 | 
         | 
| 119 | 
         
             
                    .alert-danger {
         
     | 
| 120 | 
         
            +
                         color: #991b1b; /* text-red-700 */
         
     | 
| 121 | 
         
             
                         background-color: #fef2f2; /* bg-red-50 */
         
     | 
| 122 | 
         
            +
                         border-color: #fecaca; /* border-red-200 */
         
     | 
| 123 | 
         
             
                    }
         
     | 
| 124 | 
         
             
                    .alert-danger i {
         
     | 
| 125 | 
         
             
                         color: var(--danger); /* text-red-500 */
         
     | 
| 126 | 
         
             
                    }
         
     | 
| 127 | 
         
             
                     .alert-danger div p:last-child {
         
     | 
| 128 | 
         
            +
                         color: #b91c1c; /* text-red-600 */
         
     | 
| 129 | 
         
             
                    }
         
     | 
| 130 | 
         | 
| 131 | 
         | 
| 
         | 
|
| 163 | 
         
             
                        margin-top: 10px;
         
     | 
| 164 | 
         
             
                        max-height: 0;
         
     | 
| 165 | 
         
             
                        overflow: hidden;
         
     | 
| 166 | 
         
            +
                        transition: max-height 0.3s ease-out, opacity 0.3s ease-out, margin-top 0.3s ease-out, padding-top 0.3s ease-out; /* Added padding-top */
         
     | 
| 167 | 
         
             
                        opacity: 0;
         
     | 
| 168 | 
         
            +
                        padding-top: 0; /* Start with no padding */
         
     | 
| 169 | 
         
             
                    }
         
     | 
| 170 | 
         | 
| 171 | 
         
             
                    .backup-content-expanded {
         
     | 
| 172 | 
         
             
                        display: block;
         
     | 
| 173 | 
         
            +
                        max-height: 3000px; /* Augment茅 pour les longs contenus */
         
     | 
| 174 | 
         
             
                        opacity: 1;
         
     | 
| 175 | 
         
            +
                        margin-top: 1rem; /* mt-4 */
         
     | 
| 176 | 
         
            +
                        padding-top: 0.75rem; /* pt-3 */
         
     | 
| 177 | 
         
             
                    }
         
     | 
| 178 | 
         | 
| 179 | 
         
            +
             
     | 
| 180 | 
         
             
                    /* Styles for multiple image upload */
         
     | 
| 181 | 
         
             
                    .image-preview {
         
     | 
| 182 | 
         
             
                        display: flex;
         
     | 
| 
         | 
|
| 352 | 
         
             
                            grid-template-columns: repeat(2, minmax(0, 1fr));
         
     | 
| 353 | 
         
             
                        }
         
     | 
| 354 | 
         
             
                    }
         
     | 
| 355 | 
         
            +
             
     | 
| 356 | 
         
            +
                    /* Style pour la checkbox DeepThink */
         
     | 
| 357 | 
         
            +
                    .deepthink-label {
         
     | 
| 358 | 
         
            +
                        display: flex;
         
     | 
| 359 | 
         
            +
                        align-items: center;
         
     | 
| 360 | 
         
            +
                        cursor: pointer;
         
     | 
| 361 | 
         
            +
                        font-size: 0.875rem; /* text-sm */
         
     | 
| 362 | 
         
            +
                        color: var(--secondary);
         
     | 
| 363 | 
         
            +
                    }
         
     | 
| 364 | 
         
            +
                    .deepthink-label input[type="checkbox"] {
         
     | 
| 365 | 
         
            +
                        appearance: none;
         
     | 
| 366 | 
         
            +
                        width: 1.25em;
         
     | 
| 367 | 
         
            +
                        height: 1.25em;
         
     | 
| 368 | 
         
            +
                        border: 2px solid #cbd5e0; /* border-gray-300 */
         
     | 
| 369 | 
         
            +
                        border-radius: 0.375rem; /* rounded-md */
         
     | 
| 370 | 
         
            +
                        margin-right: 0.5em;
         
     | 
| 371 | 
         
            +
                        position: relative;
         
     | 
| 372 | 
         
            +
                        top: 1px;
         
     | 
| 373 | 
         
            +
                        transition: all 0.2s ease-in-out;
         
     | 
| 374 | 
         
            +
                    }
         
     | 
| 375 | 
         
            +
                    .deepthink-label input[type="checkbox"]:checked {
         
     | 
| 376 | 
         
            +
                        background-color: var(--primary);
         
     | 
| 377 | 
         
            +
                        border-color: var(--primary);
         
     | 
| 378 | 
         
            +
                    }
         
     | 
| 379 | 
         
            +
                    .deepthink-label input[type="checkbox"]:checked::after {
         
     | 
| 380 | 
         
            +
                        content: '\f00c'; /* FontAwesome check icon */
         
     | 
| 381 | 
         
            +
                        font-family: 'Font Awesome 6 Free';
         
     | 
| 382 | 
         
            +
                        font-weight: 900;
         
     | 
| 383 | 
         
            +
                        color: white;
         
     | 
| 384 | 
         
            +
                        font-size: 0.8em;
         
     | 
| 385 | 
         
            +
                        position: absolute;
         
     | 
| 386 | 
         
            +
                        top: 50%;
         
     | 
| 387 | 
         
            +
                        left: 50%;
         
     | 
| 388 | 
         
            +
                        transform: translate(-50%, -50%);
         
     | 
| 389 | 
         
            +
                    }
         
     | 
| 390 | 
         
            +
                    .deepthink-label:hover input[type="checkbox"] {
         
     | 
| 391 | 
         
            +
                         border-color: var(--primary-dark);
         
     | 
| 392 | 
         
            +
                    }
         
     | 
| 393 | 
         
            +
                    .deepthink-tooltip {
         
     | 
| 394 | 
         
            +
                        position: relative;
         
     | 
| 395 | 
         
            +
                        display: inline-block;
         
     | 
| 396 | 
         
            +
                        margin-left: 6px;
         
     | 
| 397 | 
         
            +
                    }
         
     | 
| 398 | 
         
            +
                    .deepthink-tooltip .tooltip-text {
         
     | 
| 399 | 
         
            +
                        visibility: hidden;
         
     | 
| 400 | 
         
            +
                        width: 220px;
         
     | 
| 401 | 
         
            +
                        background-color: #2d3748; /* gray-800 */
         
     | 
| 402 | 
         
            +
                        color: #fff;
         
     | 
| 403 | 
         
            +
                        text-align: center;
         
     | 
| 404 | 
         
            +
                        border-radius: 6px;
         
     | 
| 405 | 
         
            +
                        padding: 6px 10px;
         
     | 
| 406 | 
         
            +
                        position: absolute;
         
     | 
| 407 | 
         
            +
                        z-index: 10;
         
     | 
| 408 | 
         
            +
                        bottom: 135%;
         
     | 
| 409 | 
         
            +
                        left: 50%;
         
     | 
| 410 | 
         
            +
                        margin-left: -110px;
         
     | 
| 411 | 
         
            +
                        opacity: 0;
         
     | 
| 412 | 
         
            +
                        transition: opacity 0.3s;
         
     | 
| 413 | 
         
            +
                        font-size: 0.75rem; /* text-xs */
         
     | 
| 414 | 
         
            +
                        line-height: 1.4;
         
     | 
| 415 | 
         
            +
                    }
         
     | 
| 416 | 
         
            +
                    .deepthink-tooltip .tooltip-text::after {
         
     | 
| 417 | 
         
            +
                        content: "";
         
     | 
| 418 | 
         
            +
                        position: absolute;
         
     | 
| 419 | 
         
            +
                        top: 100%;
         
     | 
| 420 | 
         
            +
                        left: 50%;
         
     | 
| 421 | 
         
            +
                        margin-left: -5px;
         
     | 
| 422 | 
         
            +
                        border-width: 5px;
         
     | 
| 423 | 
         
            +
                        border-style: solid;
         
     | 
| 424 | 
         
            +
                        border-color: #2d3748 transparent transparent transparent;
         
     | 
| 425 | 
         
            +
                    }
         
     | 
| 426 | 
         
            +
                    .deepthink-tooltip:hover .tooltip-text {
         
     | 
| 427 | 
         
            +
                        visibility: visible;
         
     | 
| 428 | 
         
            +
                        opacity: 1;
         
     | 
| 429 | 
         
            +
                    }
         
     | 
| 430 | 
         
            +
             
     | 
| 431 | 
         
             
                </style>
         
     | 
| 432 | 
         
             
            </head>
         
     | 
| 433 | 
         | 
| 
         | 
|
| 465 | 
         
             
                                        <div class="focus-ring">
         
     | 
| 466 | 
         
             
                                            <textarea id="sujet-francais" name="sujet" rows="4"
         
     | 
| 467 | 
         
             
                                                class="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-blue-500 focus:outline-none transition-all duration-200 resize-none"
         
     | 
| 468 | 
         
            +
                                                placeholder="Entrez votre sujet ici..." required></textarea>
         
     | 
| 469 | 
         
             
                                        </div>
         
     | 
| 470 | 
         
             
                                        <div class="text-xs text-gray-400 text-right" id="character-count">0 caract猫res</div>
         
     | 
| 471 | 
         
             
                                    </div>
         
     | 
| 
         | 
|
| 500 | 
         
             
                                                </span>
         
     | 
| 501 | 
         
             
                                            </label>
         
     | 
| 502 | 
         
             
                                            <label class="relative">
         
     | 
| 
         | 
|
| 503 | 
         
             
                                                <input type="radio" name="choix" value="dissertation"
         
     | 
| 504 | 
         
             
                                                    class="custom-radio absolute opacity-0 w-full h-full cursor-pointer">
         
     | 
| 505 | 
         
             
                                                <span class="flex items-center justify-center p-3 border-2 border-gray-200 rounded-xl text-sm font-medium transition-all duration-200 hover:border-blue-400">
         
     | 
| 506 | 
         
             
                                                    Dissertation
         
     | 
| 
         | 
|
| 507 | 
         
             
                                                </span>
         
     | 
| 508 | 
         
             
                                            </label>
         
     | 
| 509 | 
         
             
                                        </div>
         
     | 
| 
         | 
|
| 533 | 
         
             
                                        </div>
         
     | 
| 534 | 
         
             
                                    </div>
         
     | 
| 535 | 
         | 
| 536 | 
         
            +
                                    <!-- MODIFICATION: Ajout de la checkbox DeepThink -->
         
     | 
| 537 | 
         
            +
                                    <div class="flex items-center justify-start pt-2">
         
     | 
| 538 | 
         
            +
                                       <label for="deepthink-checkbox" class="deepthink-label">
         
     | 
| 539 | 
         
            +
                                           <input type="checkbox" id="deepthink-checkbox" name="use_deepthink_visual"> <!-- Name is different to avoid direct form submission -->
         
     | 
| 540 | 
         
            +
                                            Utiliser DeepThink
         
     | 
| 541 | 
         
            +
                                           <div class="deepthink-tooltip">
         
     | 
| 542 | 
         
            +
                                               <i class="fas fa-info-circle text-gray-400"></i>
         
     | 
| 543 | 
         
            +
                                               <span class="tooltip-text">Utilise un mod猫le plus avanc茅 (Gemini Pro) pour une meilleure qualit茅, mais peut 锚tre plus lent et co没teux.</span>
         
     | 
| 544 | 
         
            +
                                           </div>
         
     | 
| 545 | 
         
            +
                                       </label>
         
     | 
| 546 | 
         
            +
                                    </div>
         
     | 
| 547 | 
         
            +
                                    <!-- Fin de la modification -->
         
     | 
| 548 | 
         
            +
             
     | 
| 549 | 
         
            +
             
     | 
| 550 | 
         
             
                                    <button type="submit"
         
     | 
| 551 | 
         
             
                                        class="w-full bg-gradient-to-r from-blue-600 to-blue-800 text-white px-6 py-4 rounded-xl font-medium hover:from-blue-700 hover:to-blue-900 transition-all duration-300 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg">
         
     | 
| 552 | 
         
             
                                        <div class="flex items-center justify-center space-x-3">
         
     | 
| 
         | 
|
| 555 | 
         
             
                                        </div>
         
     | 
| 556 | 
         
             
                                    </button>
         
     | 
| 557 | 
         
             
                                </form>
         
     | 
| 558 | 
         
            +
                                <div id="francais-output" class="mt-8 p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[100px]">
         
     | 
| 559 | 
         
             
                                    <!-- Le contenu g茅n茅r茅 sera ins茅r茅 ici -->
         
     | 
| 560 | 
         
             
                                </div>
         
     | 
| 561 | 
         
             
                            </div>
         
     | 
| 
         | 
|
| 577 | 
         
             
                                        </label>
         
     | 
| 578 | 
         
             
                                        <div class="border-3 border-dashed border-gray-300 rounded-xl p-8 text-center cursor-pointer hover:border-blue-400 transition-all duration-200 group"
         
     | 
| 579 | 
         
             
                                             id="drop-zone">
         
     | 
| 580 | 
         
            +
                                            <input type="file" id="image-upload" name="images" accept="image/*" class="hidden" multiple>
         
     | 
| 581 | 
         
             
                                            <div class="space-y-4">
         
     | 
| 582 | 
         
             
                                                <div class="bg-blue-50 rounded-full w-16 h-16 flex items-center justify-center mx-auto transform transition-transform group-hover:scale-110 group-hover:rotate-6">
         
     | 
| 583 | 
         
             
                                                    <i class="fas fa-cloud-upload-alt text-3xl text-blue-500"></i>
         
     | 
| 
         | 
|
| 587 | 
         
             
                                                <p class="text-xs text-gray-400">PNG, JPG, WEBP jusqu'脿 10MB</p>
         
     | 
| 588 | 
         
             
                                            </div>
         
     | 
| 589 | 
         
             
                                        </div>
         
     | 
| 590 | 
         
            +
                                        <div id="image-preview" class="image-preview"></div>
         
     | 
| 591 | 
         
             
                                    </div>
         
     | 
| 592 | 
         | 
| 593 | 
         
             
                                    <button type="submit"
         
     | 
| 
         | 
|
| 598 | 
         
             
                                        </div>
         
     | 
| 599 | 
         
             
                                    </button>
         
     | 
| 600 | 
         
             
                                </form>
         
     | 
| 601 | 
         
            +
                                 <div id="etude-texte-output" class="mt-8 p-6 bg-blue-50 rounded-xl prose max-w-none shadow-inner min-h-[100px]">
         
     | 
| 602 | 
         
             
                                    <!-- Le contenu analys茅 sera ins茅r茅 ici -->
         
     | 
| 603 | 
         
             
                                </div>
         
     | 
| 604 | 
         
             
                            </div>
         
     | 
| 
         | 
|
| 734 | 
         
             
                             previewElement.style.opacity = '0';
         
     | 
| 735 | 
         
             
                             previewElement.style.transform = 'scale(0.9)';
         
     | 
| 736 | 
         
             
                             setTimeout(() => {
         
     | 
| 737 | 
         
            +
                                  if (imagePreview.contains(previewElement)) {
         
     | 
| 738 | 
         
            +
                                       imagePreview.removeChild(previewElement);
         
     | 
| 739 | 
         
            +
                                  }
         
     | 
| 740 | 
         
             
                             }, 300);
         
     | 
| 741 | 
         
             
                        }
         
     | 
| 742 | 
         
             
                    }
         
     | 
| 
         | 
|
| 744 | 
         
             
                    function sauvegarderReponse(titre, contenu) {
         
     | 
| 745 | 
         
             
                        const sauvegardes = JSON.parse(localStorage.getItem('mariam_ai_sauvegardes') || '[]');
         
     | 
| 746 | 
         
             
                        const dateSauvegarde = new Date().toISOString();
         
     | 
| 
         | 
|
| 747 | 
         
             
                        const MAX_SAUVEGARDES = 20;
         
     | 
| 748 | 
         
             
                        if (sauvegardes.length >= MAX_SAUVEGARDES) {
         
     | 
| 749 | 
         
            +
                             sauvegardes.shift();
         
     | 
| 750 | 
         
             
                        }
         
     | 
| 751 | 
         
             
                        sauvegardes.push({
         
     | 
| 752 | 
         
            +
                            titre: titre || "Sauvegarde sans titre",
         
     | 
| 753 | 
         
             
                            contenu,
         
     | 
| 754 | 
         
             
                            date: dateSauvegarde
         
     | 
| 755 | 
         
             
                        });
         
     | 
| 
         | 
|
| 757 | 
         
             
                             localStorage.setItem('mariam_ai_sauvegardes', JSON.stringify(sauvegardes));
         
     | 
| 758 | 
         
             
                        } catch (e) {
         
     | 
| 759 | 
         
             
                            console.error("Erreur lors de la sauvegarde dans localStorage (peut-锚tre plein):", e);
         
     | 
| 
         | 
|
| 760 | 
         
             
                            displayNotification("Erreur de sauvegarde: Espace de stockage local plein.", "error");
         
     | 
| 761 | 
         
            +
                            return;
         
     | 
| 762 | 
         
             
                        }
         
     | 
| 
         | 
|
| 
         | 
|
| 763 | 
         
             
                        displayNotification("Sauvegard茅 avec succ猫s", "success");
         
     | 
| 764 | 
         
            +
                        afficherSauvegardes();
         
     | 
| 765 | 
         
             
                    }
         
     | 
| 766 | 
         | 
| 767 | 
         
             
                    function displayNotification(message, type = 'success') {
         
     | 
| 768 | 
         
             
                         const notification = document.createElement('div');
         
     | 
| 769 | 
         
            +
                         const bgColor = type === 'success' ? 'bg-green-50 border-green-200 text-green-700' : type === 'error' ? 'bg-red-50 border-red-200 text-red-700' : 'bg-yellow-50 border-yellow-200 text-yellow-700';
         
     | 
| 770 | 
         
            +
                         const iconClass = type === 'success' ? 'fa-check-circle text-green-500' : type === 'error' ? 'fa-exclamation-circle text-red-500' : 'fa-exclamation-triangle text-yellow-500';
         
     | 
| 771 | 
         | 
| 772 | 
         
            +
             
     | 
| 773 | 
         
            +
                         notification.className = `fixed bottom-6 right-6 border ${bgColor} px-4 py-3 rounded-lg shadow-lg z-[100] flex items-center scale-in max-w-sm`; // z-index 茅lev茅, max-width
         
     | 
| 774 | 
         
             
                         notification.innerHTML = `
         
     | 
| 775 | 
         
            +
                            <i class="fas ${iconClass} mr-3 text-lg flex-shrink-0"></i>
         
     | 
| 776 | 
         
             
                            <span class="text-sm font-medium">${message}</span>
         
     | 
| 777 | 
         
             
                        `;
         
     | 
| 778 | 
         
             
                        document.body.appendChild(notification);
         
     | 
| 
         | 
|
| 785 | 
         
             
                                     document.body.removeChild(notification);
         
     | 
| 786 | 
         
             
                                }
         
     | 
| 787 | 
         
             
                            }, 300);
         
     | 
| 788 | 
         
            +
                        }, type === 'error' ? 6000 : 3000); // Longer display for errors
         
     | 
| 789 | 
         
             
                    }
         
     | 
| 790 | 
         | 
| 791 | 
         | 
| 
         | 
|
| 797 | 
         
             
                    }
         
     | 
| 798 | 
         | 
| 799 | 
         | 
| 800 | 
         
            +
                    function afficherSauvegardes() {
         
     | 
| 801 | 
         
            +
                        const sauvegardes = JSON.parse(localStorage.getItem('mariam_ai_sauvegardes') || '[]');
         
     | 
| 802 | 
         
            +
                        sauvegardes.sort((a, b) => new Date(b.date) - new Date(a.date));
         
     | 
| 803 | 
         
            +
                        const backupsList = document.getElementById('backups-list');
         
     | 
| 804 | 
         
            +
                        backupsList.innerHTML = '';
         
     | 
| 805 | 
         
            +
             
     | 
| 806 | 
         
            +
                        if (sauvegardes.length === 0) {
         
     | 
| 807 | 
         
            +
                            backupsList.innerHTML = `
         
     | 
| 808 | 
         
            +
                                <div class="bg-blue-50 rounded-lg p-8 text-center">
         
     | 
| 809 | 
         
            +
                                    <div class="bg-white rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4 shadow-sm">
         
     | 
| 810 | 
         
            +
                                        <i class="fas fa-folder-open text-blue-300 text-2xl"></i>
         
     | 
| 811 | 
         
            +
                                    </div>
         
     | 
| 812 | 
         
            +
                                    <p class="text-gray-600">Aucune sauvegarde pour le moment.</p>
         
     | 
| 813 | 
         
            +
                                    <p class="text-sm text-gray-500 mt-2">Vos r茅ponses g茅n茅r茅es appara卯tront ici.</p>
         
     | 
| 814 | 
         
            +
                                </div>
         
     | 
| 815 | 
         
            +
                            `;
         
     | 
| 816 | 
         
            +
                            return;
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 817 | 
         
             
                        }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 818 | 
         | 
| 819 | 
         
            +
                        sauvegardes.forEach((sauvegarde, index) => {
         
     | 
| 820 | 
         
            +
                            const date = new Date(sauvegarde.date);
         
     | 
| 821 | 
         
            +
                            const formattedDate = date.toLocaleDateString('fr-FR', {
         
     | 
| 822 | 
         
            +
                                day: 'numeric',
         
     | 
| 823 | 
         
            +
                                month: 'short',
         
     | 
| 824 | 
         
            +
                                year: 'numeric',
         
     | 
| 825 | 
         
            +
                                hour: '2-digit',
         
     | 
| 826 | 
         
            +
                                minute: '2-digit'
         
     | 
| 827 | 
         
            +
                            });
         
     | 
| 828 | 
         
            +
                            const displayTitle = sauvegarde.titre.length > 60 ? sauvegarde.titre.substring(0, 57) + '...' : sauvegarde.titre;
         
     | 
| 829 | 
         
            +
             
     | 
| 830 | 
         
            +
                            const sauvegardeDiv = document.createElement('div');
         
     | 
| 831 | 
         
            +
                            sauvegardeDiv.dataset.index = index;
         
     | 
| 832 | 
         
            +
                            sauvegardeDiv.className = 'bg-white rounded-lg shadow-md p-4 relative backup-item hover:bg-blue-50 transition-all duration-200';
         
     | 
| 833 | 
         
            +
                            sauvegardeDiv.innerHTML = `
         
     | 
| 834 | 
         
            +
                                <div class="flex items-start cursor-pointer item-header">
         
     | 
| 835 | 
         
            +
                                    <div class="bg-blue-100 rounded-lg p-2 mr-3 flex-shrink-0">
         
     | 
| 836 | 
         
            +
                                        <i class="fas fa-file-alt text-blue-600"></i>
         
     | 
| 837 | 
         
            +
                                    </div>
         
     | 
| 838 | 
         
            +
                                    <div class="flex-grow overflow-hidden">
         
     | 
| 839 | 
         
            +
                                        <h3 class="text-lg font-semibold text-gray-800 truncate" title="${sauvegarde.titre}">${displayTitle}</h3>
         
     | 
| 840 | 
         
            +
                                        <p class="text-sm text-gray-600 mb-2 flex items-center">
         
     | 
| 841 | 
         
            +
                                            <i class="fas fa-clock text-xs mr-1 text-gray-400"></i>
         
     | 
| 842 | 
         
            +
                                            ${formattedDate}
         
     | 
| 843 | 
         
            +
                                        </p>
         
     | 
| 844 | 
         
            +
                                    </div>
         
     | 
| 845 | 
         
            +
                                    <div class="flex space-x-2 ml-2 flex-shrink-0">
         
     | 
| 846 | 
         
            +
                                        <button class="text-gray-400 hover:text-blue-600 focus:outline-none copy-btn p-1" title="Copier">
         
     | 
| 847 | 
         
            +
                                            <i class="fas fa-copy"></i>
         
     | 
| 848 | 
         
            +
                                        </button>
         
     | 
| 849 | 
         
            +
                                        <button class="text-gray-400 hover:text-red-600 focus:outline-none delete-btn p-1" title="Supprimer">
         
     | 
| 850 | 
         
            +
                                            <i class="fas fa-trash-alt"></i>
         
     | 
| 851 | 
         
            +
                                        </button>
         
     | 
| 852 | 
         
            +
                                    </div>
         
     | 
| 853 | 
         
            +
                                </div>
         
     | 
| 854 | 
         
            +
                                <div class="backup-content mt-4 text-sm text-gray-700 prose max-w-none border-t border-gray-100 pt-3">
         
     | 
| 855 | 
         
            +
                                    <!-- Contenu charg茅 dynamiquement -->
         
     | 
| 856 | 
         
            +
                                </div>
         
     | 
| 857 | 
         
            +
                            `;
         
     | 
| 858 | 
         
            +
                            backupsList.appendChild(sauvegardeDiv);
         
     | 
| 859 | 
         | 
| 860 | 
         
            +
                            const backupContentDiv = sauvegardeDiv.querySelector('.backup-content');
         
     | 
| 861 | 
         
            +
                            const headerDiv = sauvegardeDiv.querySelector('.item-header');
         
     | 
| 
         | 
|
| 862 | 
         | 
| 863 | 
         
            +
                            headerDiv.addEventListener('click', (e) => {
         
     | 
| 864 | 
         
            +
                                const isExpanded = backupContentDiv.classList.contains('backup-content-expanded');
         
     | 
| 865 | 
         
            +
                                document.querySelectorAll('.backup-content-expanded').forEach(content => {
         
     | 
| 866 | 
         
            +
                                    if (content !== backupContentDiv) {
         
     | 
| 867 | 
         
            +
                                        content.classList.remove('backup-content-expanded');
         
     | 
| 868 | 
         
            +
                                        content.innerHTML = '';
         
     | 
| 869 | 
         
            +
                                     }
         
     | 
| 870 | 
         
            +
                                });
         
     | 
| 871 | 
         
            +
                                if (!isExpanded) {
         
     | 
| 872 | 
         
            +
                                    backupContentDiv.innerHTML = marked.parse(sauvegarde.contenu);
         
     | 
| 873 | 
         
            +
                                    backupContentDiv.classList.add('backup-content-expanded');
         
     | 
| 874 | 
         
            +
                                    setTimeout(() => {
         
     | 
| 875 | 
         
            +
                                        MathJax.typesetPromise([backupContentDiv]).catch(function (err) {
         
     | 
| 876 | 
         
            +
                                             console.error('MathJax typesetting error:', err);
         
     | 
| 877 | 
         
            +
                                        });
         
     | 
| 878 | 
         
            +
                                    }, 50);
         
     | 
| 879 | 
         
            +
                                } else {
         
     | 
| 880 | 
         
            +
                                     backupContentDiv.classList.remove('backup-content-expanded');
         
     | 
| 881 | 
         
            +
                                     backupContentDiv.innerHTML = '';
         
     | 
| 882 | 
         
            +
                                }
         
     | 
| 883 | 
         
            +
                            });
         
     | 
| 884 | 
         | 
| 885 | 
         
            +
                            const copyButton = sauvegardeDiv.querySelector('.copy-btn');
         
     | 
| 886 | 
         
            +
                            copyButton.addEventListener('click', (e) => {
         
     | 
| 887 | 
         
            +
                                e.stopPropagation();
         
     | 
| 888 | 
         
            +
                                navigator.clipboard.writeText(sauvegarde.contenu).then(() => {
         
     | 
| 889 | 
         
            +
                                    const icon = copyButton.querySelector('i');
         
     | 
| 890 | 
         
            +
                                    icon.className = 'fas fa-check text-green-500';
         
     | 
| 891 | 
         
            +
                                    setTimeout(() => {
         
     | 
| 892 | 
         
            +
                                        icon.className = 'fas fa-copy';
         
     | 
| 893 | 
         
            +
                                    }, 2000);
         
     | 
| 894 | 
         
            +
                                }).catch(err => {
         
     | 
| 895 | 
         
            +
                                     console.error('Erreur de copie:', err);
         
     | 
| 896 | 
         
            +
                                     displayNotification("Erreur lors de la copie", "error");
         
     | 
| 897 | 
         
            +
                                });
         
     | 
| 898 | 
         
            +
                            });
         
     | 
| 899 | 
         | 
| 900 | 
         
            +
                            const deleteButton = sauvegardeDiv.querySelector('.delete-btn');
         
     | 
| 901 | 
         
            +
                            deleteButton.addEventListener('click', (e) => {
         
     | 
| 902 | 
         
            +
                                e.stopPropagation();
         
     | 
| 903 | 
         
            +
                                const itemIndex = parseInt(sauvegardeDiv.dataset.index, 10);
         
     | 
| 904 | 
         
            +
                                const storedSauvegardes = JSON.parse(localStorage.getItem('mariam_ai_sauvegardes') || '[]');
         
     | 
| 905 | 
         
            +
                                storedSauvegardes.sort((a, b) => new Date(b.date) - new Date(a.date));
         
     | 
| 906 | 
         
            +
                                const itemToDelete = storedSauvegardes[itemIndex];
         
     | 
| 907 | 
         
            +
                                const originalSauvegardes = JSON.parse(localStorage.getItem('mariam_ai_sauvegardes') || '[]');
         
     | 
| 908 | 
         
            +
                                const originalIndex = originalSauvegardes.findIndex(s => s.date === itemToDelete?.date && s.titre === itemToDelete?.titre); // Added safe navigation
         
     | 
| 909 | 
         
            +
             
     | 
| 910 | 
         
            +
                                if (originalIndex === -1) {
         
     | 
| 911 | 
         
            +
                                    console.error("Impossible de trouver l'茅l茅ment 脿 supprimer dans le stockage original.");
         
     | 
| 912 | 
         
            +
                                    displayNotification("Erreur lors de la suppression", "error");
         
     | 
| 913 | 
         
            +
                                    return;
         
     | 
| 914 | 
         
            +
                                }
         
     | 
| 915 | 
         | 
| 916 | 
         
            +
                                const confirmationModal = document.createElement('div');
         
     | 
| 917 | 
         
            +
                                confirmationModal.className = 'fixed inset-0 flex items-center justify-center z-[100] bg-black bg-opacity-30 scale-in';
         
     | 
| 918 | 
         
            +
                                confirmationModal.innerHTML = `
         
     | 
| 919 | 
         
            +
                                    <div class="bg-white rounded-lg p-6 max-w-sm mx-4 shadow-xl">
         
     | 
| 920 | 
         
            +
                                        <div class="flex items-center mb-4">
         
     | 
| 921 | 
         
            +
                                            <div class="bg-red-100 rounded-full p-2 mr-3">
         
     | 
| 922 | 
         
            +
                                                <i class="fas fa-exclamation-triangle text-red-500"></i>
         
     | 
| 923 | 
         
            +
                                            </div>
         
     | 
| 924 | 
         
            +
                                            <h3 class="text-lg font-semibold text-gray-800">Confirmation</h3>
         
     | 
| 925 | 
         
            +
                                        </div>
         
     | 
| 926 | 
         
            +
                                        <p class="text-gray-600 mb-6 text-sm">脢tes-vous s没r de vouloir supprimer cette sauvegarde ?</p>
         
     | 
| 927 | 
         
            +
                                        <div class="flex justify-end space-x-3">
         
     | 
| 928 | 
         
            +
                                            <button class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 cancel-btn text-sm">Annuler</button>
         
     | 
| 929 | 
         
            +
                                            <button class="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 confirm-btn text-sm">Supprimer</button>
         
     | 
| 930 | 
         
            +
                                        </div>
         
     | 
| 931 | 
         
             
                                    </div>
         
     | 
| 932 | 
         
            +
                                `;
         
     | 
| 933 | 
         
            +
                                document.body.appendChild(confirmationModal);
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 934 | 
         | 
| 935 | 
         
            +
                                confirmationModal.querySelector('.cancel-btn').addEventListener('click', () => closeModal(confirmationModal));
         
     | 
| 936 | 
         
            +
                                confirmationModal.querySelector('.confirm-btn').addEventListener('click', () => {
         
     | 
| 937 | 
         
            +
                                    supprimerSauvegarde(originalIndex);
         
     | 
| 938 | 
         
            +
                                    closeModal(confirmationModal);
         
     | 
| 939 | 
         
            +
                                });
         
     | 
| 940 | 
         
            +
                                 confirmationModal.addEventListener('click', (event) => {
         
     | 
| 941 | 
         
            +
                                     if (event.target === confirmationModal) closeModal(confirmationModal);
         
     | 
| 942 | 
         
            +
                                 });
         
     | 
| 943 | 
         
            +
                            });
         
     | 
| 944 | 
         
             
                        });
         
     | 
| 945 | 
         
            +
                    }
         
     | 
| 946 | 
         | 
| 947 | 
         
            +
                    function closeModal(modalElement) {
         
     | 
| 948 | 
         
            +
                         modalElement.style.opacity = '0';
         
     | 
| 949 | 
         
            +
                         modalElement.style.transition = 'opacity 0.3s ease';
         
     | 
| 950 | 
         
            +
                         setTimeout(() => {
         
     | 
| 951 | 
         
            +
                              if (document.body.contains(modalElement)) {
         
     | 
| 952 | 
         
            +
                                 document.body.removeChild(modalElement);
         
     | 
| 953 | 
         
            +
                              }
         
     | 
| 954 | 
         
            +
                         }, 300);
         
     | 
| 955 | 
         
            +
                    }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 956 | 
         | 
| 957 | 
         | 
| 958 | 
         
             
                    async function submitFrancaisForm() {
         
     | 
| 959 | 
         
             
                        const form = document.getElementById('francais-form');
         
     | 
| 960 | 
         
             
                        const output = document.getElementById('francais-output');
         
     | 
| 961 | 
         
            +
                        const sujetTextarea = document.getElementById('sujet-francais');
         
     | 
| 962 | 
         
            +
                        const deepThinkCheckbox = document.getElementById('deepthink-checkbox'); // MODIFICATION: R茅cup茅rer la checkbox
         
     | 
| 963 | 
         | 
| 964 | 
         
             
                        form.addEventListener('submit', async (e) => {
         
     | 
| 965 | 
         
             
                            e.preventDefault();
         
     | 
| 966 | 
         | 
| 
         | 
|
| 967 | 
         
             
                            const sujetValue = sujetTextarea.value.trim();
         
     | 
| 968 | 
         
             
                            if (!sujetValue) {
         
     | 
| 969 | 
         
             
                                output.innerHTML = `
         
     | 
| 
         | 
|
| 974 | 
         
             
                                        <p>Veuillez entrer un sujet avant de g茅n茅rer.</p>
         
     | 
| 975 | 
         
             
                                    </div>
         
     | 
| 976 | 
         
             
                                </div>`;
         
     | 
| 977 | 
         
            +
                                 sujetTextarea.focus();
         
     | 
| 978 | 
         
            +
                                 sujetTextarea.classList.add('border-red-500');
         
     | 
| 979 | 
         
            +
                                 setTimeout(() => sujetTextarea.classList.remove('border-red-500'), 3000);
         
     | 
| 980 | 
         
            +
                                return;
         
     | 
| 981 | 
         
             
                            }
         
     | 
| 982 | 
         | 
| 
         | 
|
| 983 | 
         
             
                            output.innerHTML = `
         
     | 
| 984 | 
         
             
                            <div class="flex flex-col items-center justify-center py-8">
         
     | 
| 985 | 
         
             
                                <div class="loader mb-4">
         
     | 
| 986 | 
         
            +
                                    <div></div><div></div><div></div><div></div>
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 987 | 
         
             
                                </div>
         
     | 
| 988 | 
         
             
                                <p class="text-sm font-medium text-gray-600">G茅n茅ration en cours...</p>
         
     | 
| 989 | 
         
            +
                                 ${deepThinkCheckbox.checked ? '<p class="text-xs text-blue-500 mt-1">Mode DeepThink activ茅</p>' : ''}
         
     | 
| 990 | 
         
             
                            </div>`;
         
     | 
| 991 | 
         | 
| 992 | 
         
             
                            const formData = new FormData(form);
         
     | 
| 993 | 
         
            +
                            // MODIFICATION: Ajouter l'茅tat de la checkbox aux donn茅es envoy茅es
         
     | 
| 994 | 
         
            +
                            formData.append('use_deepthink', deepThinkCheckbox.checked);
         
     | 
| 995 | 
         
            +
             
     | 
| 996 | 
         
             
                            try {
         
     | 
| 997 | 
         
             
                                const response = await fetch('/api/francais', {
         
     | 
| 998 | 
         
             
                                    method: 'POST',
         
     | 
| 999 | 
         
             
                                    body: formData
         
     | 
| 1000 | 
         
             
                                });
         
     | 
| 1001 | 
         | 
| 1002 | 
         
            +
                                const result = await response.json();
         
     | 
| 1003 | 
         | 
| 1004 | 
         
             
                                if (!response.ok) {
         
     | 
| 
         | 
|
| 1005 | 
         
             
                                     throw new Error(result.output || `Erreur HTTP ${response.status}`);
         
     | 
| 1006 | 
         
             
                                }
         
     | 
| 1007 | 
         | 
| 
         | 
|
| 1008 | 
         
             
                                output.style.opacity = '0';
         
     | 
| 1009 | 
         
            +
                                output.style.transition = ''; // Remove transition before changing content
         
     | 
| 1010 | 
         
            +
                                output.innerHTML = marked.parse(result.output);
         
     | 
| 1011 | 
         
            +
             
     | 
| 1012 | 
         
            +
                                // Re-apply transition for fade-in
         
     | 
| 1013 | 
         
            +
                                requestAnimationFrame(() => {
         
     | 
| 1014 | 
         
            +
                                    output.style.transition = 'opacity 0.3s ease-in-out';
         
     | 
| 1015 | 
         
             
                                    output.style.opacity = '1';
         
     | 
| 1016 | 
         
            +
                                });
         
     | 
| 1017 | 
         
            +
             
     | 
| 1018 | 
         
            +
             
     | 
| 1019 | 
         
            +
                                const titreSauvegarde = sujetValue.length > 100 ? sujetValue.substring(0, 97) + '...' : sujetValue;
         
     | 
| 1020 | 
         
            +
                                 const deepThinkSuffix = deepThinkCheckbox.checked ? ' [DeepThink]' : ''; // Ajoute un suffixe au titre si DeepThink est utilis茅
         
     | 
| 1021 | 
         
            +
                                sauvegarderReponse(titreSauvegarde + deepThinkSuffix, result.output);
         
     | 
| 1022 | 
         
            +
             
     | 
| 1023 | 
         
            +
                                MathJax.typesetPromise([output]).catch(function (err) {
         
     | 
| 1024 | 
         
            +
                                     console.error('MathJax typesetting error:', err);
         
     | 
| 1025 | 
         
            +
                                });
         
     | 
| 1026 | 
         
            +
             
     | 
| 1027 | 
         
             
                            } catch (error) {
         
     | 
| 1028 | 
         
             
                                 console.error("Erreur lors de la soumission:", error);
         
     | 
| 1029 | 
         
             
                                 output.innerHTML = `
         
     | 
| 
         | 
|
| 1041 | 
         
             
                    async function submitEtudeTexteForm() {
         
     | 
| 1042 | 
         
             
                        const form = document.getElementById('etude-texte-form');
         
     | 
| 1043 | 
         
             
                        const output = document.getElementById('etude-texte-output');
         
     | 
| 1044 | 
         
            +
                        const fileInput = document.getElementById('image-upload');
         
     | 
| 1045 | 
         | 
| 1046 | 
         
             
                        form.addEventListener('submit', async (e) => {
         
     | 
| 1047 | 
         
             
                            e.preventDefault();
         
     | 
| 1048 | 
         | 
| 1049 | 
         
            +
                             if (uploadedFiles.size === 0) { // Use the size of our managed Map
         
     | 
| 
         | 
|
| 1050 | 
         
             
                                 output.innerHTML = `
         
     | 
| 1051 | 
         
             
                                <div class="alert-message alert-warning">
         
     | 
| 1052 | 
         
             
                                     <i class="fas fa-exclamation-triangle"></i>
         
     | 
| 
         | 
|
| 1055 | 
         
             
                                         <p>Veuillez ajouter au moins une image pour l'analyse.</p>
         
     | 
| 1056 | 
         
             
                                     </div>
         
     | 
| 1057 | 
         
             
                                 </div>`;
         
     | 
| 1058 | 
         
            +
                                return;
         
     | 
| 1059 | 
         
             
                            }
         
     | 
| 1060 | 
         | 
| 1061 | 
         
             
                            output.innerHTML = `
         
     | 
| 1062 | 
         
             
                            <div class="flex flex-col items-center justify-center py-8">
         
     | 
| 1063 | 
         
             
                                <div class="loader mb-4">
         
     | 
| 1064 | 
         
            +
                                    <div></div><div></div><div></div><div></div>
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1065 | 
         
             
                                </div>
         
     | 
| 1066 | 
         
             
                                <p class="text-sm font-medium text-gray-600">Analyse en cours...</p>
         
     | 
| 1067 | 
         
             
                                <p class="text-xs text-gray-400 mt-2">Cela peut prendre un moment</p>
         
     | 
| 1068 | 
         
             
                            </div>`;
         
     | 
| 1069 | 
         | 
| 1070 | 
         
             
                            const formData = new FormData();
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1071 | 
         
             
                             uploadedFiles.forEach((file) => {
         
     | 
| 1072 | 
         
             
                                 formData.append('images', file, file.name);
         
     | 
| 1073 | 
         
             
                             });
         
     | 
| 1074 | 
         | 
| 
         | 
|
| 1075 | 
         
             
                            try {
         
     | 
| 1076 | 
         
             
                                const response = await fetch('/api/etude-texte', {
         
     | 
| 1077 | 
         
             
                                    method: 'POST',
         
     | 
| 1078 | 
         
            +
                                    body: formData
         
     | 
| 1079 | 
         
             
                                });
         
     | 
| 1080 | 
         | 
| 1081 | 
         
            +
                                const result = await response.json();
         
     | 
| 1082 | 
         | 
| 1083 | 
         
             
                                if (!response.ok) {
         
     | 
| 
         | 
|
| 1084 | 
         
             
                                    throw new Error(result.output || `Erreur HTTP ${response.status}`);
         
     | 
| 1085 | 
         
             
                                }
         
     | 
| 1086 | 
         | 
| 
         | 
|
| 1087 | 
         
             
                                output.style.opacity = '0';
         
     | 
| 1088 | 
         
            +
                                output.style.transition = ''; // Remove transition before changing content
         
     | 
| 1089 | 
         
            +
                                output.innerHTML = marked.parse(result.output);
         
     | 
| 1090 | 
         
            +
             
     | 
| 1091 | 
         
            +
                                 // Re-apply transition for fade-in
         
     | 
| 1092 | 
         
            +
                                requestAnimationFrame(() => {
         
     | 
| 1093 | 
         
            +
                                    output.style.transition = 'opacity 0.3s ease-in-out';
         
     | 
| 1094 | 
         
             
                                    output.style.opacity = '1';
         
     | 
| 1095 | 
         
            +
                                });
         
     | 
| 1096 | 
         
            +
             
     | 
| 1097 | 
         
            +
                                const titre = `Analyse d'image(s) - ${new Date().toLocaleDateString('fr-FR')}`;
         
     | 
| 1098 | 
         
            +
                                sauvegarderReponse(titre, result.output);
         
     | 
| 1099 | 
         
            +
             
     | 
| 1100 | 
         
            +
                                MathJax.typesetPromise([output]).catch(function (err) {
         
     | 
| 1101 | 
         
            +
                                     console.error('MathJax typesetting error:', err);
         
     | 
| 1102 | 
         
            +
                                });
         
     | 
| 1103 | 
         
            +
             
     | 
| 
         | 
|
| 1104 | 
         
             
                            } catch (error) {
         
     | 
| 1105 | 
         
             
                                 console.error("Erreur lors de l'analyse:", error);
         
     | 
| 1106 | 
         
             
                                 output.innerHTML = `
         
     | 
| 
         | 
|
| 1118 | 
         
             
                    // Animation des cartes au d茅filement
         
     | 
| 1119 | 
         
             
                    function animateOnScroll() {
         
     | 
| 1120 | 
         
             
                        const cards = document.querySelectorAll('.card-hover');
         
     | 
| 
         | 
|
| 1121 | 
         
             
                        if (!('IntersectionObserver' in window)) {
         
     | 
| 1122 | 
         
             
                             cards.forEach(card => card.style.opacity = '1');
         
     | 
| 1123 | 
         
             
                             return;
         
     | 
| 1124 | 
         
             
                        }
         
     | 
| 
         | 
|
| 1125 | 
         
             
                        const observer = new IntersectionObserver((entries) => {
         
     | 
| 1126 | 
         
            +
                            entries.forEach((entry) => {
         
     | 
| 1127 | 
         
             
                                if (entry.isIntersecting) {
         
     | 
| 1128 | 
         
            +
                                    // Use requestAnimationFrame for smoother start
         
     | 
| 1129 | 
         
            +
                                    requestAnimationFrame(() => {
         
     | 
| 1130 | 
         
            +
                                        entry.target.style.opacity = '1';
         
     | 
| 1131 | 
         
            +
                                        entry.target.style.transform = 'translateY(0)';
         
     | 
| 1132 | 
         
            +
                                    });
         
     | 
| 1133 | 
         
            +
                                    observer.unobserve(entry.target);
         
     | 
| 1134 | 
         
             
                                }
         
     | 
| 1135 | 
         
             
                            });
         
     | 
| 1136 | 
         
            +
                        }, { threshold: 0.1 });
         
     | 
| 
         | 
|
| 
         | 
|
| 1137 | 
         | 
| 1138 | 
         
             
                        cards.forEach(card => {
         
     | 
| 1139 | 
         
             
                            card.style.opacity = '0';
         
     | 
| 1140 | 
         
             
                            card.style.transform = 'translateY(30px)';
         
     | 
| 1141 | 
         
            +
                            // Rely on the .scale-in animation defined in CSS for entrance
         
     | 
| 
         | 
|
| 1142 | 
         
             
                            observer.observe(card);
         
     | 
| 1143 | 
         
             
                        });
         
     | 
| 1144 | 
         
             
                    }
         
     | 
| 
         | 
|
| 1147 | 
         
             
                    function enhanceTextareaFocus() {
         
     | 
| 1148 | 
         
             
                        const textarea = document.getElementById('sujet-francais');
         
     | 
| 1149 | 
         
             
                        const counter = document.getElementById('character-count');
         
     | 
| 
         | 
|
| 1150 | 
         
             
                        textarea.addEventListener('input', () => {
         
     | 
| 1151 | 
         
             
                            const length = textarea.value.length;
         
     | 
| 1152 | 
         
             
                            counter.textContent = `${length} caract猫re${length !== 1 ? 's' : ''}`;
         
     | 
| 
         | 
|
| 1153 | 
         
             
                             textarea.classList.remove('border-red-500');
         
     | 
| 1154 | 
         
             
                        });
         
     | 
| 1155 | 
         
             
                    }
         
     | 
| 
         | 
|
| 1159 | 
         
             
                         const radioGroups = document.querySelectorAll('input[type="radio"] + span');
         
     | 
| 1160 | 
         
             
                         radioGroups.forEach(label => {
         
     | 
| 1161 | 
         
             
                            const input = label.previousElementSibling;
         
     | 
| 1162 | 
         
            +
                            if (input.disabled) return;
         
     | 
| 1163 | 
         | 
| 1164 | 
         
             
                            label.addEventListener('mouseenter', () => {
         
     | 
| 1165 | 
         
             
                                if (!input.checked) {
         
     | 
| 1166 | 
         
            +
                                     // Use Tailwind classes for consistency
         
     | 
| 1167 | 
         
            +
                                    label.classList.add('border-blue-400', 'shadow-md', 'transform' ,'-translate-y-0.5');
         
     | 
| 1168 | 
         
             
                                }
         
     | 
| 1169 | 
         
             
                            });
         
     | 
| 
         | 
|
| 1170 | 
         
             
                            label.addEventListener('mouseleave', () => {
         
     | 
| 
         | 
|
| 1171 | 
         
             
                                 if (!input.checked) {
         
     | 
| 1172 | 
         
            +
                                     label.classList.remove('border-blue-400', 'shadow-md', 'transform', '-translate-y-0.5');
         
     | 
| 1173 | 
         
             
                                 }
         
     | 
| 1174 | 
         
             
                            });
         
     | 
| 
         | 
|
| 
         | 
|
| 1175 | 
         
             
                             input.addEventListener('change', () => {
         
     | 
| 
         | 
|
| 1176 | 
         
             
                                 const groupName = input.name;
         
     | 
| 1177 | 
         
             
                                 document.querySelectorAll(`input[name="${groupName}"] + span`).forEach(otherLabel => {
         
     | 
| 1178 | 
         
             
                                     if (otherLabel !== label) {
         
     | 
| 1179 | 
         
            +
                                         otherLabel.classList.remove('border-blue-400', 'shadow-md', 'transform', '-translate-y-0.5', 'border-primary'); // Ensure clean state
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1180 | 
         
             
                                     } else {
         
     | 
| 1181 | 
         
            +
                                         label.classList.remove('shadow-md', 'transform', '-translate-y-0.5'); // Remove hover effects if checked
         
     | 
| 
         | 
|
| 
         | 
|
| 1182 | 
         
             
                                     }
         
     | 
| 1183 | 
         
             
                                 });
         
     | 
| 1184 | 
         
             
                             });
         
     | 
| 1185 | 
         
             
                        });
         
     | 
| 1186 | 
         
             
                    }
         
     | 
| 1187 | 
         | 
| 1188 | 
         
            +
                    // Initialisation
         
     | 
| 1189 | 
         
             
                    document.addEventListener('DOMContentLoaded', () => {
         
     | 
| 1190 | 
         
             
                        initializeFileUpload();
         
     | 
| 1191 | 
         
             
                        submitFrancaisForm();
         
     | 
| 
         | 
|
| 1193 | 
         
             
                        animateOnScroll();
         
     | 
| 1194 | 
         
             
                        enhanceTextareaFocus();
         
     | 
| 1195 | 
         
             
                        enhanceRadioButtons();
         
     | 
| 1196 | 
         
            +
                        afficherSauvegardes();
         
     | 
| 1197 | 
         | 
| 1198 | 
         
            +
                        // MathJax Config
         
     | 
| 1199 | 
         
             
                        window.MathJax = {
         
     | 
| 1200 | 
         
            +
                             tex: { inlineMath: [['$', '$'], ['\\(', '\\)']], displayMath: [['$$', '$$'], ['\\[', '\\]']] },
         
     | 
| 1201 | 
         
            +
                             svg: { fontCache: 'global' },
         
     | 
| 1202 | 
         
            +
                             options: { skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'], ignoreHtmlClass: 'tex2jax_ignore', processHtmlClass: 'tex2jax_process' }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1203 | 
         
             
                        };
         
     | 
| 1204 | 
         | 
| 1205 | 
         
            +
                        // Welcome Message
         
     | 
| 
         | 
|
| 1206 | 
         
             
                        const showWelcome = sessionStorage.getItem('welcomeShown') !== 'true';
         
     | 
| 1207 | 
         
             
                        if (showWelcome) {
         
     | 
| 1208 | 
         
             
                             const welcomeMessageContainer = document.createElement('div');
         
     | 
| 1209 | 
         
             
                             welcomeMessageContainer.innerHTML = `
         
     | 
| 1210 | 
         
             
                                <div class="fixed bottom-6 right-6 bg-white rounded-xl shadow-lg p-5 transform transition-all duration-500 opacity-0 translate-y-4 max-w-xs z-[100]">
         
     | 
| 1211 | 
         
             
                                    <div class="flex items-start space-x-4">
         
     | 
| 1212 | 
         
            +
                                        <div class="bg-gradient-to-r from-blue-500 to-blue-700 rounded-full p-3 mt-1 flex-shrink-0"> <i class="fas fa-robot text-white text-xl"></i> </div>
         
     | 
| 1213 | 
         
            +
                                        <div> <p class="text-sm font-semibold text-gray-800">Bienvenue sur Mariam AI !</p> <p class="text-xs text-gray-500 mt-1">Votre assistant est pr锚t. Posez un sujet ou analysez un texte.</p> </div>
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1214 | 
         
             
                                    </div>
         
     | 
| 1215 | 
         
            +
                                    <button class="absolute top-2 right-2 text-gray-400 hover:text-gray-600 focus:outline-none close-welcome p-1"> <i class="fas fa-times text-xs"></i> </button>
         
     | 
| 1216 | 
         
            +
                                </div>`;
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1217 | 
         
             
                             document.body.appendChild(welcomeMessageContainer);
         
     | 
| 1218 | 
         
             
                             const welcomeMessage = welcomeMessageContainer.firstElementChild;
         
     | 
| 1219 | 
         
            +
                            setTimeout(() => { welcomeMessage.classList.remove('opacity-0', 'translate-y-4'); }, 500);
         
     | 
| 1220 | 
         
            +
                            welcomeMessage.querySelector('.close-welcome').addEventListener('click', () => closeWelcomeMessage(welcomeMessage));
         
     | 
| 1221 | 
         
            +
                            setTimeout(() => { if (document.body.contains(welcomeMessage)) closeWelcomeMessage(welcomeMessage); }, 7000);
         
     | 
| 1222 | 
         
            +
                             sessionStorage.setItem('welcomeShown', 'true');
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1223 | 
         
             
                         }
         
     | 
| 
         | 
|
| 1224 | 
         
             
                         function closeWelcomeMessage(element) {
         
     | 
| 1225 | 
         
             
                             element.classList.add('opacity-0', 'translate-y-4');
         
     | 
| 1226 | 
         
            +
                             setTimeout(() => { if (element.parentElement) element.parentElement.remove(); }, 500);
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1227 | 
         
             
                         }
         
     | 
| 
         | 
|
| 1228 | 
         
             
                    });
         
     | 
| 1229 | 
         
             
                </script>
         
     | 
| 1230 | 
         
             
            </body>
         
     |