#!/usr/bin/env python3
"""Génère ui_mockup_v6.html — logo embarqué en base64, JS sans apostrophes dans les strings."""
import base64
from pathlib import Path

LOGO_PATH = Path(__file__).parent.parent / "assets" / "logo_header.png"
OUT_PATH  = Path(__file__).parent / "ui_mockup_v6.html"

logo_b64 = base64.b64encode(LOGO_PATH.read_bytes()).decode()
LOGO_SRC  = "data:image/png;base64," + logo_b64

HTML = r"""<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>aivanonym v6 &mdash; Prototype UI</title>
<style>
:root{
  --bg:#1a1a2e;--card:#16213e;--card-border:#0f3460;
  --primary:#e94560;--primary-dim:#c73652;--accent:#f5a623;
  --text:#e0e0e0;--text-dim:#9ca3af;--text-muted:#6b7280;
  --success:#10b981;--warning:#f59e0b;--danger:#ef4444;--blue:#3b82f6;
  --radius:8px;--shadow:0 2px 12px rgba(0,0,0,.4);
  --divider:rgba(255,255,255,.06);--btn-sec-bg:rgba(255,255,255,.08);--btn-sec-border:rgba(255,255,255,.14);
}
/* ── CLAIR : fond gris moyen, cartes blanches, bordures visibles ── */
.theme-light{
  --bg:#cdd2da;--card:#ffffff;--card-border:#9aa3b0;
  --primary:#c93050;--primary-dim:#a82545;--accent:#b45309;
  --text:#0d1117;--text-dim:#1f2937;--text-muted:#374151;
  --success:#047857;--warning:#b45309;--danger:#b91c1c;--blue:#1d4ed8;
  --shadow:0 2px 14px rgba(0,0,0,.22);
  --divider:rgba(0,0,0,.09);--btn-sec-bg:rgba(0,0,0,.07);--btn-sec-border:#9aa3b0;
}
/* ── MÉDICAL : fond bleu structuré, cartes légèrement teintées ── */
.theme-medical{
  --bg:#b8ceea;--card:#eef5ff;--card-border:#6897ca;
  --primary:#1a56db;--primary-dim:#1340b0;--accent:#0369a1;
  --text:#071427;--text-dim:#0f2a4a;--text-muted:#1e3a5f;
  --success:#166534;--warning:#92400e;--danger:#991b1b;--blue:#1e40af;
  --shadow:0 2px 14px rgba(0,50,160,.18);
  --divider:rgba(0,50,160,.09);--btn-sec-bg:rgba(0,50,160,.07);--btn-sec-border:#6897ca;
}
/* ── NEUTRE sombre : inchangé, contraste déjà correct ── */
.theme-neutral{
  --bg:#1f2937;--card:#374151;--card-border:#6b7280;
  --primary:#818cf8;--primary-dim:#6366f1;--accent:#fbbf24;
  --text:#f9fafb;--text-dim:#e5e7eb;--text-muted:#d1d5db;
  --success:#34d399;--warning:#fbbf24;--danger:#f87171;--blue:#60a5fa;
  --shadow:0 2px 12px rgba(0,0,0,.45);
  --divider:rgba(255,255,255,.08);--btn-sec-bg:rgba(255,255,255,.08);--btn-sec-border:#6b7280;
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(--text);font-size:14px;display:flex;justify-content:center;min-height:100vh}
.app-shell{width:780px;min-height:820px;display:flex;flex-direction:column;background:var(--bg);box-shadow:0 0 40px rgba(0,0,0,.5)}
@media(max-width:800px){.app-shell{width:100%;min-height:100vh}}
/* HEADER */
.header{background:var(--card);border-bottom:3px solid var(--primary);padding:10px 20px;display:flex;align-items:center;gap:12px;flex-shrink:0}
.header img{height:34px;width:auto}
.hv{margin-left:auto;font-size:11px;color:var(--text-muted);background:rgba(128,128,128,.12);padding:3px 8px;border-radius:4px}
/* TABS */
.tabs-bar{display:flex;background:var(--card);border-bottom:1px solid var(--card-border);padding:0 20px;flex-shrink:0;gap:2px}
.tab-btn{padding:9px 16px;cursor:pointer;border:none;background:none;color:var(--text-dim);font-size:13px;font-weight:500;border-bottom:3px solid transparent;margin-bottom:-1px;transition:color .15s;white-space:nowrap}
.tab-btn:hover{color:var(--text)}
.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600}
/* CONTENT */
.content{flex:1;overflow-y:auto;padding:20px}
.tab-pane{display:none}.tab-pane.active{display:block}
/* CARD */
.card{background:var(--card);border:1px solid var(--card-border);border-radius:var(--radius);padding:18px;margin-bottom:14px;box-shadow:var(--shadow)}
.ct{font-size:12px;font-weight:600;color:var(--text-dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:12px;display:flex;align-items:center;gap:8px}
.hbtn{margin-left:auto;cursor:pointer;font-size:16px;background:none;border:none;color:var(--text-muted);transition:color .15s;line-height:1;flex-shrink:0}
.hbtn:hover{color:var(--primary)}
/* DROP ZONE */
.dz{border:2px dashed var(--card-border);border-radius:var(--radius);padding:28px 16px;text-align:center;cursor:pointer;transition:border-color .2s,background .2s}
.dz:hover,.dz.over{border-color:var(--primary);background:rgba(233,69,96,.06)}
.dz-icon{font-size:32px;margin-bottom:8px}
.dz-txt{font-size:14px;margin-bottom:3px}
.dz-sub{font-size:12px;color:var(--text-muted)}
.dz-acts{display:flex;gap:8px;justify-content:center;margin-top:12px}
.file-list{margin-top:10px;display:flex;flex-direction:column;gap:5px}
.fi{display:flex;align-items:center;gap:8px;background:var(--divider);border-radius:6px;padding:7px 10px;border:1px solid var(--btn-sec-border)}
.fn{flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fs{font-size:11px;color:var(--text-muted);flex-shrink:0}
.fx{background:none;border:none;cursor:pointer;color:var(--text-muted);font-size:15px;padding:0 3px}
.fx:hover{color:var(--danger)}
/* FORMAT */
.fmt-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.fmt-card{border:2px solid var(--card-border);border-radius:var(--radius);padding:14px;text-align:center;cursor:pointer;transition:all .15s}
.fmt-card.on{border-color:var(--primary);background:rgba(233,69,96,.07)}
.fi2{font-size:22px;margin-bottom:6px}
.fn2{font-size:13px;font-weight:600}
.fs2{font-size:11px;color:var(--text-muted);margin-top:2px}
/* THEME */
.theme-row{display:flex;gap:8px;flex-wrap:wrap}
.tp{padding:6px 14px;border-radius:99px;border:2px solid var(--card-border);cursor:pointer;font-size:12px;font-weight:500;background:none;color:var(--text-dim);transition:all .15s}
.tp:hover{border-color:var(--primary);color:var(--primary)}
.tp.on{border-color:var(--primary);background:var(--primary);color:#fff}
/* BUTTONS */
.btn{display:inline-flex;align-items:center;gap:5px;padding:8px 16px;border-radius:var(--radius);border:none;cursor:pointer;font-size:13px;font-weight:600;transition:all .15s}
.bp{background:var(--primary);color:#fff}
.bp:hover{background:var(--primary-dim);transform:translateY(-1px)}
.bs{background:var(--btn-sec-bg);color:var(--text);border:1px solid var(--btn-sec-border)}
.bs:hover{background:rgba(128,128,128,.2)}
.bsu{background:var(--success);color:#fff}
.blg{padding:11px 24px;font-size:14px}
.btn:disabled{opacity:.4;cursor:not-allowed;transform:none!important}
.brow{display:flex;justify-content:flex-end;gap:8px;margin-bottom:14px}
/* PROGRESS */
.psec{display:none}.psec.vis{display:block}
.ptrack{background:var(--divider);border:1px solid var(--btn-sec-border);border-radius:99px;height:9px;overflow:hidden;margin:8px 0}
.pfill{height:100%;background:linear-gradient(90deg,var(--primary),var(--accent));border-radius:99px;transition:width .4s ease}
.plbl{display:flex;justify-content:space-between;font-size:12px;color:var(--text-muted)}
.psteps{display:flex;gap:5px;margin-top:10px;flex-wrap:wrap}
.sp{padding:3px 9px;border-radius:99px;font-size:11px;background:rgba(128,128,128,.1);color:var(--text-muted)}
.sp.done{background:rgba(16,185,129,.15);color:var(--success)}
.sp.act{background:rgba(233,69,96,.15);color:var(--primary);font-weight:600}
.log{background:var(--divider);border:1px solid var(--card-border);border-radius:6px;padding:8px;font-family:monospace;font-size:11px;color:var(--text-dim);height:90px;overflow-y:auto;line-height:1.6;margin-top:10px}
.lok{color:var(--success)}
/* RESULTS */
.rgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:12px}
.sc{background:var(--btn-sec-bg);border:1px solid var(--btn-sec-border);border-radius:var(--radius);padding:12px;text-align:center}
.sv{font-size:24px;font-weight:700;color:var(--primary)}
.sl{font-size:11px;color:var(--text-muted);margin-top:2px}
.qbar{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.qs{font-size:30px;font-weight:800;color:var(--success)}
.qg{font-size:16px;font-weight:700;color:var(--success)}
/* SUB-TABS */
.stabs{display:flex;gap:2px;border-bottom:1px solid var(--card-border);margin-bottom:16px}
.stab{padding:7px 14px;border:none;background:none;color:var(--text-dim);font-size:13px;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .15s}
.stab:hover{color:var(--text)}
.stab.on{color:var(--primary);border-bottom-color:var(--primary);font-weight:600}
.spane{display:none}.spane.on{display:block}
/* SETTINGS */
.scols{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:600px){.scols{grid-template-columns:1fr}}
.srow{display:flex;align-items:center;justify-content:space-between;padding:9px 0;border-bottom:1px solid var(--divider);gap:12px}
.slbl{font-size:13px}
.shint{font-size:11px;color:var(--text-muted);margin-top:2px}
/* TOGGLE */
.tog{position:relative;display:inline-block;width:38px;height:21px;flex-shrink:0}
.tog input{opacity:0;width:0;height:0}
.tsl{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:rgba(128,128,128,.25);border-radius:99px;transition:.2s}
.tsl:before{content:'';position:absolute;width:15px;height:15px;left:3px;bottom:3px;background:#fff;border-radius:50%;transition:.2s}
.tog input:checked+.tsl{background:var(--primary)}
.tog input:checked+.tsl:before{transform:translateX(17px)}
/* TAGS */
.tagrow{display:flex;gap:7px;margin-bottom:9px}
.taginput{flex:1;background:var(--btn-sec-bg);border:1px solid var(--btn-sec-border);border-radius:6px;padding:6px 10px;color:var(--text);font-size:13px;outline:none}
.taginput:focus{border-color:var(--primary)}
.tagcloud{display:flex;flex-wrap:wrap;gap:5px;min-height:28px}
.tag{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:99px;font-size:12px}
.tw{background:rgba(16,185,129,.12);color:var(--success);border:1px solid rgba(16,185,129,.25)}
.tb{background:rgba(233,69,96,.1);color:var(--primary);border:1px solid rgba(233,69,96,.2)}
.tx{cursor:pointer;font-size:13px;opacity:.6}
.tx:hover{opacity:1}
/* SWATCHES */
.swrow{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px}
.sw{width:30px;height:30px;border-radius:6px;cursor:pointer;border:3px solid transparent;transition:border-color .15s}
.sw.on{border-color:var(--primary)}
/* MASK PREVIEW */
.mprev{background:var(--divider);border:1px solid var(--card-border);border-radius:6px;padding:10px 14px;font-size:13px;margin-top:10px;line-height:2}
.mb{background:var(--primary);color:var(--primary);padding:0 6px;border-radius:3px}
.ms2{color:var(--text-muted)}
.mn{background:#000;color:#000;padding:0 6px;border-radius:2px}
/* RULES TABLE */
.rtbl{width:100%;border-collapse:collapse;font-size:12px}
.rtbl th{text-align:left;padding:7px 9px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);border-bottom:1px solid var(--card-border)}
.rtbl td{padding:8px 9px;border-bottom:1px solid rgba(128,128,128,.07);vertical-align:middle}
.rtbl tr:hover td{background:rgba(128,128,128,.04)}
.rst{display:inline-block;padding:2px 7px;border-radius:99px;font-size:10px;font-weight:600}
.ract{background:rgba(16,185,129,.15);color:var(--success)}
.rcand{background:rgba(245,158,11,.15);color:var(--warning)}
.rtyp{font-size:10px;padding:2px 5px;border-radius:4px;background:rgba(128,128,128,.12);color:var(--text-dim)}
/* ABOUT */
.agrid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.ai{display:flex;gap:9px}
.ak{font-size:10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}
.av{font-size:13px;font-weight:600;margin-top:2px}
/* NOTE */
.note{font-size:11px;color:var(--text-muted);font-style:italic;padding:5px 9px;background:rgba(59,130,246,.08);border-left:3px solid var(--blue);border-radius:0 4px 4px 0;margin-bottom:12px}
/* MODAL */
.mo{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.65);z-index:1000;align-items:center;justify-content:center}
.mo.open{display:flex}
.mbox{background:var(--card);border:1px solid var(--card-border);border-radius:12px;padding:24px;max-width:460px;width:90%;box-shadow:0 8px 40px rgba(0,0,0,.5);position:relative}
.mtit{font-size:15px;font-weight:700;margin-bottom:12px}
.mbody{font-size:13px;line-height:1.75;color:var(--text-dim)}
.mbody strong{color:var(--text)}
.mbody code{background:rgba(128,128,128,.15);padding:1px 5px;border-radius:4px;font-size:12px}
.mcls{position:absolute;top:14px;right:14px;background:none;border:none;font-size:20px;cursor:pointer;color:var(--text-muted)}
.mcls:hover{color:var(--text)}
/* PDF MASK EDITOR */
.me-panel{display:none;margin-top:14px;border:1px solid var(--card-border);border-radius:var(--radius);overflow:hidden}
.me-panel.open{display:block}
.me-toolbar{background:rgba(0,0,0,.15);border-bottom:1px solid var(--card-border);padding:8px 10px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.me-sep{width:1px;height:24px;background:var(--card-border);margin:0 2px;flex-shrink:0}
.me-canvas{background:rgba(0,0,0,.25);min-height:320px;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center}
.me-canvas-inner{position:relative;display:inline-block;box-shadow:0 2px 16px rgba(0,0,0,.5)}
.me-canvas-inner img{display:block;max-width:100%}
.me-overlay{position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair}
.me-mask-rect{position:absolute;background:rgba(0,0,0,.85);border:1px solid rgba(255,0,0,.4);cursor:pointer}
.me-mask-rect:hover{border-color:var(--danger);background:#000}
.me-hint{color:var(--text-muted);font-size:12px;text-align:center;padding:20px}
.me-hint span{font-size:32px;display:block;margin-bottom:8px}
.me-status{background:rgba(0,0,0,.15);border-top:1px solid var(--card-border);padding:5px 10px;font-size:11px;color:var(--text-muted);display:flex;gap:12px}
/* TOOLTIP */
[title]{position:relative}
/* native title is enough for mockup */
</style>
</head>
<body>
<div class="app-shell" id="shell">

<!-- HEADER -->
<div class="header">
  <img src="LOGO_PLACEHOLDER" alt="aivanonym">
  <div class="hv">v6.0 &middot; prototype</div>
</div>

<!-- ONGLETS PRINCIPAUX (3 : Utilisation / Configuration / À propos) -->
<div class="tabs-bar">
  <button class="tab-btn active" onclick="ST('use',this)">&#128196; Utilisation</button>
  <button class="tab-btn" onclick="ST('cfg',this)">&#9881;&#65039; Configuration</button>
  <button class="tab-btn" onclick="ST('about',this)">&#8505;&#65039; &Agrave; propos</button>
</div>

<div class="content">

<!-- ═══ UTILISATION ═══ -->
<div class="tab-pane active" id="tab-use">

  <div class="card">
    <div class="ct">&#127912; Apparence <button class="hbtn" onclick="H('theme')" title="Aide sur le th&egrave;me">&#10067;</button></div>
    <div class="theme-row">
      <button class="tp on"  onclick="TH('',this)"        title="Th&egrave;me sombre">&#127769; Sombre</button>
      <button class="tp"     onclick="TH('light',this)"   title="Th&egrave;me clair">&#9728;&#65039; Clair</button>
      <button class="tp"     onclick="TH('medical',this)" title="Th&egrave;me hospitalier">&#127973;&#65039; M&eacute;dical</button>
      <button class="tp"     onclick="TH('neutral',this)" title="Th&egrave;me neutre gris">&#127807; Neutre</button>
    </div>
  </div>

  <div class="card">
    <div class="ct">&#128194; Documents &agrave; anonymiser <button class="hbtn" onclick="H('fich')" title="Aide sur les fichiers">&#10067;</button></div>
    <div id="dropzone" class="dz" onclick="PICK()"
         ondragover="event.preventDefault();this.classList.add('over')"
         ondragleave="this.classList.remove('over')"
         ondrop="DROP(event)">
      <div class="dz-icon">&#11014;&#65039;</div>
      <div class="dz-txt">Glissez-d&eacute;posez vos fichiers ici</div>
      <div class="dz-sub">PDF &middot; Word &middot; Images &middot; Texte</div>
      <div class="dz-acts">
        <button class="btn bs" onclick="event.stopPropagation();PICK()"  title="Choisir des fichiers individuels">&#128196; Fichiers</button>
        <button class="btn bs" onclick="event.stopPropagation();PICKF()" title="Traiter tous les fichiers d'un dossier">&#128194; Dossier entier</button>
      </div>
    </div>
    <div class="file-list" id="flist"></div>
  </div>

  <div class="card">
    <div class="ct">&#128190; Format de sortie <button class="hbtn" onclick="H('fmt')" title="Aide sur les formats">&#10067;</button></div>
    <div class="fmt-grid">
      <div class="fmt-card on" onclick="this.classList.toggle('on')" title="Exporter un PDF avec les zones masqu&eacute;es en noir">
        <div class="fi2">&#128196;</div><div class="fn2">PDF anonymis&eacute;</div><div class="fs2">Zones noircies</div>
      </div>
      <div class="fmt-card on" onclick="this.classList.toggle('on')" title="Exporter un fichier texte avec les PII remplac&eacute;s par des codes">
        <div class="fi2">&#128221;</div><div class="fn2">Texte .txt</div><div class="fs2">Mots remplac&eacute;s par [NOM]&hellip;</div>
      </div>
    </div>
  </div>

  <div class="brow">
    <button class="btn bs" onclick="CLR()" title="Vider la liste de fichiers">&#10006; Effacer</button>
    <button class="btn bp blg" id="btnGo" onclick="GO()" title="Lancer le traitement d'anonymisation">&#9654; Lancer l&apos;anonymisation</button>
  </div>

  <div class="card psec" id="psec">
    <div class="ct">&#8987; Traitement en cours&hellip;</div>
    <div class="plbl"><span id="pf">Fichier 1 / 3</span><span id="pp">0 %</span></div>
    <div class="ptrack"><div class="pfill" id="pb" style="width:0%"></div></div>
    <div class="psteps">
      <span class="sp act" id="s0">&#128214; Extraction</span>
      <span class="sp" id="s1">&#129504; D&eacute;tection</span>
      <span class="sp" id="s2">&#128274; Masquage</span>
      <span class="sp" id="s3">&#128196; PDF final</span>
    </div>
    <div class="log" id="logb"></div>
    <div style="text-align:right;margin-top:9px">
      <button class="btn bs" onclick="STOP()" title="Arr&ecirc;ter le traitement en cours">&#9209; Arr&ecirc;ter</button>
    </div>
  </div>

  <div class="card psec" id="rsec">
    <div class="ct">&#9989; R&eacute;sultats</div>
    <div class="rgrid">
      <div class="sc"><div class="sv">3</div><div class="sl">Documents</div></div>
      <div class="sc"><div class="sv">142</div><div class="sl">PII masqu&eacute;s</div></div>
      <div class="sc"><div class="sv">4s</div><div class="sl">Dur&eacute;e</div></div>
      <div class="sc"><div class="sv" style="color:var(--success)">A+</div><div class="sl">Qualit&eacute;</div></div>
    </div>
    <div class="qbar">
      <div class="qs">100.0</div>
      <div><div class="qg">/ 100 &middot; A+</div><div style="font-size:11px;color:var(--text-muted)">Aucune fuite d&eacute;tect&eacute;e</div></div>
    </div>
    <div class="log">
      <span class="lok">&#10003;</span> CR_23456.pdf &rarr; 47 PII masqu&eacute;s<br>
      <span class="lok">&#10003;</span> CRO_81234.pdf &rarr; 38 PII masqu&eacute;s<br>
      <span class="lok">&#10003;</span> LETTRE_SORTIE.pdf &rarr; 57 PII masqu&eacute;s
    </div>
    <div style="display:flex;gap:8px;margin-top:12px;flex-wrap:wrap">
      <button class="btn bsu" onclick="alert('Ouverture du dossier de sortie')" title="Ouvrir le dossier contenant les fichiers anonymis&eacute;s">&#128193; Ouvrir le dossier</button>
      <button class="btn bs"  onclick="RRES()" title="Revenir au d&eacute;but pour traiter d'autres fichiers">&#128260; Nouveau traitement</button>
    </div>
  </div>
</div><!-- /use -->

<!-- ═══ CONFIGURATION ═══ -->
<div class="tab-pane" id="tab-cfg">
  <div class="stabs">
    <button class="stab on" onclick="SS('reg',this)">&#9881;&#65039; R&eacute;glages</button>
    <button class="stab"    onclick="SS('msk',this)">&#127917; Masquage</button>
    <button class="stab"    onclick="SS('shr',this)">&#128260; Partage</button>
    <button class="stab"    onclick="SS('rul',this)">&#128737;&#65039; R&egrave;gles <span style="display:inline-block;background:var(--primary);color:#fff;font-size:10px;padding:1px 5px;border-radius:9px;margin-left:4px">2</span></button>
  </div>

  <!-- RÉGLAGES -->
  <div class="spane on" id="sp-reg">
    <div class="scols">
      <div>
        <div class="card">
          <div class="ct">&#128269; Donn&eacute;es &agrave; d&eacute;tecter <button class="hbtn" onclick="H('det')" title="Aide sur la d&eacute;tection">&#10067;</button></div>
          <div class="srow"><div><div class="slbl">Noms et pr&eacute;noms</div><div class="shint">Gazetteers INSEE &middot; CamemBERT</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">Dates de naissance</div><div class="shint">Uniquement la date de naissance</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">Etablissements</div><div class="shint">R&eacute;pertoire FINESS + contexte</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">Adresses et codes postaux</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">N&deg; s&eacute;curit&eacute; sociale</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">T&eacute;l&eacute;phones et e-mails</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">N&deg; adh&eacute;rent mutuelle</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
        </div>
        <div class="card">
          <div class="ct">&#129504; Moteurs NER <button class="hbtn" onclick="H('ner')" title="Aide sur les moteurs IA">&#10067;</button></div>
          <div class="srow"><div><div class="slbl">CamemBERT-bio <span style="font-size:10px;color:var(--success)">RAPIDE</span></div><div class="shint">~10 ms/doc &middot; F1 = 0.963</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">EDS-Pseudo <span style="font-size:10px;color:var(--blue)">PRECIS</span></div><div class="shint">~200 ms/doc &middot; m&eacute;dical fran&ccedil;ais</div></div><label class="tog"><input type="checkbox" checked><span class="tsl"></span></label></div>
          <div class="srow"><div><div class="slbl">GLiNER <span style="font-size:10px;color:var(--text-muted)">OPTIONNEL</span></div><div class="shint">~95 ms/doc &middot; vote crois&eacute;</div></div><label class="tog"><input type="checkbox"><span class="tsl"></span></label></div>
        </div>
      </div>
      <div>
        <div class="card">
          <div class="ct">&#9989; Termes &agrave; toujours conserver <button class="hbtn" onclick="H('wl')" title="Aide liste blanche">&#10067;</button></div>
          <div class="note">Ces termes ne seront <strong>jamais masqu&eacute;s</strong>, m&ecirc;me s&rsquo;ils ressemblent &agrave; un nom propre.</div>
          <div class="tagrow"><input class="taginput" id="wIn" placeholder="Ex : FUROSEMIDE&hellip;" onkeydown="if(event.key==='Enter')AT('w')"><button class="btn bs" onclick="AT('w')" title="Ajouter ce terme &agrave; la liste blanche">+ Ajouter</button></div>
          <div class="tagcloud" id="wTags">
            <span class="tag tw">FUROSEMIDE <span class="tx" onclick="this.parentElement.remove()">&#215;</span></span>
            <span class="tag tw">r&eacute;&eacute;ducation fonctionnelle <span class="tx" onclick="this.parentElement.remove()">&#215;</span></span>
            <span class="tag tw">classification internationale <span class="tx" onclick="this.parentElement.remove()">&#215;</span></span>
          </div>
        </div>
        <div class="card">
          <div class="ct">&#128683; Termes &agrave; toujours masquer <button class="hbtn" onclick="H('bl')" title="Aide liste noire">&#10067;</button></div>
          <div class="note">Ces termes seront <strong>toujours masqu&eacute;s</strong>, m&ecirc;me sans contexte m&eacute;dical autour.</div>
          <div class="tagrow"><input class="taginput" id="bIn" placeholder="Ex : CHUXX, Dr Dupont&hellip;" onkeydown="if(event.key==='Enter')AT('b')"><button class="btn bs" onclick="AT('b')" title="Ajouter ce terme &agrave; la liste noire">+ Ajouter</button></div>
          <div class="tagcloud" id="bTags">
            <span class="tag tb">CHUXX <span class="tx" onclick="this.parentElement.remove()">&#215;</span></span>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- MASQUAGE -->
  <div class="spane" id="sp-msk">
    <div class="scols">
      <div>
        <div class="card">
          <div class="ct">&#11035; Couleur de masquage (PDF) <button class="hbtn" onclick="H('col')" title="Aide couleur de masquage">&#10067;</button></div>
          <div class="note">Couleur des rectangles dans le PDF final.</div>
          <div class="swrow">
            <div class="sw on" style="background:#000"    onclick="SW(this)" title="Noir (standard officiel)"></div>
            <div class="sw"    style="background:#1a1a2e" onclick="SW(this)" title="Bleu nuit"></div>
            <div class="sw"    style="background:#374151" onclick="SW(this)" title="Gris fonc&eacute;"></div>
            <div class="sw"    style="background:#92400e" onclick="SW(this)" title="Marron"></div>
            <div class="sw"    style="background:#1e3a5f" onclick="SW(this)" title="Bleu marine"></div>
          </div>
        </div>
        <div class="card">
          <div class="ct">&#127991;&#65039; Style des marqueurs (texte) <button class="hbtn" onclick="H('sty')" title="Aide style de marqueurs">&#10067;</button></div>
          <div style="display:flex;flex-direction:column;gap:8px;margin-bottom:10px">
            <label style="display:flex;align-items:center;gap:8px;cursor:pointer" title="Remplace par [NOM], [DATE_NAISSANCE], etc.">
              <input type="radio" name="ms" value="b" checked onchange="UP()">
              Crochets &mdash; <code style="color:var(--primary)">[NOM]</code>
            </label>
            <label style="display:flex;align-items:center;gap:8px;cursor:pointer" title="Remplace par des ast&eacute;risques discrets">
              <input type="radio" name="ms" value="s" onchange="UP()">
              Etoiles &mdash; <code style="color:var(--text-muted)">***</code>
            </label>
            <label style="display:flex;align-items:center;gap:8px;cursor:pointer" title="Remplace par des blocs noirs comme dans un PDF">
              <input type="radio" name="ms" value="n" onchange="UP()">
              Noirci &mdash; <span style="background:#000;color:#000;padding:0 8px;border-radius:2px">NOM</span>
            </label>
          </div>
          <div id="mprev" class="mprev"></div>
        </div>
      </div>
      <div>
        <div class="card">
          <div class="ct">&#128208; Epaisseur du masque <button class="hbtn" onclick="H('ep')" title="Aide &eacute;paisseur">&#10067;</button></div>
          <div class="note">Marge autour du texte masqu&eacute; (en points).</div>
          <div class="srow"><div><div class="slbl">Marge horizontale</div></div><input type="range" min="0" max="6" value="2" style="width:120px;accent-color:var(--primary)" title="R&eacute;gler la marge gauche-droite du masque"></div>
          <div class="srow"><div><div class="slbl">Marge verticale</div></div><input type="range" min="0" max="6" value="1" style="width:120px;accent-color:var(--primary)" title="R&eacute;gler la marge haut-bas du masque"></div>
          <div class="srow"><div><div class="slbl">Coins arrondis</div></div><label class="tog"><input type="checkbox"><span class="tsl"></span></label></div>
        </div>
        <div class="card">
          <div class="ct">&#128274; Codes de remplacement <button class="hbtn" onclick="H('ph')" title="Aide codes de remplacement">&#10067;</button></div>
          <div style="display:grid;grid-template-columns:1fr 1fr;gap:5px;font-size:12px">
            <div style="color:var(--text-muted)">Nom/Pr&eacute;nom</div><div style="color:var(--primary);font-weight:600">[NOM]</div>
            <div style="color:var(--text-muted)">Date naissance</div><div style="color:var(--primary);font-weight:600">[DATE_NAISSANCE]</div>
            <div style="color:var(--text-muted)">Etablissement</div><div style="color:var(--primary);font-weight:600">[ETABLISSEMENT]</div>
            <div style="color:var(--text-muted)">Adresse</div><div style="color:var(--primary);font-weight:600">[ADRESSE]</div>
            <div style="color:var(--text-muted)">T&eacute;l&eacute;phone</div><div style="color:var(--primary);font-weight:600">[TEL]</div>
            <div style="color:var(--text-muted)">N&deg; s&eacute;cu</div><div style="color:var(--primary);font-weight:600">[NIR]</div>
            <div style="color:var(--text-muted)">IPP</div><div style="color:var(--primary);font-weight:600">[IPP]</div>
            <div style="color:var(--text-muted)">Email</div><div style="color:var(--primary);font-weight:600">[EMAIL]</div>
          </div>
        </div>
      </div>
    </div>

    <!-- ÉDITEUR DE MASQUES PDF -->
    <div class="card" style="margin-top:0">
      <div class="ct">
        &#127968; Masques de zones fixes (logos, en-t&ecirc;tes)
        <button class="hbtn" onclick="H('medit')" title="Aide &eacute;diteur de masques">&#10067;</button>
        <button class="btn bp" style="margin-left:8px;padding:5px 12px;font-size:12px" onclick="METOG()" id="meBtnOpen" title="Ouvrir l'&eacute;diteur pour dessiner des zones &agrave; masquer sur un PDF mod&egrave;le">
          &#128393; Ouvrir l&apos;&eacute;diteur de masques
        </button>
      </div>
      <div class="note">
        Dessinez des rectangles sur un PDF mod&egrave;le pour masquer syst&eacute;matiquement les logos, en-t&ecirc;tes ou zones fixes &mdash;
        ind&eacute;pendamment de l&rsquo;OCR.
      </div>

      <!-- Panneau éditeur (togglable) -->
      <div class="me-panel" id="mePanel">

        <!-- Barre d'outils -->
        <div class="me-toolbar">
          <button class="btn bs" style="padding:5px 10px;font-size:12px" onclick="ME_open()" title="Charger un PDF pour d&eacute;finir les zones &agrave; masquer">
            &#128196; Ouvrir PDF&hellip;
          </button>

          <div class="me-sep"></div>

          <button class="btn bs" style="padding:5px 8px;font-size:13px;min-width:30px" onclick="ME_zoom(-1)" title="Zoom arri&egrave;re">&#8722;</button>
          <span id="meZoomLbl" style="font-size:12px;color:var(--text-muted);min-width:38px;text-align:center">100%</span>
          <button class="btn bs" style="padding:5px 8px;font-size:13px;min-width:30px" onclick="ME_zoom(1)"  title="Zoom avant">+</button>

          <div class="me-sep"></div>

          <span style="font-size:12px;color:var(--text-muted)">Template&nbsp;:</span>
          <input id="meTplName" type="text" value="template_masques" style="width:130px;background:rgba(128,128,128,.12);border:1px solid var(--card-border);border-radius:5px;padding:4px 7px;color:var(--text);font-size:12px;outline:none" title="Nom du template de masques">
          <button class="btn bs" style="padding:5px 10px;font-size:12px" onclick="ME_save()"  title="Sauvegarder ce template de masques dans un fichier">&#128190; Sauver</button>
          <button class="btn bs" style="padding:5px 10px;font-size:12px" onclick="ME_load()"  title="Charger un template de masques existant">&#128193; Charger</button>

          <div class="me-sep"></div>

          <button class="btn bs" style="padding:5px 10px;font-size:12px;color:var(--danger)" onclick="ME_clearPage()" title="Effacer tous les masques de la page actuelle">
            &#128465; Effacer page
          </button>
        </div>

        <!-- Zone de dessin -->
        <div class="me-canvas" id="meCanvas">
          <div id="meHint" class="me-hint">
            <span>&#128196;</span>
            Ouvrez un PDF pour commencer &agrave; dessiner des zones de masquage.<br>
            <span style="font-size:11px">Cliquez-glissez pour tracer un rectangle &bull; Clic sur un masque pour le supprimer</span>
          </div>
          <div id="meImgWrap" class="me-canvas-inner" style="display:none">
            <img id="meImg" src="" alt="page PDF">
            <canvas id="meOverlay" class="me-overlay"
              onmousedown="ME_mdown(event)"
              onmousemove="ME_mmove(event)"
              onmouseup="ME_mup(event)">
            </canvas>
          </div>
        </div>

        <!-- Barre d'action inférieure -->
        <div class="me-toolbar" style="border-top:1px solid var(--card-border);border-bottom:none;justify-content:space-between">
          <div style="display:flex;gap:6px;align-items:center">
            <span style="font-size:12px;color:var(--text-muted)">DPI raster&nbsp;:</span>
            <input id="meDpi" type="number" value="200" min="72" max="600" step="10"
              style="width:58px;background:rgba(128,128,128,.12);border:1px solid var(--card-border);border-radius:5px;padding:4px 6px;color:var(--text);font-size:12px;outline:none;text-align:center"
              title="R&eacute;solution de rendu (200 DPI recommand&eacute; pour la pr&eacute;cision des masques)">
            <button class="btn bs" style="padding:5px 10px;font-size:12px" onclick="ME_preview()" title="Pr&eacute;visualiser le r&eacute;sultat du masquage sur la page courante">
              &#128065; Pr&eacute;visualiser
            </button>
          </div>
          <button class="btn bp" style="padding:6px 14px;font-size:12px" onclick="ME_apply()" title="Appliquer ce template aux documents du traitement en cours">
            &#9654; Appliquer le template
          </button>
        </div>

        <!-- Barre de statut -->
        <div class="me-status">
          <span id="meStat">Aucun PDF charg&eacute;</span>
          <span id="meMaskCount">0 masque(s)</span>
        </div>
      </div>
    </div>
  </div><!-- /sp-msk -->

  <!-- PARTAGE -->
  <div class="spane" id="sp-shr">
    <div class="card">
      <div class="ct">&#128228; Exporter la configuration <button class="hbtn" onclick="H('exp')" title="Aide export">&#10067;</button></div>
      <div class="note">G&eacute;n&egrave;re un fichier .json avec vos listes, &agrave; envoyer par e-mail &agrave; d&rsquo;autres &eacute;tablissements.</div>
      <button class="btn bs" onclick="alert('Export JSON simul&eacute;')" title="T&eacute;l&eacute;charger votre configuration en fichier .json">&#11015; Exporter (.json)</button>
    </div>
    <div class="card">
      <div class="ct">&#128229; Importer une configuration <button class="hbtn" onclick="H('imp')" title="Aide import">&#10067;</button></div>
      <div class="note">Importez un fichier re&ccedil;u. Vos r&eacute;glages locaux ne seront pas supprim&eacute;s.</div>
      <button class="btn bs" onclick="alert('Import simul&eacute;')" title="Charger un fichier .json re&ccedil;u par e-mail">&#11014; Importer (.json)</button>
    </div>
  </div>

  <!-- RÈGLES (sous-onglet) -->
  <div class="spane" id="sp-rul">
    <div class="card">
      <div class="ct">&#128737;&#65039; R&egrave;gles actives <button class="hbtn" onclick="H('rul')" title="Aide sur les r&egrave;gles">&#10067;</button></div>
      <div class="note">Ces r&egrave;gles adaptent le moteur &agrave; votre &eacute;tablissement. Chaque r&egrave;gle est valid&eacute;e avant activation.</div>
      <table class="rtbl">
        <thead><tr><th>Label</th><th>Type</th><th>Cible &rarr; R&eacute;sultat</th><th>Statut</th><th></th></tr></thead>
        <tbody>
          <tr>
            <td>Masquer le sigle CHUXX</td>
            <td><span class="rtyp">exact</span></td>
            <td><code>CHUXX</code> &rarr; <code style="color:var(--primary)">[MASK]</code></td>
            <td><span class="rst ract">Actif</span></td>
            <td><button class="btn bs" style="padding:3px 8px;font-size:11px" onclick="SIM('CHUXX')" title="Tester cette r&egrave;gle sur un texte libre">&#9654; Tester</button></td>
          </tr>
          <tr>
            <td>Pr&eacute;server &ldquo;classification internationale&rdquo;</td>
            <td><span class="rtyp">preserve</span></td>
            <td>conserv&eacute; tel quel</td>
            <td><span class="rst ract">Actif</span></td>
            <td><button class="btn bs" style="padding:3px 8px;font-size:11px" onclick="SIM('classification')" title="Tester cette r&egrave;gle sur un texte libre">&#9654; Tester</button></td>
          </tr>
          <tr>
            <td>Identifier N&deg; 1234567</td>
            <td><span class="rtyp">norm-id</span></td>
            <td><code>N&deg; 1234567</code> &rarr; <code style="color:var(--primary)">[NDA]</code></td>
            <td><span class="rst rcand">Candidat</span></td>
            <td><button class="btn bs" style="padding:3px 8px;font-size:11px" onclick="SIM('1234567')" title="Tester cette r&egrave;gle sur un texte libre">&#9654; Tester</button></td>
          </tr>
        </tbody>
      </table>
      <div style="margin-top:12px;display:flex;gap:8px">
        <button class="btn bp" onclick="alert('Editeur de r&egrave;gles (&agrave; venir)')" title="Cr&eacute;er une nouvelle r&egrave;gle d'administration">+ Nouvelle r&egrave;gle</button>
        <button class="btn bs" title="Recharger les r&egrave;gles depuis la configuration">&#128260; Recharger</button>
      </div>
    </div>
    <div class="card" id="simcard" style="display:none">
      <div class="ct">&#129514; Testeur de r&egrave;gle</div>
      <label style="font-size:12px;color:var(--text-muted);display:block;margin-bottom:5px">Texte de test</label>
      <textarea id="simtxt" rows="3" style="width:100%;background:rgba(0,0,0,.2);border:1px solid var(--card-border);border-radius:6px;padding:8px;color:var(--text);font-size:13px;resize:vertical;outline:none"></textarea>
      <div style="display:flex;gap:8px;margin:10px 0">
        <button class="btn bp" onclick="RSIM()" title="Ex&eacute;cuter la simulation sur le texte saisi">&#9654; Tester</button>
        <button class="btn bs" onclick="document.getElementById('simcard').style.display='none'" title="Fermer le testeur">&#10006; Fermer</button>
      </div>
      <div id="simout" style="display:none;background:rgba(0,0,0,.2);border:1px solid var(--card-border);border-radius:6px;padding:10px;font-size:13px;line-height:1.8"></div>
    </div>
  </div>

</div><!-- /cfg -->

<!-- ═══ À PROPOS ═══ -->
<div class="tab-pane" id="tab-about">
  <div class="card">
    <div class="ct">&#8505;&#65039; Informations</div>
    <div class="agrid">
      <div class="ai"><span style="font-size:20px">&#127991;&#65039;</span><div><div class="ak">Version</div><div class="av">v6.0 (prototype)</div></div></div>
      <div class="ai"><span style="font-size:20px">&#128197;</span><div><div class="ak">Build</div><div class="av">2026-04-28</div></div></div>
      <div class="ai"><span style="font-size:20px">&#129504;</span><div><div class="ak">Moteurs NER</div><div class="av">CamemBERT &middot; EDS-Pseudo &middot; GLiNER</div></div></div>
      <div class="ai"><span style="font-size:20px">&#128274;</span><div><div class="ak">Traitement</div><div class="av">100 % local &mdash; aucune donn&eacute;e transmise</div></div></div>
      <div class="ai"><span style="font-size:20px">&#128218;</span><div><div class="ak">Gazetteers</div><div class="av">INSEE 219K &middot; FINESS 108K &middot; BDPM 7K</div></div></div>
      <div class="ai"><span style="font-size:20px">&#128193;</span><div><div class="ak">Formats</div><div class="av">PDF &middot; DOCX &middot; ODT &middot; RTF &middot; TXT &middot; Images</div></div></div>
    </div>
  </div>
  <div class="card">
    <div class="ct">&#128202; Derni&egrave;re session</div>
    <div class="qbar">
      <div class="qs">100.0</div>
      <div><div class="qg">/ 100 &middot; A+</div><div style="font-size:11px;color:var(--text-muted)">22 PDFs &middot; 0 fuite d&eacute;tect&eacute;e</div></div>
    </div>
  </div>
</div><!-- /about -->

</div><!-- /content -->
</div><!-- /shell -->

<!-- MODAL AIDE -->
<div class="mo" id="mo" onclick="if(event.target===this)CH()">
  <div class="mbox">
    <button class="mcls" onclick="CH()">&#215;</button>
    <div class="mtit" id="mt"></div>
    <div class="mbody" id="mb"></div>
  </div>
</div>

<script>
// Navigation onglets principaux
function ST(n,b){
  document.querySelectorAll(".tab-pane").forEach(function(p){p.classList.remove("active");});
  document.querySelectorAll(".tab-btn").forEach(function(x){x.classList.remove("active");});
  document.getElementById("tab-"+n).classList.add("active");
  b.classList.add("active");
}
// Sous-onglets configuration
function SS(n,b){
  document.querySelectorAll(".spane").forEach(function(p){p.classList.remove("on");});
  document.querySelectorAll(".stab").forEach(function(x){x.classList.remove("on");});
  document.getElementById("sp-"+n).classList.add("on");
  b.classList.add("on");
}
// Themes
function TH(t,b){
  document.getElementById("shell").className="app-shell"+(t?" theme-"+t:"");
  document.querySelectorAll(".tp").forEach(function(x){x.classList.remove("on");});
  b.classList.add("on");
}
// Fichiers
var SAMP=[{n:"CR_23456.pdf",s:"142 Ko"},{n:"CRO_81234.pdf",s:"98 Ko"},{n:"LETTRE_SORTIE.pdf",s:"64 Ko"}];
var _f=[];
function RF(f){
  _f=f;
  var h="";
  for(var i=0;i<f.length;i++){
    h+="<div class=\"fi\" id=\"fi"+i+"\"><span style=\"font-size:16px\">&#128196;</span><span class=\"fn\">"+f[i].n+"</span><span class=\"fs\">"+f[i].s+"</span><button class=\"fx\" onclick=\"document.getElementById('fi"+i+"').remove()\">&#215;</button></div>";
  }
  document.getElementById("flist").innerHTML=h;
}
function PICK(){RF(SAMP);}
function PICKF(){RF(SAMP.concat([{n:"ANAPATH.pdf",s:"211 Ko"},{n:"BACTERIO.docx",s:"34 Ko"}]));}
function DROP(e){e.preventDefault();document.getElementById("dropzone").classList.remove("over");RF(SAMP);}
function CLR(){_f=[];document.getElementById("flist").innerHTML="";RRES();}
// Progression
var _t=null;
var STP=["s0","s1","s2","s3"];
var LG=[
  ["lok","OK Lecture CR_23456.pdf"],
  ["","- Extraction texte..."],
  ["lok","OK 47 entites detectees"],
  ["","- Masquage..."],
  ["lok","OK CR_23456.pdf termine"],
  ["","- CRO_81234.pdf..."],
  ["lok","OK CRO_81234.pdf termine"],
  ["","- LETTRE_SORTIE.pdf..."],
  ["lok","OK 142 PII masques au total"]
];
function GO(){
  if(!_f.length)PICK();
  document.getElementById("psec").classList.add("vis");
  document.getElementById("rsec").classList.remove("vis");
  document.getElementById("btnGo").disabled=true;
  document.getElementById("logb").innerHTML="";
  for(var i=0;i<STP.length;i++) document.getElementById(STP[i]).className="sp";
  document.getElementById(STP[0]).className="sp act";
  var p=0,si=0,li=0;
  var lb=document.getElementById("logb");
  _t=setInterval(function(){
    p+=5; if(p>100)p=100;
    document.getElementById("pb").style.width=p+"%";
    document.getElementById("pp").textContent=p+" %";
    document.getElementById("pf").textContent="Fichier "+Math.min(3,Math.ceil(p/34))+" / 3";
    var ns=Math.min(STP.length-1,Math.floor(p/26));
    if(ns!==si){document.getElementById(STP[si]).className="sp done";si=ns;document.getElementById(STP[si]).className="sp act";}
    if(li<LG.length&&Math.random()>.5){
      lb.innerHTML+="<span class=\""+LG[li][0]+"\">"+LG[li][1]+"</span>\n";
      lb.scrollTop=lb.scrollHeight; li++;
    }
    if(p>=100){
      clearInterval(_t);
      for(var j=0;j<STP.length;j++){document.getElementById(STP[j]).className="sp done";}
      setTimeout(function(){
        document.getElementById("psec").classList.remove("vis");
        document.getElementById("rsec").classList.add("vis");
        document.getElementById("btnGo").disabled=false;
      },600);
    }
  },100);
}
function STOP(){if(_t)clearInterval(_t);document.getElementById("psec").classList.remove("vis");document.getElementById("btnGo").disabled=false;}
function RRES(){document.getElementById("rsec").classList.remove("vis");document.getElementById("psec").classList.remove("vis");document.getElementById("pb").style.width="0%";}
// Tags
function AT(t){
  var inp=document.getElementById(t==="w"?"wIn":"bIn");
  var v=inp.value.trim(); if(!v)return;
  var c=document.getElementById(t==="w"?"wTags":"bTags");
  var s=document.createElement("span");
  s.className="tag "+(t==="w"?"tw":"tb");
  s.innerHTML=v+" <span class=\"tx\" onclick=\"this.parentElement.remove()\">&#215;</span>";
  c.appendChild(s); inp.value="";
}
// Swatches
function SW(el){document.querySelectorAll(".sw").forEach(function(s){s.classList.remove("on");});el.classList.add("on");}
// Preview masquage
function UP(){
  var v=document.querySelector("input[name='ms']:checked").value;
  var nm,nd,ne;
  if(v==="b"){nm="<span class=\"mb\">[NOM]</span>";nd="<span class=\"mb\">[DATE_NAISSANCE]</span>";ne="<span class=\"mb\">[ETABLISSEMENT]</span>";}
  else if(v==="s"){nm="<span class=\"ms2\">***</span>";nd="<span class=\"ms2\">***</span>";ne="<span class=\"ms2\">***</span>";}
  else{nm="<span class=\"mn\">&#9608;&#9608;&#9608;&#9608;</span>";nd="<span class=\"mn\">&#9608;&#9608;&#9608;&#9608;</span>";ne="<span class=\"mn\">&#9608;&#9608;&#9608;&#9608;</span>";}
  document.getElementById("mprev").innerHTML="Patient : "+nm+"<br>N&eacute; le "+nd+"<br>Service du "+ne;
}
UP();
// Simulateur de regle
var _rt="";
function SIM(t){
  _rt=t;
  document.getElementById("simcard").style.display="block";
  document.getElementById("simout").style.display="none";
  document.getElementById("simtxt").value="Dossier "+t+" -- suivi au "+t+" de Chicago.\nCode CIM retient la classification internationale G56.8.";
  document.getElementById("simcard").scrollIntoView({behavior:"smooth"});
}
function RSIM(){
  var txt=document.getElementById("simtxt").value;
  var re=new RegExp(_rt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"gi");
  var out=txt.replace(re,function(m){return "<mark style=\"background:var(--primary);color:white;padding:1px 5px;border-radius:3px\">[MASK]</mark>";});
  out=out.replace(/\n/g,"<br>");
  var el=document.getElementById("simout");
  el.innerHTML=out; el.style.display="block";
}

// ── ÉDITEUR DE MASQUES PDF ──────────────────────────────────────────────────
var _meZoom=1, _meMasks=[], _meDrawing=false, _meStart=null, _meTmpRect=null;

function METOG(){
  var p=document.getElementById("mePanel");
  var b=document.getElementById("meBtnOpen");
  if(p.classList.contains("open")){
    p.classList.remove("open");
    b.innerHTML="&#128393; Ouvrir l'&eacute;diteur de masques";
  } else {
    p.classList.add("open");
    b.innerHTML="&#215; Fermer l'&eacute;diteur";
    p.scrollIntoView({behavior:"smooth",block:"nearest"});
  }
}

function ME_open(){
  // Simule le chargement d'un PDF : affiche une image de placeholder
  var w=document.getElementById("meImgWrap");
  var img=document.getElementById("meImg");
  var hint=document.getElementById("meHint");
  var cv=document.getElementById("meOverlay");
  // Page simulée (rectangle blanc avec texte simulé)
  var c2=document.createElement("canvas");
  c2.width=595; c2.height=842;
  var ctx=c2.getContext("2d");
  ctx.fillStyle="#ffffff"; ctx.fillRect(0,0,595,842);
  ctx.fillStyle="#e5e7eb"; ctx.fillRect(0,0,595,90);
  ctx.fillStyle="#9ca3af"; ctx.font="bold 18px sans-serif"; ctx.fillText("EN-TETE ETABLISSEMENT  [LOGO]",30,40);
  ctx.fillStyle="#6b7280"; ctx.font="13px sans-serif";
  ctx.fillText("Service de cardiologie  |  Tel : 05.59.XX.XX.XX",30,68);
  ctx.fillStyle="#111827"; ctx.font="13px sans-serif";
  ctx.fillText("Patient : Dupont Jean   Ne le : 12/03/1955",30,130);
  ctx.fillText("IPP : 1234567   NDA : 8901234",30,155);
  ctx.fillText("Motif : Insuffisance cardiaque decompensee.",30,200);
  ctx.fillText("Traitement : FUROSEMIDE 40mg, BISOPROLOL 5mg.",30,225);
  ctx.fillStyle="#6b7280"; ctx.font="11px sans-serif";
  ctx.fillText("Signe : Dr Martin RPPS 12345678  |  mmartin@chuxx.fr",30,790);
  img.src=c2.toDataURL();
  img.onload=function(){
    cv.width=img.naturalWidth;
    cv.height=img.naturalHeight;
    cv.style.width=Math.round(img.naturalWidth*_meZoom)+"px";
    cv.style.height=Math.round(img.naturalHeight*_meZoom)+"px";
    ME_redraw();
  };
  hint.style.display="none";
  w.style.display="inline-block";
  document.getElementById("meStat").textContent="page_modele.pdf — page 1/1";
  ME_redraw();
}

function ME_zoom(d){
  _meZoom=Math.min(3,Math.max(0.3,_meZoom+d*0.15));
  document.getElementById("meZoomLbl").textContent=Math.round(_meZoom*100)+"%";
  var img=document.getElementById("meImg");
  var cv=document.getElementById("meOverlay");
  img.style.width=Math.round(img.naturalWidth*_meZoom)+"px";
  cv.style.width=Math.round(img.naturalWidth*_meZoom)+"px";
  cv.style.height=Math.round(img.naturalHeight*_meZoom)+"px";
  ME_redraw();
}

function _meCoord(e){
  var cv=document.getElementById("meOverlay");
  var r=cv.getBoundingClientRect();
  return {x:(e.clientX-r.left)/_meZoom, y:(e.clientY-r.top)/_meZoom};
}

function ME_mdown(e){
  _meDrawing=true;
  _meStart=_meCoord(e);
}
function ME_mmove(e){
  if(!_meDrawing)return;
  ME_redraw();
  var cur=_meCoord(e);
  var cv=document.getElementById("meOverlay");
  var ctx=cv.getContext("2d");
  ctx.save();
  ctx.scale(_meZoom,_meZoom);
  ctx.fillStyle="rgba(0,0,0,0.55)";
  ctx.strokeStyle="rgba(233,69,96,0.8)";
  ctx.lineWidth=1.5/_meZoom;
  var x=Math.min(_meStart.x,cur.x), y=Math.min(_meStart.y,cur.y);
  var w=Math.abs(cur.x-_meStart.x), h=Math.abs(cur.y-_meStart.y);
  ctx.fillRect(x,y,w,h);
  ctx.strokeRect(x,y,w,h);
  ctx.restore();
}
function ME_mup(e){
  if(!_meDrawing)return;
  _meDrawing=false;
  var cur=_meCoord(e);
  var x=Math.min(_meStart.x,cur.x), y=Math.min(_meStart.y,cur.y);
  var w=Math.abs(cur.x-_meStart.x), h=Math.abs(cur.y-_meStart.y);
  if(w>4&&h>4){
    _meMasks.push({x:Math.round(x),y:Math.round(y),w:Math.round(w),h:Math.round(h)});
    ME_updCount();
  }
  ME_redraw();
}
function ME_redraw(){
  var cv=document.getElementById("meOverlay");
  if(!cv.width)return;
  var ctx=cv.getContext("2d");
  ctx.clearRect(0,0,cv.width,cv.height);
  ctx.save();
  ctx.scale(_meZoom,_meZoom);
  ctx.fillStyle="rgba(0,0,0,0.82)";
  ctx.strokeStyle="rgba(233,69,96,0.6)";
  ctx.lineWidth=1/_meZoom;
  for(var i=0;i<_meMasks.length;i++){
    var m=_meMasks[i];
    ctx.fillRect(m.x,m.y,m.w,m.h);
    ctx.strokeRect(m.x,m.y,m.w,m.h);
    ctx.fillStyle="rgba(233,69,96,0.7)";
    ctx.font="10px sans-serif";
    ctx.fillText("x",m.x+m.w/2-4,m.y+m.h/2+4);
    ctx.fillStyle="rgba(0,0,0,0.82)";
  }
  ctx.restore();
}
function ME_clearPage(){
  _meMasks=[];
  ME_redraw();
  ME_updCount();
}
function ME_updCount(){
  document.getElementById("meMaskCount").textContent=_meMasks.length+" masque(s)";
}
function ME_save(){
  var name=document.getElementById("meTplName").value||"template_masques";
  alert("Template \""+name+"\" sauvegardé ("+_meMasks.length+" masque(s)).\n\nFichier : config/mask_templates/"+name+".json");
}
function ME_load(){
  alert("Sélection du fichier template simulée.\nDans l'application réelle : ouverture d'un sélecteur de fichier .json");
}
function ME_preview(){
  var dpi=parseInt(document.getElementById("meDpi").value)||200;
  alert("Prévisualisation raster à "+dpi+" DPI\nMasques appliqués : "+_meMasks.length+"\n\nDans l'application réelle : rendu de la page avec les zones noircies.");
}
function ME_apply(){
  var name=document.getElementById("meTplName").value||"template_masques";
  if(_meMasks.length===0){alert("Aucun masque défini. Dessinez au moins une zone.");return;}
  alert("Template \""+name+"\" activé pour le prochain traitement.\n"+_meMasks.length+" zone(s) seront masquées systématiquement.");
}

// Aide contextuelle
var HELP={
  "theme":["Apparence","Choisissez le th&egrave;me visuel adapt&eacute; &agrave; votre environnement.<br><br><strong>Sombre</strong> &mdash; fond fonc&eacute;, id&eacute;al en luminosit&eacute; r&eacute;duite.<br><strong>Clair</strong> &mdash; fond blanc, pour &eacute;crans bien &eacute;clair&eacute;s.<br><strong>M&eacute;dical</strong> &mdash; bleu et blanc, proche des interfaces hospitali&egrave;res.<br><strong>Neutre</strong> &mdash; tons gris discrets."],
  "fich":["Documents","Glissez-d&eacute;posez vos fichiers dans la zone, ou cliquez sur <strong>Fichiers</strong>.<br><br>Cliquez sur <strong>Dossier entier</strong> pour traiter automatiquement tous les documents d'un r&eacute;pertoire.<br><br><strong>Formats accept&eacute;s :</strong> PDF, Word (.docx), ODT, RTF, Texte, JPEG, PNG, TIFF."],
  "fmt":["Format de sortie","<strong>PDF anonymis&eacute;</strong> &mdash; le document avec les informations recouvertes de bandes noires. Recommand&eacute; pour l'archivage.<br><br><strong>Texte .txt</strong> &mdash; le contenu avec les donn&eacute;es remplac&eacute;es par des codes comme <code>[NOM]</code>, <code>[DATE_NAISSANCE]</code>. Utile pour l'analyse."],
  "det":["D&eacute;tection","Ces options contr&ocirc;lent <strong>ce qui est recherch&eacute;</strong> lors du traitement.<br><br>D&eacute;sactiver une cat&eacute;gorie peut laisser passer des donn&eacute;es personnelles. <strong>En cas de doute, laissez tout activ&eacute;.</strong>"],
  "ner":["Moteurs NER","Le logiciel utilise plusieurs moteurs d'intelligence artificielle qui <strong>se compl&egrave;tent mutuellement</strong>.<br><br><strong>CamemBERT-bio</strong> &mdash; tr&egrave;s rapide, entra&icirc;n&eacute; sur des dossiers m&eacute;dicaux fran&ccedil;ais.<br><strong>EDS-Pseudo</strong> &mdash; plus lent mais tr&egrave;s pr&eacute;cis sur le vocabulaire clinique.<br><strong>GLiNER</strong> &mdash; optionnel, apporte un vote crois&eacute;. D&eacute;sactivez-le pour acc&eacute;l&eacute;rer."],
  "wl":["Termes &agrave; conserver","Ces termes ne seront <strong>jamais masqu&eacute;s</strong>, m&ecirc;me s'ils ressemblent &agrave; un nom propre.<br><br>Exemples :<br>&bull; <code>FUROSEMIDE</code> &mdash; m&eacute;dicament, pas un patient<br>&bull; <code>classification internationale</code> &mdash; formulation m&eacute;dicale<br><br>Ajoutez ici tout terme incorrectement masqu&eacute;."],
  "bl":["Termes &agrave; toujours masquer","Ces termes seront <strong>syst&eacute;matiquement masqu&eacute;s</strong>, peu importe leur contexte.<br><br>Exemples :<br>&bull; <code>CHUXX</code> &mdash; sigle de l'&eacute;tablissement<br>&bull; <code>Dr Dupont</code> &mdash; m&eacute;decin &agrave; masquer dans tous les documents<br><br>Id&eacute;al pour les identifiants locaux non reconnus automatiquement."],
  "col":["Couleur de masquage","Choisissez la couleur des rectangles qui recouvrent les donn&eacute;es dans le PDF.<br><br>Le <strong>noir</strong> est la norme pour les documents officiels. Les autres couleurs facilitent la relecture lors de la validation."],
  "sty":["Style des marqueurs","Dans le fichier texte, chaque donn&eacute;e masqu&eacute;e est remplac&eacute;e par un marqueur.<br><br><strong>Crochets [NOM]</strong> &mdash; explicite sur le type de donn&eacute;e (recommand&eacute;).<br><strong>Etoiles ***</strong> &mdash; plus discret.<br><strong>Noirci</strong> &mdash; imite visuellement le masquage PDF."],
  "ep":["Epaisseur du masque","La marge d&eacute;termine de combien le rectangle d&eacute;passe le texte.<br><br>Une marge de <strong>2 points</strong> est suffisante pour la plupart des PDF. Augmentez si des lettres d&eacute;passent l&eacute;g&egrave;rement du masque."],
  "ph":["Codes de remplacement","Dans le texte anonymis&eacute;, chaque donn&eacute;e est remplac&eacute;e par un code entre crochets indiquant sa nature.<br><br>Cela permet de savoir <em>ce qui a &eacute;t&eacute; masqu&eacute;</em> sans r&eacute;v&eacute;ler <em>ce que c'&eacute;tait</em>."],
  "medit":["&Eacute;diteur de masques de zones","Cet outil permet de <strong>masquer des zones fixes</strong> qui apparaissent au m&ecirc;me endroit sur tous les documents d'un mod&egrave;le.<br><br>Exemples : logo de l'&eacute;tablissement en haut de page, tampon de signature, en-t&ecirc;te avec num&eacute;ro de fax.<br><br><strong>Comment utiliser :</strong><br>1. Cliquez <em>Ouvrir PDF</em> pour charger un document mod&egrave;le.<br>2. Cliquez-glissez pour tracer des rectangles sur les zones &agrave; masquer.<br>3. Donnez un nom au template et cliquez <em>Sauver</em>.<br>4. Cliquez <em>Appliquer le template</em> pour l'activer sur les prochains traitements."],
  "exp":["Exporter","G&eacute;n&egrave;re un fichier <strong>.json</strong> contenant vos listes personnalis&eacute;es.<br><br>Envoyez ce fichier par e-mail &agrave; d'autres &eacute;tablissements pour partager votre configuration."],
  "imp":["Importer","Importez un fichier .json re&ccedil;u d'un autre &eacute;tablissement.<br><br>La configuration est <strong>fusionn&eacute;e</strong> avec la v&ocirc;tre &mdash; vos r&eacute;glages locaux ne sont pas supprim&eacute;s."],
  "rul":["R&egrave;gles administrables","Ces r&egrave;gles adaptent le moteur &agrave; votre &eacute;tablissement.<br><br><strong>Actif</strong> &mdash; appliqu&eacute;e &agrave; chaque traitement.<br><strong>Candidat</strong> &mdash; en attente de validation qualit&eacute;.<br><strong>Brouillon</strong> &mdash; en cours de cr&eacute;ation, non appliqu&eacute;e.<br><br>Cliquez sur <strong>Tester</strong> pour simuler l'effet d'une r&egrave;gle avant de l'activer."]
};
function H(k){
  var h=HELP[k]||["Aide","Information non disponible."];
  document.getElementById("mt").innerHTML=h[0];
  document.getElementById("mb").innerHTML=h[1];
  document.getElementById("mo").classList.add("open");
}
function CH(){document.getElementById("mo").classList.remove("open");}
document.addEventListener("keydown",function(e){if(e.key==="Escape")CH();});
</script>
</body>
</html>"""

HTML = HTML.replace("LOGO_PLACEHOLDER", LOGO_SRC)
OUT_PATH.write_text(HTML, encoding="utf-8")
print("OK — {} ({} Ko)".format(OUT_PATH, OUT_PATH.stat().st_size // 1024))
