DOCS/claude design/statistics-screen.html
Thomas Fransolet a5a8ecdb20 Documentation interne MyInfoMate / Unov
Import initial de la documentation : statut, roadmap, plans V1/V2,
specs verticales (creche, sport), audits securite, plan de test,
analyse concurrentielle et maquettes de design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 11:17:01 +02:00

443 lines
27 KiB
HTML

<!doctype html><html lang="fr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Maquette rapatriee depuis l'artifact 052fe8f3-0288-4847-b63f-4c7de06068ec le 2026-08-11.
Source de verite du design : ce fichier. L'artifact ne sert qu'a la diffusion.
Specification : DOCS/v2/stats-screen-plan.md -->
<title>Écran Statistiques — maquette manager-app</title>
<style>
:root {
--ground:#EDF0F4; --surface:#FFFFFF; --surface-2:#F3F5F8; --surface-3:#E7EBF1;
--ink:#14202B; --ink-2:#4A5A6B; --ink-3:#7C8B9A;
--line:#D6DDE5; --line-soft:#E6EBF1;
--brand:#264863; --brand-2:#3C6C90; --brand-fade:rgba(38,72,99,.14);
--on-brand:#FFFFFF;
--good:#1F6B4D; --warning:#9A6608; --serious:#A8322A;
--shadow:0 1px 2px rgba(20,32,43,.05), 0 4px 14px rgba(20,32,43,.05);
--sans: ui-sans-serif, -apple-system, "Segoe UI", system-ui, "Helvetica Neue", Arial, sans-serif;
--mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--ground:#0E141B; --surface:#18222C; --surface-2:#1E2A35; --surface-3:#26333F;
--ink:#E6ECF2; --ink-2:#A3B2C0; --ink-3:#74879A;
--line:#2C3A48; --line-soft:#243140;
--brand:#7FA8C9; --brand-2:#A3C4DD; --brand-fade:rgba(127,168,201,.20); --on-brand:#0E141B;
--good:#6FBF97; --warning:#D6A343; --serious:#E08078;
--shadow:0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.22);
}
}
:root[data-theme="dark"] {
--ground:#0E141B; --surface:#18222C; --surface-2:#1E2A35; --surface-3:#26333F;
--ink:#E6ECF2; --ink-2:#A3B2C0; --ink-3:#74879A;
--line:#2C3A48; --line-soft:#243140;
--brand:#7FA8C9; --brand-2:#A3C4DD; --brand-fade:rgba(127,168,201,.20); --on-brand:#0E141B;
--good:#6FBF97; --warning:#D6A343; --serious:#E08078;
--shadow:0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.22);
}
:root[data-theme="light"] {
--ground:#EDF0F4; --surface:#FFFFFF; --surface-2:#F3F5F8; --surface-3:#E7EBF1;
--ink:#14202B; --ink-2:#4A5A6B; --ink-3:#7C8B9A;
--line:#D6DDE5; --line-soft:#E6EBF1;
--brand:#264863; --brand-2:#3C6C90; --brand-fade:rgba(38,72,99,.14); --on-brand:#FFFFFF;
--good:#1F6B4D; --warning:#9A6608; --serious:#A8322A;
--shadow:0 1px 2px rgba(20,32,43,.05), 0 4px 14px rgba(20,32,43,.05);
}
* { box-sizing:border-box; }
body { margin:0; background:var(--ground); color:var(--ink); font-family:var(--sans); font-size:15px; line-height:1.5; -webkit-font-smoothing:antialiased; }
.page { max-width:1280px; margin:0 auto; padding:32px 22px 64px; }
.note { background:var(--surface); border:1px solid var(--line); border-left:3px solid var(--brand); border-radius:6px; padding:13px 16px; margin-bottom:26px; }
.note strong { display:block; font-size:13.5px; margin-bottom:2px; }
.note span { font-size:13px; color:var(--ink-2); }
.demo { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-top:12px; padding-top:12px; border-top:1px dashed var(--line); }
.demohint { font-size:12.5px; color:var(--ink-3); }
.app { display:grid; grid-template-columns:212px 1fr; background:var(--surface); border:1px solid var(--line); border-radius:10px; overflow:hidden; box-shadow:var(--shadow); }
.rail { background:var(--surface-2); border-right:1px solid var(--line); padding:18px 0; }
.rail .brandline { font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-3); padding:0 18px 14px; }
.rail a { display:block; padding:9px 18px; font-size:13.5px; color:var(--ink-2); text-decoration:none; border-left:3px solid transparent; }
.rail a.on { color:var(--ink); font-weight:600; background:var(--surface-3); border-left-color:var(--brand); }
.main { min-width:0; padding:24px 28px 32px; }
@media (max-width:900px){ .app { grid-template-columns:1fr; } .rail { display:none; } .main { padding:20px 16px 26px; } }
/* header */
.top { display:flex; flex-wrap:wrap; align-items:flex-start; justify-content:space-between; gap:16px; }
.top h1 { margin:0; font-size:23px; font-weight:700; letter-spacing:-.018em; }
.top .range { margin:4px 0 0; font-size:13.5px; color:var(--ink-3); }
.btn { display:inline-flex; align-items:center; gap:8px; background:var(--brand); color:var(--on-brand); border:none; border-radius:6px; padding:10px 16px; font-family:inherit; font-size:13.5px; font-weight:600; cursor:pointer; }
.btn:hover { background:var(--brand-2); }
.btn:focus-visible { outline:2px solid var(--brand); outline-offset:2px; }
.btn svg { width:16px; height:16px; }
/* filters — one row, one treatment */
.filters { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:18px 0 0; padding:12px 0; border-top:1px solid var(--line-soft); border-bottom:1px solid var(--line-soft); }
.flabel { font-family:var(--mono); font-size:10.5px; letter-spacing:.09em; text-transform:uppercase; color:var(--ink-3); margin-right:2px; }
.seg { display:inline-flex; background:var(--surface-2); border:1px solid var(--line); border-radius:6px; overflow:hidden; }
.seg button { appearance:none; background:none; border:none; padding:6px 13px; font-family:inherit; font-size:12.5px; color:var(--ink-2); cursor:pointer; }
.seg button + button { border-left:1px solid var(--line); }
.seg button[aria-pressed="true"] { background:var(--brand); color:var(--on-brand); font-weight:600; }
.seg button:focus-visible { outline:2px solid var(--brand); outline-offset:-2px; }
.sep { width:1px; height:22px; background:var(--line); margin:0 4px; }
.chip { display:inline-flex; align-items:baseline; gap:7px; background:var(--surface-2); border:1px solid var(--line); border-radius:999px; padding:5px 13px; font-family:inherit; font-size:12.5px; color:var(--ink-2); cursor:pointer; }
.chip b { font-family:var(--mono); font-size:11.5px; font-variant-numeric:tabular-nums; color:var(--ink-3); }
.chip[aria-pressed="true"] { background:var(--brand); border-color:var(--brand); color:var(--on-brand); font-weight:600; }
.chip[aria-pressed="true"] b { color:var(--on-brand); opacity:.8; }
.chip:focus-visible { outline:2px solid var(--brand); outline-offset:2px; }
/* takeaway */
.takeaway { margin:20px 0 0; padding:15px 18px; background:var(--surface-2); border:1px solid var(--line-soft); border-radius:8px; }
.takeaway p { margin:0; font-size:14.5px; line-height:1.55; max-width:78ch; }
.takeaway p + p { margin-top:6px; }
.takeaway em { font-style:normal; font-weight:650; }
/* kpis */
.kpis { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:1px; background:var(--line); border:1px solid var(--line); border-radius:8px; overflow:hidden; margin-top:18px; }
.kpi { background:var(--surface); padding:15px 17px 16px; }
.kpi .k { display:block; font-size:11.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-3); margin-bottom:7px; }
.kpi .n { font-family:var(--mono); font-size:29px; font-weight:600; font-variant-numeric:tabular-nums; letter-spacing:-.025em; line-height:1; }
.kpi .n small { font-size:15px; font-weight:500; letter-spacing:0; color:var(--ink-2); }
.kpi .d { display:inline-flex; align-items:center; gap:4px; margin-top:8px; font-size:12px; font-variant-numeric:tabular-nums; }
.up { color:var(--good); } .flat { color:var(--ink-3); } .new { color:var(--brand); }
/* cards */
.card { background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:18px 19px 20px; }
.card h2 { margin:0 0 2px; font-size:14.5px; font-weight:700; }
.card .sub { margin:0 0 16px; font-size:12.5px; color:var(--ink-3); }
.row2 { display:grid; grid-template-columns:1.35fr 1fr; gap:16px; align-items:stretch; margin-top:16px; }
@media (max-width:1040px){ .row2 { grid-template-columns:1fr; } }
.col { display:flex; flex-direction:column; gap:16px; min-width:0; }
.col > .card { flex:1 1 auto; }
/* la carte contenus remplit la hauteur : les barres se répartissent au lieu de laisser un vide */
.card.fill { display:flex; flex-direction:column; }
.card.fill .bars { flex:1 1 auto; justify-content:space-around; }
/* état mono-canal : pas de filtre canal, pas de carte Canaux */
.mono .chan-filter { display:none; }
.mono .card-canaux { display:none; }
/* trend */
.chartwrap { position:relative; }
svg.trend { display:block; width:100%; height:auto; overflow:visible; }
.tip { position:absolute; pointer-events:none; background:var(--ink); color:var(--surface); border-radius:5px; padding:6px 9px; font-size:12px; line-height:1.35; white-space:nowrap; transform:translate(-50%,-115%); opacity:0; transition:opacity .1s; }
.tip b { font-family:var(--mono); font-variant-numeric:tabular-nums; }
.legendline { display:flex; align-items:center; gap:14px; margin-top:10px; font-size:12px; color:var(--ink-3); }
.wkkey { display:inline-flex; align-items:center; gap:6px; }
.wkkey i { width:13px; height:11px; background:var(--surface-3); border-radius:2px; display:inline-block; }
/* bars */
.bars { display:flex; flex-direction:column; gap:11px; }
.bar { display:grid; grid-template-columns:1fr; gap:5px; }
.bar .top2 { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.bar .lab { font-size:13.5px; color:var(--ink); }
.bar .val { font-family:var(--mono); font-size:12.5px; font-variant-numeric:tabular-nums; color:var(--ink-2); }
.bar .track { height:9px; background:var(--surface-3); border-radius:4px; }
.bar .fill { height:100%; background:var(--brand); border-radius:0 4px 4px 0; }
.bar:hover .fill { background:var(--brand-2); }
.barsub { margin-top:14px; font-size:12.5px; color:var(--ink-3); }
/* report */
.report { display:grid; grid-template-columns:126px 1fr; gap:20px; align-items:center; background:var(--surface); border:1px solid var(--brand); border-radius:8px; padding:20px; margin-top:16px; box-shadow:inset 3px 0 0 var(--brand); }
@media (max-width:640px){ .report { grid-template-columns:1fr; } }
.doc { background:var(--surface); border:1px solid var(--line); border-radius:4px; padding:13px 11px; box-shadow:var(--shadow); }
.doc .band { height:16px; background:var(--brand); border-radius:2px; margin-bottom:9px; }
.doc .l { height:4px; background:var(--surface-3); border-radius:2px; margin-bottom:5px; }
.doc .l.s { width:62%; } .doc .l.m { width:84%; }
.doc .blk { height:26px; background:var(--brand-fade); border-radius:3px; margin:9px 0 7px; }
.report h2 { margin:0 0 4px; font-size:15px; font-weight:700; }
.report p { margin:0 0 12px; font-size:13.5px; color:var(--ink-2); max-width:58ch; }
.report ul { margin:0 0 14px; padding-left:17px; font-size:13px; color:var(--ink-2); }
.report li { margin-bottom:3px; }
.foot { margin-top:24px; font-size:12.5px; color:var(--ink-3); max-width:88ch; }
@media (prefers-reduced-motion: reduce){ * { transition:none !important; } }
</style>
<div class="page">
<div class="note">
<strong>Maquette — écran Statistiques de manager-app</strong>
<span>Données d'exemple (Fort Saint Héribert, août 2026). Corrige les sept défauts relevés sur l'écran actuel : libellés tronqués à 8 caractères, KPI faisant doublon avec les graphes, chips de canaux non filtrées, deux mécaniques de filtre, donuts illisibles, palette qui se répète, absence de hiérarchie et d'export.</span>
<div class="demo">
<span class="flabel">Aperçu selon l'instance</span>
<span class="seg">
<button type="button" id="dMulti" aria-pressed="true">Plusieurs canaux</button>
<button type="button" id="dMono" aria-pressed="false">Un seul canal</button>
</span>
<span class="demohint">Le bloc Canaux et le filtre disparaissent quand l'instance n'a qu'un canal actif.</span>
</div>
</div>
<div class="app">
<nav class="rail" aria-label="Navigation manager-app">
<div class="brandline">MyInfoMate</div>
<a href="#">Configurations</a>
<a href="#">Sections</a>
<a href="#">Médiathèque</a>
<a href="#">Agenda</a>
<a href="#">Guide IA</a>
<a href="#" class="on">Statistiques</a>
<a href="#">Utilisateurs</a>
<a href="#">Abonnement</a>
</nav>
<div class="main">
<div class="top">
<div>
<h1>Fréquentation</h1>
<p class="range">Du 1<sup>er</sup> au 31 août 2026 · Fort Saint Héribert</p>
</div>
<button class="btn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12"/><path d="m7 10 5 5 5-5"/><path d="M4 20h16"/></svg>
Télécharger le rapport
</button>
</div>
<div class="filters">
<span class="flabel">Période</span>
<span class="seg">
<button type="button" aria-pressed="false">7 jours</button>
<button type="button" aria-pressed="true">30 jours</button>
<button type="button" aria-pressed="false">90 jours</button>
<button type="button" aria-pressed="false">Année</button>
</span>
<span class="sep chan-filter" aria-hidden="true"></span>
<span class="flabel chan-filter">Canal</span>
<button class="chip chan-filter" type="button" aria-pressed="true">Tous <b>3 847</b></button>
<button class="chip chan-filter" type="button" aria-pressed="false">Site web <b>1 642</b></button>
<button class="chip chan-filter" type="button" aria-pressed="false">Application <b>1 208</b></button>
<button class="chip chan-filter" type="button" aria-pressed="false">Borne <b>534</b></button>
<button class="chip chan-filter" type="button" aria-pressed="false">Guide vocal <b>463</b></button>
</div>
<div class="takeaway">
<p>La fréquentation progresse de <em>18 %</em> par rapport à juillet, portée par les week-ends du 15 et du 22 août.</p>
<p id="take2">Le <em>guide vocal</em>, ouvert en juillet, représente déjà <em>12 %</em> des visites — et ces visiteurs restent en moyenne quatre minutes de plus que les autres.</p>
</div>
<div class="kpis">
<div class="kpi">
<span class="k">Visites</span>
<span class="n">3 847</span>
<span class="d up">▲ 18 % vs juillet</span>
</div>
<div class="kpi">
<span class="k">Durée moyenne</span>
<span class="n">14<small> min </small>20<small> s</small></span>
<span class="d up">▲ 2 min 10 s</span>
</div>
<div class="kpi">
<span class="k">Contenus par visite</span>
<span class="n">5,2</span>
<span class="d flat">▬ stable</span>
</div>
<div class="kpi" id="kpi4">
<span class="k">Part du guide vocal</span>
<span class="n">12<small> %</small></span>
<span class="d new">◆ nouveau canal</span>
</div>
</div>
<div class="card" style="margin-top:16px">
<h2>Visites jour par jour</h2>
<p class="sub">Août 2026 — les bandes claires signalent les week-ends</p>
<div class="chartwrap" id="cw">
<svg class="trend" id="trend" viewBox="0 0 760 210" role="img" aria-label="Courbe des visites quotidiennes d'août 2026, de 84 à 288 visites par jour"></svg>
<div class="tip" id="tip"></div>
</div>
<div class="legendline">
<span class="wkkey"><i></i> Samedis et dimanches</span>
<span>Pic le samedi 22 août — 288 visites</span>
</div>
</div>
<div class="row2">
<div class="card fill">
<h2>Contenus les plus consultés</h2>
<p class="sub">Nombre de consultations sur la période</p>
<div class="bars">
<div class="bar"><span class="top2"><span class="lab">Histoire du fort</span><span class="val">1 284</span></span><span class="track"><span class="fill" style="width:100%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Parcours des casemates</span><span class="val">962</span></span><span class="track"><span class="fill" style="width:74.9%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">La vie quotidienne des soldats</span><span class="val">731</span></span><span class="track"><span class="fill" style="width:56.9%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Agenda des visites guidées</span><span class="val">588</span></span><span class="track"><span class="fill" style="width:45.8%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Plan du site</span><span class="val">445</span></span><span class="track"><span class="fill" style="width:34.7%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Quiz « Connais-tu le fort ? »</span><span class="val">337</span></span><span class="track"><span class="fill" style="width:26.2%"></span></span></div>
</div>
<p class="barsub">Les titres complets sont affichés : c'est l'information, pas la décoration.</p>
</div>
<div class="col">
<div class="card card-canaux">
<h2>Canaux</h2>
<p class="sub">Visites par canal</p>
<div class="bars">
<div class="bar"><span class="top2"><span class="lab">Site web</span><span class="val">1 642</span></span><span class="track"><span class="fill" style="width:100%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Application mobile</span><span class="val">1 208</span></span><span class="track"><span class="fill" style="width:73.6%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Borne d'accueil</span><span class="val">534</span></span><span class="track"><span class="fill" style="width:32.5%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Guide vocal</span><span class="val">463</span></span><span class="track"><span class="fill" style="width:28.2%"></span></span></div>
</div>
</div>
<div class="card">
<h2>Langues</h2>
<p class="sub">Visites par langue</p>
<div class="bars">
<div class="bar"><span class="top2"><span class="lab">Français</span><span class="val">2 706</span></span><span class="track"><span class="fill" style="width:100%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Néerlandais</span><span class="val">743</span></span><span class="track"><span class="fill" style="width:27.5%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Anglais</span><span class="val">312</span></span><span class="track"><span class="fill" style="width:11.5%"></span></span></div>
<div class="bar"><span class="top2"><span class="lab">Allemand</span><span class="val">86</span></span><span class="track"><span class="fill" style="width:3.2%"></span></span></div>
</div>
</div>
</div>
</div>
<div class="report">
<div class="doc" aria-hidden="true">
<div class="band"></div>
<div class="l m"></div><div class="l"></div><div class="l s"></div>
<div class="blk"></div>
<div class="l"></div><div class="l m"></div><div class="l s"></div>
</div>
<div>
<h2>Votre rapport d'août 2026</h2>
<p>Un document de 6 pages à vos couleurs, prêt à transmettre à votre commune, votre conseil d'administration ou vos subsidiants.</p>
<ul>
<li>Fréquentation, durées de visite et évolution sur douze mois</li>
<li>Contenus les plus consultés et parcours terminés</li>
<li>Répartition par canal, dont le guide vocal, et par langue</li>
<li>Ce que vos visiteurs ont demandé au guide IA</li>
</ul>
<button class="btn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12"/><path d="m7 10 5 5 5-5"/><path d="M4 20h16"/></svg>
Télécharger le PDF
</button>
</div>
</div>
</div>
</div>
<p class="foot">Toutes les barres mesurent la même chose — un nombre de visites — donc une seule teinte : c'est la longueur qui porte l'information. Colorer chaque barre différemment suggérerait une distinction qui n'existe pas, et rendrait la palette illisible dès sept catégories. Aucun graphe en anneau : au-delà de trois parts, l'œil compare mal des angles.</p>
</div>
<script>
(function(){
var days = [
{d:'1 août', v:212, we:true}, {d:'2 août', v:238, we:true}, {d:'3 août', v:96},
{d:'4 août', v:104}, {d:'5 août', v:88}, {d:'6 août', v:112}, {d:'7 août', v:127},
{d:'8 août', v:231, we:true}, {d:'9 août', v:246, we:true}, {d:'10 août', v:101},
{d:'11 août', v:94}, {d:'12 août', v:118},{d:'13 août', v:126},{d:'14 août', v:149},
{d:'15 août', v:274, we:true}, {d:'16 août', v:261, we:true}, {d:'17 août', v:113},
{d:'18 août', v:107},{d:'19 août', v:99}, {d:'20 août', v:121},{d:'21 août', v:138},
{d:'22 août', v:288, we:true}, {d:'23 août', v:252, we:true}, {d:'24 août', v:110},
{d:'25 août', v:102},{d:'26 août', v:84}, {d:'27 août', v:93}, {d:'28 août', v:119},
{d:'29 août', v:229, we:true}, {d:'30 août', v:241, we:true}, {d:'31 août', v:97}
];
var W = 760, H = 210, PL = 38, PR = 8, PT = 12, PB = 26;
var iw = W - PL - PR, ih = H - PT - PB;
var max = 300;
var svg = document.getElementById('trend');
var NS = 'http://www.w3.org/2000/svg';
var x = function(i){ return PL + (i / (days.length - 1)) * iw; };
var y = function(v){ return PT + ih - (v / max) * ih; };
function el(n, a){ var e = document.createElementNS(NS, n); for (var k in a) e.setAttribute(k, a[k]); return e; }
// gradient
var defs = el('defs');
var g = el('linearGradient', {id:'ag', x1:'0', y1:'0', x2:'0', y2:'1'});
g.appendChild(el('stop', {offset:'0', 'stop-color':'var(--brand)', 'stop-opacity':'.30'}));
g.appendChild(el('stop', {offset:'1', 'stop-color':'var(--brand)', 'stop-opacity':'0'}));
defs.appendChild(g); svg.appendChild(defs);
// weekend bands
for (var i = 0; i < days.length; i++) {
if (!days[i].we) continue;
var half = iw / (days.length - 1) / 2;
svg.appendChild(el('rect', {x:x(i)-half, y:PT, width:half*2, height:ih, fill:'var(--surface-3)', opacity:'.7'}));
}
// gridlines + y labels
[0, 100, 200, 300].forEach(function(v){
svg.appendChild(el('line', {x1:PL, x2:W-PR, y1:y(v), y2:y(v), stroke:'var(--line)', 'stroke-width':'1'}));
var t = el('text', {x:PL-9, y:y(v)+4, 'text-anchor':'end', fill:'var(--ink-3)', 'font-size':'11', 'font-family':'var(--mono)'});
t.textContent = v; svg.appendChild(t);
});
// area + line
var line = '', area = 'M' + x(0) + ' ' + y(0);
days.forEach(function(p, i){
line += (i ? 'L' : 'M') + x(i) + ' ' + y(p.v);
area += 'L' + x(i) + ' ' + y(p.v);
});
area += 'L' + x(days.length-1) + ' ' + y(0) + 'Z';
svg.appendChild(el('path', {d:area, fill:'url(#ag)'}));
svg.appendChild(el('path', {d:line, fill:'none', stroke:'var(--brand)', 'stroke-width':'2', 'stroke-linejoin':'round', 'stroke-linecap':'round'}));
// peak emphasis
var pk = days.reduce(function(a,b,i){ return b.v > days[a].v ? i : a; }, 0);
svg.appendChild(el('circle', {cx:x(pk), cy:y(days[pk].v), r:'5.5', fill:'var(--surface)', stroke:'var(--brand)', 'stroke-width':'2.5'}));
// x labels
[0, 7, 14, 21, 30].forEach(function(i){
var t = el('text', {x:x(i), y:H-7, 'text-anchor':'middle', fill:'var(--ink-3)', 'font-size':'11'});
t.textContent = days[i].d.replace(' août',''); svg.appendChild(t);
});
// hover
var cursor = el('line', {y1:PT, y2:PT+ih, stroke:'var(--brand)', 'stroke-width':'1', opacity:'0'});
var dot = el('circle', {r:'4', fill:'var(--brand)', stroke:'var(--surface)', 'stroke-width':'2', opacity:'0'});
svg.appendChild(cursor); svg.appendChild(dot);
var tip = document.getElementById('tip'), cw = document.getElementById('cw');
svg.addEventListener('mousemove', function(e){
var r = svg.getBoundingClientRect();
var px = (e.clientX - r.left) / r.width * W;
var i = Math.round((px - PL) / iw * (days.length - 1));
if (i < 0 || i >= days.length) return;
cursor.setAttribute('x1', x(i)); cursor.setAttribute('x2', x(i)); cursor.setAttribute('opacity', '.35');
dot.setAttribute('cx', x(i)); dot.setAttribute('cy', y(days[i].v)); dot.setAttribute('opacity', '1');
tip.innerHTML = days[i].d + ' · <b>' + days[i].v + '</b> visites';
tip.style.left = (x(i) / W * 100) + '%';
tip.style.top = (y(days[i].v) / H * r.height) + 'px';
tip.style.opacity = '1';
});
svg.addEventListener('mouseleave', function(){
cursor.setAttribute('opacity','0'); dot.setAttribute('opacity','0'); tip.style.opacity = '0';
});
// filtres — comportement de maquette uniquement
document.querySelectorAll('.filters .seg button').forEach(function(b, _, all){
b.addEventListener('click', function(){ all.forEach(function(o){ o.setAttribute('aria-pressed', String(o === b)); }); });
});
var chips = document.querySelectorAll('.chip');
chips.forEach(function(c){
c.addEventListener('click', function(){ chips.forEach(function(o){ o.setAttribute('aria-pressed', String(o === c)); }); });
});
// bascule de démo : instance mono-canal vs multi-canal
var app = document.querySelector('.app');
var kpi4 = document.getElementById('kpi4');
var take2 = document.getElementById('take2');
var multi = document.getElementById('dMulti'), mono = document.getElementById('dMono');
var KPI_MULTI = '<span class="k">Part du guide vocal</span><span class="n">12<small> %</small></span><span class="d new">◆ nouveau canal</span>';
var KPI_MONO = '<span class="k">Visiteurs uniques</span><span class="n">2 615</span><span class="d up">▲ 14 % vs juillet</span>';
var T2_MULTI = 'Le <em>guide vocal</em>, ouvert en juillet, représente déjà <em>12 %</em> des visites — et ces visiteurs restent en moyenne quatre minutes de plus que les autres.';
var T2_MONO = 'Le contenu <em>Histoire du fort</em> concentre à lui seul un tiers des consultations : c\'est votre porte d\'entrée, il mérite d\'être tenu à jour en priorité.';
function setMode(isMono){
app.classList.toggle('mono', isMono);
kpi4.innerHTML = isMono ? KPI_MONO : KPI_MULTI;
take2.innerHTML = isMono ? T2_MONO : T2_MULTI;
mono.setAttribute('aria-pressed', String(isMono));
multi.setAttribute('aria-pressed', String(!isMono));
}
mono.addEventListener('click', function(){ setMode(true); });
multi.addEventListener('click', function(){ setMode(false); });
})();
</script>
</body></html>