Maquettes Claude Design avec visio de classe

This commit is contained in:
Adam Belkacemi 2026-10-06 23:28:18 +02:00
parent 238070ae54
commit 236d2d3567
243 changed files with 27992 additions and 0 deletions

View file

@ -0,0 +1,199 @@
// Terminal élève Syllabus : xterm.js + un petit shell simulé (vitrine et lab d'essai).
// En production, le terminal se branche sur le proxy WebSocket de la console série Nova.
(function () {
var THEME = {
background: '#13233A', foreground: '#E8EDF5', cursor: '#FFD23F', cursorAccent: '#13233A',
selectionBackground: '#2B4A73', black: '#0D192B', red: '#FF7A66', green: '#7CF2C0', yellow: '#FFD23F',
blue: '#8DB4FF', magenta: '#FF6FB5', cyan: '#7CE3F2', white: '#E8EDF5',
brightBlack: '#6B7F99', brightRed: '#FF9A8A', brightGreen: '#7CF2C0', brightYellow: '#FFD23F',
brightBlue: '#A9C6FF', brightMagenta: '#FF8FC6', brightCyan: '#9CEBF7', brightWhite: '#FFFFFF'
};
var G = '\x1b[1;92m', B = '\x1b[1;94m', Y = '\x1b[93m', R = '\x1b[91m', D = '\x1b[2m', X = '\x1b[0m';
function Shell(term, o) {
this.t = term; this.o = o;
this.user = o.user || 'eleve'; this.host = o.host || 'debian-lab';
this.home = '/home/' + this.user; this.cwd = this.home;
this.dirs = new Set(['/', '/home', this.home, '/etc', '/tmp', '/var', '/var/log']);
this.files = new Map([
[this.home + '/.bashrc', '# ~/.bashrc'],
['/etc/hostname', this.host],
['/etc/os-release', 'PRETTY_NAME="Debian GNU/Linux 13 (trixie)"\nID=debian']
]);
this.line = ''; this.hist = []; this.hi = 0; this.busy = false;
}
Shell.prototype.short = function (p) { return p === this.home ? '~' : p.indexOf(this.home + '/') === 0 ? '~' + p.slice(this.home.length) : p; };
Shell.prototype.prompt = function () { this.t.write(G + this.user + '@' + this.host + X + ':' + B + this.short(this.cwd) + X + '$ '); };
Shell.prototype.path = function (p) {
if (!p || p === '~') return this.home;
if (p.indexOf('~/') === 0) p = this.home + p.slice(1);
var parts = (p[0] === '/' ? p : this.cwd + '/' + p).split('/'), out = [];
parts.forEach(function (s) { if (!s || s === '.') return; if (s === '..') out.pop(); else out.push(s); });
return '/' + out.join('/');
};
Shell.prototype.parent = function (p) { var i = p.lastIndexOf('/'); return i <= 0 ? '/' : p.slice(0, i); };
Shell.prototype.base = function (p) { return p.slice(p.lastIndexOf('/') + 1); };
Shell.prototype.children = function (d) {
var self = this, out = [];
this.dirs.forEach(function (x) { if (x !== '/' && self.parent(x) === d) out.push({ n: self.base(x), dir: true }); });
this.files.forEach(function (v, x) { if (self.parent(x) === d) out.push({ n: self.base(x), dir: false, size: v.length }); });
return out.sort(function (a, b) { return a.n.replace(/^\./, '').localeCompare(b.n.replace(/^\./, '')); });
};
Shell.prototype.out = function (s) { this.t.write(String(s).replace(/\n/g, '\r\n') + '\r\n'); };
Shell.prototype.err = function (s) { this.out(R + s + X); };
Shell.prototype.exec = function (raw) {
var self = this, parts = raw.split(/&&|;/);
for (var i = 0; i < parts.length; i++) { if (!self.run(parts[i].trim())) break; }
if (this.o.onCommand) this.o.onCommand(raw, this);
};
Shell.prototype.run = function (cmd) {
if (!cmd) return true;
var toks = [], m, re = /"([^"]*)"|'([^']*)'|(\S+)/g;
while ((m = re.exec(cmd))) toks.push(m[1] != null ? m[1] : m[2] != null ? m[2] : m[3]);
var redir = null, ri = toks.findIndex(function (t) { return t === '>' || t === '>>'; });
if (ri > -1) { redir = { mode: toks[ri], file: toks[ri + 1] }; toks = toks.slice(0, ri); }
var c = toks[0], a = toks.slice(1), self = this, flags = a.filter(function (x) { return x[0] === '-'; }).join(''), args = a.filter(function (x) { return x[0] !== '-'; });
var capture = null, print = function (s) { if (redir) capture = (capture ? capture + '\n' : '') + s; else self.out(s); };
switch (c) {
case 'help': print('Commandes : pwd, ls, cd, mkdir, touch, echo, cat, rm, rmdir, whoami, hostname, date, uname, ip a, clear'); break;
case 'pwd': print(this.cwd); break;
case 'whoami': print(this.user); break;
case 'hostname': print(this.host); break;
case 'date': print(new Date().toLocaleString('fr-FR', { dateStyle: 'full', timeStyle: 'medium' })); break;
case 'uname': print(flags.indexOf('a') > -1 ? 'Linux ' + this.host + ' 6.12.0-amd64 #1 SMP Debian x86_64 GNU/Linux' : 'Linux'); break;
case 'clear': this.t.clear(); break;
case 'ip':
if (/^a|^addr/.test(args[0] || '')) print('1: lo: <LOOPBACK,UP> mtu 65536\n inet 127.0.0.1/8 scope host lo\n2: ens3: <BROADCAST,MULTICAST,UP> mtu 1500\n inet 192.168.10.10/26 brd 192.168.10.63 scope global ens3');
else print('Usage : ip addr'); break;
case 'ls': {
var d = this.path(args[0] || '.');
if (!this.dirs.has(d)) { this.err("ls: impossible d'accéder à '" + (args[0] || '.') + "': Aucun fichier ou dossier de ce nom"); return false; }
var all = flags.indexOf('a') > -1, long = flags.indexOf('l') > -1;
var list = this.children(d).filter(function (e) { return all || e.n[0] !== '.'; });
if (all) list = [{ n: '.', dir: true }, { n: '..', dir: true }].concat(list);
var col = function (e) { return redir ? e.n : e.dir ? B + e.n + X : e.n; };
if (long) {
var now = new Date(), stamp = now.toLocaleDateString('fr-FR', { day: '2-digit', month: 'short' }) + ' ' + now.toTimeString().slice(0, 5);
print('total ' + list.length * 4);
list.forEach(function (e) { print((e.dir ? 'drwxr-xr-x 2 ' : '-rw-r--r-- 1 ') + self.user + ' ' + self.user + ' ' + String(e.dir ? 4096 : e.size).padStart(5) + ' ' + stamp + ' ' + col(e)); });
} else if (list.length) print(list.map(col).join(' '));
break;
}
case 'cd': {
var p = this.path(args[0]);
if (!this.dirs.has(p)) { this.err('bash: cd: ' + args[0] + ': Aucun fichier ou dossier de ce nom'); return false; }
this.cwd = p; break;
}
case 'mkdir':
if (!args.length) { this.err('mkdir: opérande manquant'); return false; }
for (var i = 0; i < args.length; i++) {
var np = this.path(args[i]);
if (this.dirs.has(np)) { if (flags.indexOf('p') < 0) { this.err("mkdir: impossible de créer le répertoire « " + args[i] + " »: Le fichier existe"); return false; } continue; }
if (!this.dirs.has(this.parent(np))) {
if (flags.indexOf('p') < 0) { this.err("mkdir: impossible de créer le répertoire « " + args[i] + " »: Aucun fichier ou dossier de ce nom"); return false; }
var acc = ''; np.split('/').slice(1).forEach(function (s) { acc += '/' + s; self.dirs.add(acc); });
} else this.dirs.add(np);
}
break;
case 'touch':
if (!args.length) { this.err('touch: opérande de fichier manquant'); return false; }
args.forEach(function (f) { var fp = self.path(f); if (!self.files.has(fp)) self.files.set(fp, ''); }); break;
case 'echo': print(args.join(' ')); break;
case 'cat': {
var f = this.path(args[0]);
if (this.dirs.has(f)) { this.err('cat: ' + args[0] + ': est un dossier'); return false; }
if (!this.files.has(f)) { this.err('cat: ' + args[0] + ': Aucun fichier ou dossier de ce nom'); return false; }
var v = this.files.get(f); if (v) print(v); break;
}
case 'rm':
for (var k = 0; k < args.length; k++) {
var rp = this.path(args[k]);
if (this.dirs.has(rp)) { this.err("rm: impossible de supprimer '" + args[k] + "': est un dossier"); return false; }
if (!this.files.delete(rp)) { this.err("rm: impossible de supprimer '" + args[k] + "': Aucun fichier ou dossier de ce nom"); return false; }
}
break;
case 'rmdir': {
var dp = this.path(args[0]);
if (!this.dirs.has(dp)) { this.err("rmdir: '" + args[0] + "': Aucun fichier ou dossier de ce nom"); return false; }
if (this.children(dp).length) { this.err("rmdir: '" + args[0] + "': Le dossier n'est pas vide"); return false; }
this.dirs.delete(dp); break;
}
case 'sudo': if (this.o.commands) return this.run(a.join(' ')); print(Y + 'Pas besoin de sudo pour ce lab : tout se passe dans ton dossier.' + X); break;
default:
if (this.o.commands && this.o.commands[c]) { var res = this.o.commands[c](a, this); if (res === false) return false; if (res) print(res); break; }
this.err('bash: ' + c + ' : commande introuvable'); return false;
}
if (redir) {
if (!redir.file) { this.err('bash: erreur de syntaxe près du symbole inattendu « newline »'); return false; }
var fp2 = this.path(redir.file);
if (!this.dirs.has(this.parent(fp2))) { this.err('bash: ' + redir.file + ': Aucun fichier ou dossier de ce nom'); return false; }
var prev = redir.mode === '>>' && this.files.has(fp2) ? this.files.get(fp2) : '';
this.files.set(fp2, prev ? prev + '\n' + (capture || '') : (capture || ''));
}
return true;
};
Shell.prototype.key = function (d) {
if (this.busy) return;
var t = this.t;
if (d === '\r') { t.write('\r\n'); var l = this.line; this.line = ''; if (l.trim()) { this.hist.push(l); } this.hi = this.hist.length; this.exec(l); this.prompt(); return; }
if (d === '\x7f') { if (this.line) { this.line = this.line.slice(0, -1); t.write('\b \b'); } return; }
if (d === '\x03') { t.write('^C\r\n'); this.line = ''; this.prompt(); return; }
if (d === '\x0c') { t.clear(); return; }
if (d === '\x1b[A' || d === '\x1b[B') {
if (!this.hist.length) return;
this.hi = Math.max(0, Math.min(this.hist.length, this.hi + (d === '\x1b[A' ? -1 : 1)));
var h = this.hist[this.hi] || '';
t.write('\b \b'.repeat(this.line.length)); this.line = h; t.write(h); return;
}
if (d[0] === '\x1b') return;
var clean = d.replace(/[\x00-\x1f]/g, ''); this.line += clean; t.write(clean);
};
Shell.prototype.demo = function (cmds, loop) {
var self = this, reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
this.busy = true;
var i = 0;
function next() {
if (i >= cmds.length) {
if (!loop || reduce) return;
return setTimeout(function () { self.t.clear(); self.t.write('\x1b[2J\x1b[H'); self.cwd = self.home; self.dirs = new Set(['/', '/home', self.home, '/etc', '/tmp', '/var', '/var/log']); self.files.forEach(function (v, k) { if (k.indexOf(self.home + '/') === 0 && k !== self.home + '/.bashrc') self.files.delete(k); }); i = 0; self.prompt(); setTimeout(next, 600); }, 3500);
}
var c = cmds[i++], j = 0;
if (reduce) { self.t.write(c + '\r\n'); self.exec(c); self.prompt(); return next(); }
(function type() {
if (j < c.length) { self.t.write(c[j++]); return setTimeout(type, 40 + Math.random() * 50); }
setTimeout(function () { self.t.write('\r\n'); self.exec(c); self.prompt(); setTimeout(next, 900); }, 300);
})();
}
setTimeout(next, 700);
};
function mount(el, o) {
o = o || {};
var term = new window.Terminal({
theme: THEME, fontFamily: '"IBM Plex Mono", ui-monospace, monospace', fontSize: o.fontSize || 14,
lineHeight: 1.25, cursorBlink: true, cursorStyle: 'block', scrollback: 500, convertEol: false,
disableStdin: !!o.demo, allowTransparency: false
});
var fit = window.FitAddon ? new window.FitAddon.FitAddon() : null;
if (fit) term.loadAddon(fit);
term.open(el);
var fitNow = function () { try { fit && fit.fit(); } catch (e) {} };
var raf, doFit = function () { cancelAnimationFrame(raf); raf = requestAnimationFrame(fitNow); };
fitNow(); window.addEventListener('resize', doFit);
if (window.ResizeObserver) new ResizeObserver(doFit).observe(el);
var sh = new Shell(term, o);
if (o.welcome) term.write(o.welcome.replace(/\n/g, '\r\n') + '\r\n');
sh.prompt();
if (o.demo) sh.demo(o.demo, o.loop !== false);
else { term.onData(function (d) { sh.key(d); }); if (o.focus) term.focus(); }
return sh;
}
window.SyllabusTerminal = { mount: function (el, o) {
var go = function () { mount(el, o); };
(document.fonts && document.fonts.ready ? document.fonts.ready : Promise.resolve()).then(go);
} };
})();

View file

@ -0,0 +1,52 @@
(function () {
var L = window.RESSOURCES, id = new URLSearchParams(location.search).get('outil');
var R = L.find(function (r) { return r.id === id; }) || L[0];
var el = function (i) { return document.getElementById(i); };
var demo = (window.URL_DEMOS && window.URL_DEMOS[R.id]) || R.demo;
document.title = R.titre + ' · Syllabus';
el('r-titre-k').textContent = R.titre;
el('r-titre').textContent = R.accroche;
el('r-probleme').textContent = R.probleme;
el('r-pour').textContent = 'Pour : ' + R.pour;
el('r-accroche-fin').textContent = 'Essayez ' + R.titre.toLowerCase() + ' en quelques clics.';
el('r-demo').href = el('r-demo2').href = demo;
var ul = el('r-points');
R.points.forEach(function (pt) {
var li = document.createElement('li'), h = document.createElement('h3'), t = document.createElement('p');
h.style.cssText = 'margin:0;font-size:20px;font-weight:800;letter-spacing:-0.01em;color:#0b1220';
t.style.cssText = 'margin:12px 0 0;font-size:16px;line-height:1.65;font-weight:500;color:#374151';
h.textContent = pt[0]; t.textContent = pt[1]; li.appendChild(h); li.appendChild(t); ul.appendChild(li);
});
var ol = el('r-etapes');
R.etapes.forEach(function (e, i) {
var li = document.createElement('li'), n = document.createElement('span'), t = document.createElement('p');
li.style.cssText = 'display:grid;grid-template-columns:48px 1fr;align-items:baseline;gap:16px';
n.style.cssText = 'font-size:28px;font-weight:800;color:#1d5cf5;font-variant-numeric:tabular-nums';
t.style.cssText = 'margin:0;font-size:20px;line-height:1.5;font-weight:600;color:#0b1220';
n.textContent = String(i + 1).padStart(2, '0'); t.textContent = e;
li.appendChild(n); li.appendChild(t); ol.appendChild(li);
});
var box = el('r-video'), base = window.URL_VIDEOS || 'videos', reduit = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var v = document.createElement('video');
v.muted = true; v.loop = true; v.playsInline = true; v.autoplay = !reduit; v.preload = 'metadata';
v.setAttribute('aria-label', 'Démonstration vidéo : ' + R.titre);
v.style.cssText = 'display:block;width:100%;height:100%;object-fit:cover';
v.src = base + '/' + R.id + '.mp4';
var btn = document.createElement('button');
btn.type = 'button';
btn.style.cssText = 'position:absolute;right:20px;bottom:20px;width:44px;height:44px;border-radius:999px;border:0;background:rgba(255,255,255,.92);color:#0b1220;font-size:14px;font-weight:800;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.15)';
var maj = function () { btn.textContent = v.paused ? '▶' : '❚❚'; btn.setAttribute('aria-label', v.paused ? 'Lire la vidéo' : 'Mettre en pause'); };
btn.addEventListener('click', function () { v.paused ? v.play() : v.pause(); });
v.addEventListener('play', maj); v.addEventListener('pause', maj);
v.addEventListener('error', function () {
box.innerHTML = '';
var d = document.createElement('div');
d.style.cssText = 'height:100%;display:grid;place-items:center;text-align:center;padding:32px';
d.innerHTML = '<div><p style="margin:0;font-size:18px;font-weight:700;color:#0b1220">Vidéo de démonstration</p><p style="margin:8px 0 0;font-size:14px;font-weight:600;color:#4b5563">Fichier attendu : <code>videos/' + R.id + '.mp4</code></p></div>';
box.appendChild(d);
el('r-video-legende').textContent = '';
});
box.appendChild(v); box.appendChild(btn); maj();
el('r-video-legende').textContent = R.titre + ', en conditions réelles.';
if (!reduit) { var pr = v.play(); if (pr && pr.catch) pr.catch(function () {}); }
})();

View file

@ -0,0 +1,123 @@
// Présentations des outils Syllabus (page ressource). demo = page de démonstration existante.
window.RESSOURCES = [
{ id: 'visio', cat: 'Piloter', titre: 'Visio de classe', demo: 'liste-attente.html', pour: 'Enseignants, élèves',
accroche: 'Une visio intégrée où les élèves arrivent en sourdine et ne parlent que quand vous leur donnez la parole.',
probleme: 'En classe à distance, les micros ouverts et le chat qui défile empêchent d’enseigner, et les élèves discrets n’osent pas intervenir.',
points: [['Tous en sourdine', 'Micro et caméra bloqués tant que le prof n’a pas donné la parole.'], ['File des mains levées', 'Premier arrivé en haut, avec l’étape du lab de chaque élève.'], ['Salle d’attente', 'Vous admettez chaque élève avant qu’il rejoigne la classe.'], ['Chat contrôlé', 'Désactivé par défaut, activable d’un interrupteur.']],
etapes: ['Lancez la visio depuis votre tableau de bord', 'Admettez les élèves de la salle d’attente', 'Donnez la parole depuis la file des mains levées'] },
{ id: 'cockpit', cat: 'Piloter', titre: 'Tableau de bord prof', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Toute la classe sur un seul écran : qui avance, qui bloque, qui a levé la main.',
probleme: 'Avec 30 élèves en TP, on ne voit que ceux qui appellent. Les élèves discrets en difficulté passent inaperçus jusqu’à l’évaluation.',
points: [['Mains levées dans l’ordre', 'La file d’attente s’affiche en temps réel avec l’étape où chaque élève bloque.'], ['Alertes de décrochage', 'Un élève qui n’avance plus ou accumule les indices est signalé, sans surveillance intrusive.'], ['Examens et devoirs en cours', 'Copies rendues, sorties de fenêtre, temps restant : tout est suivi depuis le même écran.'], ['Accès à la fiche élève', 'Un clic ouvre l’historique complet pour préparer un entretien ou un conseil de classe.']],
etapes: ['Ouvrez votre classe en début de séance', 'Suivez la progression pendant le TP', 'Repérez les élèves à accompagner en priorité'] },
{ id: 'espace-eleve', cat: 'Piloter', titre: 'Espace élève', demo: 'liste-attente.html', pour: 'Élèves et étudiants',
accroche: 'Un calendrier, les devoirs à rendre, les examens à venir et de quoi s’entraîner.',
probleme: 'Les consignes sont dispersées entre l’ENT, les mails et le tableau. L’élève ne sait pas toujours ce qu’il doit rendre ni quand.',
points: [['Calendrier unique', 'Devoirs, examens et séances de TP au même endroit, avec rappels.'], ['Progression visible', 'Compétences acquises et chapitres à revoir, chapitre par chapitre.'], ['Entraînement libre', 'Exercices et labs disponibles hors classe, corrigés automatiquement.'], ['Lever la main', 'Une demande d’aide en un clic pendant le TP.']],
etapes: ['L’élève se connecte avec ses identifiants', 'Il consulte ce qui l’attend cette semaine', 'Il s’entraîne et rend ses travaux en ligne'] },
{ id: 'vie-scolaire', cat: 'Piloter', titre: 'Vie scolaire', demo: 'liste-attente.html', pour: 'CPE, direction, intendance',
accroche: 'L’assiduité et les signaux de décrochage de tout l’établissement, classe par classe.',
probleme: 'Les informations utiles au suivi sont réparties entre les enseignants. Le CPE les découvre souvent trop tard.',
points: [['Présence aux séances en ligne', 'Connexions aux quiz, labs et examens, par classe et par élève.'], ['Signalements centralisés', 'Les alertes des enseignants arrivent au même endroit, avec leur historique.'], ['Suivi des accompagnements', 'Entretiens, contacts familles et décisions consignés.'], ['Exports', 'Données prêtes pour le conseil de classe ou le logiciel de vie scolaire.']],
etapes: ['Choisissez la classe ou le niveau', 'Repérez les élèves signalés', 'Planifiez l’accompagnement et suivez-le'] },
{ id: 'academie', cat: 'Piloter', titre: 'Académie', demo: 'liste-attente.html', pour: 'Inspection, rectorat, réseaux d’établissements',
accroche: 'Une vue agrégée de plusieurs établissements, sans aucune donnée nominative.',
probleme: 'Évaluer l’usage d’un outil ou repérer les compétences mal acquises à l’échelle d’un territoire demande de compiler des tableaux à la main.',
points: [['Indicateurs par établissement', 'Activité, labs réalisés, compétences validées.'], ['Compétences les moins acquises', 'Pour cibler les formations et les ressources.'], ['Données anonymisées', 'Uniquement des moyennes par établissement et par classe.'], ['Rapports téléchargeables', 'Bilans en PDF et en CSV.']],
etapes: ['Choisissez le périmètre', 'Comparez les établissements', 'Exportez le rapport'] },
{ id: 'cohortes', cat: 'Piloter', titre: 'Suivi des cohortes', demo: 'liste-attente.html', pour: 'Responsables de formation, scolarité',
accroche: 'La progression d’une promotion entière, semestre après semestre.',
probleme: 'Savoir si une promotion est en avance ou en retard sur le référentiel suppose de croiser les résultats de plusieurs enseignants.',
points: [['Progression par compétence', 'Taux d’acquisition de chaque bloc du référentiel.'], ['Comparaison entre promotions', 'Même formation, années différentes.'], ['Assiduité et résultats', 'Corrélés pour repérer les décrochages.'], ['Export des notes', 'CSV compatible avec les logiciels de scolarité.']],
etapes: ['Sélectionnez la promotion', 'Lisez les indicateurs par compétence', 'Exportez pour le jury ou le conseil'] },
{ id: 'espace-etablissement', cat: 'Piloter', titre: 'Espace établissement', demo: 'liste-attente.html', pour: 'Intendance, direction',
accroche: 'Licences, devis, factures et conventions au même endroit.',
probleme: 'Commander un service en ligne dans un établissement public impose devis, bon de commande, Chorus Pro et suivi des licences.',
points: [['Gestion des licences', 'Ajout et retrait d’élèves, licences utilisées et disponibles.'], ['Devis et bons de commande', 'Générés au nom de l’établissement.'], ['Factures Chorus Pro', 'Déposées automatiquement, téléchargeables en PDF.'], ['Documents contractuels', 'Conditions, DPA et convention signée.']],
etapes: ['Demandez un devis', 'Validez le bon de commande', 'Gérez les licences au fil de l’année'] },
{ id: 'integration', cat: 'Piloter', titre: 'Intégration et sécurité', demo: 'liste-attente.html', pour: 'DSI, administrateurs',
accroche: 'SSO, API, hébergement et conformité : ce que votre DSI doit vérifier.',
probleme: 'Avant d’adopter un outil, la DSI doit s’assurer de l’authentification, de la protection des données et des prérequis réseau.',
points: [['Authentification unique', 'Connexion par l’ENT ou l’annuaire de l’établissement.'], ['Hébergement en France', 'Serveurs Scaleway à Paris.'], ['RGPD', 'Registre, DPA, durées de conservation documentées.'], ['Prérequis réseau', 'Navigateur récent, accès HTTPS, aucun logiciel à installer.']],
etapes: ['Consultez la fiche technique', 'Testez la connexion depuis votre réseau', 'Échangez avec nous pour le SSO'] },
{ id: 'cours', cat: 'Apprendre', titre: 'Cours gratuits', demo: 'liste-attente.html', pour: 'Enseignants et élèves',
accroche: 'Des cours complets alignés sur les référentiels, du lycée au master.',
probleme: 'Préparer un cours technique complet prend des heures, et les ressources en ligne sont rarement adaptées au référentiel.',
points: [['Cours magistral détaillé', 'Théorie, exemples commentés, schémas et mise en situation.'], ['QCM de lecture', 'Pour vérifier que le cours a été lu et compris.'], ['TD et TP corrigés', 'Exercices progressifs et travaux pratiques sur machine.'], ['Sujets d’examen', 'Avec éléments de correction.']],
etapes: ['Choisissez le cursus', 'Ouvrez un chapitre', 'Donnez-le à lire ou projetez-le'] },
{ id: 'labs', cat: 'Apprendre', titre: 'TP sur machine Linux', demo: 'liste-attente.html', pour: 'Élèves, enseignants',
accroche: 'Une vraie machine Linux par élève, dans le navigateur, corrigée automatiquement.',
probleme: 'Installer et maintenir des machines virtuelles pour chaque élève prend du temps et dépend du matériel de la salle.',
points: [['Terminal dans le navigateur', 'Aucune installation, sur PC comme sur tablette.'], ['Étapes vérifiées', 'Chaque étape est validée automatiquement dans la machine.'], ['Indices progressifs', 'Débloqués après plusieurs essais pour encourager la réflexion.'], ['Machine réinitialisable', 'L’élève peut tout recommencer sans risque.']],
etapes: ['Lancez le lab pour la classe', 'Les élèves suivent les étapes', 'Consultez les résultats dans le tableau de bord'] },
{ id: 'lab-web', cat: 'Apprendre', titre: 'Lab web', demo: 'liste-attente.html', pour: 'Élèves, enseignants',
accroche: 'Un terminal et un navigateur reliés : on configure un serveur et on voit le résultat.',
probleme: 'Comprendre le lien entre une commande serveur et ce qu’affiche le navigateur est difficile sans les avoir côte à côte.',
points: [['Terminal et navigateur liés', 'Le navigateur affiche la machine de l’élève.'], ['Serveur réel', 'Apache, Nginx, PHP installés pour de vrai.'], ['Vérifications automatiques', 'Page servie, service actif, journaux.'], ['Idéal pour SNT, NSI, SIO', 'Du premier site au serveur HTTPS.']],
etapes: ['Ouvrez le lab', 'Installez et configurez le serveur', 'Actualisez le navigateur relié'] },
{ id: 'ide', cat: 'Apprendre', titre: 'Éditeur de code en ligne', demo: 'liste-attente.html', pour: 'Élèves, enseignants',
accroche: 'Python, SQL, web et Bash dans le navigateur, avec des exercices testés automatiquement.',
probleme: 'Installer un environnement de développement sur chaque poste et à la maison est une source d’échecs en début d’année.',
points: [['Quatre langages', 'Python, SQL, HTML/CSS/JS et Bash.'], ['Tests automatiques', 'L’élève sait immédiatement si son code est juste.'], ['Exercices progressifs', 'Du niveau découverte aux défis.'], ['Aucune installation', 'Fonctionne aussi à la maison.']],
etapes: ['Choisissez un exercice', 'L’élève code et lance les tests', 'Suivez les réussites dans le tableau de bord'] },
{ id: 'maison', cat: 'Apprendre', titre: 'Ressources à la maison', demo: 'liste-attente.html', pour: 'Élèves',
accroche: 'Pour aller plus loin chez soi : exercices, défis et plateformes reconnues.',
probleme: 'Les élèves motivés ne savent pas toujours où trouver des ressources sérieuses et adaptées à leur niveau.',
points: [['Parcours par niveau', 'Du lycée au supérieur.'], ['Plateformes reconnues', 'HackerRank, DataCamp, Root-Me, France-IOI.'], ['Défis sans prendre d’avance', 'Des notions connexes qui développent la culture générale.'], ['Suivi optionnel', 'L’enseignant voit les défis réalisés.']],
etapes: ['L’élève choisit un thème', 'Il réalise les exercices', 'Il partage sa progression s’il le souhaite'] },
{ id: 'bibliotheque', cat: 'Préparer', titre: 'Bibliothèque du prof', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Tous les chapitres du référentiel, avec leurs cours, QCM, TD et TP.',
probleme: 'Retrouver une ressource adaptée à un point précis du programme demande de fouiller plusieurs sites.',
points: [['Classée par référentiel', 'SNT, NSI, BTS SIO, CIEL, BUT, titres professionnels, master.'], ['Recherche', 'Par mot-clé, compétence ou type de ressource.'], ['Prêt à l’emploi', 'À projeter, imprimer ou donner en devoir.'], ['Personnalisable', 'Dupliquez et adaptez une ressource.']],
etapes: ['Choisissez le référentiel', 'Filtrez par chapitre', 'Ajoutez la ressource à votre séquence'] },
{ id: 'banque', cat: 'Préparer', titre: 'Banque de sujets', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Des centaines de questions et de sujets d’examen, à combiner et à adapter.',
probleme: 'Rédiger des sujets d’évaluation variés et équilibrés prend un temps considérable.',
points: [['Questions classées', 'Par chapitre, type et difficulté.'], ['Sujets blancs', 'Calqués sur les épreuves officielles.'], ['Vos questions', 'Ajoutez et partagez vos propres questions.'], ['Correction fournie', 'Éléments de correction et barème.']],
etapes: ['Recherchez des questions', 'Composez votre sujet', 'Programmez-le en examen'] },
{ id: 'generateur', cat: 'Préparer', titre: 'Générateur de TD', demo: 'liste-attente.html', pour: 'Enseignants, élèves',
accroche: 'Des exercices de calcul générés à l’infini : conversions, sous-réseaux, droits.',
probleme: 'Pour automatiser un savoir-faire, il faut beaucoup d’exercices différents, ce qu’aucun manuel ne fournit.',
points: [['Exercices aléatoires', 'Toujours nouveaux, jamais copiables.'], ['Correction immédiate', 'Avec la méthode détaillée.'], ['Niveaux réglables', 'De l’échauffement à l’approfondissement.'], ['Mode chronométré', 'Pour préparer l’examen.']],
etapes: ['Choisissez le type d’exercice', 'Réglez la difficulté', 'Lancez la série'] },
{ id: 'td-imprimable', cat: 'Préparer', titre: 'TD à imprimer', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Des fiches papier avec les étapes à suivre, des cases à remplir et la correction séparée.',
probleme: 'Tout ne se fait pas sur écran : certains exercices s’apprennent mieux sur papier, et la salle n’est pas toujours équipée.',
points: [['Mise en page soignée', 'Format A4, lisible en noir et blanc.'], ['Cases à remplir', 'Pour structurer la réponse.'], ['Correction à part', 'Imprimée séparément.'], ['Export PDF', 'Prêt pour la photocopieuse.']],
etapes: ['Choisissez le TD', 'Prévisualisez', 'Téléchargez le PDF'] },
{ id: 'quiz', cat: 'Évaluer', titre: 'Quiz flash', demo: 'liste-attente.html', pour: 'Enseignants, élèves',
accroche: 'Un quiz projeté en début d’heure, auquel les élèves répondent depuis leur téléphone ou leur PC.',
probleme: 'Vérifier ce qui a été retenu de la séance précédente prend du temps et ne touche que les élèves qui lèvent la main.',
points: [['Projection en classe', 'Diaporama plein écran, question par question.'], ['Réponse sur tout appareil', 'Dans le navigateur, avec les identifiants de l’élève.'], ['Présences', 'Vous voyez qui est connecté et qui manque.'], ['Résultats immédiats', 'Par question et par élève.']],
etapes: ['Choisissez ou créez un quiz', 'Projetez-le et donnez le code', 'Lisez les résultats en fin de quiz'] },
{ id: 'sujet', cat: 'Évaluer', titre: 'Créer un sujet', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Un sujet d’examen en cinq étapes : cadre, questions, barème, surveillance, publication.',
probleme: 'Organiser une évaluation en ligne fiable demande de penser au barème, aux aménagements et à la surveillance.',
points: [['Questions de la banque ou personnelles', 'QCM, calcul, code, lab, rédaction.'], ['Barème automatique', 'Ramené sur 20, avec pré-correction.'], ['Mode examen', 'Plein écran, détection des changements d’onglet.'], ['Aménagements', 'Tiers-temps appliqué automatiquement.']],
etapes: ['Définissez le cadre', 'Ajoutez les questions', 'Programmez l’examen'] },
{ id: 'devoirs', cat: 'Évaluer', titre: 'Devoirs maison', demo: 'liste-attente.html', pour: 'Enseignants, élèves',
accroche: 'Programmez un devoir, recevez les rendus, corrigez en ligne.',
probleme: 'Collecter des devoirs par mail ou sur clé USB, c’est des fichiers perdus, des retards non tracés et des relances.',
points: [['Programmation', 'Date d’ouverture et date limite.'], ['Rendus centralisés', 'Fichiers, code ou lab, horodatés.'], ['Relances automatiques', 'Pour les élèves en retard.'], ['Lien avec la correction', 'Les copies arrivent directement dans l’outil de correction.']],
etapes: ['Créez le devoir', 'Les élèves rendent en ligne', 'Corrigez et publiez les notes'] },
{ id: 'correction', cat: 'Évaluer', titre: 'Corriger les copies', demo: 'liste-attente.html', pour: 'Enseignants',
accroche: 'Une pré-correction selon votre barème, que vous validez et commentez.',
probleme: 'Corriger 30 copies de TP identiques prend des heures, surtout pour vérifier ce qu’une machine pourrait contrôler.',
points: [['Pré-correction', 'Calculs, commandes et code vérifiés automatiquement.'], ['Vous gardez la main', 'Rien n’est publié sans votre validation.'], ['Commentaires rapides', 'Remarques fréquentes en un clic.'], ['Navigation copie par copie', 'Avec la note recalculée à chaque ajustement.']],
etapes: ['Ouvrez le devoir', 'Validez ou ajustez la pré-correction', 'Publiez les notes'] },
{ id: 'fiche-eleve', cat: 'Suivre', titre: 'Fiche élève', demo: 'liste-attente.html', pour: 'Enseignants, CPE',
accroche: 'L’historique, les compétences et les observations d’un élève sur une seule page.',
probleme: 'Préparer un conseil de classe ou un entretien demande de rassembler des informations éparses.',
points: [['Compétences et évolution', 'Par bloc du référentiel.'], ['Historique', 'Labs, QCM, devoirs, examens.'], ['Observations partagées', 'Entre enseignants et vie scolaire.'], ['Export PDF', 'Pour le conseil de classe.']],
etapes: ['Ouvrez la fiche depuis le tableau de bord', 'Consultez l’historique', 'Ajoutez une observation'] },
{ id: 'messagerie', cat: 'Suivre', titre: 'Messagerie', demo: 'liste-attente.html', pour: 'Enseignants, élèves, CPE',
accroche: 'Des échanges encadrés entre enseignant, élève et vie scolaire.',
probleme: 'Les échanges par réseaux sociaux ou téléphone personnel sont difficiles à encadrer et à tracer.',
points: [['Conversations par élève et par classe', 'Avec la fiche élève à portée de clic.'], ['Réponses rapides', 'Envoyer un indice, joindre un cours, proposer un créneau.'], ['Pas de messages entre élèves', 'Échanges visibles par l’équipe pédagogique.'], ['Horaires conseillés', 'Pour respecter le droit à la déconnexion.']],
etapes: ['Ouvrez une conversation', 'Répondez ou joignez une ressource', 'Associez la CPE si besoin'] },
{ id: 'export', cat: 'Suivre', titre: 'Export Pronote / ENT', demo: 'liste-attente.html', pour: 'Enseignants, scolarité',
accroche: 'Notes, présences et appréciations prêtes à charger dans votre logiciel de vie scolaire.',
probleme: 'Ressaisir les notes d’un outil à l’autre est une perte de temps et une source d’erreurs.',
points: [['Fichier CSV compatible', 'Format attendu par les principaux logiciels de vie scolaire.'], ['Choix du contenu', 'Notes, moyennes par compétence, présences, appréciations.'], ['Aperçu avant export', 'Pour vérifier les colonnes.'], ['Guide d’import', 'Étapes détaillées pour chaque logiciel.']],
etapes: ['Choisissez le contenu et la période', 'Vérifiez l’aperçu', 'Téléchargez et importez le fichier'] }
];