Commit dfcd7a81 by PLN (Algolia)

Add the Clarté ADHD self-assessment at /tdah/ and /adhd/

parent 0620d69a
/**
* Clarté - ADHD Self-Evaluation App
* Client-side questionnaire logic and PDF generation
*/
// ============================================
// QUESTIONNAIRE DATA
// ============================================
const ASRS_QUESTIONS = {
part_a: [
{ id: 'asrs_1', text: "À quelle fréquence avez-vous des difficultés à finaliser les derniers détails d'un projet, une fois que les parties les plus stimulantes ont été réalisées ?", threshold: 2 },
{ id: 'asrs_2', text: "À quelle fréquence avez-vous des difficultés à mettre de l'ordre lorsque vous devez effectuer une tâche qui requiert de l'organisation ?", threshold: 2 },
{ id: 'asrs_3', text: "À quelle fréquence avez-vous des difficultés à vous souvenir de vos rendez-vous ou de vos obligations ?", threshold: 2 },
{ id: 'asrs_4', text: "Lorsque vous devez effectuer une tâche qui demande beaucoup de réflexion, à quelle fréquence évitez-vous ou retardez-vous le moment de commencer ?", threshold: 3 },
{ id: 'asrs_5', text: "À quelle fréquence remuez-vous ou tortillez-vous les mains ou les pieds lorsque vous devez rester assis(e) pendant une longue période ?", threshold: 3 },
{ id: 'asrs_6', text: "À quelle fréquence vous sentez-vous excessivement actif(ve) et poussé(e) à faire des choses, comme si vous étiez mû(e) par un moteur ?", threshold: 3 },
],
part_b: [
{ id: 'asrs_7', text: "À quelle fréquence faites-vous des erreurs d'inattention lorsque vous devez travailler sur un projet ennuyeux ou difficile ?" },
{ id: 'asrs_8', text: "À quelle fréquence avez-vous des difficultés à maintenir votre attention lorsque vous effectuez un travail ennuyeux ou répétitif ?" },
{ id: 'asrs_9', text: "À quelle fréquence avez-vous des difficultés à vous concentrer sur ce que les gens vous disent, même lorsqu'ils s'adressent directement à vous ?" },
{ id: 'asrs_10', text: "À quelle fréquence égarez-vous ou avez-vous du mal à retrouver des objets à la maison ou au travail ?" },
{ id: 'asrs_11', text: "À quelle fréquence êtes-vous distrait(e) par l'activité ou le bruit autour de vous ?" },
{ id: 'asrs_12', text: "À quelle fréquence quittez-vous votre siège lors de réunions ou dans d'autres situations où vous êtes censé(e) rester assis(e) ?" },
{ id: 'asrs_13', text: "À quelle fréquence vous sentez-vous agité(e) ou remuant(e) ?" },
{ id: 'asrs_14', text: "À quelle fréquence avez-vous des difficultés à vous détendre et à vous relaxer lorsque vous avez du temps libre ?" },
{ id: 'asrs_15', text: "À quelle fréquence vous trouvez-vous à parler trop en situation sociale ?" },
{ id: 'asrs_16', text: "Lors d'une conversation, à quelle fréquence finissez-vous les phrases des personnes avec qui vous parlez avant qu'elles ne puissent les terminer elles-mêmes ?" },
{ id: 'asrs_17', text: "À quelle fréquence avez-vous des difficultés à attendre votre tour dans des situations qui l'exigent ?" },
{ id: 'asrs_18', text: "À quelle fréquence interrompez-vous les autres lorsqu'ils sont occupés ?" },
]
};
const ASRS_OPTIONS = [
{ value: 0, label: 'Jamais' },
{ value: 1, label: 'Rarement' },
{ value: 2, label: 'Parfois' },
{ value: 3, label: 'Souvent' },
{ value: 4, label: 'Très souvent' }
];
const DIVA_INATTENTION = [
{ id: 'diva_ia_1', text: "Avez-vous souvent du mal à prêter attention aux détails ou faites-vous des erreurs d'inattention dans votre travail ou d'autres activités ? (ex: négliger des détails, travail inexact)" },
{ id: 'diva_ia_2', text: "Avez-vous souvent du mal à maintenir votre attention sur des tâches ou des activités ? (ex: difficulté à rester concentré pendant les réunions, lectures)" },
{ id: 'diva_ia_3', text: "Avez-vous souvent l'impression de ne pas écouter quand on vous parle directement ? (ex: esprit ailleurs, même sans distraction évidente)" },
{ id: 'diva_ia_4', text: "Avez-vous souvent du mal à suivre les instructions jusqu'au bout et à terminer vos tâches professionnelles ou obligations ?" },
{ id: 'diva_ia_5', text: "Avez-vous souvent du mal à organiser vos tâches et activités ? (ex: difficulté à gérer le temps, respecter les délais)" },
{ id: 'diva_ia_6', text: "Évitez-vous souvent, ou êtes-vous réticent(e) à vous engager dans des tâches qui nécessitent un effort mental soutenu ?" },
{ id: 'diva_ia_7', text: "Perdez-vous souvent des objets nécessaires à vos activités ? (ex: clés, portefeuille, téléphone, documents)" },
{ id: 'diva_ia_8', text: "Êtes-vous souvent facilement distrait(e) par des stimuli externes ou des pensées sans rapport ?" },
{ id: 'diva_ia_9', text: "Êtes-vous souvent oublieux(se) dans la vie quotidienne ? (ex: oublier de rappeler, payer des factures, honorer des rendez-vous)" },
];
const DIVA_HYPERACTIVITY = [
{ id: 'diva_hi_1', text: "Remuez-vous souvent les mains ou les pieds, ou vous tortillez-vous sur votre siège ?" },
{ id: 'diva_hi_2', text: "Quittez-vous souvent votre siège dans des situations où vous êtes censé(e) rester assis(e) ?" },
{ id: 'diva_hi_3', text: "Vous sentez-vous souvent agité(e) ou avez-vous du mal à rester en place ?" },
{ id: 'diva_hi_4', text: "Avez-vous souvent du mal à vous adonner à des loisirs ou activités calmes de manière tranquille ?" },
{ id: 'diva_hi_5', text: "Êtes-vous souvent « sur la brèche » ou agissez-vous comme si vous étiez « monté(e) sur ressorts » ?" },
{ id: 'diva_hi_6', text: "Parlez-vous souvent trop ?" },
{ id: 'diva_hi_7', text: "Laissez-vous souvent échapper une réponse avant qu'une question ne soit terminée ?" },
{ id: 'diva_hi_8', text: "Avez-vous souvent du mal à attendre votre tour ?" },
{ id: 'diva_hi_9', text: "Interrompez-vous souvent les autres ou vous imposez-vous ?" },
];
const DIVA_CHILDHOOD = [
{ id: 'diva_child_1', text: "Avant l'âge de 12 ans, aviez-vous des difficultés à rester attentif(ve) à l'école ou lors des devoirs ?" },
{ id: 'diva_child_2', text: "Avant l'âge de 12 ans, étiez-vous considéré(e) comme un enfant rêveur, « dans la lune » ?" },
{ id: 'diva_child_3', text: "Avant l'âge de 12 ans, aviez-vous du mal à rester assis(e) ou étiez-vous agité(e) à l'école ?" },
{ id: 'diva_child_4', text: "Avant l'âge de 12 ans, aviez-vous souvent des remarques sur vos bulletins concernant l'attention ou le comportement ?" },
{ id: 'diva_child_5', text: "Avant l'âge de 12 ans, perdiez-vous souvent vos affaires scolaires ou oubliiez-vous de faire vos devoirs ?" },
];
const DIVA_IMPAIRMENT = [
{ id: 'diva_imp_1', text: "Ces difficultés ont-elles un impact négatif sur votre travail ou vos études ?", domain: "Travail/Études" },
{ id: 'diva_imp_2', text: "Ces difficultés ont-elles un impact négatif sur vos relations familiales ou amoureuses ?", domain: "Relations familiales" },
{ id: 'diva_imp_3', text: "Ces difficultés ont-elles un impact négatif sur vos relations sociales et amicales ?", domain: "Relations sociales" },
{ id: 'diva_imp_4', text: "Ces difficultés ont-elles un impact négatif sur vos loisirs et activités de temps libre ?", domain: "Loisirs" },
{ id: 'diva_imp_5', text: "Ces difficultés ont-elles un impact négatif sur votre estime de soi ou votre confiance en vous ?", domain: "Estime de soi" },
];
const EXEC_FUNCTIONS = {
activation: {
name: "Activation",
description: "Organisation, priorisation, démarrage",
questions: [
{ id: 'ef_act_1', text: "Difficulté à organiser et planifier des tâches ou projets" },
{ id: 'ef_act_2', text: "Difficulté à établir des priorités entre différentes tâches" },
{ id: 'ef_act_3', text: "Difficulté à commencer une tâche, même quand elle est importante" },
{ id: 'ef_act_4', text: "Tendance à procrastiner, reporter les tâches au lendemain" },
]
},
focus: {
name: "Attention / Focus",
description: "Attention soutenue, résistance à la distraction",
questions: [
{ id: 'ef_foc_1', text: "Difficulté à maintenir l'attention sur une tâche jusqu'à son achèvement" },
{ id: 'ef_foc_2', text: "Facilement distrait(e) par des pensées ou stimuli non pertinents" },
{ id: 'ef_foc_3', text: "Difficulté à écouter et retenir ce qui est dit lors de conversations" },
{ id: 'ef_foc_4', text: "Passer d'une activité à l'autre sans en terminer aucune" },
]
},
effort: {
name: "Effort / Énergie",
description: "Régulation de l'éveil et de la vigilance",
questions: [
{ id: 'ef_eff_1', text: "Somnolence ou fatigue mentale lors de tâches peu stimulantes" },
{ id: 'ef_eff_2', text: "Difficulté à maintenir un niveau d'énergie constant tout au long de la journée" },
{ id: 'ef_eff_3', text: "Lenteur excessive pour accomplir des tâches routinières" },
{ id: 'ef_eff_4', text: "Besoin de stimulation intense pour rester motivé(e)" },
]
},
emotion: {
name: "Régulation émotionnelle",
description: "Gestion de la frustration et des affects",
questions: [
{ id: 'ef_emo_1', text: "Réactions émotionnelles excessives ou disproportionnées" },
{ id: 'ef_emo_2', text: "Difficulté à gérer la frustration et l'irritabilité" },
{ id: 'ef_emo_3', text: "Sensibilité excessive aux critiques ou aux commentaires négatifs" },
{ id: 'ef_emo_4', text: "Fluctuations d'humeur fréquentes au cours de la journée" },
]
},
memory: {
name: "Mémoire de travail",
description: "Mémoire active et rappel",
questions: [
{ id: 'ef_mem_1', text: "Oublier ce que l'on vient de lire et devoir relire plusieurs fois" },
{ id: 'ef_mem_2', text: "Difficulté à se souvenir des consignes ou instructions données verbalement" },
{ id: 'ef_mem_3', text: "Oublier fréquemment des rendez-vous ou des tâches prévues" },
{ id: 'ef_mem_4', text: "Perdre le fil de ses pensées en milieu de phrase ou d'action" },
]
},
action: {
name: "Inhibition / Action",
description: "Contrôle des impulsions et auto-régulation",
questions: [
{ id: 'ef_act2_1', text: "Agir ou parler impulsivement sans réfléchir aux conséquences" },
{ id: 'ef_act2_2', text: "Difficulté à rester assis(e) ou à se tenir tranquille" },
{ id: 'ef_act2_3', text: "Interrompre les autres ou s'imposer dans les conversations" },
{ id: 'ef_act2_4', text: "Difficulté à contrôler ses impulsions (achats, alimentation, etc.)" },
]
}
};
const EF_OPTIONS = [
{ value: 0, label: 'Pas un problème' },
{ value: 1, label: 'Rarement' },
{ value: 2, label: 'Parfois' },
{ value: 3, label: 'Souvent' }
];
// ============================================
// APP STATE
// ============================================
const state = {
currentSection: 'home',
responses: {},
results: null
};
// ============================================
// NAVIGATION
// ============================================
const sections = ['home', 'asrs', 'diva', 'executive', 'results'];
function showSection(sectionId) {
sections.forEach(s => {
const el = document.getElementById(s);
if (el) el.classList.remove('active');
});
const target = document.getElementById(sectionId);
if (target) {
target.classList.add('active');
state.currentSection = sectionId;
updateProgress();
window.scrollTo(0, 0);
}
}
function updateProgress() {
const currentIndex = sections.indexOf(state.currentSection);
const dots = document.querySelectorAll('.step-dot');
const connectors = document.querySelectorAll('.step-connector');
const label = document.querySelector('.progress-label');
dots.forEach((dot, i) => {
dot.classList.remove('active', 'completed');
if (i < currentIndex) dot.classList.add('completed');
if (i === currentIndex) dot.classList.add('active');
});
connectors.forEach((conn, i) => {
conn.classList.remove('completed');
if (i < currentIndex) conn.classList.add('completed');
});
const labels = ['Accueil', 'ASRS (OMS)', 'Critères DSM-5', 'Fonctions Exécutives', 'Résultats'];
if (label) label.textContent = labels[currentIndex] || '';
}
// ============================================
// RENDER QUESTIONS
// ============================================
function renderASRS() {
const container = document.getElementById('asrs-questions');
let html = '';
// Part A
html += `<div class="question-group">
<h3>Partie A — Dépistage</h3>
<p class="hint">Ces 6 questions sont les plus prédictives du TDAH.</p>`;
ASRS_QUESTIONS.part_a.forEach((q, i) => {
html += renderQuestion(q, i + 1, ASRS_OPTIONS);
});
html += '</div>';
// Part B
html += `<div class="question-group">
<h3>Partie B — Questions complémentaires</h3>`;
ASRS_QUESTIONS.part_b.forEach((q, i) => {
html += renderQuestion(q, i + 7, ASRS_OPTIONS);
});
html += '</div>';
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderDIVA() {
const container = document.getElementById('diva-questions');
let html = '';
// Inattention
html += `<div class="question-group">
<h3>Critère A1 — Inattention</h3>
<p class="hint">Pour les adultes, ≥5 symptômes sont requis. Répondez Oui si le symptôme est fréquent depuis plus de 6 mois.</p>`;
DIVA_INATTENTION.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Hyperactivity
html += `<div class="question-group">
<h3>Critère A2 — Hyperactivité / Impulsivité</h3>`;
DIVA_HYPERACTIVITY.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Childhood
html += `<div class="question-group">
<h3>Critère B — Symptômes dans l'enfance</h3>
<p class="hint">Le DSM-5 exige que des symptômes aient été présents avant l'âge de 12 ans.</p>`;
DIVA_CHILDHOOD.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Impairment
html += `<div class="question-group">
<h3>Critères C/D — Retentissement fonctionnel</h3>
<p class="hint">Les symptômes doivent causer une gêne significative dans au moins 2 domaines.</p>`;
DIVA_IMPAIRMENT.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderExecutive() {
const container = document.getElementById('executive-questions');
let html = '';
Object.values(EXEC_FUNCTIONS).forEach(cluster => {
html += `<div class="question-group">
<h3>${cluster.name}</h3>
<p class="hint">${cluster.description}</p>`;
cluster.questions.forEach((q, i) => {
html += renderQuestion(q, i + 1, EF_OPTIONS, true);
});
html += '</div>';
});
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderQuestion(q, num, options, compact = false) {
const answered = state.responses[q.id] !== undefined;
return `
<div class="question ${answered ? 'answered' : ''}" data-id="${q.id}">
<p class="question-text"><span class="question-number">${num}.</span> ${q.text}</p>
<div class="options">
${options.map(opt => `
<div class="option">
<input type="radio" name="${q.id}" id="${q.id}_${opt.value}" value="${opt.value}"
${state.responses[q.id] === opt.value ? 'checked' : ''}>
<label for="${q.id}_${opt.value}">${opt.label}</label>
</div>
`).join('')}
</div>
</div>
`;
}
function renderBinaryQuestion(q, num) {
const answered = state.responses[q.id] !== undefined;
return `
<div class="question ${answered ? 'answered' : ''}" data-id="${q.id}">
<p class="question-text"><span class="question-number">${num}.</span> ${q.text}</p>
<div class="options binary">
<div class="option yes">
<input type="radio" name="${q.id}" id="${q.id}_1" value="1"
${state.responses[q.id] === 1 ? 'checked' : ''}>
<label for="${q.id}_1">Oui</label>
</div>
<div class="option no">
<input type="radio" name="${q.id}" id="${q.id}_0" value="0"
${state.responses[q.id] === 0 ? 'checked' : ''}>
<label for="${q.id}_0">Non</label>
</div>
</div>
</div>
`;
}
function attachOptionHandlers(container) {
container.querySelectorAll('input[type="radio"]').forEach(input => {
input.addEventListener('change', (e) => {
state.responses[e.target.name] = parseInt(e.target.value);
const question = e.target.closest('.question');
if (question) question.classList.add('answered');
});
});
}
// ============================================
// SCORING
// ============================================
function calculateResults() {
const results = {
asrs: scoreASRS(),
diva: scoreDIVA(),
executive: scoreExecutive()
};
// Global assessment
let positiveIndicators = 0;
if (results.asrs.screeningPositive) positiveIndicators++;
if (results.diva.meetsInattention || results.diva.meetsHyperactivity) positiveIndicators++;
if (results.executive.severity !== 'Faible') positiveIndicators++;
results.global = {
positiveIndicators,
confidence: positiveIndicators >= 3 ? 'Élevée' : positiveIndicators >= 2 ? 'Modérée' : 'Faible'
};
state.results = results;
return results;
}
function scoreASRS() {
let partAScore = 0, partAShaded = 0, partBScore = 0;
let inattention = 0, hyperactivity = 0;
const inattentionQs = [1, 2, 3, 4, 7, 8, 9, 10, 11];
ASRS_QUESTIONS.part_a.forEach(q => {
const val = state.responses[q.id] || 0;
partAScore += val;
if (val >= q.threshold) partAShaded++;
const num = parseInt(q.id.split('_')[1]);
if (inattentionQs.includes(num)) inattention += val;
else hyperactivity += val;
});
ASRS_QUESTIONS.part_b.forEach(q => {
const val = state.responses[q.id] || 0;
partBScore += val;
const num = parseInt(q.id.split('_')[1]);
if (inattentionQs.includes(num)) inattention += val;
else hyperactivity += val;
});
const screeningPositive = partAShaded >= 4;
return {
partAScore,
partAShaded,
partBScore,
total: partAScore + partBScore,
inattention,
hyperactivity,
screeningPositive,
interpretation: screeningPositive
? "Le dépistage est POSITIF. Vos réponses suggèrent des symptômes compatibles avec un TDAH chez l'adulte."
: "Le dépistage est négatif. Une évaluation clinique reste recommandée si vous avez des préoccupations."
};
}
function scoreDIVA() {
let inattentionCount = 0, hyperactivityCount = 0, childhoodCount = 0;
const impairmentDomains = [];
DIVA_INATTENTION.forEach(q => {
if (state.responses[q.id] === 1) inattentionCount++;
});
DIVA_HYPERACTIVITY.forEach(q => {
if (state.responses[q.id] === 1) hyperactivityCount++;
});
DIVA_CHILDHOOD.forEach(q => {
if (state.responses[q.id] === 1) childhoodCount++;
});
DIVA_IMPAIRMENT.forEach(q => {
if (state.responses[q.id] === 1) impairmentDomains.push(q.domain);
});
const meetsInattention = inattentionCount >= 5;
const meetsHyperactivity = hyperactivityCount >= 5;
let presentation = "Sous les seuils cliniques";
if (meetsInattention && meetsHyperactivity) presentation = "Inattention + Hyperactivité/Impulsivité";
else if (meetsInattention) presentation = "Inattention prédominante";
else if (meetsHyperactivity) presentation = "Hyperactivité/Impulsivité prédominante";
return {
inattentionCount,
hyperactivityCount,
childhoodCount,
childhoodPositive: childhoodCount >= 2,
impairmentDomains,
meetsInattention,
meetsHyperactivity,
presentation
};
}
function scoreExecutive() {
const clusterScores = {};
let total = 0, maxTotal = 0;
Object.entries(EXEC_FUNCTIONS).forEach(([key, cluster]) => {
let score = 0;
cluster.questions.forEach(q => {
score += state.responses[q.id] || 0;
});
const max = cluster.questions.length * 3;
clusterScores[cluster.name] = { score, max, percentage: Math.round((score / max) * 100) };
total += score;
maxTotal += max;
});
const percentage = Math.round((total / maxTotal) * 100);
let severity = 'Faible';
if (percentage >= 66) severity = 'Élevé';
else if (percentage >= 40) severity = 'Modéré';
const impaired = Object.entries(clusterScores)
.filter(([_, s]) => s.percentage >= 50)
.map(([name, _]) => name);
return { clusterScores, total, maxTotal, percentage, severity, impaired };
}
// ============================================
// RENDER RESULTS
// ============================================
function renderResults() {
const results = calculateResults();
const container = document.getElementById('results-content');
const asrsLevel = results.asrs.screeningPositive ? 'high' : 'low';
const divaLevel = (results.diva.meetsInattention || results.diva.meetsHyperactivity) ? 'high' : 'low';
const efLevel = results.executive.severity === 'Élevé' ? 'high' : results.executive.severity === 'Modéré' ? 'moderate' : 'low';
let html = `
<div class="summary-card">
<h2>Synthèse</h2>
<p class="summary-text">
<strong>${results.global.positiveIndicators}/3</strong> outils d'évaluation suggèrent des symptômes
${results.global.positiveIndicators >= 2 ? 'évocateurs, méritant une évaluation clinique' : 'à explorer si besoin'}.
</p>
${results.asrs.screeningPositive ? '<p>• ASRS: Seuil de dépistage <strong>atteint</strong></p>' : ''}
${results.diva.meetsInattention || results.diva.meetsHyperactivity ?
`<p>• Critères DSM-5: <strong>${results.diva.presentation}</strong></p>` : ''}
${results.executive.severity !== 'Faible' ?
`<p>• Fonctions exécutives: Difficultés de niveau <strong>${results.executive.severity}</strong></p>` : ''}
<div class="recommendation">
<strong>Recommandation:</strong>
${results.global.positiveIndicators >= 2
? "Une évaluation clinique par un spécialiste (psychiatre, neurologue) est recommandée pour explorer ces symptômes. Apportez ce rapport lors de votre consultation."
: "Si ces difficultés impactent votre quotidien, une consultation pourrait être utile pour explorer les causes possibles."}
</div>
</div>
<div class="result-card ${asrsLevel}">
<h3>1. ASRS v1.1 — Dépistage OMS</h3>
<div class="result-status ${asrsLevel}">
Seuil ${results.asrs.screeningPositive ? 'atteint' : 'non atteint'}
(${results.asrs.partAShaded}/6 critères, seuil ≥4)
</div>
<div class="scores-grid">
<div class="score-item">
<span class="score-label">Partie A</span>
<span class="score-value">${results.asrs.partAScore}/24</span>
</div>
<div class="score-item">
<span class="score-label">Partie B</span>
<span class="score-value">${results.asrs.partBScore}/48</span>
</div>
<div class="score-item">
<span class="score-label">Total</span>
<span class="score-value">${results.asrs.total}/72</span>
</div>
</div>
<div class="progress-item">
<div class="progress-label-row">
<span>Inattention</span>
<span>${results.asrs.inattention}/36</span>
</div>
<div class="progress-track">
<div class="progress-fill" style="width: ${Math.round(results.asrs.inattention / 36 * 100)}%"></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label-row">
<span>Hyperactivité/Impulsivité</span>
<span>${results.asrs.hyperactivity}/36</span>
</div>
<div class="progress-track">
<div class="progress-fill" style="width: ${Math.round(results.asrs.hyperactivity / 36 * 100)}%"></div>
</div>
</div>
</div>
<div class="result-card ${divaLevel}">
<h3>2. Critères DSM-5</h3>
<div class="result-status ${divaLevel}">
${results.diva.presentation}
</div>
<div class="scores-grid">
<div class="score-item">
<span class="score-label">Inattention (A1)</span>
<span class="score-value">${results.diva.inattentionCount}/9</span>
</div>
<div class="score-item">
<span class="score-label">Hyperactivité (A2)</span>
<span class="score-value">${results.diva.hyperactivityCount}/9</span>
</div>
<div class="score-item">
<span class="score-label">Enfance (B)</span>
<span class="score-value">${results.diva.childhoodPositive ? '✓' : '✗'}</span>
</div>
<div class="score-item">
<span class="score-label">Retentissement</span>
<span class="score-value">${results.diva.impairmentDomains.length}/5</span>
</div>
</div>
${results.diva.impairmentDomains.length > 0 ? `
<p class="interpretation">Domaines impactés: ${results.diva.impairmentDomains.join(', ')}</p>
` : ''}
</div>
<div class="result-card ${efLevel}">
<h3>3. Fonctions Exécutives</h3>
<div class="result-status ${efLevel}">
Niveau de difficulté: ${results.executive.severity} (${results.executive.percentage}%)
</div>
${Object.entries(results.executive.clusterScores).map(([name, s]) => `
<div class="progress-item">
<div class="progress-label-row">
<span>${name}</span>
<span>${s.score}/${s.max}</span>
</div>
<div class="progress-track">
<div class="progress-fill ${s.percentage >= 50 ? 'high' : ''}" style="width: ${s.percentage}%"></div>
</div>
</div>
`).join('')}
${results.executive.impaired.length > 0 ? `
<p class="interpretation">Domaines les plus impactés: ${results.executive.impaired.join(', ')}</p>
` : ''}
</div>
`;
container.innerHTML = html;
}
// ============================================
// PDF GENERATION
// ============================================
function generatePDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const results = state.results;
const now = new Date().toLocaleString('fr-FR');
let y = 20;
const margin = 20;
const pageWidth = doc.internal.pageSize.width;
// Helper functions
const addTitle = (text, size = 16) => {
doc.setFontSize(size);
doc.setFont(undefined, 'bold');
doc.text(text, margin, y);
y += size * 0.5;
};
const addText = (text, size = 11) => {
doc.setFontSize(size);
doc.setFont(undefined, 'normal');
const lines = doc.splitTextToSize(text, pageWidth - 2 * margin);
doc.text(lines, margin, y);
y += lines.length * size * 0.4 + 2;
};
const addLine = () => {
doc.setDrawColor(200);
doc.line(margin, y, pageWidth - margin, y);
y += 5;
};
const checkPage = (needed = 30) => {
if (y + needed > 280) {
doc.addPage();
y = 20;
}
};
// Title
addTitle('Rapport d\'Auto-Évaluation TDAH Adulte', 18);
y += 5;
addText(`Généré le ${now}`);
addLine();
// Disclaimer
doc.setFillColor(255, 243, 205);
doc.rect(margin, y, pageWidth - 2 * margin, 25, 'F');
y += 5;
doc.setFontSize(9);
doc.setFont(undefined, 'bold');
doc.text('AVERTISSEMENT', margin + 2, y);
y += 4;
doc.setFont(undefined, 'normal');
const disclaimer = 'Ce document est un outil d\'AUTO-ÉVALUATION et NE CONSTITUE PAS un diagnostic médical. Seul un professionnel de santé qualifié peut établir un diagnostic de TDAH.';
const disclaimerLines = doc.splitTextToSize(disclaimer, pageWidth - 2 * margin - 4);
doc.text(disclaimerLines, margin + 2, y);
y += 20;
// Summary
checkPage(50);
addTitle('Synthèse des Résultats', 14);
y += 3;
addText(`${results.global.positiveIndicators}/3 outils suggèrent des symptômes ${results.global.positiveIndicators >= 2 ? 'évocateurs, méritant une évaluation clinique' : 'à explorer si besoin'}.`);
if (results.asrs.screeningPositive) addText('• ASRS: Seuil de dépistage atteint');
if (results.diva.meetsInattention || results.diva.meetsHyperactivity)
addText(`• Critères DSM-5: ${results.diva.presentation}`);
if (results.executive.severity !== 'Faible')
addText(`• Fonctions exécutives: Difficultés de niveau ${results.executive.severity}`);
y += 5;
addLine();
// ASRS Results
checkPage(40);
addTitle('1. ASRS v1.1 (OMS/Harvard)', 12);
addText(`Seuil: ${results.asrs.screeningPositive ? 'Atteint' : 'Non atteint'} (${results.asrs.partAShaded}/6 critères)`);
addText(`Score total: ${results.asrs.total}/72 | Inattention: ${results.asrs.inattention}/36 | Hyperactivité: ${results.asrs.hyperactivity}/36`);
y += 3;
// DIVA Results
checkPage(40);
addTitle('2. Critères DSM-5', 12);
addText(`Présentation: ${results.diva.presentation}`);
addText(`Inattention: ${results.diva.inattentionCount}/9 | Hyperactivité: ${results.diva.hyperactivityCount}/9`);
addText(`Enfance: ${results.diva.childhoodPositive ? 'Confirmé' : 'Non confirmé'} | Retentissement: ${results.diva.impairmentDomains.length} domaines`);
y += 3;
// Executive Functions
checkPage(50);
addTitle('3. Fonctions Exécutives', 12);
addText(`Niveau global: ${results.executive.severity} (${results.executive.percentage}%)`);
Object.entries(results.executive.clusterScores).forEach(([name, s]) => {
addText(` • ${name}: ${s.score}/${s.max} (${s.percentage}%)`);
});
// New page for detailed responses
doc.addPage();
y = 20;
addTitle('Annexe: Réponses Détaillées', 14);
addLine();
// ASRS responses
addTitle('ASRS v1.1', 11);
[...ASRS_QUESTIONS.part_a, ...ASRS_QUESTIONS.part_b].forEach((q, i) => {
checkPage(15);
const val = state.responses[q.id];
const label = ASRS_OPTIONS.find(o => o.value === val)?.label || 'Non répondu';
doc.setFontSize(9);
const qText = doc.splitTextToSize(`${i + 1}. ${q.text}`, pageWidth - 2 * margin - 40);
doc.text(qText, margin, y);
doc.text(label, pageWidth - margin - 30, y);
y += qText.length * 4 + 2;
});
// DIVA responses
checkPage(20);
addTitle('Critères DSM-5', 11);
[...DIVA_INATTENTION, ...DIVA_HYPERACTIVITY, ...DIVA_CHILDHOOD, ...DIVA_IMPAIRMENT].forEach((q, i) => {
checkPage(12);
const val = state.responses[q.id];
doc.setFontSize(9);
const qText = doc.splitTextToSize(`${q.text}`, pageWidth - 2 * margin - 20);
doc.text(qText, margin, y);
doc.text(val === 1 ? 'Oui' : 'Non', pageWidth - margin - 15, y);
y += qText.length * 4 + 2;
});
// References page
doc.addPage();
y = 20;
addTitle('Références Scientifiques', 14);
addLine();
doc.setFontSize(10);
addText('1. Kessler RC, et al. (2005). The World Health Organization Adult ADHD Self-Report Scale (ASRS).');
addText(' Psychological Medicine, 35(2), 245-256. https://pubmed.ncbi.nlm.nih.gov/15841682/');
y += 3;
addText('2. American Psychiatric Association (2013). Diagnostic and Statistical Manual of Mental Disorders (5th ed.).');
addText(' https://www.psychiatry.org/psychiatrists/practice/dsm');
y += 3;
addText('3. Kooij JJS, et al. (2010). DIVA 2.0: Diagnostic Interview for ADHD in Adults.');
addText(' DIVA Foundation. https://www.divacenter.eu/');
y += 3;
addText('4. Brown TE (2013). A New Understanding of ADHD in Children and Adults.');
addText(' Executive Function Impairments. Routledge. https://pubmed.ncbi.nlm.nih.gov/24232170/');
// Footer on each page
const pageCount = doc.internal.getNumberOfPages();
for (let i = 1; i <= pageCount; i++) {
doc.setPage(i);
doc.setFontSize(8);
doc.setTextColor(128);
doc.text(`Page ${i}/${pageCount} | Ce document ne constitue pas un diagnostic médical`, margin, 290);
}
doc.save('evaluation_tdah.pdf');
}
// ============================================
// VALIDATION
// ============================================
function validateSection(section) {
let questions = [];
if (section === 'asrs') {
questions = [...ASRS_QUESTIONS.part_a, ...ASRS_QUESTIONS.part_b].map(q => q.id);
} else if (section === 'diva') {
questions = [
...DIVA_INATTENTION, ...DIVA_HYPERACTIVITY,
...DIVA_CHILDHOOD, ...DIVA_IMPAIRMENT
].map(q => q.id);
} else if (section === 'executive') {
questions = Object.values(EXEC_FUNCTIONS).flatMap(c => c.questions.map(q => q.id));
}
const answered = questions.filter(id => state.responses[id] !== undefined).length;
return answered === questions.length;
}
// ============================================
// EVENT HANDLERS
// ============================================
function init() {
// Render all questionnaires
renderASRS();
renderDIVA();
renderExecutive();
// Consent checkbox
document.getElementById('consent').addEventListener('change', (e) => {
document.getElementById('start-btn').disabled = !e.target.checked;
});
// Navigation buttons
document.getElementById('start-btn').addEventListener('click', () => showSection('asrs'));
document.getElementById('asrs-next').addEventListener('click', () => {
if (!validateSection('asrs')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
showSection('diva');
});
document.getElementById('diva-back').addEventListener('click', () => showSection('asrs'));
document.getElementById('diva-next').addEventListener('click', () => {
if (!validateSection('diva')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
showSection('executive');
});
document.getElementById('exec-back').addEventListener('click', () => showSection('diva'));
document.getElementById('exec-next').addEventListener('click', () => {
if (!validateSection('executive')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
renderResults();
showSection('results');
});
document.getElementById('download-pdf').addEventListener('click', generatePDF);
document.getElementById('restart').addEventListener('click', () => {
state.responses = {};
state.results = null;
renderASRS();
renderDIVA();
renderExecutive();
showSection('home');
});
// Initialize
showSection('home');
}
// Start app when DOM is ready
document.addEventListener('DOMContentLoaded', init);
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Auto-évaluation scientifique du TDAH chez l'adulte. Outils validés: ASRS (OMS), critères DSM-5, fonctions exécutives.">
<meta name="theme-color" content="#5B8A8A">
<!-- Open Graph / Social -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://plnech.github.io/adhd/">
<meta property="og:title" content="Clarté — Auto-Évaluation TDAH Adulte">
<meta property="og:description" content="Évaluez vos symptômes avec des outils scientifiquement validés: ASRS (OMS), critères DSM-5, fonctions exécutives. Gratuit, confidentiel, avec rapport PDF.">
<meta property="og:image" content="https://plnech.github.io/adhd/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Clarté — Auto-Évaluation TDAH Adulte">
<meta name="twitter:description" content="Évaluez vos symptômes avec des outils scientifiquement validés. Gratuit et confidentiel.">
<meta name="twitter:image" content="https://plnech.github.io/adhd/og-image.png">
<title>Clarté — Auto-Évaluation TDAH Adulte</title>
<link rel="stylesheet" href="style.css">
<script src="jspdf.min.js"></script>
</head>
<body>
<header>
<div class="container">
<div class="logo">
<div class="logo-icon">◎</div>
</div>
<h1>Clarté</h1>
<p class="subtitle">Auto-évaluation TDAH pour adultes</p>
</div>
</header>
<nav class="progress-bar">
<div class="container">
<div class="progress-steps">
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
</div>
<p class="progress-label">Accueil</p>
</div>
</nav>
<main class="container">
<!-- HOME -->
<section id="home" class="section active">
<div class="card">
<div class="card-header">
<h2>Bienvenue</h2>
</div>
<p>
Cette application vous permet de réaliser une auto-évaluation structurée
des symptômes du <strong>Trouble Déficit de l'Attention avec ou sans Hyperactivité (TDAH)</strong>
chez l'adulte, en utilisant des outils scientifiquement validés.
</p>
<div class="intro-grid">
<div class="intro-card">
<div class="intro-card-icon teal">📋</div>
<div>
<h4>ASRS v1.1</h4>
<p>18 questions validées par l'OMS et Harvard pour le dépistage du TDAH adulte.</p>
</div>
</div>
<div class="intro-card">
<div class="intro-card-icon coral">🔬</div>
<div>
<h4>Critères DSM-5</h4>
<p>Évaluation structurée des 18 critères diagnostiques officiels, incluant l'enfance.</p>
</div>
</div>
<div class="intro-card">
<div class="intro-card-icon lavender">🧠</div>
<div>
<h4>Fonctions Exécutives</h4>
<p>6 domaines cognitifs selon le modèle de Brown: attention, mémoire, régulation.</p>
</div>
</div>
</div>
<div class="notice warning">
<h4>⚠️ Important — Veuillez lire attentivement</h4>
<ul>
<li><strong>Cette évaluation ne constitue PAS un diagnostic médical.</strong></li>
<li>Seul un professionnel de santé qualifié (psychiatre, neurologue) peut établir un diagnostic de TDAH.</li>
<li>Les résultats sont destinés à faciliter la discussion avec votre médecin.</li>
<li>Répondez honnêtement en pensant à votre fonctionnement des <strong>6 derniers mois</strong>.</li>
<li>Durée estimée: <strong>15-20 minutes</strong>.</li>
<li>Vos données restent sur votre appareil et ne sont jamais transmises.</li>
</ul>
</div>
<label class="checkbox-wrapper">
<input type="checkbox" id="consent">
<span>
Je comprends que cette auto-évaluation ne constitue pas un diagnostic médical
et que je dois consulter un professionnel de santé pour toute évaluation diagnostique.
</span>
</label>
<div style="text-align: center;">
<button id="start-btn" class="btn btn-primary btn-large" disabled>
Commencer l'évaluation
</button>
</div>
</div>
</section>
<!-- ASRS -->
<section id="asrs" class="section">
<div class="card">
<div class="card-header">
<h2>ASRS v1.1 — Échelle d'auto-évaluation</h2>
<p class="source">Organisation Mondiale de la Santé / Harvard Medical School</p>
</div>
<div class="notice info">
<p>
Pour chaque question, indiquez à quelle fréquence vous avez ressenti ou agi
de cette manière au cours des <strong>6 derniers mois</strong>.
</p>
</div>
<div id="asrs-questions"></div>
<div class="actions">
<div></div>
<button id="asrs-next" class="btn btn-primary">
Continuer →
</button>
</div>
</div>
</section>
<!-- DIVA -->
<section id="diva" class="section">
<div class="card">
<div class="card-header">
<h2>Critères DSM-5</h2>
<p class="source">American Psychiatric Association (2013)</p>
</div>
<div class="notice info">
<p>
Répondez <strong>Oui</strong> si le symptôme est présent de manière fréquente et persistante
depuis au moins <strong>6 mois</strong>, et qu'il interfère avec votre fonctionnement.
</p>
</div>
<div id="diva-questions"></div>
<div class="actions">
<button id="diva-back" class="btn btn-secondary">
← Retour
</button>
<button id="diva-next" class="btn btn-primary">
Continuer →
</button>
</div>
</div>
</section>
<!-- EXECUTIVE FUNCTIONS -->
<section id="executive" class="section">
<div class="card">
<div class="card-header">
<h2>Fonctions Exécutives</h2>
<p class="source">Basé sur le modèle de Brown (2013)</p>
</div>
<div class="notice info">
<p>
Les fonctions exécutives sont les capacités cognitives qui nous permettent de gérer
notre attention, nos émotions et nos comportements. Indiquez à quel point chaque
difficulté est un problème pour vous <strong>actuellement</strong>.
</p>
</div>
<div id="executive-questions"></div>
<div class="actions">
<button id="exec-back" class="btn btn-secondary">
← Retour
</button>
<button id="exec-next" class="btn btn-primary">
Voir les résultats →
</button>
</div>
</div>
</section>
<!-- RESULTS -->
<section id="results" class="section">
<div class="notice warning">
<p>
<strong>Rappel:</strong> Ces résultats constituent une AUTO-ÉVALUATION et non un diagnostic médical.
Seul un professionnel de santé qualifié peut établir un diagnostic de TDAH.
</p>
</div>
<div id="results-content"></div>
<div style="text-align: center; margin-top: 2rem;">
<button id="download-pdf" class="btn btn-primary btn-large">
📄 Télécharger le rapport PDF
</button>
<p style="color: var(--ink-light); font-size: 0.9rem; margin-top: 1rem;">
Le rapport inclut une synthèse et les réponses détaillées pour votre médecin.
</p>
<button id="restart" class="btn btn-secondary" style="margin-top: 1rem;">
Recommencer l'évaluation
</button>
</div>
</section>
</main>
<footer>
<div class="container">
<p class="disclaimer">
<strong>Avertissement:</strong> Cet outil est fourni à titre informatif uniquement.
Il ne constitue pas un diagnostic médical. Consultez un professionnel de santé qualifié.
</p>
<p><strong>Références scientifiques:</strong></p>
<p style="font-size: 0.8rem; line-height: 1.8;">
<a href="https://pubmed.ncbi.nlm.nih.gov/15841682/" target="_blank" rel="noopener">ASRS v1.1 — Kessler et al. (2005)</a> •
<a href="https://www.psychiatry.org/psychiatrists/practice/dsm" target="_blank" rel="noopener">DSM-5 — APA (2013)</a> •
<a href="https://www.divacenter.eu/" target="_blank" rel="noopener">DIVA Foundation</a> •
<a href="https://pubmed.ncbi.nlm.nih.gov/24232170/" target="_blank" rel="noopener">Brown EF Model (2013)</a>
</p>
<p style="margin-top: 1rem; font-size: 0.8rem;">
<a href="https://github.com/PLNech/adhd" target="_blank" rel="noopener">Code source</a> •
MIT License © 2025 PLNech
</p>
</div>
</footer>
<script src="app.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
<svg width="1200" height="630" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Main gradient: warm cream to soft teal -->
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#FAF8F5"/>
<stop offset="30%" style="stop-color:#F0EDE8"/>
<stop offset="70%" style="stop-color:#E8F0F0"/>
<stop offset="100%" style="stop-color:#D8E8E8"/>
</linearGradient>
<!-- Accent blob gradients -->
<radialGradient id="blob1" cx="20%" cy="30%" r="40%">
<stop offset="0%" style="stop-color:#A89BBF;stop-opacity:0.15"/>
<stop offset="100%" style="stop-color:#A89BBF;stop-opacity:0"/>
</radialGradient>
<radialGradient id="blob2" cx="80%" cy="70%" r="35%">
<stop offset="0%" style="stop-color:#D4A27F;stop-opacity:0.12"/>
<stop offset="100%" style="stop-color:#D4A27F;stop-opacity:0"/>
</radialGradient>
<radialGradient id="blob3" cx="60%" cy="20%" r="30%">
<stop offset="0%" style="stop-color:#5B8A8A;stop-opacity:0.08"/>
<stop offset="100%" style="stop-color:#5B8A8A;stop-opacity:0"/>
</radialGradient>
</defs>
<!-- Background -->
<rect width="1200" height="630" fill="url(#bgGradient)"/>
<!-- Soft blobs -->
<ellipse cx="240" cy="190" rx="300" ry="250" fill="url(#blob1)"/>
<ellipse cx="960" cy="440" rx="280" ry="220" fill="url(#blob2)"/>
<ellipse cx="720" cy="126" rx="240" ry="180" fill="url(#blob3)"/>
<!-- Decorative circle/logo -->
<circle cx="600" cy="200" r="60" fill="#5B8A8A" opacity="0.9"/>
<circle cx="600" cy="200" r="45" fill="none" stroke="#FAF8F5" stroke-width="3"/>
<circle cx="600" cy="200" r="8" fill="#FAF8F5"/>
<!-- Title -->
<text x="600" y="340" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="700" fill="#3A3632">
Clarté
</text>
<!-- Subtitle -->
<text x="600" y="410" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="32" fill="#5B8A8A">
Auto-Évaluation TDAH Adulte
</text>
<!-- Tagline -->
<text x="600" y="480" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="22" fill="#6B6560">
Outils scientifiquement validés • ASRS • DSM-5 • Fonctions Exécutives
</text>
<!-- Bottom accent line -->
<rect x="400" y="530" width="400" height="4" rx="2" fill="#5B8A8A" opacity="0.6"/>
</svg>
/*
* Clarté Theme - ADHD Self-Evaluation
* A soothing, paper-like design focused on clarity and calm
*/
/* ============================================
FONTS - Atkinson Hyperlegible (self-hosted)
Designed for readability by Braille Institute
============================================ */
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Italic.woff2') format('woff2');
font-weight: 400;
font-style: italic;
font-display: swap;
}
/* ============================================
COLOR PALETTE - Warm, soothing, paper-like
============================================ */
:root {
/* Paper & Background */
--paper: #FAF8F5;
--paper-dark: #F0EDE8;
--paper-shadow: #E5E0D8;
/* Text */
--ink: #3A3632;
--ink-light: #6B6560;
--ink-faint: #9A9590;
/* Primary - Calming Teal */
--teal: #5B8A8A;
--teal-light: #7BA8A8;
--teal-dark: #4A7272;
--teal-faint: #E8F0F0;
/* Accent - Warm Coral */
--coral: #D4A27F;
--coral-light: #E8C4A8;
--coral-faint: #FDF5F0;
/* Accent - Soft Lavender */
--lavender: #A89BBF;
--lavender-faint: #F5F3F8;
/* Semantic - Purple scale for results (non-alarming) */
--sage: #7D9E83;
--sage-faint: #EFF5F0;
--purple-light: #B8A9C9;
--purple-light-faint: #F5F2F8;
--purple-mid: #9683A8;
--purple-mid-faint: #F0ECF5;
--purple-deep: #7B6B8A;
--purple-deep-faint: #EBE7F0;
/* Spacing */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
/* Radius */
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 20px;
--radius-full: 9999px;
/* Shadows - soft, warm */
--shadow-sm: 0 1px 3px rgba(58, 54, 50, 0.08);
--shadow-md: 0 4px 12px rgba(58, 54, 50, 0.1);
--shadow-lg: 0 8px 24px rgba(58, 54, 50, 0.12);
}
/* ============================================
BASE STYLES
============================================ */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: 'Atkinson', -apple-system, BlinkMacSystemFont, sans-serif;
line-height: 1.65;
color: var(--ink);
background: var(--paper);
min-height: 100vh;
/* Subtle paper texture */
background-image:
radial-gradient(ellipse at 20% 30%, rgba(168, 155, 191, 0.03) 0%, transparent 50%),
radial-gradient(ellipse at 80% 70%, rgba(212, 162, 127, 0.03) 0%, transparent 50%);
}
/* ============================================
TYPOGRAPHY
============================================ */
h1, h2, h3, h4 {
font-weight: 700;
line-height: 1.3;
color: var(--ink);
}
h1 {
font-size: 2rem;
letter-spacing: -0.02em;
}
h2 {
font-size: 1.5rem;
color: var(--teal-dark);
}
h3 {
font-size: 1.2rem;
}
p {
margin-bottom: var(--space-md);
}
a {
color: var(--teal);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color 0.2s;
}
a:hover {
border-bottom-color: var(--teal);
}
/* ============================================
LAYOUT
============================================ */
.container {
max-width: 720px;
margin: 0 auto;
padding: 0 var(--space-lg);
}
/* ============================================
HEADER
============================================ */
header {
padding: var(--space-xl) 0;
text-align: center;
border-bottom: 1px solid var(--paper-shadow);
background: linear-gradient(180deg, var(--paper) 0%, var(--teal-faint) 100%);
}
.logo {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
margin-bottom: var(--space-sm);
}
.logo-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--teal) 0%, var(--teal-dark) 100%);
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
box-shadow: var(--shadow-md);
}
header h1 {
margin-bottom: var(--space-xs);
}
header .subtitle {
color: var(--ink-light);
font-size: 1.1rem;
}
/* ============================================
PROGRESS INDICATOR
============================================ */
.progress-bar {
padding: var(--space-md) 0;
background: var(--paper);
border-bottom: 1px solid var(--paper-shadow);
position: sticky;
top: 0;
z-index: 100;
}
.progress-steps {
display: flex;
justify-content: center;
gap: var(--space-xs);
align-items: center;
}
.step-dot {
width: 12px;
height: 12px;
border-radius: var(--radius-full);
background: var(--paper-shadow);
transition: all 0.3s ease;
}
.step-dot.active {
background: var(--teal);
transform: scale(1.3);
}
.step-dot.completed {
background: var(--sage);
}
.step-connector {
width: 40px;
height: 2px;
background: var(--paper-shadow);
transition: background 0.3s;
}
.step-connector.completed {
background: var(--sage);
}
.progress-label {
text-align: center;
margin-top: var(--space-sm);
font-size: 0.85rem;
color: var(--ink-light);
}
/* ============================================
MAIN CONTENT
============================================ */
main {
padding: var(--space-2xl) 0;
min-height: 60vh;
}
.section {
display: none;
animation: fadeIn 0.4s ease;
}
.section.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* ============================================
CARDS
============================================ */
.card {
background: white;
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-lg);
box-shadow: var(--shadow-sm);
border: 1px solid var(--paper-shadow);
}
.card-header {
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 2px solid var(--teal-faint);
}
.card-header h2 {
margin-bottom: var(--space-xs);
}
.card-header .source {
font-size: 0.85rem;
color: var(--ink-faint);
font-style: italic;
}
/* ============================================
INTRO CARDS (Home)
============================================ */
.intro-grid {
display: grid;
gap: var(--space-md);
margin: var(--space-xl) 0;
}
.intro-card {
background: white;
border-radius: var(--radius-md);
padding: var(--space-lg);
border: 1px solid var(--paper-shadow);
display: flex;
gap: var(--space-md);
align-items: flex-start;
}
.intro-card-icon {
width: 44px;
height: 44px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3rem;
flex-shrink: 0;
}
.intro-card-icon.teal { background: var(--teal-faint); color: var(--teal); }
.intro-card-icon.coral { background: var(--coral-faint); color: var(--coral); }
.intro-card-icon.lavender { background: var(--lavender-faint); color: var(--lavender); }
.intro-card h4 {
margin-bottom: var(--space-xs);
}
.intro-card p {
font-size: 0.9rem;
color: var(--ink-light);
margin: 0;
}
/* ============================================
ALERTS / NOTICES
============================================ */
.notice {
padding: var(--space-lg);
border-radius: var(--radius-md);
margin-bottom: var(--space-lg);
}
.notice.warning {
background: var(--amber-faint);
border: 1px solid var(--amber);
}
.notice.info {
background: var(--teal-faint);
border: 1px solid var(--teal-light);
}
.notice h4 {
margin-bottom: var(--space-sm);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.notice ul {
margin-left: var(--space-lg);
color: var(--ink-light);
}
.notice li {
margin-bottom: var(--space-xs);
}
/* ============================================
QUESTIONS
============================================ */
.question-group {
margin-bottom: var(--space-xl);
}
.question-group h3 {
color: var(--teal-dark);
margin-bottom: var(--space-md);
padding-bottom: var(--space-sm);
border-bottom: 1px solid var(--paper-shadow);
}
.question-group .hint {
font-size: 0.85rem;
color: var(--ink-faint);
font-style: italic;
margin-bottom: var(--space-md);
}
.question {
background: var(--paper);
border-radius: var(--radius-md);
padding: var(--space-lg);
margin-bottom: var(--space-md);
border: 1px solid transparent;
transition: border-color 0.2s, box-shadow 0.2s;
}
.question:hover {
border-color: var(--paper-shadow);
}
.question.answered {
border-color: var(--sage);
background: var(--sage-faint);
}
.question-text {
font-weight: 500;
margin-bottom: var(--space-md);
line-height: 1.5;
}
.question-number {
color: var(--teal);
font-weight: 700;
}
/* ============================================
RESPONSE OPTIONS
============================================ */
.options {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
}
.option {
position: relative;
}
.option input {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.option label {
display: inline-block;
padding: var(--space-sm) var(--space-md);
background: white;
border: 2px solid var(--paper-shadow);
border-radius: var(--radius-full);
cursor: pointer;
font-size: 0.9rem;
transition: all 0.2s;
}
.option label:hover {
border-color: var(--teal-light);
background: var(--teal-faint);
}
.option input:checked + label {
background: var(--teal);
border-color: var(--teal);
color: white;
}
/* Binary options (Yes/No) */
.options.binary {
gap: var(--space-md);
}
.options.binary .option label {
min-width: 80px;
text-align: center;
}
.options.binary .option.yes input:checked + label {
background: var(--coral);
border-color: var(--coral);
}
.options.binary .option.no input:checked + label {
background: var(--sage);
border-color: var(--sage);
}
/* ============================================
BUTTONS
============================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-sm);
padding: var(--space-md) var(--space-xl);
border-radius: var(--radius-full);
font-family: inherit;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
}
.btn-primary {
background: var(--teal);
color: white;
}
.btn-primary:hover {
background: var(--teal-dark);
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.btn-secondary {
background: white;
color: var(--ink);
border-color: var(--paper-shadow);
}
.btn-secondary:hover {
border-color: var(--teal);
color: var(--teal);
}
.btn-large {
padding: var(--space-lg) var(--space-2xl);
font-size: 1.1rem;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: var(--space-xl);
padding-top: var(--space-lg);
border-top: 1px solid var(--paper-shadow);
}
/* ============================================
CHECKBOX (Consent)
============================================ */
.checkbox-wrapper {
display: flex;
align-items: flex-start;
gap: var(--space-md);
padding: var(--space-lg);
background: var(--paper);
border-radius: var(--radius-md);
margin-bottom: var(--space-lg);
cursor: pointer;
}
.checkbox-wrapper input[type="checkbox"] {
width: 22px;
height: 22px;
margin-top: 2px;
accent-color: var(--teal);
cursor: pointer;
}
.checkbox-wrapper span {
font-size: 0.95rem;
line-height: 1.5;
}
/* ============================================
RESULTS
============================================ */
.summary-card {
background: linear-gradient(135deg, var(--teal-faint) 0%, var(--lavender-faint) 100%);
border: 2px solid var(--teal);
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-xl);
}
.summary-card h2 {
margin-bottom: var(--space-md);
}
.summary-text {
font-size: 1.05rem;
line-height: 1.7;
margin-bottom: var(--space-md);
}
.recommendation {
background: white;
padding: var(--space-md);
border-radius: var(--radius-md);
border-left: 4px solid var(--teal);
}
/* Result Cards */
.result-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-lg);
border: 1px solid var(--paper-shadow);
border-left: 5px solid var(--paper-shadow);
}
.result-card.high {
border-left-color: var(--purple-deep);
}
.result-card.low {
border-left-color: var(--sage);
}
.result-card.moderate {
border-left-color: var(--purple-mid);
}
.result-card h3 {
margin-bottom: var(--space-md);
}
.result-status {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border-radius: var(--radius-full);
font-weight: 600;
font-size: 0.9rem;
margin-bottom: var(--space-md);
}
.result-status.high {
background: var(--purple-deep-faint);
color: var(--purple-deep);
}
.result-status.low {
background: var(--sage-faint);
color: var(--sage);
}
.result-status.moderate {
background: var(--purple-mid-faint);
color: var(--purple-mid);
}
/* Score Grid */
.scores-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: var(--space-md);
margin: var(--space-md) 0;
}
.score-item {
background: var(--paper);
padding: var(--space-md);
border-radius: var(--radius-md);
text-align: center;
}
.score-label {
font-size: 0.8rem;
color: var(--ink-light);
display: block;
margin-bottom: var(--space-xs);
}
.score-value {
font-size: 1.4rem;
font-weight: 700;
color: var(--teal-dark);
}
/* Progress Bars */
.progress-item {
margin-bottom: var(--space-md);
}
.progress-label-row {
display: flex;
justify-content: space-between;
margin-bottom: var(--space-xs);
font-size: 0.9rem;
}
.progress-track {
height: 10px;
background: var(--paper-shadow);
border-radius: var(--radius-full);
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--teal);
border-radius: var(--radius-full);
transition: width 0.5s ease;
}
.progress-fill.high {
background: var(--purple-deep);
}
.progress-fill.moderate {
background: var(--purple-mid);
}
/* Interpretation */
.interpretation {
margin-top: var(--space-md);
padding-top: var(--space-md);
border-top: 1px dashed var(--paper-shadow);
font-style: italic;
color: var(--ink-light);
}
/* ============================================
FOOTER
============================================ */
footer {
padding: var(--space-xl) 0;
background: var(--paper-dark);
border-top: 1px solid var(--paper-shadow);
text-align: center;
}
footer p {
font-size: 0.85rem;
color: var(--ink-light);
margin-bottom: var(--space-sm);
}
footer .disclaimer {
max-width: 600px;
margin: 0 auto var(--space-md);
}
/* ============================================
RESPONSIVE
============================================ */
@media (max-width: 600px) {
html { font-size: 15px; }
.container { padding: 0 var(--space-md); }
.card { padding: var(--space-lg); }
.options { flex-direction: column; }
.option label { display: block; text-align: center; }
.actions { flex-direction: column; gap: var(--space-md); }
.btn { width: 100%; }
.scores-grid { grid-template-columns: repeat(2, 1fr); }
}
/* ============================================
PRINT STYLES
============================================ */
@media print {
body { background: white; }
.progress-bar, .actions, footer { display: none; }
.section { display: block !important; page-break-inside: avoid; }
}
/**
* Clarté - ADHD Self-Evaluation App
* Client-side questionnaire logic and PDF generation
*/
// ============================================
// QUESTIONNAIRE DATA
// ============================================
const ASRS_QUESTIONS = {
part_a: [
{ id: 'asrs_1', text: "À quelle fréquence avez-vous des difficultés à finaliser les derniers détails d'un projet, une fois que les parties les plus stimulantes ont été réalisées ?", threshold: 2 },
{ id: 'asrs_2', text: "À quelle fréquence avez-vous des difficultés à mettre de l'ordre lorsque vous devez effectuer une tâche qui requiert de l'organisation ?", threshold: 2 },
{ id: 'asrs_3', text: "À quelle fréquence avez-vous des difficultés à vous souvenir de vos rendez-vous ou de vos obligations ?", threshold: 2 },
{ id: 'asrs_4', text: "Lorsque vous devez effectuer une tâche qui demande beaucoup de réflexion, à quelle fréquence évitez-vous ou retardez-vous le moment de commencer ?", threshold: 3 },
{ id: 'asrs_5', text: "À quelle fréquence remuez-vous ou tortillez-vous les mains ou les pieds lorsque vous devez rester assis(e) pendant une longue période ?", threshold: 3 },
{ id: 'asrs_6', text: "À quelle fréquence vous sentez-vous excessivement actif(ve) et poussé(e) à faire des choses, comme si vous étiez mû(e) par un moteur ?", threshold: 3 },
],
part_b: [
{ id: 'asrs_7', text: "À quelle fréquence faites-vous des erreurs d'inattention lorsque vous devez travailler sur un projet ennuyeux ou difficile ?" },
{ id: 'asrs_8', text: "À quelle fréquence avez-vous des difficultés à maintenir votre attention lorsque vous effectuez un travail ennuyeux ou répétitif ?" },
{ id: 'asrs_9', text: "À quelle fréquence avez-vous des difficultés à vous concentrer sur ce que les gens vous disent, même lorsqu'ils s'adressent directement à vous ?" },
{ id: 'asrs_10', text: "À quelle fréquence égarez-vous ou avez-vous du mal à retrouver des objets à la maison ou au travail ?" },
{ id: 'asrs_11', text: "À quelle fréquence êtes-vous distrait(e) par l'activité ou le bruit autour de vous ?" },
{ id: 'asrs_12', text: "À quelle fréquence quittez-vous votre siège lors de réunions ou dans d'autres situations où vous êtes censé(e) rester assis(e) ?" },
{ id: 'asrs_13', text: "À quelle fréquence vous sentez-vous agité(e) ou remuant(e) ?" },
{ id: 'asrs_14', text: "À quelle fréquence avez-vous des difficultés à vous détendre et à vous relaxer lorsque vous avez du temps libre ?" },
{ id: 'asrs_15', text: "À quelle fréquence vous trouvez-vous à parler trop en situation sociale ?" },
{ id: 'asrs_16', text: "Lors d'une conversation, à quelle fréquence finissez-vous les phrases des personnes avec qui vous parlez avant qu'elles ne puissent les terminer elles-mêmes ?" },
{ id: 'asrs_17', text: "À quelle fréquence avez-vous des difficultés à attendre votre tour dans des situations qui l'exigent ?" },
{ id: 'asrs_18', text: "À quelle fréquence interrompez-vous les autres lorsqu'ils sont occupés ?" },
]
};
const ASRS_OPTIONS = [
{ value: 0, label: 'Jamais' },
{ value: 1, label: 'Rarement' },
{ value: 2, label: 'Parfois' },
{ value: 3, label: 'Souvent' },
{ value: 4, label: 'Très souvent' }
];
const DIVA_INATTENTION = [
{ id: 'diva_ia_1', text: "Avez-vous souvent du mal à prêter attention aux détails ou faites-vous des erreurs d'inattention dans votre travail ou d'autres activités ? (ex: négliger des détails, travail inexact)" },
{ id: 'diva_ia_2', text: "Avez-vous souvent du mal à maintenir votre attention sur des tâches ou des activités ? (ex: difficulté à rester concentré pendant les réunions, lectures)" },
{ id: 'diva_ia_3', text: "Avez-vous souvent l'impression de ne pas écouter quand on vous parle directement ? (ex: esprit ailleurs, même sans distraction évidente)" },
{ id: 'diva_ia_4', text: "Avez-vous souvent du mal à suivre les instructions jusqu'au bout et à terminer vos tâches professionnelles ou obligations ?" },
{ id: 'diva_ia_5', text: "Avez-vous souvent du mal à organiser vos tâches et activités ? (ex: difficulté à gérer le temps, respecter les délais)" },
{ id: 'diva_ia_6', text: "Évitez-vous souvent, ou êtes-vous réticent(e) à vous engager dans des tâches qui nécessitent un effort mental soutenu ?" },
{ id: 'diva_ia_7', text: "Perdez-vous souvent des objets nécessaires à vos activités ? (ex: clés, portefeuille, téléphone, documents)" },
{ id: 'diva_ia_8', text: "Êtes-vous souvent facilement distrait(e) par des stimuli externes ou des pensées sans rapport ?" },
{ id: 'diva_ia_9', text: "Êtes-vous souvent oublieux(se) dans la vie quotidienne ? (ex: oublier de rappeler, payer des factures, honorer des rendez-vous)" },
];
const DIVA_HYPERACTIVITY = [
{ id: 'diva_hi_1', text: "Remuez-vous souvent les mains ou les pieds, ou vous tortillez-vous sur votre siège ?" },
{ id: 'diva_hi_2', text: "Quittez-vous souvent votre siège dans des situations où vous êtes censé(e) rester assis(e) ?" },
{ id: 'diva_hi_3', text: "Vous sentez-vous souvent agité(e) ou avez-vous du mal à rester en place ?" },
{ id: 'diva_hi_4', text: "Avez-vous souvent du mal à vous adonner à des loisirs ou activités calmes de manière tranquille ?" },
{ id: 'diva_hi_5', text: "Êtes-vous souvent « sur la brèche » ou agissez-vous comme si vous étiez « monté(e) sur ressorts » ?" },
{ id: 'diva_hi_6', text: "Parlez-vous souvent trop ?" },
{ id: 'diva_hi_7', text: "Laissez-vous souvent échapper une réponse avant qu'une question ne soit terminée ?" },
{ id: 'diva_hi_8', text: "Avez-vous souvent du mal à attendre votre tour ?" },
{ id: 'diva_hi_9', text: "Interrompez-vous souvent les autres ou vous imposez-vous ?" },
];
const DIVA_CHILDHOOD = [
{ id: 'diva_child_1', text: "Avant l'âge de 12 ans, aviez-vous des difficultés à rester attentif(ve) à l'école ou lors des devoirs ?" },
{ id: 'diva_child_2', text: "Avant l'âge de 12 ans, étiez-vous considéré(e) comme un enfant rêveur, « dans la lune » ?" },
{ id: 'diva_child_3', text: "Avant l'âge de 12 ans, aviez-vous du mal à rester assis(e) ou étiez-vous agité(e) à l'école ?" },
{ id: 'diva_child_4', text: "Avant l'âge de 12 ans, aviez-vous souvent des remarques sur vos bulletins concernant l'attention ou le comportement ?" },
{ id: 'diva_child_5', text: "Avant l'âge de 12 ans, perdiez-vous souvent vos affaires scolaires ou oubliiez-vous de faire vos devoirs ?" },
];
const DIVA_IMPAIRMENT = [
{ id: 'diva_imp_1', text: "Ces difficultés ont-elles un impact négatif sur votre travail ou vos études ?", domain: "Travail/Études" },
{ id: 'diva_imp_2', text: "Ces difficultés ont-elles un impact négatif sur vos relations familiales ou amoureuses ?", domain: "Relations familiales" },
{ id: 'diva_imp_3', text: "Ces difficultés ont-elles un impact négatif sur vos relations sociales et amicales ?", domain: "Relations sociales" },
{ id: 'diva_imp_4', text: "Ces difficultés ont-elles un impact négatif sur vos loisirs et activités de temps libre ?", domain: "Loisirs" },
{ id: 'diva_imp_5', text: "Ces difficultés ont-elles un impact négatif sur votre estime de soi ou votre confiance en vous ?", domain: "Estime de soi" },
];
const EXEC_FUNCTIONS = {
activation: {
name: "Activation",
description: "Organisation, priorisation, démarrage",
questions: [
{ id: 'ef_act_1', text: "Difficulté à organiser et planifier des tâches ou projets" },
{ id: 'ef_act_2', text: "Difficulté à établir des priorités entre différentes tâches" },
{ id: 'ef_act_3', text: "Difficulté à commencer une tâche, même quand elle est importante" },
{ id: 'ef_act_4', text: "Tendance à procrastiner, reporter les tâches au lendemain" },
]
},
focus: {
name: "Attention / Focus",
description: "Attention soutenue, résistance à la distraction",
questions: [
{ id: 'ef_foc_1', text: "Difficulté à maintenir l'attention sur une tâche jusqu'à son achèvement" },
{ id: 'ef_foc_2', text: "Facilement distrait(e) par des pensées ou stimuli non pertinents" },
{ id: 'ef_foc_3', text: "Difficulté à écouter et retenir ce qui est dit lors de conversations" },
{ id: 'ef_foc_4', text: "Passer d'une activité à l'autre sans en terminer aucune" },
]
},
effort: {
name: "Effort / Énergie",
description: "Régulation de l'éveil et de la vigilance",
questions: [
{ id: 'ef_eff_1', text: "Somnolence ou fatigue mentale lors de tâches peu stimulantes" },
{ id: 'ef_eff_2', text: "Difficulté à maintenir un niveau d'énergie constant tout au long de la journée" },
{ id: 'ef_eff_3', text: "Lenteur excessive pour accomplir des tâches routinières" },
{ id: 'ef_eff_4', text: "Besoin de stimulation intense pour rester motivé(e)" },
]
},
emotion: {
name: "Régulation émotionnelle",
description: "Gestion de la frustration et des affects",
questions: [
{ id: 'ef_emo_1', text: "Réactions émotionnelles excessives ou disproportionnées" },
{ id: 'ef_emo_2', text: "Difficulté à gérer la frustration et l'irritabilité" },
{ id: 'ef_emo_3', text: "Sensibilité excessive aux critiques ou aux commentaires négatifs" },
{ id: 'ef_emo_4', text: "Fluctuations d'humeur fréquentes au cours de la journée" },
]
},
memory: {
name: "Mémoire de travail",
description: "Mémoire active et rappel",
questions: [
{ id: 'ef_mem_1', text: "Oublier ce que l'on vient de lire et devoir relire plusieurs fois" },
{ id: 'ef_mem_2', text: "Difficulté à se souvenir des consignes ou instructions données verbalement" },
{ id: 'ef_mem_3', text: "Oublier fréquemment des rendez-vous ou des tâches prévues" },
{ id: 'ef_mem_4', text: "Perdre le fil de ses pensées en milieu de phrase ou d'action" },
]
},
action: {
name: "Inhibition / Action",
description: "Contrôle des impulsions et auto-régulation",
questions: [
{ id: 'ef_act2_1', text: "Agir ou parler impulsivement sans réfléchir aux conséquences" },
{ id: 'ef_act2_2', text: "Difficulté à rester assis(e) ou à se tenir tranquille" },
{ id: 'ef_act2_3', text: "Interrompre les autres ou s'imposer dans les conversations" },
{ id: 'ef_act2_4', text: "Difficulté à contrôler ses impulsions (achats, alimentation, etc.)" },
]
}
};
const EF_OPTIONS = [
{ value: 0, label: 'Pas un problème' },
{ value: 1, label: 'Rarement' },
{ value: 2, label: 'Parfois' },
{ value: 3, label: 'Souvent' }
];
// ============================================
// APP STATE
// ============================================
const state = {
currentSection: 'home',
responses: {},
results: null
};
// ============================================
// NAVIGATION
// ============================================
const sections = ['home', 'asrs', 'diva', 'executive', 'results'];
function showSection(sectionId) {
sections.forEach(s => {
const el = document.getElementById(s);
if (el) el.classList.remove('active');
});
const target = document.getElementById(sectionId);
if (target) {
target.classList.add('active');
state.currentSection = sectionId;
updateProgress();
window.scrollTo(0, 0);
}
}
function updateProgress() {
const currentIndex = sections.indexOf(state.currentSection);
const dots = document.querySelectorAll('.step-dot');
const connectors = document.querySelectorAll('.step-connector');
const label = document.querySelector('.progress-label');
dots.forEach((dot, i) => {
dot.classList.remove('active', 'completed');
if (i < currentIndex) dot.classList.add('completed');
if (i === currentIndex) dot.classList.add('active');
});
connectors.forEach((conn, i) => {
conn.classList.remove('completed');
if (i < currentIndex) conn.classList.add('completed');
});
const labels = ['Accueil', 'ASRS (OMS)', 'Critères DSM-5', 'Fonctions Exécutives', 'Résultats'];
if (label) label.textContent = labels[currentIndex] || '';
}
// ============================================
// RENDER QUESTIONS
// ============================================
function renderASRS() {
const container = document.getElementById('asrs-questions');
let html = '';
// Part A
html += `<div class="question-group">
<h3>Partie A — Dépistage</h3>
<p class="hint">Ces 6 questions sont les plus prédictives du TDAH.</p>`;
ASRS_QUESTIONS.part_a.forEach((q, i) => {
html += renderQuestion(q, i + 1, ASRS_OPTIONS);
});
html += '</div>';
// Part B
html += `<div class="question-group">
<h3>Partie B — Questions complémentaires</h3>`;
ASRS_QUESTIONS.part_b.forEach((q, i) => {
html += renderQuestion(q, i + 7, ASRS_OPTIONS);
});
html += '</div>';
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderDIVA() {
const container = document.getElementById('diva-questions');
let html = '';
// Inattention
html += `<div class="question-group">
<h3>Critère A1 — Inattention</h3>
<p class="hint">Pour les adultes, ≥5 symptômes sont requis. Répondez Oui si le symptôme est fréquent depuis plus de 6 mois.</p>`;
DIVA_INATTENTION.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Hyperactivity
html += `<div class="question-group">
<h3>Critère A2 — Hyperactivité / Impulsivité</h3>`;
DIVA_HYPERACTIVITY.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Childhood
html += `<div class="question-group">
<h3>Critère B — Symptômes dans l'enfance</h3>
<p class="hint">Le DSM-5 exige que des symptômes aient été présents avant l'âge de 12 ans.</p>`;
DIVA_CHILDHOOD.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
// Impairment
html += `<div class="question-group">
<h3>Critères C/D — Retentissement fonctionnel</h3>
<p class="hint">Les symptômes doivent causer une gêne significative dans au moins 2 domaines.</p>`;
DIVA_IMPAIRMENT.forEach((q, i) => {
html += renderBinaryQuestion(q, i + 1);
});
html += '</div>';
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderExecutive() {
const container = document.getElementById('executive-questions');
let html = '';
Object.values(EXEC_FUNCTIONS).forEach(cluster => {
html += `<div class="question-group">
<h3>${cluster.name}</h3>
<p class="hint">${cluster.description}</p>`;
cluster.questions.forEach((q, i) => {
html += renderQuestion(q, i + 1, EF_OPTIONS, true);
});
html += '</div>';
});
container.innerHTML = html;
attachOptionHandlers(container);
}
function renderQuestion(q, num, options, compact = false) {
const answered = state.responses[q.id] !== undefined;
return `
<div class="question ${answered ? 'answered' : ''}" data-id="${q.id}">
<p class="question-text"><span class="question-number">${num}.</span> ${q.text}</p>
<div class="options">
${options.map(opt => `
<div class="option">
<input type="radio" name="${q.id}" id="${q.id}_${opt.value}" value="${opt.value}"
${state.responses[q.id] === opt.value ? 'checked' : ''}>
<label for="${q.id}_${opt.value}">${opt.label}</label>
</div>
`).join('')}
</div>
</div>
`;
}
function renderBinaryQuestion(q, num) {
const answered = state.responses[q.id] !== undefined;
return `
<div class="question ${answered ? 'answered' : ''}" data-id="${q.id}">
<p class="question-text"><span class="question-number">${num}.</span> ${q.text}</p>
<div class="options binary">
<div class="option yes">
<input type="radio" name="${q.id}" id="${q.id}_1" value="1"
${state.responses[q.id] === 1 ? 'checked' : ''}>
<label for="${q.id}_1">Oui</label>
</div>
<div class="option no">
<input type="radio" name="${q.id}" id="${q.id}_0" value="0"
${state.responses[q.id] === 0 ? 'checked' : ''}>
<label for="${q.id}_0">Non</label>
</div>
</div>
</div>
`;
}
function attachOptionHandlers(container) {
container.querySelectorAll('input[type="radio"]').forEach(input => {
input.addEventListener('change', (e) => {
state.responses[e.target.name] = parseInt(e.target.value);
const question = e.target.closest('.question');
if (question) question.classList.add('answered');
});
});
}
// ============================================
// SCORING
// ============================================
function calculateResults() {
const results = {
asrs: scoreASRS(),
diva: scoreDIVA(),
executive: scoreExecutive()
};
// Global assessment
let positiveIndicators = 0;
if (results.asrs.screeningPositive) positiveIndicators++;
if (results.diva.meetsInattention || results.diva.meetsHyperactivity) positiveIndicators++;
if (results.executive.severity !== 'Faible') positiveIndicators++;
results.global = {
positiveIndicators,
confidence: positiveIndicators >= 3 ? 'Élevée' : positiveIndicators >= 2 ? 'Modérée' : 'Faible'
};
state.results = results;
return results;
}
function scoreASRS() {
let partAScore = 0, partAShaded = 0, partBScore = 0;
let inattention = 0, hyperactivity = 0;
const inattentionQs = [1, 2, 3, 4, 7, 8, 9, 10, 11];
ASRS_QUESTIONS.part_a.forEach(q => {
const val = state.responses[q.id] || 0;
partAScore += val;
if (val >= q.threshold) partAShaded++;
const num = parseInt(q.id.split('_')[1]);
if (inattentionQs.includes(num)) inattention += val;
else hyperactivity += val;
});
ASRS_QUESTIONS.part_b.forEach(q => {
const val = state.responses[q.id] || 0;
partBScore += val;
const num = parseInt(q.id.split('_')[1]);
if (inattentionQs.includes(num)) inattention += val;
else hyperactivity += val;
});
const screeningPositive = partAShaded >= 4;
return {
partAScore,
partAShaded,
partBScore,
total: partAScore + partBScore,
inattention,
hyperactivity,
screeningPositive,
interpretation: screeningPositive
? "Le dépistage est POSITIF. Vos réponses suggèrent des symptômes compatibles avec un TDAH chez l'adulte."
: "Le dépistage est négatif. Une évaluation clinique reste recommandée si vous avez des préoccupations."
};
}
function scoreDIVA() {
let inattentionCount = 0, hyperactivityCount = 0, childhoodCount = 0;
const impairmentDomains = [];
DIVA_INATTENTION.forEach(q => {
if (state.responses[q.id] === 1) inattentionCount++;
});
DIVA_HYPERACTIVITY.forEach(q => {
if (state.responses[q.id] === 1) hyperactivityCount++;
});
DIVA_CHILDHOOD.forEach(q => {
if (state.responses[q.id] === 1) childhoodCount++;
});
DIVA_IMPAIRMENT.forEach(q => {
if (state.responses[q.id] === 1) impairmentDomains.push(q.domain);
});
const meetsInattention = inattentionCount >= 5;
const meetsHyperactivity = hyperactivityCount >= 5;
let presentation = "Sous les seuils cliniques";
if (meetsInattention && meetsHyperactivity) presentation = "Inattention + Hyperactivité/Impulsivité";
else if (meetsInattention) presentation = "Inattention prédominante";
else if (meetsHyperactivity) presentation = "Hyperactivité/Impulsivité prédominante";
return {
inattentionCount,
hyperactivityCount,
childhoodCount,
childhoodPositive: childhoodCount >= 2,
impairmentDomains,
meetsInattention,
meetsHyperactivity,
presentation
};
}
function scoreExecutive() {
const clusterScores = {};
let total = 0, maxTotal = 0;
Object.entries(EXEC_FUNCTIONS).forEach(([key, cluster]) => {
let score = 0;
cluster.questions.forEach(q => {
score += state.responses[q.id] || 0;
});
const max = cluster.questions.length * 3;
clusterScores[cluster.name] = { score, max, percentage: Math.round((score / max) * 100) };
total += score;
maxTotal += max;
});
const percentage = Math.round((total / maxTotal) * 100);
let severity = 'Faible';
if (percentage >= 66) severity = 'Élevé';
else if (percentage >= 40) severity = 'Modéré';
const impaired = Object.entries(clusterScores)
.filter(([_, s]) => s.percentage >= 50)
.map(([name, _]) => name);
return { clusterScores, total, maxTotal, percentage, severity, impaired };
}
// ============================================
// RENDER RESULTS
// ============================================
function renderResults() {
const results = calculateResults();
const container = document.getElementById('results-content');
const asrsLevel = results.asrs.screeningPositive ? 'high' : 'low';
const divaLevel = (results.diva.meetsInattention || results.diva.meetsHyperactivity) ? 'high' : 'low';
const efLevel = results.executive.severity === 'Élevé' ? 'high' : results.executive.severity === 'Modéré' ? 'moderate' : 'low';
let html = `
<div class="summary-card">
<h2>Synthèse</h2>
<p class="summary-text">
<strong>${results.global.positiveIndicators}/3</strong> outils d'évaluation suggèrent des symptômes
${results.global.positiveIndicators >= 2 ? 'évocateurs, méritant une évaluation clinique' : 'à explorer si besoin'}.
</p>
${results.asrs.screeningPositive ? '<p>• ASRS: Seuil de dépistage <strong>atteint</strong></p>' : ''}
${results.diva.meetsInattention || results.diva.meetsHyperactivity ?
`<p>• Critères DSM-5: <strong>${results.diva.presentation}</strong></p>` : ''}
${results.executive.severity !== 'Faible' ?
`<p>• Fonctions exécutives: Difficultés de niveau <strong>${results.executive.severity}</strong></p>` : ''}
<div class="recommendation">
<strong>Recommandation:</strong>
${results.global.positiveIndicators >= 2
? "Une évaluation clinique par un spécialiste (psychiatre, neurologue) est recommandée pour explorer ces symptômes. Apportez ce rapport lors de votre consultation."
: "Si ces difficultés impactent votre quotidien, une consultation pourrait être utile pour explorer les causes possibles."}
</div>
</div>
<div class="result-card ${asrsLevel}">
<h3>1. ASRS v1.1 — Dépistage OMS</h3>
<div class="result-status ${asrsLevel}">
Seuil ${results.asrs.screeningPositive ? 'atteint' : 'non atteint'}
(${results.asrs.partAShaded}/6 critères, seuil ≥4)
</div>
<div class="scores-grid">
<div class="score-item">
<span class="score-label">Partie A</span>
<span class="score-value">${results.asrs.partAScore}/24</span>
</div>
<div class="score-item">
<span class="score-label">Partie B</span>
<span class="score-value">${results.asrs.partBScore}/48</span>
</div>
<div class="score-item">
<span class="score-label">Total</span>
<span class="score-value">${results.asrs.total}/72</span>
</div>
</div>
<div class="progress-item">
<div class="progress-label-row">
<span>Inattention</span>
<span>${results.asrs.inattention}/36</span>
</div>
<div class="progress-track">
<div class="progress-fill" style="width: ${Math.round(results.asrs.inattention / 36 * 100)}%"></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label-row">
<span>Hyperactivité/Impulsivité</span>
<span>${results.asrs.hyperactivity}/36</span>
</div>
<div class="progress-track">
<div class="progress-fill" style="width: ${Math.round(results.asrs.hyperactivity / 36 * 100)}%"></div>
</div>
</div>
</div>
<div class="result-card ${divaLevel}">
<h3>2. Critères DSM-5</h3>
<div class="result-status ${divaLevel}">
${results.diva.presentation}
</div>
<div class="scores-grid">
<div class="score-item">
<span class="score-label">Inattention (A1)</span>
<span class="score-value">${results.diva.inattentionCount}/9</span>
</div>
<div class="score-item">
<span class="score-label">Hyperactivité (A2)</span>
<span class="score-value">${results.diva.hyperactivityCount}/9</span>
</div>
<div class="score-item">
<span class="score-label">Enfance (B)</span>
<span class="score-value">${results.diva.childhoodPositive ? '✓' : '✗'}</span>
</div>
<div class="score-item">
<span class="score-label">Retentissement</span>
<span class="score-value">${results.diva.impairmentDomains.length}/5</span>
</div>
</div>
${results.diva.impairmentDomains.length > 0 ? `
<p class="interpretation">Domaines impactés: ${results.diva.impairmentDomains.join(', ')}</p>
` : ''}
</div>
<div class="result-card ${efLevel}">
<h3>3. Fonctions Exécutives</h3>
<div class="result-status ${efLevel}">
Niveau de difficulté: ${results.executive.severity} (${results.executive.percentage}%)
</div>
${Object.entries(results.executive.clusterScores).map(([name, s]) => `
<div class="progress-item">
<div class="progress-label-row">
<span>${name}</span>
<span>${s.score}/${s.max}</span>
</div>
<div class="progress-track">
<div class="progress-fill ${s.percentage >= 50 ? 'high' : ''}" style="width: ${s.percentage}%"></div>
</div>
</div>
`).join('')}
${results.executive.impaired.length > 0 ? `
<p class="interpretation">Domaines les plus impactés: ${results.executive.impaired.join(', ')}</p>
` : ''}
</div>
`;
container.innerHTML = html;
}
// ============================================
// PDF GENERATION
// ============================================
function generatePDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const results = state.results;
const now = new Date().toLocaleString('fr-FR');
let y = 20;
const margin = 20;
const pageWidth = doc.internal.pageSize.width;
// Helper functions
const addTitle = (text, size = 16) => {
doc.setFontSize(size);
doc.setFont(undefined, 'bold');
doc.text(text, margin, y);
y += size * 0.5;
};
const addText = (text, size = 11) => {
doc.setFontSize(size);
doc.setFont(undefined, 'normal');
const lines = doc.splitTextToSize(text, pageWidth - 2 * margin);
doc.text(lines, margin, y);
y += lines.length * size * 0.4 + 2;
};
const addLine = () => {
doc.setDrawColor(200);
doc.line(margin, y, pageWidth - margin, y);
y += 5;
};
const checkPage = (needed = 30) => {
if (y + needed > 280) {
doc.addPage();
y = 20;
}
};
// Title
addTitle('Rapport d\'Auto-Évaluation TDAH Adulte', 18);
y += 5;
addText(`Généré le ${now}`);
addLine();
// Disclaimer
doc.setFillColor(255, 243, 205);
doc.rect(margin, y, pageWidth - 2 * margin, 25, 'F');
y += 5;
doc.setFontSize(9);
doc.setFont(undefined, 'bold');
doc.text('AVERTISSEMENT', margin + 2, y);
y += 4;
doc.setFont(undefined, 'normal');
const disclaimer = 'Ce document est un outil d\'AUTO-ÉVALUATION et NE CONSTITUE PAS un diagnostic médical. Seul un professionnel de santé qualifié peut établir un diagnostic de TDAH.';
const disclaimerLines = doc.splitTextToSize(disclaimer, pageWidth - 2 * margin - 4);
doc.text(disclaimerLines, margin + 2, y);
y += 20;
// Summary
checkPage(50);
addTitle('Synthèse des Résultats', 14);
y += 3;
addText(`${results.global.positiveIndicators}/3 outils suggèrent des symptômes ${results.global.positiveIndicators >= 2 ? 'évocateurs, méritant une évaluation clinique' : 'à explorer si besoin'}.`);
if (results.asrs.screeningPositive) addText('• ASRS: Seuil de dépistage atteint');
if (results.diva.meetsInattention || results.diva.meetsHyperactivity)
addText(`• Critères DSM-5: ${results.diva.presentation}`);
if (results.executive.severity !== 'Faible')
addText(`• Fonctions exécutives: Difficultés de niveau ${results.executive.severity}`);
y += 5;
addLine();
// ASRS Results
checkPage(40);
addTitle('1. ASRS v1.1 (OMS/Harvard)', 12);
addText(`Seuil: ${results.asrs.screeningPositive ? 'Atteint' : 'Non atteint'} (${results.asrs.partAShaded}/6 critères)`);
addText(`Score total: ${results.asrs.total}/72 | Inattention: ${results.asrs.inattention}/36 | Hyperactivité: ${results.asrs.hyperactivity}/36`);
y += 3;
// DIVA Results
checkPage(40);
addTitle('2. Critères DSM-5', 12);
addText(`Présentation: ${results.diva.presentation}`);
addText(`Inattention: ${results.diva.inattentionCount}/9 | Hyperactivité: ${results.diva.hyperactivityCount}/9`);
addText(`Enfance: ${results.diva.childhoodPositive ? 'Confirmé' : 'Non confirmé'} | Retentissement: ${results.diva.impairmentDomains.length} domaines`);
y += 3;
// Executive Functions
checkPage(50);
addTitle('3. Fonctions Exécutives', 12);
addText(`Niveau global: ${results.executive.severity} (${results.executive.percentage}%)`);
Object.entries(results.executive.clusterScores).forEach(([name, s]) => {
addText(` • ${name}: ${s.score}/${s.max} (${s.percentage}%)`);
});
// New page for detailed responses
doc.addPage();
y = 20;
addTitle('Annexe: Réponses Détaillées', 14);
addLine();
// ASRS responses
addTitle('ASRS v1.1', 11);
[...ASRS_QUESTIONS.part_a, ...ASRS_QUESTIONS.part_b].forEach((q, i) => {
checkPage(15);
const val = state.responses[q.id];
const label = ASRS_OPTIONS.find(o => o.value === val)?.label || 'Non répondu';
doc.setFontSize(9);
const qText = doc.splitTextToSize(`${i + 1}. ${q.text}`, pageWidth - 2 * margin - 40);
doc.text(qText, margin, y);
doc.text(label, pageWidth - margin - 30, y);
y += qText.length * 4 + 2;
});
// DIVA responses
checkPage(20);
addTitle('Critères DSM-5', 11);
[...DIVA_INATTENTION, ...DIVA_HYPERACTIVITY, ...DIVA_CHILDHOOD, ...DIVA_IMPAIRMENT].forEach((q, i) => {
checkPage(12);
const val = state.responses[q.id];
doc.setFontSize(9);
const qText = doc.splitTextToSize(`${q.text}`, pageWidth - 2 * margin - 20);
doc.text(qText, margin, y);
doc.text(val === 1 ? 'Oui' : 'Non', pageWidth - margin - 15, y);
y += qText.length * 4 + 2;
});
// References page
doc.addPage();
y = 20;
addTitle('Références Scientifiques', 14);
addLine();
doc.setFontSize(10);
addText('1. Kessler RC, et al. (2005). The World Health Organization Adult ADHD Self-Report Scale (ASRS).');
addText(' Psychological Medicine, 35(2), 245-256. https://pubmed.ncbi.nlm.nih.gov/15841682/');
y += 3;
addText('2. American Psychiatric Association (2013). Diagnostic and Statistical Manual of Mental Disorders (5th ed.).');
addText(' https://www.psychiatry.org/psychiatrists/practice/dsm');
y += 3;
addText('3. Kooij JJS, et al. (2010). DIVA 2.0: Diagnostic Interview for ADHD in Adults.');
addText(' DIVA Foundation. https://www.divacenter.eu/');
y += 3;
addText('4. Brown TE (2013). A New Understanding of ADHD in Children and Adults.');
addText(' Executive Function Impairments. Routledge. https://pubmed.ncbi.nlm.nih.gov/24232170/');
// Footer on each page
const pageCount = doc.internal.getNumberOfPages();
for (let i = 1; i <= pageCount; i++) {
doc.setPage(i);
doc.setFontSize(8);
doc.setTextColor(128);
doc.text(`Page ${i}/${pageCount} | Ce document ne constitue pas un diagnostic médical`, margin, 290);
}
doc.save('evaluation_tdah.pdf');
}
// ============================================
// VALIDATION
// ============================================
function validateSection(section) {
let questions = [];
if (section === 'asrs') {
questions = [...ASRS_QUESTIONS.part_a, ...ASRS_QUESTIONS.part_b].map(q => q.id);
} else if (section === 'diva') {
questions = [
...DIVA_INATTENTION, ...DIVA_HYPERACTIVITY,
...DIVA_CHILDHOOD, ...DIVA_IMPAIRMENT
].map(q => q.id);
} else if (section === 'executive') {
questions = Object.values(EXEC_FUNCTIONS).flatMap(c => c.questions.map(q => q.id));
}
const answered = questions.filter(id => state.responses[id] !== undefined).length;
return answered === questions.length;
}
// ============================================
// EVENT HANDLERS
// ============================================
function init() {
// Render all questionnaires
renderASRS();
renderDIVA();
renderExecutive();
// Consent checkbox
document.getElementById('consent').addEventListener('change', (e) => {
document.getElementById('start-btn').disabled = !e.target.checked;
});
// Navigation buttons
document.getElementById('start-btn').addEventListener('click', () => showSection('asrs'));
document.getElementById('asrs-next').addEventListener('click', () => {
if (!validateSection('asrs')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
showSection('diva');
});
document.getElementById('diva-back').addEventListener('click', () => showSection('asrs'));
document.getElementById('diva-next').addEventListener('click', () => {
if (!validateSection('diva')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
showSection('executive');
});
document.getElementById('exec-back').addEventListener('click', () => showSection('diva'));
document.getElementById('exec-next').addEventListener('click', () => {
if (!validateSection('executive')) {
alert('Veuillez répondre à toutes les questions avant de continuer.');
return;
}
renderResults();
showSection('results');
});
document.getElementById('download-pdf').addEventListener('click', generatePDF);
document.getElementById('restart').addEventListener('click', () => {
state.responses = {};
state.results = null;
renderASRS();
renderDIVA();
renderExecutive();
showSection('home');
});
// Initialize
showSection('home');
}
// Start app when DOM is ready
document.addEventListener('DOMContentLoaded', init);
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Auto-évaluation scientifique du TDAH chez l'adulte. Outils validés: ASRS (OMS), critères DSM-5, fonctions exécutives.">
<meta name="theme-color" content="#5B8A8A">
<!-- Open Graph / Social -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://plnech.github.io/adhd/">
<meta property="og:title" content="Clarté — Auto-Évaluation TDAH Adulte">
<meta property="og:description" content="Évaluez vos symptômes avec des outils scientifiquement validés: ASRS (OMS), critères DSM-5, fonctions exécutives. Gratuit, confidentiel, avec rapport PDF.">
<meta property="og:image" content="https://plnech.github.io/adhd/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Clarté — Auto-Évaluation TDAH Adulte">
<meta name="twitter:description" content="Évaluez vos symptômes avec des outils scientifiquement validés. Gratuit et confidentiel.">
<meta name="twitter:image" content="https://plnech.github.io/adhd/og-image.png">
<title>Clarté — Auto-Évaluation TDAH Adulte</title>
<link rel="stylesheet" href="style.css">
<script src="jspdf.min.js"></script>
</head>
<body>
<header>
<div class="container">
<div class="logo">
<div class="logo-icon">◎</div>
</div>
<h1>Clarté</h1>
<p class="subtitle">Auto-évaluation TDAH pour adultes</p>
</div>
</header>
<nav class="progress-bar">
<div class="container">
<div class="progress-steps">
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
<div class="step-connector"></div>
<div class="step-dot"></div>
</div>
<p class="progress-label">Accueil</p>
</div>
</nav>
<main class="container">
<!-- HOME -->
<section id="home" class="section active">
<div class="card">
<div class="card-header">
<h2>Bienvenue</h2>
</div>
<p>
Cette application vous permet de réaliser une auto-évaluation structurée
des symptômes du <strong>Trouble Déficit de l'Attention avec ou sans Hyperactivité (TDAH)</strong>
chez l'adulte, en utilisant des outils scientifiquement validés.
</p>
<div class="intro-grid">
<div class="intro-card">
<div class="intro-card-icon teal">📋</div>
<div>
<h4>ASRS v1.1</h4>
<p>18 questions validées par l'OMS et Harvard pour le dépistage du TDAH adulte.</p>
</div>
</div>
<div class="intro-card">
<div class="intro-card-icon coral">🔬</div>
<div>
<h4>Critères DSM-5</h4>
<p>Évaluation structurée des 18 critères diagnostiques officiels, incluant l'enfance.</p>
</div>
</div>
<div class="intro-card">
<div class="intro-card-icon lavender">🧠</div>
<div>
<h4>Fonctions Exécutives</h4>
<p>6 domaines cognitifs selon le modèle de Brown: attention, mémoire, régulation.</p>
</div>
</div>
</div>
<div class="notice warning">
<h4>⚠️ Important — Veuillez lire attentivement</h4>
<ul>
<li><strong>Cette évaluation ne constitue PAS un diagnostic médical.</strong></li>
<li>Seul un professionnel de santé qualifié (psychiatre, neurologue) peut établir un diagnostic de TDAH.</li>
<li>Les résultats sont destinés à faciliter la discussion avec votre médecin.</li>
<li>Répondez honnêtement en pensant à votre fonctionnement des <strong>6 derniers mois</strong>.</li>
<li>Durée estimée: <strong>15-20 minutes</strong>.</li>
<li>Vos données restent sur votre appareil et ne sont jamais transmises.</li>
</ul>
</div>
<label class="checkbox-wrapper">
<input type="checkbox" id="consent">
<span>
Je comprends que cette auto-évaluation ne constitue pas un diagnostic médical
et que je dois consulter un professionnel de santé pour toute évaluation diagnostique.
</span>
</label>
<div style="text-align: center;">
<button id="start-btn" class="btn btn-primary btn-large" disabled>
Commencer l'évaluation
</button>
</div>
</div>
</section>
<!-- ASRS -->
<section id="asrs" class="section">
<div class="card">
<div class="card-header">
<h2>ASRS v1.1 — Échelle d'auto-évaluation</h2>
<p class="source">Organisation Mondiale de la Santé / Harvard Medical School</p>
</div>
<div class="notice info">
<p>
Pour chaque question, indiquez à quelle fréquence vous avez ressenti ou agi
de cette manière au cours des <strong>6 derniers mois</strong>.
</p>
</div>
<div id="asrs-questions"></div>
<div class="actions">
<div></div>
<button id="asrs-next" class="btn btn-primary">
Continuer →
</button>
</div>
</div>
</section>
<!-- DIVA -->
<section id="diva" class="section">
<div class="card">
<div class="card-header">
<h2>Critères DSM-5</h2>
<p class="source">American Psychiatric Association (2013)</p>
</div>
<div class="notice info">
<p>
Répondez <strong>Oui</strong> si le symptôme est présent de manière fréquente et persistante
depuis au moins <strong>6 mois</strong>, et qu'il interfère avec votre fonctionnement.
</p>
</div>
<div id="diva-questions"></div>
<div class="actions">
<button id="diva-back" class="btn btn-secondary">
← Retour
</button>
<button id="diva-next" class="btn btn-primary">
Continuer →
</button>
</div>
</div>
</section>
<!-- EXECUTIVE FUNCTIONS -->
<section id="executive" class="section">
<div class="card">
<div class="card-header">
<h2>Fonctions Exécutives</h2>
<p class="source">Basé sur le modèle de Brown (2013)</p>
</div>
<div class="notice info">
<p>
Les fonctions exécutives sont les capacités cognitives qui nous permettent de gérer
notre attention, nos émotions et nos comportements. Indiquez à quel point chaque
difficulté est un problème pour vous <strong>actuellement</strong>.
</p>
</div>
<div id="executive-questions"></div>
<div class="actions">
<button id="exec-back" class="btn btn-secondary">
← Retour
</button>
<button id="exec-next" class="btn btn-primary">
Voir les résultats →
</button>
</div>
</div>
</section>
<!-- RESULTS -->
<section id="results" class="section">
<div class="notice warning">
<p>
<strong>Rappel:</strong> Ces résultats constituent une AUTO-ÉVALUATION et non un diagnostic médical.
Seul un professionnel de santé qualifié peut établir un diagnostic de TDAH.
</p>
</div>
<div id="results-content"></div>
<div style="text-align: center; margin-top: 2rem;">
<button id="download-pdf" class="btn btn-primary btn-large">
📄 Télécharger le rapport PDF
</button>
<p style="color: var(--ink-light); font-size: 0.9rem; margin-top: 1rem;">
Le rapport inclut une synthèse et les réponses détaillées pour votre médecin.
</p>
<button id="restart" class="btn btn-secondary" style="margin-top: 1rem;">
Recommencer l'évaluation
</button>
</div>
</section>
</main>
<footer>
<div class="container">
<p class="disclaimer">
<strong>Avertissement:</strong> Cet outil est fourni à titre informatif uniquement.
Il ne constitue pas un diagnostic médical. Consultez un professionnel de santé qualifié.
</p>
<p><strong>Références scientifiques:</strong></p>
<p style="font-size: 0.8rem; line-height: 1.8;">
<a href="https://pubmed.ncbi.nlm.nih.gov/15841682/" target="_blank" rel="noopener">ASRS v1.1 — Kessler et al. (2005)</a> •
<a href="https://www.psychiatry.org/psychiatrists/practice/dsm" target="_blank" rel="noopener">DSM-5 — APA (2013)</a> •
<a href="https://www.divacenter.eu/" target="_blank" rel="noopener">DIVA Foundation</a> •
<a href="https://pubmed.ncbi.nlm.nih.gov/24232170/" target="_blank" rel="noopener">Brown EF Model (2013)</a>
</p>
<p style="margin-top: 1rem; font-size: 0.8rem;">
<a href="https://github.com/PLNech/adhd" target="_blank" rel="noopener">Code source</a> •
MIT License © 2025 PLNech
</p>
</div>
</footer>
<script src="app.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
<svg width="1200" height="630" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Main gradient: warm cream to soft teal -->
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#FAF8F5"/>
<stop offset="30%" style="stop-color:#F0EDE8"/>
<stop offset="70%" style="stop-color:#E8F0F0"/>
<stop offset="100%" style="stop-color:#D8E8E8"/>
</linearGradient>
<!-- Accent blob gradients -->
<radialGradient id="blob1" cx="20%" cy="30%" r="40%">
<stop offset="0%" style="stop-color:#A89BBF;stop-opacity:0.15"/>
<stop offset="100%" style="stop-color:#A89BBF;stop-opacity:0"/>
</radialGradient>
<radialGradient id="blob2" cx="80%" cy="70%" r="35%">
<stop offset="0%" style="stop-color:#D4A27F;stop-opacity:0.12"/>
<stop offset="100%" style="stop-color:#D4A27F;stop-opacity:0"/>
</radialGradient>
<radialGradient id="blob3" cx="60%" cy="20%" r="30%">
<stop offset="0%" style="stop-color:#5B8A8A;stop-opacity:0.08"/>
<stop offset="100%" style="stop-color:#5B8A8A;stop-opacity:0"/>
</radialGradient>
</defs>
<!-- Background -->
<rect width="1200" height="630" fill="url(#bgGradient)"/>
<!-- Soft blobs -->
<ellipse cx="240" cy="190" rx="300" ry="250" fill="url(#blob1)"/>
<ellipse cx="960" cy="440" rx="280" ry="220" fill="url(#blob2)"/>
<ellipse cx="720" cy="126" rx="240" ry="180" fill="url(#blob3)"/>
<!-- Decorative circle/logo -->
<circle cx="600" cy="200" r="60" fill="#5B8A8A" opacity="0.9"/>
<circle cx="600" cy="200" r="45" fill="none" stroke="#FAF8F5" stroke-width="3"/>
<circle cx="600" cy="200" r="8" fill="#FAF8F5"/>
<!-- Title -->
<text x="600" y="340" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="700" fill="#3A3632">
Clarté
</text>
<!-- Subtitle -->
<text x="600" y="410" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="32" fill="#5B8A8A">
Auto-Évaluation TDAH Adulte
</text>
<!-- Tagline -->
<text x="600" y="480" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="22" fill="#6B6560">
Outils scientifiquement validés • ASRS • DSM-5 • Fonctions Exécutives
</text>
<!-- Bottom accent line -->
<rect x="400" y="530" width="400" height="4" rx="2" fill="#5B8A8A" opacity="0.6"/>
</svg>
/*
* Clarté Theme - ADHD Self-Evaluation
* A soothing, paper-like design focused on clarity and calm
*/
/* ============================================
FONTS - Atkinson Hyperlegible (self-hosted)
Designed for readability by Braille Institute
============================================ */
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Atkinson';
src: url('fonts/AtkinsonHyperlegible-Italic.woff2') format('woff2');
font-weight: 400;
font-style: italic;
font-display: swap;
}
/* ============================================
COLOR PALETTE - Warm, soothing, paper-like
============================================ */
:root {
/* Paper & Background */
--paper: #FAF8F5;
--paper-dark: #F0EDE8;
--paper-shadow: #E5E0D8;
/* Text */
--ink: #3A3632;
--ink-light: #6B6560;
--ink-faint: #9A9590;
/* Primary - Calming Teal */
--teal: #5B8A8A;
--teal-light: #7BA8A8;
--teal-dark: #4A7272;
--teal-faint: #E8F0F0;
/* Accent - Warm Coral */
--coral: #D4A27F;
--coral-light: #E8C4A8;
--coral-faint: #FDF5F0;
/* Accent - Soft Lavender */
--lavender: #A89BBF;
--lavender-faint: #F5F3F8;
/* Semantic - Purple scale for results (non-alarming) */
--sage: #7D9E83;
--sage-faint: #EFF5F0;
--purple-light: #B8A9C9;
--purple-light-faint: #F5F2F8;
--purple-mid: #9683A8;
--purple-mid-faint: #F0ECF5;
--purple-deep: #7B6B8A;
--purple-deep-faint: #EBE7F0;
/* Spacing */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
/* Radius */
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 20px;
--radius-full: 9999px;
/* Shadows - soft, warm */
--shadow-sm: 0 1px 3px rgba(58, 54, 50, 0.08);
--shadow-md: 0 4px 12px rgba(58, 54, 50, 0.1);
--shadow-lg: 0 8px 24px rgba(58, 54, 50, 0.12);
}
/* ============================================
BASE STYLES
============================================ */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: 'Atkinson', -apple-system, BlinkMacSystemFont, sans-serif;
line-height: 1.65;
color: var(--ink);
background: var(--paper);
min-height: 100vh;
/* Subtle paper texture */
background-image:
radial-gradient(ellipse at 20% 30%, rgba(168, 155, 191, 0.03) 0%, transparent 50%),
radial-gradient(ellipse at 80% 70%, rgba(212, 162, 127, 0.03) 0%, transparent 50%);
}
/* ============================================
TYPOGRAPHY
============================================ */
h1, h2, h3, h4 {
font-weight: 700;
line-height: 1.3;
color: var(--ink);
}
h1 {
font-size: 2rem;
letter-spacing: -0.02em;
}
h2 {
font-size: 1.5rem;
color: var(--teal-dark);
}
h3 {
font-size: 1.2rem;
}
p {
margin-bottom: var(--space-md);
}
a {
color: var(--teal);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color 0.2s;
}
a:hover {
border-bottom-color: var(--teal);
}
/* ============================================
LAYOUT
============================================ */
.container {
max-width: 720px;
margin: 0 auto;
padding: 0 var(--space-lg);
}
/* ============================================
HEADER
============================================ */
header {
padding: var(--space-xl) 0;
text-align: center;
border-bottom: 1px solid var(--paper-shadow);
background: linear-gradient(180deg, var(--paper) 0%, var(--teal-faint) 100%);
}
.logo {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
margin-bottom: var(--space-sm);
}
.logo-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--teal) 0%, var(--teal-dark) 100%);
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
box-shadow: var(--shadow-md);
}
header h1 {
margin-bottom: var(--space-xs);
}
header .subtitle {
color: var(--ink-light);
font-size: 1.1rem;
}
/* ============================================
PROGRESS INDICATOR
============================================ */
.progress-bar {
padding: var(--space-md) 0;
background: var(--paper);
border-bottom: 1px solid var(--paper-shadow);
position: sticky;
top: 0;
z-index: 100;
}
.progress-steps {
display: flex;
justify-content: center;
gap: var(--space-xs);
align-items: center;
}
.step-dot {
width: 12px;
height: 12px;
border-radius: var(--radius-full);
background: var(--paper-shadow);
transition: all 0.3s ease;
}
.step-dot.active {
background: var(--teal);
transform: scale(1.3);
}
.step-dot.completed {
background: var(--sage);
}
.step-connector {
width: 40px;
height: 2px;
background: var(--paper-shadow);
transition: background 0.3s;
}
.step-connector.completed {
background: var(--sage);
}
.progress-label {
text-align: center;
margin-top: var(--space-sm);
font-size: 0.85rem;
color: var(--ink-light);
}
/* ============================================
MAIN CONTENT
============================================ */
main {
padding: var(--space-2xl) 0;
min-height: 60vh;
}
.section {
display: none;
animation: fadeIn 0.4s ease;
}
.section.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* ============================================
CARDS
============================================ */
.card {
background: white;
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-lg);
box-shadow: var(--shadow-sm);
border: 1px solid var(--paper-shadow);
}
.card-header {
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 2px solid var(--teal-faint);
}
.card-header h2 {
margin-bottom: var(--space-xs);
}
.card-header .source {
font-size: 0.85rem;
color: var(--ink-faint);
font-style: italic;
}
/* ============================================
INTRO CARDS (Home)
============================================ */
.intro-grid {
display: grid;
gap: var(--space-md);
margin: var(--space-xl) 0;
}
.intro-card {
background: white;
border-radius: var(--radius-md);
padding: var(--space-lg);
border: 1px solid var(--paper-shadow);
display: flex;
gap: var(--space-md);
align-items: flex-start;
}
.intro-card-icon {
width: 44px;
height: 44px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3rem;
flex-shrink: 0;
}
.intro-card-icon.teal { background: var(--teal-faint); color: var(--teal); }
.intro-card-icon.coral { background: var(--coral-faint); color: var(--coral); }
.intro-card-icon.lavender { background: var(--lavender-faint); color: var(--lavender); }
.intro-card h4 {
margin-bottom: var(--space-xs);
}
.intro-card p {
font-size: 0.9rem;
color: var(--ink-light);
margin: 0;
}
/* ============================================
ALERTS / NOTICES
============================================ */
.notice {
padding: var(--space-lg);
border-radius: var(--radius-md);
margin-bottom: var(--space-lg);
}
.notice.warning {
background: var(--amber-faint);
border: 1px solid var(--amber);
}
.notice.info {
background: var(--teal-faint);
border: 1px solid var(--teal-light);
}
.notice h4 {
margin-bottom: var(--space-sm);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.notice ul {
margin-left: var(--space-lg);
color: var(--ink-light);
}
.notice li {
margin-bottom: var(--space-xs);
}
/* ============================================
QUESTIONS
============================================ */
.question-group {
margin-bottom: var(--space-xl);
}
.question-group h3 {
color: var(--teal-dark);
margin-bottom: var(--space-md);
padding-bottom: var(--space-sm);
border-bottom: 1px solid var(--paper-shadow);
}
.question-group .hint {
font-size: 0.85rem;
color: var(--ink-faint);
font-style: italic;
margin-bottom: var(--space-md);
}
.question {
background: var(--paper);
border-radius: var(--radius-md);
padding: var(--space-lg);
margin-bottom: var(--space-md);
border: 1px solid transparent;
transition: border-color 0.2s, box-shadow 0.2s;
}
.question:hover {
border-color: var(--paper-shadow);
}
.question.answered {
border-color: var(--sage);
background: var(--sage-faint);
}
.question-text {
font-weight: 500;
margin-bottom: var(--space-md);
line-height: 1.5;
}
.question-number {
color: var(--teal);
font-weight: 700;
}
/* ============================================
RESPONSE OPTIONS
============================================ */
.options {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
}
.option {
position: relative;
}
.option input {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.option label {
display: inline-block;
padding: var(--space-sm) var(--space-md);
background: white;
border: 2px solid var(--paper-shadow);
border-radius: var(--radius-full);
cursor: pointer;
font-size: 0.9rem;
transition: all 0.2s;
}
.option label:hover {
border-color: var(--teal-light);
background: var(--teal-faint);
}
.option input:checked + label {
background: var(--teal);
border-color: var(--teal);
color: white;
}
/* Binary options (Yes/No) */
.options.binary {
gap: var(--space-md);
}
.options.binary .option label {
min-width: 80px;
text-align: center;
}
.options.binary .option.yes input:checked + label {
background: var(--coral);
border-color: var(--coral);
}
.options.binary .option.no input:checked + label {
background: var(--sage);
border-color: var(--sage);
}
/* ============================================
BUTTONS
============================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-sm);
padding: var(--space-md) var(--space-xl);
border-radius: var(--radius-full);
font-family: inherit;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
}
.btn-primary {
background: var(--teal);
color: white;
}
.btn-primary:hover {
background: var(--teal-dark);
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.btn-secondary {
background: white;
color: var(--ink);
border-color: var(--paper-shadow);
}
.btn-secondary:hover {
border-color: var(--teal);
color: var(--teal);
}
.btn-large {
padding: var(--space-lg) var(--space-2xl);
font-size: 1.1rem;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: var(--space-xl);
padding-top: var(--space-lg);
border-top: 1px solid var(--paper-shadow);
}
/* ============================================
CHECKBOX (Consent)
============================================ */
.checkbox-wrapper {
display: flex;
align-items: flex-start;
gap: var(--space-md);
padding: var(--space-lg);
background: var(--paper);
border-radius: var(--radius-md);
margin-bottom: var(--space-lg);
cursor: pointer;
}
.checkbox-wrapper input[type="checkbox"] {
width: 22px;
height: 22px;
margin-top: 2px;
accent-color: var(--teal);
cursor: pointer;
}
.checkbox-wrapper span {
font-size: 0.95rem;
line-height: 1.5;
}
/* ============================================
RESULTS
============================================ */
.summary-card {
background: linear-gradient(135deg, var(--teal-faint) 0%, var(--lavender-faint) 100%);
border: 2px solid var(--teal);
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-xl);
}
.summary-card h2 {
margin-bottom: var(--space-md);
}
.summary-text {
font-size: 1.05rem;
line-height: 1.7;
margin-bottom: var(--space-md);
}
.recommendation {
background: white;
padding: var(--space-md);
border-radius: var(--radius-md);
border-left: 4px solid var(--teal);
}
/* Result Cards */
.result-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--space-xl);
margin-bottom: var(--space-lg);
border: 1px solid var(--paper-shadow);
border-left: 5px solid var(--paper-shadow);
}
.result-card.high {
border-left-color: var(--purple-deep);
}
.result-card.low {
border-left-color: var(--sage);
}
.result-card.moderate {
border-left-color: var(--purple-mid);
}
.result-card h3 {
margin-bottom: var(--space-md);
}
.result-status {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border-radius: var(--radius-full);
font-weight: 600;
font-size: 0.9rem;
margin-bottom: var(--space-md);
}
.result-status.high {
background: var(--purple-deep-faint);
color: var(--purple-deep);
}
.result-status.low {
background: var(--sage-faint);
color: var(--sage);
}
.result-status.moderate {
background: var(--purple-mid-faint);
color: var(--purple-mid);
}
/* Score Grid */
.scores-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: var(--space-md);
margin: var(--space-md) 0;
}
.score-item {
background: var(--paper);
padding: var(--space-md);
border-radius: var(--radius-md);
text-align: center;
}
.score-label {
font-size: 0.8rem;
color: var(--ink-light);
display: block;
margin-bottom: var(--space-xs);
}
.score-value {
font-size: 1.4rem;
font-weight: 700;
color: var(--teal-dark);
}
/* Progress Bars */
.progress-item {
margin-bottom: var(--space-md);
}
.progress-label-row {
display: flex;
justify-content: space-between;
margin-bottom: var(--space-xs);
font-size: 0.9rem;
}
.progress-track {
height: 10px;
background: var(--paper-shadow);
border-radius: var(--radius-full);
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--teal);
border-radius: var(--radius-full);
transition: width 0.5s ease;
}
.progress-fill.high {
background: var(--purple-deep);
}
.progress-fill.moderate {
background: var(--purple-mid);
}
/* Interpretation */
.interpretation {
margin-top: var(--space-md);
padding-top: var(--space-md);
border-top: 1px dashed var(--paper-shadow);
font-style: italic;
color: var(--ink-light);
}
/* ============================================
FOOTER
============================================ */
footer {
padding: var(--space-xl) 0;
background: var(--paper-dark);
border-top: 1px solid var(--paper-shadow);
text-align: center;
}
footer p {
font-size: 0.85rem;
color: var(--ink-light);
margin-bottom: var(--space-sm);
}
footer .disclaimer {
max-width: 600px;
margin: 0 auto var(--space-md);
}
/* ============================================
RESPONSIVE
============================================ */
@media (max-width: 600px) {
html { font-size: 15px; }
.container { padding: 0 var(--space-md); }
.card { padding: var(--space-lg); }
.options { flex-direction: column; }
.option label { display: block; text-align: center; }
.actions { flex-direction: column; gap: var(--space-md); }
.btn { width: 100%; }
.scores-grid { grid-template-columns: repeat(2, 1fr); }
}
/* ============================================
PRINT STYLES
============================================ */
@media print {
body { background: white; }
.progress-bar, .actions, footer { display: none; }
.section { display: block !important; page-break-inside: avoid; }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment