diff --git a/app/static/script.js b/app/static/script.js
new file mode 100644
index 0000000..5e1178e
--- /dev/null
+++ b/app/static/script.js
@@ -0,0 +1,180 @@
+let currentCard = null;
+let attempts = 0;
+let stats = { points: 0, total: 0 };
+
+document.addEventListener('DOMContentLoaded', loadLessons);
+
+function loadLessons() {
+ fetch('/api/lessons')
+ .then(res => res.json())
+ .then(lessons => {
+ const list = document.getElementById('lesson-list');
+ list.innerHTML = '';
+ lessons.forEach(l => {
+ const div = document.createElement('div');
+ div.className = 'lesson-item';
+ div.innerHTML = `
+
+
+ `;
+ list.appendChild(div);
+ });
+ });
+}
+
+function updateStartBtn() {
+ const checked = document.querySelectorAll('#lesson-list input:checked');
+ document.getElementById('btn-start').disabled = (checked.length === 0);
+}
+
+function startQuiz() {
+ stats = { points: 0, total: 0 };
+ updateStats();
+ document.getElementById('setup-screen').style.display = 'none';
+ document.getElementById('quiz-screen').style.display = 'flex';
+ nextQuestion();
+}
+
+function stopQuiz() {
+ document.getElementById('quiz-screen').style.display = 'none';
+ document.getElementById('setup-screen').style.display = 'block';
+}
+
+function nextQuestion() {
+ const btn = document.getElementById('btn-action');
+ btn.innerText = "Prüfen";
+ btn.onclick = checkAnswer;
+ btn.className = "action-btn primary";
+
+ document.getElementById('feedback').innerText = '';
+
+ const lids = Array.from(document.querySelectorAll('#lesson-list input:checked')).map(cb => cb.value);
+ const mid = document.getElementById('opt-middle').checked;
+
+ fetch('/api/question', {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({ lessons: lids, askMiddle: mid })
+ })
+ .then(res => res.json())
+ .then(card => {
+ if(card.error) { alert(card.error); stopQuiz(); return; }
+ currentCard = card;
+ attempts = 0;
+ renderCard(card);
+ });
+}
+
+function renderCard(card) {
+ document.getElementById('latin-text').innerText = card.latin;
+ document.getElementById('hint-text').innerText = card.hint;
+
+ const container = document.getElementById('inputs-container');
+ container.innerHTML = '';
+
+ if (card.middle_req) {
+ const row = document.createElement('div');
+ row.className = 'input-row';
+ row.innerHTML = `
+ Form:
+
+ `;
+ container.appendChild(row);
+ }
+
+ card.german_correct.forEach(ans => {
+ const row = document.createElement('div');
+ row.className = 'input-row';
+ row.innerHTML = `
+ Dt:
+
+ `;
+ container.appendChild(row);
+ });
+
+ const first = container.querySelector('input');
+ if(first) first.focus();
+}
+
+function checkAnswer() {
+ const inputs = document.querySelectorAll('.quiz-input');
+ const payload = [];
+ inputs.forEach(i => {
+ payload.push({
+ value: i.value,
+ correct: i.dataset.correct,
+ type: i.dataset.type || 'german'
+ });
+ });
+
+ attempts++;
+
+ fetch('/api/check', {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({ inputs: payload, attempt: attempts })
+ })
+ .then(res => res.json())
+ .then(res => {
+ const fb = document.getElementById('feedback');
+ let globalMsg = "";
+
+ res.results.forEach((r, idx) => {
+ const el = inputs[idx];
+ el.classList.remove('wrong', 'correct', 'typo', 'incomplete');
+
+ if (r.status === 'correct') {
+ el.classList.add('correct');
+ } else if (r.status === 'typo') {
+ el.classList.add('typo');
+ } else if (r.status === 'incomplete') {
+ el.classList.add('incomplete');
+ globalMsg = r.msg;
+ } else {
+ el.classList.add('wrong');
+ }
+ });
+
+ if (res.all_correct) {
+ fb.innerText = "Alles richtig!";
+ fb.style.color = "green";
+ stats.points += res.score;
+ finishTurn();
+ } else {
+ if (res.has_incomplete) {
+ fb.innerText = globalMsg || "Unvollständig.";
+ fb.style.color = "#d39e00";
+ } else {
+ if (attempts >= 3) {
+ fb.innerText = "Leider nicht geschafft. Lösungen eingesetzt.";
+ fb.style.color = "red";
+ inputs.forEach(i => i.value = i.dataset.correct);
+ finishTurn();
+ } else {
+ fb.innerText = `Fehler. Versuch ${attempts}/3`;
+ fb.style.color = "orange";
+ }
+ }
+ }
+ });
+}
+
+function finishTurn() {
+ stats.total++;
+ updateStats();
+ const btn = document.getElementById('btn-action');
+ btn.innerText = "Weiter";
+ btn.onclick = nextQuestion;
+ btn.focus();
+}
+
+function updateStats() {
+ let p = 0;
+ if (stats.total > 0) p = Math.round((stats.points / stats.total) * 100);
+ document.getElementById('progress-bar').style.width = `${p}%`;
+ document.getElementById('stats-text').innerText = `${p}% (${stats.points.toFixed(1)}/${stats.total})`;
+}
+
+document.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') document.getElementById('btn-action').click();
+});
\ No newline at end of file