|
<!DOCTYPE html> |
|
<html lang="fr"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Mariam AI - Analyse Littéraire</title> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script> |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;500;600;700&display=swap'); |
|
|
|
:root { |
|
--primary: #4361ee; |
|
--primary-dark: #3a56d4; |
|
--secondary: #2b2d42; |
|
--accent: #ef476f; |
|
--light: #f8f9fa; |
|
--gray-100: #f1f3f5; |
|
--gray-200: #e9ecef; |
|
--gray-300: #dee2e6; |
|
--gray-400: #ced4da; |
|
--gray-700: #495057; |
|
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05); |
|
--shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06); |
|
--shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); |
|
--radius-sm: 0.375rem; |
|
--radius-md: 0.5rem; |
|
--radius-lg: 0.75rem; |
|
} |
|
|
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: 'Inter', sans-serif; |
|
background: linear-gradient(135deg, #f6f8fb 0%, #f1f3f5 100%); |
|
color: var(--secondary); |
|
line-height: 1.6; |
|
padding-bottom: 2rem; |
|
} |
|
|
|
header { |
|
background-color: white; |
|
padding: 1.5rem 1rem; |
|
text-align: center; |
|
box-shadow: var(--shadow-sm); |
|
position: relative; |
|
z-index: 10; |
|
} |
|
|
|
.logo { |
|
font-family: 'Playfair Display', serif; |
|
font-size: 2rem; |
|
color: var(--secondary); |
|
margin-bottom: 0.25rem; |
|
} |
|
|
|
.tagline { |
|
font-size: 0.9rem; |
|
color: var(--gray-700); |
|
font-weight: 500; |
|
} |
|
|
|
.card { |
|
background: white; |
|
border-radius: var(--radius-lg); |
|
box-shadow: var(--shadow-md); |
|
padding: 1.5rem; |
|
margin: 1rem; |
|
transition: transform 0.2s ease, box-shadow 0.2s ease; |
|
} |
|
|
|
.upload-area { |
|
border: 2px dashed var(--gray-300); |
|
border-radius: var(--radius-md); |
|
padding: 1.5rem 1rem; |
|
text-align: center; |
|
cursor: pointer; |
|
transition: all 0.2s ease; |
|
margin: 1.5rem 0; |
|
} |
|
|
|
.upload-area:hover, .upload-area.active { |
|
border-color: var(--primary); |
|
background-color: rgba(67, 97, 238, 0.05); |
|
} |
|
|
|
.upload-icon { |
|
width: 3.5rem; |
|
height: 3.5rem; |
|
margin: 0 auto 1rem; |
|
color: var(--gray-400); |
|
} |
|
|
|
.upload-area:hover .upload-icon, .upload-area.active .upload-icon { |
|
color: var(--primary); |
|
} |
|
|
|
.input-group { |
|
margin-bottom: 1.5rem; |
|
} |
|
|
|
.label { |
|
display: block; |
|
margin-bottom: 0.5rem; |
|
font-weight: 600; |
|
font-size: 0.9rem; |
|
} |
|
|
|
.input { |
|
width: 100%; |
|
padding: 0.75rem; |
|
border: 1px solid var(--gray-300); |
|
border-radius: var(--radius-md); |
|
font-family: 'Inter', sans-serif; |
|
font-size: 1rem; |
|
transition: border-color 0.2s ease; |
|
} |
|
|
|
.input:focus { |
|
outline: none; |
|
border-color: var(--primary); |
|
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1); |
|
} |
|
|
|
.preview-container { |
|
margin: 1.5rem 0; |
|
} |
|
|
|
.preview-title { |
|
font-weight: 600; |
|
margin-bottom: 0.5rem; |
|
font-size: 0.9rem; |
|
} |
|
|
|
.preview-image-container { |
|
background-color: var(--gray-100); |
|
border-radius: var(--radius-md); |
|
overflow: hidden; |
|
position: relative; |
|
} |
|
|
|
.preview-image { |
|
max-width: 100%; |
|
max-height: 15rem; |
|
margin: 0 auto; |
|
display: block; |
|
} |
|
|
|
.btn { |
|
display: block; |
|
width: 100%; |
|
padding: 0.875rem; |
|
font-weight: 600; |
|
text-align: center; |
|
border: none; |
|
border-radius: var(--radius-md); |
|
cursor: pointer; |
|
transition: all 0.2s ease; |
|
font-size: 1rem; |
|
} |
|
|
|
.btn-primary { |
|
background-color: var(--primary); |
|
color: white; |
|
} |
|
|
|
.btn-primary:hover, .btn-primary:focus { |
|
background-color: var(--primary-dark); |
|
transform: translateY(-1px); |
|
box-shadow: var(--shadow-md); |
|
} |
|
|
|
.btn-primary:active { |
|
transform: translateY(0); |
|
} |
|
|
|
.loading-overlay { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
right: 0; |
|
bottom: 0; |
|
background-color: rgba(0, 0, 0, 0.5); |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 100; |
|
} |
|
|
|
.loading-card { |
|
background-color: white; |
|
padding: 2rem; |
|
border-radius: var(--radius-lg); |
|
box-shadow: var(--shadow-lg); |
|
text-align: center; |
|
max-width: 80%; |
|
} |
|
|
|
.spinner { |
|
width: 3rem; |
|
height: 3rem; |
|
border: 4px solid var(--gray-200); |
|
border-radius: 50%; |
|
border-top-color: var(--primary); |
|
animation: spin 1s linear infinite; |
|
margin: 0 auto 1rem; |
|
} |
|
|
|
@keyframes spin { |
|
to { transform: rotate(360deg); } |
|
} |
|
|
|
.result-card { |
|
padding: 0; |
|
overflow: hidden; |
|
} |
|
|
|
.tabs { |
|
display: flex; |
|
border-bottom: 1px solid var(--gray-200); |
|
} |
|
|
|
.tab { |
|
flex: 1; |
|
text-align: center; |
|
padding: 1rem 0.5rem; |
|
font-weight: 600; |
|
font-size: 0.9rem; |
|
color: var(--gray-700); |
|
background-color: transparent; |
|
border: none; |
|
border-bottom: 2px solid transparent; |
|
cursor: pointer; |
|
} |
|
|
|
.tab.active { |
|
color: var(--primary); |
|
border-bottom-color: var(--primary); |
|
} |
|
|
|
.tab-content { |
|
padding: 1.5rem; |
|
} |
|
|
|
.custom-prose { |
|
font-size: 1rem; |
|
line-height: 1.8; |
|
} |
|
|
|
.custom-prose h1, .custom-prose h2, .custom-prose h3 { |
|
font-family: 'Playfair Display', serif; |
|
margin-top: 1.5em; |
|
margin-bottom: 0.75em; |
|
line-height: 1.3; |
|
} |
|
|
|
.custom-prose h1 { |
|
font-size: 1.75rem; |
|
} |
|
|
|
.custom-prose h2 { |
|
font-size: 1.5rem; |
|
} |
|
|
|
.custom-prose h3 { |
|
font-size: 1.25rem; |
|
} |
|
|
|
.custom-prose p { |
|
margin-bottom: 1.25em; |
|
} |
|
|
|
.custom-prose ul, .custom-prose ol { |
|
margin-top: 1em; |
|
margin-bottom: 1em; |
|
padding-left: 1.5em; |
|
} |
|
|
|
.custom-prose li { |
|
margin-bottom: 0.5em; |
|
} |
|
|
|
.markdown-table { |
|
overflow-x: auto; |
|
-webkit-overflow-scrolling: touch; |
|
} |
|
|
|
.markdown-table table { |
|
width: 100%; |
|
border-collapse: separate; |
|
border-spacing: 0; |
|
margin: 1em 0; |
|
} |
|
|
|
.markdown-table th { |
|
background: var(--primary); |
|
color: white; |
|
font-weight: 600; |
|
padding: 0.75rem; |
|
text-align: left; |
|
font-size: 0.9rem; |
|
} |
|
|
|
.markdown-table td { |
|
padding: 0.75rem; |
|
border-bottom: 1px solid var(--gray-200); |
|
font-size: 0.9rem; |
|
} |
|
|
|
.markdown-table tr:hover { |
|
background: var(--gray-100); |
|
} |
|
|
|
.upload-instructions { |
|
font-size: 0.85rem; |
|
color: var(--gray-700); |
|
margin-top: 0.5rem; |
|
} |
|
|
|
.file-input { |
|
display: none; |
|
} |
|
|
|
.slide-up { |
|
animation: slide-up 0.4s ease forwards; |
|
} |
|
|
|
@keyframes slide-up { |
|
from { |
|
opacity: 0; |
|
transform: translateY(20px); |
|
} |
|
to { |
|
opacity: 1; |
|
transform: translateY(0); |
|
} |
|
} |
|
|
|
.shimmer { |
|
position: absolute; |
|
top: 0; |
|
left: -100%; |
|
width: 50%; |
|
height: 100%; |
|
background: linear-gradient(90deg, |
|
rgba(255,255,255,0) 0%, |
|
rgba(255,255,255,0.2) 50%, |
|
rgba(255,255,255,0) 100%); |
|
animation: shimmer 2s infinite; |
|
} |
|
|
|
@keyframes shimmer { |
|
to { |
|
left: 100%; |
|
} |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<header> |
|
<h1 class="logo">Mariam AI</h1> |
|
<p class="tagline">Assistant d'Analyse Littéraire</p> |
|
</header> |
|
|
|
<main> |
|
<div class="card"> |
|
<form id="uploadForm"> |
|
<div class="input-group"> |
|
<label for="imageInput" class="label">Votre document</label> |
|
<div id="uploadArea" class="upload-area"> |
|
<svg class="upload-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" /> |
|
</svg> |
|
<p>Touchez pour télécharger</p> |
|
<p class="upload-instructions">PNG, JPG jusqu'à 10MB</p> |
|
<input id="imageInput" type="file" class="file-input" accept="image/*" required> |
|
</div> |
|
</div> |
|
|
|
<div class="input-group"> |
|
<label for="consignesInput" class="label">Consignes (optionnel)</label> |
|
<input id="consignesInput" type="text" class="input" placeholder="Entrez vos consignes ici"> |
|
</div> |
|
|
|
<div id="previewContainer" class="preview-container" style="display: none;"> |
|
<p class="preview-title">Aperçu du document</p> |
|
<div class="preview-image-container"> |
|
<img id="previewImage" class="preview-image" src="#" alt="Aperçu"> |
|
</div> |
|
</div> |
|
|
|
<button type="submit" class="btn btn-primary"> |
|
Lancer l'analyse |
|
</button> |
|
</form> |
|
</div> |
|
|
|
<div id="result" class="card result-card" style="display: none;"> |
|
<div class="tabs"> |
|
<button id="dissertationTab" class="tab active">Dissertation</button> |
|
<button id="tableauTab" class="tab">Tableau</button> |
|
</div> |
|
<div class="tab-content"> |
|
<div id="dissertationContent" class="custom-prose"></div> |
|
<div id="tableauContent" class="markdown-table" style="display: none;"></div> |
|
</div> |
|
</div> |
|
</main> |
|
|
|
<div id="loading" class="loading-overlay" style="display: none;"> |
|
<div class="loading-card"> |
|
<div class="spinner"></div> |
|
<p>Analyse en cours...</p> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
const uploadForm = document.getElementById('uploadForm'); |
|
const imageInput = document.getElementById('imageInput'); |
|
const uploadArea = document.getElementById('uploadArea'); |
|
const previewContainer = document.getElementById('previewContainer'); |
|
const previewImage = document.getElementById('previewImage'); |
|
const loadingIndicator = document.getElementById('loading'); |
|
const resultDiv = document.getElementById('result'); |
|
const dissertationTab = document.getElementById('dissertationTab'); |
|
const tableauTab = document.getElementById('tableauTab'); |
|
const dissertationContent = document.getElementById('dissertationContent'); |
|
const tableauContent = document.getElementById('tableauContent'); |
|
|
|
|
|
marked.setOptions({ |
|
breaks: true, |
|
gfm: true |
|
}); |
|
|
|
|
|
uploadArea.addEventListener('click', function() { |
|
imageInput.click(); |
|
}); |
|
|
|
|
|
uploadArea.addEventListener('touchstart', function() { |
|
this.classList.add('active'); |
|
}); |
|
|
|
uploadArea.addEventListener('touchend', function() { |
|
this.classList.remove('active'); |
|
}); |
|
|
|
|
|
imageInput.addEventListener('change', function() { |
|
const file = this.files[0]; |
|
if (file) { |
|
const reader = new FileReader(); |
|
reader.onload = function(e) { |
|
previewImage.src = e.target.result; |
|
previewContainer.style.display = 'block'; |
|
previewContainer.classList.add('slide-up'); |
|
|
|
|
|
uploadArea.classList.add('active'); |
|
setTimeout(() => uploadArea.classList.remove('active'), 500); |
|
} |
|
reader.readAsDataURL(file); |
|
} else { |
|
previewContainer.style.display = 'none'; |
|
} |
|
}); |
|
|
|
|
|
dissertationTab.addEventListener('click', function() { |
|
dissertationTab.classList.add('active'); |
|
tableauTab.classList.remove('active'); |
|
dissertationContent.style.display = 'block'; |
|
tableauContent.style.display = 'none'; |
|
}); |
|
|
|
tableauTab.addEventListener('click', function() { |
|
tableauTab.classList.add('active'); |
|
dissertationTab.classList.remove('active'); |
|
tableauContent.style.display = 'block'; |
|
dissertationContent.style.display = 'none'; |
|
}); |
|
|
|
|
|
uploadForm.addEventListener('submit', function(e) { |
|
e.preventDefault(); |
|
loadingIndicator.style.display = 'flex'; |
|
|
|
|
|
|
|
setTimeout(() => { |
|
loadingIndicator.style.display = 'none'; |
|
|
|
|
|
const data = { |
|
dissertation: `# Analyse de Baudelaire: Les Fleurs du Mal |
|
|
|
Dans cette œuvre majeure du XIXe siècle, Baudelaire révèle la dualité de l'existence humaine à travers une poésie à la fois sublime et déchirante. |
|
|
|
## Le spleen et l'idéal |
|
|
|
Baudelaire explore la tension entre l'aspiration à la beauté et le poids de l'existence quotidienne. Cette dualité constitue l'essence même de sa poétique. |
|
|
|
## La modernité baudelairienne |
|
|
|
En faisant de la ville et de ses aspects les plus sombres un objet poétique, Baudelaire invente une nouvelle façon de percevoir la modernité et influence toute la poésie qui suivra.`, |
|
|
|
tableau: `| Thème | Poèmes représentatifs | Analyse | |
|
|-------|----------------------|---------| |
|
| Spleen | "Spleen I-IV", "De profundis clamavi" | Expression du mal-être, ennui, mélancolie | |
|
| Idéal | "L'Invitation au voyage", "Élévation" | Aspiration vers la beauté, évasion | |
|
| Amour | "À une passante", "Le Vampire" | Amour impossible, femme fatale | |
|
| Mort | "La Charogne", "Une Martyre" | Fascination pour la décomposition |` |
|
}; |
|
|
|
dissertationContent.innerHTML = marked.parse(data.dissertation); |
|
tableauContent.innerHTML = marked.parse(data.tableau); |
|
|
|
resultDiv.style.display = 'block'; |
|
resultDiv.classList.add('slide-up'); |
|
|
|
|
|
resultDiv.scrollIntoView({ behavior: 'smooth' }); |
|
}, 2000); |
|
}); |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
const interactiveElements = document.querySelectorAll('.btn, .tab, .upload-area'); |
|
|
|
interactiveElements.forEach(el => { |
|
el.addEventListener('touchstart', function() { |
|
this.style.transform = 'scale(0.98)'; |
|
}); |
|
|
|
el.addEventListener('touchend', function() { |
|
this.style.transform = 'scale(1)'; |
|
}); |
|
}); |
|
}); |
|
</script> |
|
</body> |
|
</html> |
|
|