Files
siop2/docs/02-design/maquettes/maquette-mobile-assistant.html
pr-daaif ac8b92e9c5 feat(r6): R6.5 — Assistant mobile (chat sourcé + dictée)
Maquette dédiée validée (docs/02-design/maquettes/maquette-mobile-assistant.html,
3 écrans) — la seule sous-étape de R6 à avoir eu son propre tour de
design-first plutôt qu'une exécution directe de la maquette R6 initiale,
un chat sourcé étant un patron d'écran neuf. D1 un échange à la fois ; D2
"Voir le document" → métadonnées seules (R6.3), "Ouvrir l'OT" → fiche R4 ;
D3 refus chiffré + avertissement permanents, identiques au web ; D4
Assistant rejoint Pilotage pour tout rôle avec WORK_ORDERS.view ; D5
(ajoutée en revue) — la question peut être tapée OU dictée, même pipeline
que la dictée déjà livrée en clôture (ADR-004 §5, faster-whisper local,
audio jamais persisté), la transcription remplit le champ, jamais d'envoi
automatique.

api/assistant.ts (useAskAssistant, 503 géré comme le web). Écran Assistant :
chat un échange à la fois, citations numérotées, sources avec extrait
exact, refus honnête chiffré + Reformuler. Micro dans la barre de saisie :
réutilise telle quelle la mécanique de cloture.tsx (useAudioRecorder,
setAudioModeAsync, useTranscription, purge quoi qu'il arrive) — pipeline
déjà recetté sur iPhone physique (01/08), aucun nouveau bug à découvrir.

Fiche document (bibliotheque/[id].tsx, nouveau) — la liste R6.3 y mène
aussi désormais. Menu : Assistant route réellement — le Menu R6 n'a plus
d'entrée "à venir" dans les 4 groupes (Catégories exceptée, admin, hors
périmètre mobile).

R6 fonctionnellement complet (Exploitation/Parc/Ressources/Pilotage,
Assistant inclus, pour tous les rôles) — reste une recette complète avant
de considérer R6 close au sens R0→R5.

Typecheck propre, 17 tests Jest, lint 5/5 paquets. Contrat non touché.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 12:18:25 +01:00

356 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SIOP V2 — Maquette HD · Assistant mobile</title>
</head>
<body>
<!--
SIOP V2 — Maquette HD « Assistant mobile » (design-first).
À VALIDER PAR LE RÉFÉRENT AVANT TOUT CODE EXPO (principe n°1).
Suite de R6 (mobile ouvert à tous les rôles) : le Menu avait laissé
« Assistant » en « à venir » — un chat sourcé est un patron d'écran neuf,
jamais maquetté sur mobile (contrairement à Sites/Stock/Personnes qui
réutilisaient Carte/LigneInfo/EnteteFiche déjà validés). Reprend le
contenu et les règles de l'Assistant web (maquette-r5.html, écrans 1-2,
D2 « sourcé ou silencieux ») porté au format téléphone. Tokens et gabarit
téléphone repris tels quels de maquette-mobile-tous-roles.html.
Décisions proposées à validation :
D1 — Un échange à la fois (question → réponse), comme le web ; pas
d'historique de conversation multi-tours conservé entre les sessions
(même limite que le web aujourd'hui).
D2 — « Ouvrir » une source d'historique (OT) mène à la fiche OT R4 telle
quelle (déjà générique, aucune dépendance nouvelle). « Ouvrir » une
source document mène à ses MÉTADONNÉES seulement (même écran que la
bibliothèque R6.3) — l'ouverture du fichier lui-même reste au web
tant qu'`expo-sharing` n'est pas ajouté (même arbitrage que R6.3/6.4,
pas de nouvelle dépendance native au milieu d'une passe).
D3 — Le refus chiffré (« cherché dans N documents, M bilans ») et
l'avertissement « l'IA propose, vous validez » sont permanents,
identiques au web — aucune règle nouvelle, juste portée au pouce.
D4 — Assistant rejoint le groupe Pilotage du Menu pour tous les rôles
ayant WORK_ORDERS.view (même garde que le web).
D5 — La question peut être TAPÉE OU DICTÉE (référent, 02/08) : réutilise
EXACTEMENT le pipeline déjà validé (ADR-004 §5, faster-whisper local,
opt-in, audio jamais persisté — même écran Voix que la clôture R4/R5).
La transcription REMPLIT le champ de saisie, éditable — jamais
d'envoi automatique après dictée : l'humain relit sa question comme
il relirait n'importe quel texte tapé, puis appuie sur Envoyer.
-->
<style>
/* ═══ Tokens (répliques de ../tokens.css) ═══ */
:root{
--primaire:#1f4fb8;--primaire-actif:#1a439c;--primaire-doux:#eaf0fb;
--safran:#dd8a0b;--safran-doux:#fdf3e3;
--fond:#f5f7fa;--surface:#ffffff;--surface-2:#eef2f7;
--bordure:#dce3ec;--bordure-forte:#b9c4d4;
--encre:#1b2534;--encre-2:#55647a;--encre-3:#8494ab;
--st-ouvert:#3d6fe0;--st-ouvert-fond:#e9effc;--st-encours:#6d5bd8;--st-encours-fond:#efecfa;
--st-attente:#b96f07;--st-attente-fond:#fbf1df;--st-termine:#178a50;--st-termine-fond:#e6f5ec;
--st-annule:#68788f;--st-annule-fond:#edf0f4;
--prio-bloque:#d92626;--prio-bloque-fond:#fdeaea;--prio-haute:#d92626;
--prio-moyenne:#b96f07;--prio-basse:#178a50;--prio-aucune:#8494ab;
--succes:#178a50;--alerte:#b96f07;--danger:#d92626;--info:#3d6fe0;
--nav-fond:#16233b;--nav-encre:#c6d2e4;--nav-encre-vif:#ffffff;--nav-bordure:#24344f;
--police-ui:"Manrope","Avenir Next","Segoe UI Variable",system-ui,sans-serif;
--rayon:10px;--rayon-controle:8px;--ombre-menu:0 8px 24px rgb(16 30 54/.14);
--transition:140ms ease-out;
}
@media (prefers-color-scheme:dark){:root{
--primaire:#6e92e8;--primaire-actif:#8facf0;--primaire-doux:#1d2c4c;
--safran:#e89a1f;--safran-doux:#33270f;
--fond:#0f1622;--surface:#182234;--surface-2:#1e2a40;
--bordure:#2b3850;--bordure-forte:#3d4d6b;
--encre:#e8edf5;--encre-2:#a7b4c8;--encre-3:#6d7d96;
--st-ouvert:#7da2ee;--st-ouvert-fond:#1c2a47;--st-encours:#a394ec;--st-encours-fond:#262040;
--st-attente:#e0a33c;--st-attente-fond:#322510;--st-termine:#4bc084;--st-termine-fond:#12301f;
--st-annule:#93a3ba;--st-annule-fond:#222d3f;
--prio-bloque:#f26d6d;--prio-bloque-fond:#3a1414;--prio-haute:#f26d6d;
--prio-moyenne:#e0a33c;--prio-basse:#4bc084;--prio-aucune:#6d7d96;
--succes:#4bc084;--alerte:#e0a33c;--danger:#f26d6d;--info:#7da2ee;
--nav-fond:#0c1524;--nav-encre:#a7b4c8;--nav-encre-vif:#f2f6fc;--nav-bordure:#1e2c44;
--ombre-menu:0 8px 24px rgb(0 0 0/.45);
}}
:root[data-theme="light"]{
--primaire:#1f4fb8;--primaire-actif:#1a439c;--primaire-doux:#eaf0fb;
--safran:#dd8a0b;--safran-doux:#fdf3e3;
--fond:#f5f7fa;--surface:#ffffff;--surface-2:#eef2f7;
--bordure:#dce3ec;--bordure-forte:#b9c4d4;
--encre:#1b2534;--encre-2:#55647a;--encre-3:#8494ab;
--st-ouvert:#3d6fe0;--st-ouvert-fond:#e9effc;--st-encours:#6d5bd8;--st-encours-fond:#efecfa;
--st-attente:#b96f07;--st-attente-fond:#fbf1df;--st-termine:#178a50;--st-termine-fond:#e6f5ec;
--st-annule:#68788f;--st-annule-fond:#edf0f4;
--prio-bloque:#d92626;--prio-bloque-fond:#fdeaea;--prio-haute:#d92626;
--prio-moyenne:#b96f07;--prio-basse:#178a50;--prio-aucune:#8494ab;
--succes:#178a50;--alerte:#b96f07;--danger:#d92626;--info:#3d6fe0;
--nav-fond:#16233b;--nav-encre:#c6d2e4;--nav-encre-vif:#ffffff;--nav-bordure:#24344f;
--ombre-menu:0 8px 24px rgb(16 30 54/.14);
}
:root[data-theme="dark"]{
--primaire:#6e92e8;--primaire-actif:#8facf0;--primaire-doux:#1d2c4c;
--safran:#e89a1f;--safran-doux:#33270f;
--fond:#0f1622;--surface:#182234;--surface-2:#1e2a40;
--bordure:#2b3850;--bordure-forte:#3d4d6b;
--encre:#e8edf5;--encre-2:#a7b4c8;--encre-3:#6d7d96;
--st-ouvert:#7da2ee;--st-ouvert-fond:#1c2a47;--st-encours:#a394ec;--st-encours-fond:#262040;
--st-attente:#e0a33c;--st-attente-fond:#322510;--st-termine:#4bc084;--st-termine-fond:#12301f;
--st-annule:#93a3ba;--st-annule-fond:#222d3f;
--prio-bloque:#f26d6d;--prio-bloque-fond:#3a1414;--prio-haute:#f26d6d;
--prio-moyenne:#e0a33c;--prio-basse:#4bc084;--prio-aucune:#6d7d96;
--succes:#4bc084;--alerte:#e0a33c;--danger:#f26d6d;--info:#7da2ee;
--nav-fond:#0c1524;--nav-encre:#a7b4c8;--nav-encre-vif:#f2f6fc;--nav-bordure:#1e2c44;
--ombre-menu:0 8px 24px rgb(0 0 0/.45);
}
/* ═══ Base ═══ */
*{box-sizing:border-box;margin:0}
html,body{background:var(--fond)}
body{font-family:var(--police-ui);color:var(--encre);font-size:14px;line-height:1.5}
button{font:inherit;cursor:pointer;border:0;background:none;color:inherit}
button:focus-visible,a:focus-visible{outline:2px solid var(--primaire);outline-offset:2px;border-radius:4px}
/* ═══ Barre de revue (outil maquette, pas l'app) ═══ */
.revue{position:sticky;top:0;z-index:50;display:flex;align-items:center;gap:12px;flex-wrap:wrap;
padding:10px 16px;background:var(--nav-fond);color:var(--nav-encre);font-size:13px}
.revue b{color:var(--nav-encre-vif);letter-spacing:.02em}
.revue .onglets{display:flex;gap:4px;flex-wrap:wrap}
.revue .onglets button{padding:6px 10px;border-radius:6px;color:var(--nav-encre)}
.revue .onglets button:hover{background:rgb(255 255 255/.08);color:var(--nav-encre-vif)}
.revue .onglets button[aria-selected="true"]{background:rgb(255 255 255/.12);color:var(--nav-encre-vif);
box-shadow:inset 3px 0 0 var(--safran)}
.revue .droite{margin-left:auto;display:flex;align-items:center;gap:8px}
.revue .theme{padding:6px 10px;border:1px solid var(--nav-bordure);border-radius:6px}
.note-ecran{max-width:1120px;margin:14px auto 0;padding:0 20px;color:var(--encre-2);font-size:13px}
.note-ecran b{color:var(--encre)}
/* ═══ Écrans / téléphone (repris de maquette-mobile-tous-roles) ═══ */
.ecran{display:none;max-width:1120px;margin:18px auto 44px;padding:0 20px}
.ecran.actif{display:block}
.tels{display:flex;gap:28px;justify-content:center;flex-wrap:wrap}
.tel{width:310px;border:1px solid var(--bordure-forte);border-radius:28px;overflow:hidden;background:var(--fond);
box-shadow:var(--ombre-menu);display:flex;flex-direction:column}
.tel .encoche{height:26px;background:var(--nav-fond);display:flex;justify-content:center;align-items:center;flex:none}
.tel .encoche i{width:70px;height:7px;border-radius:999px;background:rgb(255 255 255/.18)}
.tel .legende{flex:none;text-align:center;font-size:11.5px;font-weight:700;letter-spacing:.05em;
text-transform:uppercase;color:var(--encre-3);padding:8px;background:var(--surface-2)}
.ecran-tel{padding:14px;display:flex;flex-direction:column;gap:10px;min-height:560px}
.entete-tel{display:flex;align-items:center;gap:8px}
.entete-tel .retour{font-size:20px;color:var(--primaire);font-weight:700}
.entete-tel b{font-size:16px;letter-spacing:.02em}
.btn-tel{display:flex;justify-content:center;align-items:center;gap:8px;padding:11px;border-radius:10px;
font-weight:700;font-size:13.5px;background:var(--primaire);color:#fff;width:100%}
.btn-tel.contour{background:var(--surface);color:var(--primaire);border:1.5px solid var(--primaire)}
.btn-tel.gris{background:var(--bordure-forte);color:var(--surface)}
/* ═══ Nouveautés : chat au format téléphone ═══ */
.chat-tel{display:flex;flex-direction:column;gap:10px;flex:1}
.msg-q-tel{align-self:flex-end;background:var(--primaire);color:#fff;border-radius:13px 13px 3px 13px;
padding:9px 12px;max-width:85%;font-size:12.5px;font-family:'Manrope',sans-serif}
.msg-r-tel{background:var(--surface);border:1px solid var(--bordure);border-radius:13px 13px 13px 3px;
padding:11px 12px;display:flex;flex-direction:column;gap:9px;font-size:12.5px}
.cite-tel{display:inline-flex;align-items:center;justify-content:center;min-width:15px;height:15px;
border-radius:5px;background:var(--primaire-doux);color:var(--primaire);font-size:10px;font-weight:800;
vertical-align:1px;margin:0 1px}
.sources-tel{display:flex;flex-direction:column;gap:7px;border-top:1px dashed var(--bordure);padding-top:9px}
.source-tel{display:flex;flex-direction:column;gap:4px;background:var(--surface-2);border-radius:9px;padding:8px 9px}
.source-tel .entete-source{display:flex;align-items:center;gap:7px}
.source-tel .no{flex:none;width:16px;height:16px;border-radius:5px;background:var(--primaire-doux);
color:var(--primaire);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:800}
.source-tel b{font-size:11.5px;flex:1}
.source-tel .ou{color:var(--encre-2);font-size:10.5px;margin-left:23px}
.source-tel .extrait{color:var(--encre-2);font-size:11px;font-style:italic;border-left:2px solid var(--safran);
padding-left:7px;margin-left:23px}
.source-tel .ouvrir{margin-left:23px;align-self:flex-start;color:var(--primaire);font-weight:700;font-size:11px}
.avert-tel{display:flex;gap:6px;align-items:flex-start;background:var(--safran-doux);color:var(--alerte);
border-radius:9px;padding:8px 9px;font-size:10.5px;font-weight:600;line-height:1.4}
.refus-tel{background:var(--surface);border:1.5px dashed var(--bordure-forte);border-radius:13px;
padding:11px 12px;display:flex;flex-direction:column;gap:8px;font-size:12.5px}
.refus-tel b{color:var(--encre)}
.refus-tel .pourquoi{color:var(--encre-2);font-size:11.5px}
.saisie-chat-tel{margin-top:auto;display:flex;gap:8px;align-items:center;border:1.5px solid var(--bordure-forte);
border-radius:10px;background:var(--surface);padding:9px 10px}
.saisie-chat-tel span.txt{flex:1;color:var(--encre-3);font-size:12px}
.saisie-chat-tel span.txt.rempli{color:var(--encre);font-weight:600}
.saisie-chat-tel .envoyer{flex:none;color:var(--primaire);font-weight:800;font-size:12.5px}
.micro-mini{flex:none;width:26px;height:26px;border-radius:50%;background:var(--primaire-doux);color:var(--primaire);
display:flex;align-items:center;justify-content:center;font-size:13px}
.rappel-tel{color:var(--encre-3);font-size:11px;text-align:center;padding:8px}
/* Dictée de la question (D5) — même patron que l'écran Voix R5 */
.dictee-tel{margin-top:auto;display:flex;flex-direction:column;align-items:center;gap:10px;
border:1.5px solid var(--bordure);border-radius:13px;background:var(--surface);padding:18px 12px}
.micro-gd{width:48px;height:48px;border-radius:50%;background:var(--prio-bloque);color:#fff;display:flex;
align-items:center;justify-content:center;font-size:19px}
.onde-tel{display:flex;gap:3px;align-items:center;justify-content:center;height:22px}
.onde-tel i{width:3px;border-radius:2px;background:var(--primaire)}
.dictee-tel .provisoire{font-size:12px;color:var(--encre-2);text-align:center;font-style:italic}
.purge-tel{display:flex;align-items:center;gap:6px;font-size:10.5px;font-weight:700;color:var(--st-termine)}
</style>
<header class="revue">
<b>SIOP · Maquette — Assistant mobile</b>
<nav class="onglets" role="tablist" aria-label="Écrans">
<button role="tab" aria-selected="true" data-cible="sourcee">1 · Réponse sourcée</button>
<button role="tab" aria-selected="false" data-cible="refus">2 · Sans source = refus</button>
<button role="tab" aria-selected="false" data-cible="dictee">3 · Dictée de la question</button>
</nav>
<div class="droite"><button class="theme" id="btn-theme">Thème : auto</button></div>
</header>
<!-- ═══ 1 · RÉPONSE SOURCÉE ═══ -->
<p class="note-ecran" data-note="sourcee"><b>Intention :</b> même contenu, mêmes règles que
l'Assistant web (maquette-r5, D2) — chaque affirmation porte ses <b>citations numérotées</b>,
chaque source montre le document ou l'historique, la localisation précise et l'<b>extrait
exact</b>. « Ouvrir l'OT » mène à la fiche R4 (déjà générique) ; « Voir le document » mène à ses
métadonnées (bibliothèque R6.3) — l'ouverture du fichier lui-même reste au web pour l'instant
(D2, `expo-sharing` non ajouté à la légère). L'avertissement est permanent, pas un disclaimer
caché.</p>
<section class="ecran actif" id="sourcee">
<div class="tels">
<div class="tel">
<div class="encoche"><i></i></div>
<div class="legende">Gestionnaire — question posée</div>
<div class="ecran-tel">
<div class="entete-tel"><span class="retour"></span><b>Assistant</b></div>
<div class="chat-tel">
<div class="msg-q-tel">Quel couple de serrage pour les coulisseaux de guides du Gen2 ?</div>
<div class="rappel-tel">Recherche dans le corpus…</div>
</div>
<div class="saisie-chat-tel"><span class="micro-mini">🎙</span><span class="txt">Poser une question…</span><span class="envoyer">Envoyer</span></div>
</div>
</div>
<div class="tel">
<div class="encoche"><i></i></div>
<div class="legende">Réponse sourcée + citations</div>
<div class="ecran-tel">
<div class="entete-tel"><span class="retour"></span><b>Assistant</b></div>
<div class="chat-tel">
<div class="msg-q-tel">Quel couple de serrage pour les coulisseaux de guides du Gen2 ?</div>
<div class="msg-r-tel">
<p>Pour l'Otis <b>Gen2 Premier</b>, la notice prescrit <b>25 N·m</b> pour les vis de
fixation des coulisseaux<span class="cite-tel">1</span>, jeu latéral max. 0,5 mm
<span class="cite-tel">1</span>. Appliqué sur l'ascenseur A1 le 17 juillet
<span class="cite-tel">2</span>.</p>
<div class="sources-tel">
<div class="source-tel">
<div class="entete-source"><span class="no">1</span><b>Notice Otis Gen2 Premier.pdf</b></div>
<div class="ou">Bibliothèque · Asc. A1 · page 42</div>
<div class="extrait">« Serrer au couple de 25 N·m ; jeu latéral maximal : 0,5 mm. »</div>
<div class="ouvrir">Voir le document</div>
</div>
<div class="source-tel">
<div class="entete-source"><span class="no">2</span><b>OT-2026-0341 — Bruit anormal en gaine</b></div>
<div class="ou">Historique · clôturé le 17/07/2026</div>
<div class="extrait">« Coulisseau de guide 16 mm × 2 — remplacement effectué. »</div>
<div class="ouvrir">Ouvrir l'OT</div>
</div>
</div>
<div class="avert-tel">⚠ L'IA propose, vous validez : vérifiez la notice avant d'agir sur l'appareil.</div>
</div>
</div>
<div class="saisie-chat-tel"><span class="micro-mini">🎙</span><span class="txt">Poser une question…</span><span class="envoyer">Envoyer</span></div>
</div>
</div>
</div>
</section>
<!-- ═══ 2 · SANS SOURCE = REFUS ═══ -->
<p class="note-ecran" data-note="refus" hidden><b>Intention :</b> l'anti-hallucination rendue
visible, comme au web — quand le corpus ne porte pas la réponse, l'assistant le dit, CHIFFRE ce
qu'il a cherché, et propose l'action utile. Jamais de réponse inventée « pour faire plaisir ».</p>
<section class="ecran" id="refus">
<div class="tels">
<div class="tel">
<div class="encoche"><i></i></div>
<div class="legende">Refus honnête et chiffré</div>
<div class="ecran-tel">
<div class="entete-tel"><span class="retour"></span><b>Assistant</b></div>
<div class="chat-tel">
<div class="msg-q-tel">Procédure de remplacement du variateur KONE ?</div>
<div class="refus-tel">
<b>Je ne trouve pas de source fiable dans votre bibliothèque — je préfère ne pas inventer.</b>
<div class="pourquoi">J'ai cherché dans 6 documents indexés et 214 bilans d'intervention :
aucune notice KONE, aucun historique de variateur sur ce parc.</div>
<div class="btn-tel contour">Reformuler ma question</div>
</div>
</div>
<div class="saisie-chat-tel"><span class="micro-mini">🎙</span><span class="txt">Poser une question…</span><span class="envoyer">Envoyer</span></div>
</div>
</div>
</div>
</section>
<!-- ═══ 3 · DICTÉE DE LA QUESTION ═══ -->
<p class="note-ecran" data-note="dictee" hidden><b>Intention :</b> même pipeline que la dictée déjà
livrée en clôture (ADR-004 §5) — appui sur le micro du champ de saisie, transcription locale
(faster-whisper), audio purgé immédiatement. La transcription REMPLIT le champ, éditable :
l'humain relit sa question avant d'appuyer sur Envoyer, exactement comme s'il l'avait tapée.</p>
<section class="ecran" id="dictee">
<div class="tels">
<div class="tel">
<div class="encoche"><i></i></div>
<div class="legende">Pendant l'enregistrement</div>
<div class="ecran-tel">
<div class="entete-tel"><span class="retour"></span><b>Assistant</b></div>
<div class="chat-tel">
<div class="rappel-tel">Posez votre question, notice ou historique…</div>
</div>
<div class="dictee-tel">
<div class="micro-gd">🎙</div>
<div class="onde-tel">
<i style="height:7px"></i><i style="height:16px"></i><i style="height:11px"></i>
<i style="height:20px"></i><i style="height:9px"></i><i style="height:14px"></i>
<i style="height:6px"></i>
</div>
<div class="provisoire">« …quel couple de serrage pour les coulisseaux… »</div>
<div class="btn-tel" style="background:var(--danger)">■ Terminer la dictée</div>
</div>
</div>
</div>
<div class="tel">
<div class="encoche"><i></i></div>
<div class="legende">Transcrite — relecture avant envoi</div>
<div class="ecran-tel">
<div class="entete-tel"><span class="retour"></span><b>Assistant</b></div>
<div class="chat-tel">
<div class="rappel-tel">Posez votre question, notice ou historique…</div>
</div>
<div class="saisie-chat-tel" style="align-items:flex-start">
<span class="micro-mini">🎙</span>
<span class="txt rempli">Quel couple de serrage pour les coulisseaux de guides du Gen2 ?</span>
<span class="envoyer">Envoyer</span>
</div>
<div class="purge-tel">✓ Audio purgé (2,1 s après transcription) — relisez avant d'envoyer</div>
</div>
</div>
</div>
</section>
<script>
(function(){
var onglets=document.querySelectorAll('.revue .onglets button');
var ecrans=document.querySelectorAll('.ecran');
var notes=document.querySelectorAll('.note-ecran');
onglets.forEach(function(b){b.addEventListener('click',function(){
onglets.forEach(function(x){x.setAttribute('aria-selected','false')});
b.setAttribute('aria-selected','true');
var cible=b.dataset.cible;
ecrans.forEach(function(e){e.classList.toggle('actif',e.id===cible)});
notes.forEach(function(n){n.hidden=(n.dataset.note!==cible)});
window.scrollTo({top:0});
})});
var ordre=['auto','light','dark'];var i=0;
var bt=document.getElementById('btn-theme');
bt.addEventListener('click',function(){
i=(i+1)%3;var m=ordre[i];
if(m==='auto'){document.documentElement.removeAttribute('data-theme')}
else{document.documentElement.setAttribute('data-theme',m)}
bt.textContent='Thème : '+(m==='auto'?'auto':(m==='light'?'clair':'sombre'));
});
})();
</script>
</body>
</html>