/* ============================================================================
   CléPass v3 — vue principale (portage fidèle du template de
   « CléPass Pastel.dc.html »). Reçoit `v` = renderVals() de app.jsx.
   Conventions de portage :
     {{ x }}                  → {v.x}
     sc-if value="{{ c }}"    → {v.c && <>…</>}
     sc-for list as x         → {v.list.map((x, i) => …)}
     style="…"                → style={sx('…')}
     style-hover / style-focus→ <Hv hover=… focus=… />
   ============================================================================ */
(function () {
const { sx, Hv } = window.CP;
const F = React.Fragment;

window.CPAppView = function (v) {
  const Editeur = window.CPEditeur;
  return (
<div data-theme={v.themeAttr} style={sx('position:fixed;inset:0;overflow:hidden;background:#ebe6f3')}>
<div style={sx('position:absolute;inset:0;background:#fbf7fb;overflow:hidden;display:flex;flex-direction:column;color:#3a3340')}>

  {/* ===================== EN-TÊTE ===================== */}
  <div style={sx('display:flex;align-items:center;justify-content:space-between;padding:' + (v.mobile ? '10px 12px' : '15px 22px') + ';flex:none')}>
    <div style={sx('display:flex;align-items:center;gap:' + (v.mobile ? '10px' : '14px'))}>
      {/* Ouvre le tiroir des filtres / dossiers : en mobile la barre latérale
          n'est plus une colonne, il n'existe aucun autre accès. */}
      {v.mobile && <div onClick={v.onBarreToggle} title="Filtres et dossiers" style={sx('width:40px;height:40px;border-radius:11px;background:#f3ecf3;color:#6a6070;display:grid;place-items:center;cursor:pointer;flex:none')}><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M4 7h16"></path><path d="M4 12h16"></path><path d="M4 17h16"></path></svg></div>}
      <div style={sx('display:flex;align-items:center;gap:11px')}><img src={v.logoDark ? 'assets/logo-dark.svg' : 'assets/logo.svg'} width="32" height="32" alt="CléPass" style={{ display: 'block', flex: 'none' }} /><span style={sx('font-weight:800;font-size:17px')}>CléPass</span></div>
      {/* Bascule Pro/Perso : retirée en mobile faute de place (elle reste
          atteignable en tournant l'appareil ou sur un écran plus large). */}
      {!v.mobile && <div style={sx('display:flex;background:#f3ecf3;border-radius:10px;padding:3px;gap:2px')}>
        <div onMouseEnter={v.espPro.onEnter} onMouseLeave={v.espPro.onLeave} style={sx(v.espPro.style)} onClick={v.espPro.onClick}><span style={sx('font-size:13px')}>{v.iCase}</span>{v.proLabel}{v.espPro.hovered && <span onClick={v.espPro.onEdit} title="Renommer l'espace" style={sx('margin-left:3px;display:inline-flex;align-items:center;color:#a98bde;cursor:pointer;font-size:12px')}>{v.iEdit}</span>}</div>
        <div style={sx(v.espPerso.style)} onClick={v.espPerso.onClick}><span style={sx('font-size:13px')}>{v.iUser}</span>Perso</div>
      </div>}
    </div>
    <div style={sx('display:flex;align-items:center;gap:0;font-size:13px;color:#9a8fa0')}>
      {/* ── Annuler / Refaire + historique des 10 dernières actions ──
          Masqués en mobile : trois boutons de plus dans un en-tête déjà
          saturé, pour des gestes qui relèvent du poste de travail. */}
      {!v.mobile && <div style={sx('position:relative;display:flex;align-items:center;gap:4px;margin-right:10px')}>
        <div onClick={v.onUndo} title={v.histUndoTitle} style={sx(v.histUndoStyle)}><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 14L4 9l5-5"></path><path d="M4 9h11a5 5 0 0 1 0 10h-4"></path></svg></div>
        <div onClick={v.onRedo} title={v.histRedoTitle} style={sx(v.histRedoStyle)}><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="2"><path d="M15 14l5-5-5-5"></path><path d="M20 9H9a5 5 0 0 0 0 10h4"></path></svg></div>
        <div onClick={v.onHistToggle} title="Historique des 10 dernières actions" style={sx(v.histMenuStyle)}><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 2"></path></svg></div>
        {v.histOpen && <F>
          <div onClick={v.onHistClose} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:44')}></div>
          <div style={sx('position:absolute;top:calc(100% + 8px);right:0;width:420px;max-width:calc(100vw - 32px);background:#fff;border-radius:14px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:8px;z-index:45;text-align:left;transform-origin:top right;animation:scDrop .15s ease')}>
            {v.histRedoRows.length > 0 && <F>
              <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:7px 10px 6px")}>À REFAIRE</div>
              {v.histRedoRows.map((h, i) => (
                <Hv key={'r' + i} onClick={h.onClick} title={h.title} style="display:flex;align-items:flex-start;gap:9px;padding:8px 10px;border-radius:9px;cursor:pointer;opacity:.7" hover="background:#f3eefb;opacity:1">
                  <span style={sx('color:#6b4fb8;display:inline-flex;flex:none;margin-top:2px')}><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2"><path d="M15 14l5-5-5-5"></path><path d="M20 9H9a5 5 0 0 0 0 10h4"></path></svg></span>
                  <span style={sx('flex:1;min-width:0')}>
                    <span style={sx('display:block;font-size:12.5px;font-weight:600;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{h.label}</span>
                    {h.detail && <span style={sx('display:block;margin-top:3px')}>{h.detail.split('\n').map((ln, j) => { const ci = ln.indexOf(' : '); return (<span key={j} style={sx('display:block;font-size:11px;line-height:1.5;color:#8a7f96;margin-top:1px;word-break:break-word')}>{ci > 0 ? <F><span style={sx('color:#6a6070;font-weight:600')}>{ln.slice(0, ci)}</span>{ln.slice(ci)}</F> : ln}</span>); })}</span>}
                  </span>
                  <span style={sx('font-size:10.5px;color:#b3a8b9;flex:none')}>{h.time}</span>
                </Hv>
              ))}
              <div style={sx('height:1px;background:#f0eaf2;margin:5px 8px')}></div>
            </F>}
            <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:7px 10px 6px")}>DERNIÈRES ACTIONS</div>
            {v.histRows.map((h, i) => (
              <Hv key={i} onClick={h.onClick} title={h.title} style="display:flex;align-items:flex-start;gap:9px;padding:8px 10px;border-radius:9px;cursor:pointer" hover="background:#f7f3fb">
                <span style={sx('color:#a98bde;display:inline-flex;flex:none;margin-top:2px')}><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 14L4 9l5-5"></path><path d="M4 9h11a5 5 0 0 1 0 10h-4"></path></svg></span>
                <span style={sx('flex:1;min-width:0')}>
                  <span style={sx('display:block;font-size:12.5px;font-weight:600;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{h.label}</span>
                  {h.detail && <span style={sx('display:block;margin-top:3px')}>{h.detail.split('\n').map((ln, j) => { const ci = ln.indexOf(' : '); return (<span key={j} style={sx('display:block;font-size:11px;line-height:1.5;color:#8a7f96;margin-top:1px;word-break:break-word')}>{ci > 0 ? <F><span style={sx('color:#6a6070;font-weight:600')}>{ln.slice(0, ci)}</span>{ln.slice(ci)}</F> : ln}</span>); })}</span>}
                </span>
                <span style={sx('font-size:10.5px;color:#b3a8b9;flex:none')}>{h.time}</span>
              </Hv>
            ))}
            {!v.histRows.length && <div style={sx('font-size:12px;color:#a99fb0;padding:10px;text-align:center')}>Aucune action historisée pour l'instant.</div>}
            {v.histRows.length > 0 && <div style={sx('font-size:10.5px;color:#a99fb0;line-height:1.45;padding:7px 10px 5px;border-top:1px solid #f0eaf2;margin-top:4px')}>Cliquer une action l'annule ainsi que toutes celles qui ont suivi.</div>}
          </div>
        </F>}
      </div>}
      {/* ── Menu d'actions du mobile ──────────────────────────────────────
          Recueille ce que l'en-tête d'un téléphone ne peut pas afficher :
          la bascule Pro/Perso (et son renommage) et l'annulation. Sans lui,
          ces fonctions n'étaient atteignables sur AUCUN petit écran. */}
      {v.mobile && <div style={sx('position:relative;margin-right:8px')}>
        <div onClick={v.menuActions.onToggle} title="Espaces et historique" style={sx('width:40px;height:40px;border-radius:11px;background:#f3ecf3;color:#6a6070;display:grid;place-items:center;cursor:pointer;flex:none')}>
          <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M4 7h16M4 12h16M4 17h16" /></svg>
        </div>
        {v.menuActions.open && <F>
          <div onClick={v.menuActions.onClose} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:44')}></div>
          <div style={sx('position:absolute;top:calc(100% + 8px);right:0;width:250px;max-width:calc(100vw - 24px);background:#fff;border-radius:14px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(20,15,30,.45);padding:8px;z-index:45')}>
            <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:6px 10px 7px")}>ESPACE</div>
            <div style={sx(v.menuActions.railStyle)}>
              <div onClick={v.menuActions.onPro} style={sx(v.menuActions.segmentStyle(v.menuActions.espace === 'pro'))}><span style={sx('font-size:13px;flex:none')}>{v.iCase}</span><span style={sx('min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap')}>{v.menuActions.proLabel}</span></div>
              <div onClick={v.menuActions.onPerso} style={sx(v.menuActions.segmentStyle(v.menuActions.espace === 'perso'))}><span style={sx('font-size:13px;flex:none')}>{v.iUser}</span>Perso</div>
            </div>
            <Hv onClick={v.menuActions.onRenommer} style={v.menuActions.ligneStyle(true)} hover="background:#f7f2fa">Renommer l’espace pro</Hv>
            <div style={sx('height:1px;background:#f0eaf2;margin:6px 8px')}></div>
            <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:6px 10px 7px")}>HISTORIQUE</div>
            {/* Les libellés portent déjà l'action concernée (« Annuler :
                Création de la fiche … »), ou « Rien à annuler » : inutile de
                doubler d'une infobulle, invisible au doigt. */}
            <Hv onClick={v.menuActions.onUndo} style={v.menuActions.ligneStyle(v.histUndoActif)} hover={v.histUndoActif ? 'background:#f7f2fa' : ''}>
              <span style={sx('display:inline-flex;flex:none')}><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 14L4 9l5-5" /><path d="M4 9h11a5 5 0 0 1 0 10h-3" /></svg></span>
              <span style={sx('flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.histUndoTitle}</span>
            </Hv>
            <Hv onClick={v.menuActions.onRedo} style={v.menuActions.ligneStyle(v.histRedoActif)} hover={v.histRedoActif ? 'background:#f7f2fa' : ''}>
              <span style={sx('display:inline-flex;flex:none')}><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 14l5-5-5-5" /><path d="M20 9H9a5 5 0 0 0 0 10h3" /></svg></span>
              <span style={sx('flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.histRedoTitle}</span>
            </Hv>
          </div>
        </F>}
      </div>}
      <div style={sx('position:relative')}>
        <div onClick={v.onMenu} title="Compte & déconnexion" style={sx(v.menuBtnStyle)}>{!v.mobile && v.compteEmail}<span style={sx('display:inline-flex;font-size:' + (v.mobile ? '17px' : '15px'))}>{v.iLock}</span></div>
        {v.menuOpen && <F>
          <div onClick={v.onMenu} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:38')}></div>
          <div style={sx('position:absolute;top:calc(100% + 8px);right:0;width:344px;max-width:calc(100vw - 24px);background:#fff;border-radius:14px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:8px;z-index:41;transform-origin:top right;animation:scDrop .15s ease')}>
            <div style={sx('display:flex;align-items:center;gap:10px;padding:9px 10px 11px')}>
              <div style={sx('width:34px;height:34px;border-radius:10px;background:#f0c9e4;color:#b14f8e;display:grid;place-items:center;font-size:15px;flex:none')}>{v.iUser}</div>
              <div style={sx('min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{v.compteNom}</div><div style={sx('font-size:11px;color:#a99fb0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.compteEmail}</div></div>
            </div>
            <div style={sx('height:1px;background:#f0eaf2;margin:2px 4px 6px')}></div>
            <Hv onClick={v.onLockDevice} style="display:flex;align-items:center;gap:11px;padding:10px;border-radius:10px;cursor:pointer" hover="background:#f5f0f6">
              <div style={sx('width:32px;height:32px;border-radius:9px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:16px;flex:none')}>{v.iLock}</div>
              <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>Déconnecter le coffre</div><div style={sx('font-size:11px;color:#a99fb0')}>Verrouille cet appareil</div></div>
            </Hv>
            <Hv onClick={v.onLockAll} style="display:flex;align-items:center;gap:11px;padding:10px;border-radius:10px;cursor:pointer" hover="background:#fdf1f1">
              <div style={sx('width:32px;height:32px;border-radius:9px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;font-size:16px;flex:none')}>{v.iPower}</div>
              <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#c0392b')}>Déconnecter de tous les périphériques</div><div style={sx('font-size:11px;color:#c0716a')}>Verrouillage panique · ferme partout</div></div>
            </Hv>

            {/* Extender « historique de connexion » : les dernières ouvertures
                du coffre (appareil, IP, lieu, navigateur, date). */}
            <div style={sx('height:1px;background:#f0eaf2;margin:6px 4px')}></div>
            <Hv onClick={v.onMenuSessToggle} style="display:flex;align-items:center;justify-content:center;gap:7px;padding:9px 10px;border-radius:10px;cursor:pointer;font-size:11.5px;font-weight:600;color:#9a8fa0" hover="background:#f5f0f6;color:#6b4fb8">
              Voir l'historique de connexion
              <span style={sx('display:inline-flex;font-size:12px;transition:transform .18s ease;transform:rotate(' + (v.menuSessOpen ? '-90deg' : '90deg') + ')')}>{v.iChev}</span>
            </Hv>
            {v.menuSessOpen && <div className="scl" style={sx('max-height:216px;overflow:auto;margin:2px 2px 0')}>
              {v.menuSessLoading && <div style={sx('font-size:12px;color:#a99fb0;padding:12px;text-align:center')}>Chargement des connexions…</div>}
              {v.menuSessEmpty && <div style={sx('font-size:12px;color:#a99fb0;padding:12px;text-align:center')}>Aucune connexion récente.</div>}
              {v.menuSessions.map((s, i) => (
                <div key={i} style={sx('display:flex;gap:10px;align-items:flex-start;padding:8px 6px;' + (i ? 'border-top:1px solid #f4eff6;' : ''))}>
                  <div style={sx('width:28px;height:28px;border-radius:8px;display:grid;place-items:center;font-size:14px;flex:none;margin-top:1px;' + (s.courante ? 'background:#efe7fc;color:#6b4fb8;' : 'background:#f3eef5;color:#a99fb0;'))}>{v.iGlobe}</div>
                  <div style={sx('flex:1;min-width:0')}>
                    <div style={sx('display:flex;align-items:center;gap:6px')}>
                      <span style={sx('font-size:12px;font-weight:700;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{s.nom}</span>
                      {s.courante && <span style={sx('flex:none;font-size:9px;font-weight:700;letter-spacing:.04em;background:#efe7fc;color:#6b4fb8;border-radius:999px;padding:2px 6px')}>Cet appareil</span>}
                      {s.multi && <span title={s.nb + ' connexions regroupées'} style={sx('flex:none;font-size:9px;font-weight:700;background:#f1ecf6;color:#8a7f90;border-radius:999px;padding:2px 6px')}>× {s.nb}</span>}
                      <span style={sx('flex:none;margin-left:auto;font-size:10px;color:#a99fb0')}>{s.date}</span>
                    </div>
                    <div style={sx('font-size:10.5px;color:#7a7184;margin-top:2px')}>{s.ip} · {s.lieu}</div>
                    {s.ua && <div title={s.ua} style={sx('font-size:9.5px;color:#b3a8b9;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{s.ua}</div>}
                  </div>
                </div>
              ))}
            </div>}
          </div>
        </F>}
      </div>
    </div>
  </div>

  {/* ============ BANDEAU « ALERTE CONNEXION INHABITUELLE » ============
      Levé au déverrouillage quand la session courante vient d'un appareil ou
      d'un lieu jamais vus (réglage « Sécurité & outils »). */}
  {v.alerteCx && <div style={sx('flex:none;margin:0 16px 12px;display:flex;align-items:flex-start;gap:12px;background:#fdf1e3;border:1px solid #f0d9b5;border-radius:14px;padding:13px 16px')}>
    <span style={sx('width:30px;height:30px;border-radius:9px;background:#fdeede;color:#b87e2e;display:grid;place-items:center;flex:none;font-size:15px')}>{v.iGlobe}</span>
    <div style={sx('flex:1;min-width:0')}>
      <div style={sx('font-weight:700;font-size:13px;color:#8a6d3b')}>Connexion inhabituelle détectée</div>
      {v.alerteCx.motifs.map((m) => (<div key={m} style={sx('font-size:11.5px;color:#8a6d3b;line-height:1.5;margin-top:2px')}>{m}</div>))}
      <div style={sx('font-size:11.5px;color:#a08a63;line-height:1.5;margin-top:4px')}>Si ce n’est pas vous, déconnectez toutes les sessions et changez votre mot de passe maître.</div>
    </div>
    <Hv onClick={v.alerteCx.onDeconnecter} style="flex:none;padding:8px 13px;border-radius:10px;background:#b87e2e;color:#fff;font-size:12px;font-weight:600;cursor:pointer" hover="filter:brightness(1.08)">Déconnecter partout</Hv>
    <span onClick={v.alerteCx.onFermer} title="Ignorer" style={sx('flex:none;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;color:#a08a63;cursor:pointer;font-size:13px')}>✕</span>
  </div>}

  <div style={sx('flex:1;display:flex;gap:' + (v.mobile ? '0' : '12px') + ';padding:0 ' + (v.mobile ? '10px 10px' : '16px 16px') + ';min-height:0' + (v.mobile ? ';position:relative' : ''))}>

    {/* Voile du tiroir : le refermer d'un tap hors de la barre est le seul
        geste naturel sur téléphone. */}
    {v.barreOuverte && <div onClick={v.onBarreClose} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(4px);z-index:60')}></div>}

    {/* ===================== BARRE LATÉRALE =====================
        En mobile elle devient un tiroir posé par-dessus le contenu, et n'est
        montée que lorsqu'il est ouvert. Elle GARDE display:flex + une hauteur
        définie (top/bottom) : les margin-top:auto de la carte Extension et de
        la rangée du bas en dépendent. */}
    {(!v.mobile || v.barreOuverte) && <div className="scl" style={sx(v.mobile
      ? 'position:absolute;left:0;top:0;bottom:0;z-index:70;width:272px;max-width:84%;background:#fff;border:1px solid #e4dce8;border-radius:0 18px 18px 0;display:flex;flex-direction:column;gap:3px;overflow:auto;padding:10px 10px 0'
      : 'flex:0 0 21.4%;max-width:400px;min-width:0;display:flex;flex-direction:column;gap:3px;overflow:auto;padding-right:6px')}>
      <div onMouseEnter={v.onFiltresEnter} onMouseLeave={v.onHdrLeave} style={sx('display:flex;align-items:center;justify-content:space-between;margin:2px 8px 6px;min-height:22px')}>
        <span title="Filtrez la liste des fiches par type (générique ou personnalisé)" style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;cursor:help")}>Filtres</span>
        <Hv tag="span" onClick={v.onCatManager} title="Gérer les types" style={v.filtresAddStyle} hover="background:#efe7fc;color:#6b4fb8">{v.iEdit}</Hv>
      </div>
      <div style={sx('display:flex;gap:5px')}>
        <div style={sx(v.catAll.style)} onClick={v.catAll.onClick}><div style={sx(v.catAll.tileStyle)}>{v.catAll.icon}</div>{v.catAll.label}<span style={sx(v.catAll.countStyle)}>{v.catAll.count}</span></div>
        <div style={sx(v.catFav.style)} onClick={v.catFav.onClick}><div style={sx(v.catFav.tileStyle)}>{v.catFav.icon}</div><span style={sx(v.catFav.countStyle)}>{v.catFav.count}</span></div>
        <div style={sx(v.catShared.style)} onClick={v.catShared.onClick} title="Partagés"><div style={sx(v.catShared.tileStyle)}>{v.catShared.icon}</div><span style={sx(v.catShared.countStyle)}>{v.catShared.count}</span></div>
      </div>
      <div style={sx('display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:4px;margin-top:5px')}>
        {v.catsGrid.map((cat, i) => (
          <div key={cat.label + i} style={sx(cat.style)} onClick={cat.onClick}><div style={sx(cat.tileStyle)}>{cat.icon}</div><span style={sx('flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{cat.label}</span><span style={sx(cat.countStyle)}>{cat.count}</span></div>
        ))}
      </div>
      <div onMouseEnter={v.onDossiersEnter} onMouseLeave={v.onHdrLeave} style={sx('display:flex;align-items:center;justify-content:space-between;margin:13px 8px 5px;min-height:22px')}>
        <span onDragOver={v.folderRootDrop.active ? v.folderRootDrop.onOver : undefined} onDragLeave={v.folderRootDrop.onLeave} onDrop={v.folderRootDrop.onDrop} style={sx("font:600 10px 'Sora';letter-spacing:.13em;text-transform:uppercase;" + (v.folderRootDrop.active ? 'padding:3px 7px;margin:-3px -7px;border-radius:7px;' : '') + (v.folderRootDrop.hover ? 'background:#e7f7ef;box-shadow:inset 0 0 0 1.5px #2e8f72;color:#2e8f72;' : 'color:#b3a8b9;'))}>{v.folderRootDrop.active ? 'Dossiers · racine' : 'Dossiers'}</span>
        <Hv tag="span" onClick={v.onAddRootFolder} title="Nouveau dossier" style={v.dossiersAddStyle} hover="background:#efe7fc;color:#6b4fb8">+</Hv>
      </div>
      {v.folders.map((folder) => (
        <div key={folder.id} draggable={folder.drag} onDragStart={folder.onDragStart} onDragEnd={folder.onDragEnd} style={sx(folder.rowStyle)} onMouseEnter={folder.onEnter} onMouseLeave={folder.onLeave} onDragOver={folder.onDropOver} onDragLeave={folder.onDropLeave} onDrop={folder.onDropItem}>
          <span onClick={folder.onChevron} style={sx(folder.chevStyle)}>{v.iChev}</span>
          <span style={sx(folder.iconStyle)}>{folder.icon}</span>
          {folder.editing && <input value={folder.name} onChange={folder.onNameChange} onKeyDown={folder.onNameKey} onBlur={folder.onNameBlur} placeholder="Nom du dossier" autoFocus={true} style={sx(folder.inputStyle)} />}
          {folder.notEditing && <F><span onClick={folder.onClick} style={sx(folder.nameStyle)}>{folder.name}</span><span style={sx(folder.countStyle)}>{folder.count}</span><Hv tag="span" onClick={folder.onAdd} title="Nouveau sous-dossier" style={folder.addStyle} hover="background:#efe7fc;color:#6b4fb8">+</Hv></F>}
        </div>
      ))}

      {/* Carte « Extension Chrome » : proposée tant que l'extension n'est pas
          détectée ; un clic déplie les étapes d'installation. Elle porte le
          margin-top:auto quand elle est visible (sinon la rangée du bas le
          garde) — deux marges auto se partageraient l'espace libre. */}
      {v.extPromo && <div style={sx('margin-top:auto;background:#efe7fc;border-radius:13px;padding:9px 10px;display:flex;flex-direction:column;gap:7px')}>
        <div style={sx('display:flex;align-items:center;gap:9px;cursor:pointer')} onClick={v.extPromo.onToggle}>
          <div style={sx('width:26px;height:26px;border-radius:9px;background:linear-gradient(135deg,#7c5cff,#b06ad6);display:grid;place-items:center;color:#fff;font-size:13px;flex:none')}>{v.extPromo.icone}</div>
          <div style={sx('flex:1;min-width:0')}>
            <div style={sx('font-size:11.5px;font-weight:700;color:#3a3340')}>Extension Chrome</div>
            <div style={sx('font-size:10px;color:#8a7f96')}>Remplissage auto sur les sites</div>
          </div>
          <span style={sx('font-size:10.5px;font-weight:700;color:#6b4fb8;white-space:nowrap')}>{v.extPromo.ouvert ? 'Fermer' : 'Installer'}</span>
        </div>
        {v.extPromo.ouvert && <div style={sx('font-size:10.5px;color:#5a4f66;line-height:1.6')}>
          1. Ouvrez <b>chrome://extensions</b><br />
          2. Activez le <b>Mode développeur</b><br />
          3. « Charger l’extension non empaquetée »<br />→ dossier <b>extension/</b> de CléPass.
        </div>}
      </div>}
      <div style={sx((v.extPromo ? '' : 'margin-top:auto;') + 'position:sticky;bottom:0;display:flex;gap:6px;padding-top:12px;background:' + v.fondBarre + ';box-shadow:0 -8px 12px -6px ' + v.fondBarre)}>
        <div style={sx(v.healthStyle)} onClick={v.onSante} title={v.santeTitle}>
          {v.santeBack && <F>
            <div style={sx('display:grid;place-items:center;width:28px;height:28px;font-size:16px')}><span style={sx('display:inline-flex;transform:rotate(180deg)')}>{v.iChev}</span></div>
            <span style={sx('font-size:11px;font-weight:600')}>Retour</span>
          </F>}
          {v.santeNormal && <F>
            <div style={sx('position:relative;width:28px;height:28px;flex:none')}>
              <div style={sx(v.sante.tileRing)}><div style={sx(v.sante.tileHole)}>{v.sante.score}</div></div>
              {v.sante.tileAlerte && <span style={sx('position:absolute;top:-5px;right:-5px;min-width:15px;height:15px;padding:0 3px;border-radius:999px;background:#c0392b;color:#fff;font-size:8px;font-weight:700;display:grid;place-items:center;border:2px solid ' + v.fondBarre)}>{v.sante.tileAlertes}</span>}
            </div>
            <span style={sx('font-size:11px;font-weight:600')}>Santé</span>
          </F>}
        </div>
        <div style={sx(v.toolsStyle)} onClick={v.onToolsTile} title={v.toolsTitle}>
          {v.toolsBack && <F>
            <div style={sx('display:grid;place-items:center;width:28px;height:28px;font-size:16px')}><span style={sx('display:inline-flex;transform:rotate(180deg)')}>{v.iChev}</span></div>
            <span style={sx('font-size:11px;font-weight:600')}>Retour</span>
          </F>}
          {v.toolsNormal && <F>
            <div style={sx('display:grid;place-items:center;width:28px;height:28px;font-size:18px')}>{v.iSliders}</div>
            <span style={sx('font-size:11px;font-weight:600')}>Outils</span>
          </F>}
        </div>
        <div style={sx(v.settingsStyle)} onClick={v.onSettingsTile} title={v.settingsTitle}>
          {v.settingsBack && <F>
            <div style={sx('display:grid;place-items:center;width:28px;height:28px;font-size:16px')}><span style={sx('display:inline-flex;transform:rotate(180deg)')}>{v.iChev}</span></div>
            <span style={sx('font-size:11px;font-weight:600')}>Retour</span>
          </F>}
          {v.settingsNormal && <F>
            <div style={sx('display:grid;place-items:center;width:28px;height:28px;font-size:18px')}>{v.iSettings}</div>
            <span style={sx('font-size:11px;font-weight:600;white-space:nowrap')}>Paramètres</span>
          </F>}
        </div>
      </div>
    </div>}

    {/* ===================== LISTE ===================== */}
    {v.showList && <div style={sx('flex:358 1 0;min-width:0;background:#fff;border-radius:18px;box-shadow:0 6px 22px -12px rgba(120,80,140,.22);display:flex;min-height:0;overflow:hidden')}>
      {/* Rail alphabétique : 27 cibles de 17 px, impossibles à viser au doigt
          et 26 px pris sur une largeur déjà comptée — retiré en mobile. */}
      {!v.mobile && <div style={sx('width:26px;flex:none;display:flex;flex-direction:column;align-items:center;justify-content:space-between;padding:12px 0;background:#fff')}>
        {v.alphabet.map((a) => (<div key={a.label} style={sx(a.style)} onClick={a.onClick}>{a.label}</div>))}
      </div>}
      <div style={sx('flex:1;min-width:0;display:flex;flex-direction:column;min-height:0')}>
      <div style={sx('padding:17px 18px 10px;display:flex;align-items:center;justify-content:space-between;flex:none')}><div style={sx('font-weight:700;font-size:18px')}>{v.title} <span style={sx('font-size:13px;color:#b3a8b9;font-weight:500')}>· {v.count}</span></div><div onClick={v.onAddToggle} title="Nouvel élément" style={sx('width:' + (v.mobile ? '40' : '30') + 'px;height:' + (v.mobile ? '40' : '30') + 'px;border-radius:10px;background:#f3ecf3;display:grid;place-items:center;color:#6a6070;font-size:' + (v.mobile ? '18' : '15') + 'px;cursor:pointer')}>{v.iPlus}</div></div>
      <div style={sx('margin:0 16px 10px;display:flex;align-items:center;gap:9px;padding:10px 13px;background:#f5f0f6;border-radius:12px;flex:none')}><span style={sx('font-size:15px;color:#b3a8b9')}>{v.iSearch}</span><input value={v.q} onChange={v.onSearch} placeholder="Rechercher une fiche…" style={sx('border:0;background:transparent;outline:none;font-size:13px;color:#3a3340;width:100%')} /></div>
      {/* Invitations de partage : rien n'entre dans le coffre sans accord. */}
      {v.invitations.rows.length > 0 && <div style={sx('margin:0 16px 10px;flex:none')}>
        {v.invitations.err && <div style={sx('background:#fbe4e4;color:#c0392b;border-radius:10px;padding:8px 11px;font-size:11.5px;font-weight:600;margin-bottom:7px')}>{v.invitations.err}</div>}
        {v.invitations.rows.map((r) => (
          <div key={r.key} style={sx('background:#fdf4e3;border:1px solid #eeddba;border-radius:12px;padding:11px 13px;margin-bottom:7px')}>
            <div style={sx('font-size:12.5px;color:#8a6d3b;line-height:1.45')}><b style={sx('color:#6a5427')}>{r.de}</b> souhaite partager une fiche avec vous.</div>
            <div style={sx('font-size:11px;color:#a08a5e;margin-top:3px')}>{r.quoi}</div>
            <div style={sx('display:flex;gap:7px;margin-top:9px')}>
              <Hv onClick={r.onAccept} style={`font-size:11.5px;font-weight:700;color:#fff;background:#2e8f72;border-radius:9px;padding:6px 12px;cursor:pointer;${r.busy ? 'opacity:.6;' : ''}`} hover="background:#26775f">{r.busy ? '…' : 'Accepter'}</Hv>
              <Hv onClick={r.onRefuse} style={`font-size:11.5px;font-weight:600;color:#6a6070;background:#f3ecf3;border-radius:9px;padding:6px 12px;cursor:pointer;${r.busy ? 'opacity:.6;' : ''}`} hover="background:#ece3f1">Refuser</Hv>
            </div>
          </div>
        ))}
      </div>}
      <div className="scl" ref={v.listRef} style={sx('padding:2px 12px 10px;display:flex;flex-direction:column;gap:5px;overflow:auto')}>
        {v.items.map((item) => (
          <div key={item.id} data-alpha={item.alpha} draggable={item.drag} onDragStart={item.onDragStart} onDragEnd={item.onDragEnd} style={sx(item.style)} onClick={item.onClick}>{item.avEl}<div style={sx('min-width:0;flex:1')}><div style={sx('font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{item.name}</div><div style={sx('font-size:12px;color:#b3a8b9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{item.sub}</div></div>{item.shared ? <span title="Partagé" style={sx(item.shareStyle)}>{v.iShare} {item.shareCount}</span> : null}</div>
        ))}
        {v.leavingList.map((g, i) => (
          <div key={'lv' + i} style={sx(g.style)}>{g.av}<div style={sx('min-width:0;flex:1')}><div style={sx('font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#3a3340')}>{g.name}</div><div style={sx('font-size:12px;color:#b3a8b9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{g.sub}</div></div></div>
        ))}
        {v.isEmpty && <div style={sx('padding:30px 18px;text-align:center;color:#b3a8b9')}><div style={sx('font-size:30px;opacity:.5;margin-bottom:8px;display:flex;justify-content:center')}>{v.iFolder}</div><div style={sx('font-size:12.5px')}>{v.emptyMsg}</div></div>}
      </div>
      </div>
    </div>}

    {v.showDetail && <div className="scl" style={sx('flex:526 1 0;min-width:0;background:#fff;border-radius:18px;box-shadow:0 6px 22px -12px rgba(120,80,140,.22);overflow:auto')}>

      {/* Retour en mobile : le détail occupe seul l'écran, sans ce bandeau on
          ne peut plus revenir à la liste. Collant, car le panneau défile. */}
      {v.mobileRetour && <div onClick={v.onMobileRetour} style={sx('position:sticky;top:0;z-index:6;display:flex;align-items:center;gap:8px;min-height:44px;padding:0 14px;background:#fff;border-bottom:1px solid #f0eaf2;font-size:13px;font-weight:600;color:#6b4fb8;cursor:pointer')}><span style={sx('display:inline-flex;transform:rotate(180deg);font-size:15px')}>{v.iChev}</span>{v.mobileRetourLabel}</div>}

      {/* ===================== VUE ÉLÉMENT ===================== */}
      {v.isItem && <div style={sx('padding:' + (v.mobile ? '14px 14px 18px' : '24px 26px'))}>
        {v.editMode && <div style={sx('animation:scEditIn .32s cubic-bezier(.2,.8,.25,1)')}>
          {/* Titre / sous-titre : deux champs encadrés collés en un seul bloc (pas
              d'arrondi ni de double filet entre eux — le sous-titre remonte de la
              largeur d'une bordure), sans étiquette : le cadre suffit à montrer
              qu'on peut écrire, là où la lecture n'affiche que du texte. */}
          <div style={sx('display:flex;align-items:flex-start;gap:14px;margin-bottom:18px' + (v.mobile ? ';flex-wrap:wrap' : ''))}>
            {v.editAvEl}
            <div style={sx('flex:1;min-width:0')}>
              <Hv tag="input" value={v.edit.name} onChange={v.onEditName} placeholder="Titre (requis)" style={v.editTitleStyle} hover="border-color:#d9cde6;z-index:3" focus="border-color:#6b4fb8;background:#fff;z-index:4" />
              <Hv tag="input" value={v.edit.sub} onChange={v.onEditSub} placeholder="Sous-titre" style="position:relative;z-index:1;width:100%;box-sizing:border-box;margin-top:-1.5px;font-size:13px;color:#6a6070;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:0 0 12px 12px;padding:8px 12px;outline:none;font-family:inherit" hover="border-color:#d9cde6;z-index:3" focus="border-color:#6b4fb8;background:#fff;z-index:4" />
              {v.editTitleErr && <div style={sx('font-size:11px;color:#e0534f;font-weight:600;margin-top:5px')}>Le titre est obligatoire</div>}
            </div>
            {/* Annuler / Enregistrer : à droite du titre / sous-titre de la fiche. */}
            <div style={sx('display:flex;gap:8px;flex:none')}>
              <Hv onClick={v.onEditCancel} style="padding:7px 14px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:12.5px;font-weight:600;cursor:pointer" hover="background:#ece3f1">Annuler</Hv>
              <div onClick={v.onEditSave} style={sx('padding:7px 16px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:12.5px;font-weight:700;cursor:pointer')}>Enregistrer</div>
            </div>
          </div>
          {/* Style d'avatar (switch Lettre/Logo/Icône) + couleur : posé à même le
              panneau (ni fond, ni cadre, ni retrait), simplement titré comme
              « SITES WEB » ou « TAGS INTELLIGENTS ». Le switch reste en haut à
              gauche, la 1ʳᵉ ligne de couleurs à sa suite, les suivantes dessous. */}
          <div style={sx('margin-bottom:18px')}>
            <span style={sx("font:600 10px 'Sora';letter-spacing:.1em;color:#b3a8b9;text-transform:uppercase;display:block;margin-bottom:10px")}>Style et couleur</span>
            <div style={sx('display:flex;flex-wrap:wrap;align-items:center;gap:6px')}>
              <div style={sx('display:flex;gap:3px;background:#f1ecf6;border-radius:9px;padding:3px;flex:none;margin-right:5px')}>
                {v.editModes.map((m) => (<div key={m.label} onClick={m.onClick} style={sx(m.style)}>{m.label}</div>))}
              </div>
              {v.editColors.map((c, i) => (c.sep ? <span key={i} style={sx('width:1px;height:20px;background:#e2d8e6;margin:0 3px;flex:none;border-radius:1px')}></span> : <span key={i} onClick={c.onClick} title={c.title} style={sx(c.style)}>{c.icon}{c.dotStyle ? <span style={sx(c.dotStyle)}></span> : null}</span>))}
            </div>
          </div>
          {v.editShowIcons && <div style={sx('display:flex;flex-wrap:wrap;gap:9px;background:#faf7fd;border:1px solid #f0eaf2;border-radius:14px;padding:13px;margin-bottom:18px')}>
            {v.editIconOptions.map((o) => (
              <div key={o.key} onClick={o.onClick} title={o.label} style={sx(o.style)}>{o.icon}</div>
            ))}
          </div>}
          {/* Choix du logo : posé à même le panneau lui aussi, comme « Style et
              couleur » — seul l'intitulé sépare la rangée de logos du reste. */}
          {v.editShowLogos && <div style={sx('display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin-bottom:18px')}>
            <span style={sx("font:600 10px 'Sora';letter-spacing:.1em;color:#b3a8b9;text-transform:uppercase;width:100%")}>Choisir le logo</span>
            {v.editLogoOptions}
          </div>}
          <div style={sx("font:600 10px 'Sora';letter-spacing:.1em;color:#b3a8b9;text-transform:uppercase;margin:0 0 10px")}>Sites web</div>
          <div style={sx('display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:16px')}>
            {v.editUrlChips.map((u, i) => (<span key={i} draggable={true} onDragStart={u.onDragStart} onDragEnd={u.onDragEnd} onDragOver={u.onOver} onDrop={u.onDrop} title="Glisser pour réordonner" style={sx(u.style)}><svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="1.9"><circle cx="12" cy="12" r="9"></circle><path d="M3 12h18"></path><path d="M12 3c2.4 2.8 2.4 15.2 0 18M12 3c-2.4 2.8-2.4 15.2 0 18"></path></svg>{u.label}<span onClick={u.onRemove} style={sx('cursor:pointer;margin-left:1px;font-size:12px;opacity:.6')}>✕</span></span>))}
            <Hv tag="input" value={v.editUrlDraft} onChange={v.onEditUrlDraft} onKeyDown={v.onEditUrlKey} placeholder="Ajouter une URL + Entrée" style="flex:1;min-width:150px;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:999px;padding:8px 14px;font-size:12.5px;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
          </div>
          <div style={sx("font:600 10px 'Sora';letter-spacing:.1em;color:#b3a8b9;text-transform:uppercase;margin:0 0 10px")}>Tags intelligents</div>
          <div style={sx('display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:18px')}>
            {v.editTagChips.map((tg, i) => (<span key={i} style={sx(tg.style)}>{tg.label}<span onClick={tg.onRemove} style={sx('cursor:pointer;margin-left:1px;font-size:11px;opacity:.65')}>✕</span></span>))}
            <Hv tag="input" value={v.editTagDraft} onChange={v.onEditTagDraft} onKeyDown={v.onEditTagKey} placeholder="Ajouter un tag + Entrée" style="flex:1;min-width:150px;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:999px;padding:8px 14px;font-size:12.5px;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
          </div>
          <div style={sx('height:1.5px;background:#f0eaf2;margin:4px 0 18px')}></div>
          {v.editBlocks.map((b) => (
            <div key={b.id} style={sx('position:relative')}>
              {b.showBefore && <div style={sx('position:absolute;left:0;right:0;top:-6px;height:3px;background:#7c5cff;border-radius:999px;z-index:5')}></div>}
              <div style={sx(b.cardStyle)} onDragOver={b.onDragOver} onDrop={b.onDrop}>
                <div draggable={true} onDragStart={b.onDragStart} onDragEnd={b.onDragEnd} onClick={b.onToggle} style={sx('display:flex;align-items:center;gap:10px;cursor:pointer;user-select:none')}>
                  <span title="Glisser pour réorganiser" style={sx('display:inline-grid;grid-template-columns:2.5px 2.5px;gap:3px;flex:none;cursor:grab')}><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span></span>
                  <span style={sx(b.tileStyle)}>
                    {b.isPwIcon && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><circle cx="7" cy="16" r="3"></circle><path d="M9.3 13.7l8-8M15 5l3 3"></path></svg>}
                    {b.isO365 && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><rect x="3" y="7" width="18" height="13" rx="2"></rect><path d="M8 7V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>}
                    {b.isOtp && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M12 3l7 2.5v5.5c0 4-3 6.8-7 8-4-1.2-7-4-7-8V5.5z"></path></svg>}
                    {b.isWifi && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M4.5 11a11 11 0 0 1 15 0M7.5 14a7 7 0 0 1 9 0"></path><circle cx="12" cy="17.5" r="1" fill="currentColor" stroke="none"></circle></svg>}
                    {b.isCard && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><rect x="3" y="6" width="18" height="12" rx="2"></rect><path d="M3 10h18"></path></svg>}
                    {b.isNotes && <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M6 3h9l4 4v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"></path><path d="M14 3v5h5M9 12h6M9 16h4"></path></svg>}
                    {b.isCat && b.catIcon}
                  </span>
                  <span style={sx("font:700 12px 'Sora';letter-spacing:.03em;color:#3a3340;flex:1;text-transform:uppercase")}>{b.name}</span>
                  <span onClick={b.onRemove} title="Retirer" style={sx('width:24px;height:24px;border-radius:7px;display:grid;place-items:center;color:#c0899f;font-size:12px;cursor:pointer')}>✕</span>
                  <span style={sx(b.chevStyle)}><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2.2"><path d="M6 9l6 6 6-6"></path></svg></span>
                </div>
                {b.bodyOpen && <F>
                  {b.isLogin && <F>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Nom d'utilisateur</div><input value={b.user} onChange={b.onUser} placeholder="identifiant@exemple.fr" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px;display:flex;align-items:center;justify-content:space-between;gap:12px')}><div style={sx('flex:1;min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Mot de passe</div><input type={b.pwType} value={b.password} onChange={b.onPassword} placeholder="••••••••" style={sx("width:100%;box-sizing:border-box;font:600 15px 'IBM Plex Mono';letter-spacing:.04em;color:#3a3340;background:transparent;border:none;outline:none")} /></div><div style={sx('display:flex;align-items:center;gap:12px;font-size:16px;flex:none')}><span onClick={b.onToggleShow} title="Afficher" style={sx('cursor:pointer;color:#9a8fa0;display:inline-flex')}>{v.iEye}</span><span onClick={b.onGen} title="Générer" style={sx('cursor:pointer;color:#6b4fb8;display:inline-flex')}>{v.iRefresh}</span></div></div>
                  </F>}
                  {b.isOtp && <F>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Émetteur</div><input value={b.issuer} onChange={b.onIssuer} placeholder="GitHub, Google…" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Clé secrète (OTP)</div><input value={b.secret} onChange={b.onSecret} placeholder="JBSW Y3DP… ou otpauth://" style={sx("width:100%;box-sizing:border-box;font:600 14px 'IBM Plex Mono';letter-spacing:.04em;color:#3a3340;background:transparent;border:none;outline:none")} /></div>
                    {b.otpLive && <div style={sx('background:#fff;border-radius:12px;padding:10px 14px;display:flex;align-items:center;gap:12px')}>
                      <div style={sx(b.otpRingStyle)}><div style={sx(b.otpHoleStyle)}>{b.otpLiveRemaining}</div></div>
                      <span key={b.otpLiveCode} style={sx("font:600 18px 'IBM Plex Mono';letter-spacing:2.5px;color:#2a2431;animation:scFade .3s ease")}>{b.otpLiveCode}</span>
                      <span style={sx('font-size:11px;color:#b3a8b9;margin-left:auto')}>code actuel</span>
                    </div>}
                  </F>}
                  {b.isWifi && <F>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>SSID</div><input value={b.ssid} onChange={b.onSsid} placeholder="Nom du réseau" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>
                    <div style={sx('display:flex;gap:10px')}><div style={sx('flex:1;background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Mot de passe</div><input value={b.wifiPass} onChange={b.onWifiPass} placeholder="••••••••" style={sx("width:100%;box-sizing:border-box;font:600 14px 'IBM Plex Mono';color:#3a3340;background:transparent;border:none;outline:none")} /></div><div style={sx('width:120px;flex:none;background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Sécurité</div><input value={b.security} onChange={b.onSecurity} placeholder="WPA2" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div></div>
                  </F>}
                  {b.isCard && <F>
                    <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Numéro de carte</div><input value={b.number} onChange={b.onNumber} placeholder="0000 0000 0000 0000" style={sx("width:100%;box-sizing:border-box;font:600 14px 'IBM Plex Mono';color:#3a3340;background:transparent;border:none;outline:none")} /></div>
                    <div style={sx('display:flex;gap:10px')}><div style={sx('flex:1;background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Expiration</div><input value={b.exp} onChange={b.onExp} placeholder="MM/AA" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div><div style={sx('flex:1;background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>CVV</div><input value={b.cvv} onChange={b.onCvv} placeholder="•••" style={sx("width:100%;box-sizing:border-box;font:600 14px 'IBM Plex Mono';color:#3a3340;background:transparent;border:none;outline:none")} /></div></div>
                  </F>}
                  {b.isNotes && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>Contenu</div><textarea value={b.text} onChange={b.onText} placeholder="Note sécurisée…" style={sx('width:100%;box-sizing:border-box;min-height:84px;resize:vertical;font-size:13.5px;line-height:1.5;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')}></textarea></div>}
                  {b.isCat && <div style={sx('display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px')}>
                    {b.catFields.map((f, fi) => (
                      <div key={fi} style={sx(f.cellStyle)}>
                        {f.isTexte && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><input value={f.value} onChange={f.onChange} placeholder="—" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>}
                        {f.isDate && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><input type="date" value={f.value} onChange={f.onChange} style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:13.5px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>}
                        {f.isNombre && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><input type="number" value={f.value} onChange={f.onChange} placeholder="0" style={sx('width:100%;box-sizing:border-box;font-weight:600;font-size:14px;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')} /></div>}
                        {f.isMulti && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><textarea value={f.value} onChange={f.onChange} placeholder="Texte libre…" style={sx('width:100%;box-sizing:border-box;min-height:64px;resize:vertical;font-size:13.5px;line-height:1.5;color:#3a3340;background:transparent;border:none;outline:none;font-family:inherit')}></textarea></div>}
                        {f.isMdp && <div style={sx('background:#fff;border-radius:12px;padding:12px 14px;display:flex;align-items:center;gap:12px')}><div style={sx('flex:1;min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><input type={f.pwType} value={f.value} onChange={f.onChange} placeholder="••••••••" style={sx("width:100%;box-sizing:border-box;font:600 15px 'IBM Plex Mono';letter-spacing:.04em;color:#3a3340;background:transparent;border:none;outline:none")} /></div><span onClick={f.onToggleShow} title="Afficher" style={sx(f.eyeStyle)}>{v.iEye}</span></div>}
                        {f.isListe && <F>
                          <div onClick={f.onOpenMenu} style={sx('background:#fff;border-radius:12px;padding:12px 14px;display:flex;align-items:center;gap:10px;cursor:pointer' + (f.menuOpen ? ';position:relative;z-index:39' : ''))}><div style={sx('flex:1;min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><div style={sx('font-weight:600;font-size:14px;color:#3a3340')}>{f.value}</div></div><span style={sx(f.chevStyle)}>{v.iChev}</span></div>
                          {f.menuOpen && <F>
                            <div onClick={f.onCloseMenu} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:38')}></div>
                            <div style={sx('position:absolute;top:calc(100% + 6px);left:0;right:0;background:#fff;border-radius:13px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:6px;z-index:41;transform-origin:top;animation:scDrop .15s ease')}>
                              {f.options.map((o) => (<div key={o.label} style={sx(o.style)} onClick={o.onClick}><span>{o.label}</span>{o.selected && <span style={sx('color:#6b4fb8;font-weight:800')}>✓</span>}</div>))}
                            </div>
                          </F>}
                        </F>}
                        {f.isToggle && <div onClick={f.onToggle} style={sx('background:#fff;border-radius:12px;padding:12px 14px;display:flex;align-items:center;gap:12px;cursor:pointer')}><div style={sx('flex:1;min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{f.label}</div><div style={sx('font-weight:600;font-size:14px;color:#3a3340')}>{f.toggleLabel}</div></div><div style={sx(f.trackStyle)}><div style={sx(f.knobStyle)}></div></div></div>}
                      </div>
                    ))}
                  </div>}
                </F>}
              </div>
              {b.showAfter && <div style={sx('position:absolute;left:0;right:0;bottom:-6px;height:3px;background:#7c5cff;border-radius:999px;z-index:5')}></div>}
            </div>
          ))}
          <div style={sx('position:relative;margin-bottom:2px')} onDragOver={v.onEndOver} onDrop={v.onEndDrop}>
            {v.showEnd && <div style={sx('position:absolute;left:0;right:0;top:-6px;height:3px;background:#7c5cff;border-radius:999px;z-index:5')}></div>}
            <div onClick={v.onEditAddToggle} style={sx('display:flex;align-items:center;justify-content:center;gap:8px;border:1.5px dashed #d9cde6;border-radius:13px;padding:12px;color:#6b4fb8;font-size:13px;font-weight:600;cursor:pointer')}>＋ Ajouter un élément</div>
          </div>
          {/* Les champs de type personnalisé sont désormais édités dans leur
              bloc (type 'cat:…'), déplaçable comme les autres. */}
          {v.editAddOpen && <div onClick={v.onEditAddClose} style={sx(v.editAddOverlayStyle)}>
            <div onClick={v.onEditMenuStop} style={sx(v.editAddCardStyle)}>
              <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:8px 10px 9px")}>CHOISIR UN TYPE</div>
              {v.editAddOptions.map((o) => (
                <Hv key={o.label} onClick={o.onClick} style="display:flex;align-items:center;gap:11px;padding:10px;border-radius:10px;cursor:pointer" hover="background:#f7f3fb">
                  <span style={sx(o.tileStyle)}>
                    {o.isPw && <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.9"><circle cx="7" cy="16" r="3"></circle><path d="M9.3 13.7l8-8M15 5l3 3"></path></svg>}
                    {o.isOtp && <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M12 3l7 2.5v5.5c0 4-3 6.8-7 8-4-1.2-7-4-7-8V5.5z"></path></svg>}
                    {o.isWifi && <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M4.5 11a11 11 0 0 1 15 0M7.5 14a7 7 0 0 1 9 0"></path><circle cx="12" cy="17.5" r="1" fill="currentColor" stroke="none"></circle></svg>}
                    {o.isCard && <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.9"><rect x="3" y="6" width="18" height="12" rx="2"></rect><path d="M3 10h18"></path></svg>}
                    {o.isNotes && <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" strokeWidth="1.9"><path d="M6 3h9l4 4v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"></path><path d="M14 3v5h5M9 12h6M9 16h4"></path></svg>}
                  </span>
                  <div style={sx('min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{o.label}</div><div style={sx('font-size:10.5px;color:#b3a8b9')}>{o.desc}</div></div>
                </Hv>
              ))}
              {v.editAddCustom.length > 0 && <F>
                <div style={sx('height:1px;background:#f0eaf2;margin:6px 8px')}></div>
                <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:8px 10px 9px")}>CHOISIR UN TYPE PERSONNALISÉ</div>
                {v.editAddCustom.map((o) => (
                  <Hv key={o.label} onClick={o.onClick} style="display:flex;align-items:center;gap:11px;padding:10px;border-radius:10px;cursor:pointer" hover="background:#f7f3fb">
                    <span style={sx(o.tileStyle)}>{o.icon}</span>
                    <div style={sx('min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{o.label}</div><div style={sx('font-size:10.5px;color:#b3a8b9')}>{o.desc}</div></div>
                  </Hv>
                ))}
              </F>}
            </div>
          </div>}
        </div>}
        {v.notEditMode && <div style={sx(v.detailAnim)}>
        <div style={sx('display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:18px')}>
          <div style={sx('display:flex;align-items:center;gap:14px')}>{v.sel.av}<div><div style={sx('font-weight:700;font-size:21px;display:flex;align-items:center;gap:9px')}>{v.sel.name}{v.sel.verified && <span title="Domaine vérifié — anti-hameçonnage" style={sx('display:inline-flex;align-items:center;color:#2e8f72;font-size:20px;line-height:0')}>{v.iShieldCheck}</span>}</div><div style={sx('font-size:12px;color:#b3a8b9')}>{v.sel.sub}{v.sel.partageDe ? <span style={sx('color:#bb4f78;font-weight:600')}> · partagé par {v.sel.partageDe} ({v.sel.partagePermLabel})</span> : null}</div></div></div>
        </div>

        {/* flex-wrap en mobile : sans lui, « Modifier » et le menu ⋮ sont
            poussés HORS de l'écran par les onglets — donc inatteignables. */}
        <div style={sx('display:flex;align-items:center;gap:6px;margin-bottom:18px;border-bottom:1.5px solid #f0eaf2' + (v.mobile ? ';flex-wrap:wrap;row-gap:2px' : ''))}>
          <div style={sx(v.tabCoffre.style)} onClick={v.tabCoffre.onClick}>Détail</div>
          <div style={sx(v.tabActivite.style)} onClick={v.tabActivite.onClick}>Activité</div>
          {v.tabPartage.visible && <div style={sx(v.tabPartage.style)} onClick={v.tabPartage.onClick}>Partager{v.sel.shared ? <span style={sx('margin-left:6px;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:#bb4f78;color:#fff;font-size:10.5px;font-weight:700;display:inline-flex;align-items:center;justify-content:center')}>{v.sel.shareCount}</span> : null}</div>}
          <div style={sx('margin-left:auto;display:flex;align-items:center;gap:8px;padding-bottom:6px')}>
            {!v.sel.lectureSeule && <div onClick={v.onEnterEdit} style={sx('display:flex;align-items:center;gap:7px;padding:7px 14px;background:#f3eefb;color:#6b4fb8;border-radius:10px;font-size:12.5px;font-weight:600;cursor:pointer')}>{v.iEdit} Modifier</div>}
            {v.sel.lectureSeule && <span title="Cette fiche vous est partagée en lecture seule" style={sx('display:flex;align-items:center;gap:6px;padding:7px 13px;background:#faf7fd;color:#8a7f96;border-radius:10px;font-size:12px;font-weight:600')}>{v.iEye} Lecture seule</span>}
            <div style={sx('position:relative')}>
              <div onClick={v.onDetailToggle} title="Plus d'actions" style={sx('width:32px;height:32px;border-radius:10px;background:#f3ecf3;display:grid;place-items:center;color:#8a7f90;cursor:pointer;font-size:16px')}>{v.iDots}</div>
              {v.detailMenuOpen && <F>
                <div onClick={v.onDetailClose} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:44')}></div>
                <div style={sx('position:absolute;top:calc(100% + 8px);right:0;width:228px;background:#fff;border-radius:14px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:7px;z-index:45;text-align:left;transform-origin:top right;animation:scDrop .15s ease')}>
                  {/* « Modifier popup » ouvre CPEditeur (editeur.jsx), dont la
                      mise en page est figée à deux colonnes (216 px de barre
                      latérale non rétractable) : à 375 px la colonne de
                      contenu tombe sous 90 px. L'entrée est donc retirée en
                      mobile — « Modifier » édite la même fiche dans le
                      panneau, lui responsive. */}
                  {!v.sel.lectureSeule && !v.mobile && <Hv onClick={v.onEditEntry} style="display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:9px;cursor:pointer" hover="background:#f3eefb"><span style={sx('color:#6b4fb8;font-size:16px;display:inline-flex')}>{v.iEdit}</span><span style={sx('font-size:13px;font-weight:600;color:#3a3340')}>Modifier popup</span></Hv>}
                  <Hv onClick={v.onToggleFav} style="display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:9px;cursor:pointer" hover="background:#fbe2ea"><span style={sx('color:#bb4f78;font-size:16px;display:inline-flex')}>{v.iStar}</span><span style={sx('font-size:13px;font-weight:600;color:#3a3340')}>{v.favLabel}</span></Hv>
                  <Hv onClick={v.onDeleteItem} style="display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:9px;cursor:pointer" hover="background:#fdf1f1"><span style={sx('color:#c0392b;font-size:16px;display:inline-flex')}>{v.iTrash}</span><span style={sx('font-size:13px;font-weight:600;color:#c0392b')}>Supprimer</span></Hv>
                </div>
              </F>}
            </div>
          </div>
        </div>

        <div style={sx(v.tabBodyAnim)}>
        {/* ---- Onglet Coffre ---- */}
        {v.showCoffre && <F>
          {/* UNE section par bloc de la fiche, dans l'ordre défini en
              édition — plusieurs blocs d'un même type = sections numérotées. */}
          {v.sel.sections.map((sec, si) => (
            <F key={si}>
              {sec.otp && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.otp.title}</div>
                <div style={sx('background:linear-gradient(135deg,#efe7fc,#fbeef4);border-radius:18px;padding:20px 22px;margin-bottom:14px;display:flex;align-items:center;justify-content:space-between')}><div><div style={sx('font-size:11px;color:#9b8fb5;font-weight:600;margin-bottom:7px;display:flex;align-items:center;gap:6px')}>{v.iShield} {sec.otp.label}</div><div key={sec.otp.code} style={sx(sec.otp.codeStyle)}>{sec.otp.code}</div></div><div style={sx('display:flex;align-items:center;gap:12px')}><div title="Nouveau code toutes les 30 s" style={sx(sec.otp.ringStyle)}><div style={sx(sec.otp.holeStyle)}>{sec.otp.remaining}</div></div><div onClick={sec.otp.onCopy} style={sx('display:flex;align-items:center;gap:7px;padding:10px 16px;background:#6b4fb8;color:#fff;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>{v.iCopy} Copier</div></div></div>
              </F>}

              {sec.login && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.login.title}</div>
                <div style={sx(sec.login.inline ? 'display:flex;gap:10px;margin-bottom:12px;align-items:stretch' : '')}>
                <div style={sx('flex:1;min-width:0;background:#faf7fd;border-radius:14px;padding:14px 16px;display:flex;align-items:center;justify-content:space-between;' + (sec.login.inline ? '' : 'margin-bottom:10px'))}><div style={sx('min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Nom d'utilisateur</div><div style={sx('font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{sec.login.user}</div></div><span onClick={sec.login.onCopyUser} style={sx('color:#9a8fa0;font-size:17px;cursor:pointer;margin-left:12px')}>{v.iCopy}</span></div>
                <div style={sx('flex:1;min-width:0;background:#faf7fd;border-radius:14px;padding:14px 16px;display:flex;align-items:center;justify-content:space-between;' + (sec.login.inline ? '' : 'margin-bottom:12px'))}><div style={sx('min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Mot de passe</div><div style={sx("font:600 16px 'Space Grotesk';letter-spacing:.16em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis")}>{sec.login.pwEl}</div></div><div style={sx('display:flex;align-items:center;gap:10px;font-size:17px;flex:none')}><span title={sec.login.forceLabel} style={sx(sec.login.forceStyle)}>{sec.login.forceFaible ? v.iRadar : v.iShieldCheck}</span><span style={sx('width:1px;height:18px;background:#e9e0ee')}></span><span onClick={sec.login.onRevealPw} title="Afficher 30 s" style={sx(sec.login.eyeStyle)}>{v.iEye}</span><span onClick={sec.login.onCopyPw} title="Copier le mot de passe" style={sx('cursor:pointer;color:#9a8fa0')}>{v.iCopy}</span></div></div>
                </div>
                {/* Le renouvellement automatique n'est pas implémenté : la tuile
                    affichait un interrupteur figé sur ON et une échéance
                    inventée (« prochaine dans 28 jours »). Elle annonce
                    désormais la fonction sans prétendre l'assurer. */}
                {sec.login.rotation && <div style={sx('display:flex;align-items:center;gap:12px;background:#f4f0fb;border-radius:14px;padding:12px 16px;margin-bottom:12px;opacity:.55')}><div style={sx('width:32px;height:32px;border-radius:9px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:16px;flex:none')}>{v.iRefresh}</div><div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px')}>Rotation automatique</div><div style={sx('font-size:11px;color:#a99fb0')}>Renouvellement périodique du mot de passe</div></div><span style={sx('font-size:10px;font-weight:700;color:#8a7f90;background:#eee9ef;padding:3px 9px;border-radius:999px;flex:none')}>Coming soon</span></div>}
              </F>}

              {sec.wifi && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.wifi.title}</div>
                {sec.wifi.qr && <div style={sx('display:flex;gap:18px;align-items:center;background:linear-gradient(135deg,#efe7fc,#fbeef4);border-radius:18px;padding:20px;margin-bottom:12px')}>
                  {sec.wifi.qrEl}
                  <div><div style={sx('font-weight:700;font-size:16px;margin-bottom:6px')}>Connexion automatique</div><div style={sx('font-size:13px;color:#7a7184;line-height:1.5')}>Scannez ce QR code avec l'appareil photo d'un iPhone ou d'un Android pour rejoindre <b style={sx('color:#3a3340')}>{sec.wifi.ssid}</b> sans saisir le mot de passe.</div><div style={sx("margin-top:12px;font:500 11px 'IBM Plex Mono';color:#9a8fa0;background:#fff;border-radius:8px;padding:8px 10px;word-break:break-all")}>{sec.wifi.payload}</div></div>
                </div>}
                <div style={sx('display:flex;gap:12px;margin-bottom:12px')}>
                  <div style={sx('flex:1;background:#faf7fd;border-radius:14px;padding:14px 16px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>SSID</div><div style={sx('font-weight:600;font-size:14px')}>{sec.wifi.ssid}</div></div>
                  <div style={sx('flex:1;background:#faf7fd;border-radius:14px;padding:14px 16px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Sécurité</div><div style={sx('font-weight:600;font-size:14px')}>{sec.wifi.security}</div></div>
                </div>
                <div style={sx('background:#faf7fd;border-radius:14px;padding:14px 16px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px')}><div><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Mot de passe</div><div style={sx("font:600 16px 'Space Grotesk';letter-spacing:.16em")}>{sec.wifi.passEl}</div></div><div style={sx('display:flex;align-items:center;gap:10px;font-size:17px')}><span onClick={sec.wifi.onReveal} title="Afficher le mot de passe" style={sx(sec.wifi.eyeStyle)}>{v.iEye}</span><span onClick={sec.wifi.onCopy} title="Copier la clé Wi-Fi" style={sx('cursor:pointer;color:#9a8fa0')}>{v.iCopy}</span></div></div>
              </F>}

              {sec.card && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.card.title}</div>
                <div style={sx('background:#faf7fd;border-radius:14px;padding:14px 16px;display:flex;align-items:center;justify-content:space-between;margin-bottom:10px')}><div style={sx('min-width:0')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Numéro de carte</div><div style={sx("font:600 15px 'IBM Plex Mono';letter-spacing:.08em")}>{sec.card.number}</div></div><div style={sx('display:flex;align-items:center;gap:10px;font-size:17px;margin-left:12px;flex:none')}><span onClick={sec.card.onRevealNumber} title="Afficher le numéro" style={sx(sec.card.numEyeStyle)}>{v.iEye}</span><span onClick={sec.card.onCopy} title="Copier le numéro" style={sx('cursor:pointer;color:#9a8fa0')}>{v.iCopy}</span></div></div>
                <div style={sx('display:flex;gap:12px;margin-bottom:12px')}>
                  <div style={sx('flex:1;background:#faf7fd;border-radius:14px;padding:14px 16px')}><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>Expiration</div><div style={sx('font-weight:600;font-size:14px')}>{sec.card.exp}</div></div>
                  <div style={sx('flex:1;background:#faf7fd;border-radius:14px;padding:14px 16px;display:flex;align-items:center;justify-content:space-between')}><div><div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:6px')}>CVV</div><div style={sx("font:600 14px 'IBM Plex Mono';letter-spacing:.1em")}>{sec.card.cvv}</div></div><span onClick={sec.card.onReveal} title="Afficher le CVV" style={sx(sec.card.eyeStyle + ';font-size:16px;flex:none')}>{v.iEye}</span></div>
                </div>
              </F>}

              {sec.note && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.note.title}</div>
                <div style={sx('background:#faf7fd;border-radius:14px;padding:14px 16px;margin-bottom:12px;font-size:13.5px;line-height:1.6;color:#3a3340;white-space:pre-wrap')}>{sec.note.text}</div>
              </F>}

              {/* Champs des types personnalisés (popup « Personnaliser le type ») */}
              {sec.cat && <F>
                <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:6px 0 10px")}>{sec.cat.title}</div>
                <div style={sx('display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px;margin-bottom:12px')}>
                  {sec.cat.fields.map((fld, fi) => (
                    <div key={fi} style={sx('background:#faf7fd;border-radius:14px;padding:13px 15px;display:flex;align-items:center;gap:10px;' + fld.cellStyle)}>
                      <div style={sx('flex:1;min-width:0')}>
                        <div style={sx('font-size:11px;color:#b3a8b9;margin-bottom:5px')}>{fld.label}</div>
                        {fld.isMdp && <div style={sx("font:600 15px 'Space Grotesk';letter-spacing:.14em")}>{fld.value}</div>}
                        {(fld.isTexte || fld.isListe || fld.isToggle || fld.isDate || fld.isNombre) && <div style={sx('font-weight:600;font-size:14px;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{fld.value}</div>}
                        {fld.isLien && <div style={sx('font-weight:600;font-size:14px;color:#6b4fb8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{fld.value}</div>}
                        {fld.isMulti && <div style={sx('font-weight:600;font-size:13.5px;line-height:1.5;color:#3a3340;white-space:pre-wrap')}>{fld.value}</div>}
                      </div>
                      {fld.isMdp && fld.hasVal && <span onClick={fld.onReveal} title="Afficher / masquer" style={sx(fld.eyeStyle)}>{v.iEye}</span>}
                      {fld.isMdp && fld.hasVal && <span onClick={fld.onCopyVal} title="Copier" style={sx('color:#9a8fa0;font-size:16px;cursor:pointer;flex:none')}>{v.iCopy}</span>}
                      {fld.isToggle && <div style={sx(fld.trackStyle)}><div style={sx(fld.knobStyle)}></div></div>}
                    </div>
                  ))}
                </div>
              </F>}
            </F>
          ))}
          <div style={sx('display:flex;flex-wrap:wrap;gap:7px;margin-top:4px')}><span style={sx("font:600 10px 'Sora';letter-spacing:.1em;color:#b3a8b9;text-transform:uppercase;width:100%;margin-bottom:2px")}>Tags intelligents</span>{v.sel.tags.map((tag, i) => (<span key={i} style={sx(tag.style)}>{tag.label}</span>))}</div>
        </F>}

        {/* ---- Onglet Activité : historique fusionné (modifications + accès),
                toutes les entrées avec le même rendu (icône + libellé en gras). ---- */}
        {v.showActivite && <F>
          <div style={sx('display:flex;flex-direction:column')}>
            {v.activite.map((h, i) => (
              <div key={i} style={sx('display:flex;align-items:center;gap:11px;padding:10px 4px;border-bottom:1px solid #f4eff6')}>
                <span style={sx('width:26px;height:26px;border-radius:50%;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;flex:none;font-size:13px')}>{h.iconEl}</span>
                <span style={sx('flex:1;min-width:0')}>
                  <span style={sx('display:block;font-size:13px;font-weight:600;color:#3a3340')}>{h.label}</span>
                  {h.detail && <span style={sx('display:block;margin-top:3px')}>{h.detail.split('\n').map((ln, j) => { const ci = ln.indexOf(' : '); return (<span key={j} style={sx('display:block;font-size:11px;line-height:1.5;color:#8a7f96;margin-top:1px;word-break:break-word')}>{ci > 0 ? <F><span style={sx('color:#6a6070;font-weight:600')}>{ln.slice(0, ci)}</span>{ln.slice(ci)}</F> : ln}</span>); })}</span>}
                </span>
                <span style={sx('font-size:10.5px;color:#b3a8b9;flex:none')}>{h.time}</span>
              </div>
            ))}
            {v.activite.length === 0 && <div style={sx('font-size:12.5px;color:#a99fb0;padding:14px 4px')}>Aucune activité enregistrée pour cette fiche.</div>}
          </div>
          <div style={sx('margin-top:14px;display:flex;align-items:center;gap:11px;background:#f4faf6;border-radius:14px;padding:13px 16px')}><div style={sx('width:32px;height:32px;border-radius:9px;background:#def3ec;color:#2e8f72;display:grid;place-items:center;font-size:16px;flex:none')}>{v.iRefresh}</div><div style={sx('flex:1')}><div style={sx('font-weight:600;font-size:13px')}>Versions restaurables</div><div style={sx('font-size:11px;color:#a99fb0')}>Revenez à n'importe quelle version antérieure du mot de passe.</div></div><span onClick={v.versions.onOpen} style={sx('font-size:12px;font-weight:600;color:#2e8f72;cursor:pointer')}>Restaurer</span></div>
        </F>}
        {/* ---- Onglet Partager (bout en bout) ---- */}
        {v.showPartage && <F>
          {v.share.dejaRecu ? (
            <div style={sx('background:#fdf4e3;color:#8a6d3b;border-radius:12px;padding:13px 15px;font-size:12.5px;font-weight:600')}>Cette entrée vous a été partagée : seul son propriétaire peut la partager.</div>
          ) : (
            <div style={sx('background:#faf7fd;border:1px solid #f0eaf2;border-radius:14px;padding:16px')}>
              <div style={sx("font:700 10.5px 'Sora';letter-spacing:.06em;text-transform:uppercase;color:#a99fb0;margin:0 2px 6px")}>Partager avec un membre</div>
              <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:12px;line-height:1.5')}>La clé de l'entrée est scellée pour le destinataire dans votre navigateur — le serveur ne peut pas la lire.</div>
              <div style={sx('display:flex;gap:8px;flex-wrap:wrap')}>
                <input type="email" value={v.share.email} onChange={v.share.onEmail} placeholder="collegue@exemple.fr" style={sx('flex:1;min-width:200px;box-sizing:border-box;background:#fff;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font-size:14px;color:#3a3340;font-family:inherit;outline:none')} />
                <div onClick={v.share.onSend} style={sx(`padding:11px 20px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:11px;font-size:13px;font-weight:700;cursor:pointer;flex:none;${v.share.occupe ? 'opacity:.6;' : ''}`)}>{v.share.occupe ? 'Scellement…' : 'Partager'}</div>
              </div>
              <div style={sx('display:flex;gap:4px;background:#f1ecf6;border-radius:11px;padding:4px;margin-top:10px;max-width:340px')}>
                <div onClick={() => v.share.onPermission('lecture')} style={sx(`flex:1;text-align:center;padding:8px 6px;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;${v.share.permission === 'lecture' ? 'background:#6b4fb8;color:#fff;' : 'color:#7a7184;'}`)}>Lecture seule</div>
                <div onClick={() => v.share.onPermission('lecture_ecriture')} style={sx(`flex:1;text-align:center;padding:8px 6px;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;${v.share.permission === 'lecture_ecriture' ? 'background:#6b4fb8;color:#fff;' : 'color:#7a7184;'}`)}>Lecture + écriture</div>
              </div>
              {v.share.err && <div style={sx('margin-top:12px;background:#fbe4e4;color:#c0392b;border-radius:10px;padding:9px 12px;font-size:12px;font-weight:600')}>{v.share.err}</div>}
              {v.share.envoye && <div style={sx('margin-top:12px;background:#def3ec;color:#2e8f72;border-radius:10px;padding:9px 12px;font-size:12px;font-weight:600')}>Partage envoyé — il apparaîtra dans le coffre du destinataire à sa prochaine connexion.</div>}
            </div>
          )}
          <div style={sx("font:700 10.5px 'Sora';letter-spacing:.06em;text-transform:uppercase;color:#a99fb0;margin:20px 2px 9px")}>Partages en cours</div>
          {v.share.liste.length === 0
            ? <div style={sx('font-size:12.5px;color:#a99fb0;padding:6px 2px')}>Cette entrée n'est partagée avec personne pour l'instant.</div>
            : v.share.liste.map((p, i) => (
              <div key={i} style={sx('display:flex;align-items:center;gap:10px;background:#faf7fd;border-radius:11px;padding:11px 14px;margin-bottom:7px' + (p.menuOpen ? ';position:relative;z-index:39' : ''))}>
                <span style={sx('flex:1;min-width:0;font-size:13px;font-weight:600;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{p.destinataire}</span>
                <span style={sx('font-size:11px;color:#8a7f96;flex:none')}>{p.permission}</span>
                <span style={sx(`font-size:10px;font-weight:700;padding:3px 8px;border-radius:999px;flex:none;${p.statut === 'accepté' ? 'background:#def3ec;color:#2e8f72;' : 'background:#fdeede;color:#b87e2e;'}`)}>{p.statut}</span>
                {!v.share.dejaRecu && (p.id
                  ? <span style={sx('position:relative;flex:none')}>
                      <Hv onClick={p.onMenuToggle} title="Gérer ce partage" style={`width:28px;height:28px;border-radius:9px;display:grid;place-items:center;color:#8a7f90;cursor:pointer;font-size:15px;${v.share.revoking === p.id ? 'opacity:.6;' : ''}`} hover="background:#ece3f1">{v.iDots}</Hv>
                      {p.menuOpen && <F>
                        <div onClick={p.onMenuClose} style={sx('position:fixed;inset:0;z-index:38')}></div>
                        <div style={sx('position:absolute;top:calc(100% + 6px);right:0;width:214px;background:#fff;border-radius:13px;border:1px solid #e4dce8;padding:6px;z-index:41;text-align:left;transform-origin:top right;animation:scDrop .15s ease')}>
                          <div style={sx("font:700 9.5px 'Sora';letter-spacing:.06em;color:#b3a8b9;padding:6px 9px 5px")}>DROIT ACCORDÉ</div>
                          <Hv onClick={p.onLecture} style="display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:9px;cursor:pointer" hover="background:#f3eefb">
                            <span style={sx('width:16px;flex:none;color:#6b4fb8;font-size:12px')}>{p.ecriture ? '' : '✓'}</span>
                            <span style={sx('font-size:12.5px;font-weight:600;color:#3a3340')}>Lecture seule</span>
                          </Hv>
                          <Hv onClick={p.onEcriture} style="display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:9px;cursor:pointer" hover="background:#f3eefb">
                            <span style={sx('width:16px;flex:none;color:#6b4fb8;font-size:12px')}>{p.ecriture ? '✓' : ''}</span>
                            <span style={sx('font-size:12.5px;font-weight:600;color:#3a3340')}>Lecture + écriture</span>
                          </Hv>
                          <div style={sx('height:1px;background:#f0eaf2;margin:5px 8px')}></div>
                          <Hv onClick={() => v.share.onRevoke(p.id)} style="display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:9px;cursor:pointer" hover="background:#fdf1f1">
                            <span style={sx('width:16px;flex:none;color:#c0392b;font-size:13px;display:inline-flex')}>{v.iTrash}</span>
                            <span style={sx('font-size:12.5px;font-weight:600;color:#c0392b')}>Révoquer le partage</span>
                          </Hv>
                        </div>
                      </F>}
                    </span>
                  : <span title="Rechargez la page pour gérer ce partage récent" style={sx('font-size:10.5px;color:#c3b8cc;flex:none')}>—</span>)}
              </div>
            ))}
        </F>}
        </div>
        </div>}
      </div>}

      {/* ===================== VUE SANTÉ ===================== */}
      {v.isHealth && <div style={sx('padding:' + (v.mobile ? '14px 14px 18px' : '24px 26px'))}>
        <div style={sx('font-weight:700;font-size:21px;margin-bottom:4px')}>Santé du coffre</div>
        <div style={sx('font-size:12.5px;color:#b3a8b9;margin-bottom:20px')}>{v.sante.sousTitre}</div>
        <div style={sx('display:flex;gap:20px;align-items:center;background:linear-gradient(135deg,#f4faf6,#efe7fc);border-radius:18px;padding:22px;margin-bottom:16px')}>
          <div style={sx(v.sante.scoreStyle)}><div style={sx('width:78px;height:78px;border-radius:50%;background:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center')}><span style={sx(v.sante.scoreTxtStyle)}>{v.sante.score}</span><span style={sx('font-size:9px;color:#9bbfa9;letter-spacing:.08em')}>/ 100</span></div></div>
          <div style={sx('flex:1')}><div style={sx('font-weight:700;font-size:16px;margin-bottom:6px')}>{v.sante.niveau}</div><div style={sx('font-size:12.5px;color:#7a7184;line-height:1.55')}>{v.sante.resume}</div></div>
        </div>
        <div style={sx('display:flex;gap:12px;margin-bottom:18px')}>
          <div style={sx('flex:1;background:#fdf4e4;border-radius:14px;padding:15px 17px')}><div style={sx("font:700 24px 'Space Grotesk';color:#b87e2e")}>{v.sante.nbFaibles}</div><div style={sx('font-size:11.5px;color:#9a8f7a')}>mots de passe faibles</div></div>
          <div style={sx('flex:1;background:#fbe2e8;border-radius:14px;padding:15px 17px')}><div style={sx("font:700 24px 'Space Grotesk';color:#bb4f78")}>{v.sante.nbReutil}</div><div style={sx('font-size:11.5px;color:#a98594')}>réutilisés</div></div>
          <div style={sx('flex:1;background:#f4faf5;border-radius:14px;padding:15px 17px')}><div style={sx("font:700 24px 'Space Grotesk';color:#2e8f72")}>{v.sante.nb2fa}</div><div style={sx('font-size:11.5px;color:#84a896')}>protégés en 2FA</div></div>
        </div>
        {v.sante.rien && <div style={sx('background:#f4faf6;border:1px solid #cfe9db;border-radius:12px;padding:13px 15px;font-size:12.5px;color:#2e8f72;font-weight:600;margin-bottom:18px')}>Aucun mot de passe faible ni réutilisé dans ce coffre.</div>}
        {v.sante.faibles.length > 0 && <F>
          <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:0 0 9px")}>Mots de passe à renforcer</div>
          <div style={sx('display:flex;flex-direction:column;gap:8px;margin-bottom:18px')}>
            {v.sante.faibles.map((r) => (
              <div key={r.key} style={sx(r.style)}>
                <div style={sx(r.avStyle)}>{r.ini}</div>
                <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.nom}</div><div style={sx(r.descStyle)}>{r.sousTitre}</div></div>
                <span onClick={r.onFix} style={sx('font-size:11px;font-weight:600;color:#6b4fb8;cursor:pointer;flex:none')}>Corriger</span>
              </div>
            ))}
          </div>
        </F>}
        {v.sante.reutilises.length > 0 && <F>
          <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase;margin:0 0 9px")}>Mots de passe réutilisés</div>
          <div style={sx('display:flex;flex-direction:column;gap:8px;margin-bottom:18px')}>
            {v.sante.reutilises.map((r) => (
              <div key={r.key} style={sx(r.style)}>
                <div style={sx(r.avStyle)}>{r.ini}</div>
                <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.nom}</div><div style={sx(r.descStyle)}>{r.sousTitre}</div></div>
                <span onClick={r.onFix} style={sx('font-size:11px;font-weight:600;color:#6b4fb8;cursor:pointer;flex:none')}>Corriger</span>
              </div>
            ))}
          </div>
        </F>}
        <div style={sx('display:flex;align-items:center;gap:10px;margin-bottom:10px')}>
          <div style={sx('width:30px;height:30px;border-radius:9px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;font-size:16px')}>{v.iRadar}</div>
          <div style={sx('font-weight:700;font-size:14px')}>Surveillance des fuites</div>
          {v.sante.fuEtat === 'ok' && <span style={sx('margin-left:auto;font-size:11px;font-weight:600;color:' + (v.sante.fuNb === '0' ? '#2e8f72' : '#c0716a'))}>{v.sante.fuNb === '0' ? 'aucun exposé' : v.sante.fuNb + ' exposé(s)'}</span>}
        </div>
        <div style={sx('background:#faf7fd;border-radius:12px;padding:13px 15px;margin-bottom:8px')}>
          <div style={sx('font-size:12px;color:#7a7184;line-height:1.55')}>Vérifie vos mots de passe auprès de <b style={sx('color:#3a3340')}>Have I Been Pwned</b>. L'empreinte est calculée sur votre appareil et <b style={sx('color:#3a3340')}>seuls ses 5 premiers caractères</b> sont envoyés (k-anonymity) : ni le mot de passe, ni son empreinte complète, ni le nom de la fiche ne sortent du navigateur.</div>
          <div style={sx('display:flex;align-items:center;gap:10px;margin-top:11px')}>
            <div onClick={v.sante.onScan} style={sx(`display:inline-flex;align-items:center;gap:7px;padding:8px 14px;background:#efe7fc;color:#6b4fb8;border-radius:10px;font-size:12px;font-weight:600;cursor:pointer;${v.sante.fuEtat === 'scan' ? 'opacity:.6;' : ''}`)}>{v.sante.fuEtat === 'scan' ? 'Vérification…' : (v.sante.fuEtat === 'idle' ? 'Vérifier maintenant' : 'Relancer la vérification')}</div>
            {v.sante.fuQuand && <span style={sx('font-size:11px;color:#a99fb0')}>Dernière vérification : {v.sante.fuQuand}</span>}
          </div>
          {v.sante.fuErr && <div style={sx('margin-top:10px;background:#fbe4e4;color:#c0392b;border-radius:10px;padding:8px 11px;font-size:11.5px;font-weight:600')}>{v.sante.fuErr}</div>}
        </div>
        <div style={sx('display:flex;flex-direction:column;gap:8px')}>
          {v.sante.fuRows.map((r) => (
            <div key={r.key} style={sx(r.style)}>
              <div style={sx(r.avStyle)}>{r.ini}</div>
              <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.nom}</div><div style={sx(r.descStyle)}>{r.sousTitre}</div></div>
              <span onClick={r.onFix} style={sx('font-size:11px;font-weight:600;color:#6b4fb8;cursor:pointer;flex:none')}>Corriger</span>
            </div>
          ))}
        </div>
        <div style={sx('margin-top:18px;display:flex;align-items:center;gap:13px;background:#f4f0fb;border-radius:14px;padding:15px 18px')}><div style={sx('width:40px;height:40px;border-radius:11px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:19px;flex:none')}>{v.iLock}</div><div><div style={sx('font-weight:700;font-size:14px')}>Chiffré de bout en bout</div><div style={sx("font:500 12px 'IBM Plex Mono';color:#a99fb0")}>AES-256-GCM · Argon2id · Zero-knowledge</div></div><span style={sx('margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:#2e8f72;background:#def3ec;border-radius:999px;padding:5px 11px')}>{v.iShieldCheck} Actif</span></div>
      </div>}

      {/* ===================== VUE SÉCURITÉ & OUTILS ===================== */}
      {v.isTools && <div style={sx('padding:' + (v.mobile ? '14px 14px 18px' : '24px 26px') + ';display:flex;flex-direction:column;align-items:center')}>
        <div style={sx('width:100%;max-width:1040px')}>
        <div style={sx('font-weight:700;font-size:21px;margin-bottom:4px')}>Sécurité & outils</div>
        <div style={sx('font-size:12.5px;color:#b3a8b9;margin-bottom:20px')}>Réglages de protection et fonctions avancées du coffre</div>
        <div style={sx('display:flex;flex-direction:column;gap:22px')}>
          {v.toolSections.map((sec) => (
            <div key={sec.title}>
              <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 10px")}>{sec.title}</div>
              <div style={sx('display:grid;grid-template-columns:' + (v.mobile ? '1fr' : '1fr 1fr') + ';gap:10px;align-items:start')}>
                {sec.tools.map((t) => (
                  <div key={t.title} style={sx(t.cellStyle)}>
                    <div style={sx(t.rowStyle)} onClick={t.onClick}>
                      <div style={sx(t.tileStyle)}>{t.icon}</div>
                      <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{t.title}</div><div style={sx('font-size:11px;color:#a99fb0;line-height:1.35')}>{t.desc}</div></div>
                      {t.soon && <span style={sx(t.soonBadgeStyle)}>Coming soon</span>}
                      {t.isToggle && <div style={sx(t.trackStyle)}><div style={sx(t.knobStyle)}></div></div>}
                      {t.isBadge && <span style={sx(t.badgeStyle)}>{t.badge}</span>}
                      {t.isChevron && <span style={sx(t.chevStyle)}>{v.iChev}</span>}
                    </div>
                    {t.open && <div style={sx('margin-top:11px;padding-top:11px;border-top:1px solid #efe7ef')}>
                      <div style={sx('font-size:11.5px;color:#7a7184;line-height:1.5;margin-bottom:10px')}>{t.detail}</div>
                      <div style={sx(t.ctaStyle)} onClick={t.ctaClick}>{t.cta}</div>
                    </div>}
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
        </div>
      </div>}

      {/* ===================== VUE PARAMÈTRES ===================== */}
      {v.isSettings && <div style={sx('padding:' + (v.mobile ? '14px 14px 18px' : '24px 26px') + ';display:flex;flex-direction:column;align-items:center')}>
        <div style={sx('width:100%;max-width:1040px')}>
        <div style={sx('font-weight:700;font-size:21px;margin-bottom:4px')}>Paramètres</div>
        <div style={sx('font-size:12.5px;color:#b3a8b9;margin-bottom:20px')}>Préférences pour ce coffre. Stockées chiffrées comme le reste.</div>
        <div style={sx('display:flex;flex-direction:column;gap:22px')}>

          <div style={sx('display:flex;align-items:center;gap:14px;background:#faf7fd;border-radius:16px;padding:16px 18px')}>
            <div style={sx('width:52px;height:52px;border-radius:14px;background:#f0c9e4;color:#b14f8e;display:grid;place-items:center;font-size:22px;flex:none')}>{v.iUser}</div>
            <div style={sx('flex:1;min-width:0')}>
              <div style={sx('font-weight:700;font-size:16px')}>{v.compteNom}</div>
              <div style={sx('display:flex;align-items:center;gap:7px;min-width:0')}>
                <span style={sx('font-size:12.5px;color:#a99fb0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.compteEmail}</span>
                {/* Sans ce badge, une adresse non confirmée s'affiche comme
                    n'importe quelle autre et laisse croire que tout est en
                    règle — alors que le partage est bloqué. */}
                {!v.compteEmailVerifie && <span style={sx('flex:none;font:700 10px \'Sora\';letter-spacing:.04em;text-transform:uppercase;color:#b87e2e;background:#fdf0dd;border-radius:999px;padding:3px 9px')}>Non confirmée</span>}
              </div>
            </div>
            {/* Bouton TOUJOURS présent : le masquer quand le serveur n'envoie
                pas de courriel laissait croire que changer d'adresse était
                impossible dans CléPass, alors que seule la configuration du
                serveur manquait. La popup explique le cas.
                Le badge « Coming soon » ne vit QUE sur le bouton d'envoi : ici
                il annoncerait une porte fermée alors que la popup s'ouvre et
                se parcourt normalement. */}
            <Hv onClick={v.courriel.onOpen} style="display:flex;align-items:center;gap:7px;padding:8px 14px;background:#f3eefb;color:#6b4fb8;border-radius:10px;font-size:12.5px;font-weight:600;cursor:pointer;flex:none" hover="background:#efe7fb">{v.iGlobe} Adresse e-mail</Hv>
            <Hv onClick={v.mp.onOpen} style="display:flex;align-items:center;gap:7px;padding:8px 14px;background:#f3eefb;color:#6b4fb8;border-radius:10px;font-size:12.5px;font-weight:600;cursor:pointer;flex:none" hover="background:#efe7fb">{v.iLock} Mot de passe maître</Hv>
          </div>
          {v.mp.saved && <div style={sx('display:flex;align-items:center;gap:9px;background:#eaf6ef;border:1px solid #cfe9db;color:#2e8f72;border-radius:12px;padding:11px 14px;font-size:12px;font-weight:600;margin-top:-12px')}><span style={sx('font-size:15px')}>{v.iShieldCheck}</span>Mot de passe maître modifié. Vos données ont été rechiffrées avec la nouvelle clé.</div>}
          {/* Changement d'adresse déposé mais pas confirmé : sans ce rappel,
              l'utilisateur qui n'a jamais reçu le courriel n'a aucun moyen de
              savoir qu'une demande est en cours, ni de la reprendre. */}
          {v.courriel.enAttente && <div style={sx('display:flex;align-items:center;gap:11px;background:#fdf6ea;border:1px solid #f0dcbe;color:#8a6a2e;border-radius:12px;padding:11px 14px;font-size:12px;line-height:1.5;margin-top:-12px')}>
            <span style={sx('flex:none;font-size:14px')}>✉</span>
            <div style={sx('flex:1;min-width:0')}>En attente de confirmation : <b style={sx('color:#6b4f1e')}>{v.courriel.enAttente}</b>. Votre compte reste rattaché à l’adresse actuelle tant que le lien n’est pas ouvert.</div>
            <Hv onClick={v.courriel.onAnnuler} style={`flex:none;font-size:11.5px;font-weight:600;color:#6a6070;background:#fff;border-radius:9px;padding:6px 12px;cursor:pointer;${v.courriel.busy ? 'opacity:.6;' : ''}`} hover="background:#f3ecf3">Annuler</Hv>
          </div>}

          <div>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 12px")}>Avatar par défaut</div>
            <div style={sx('display:flex;gap:4px;background:#f1ecf6;border-radius:12px;padding:4px')}>
              {v.avatarDefaultSeg.map((o) => (
                <div key={o.label} style={sx(o.wrapStyle)}>
                  <div style={sx(o.innerStyle)}>
                    <div style={sx(o.labelStyle)} onClick={o.onClick}>{o.label}</div>
                    {o.showChevron && <div style={sx(o.chevStyle)} onClick={o.onChevron}><span style={sx(o.chevIconStyle)}>{v.iChev}</span></div>}
                  </div>
                  {o.menuOpen && <div style={sx('position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);width:256px;background:#fff;border-radius:13px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:7px;z-index:40;text-align:left')}>
                    <Hv onClick={v.onApplyAll} style="display:flex;align-items:flex-start;gap:10px;padding:10px 11px;border-radius:9px;cursor:pointer" hover="background:#f5f0f6"><span style={sx('color:#6b4fb8;font-size:15px;margin-top:1px')}>{v.iLayers}</span><div><div style={sx('font-size:12.5px;font-weight:600;color:#3a3340')}>Appliquer à tous les mots de passe du coffre</div><div style={sx('font-size:11px;color:#a99fb0;margin-top:2px;line-height:1.4')}>Remplace l'avatar de chaque entrée par ce type. Action ponctuelle.</div></div></Hv>
                  </div>}
                </div>
              ))}
            </div>
            {v.showLogoWarn && <div style={sx('display:flex;gap:8px;color:#7a7184;padding:2px 4px 0;font-size:11.5px;line-height:1.5;margin-top:8px')}><span style={sx('flex:none')}>⚠</span><div>Le logo est récupéré depuis icons.duckduckgo.com à chaque affichage. Cela révèle au CDN les domaines de votre coffre.</div></div>}
            {v.avatarApplied && <div style={sx('display:flex;align-items:center;gap:9px;background:#eaf6ef;border:1px solid #cfe9db;color:#2e8f72;border-radius:12px;padding:11px 14px;font-size:12px;font-weight:600;margin-top:10px')}><span style={sx('font-size:15px')}>{v.iShieldCheck}</span>Avatar appliqué à toutes les fiches du coffre.</div>}
          </div>

          <div style={sx('display:flex;gap:22px;align-items:flex-start')}>
          <div style={sx('flex:1;min-width:0')}>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 10px")}>Comportement de la sidebar</div>
            <div style={sx('display:flex;flex-direction:column;gap:10px')}>
              {v.sidebarToggles.map((s) => (
                <div key={s.label} style={sx(s.rowStyle)} onClick={s.onClick}>
                  <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{s.label}</div>{s.hasDesc && <div style={sx('font-size:11px;color:#a99fb0;line-height:1.35;margin-top:2px')}>{s.desc}</div>}</div>
                  {s.soon
                    ? <span style={sx(s.soonBadgeStyle)}>Coming soon</span>
                    : <div style={sx(s.trackStyle)}><div style={sx(s.knobStyle)}></div></div>}
                </div>
              ))}
            </div>
          </div>

          <div style={sx('flex:1;min-width:0')}>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 10px")}>Comportement de la liste des fiches</div>
            <div style={sx('display:flex;flex-direction:column;gap:10px')}>
              {v.listToggles.map((s) => (
                <div key={s.label} style={sx(s.rowStyle)} onClick={s.onClick}>
                  <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{s.label}</div>{s.hasDesc && <div style={sx('font-size:11px;color:#a99fb0;line-height:1.35;margin-top:2px')}>{s.desc}</div>}</div>
                  {s.soon
                    ? <span style={sx(s.soonBadgeStyle)}>Coming soon</span>
                    : <div style={sx(s.trackStyle)}><div style={sx(s.knobStyle)}></div></div>}
                </div>
              ))}
            </div>
          </div>
          </div>

          <div>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 10px")}>Sécurité</div>
            <div style={sx('display:grid;grid-template-columns:' + (v.mobile ? '1fr' : '1fr 1fr') + ';gap:10px;align-items:start')}>
            <div style={sx('position:relative')}>
              <div onClick={v.onLockToggle} style={sx('position:relative;' + (v.lockMenuOpen ? 'z-index:39;' : '') + 'display:flex;align-items:center;gap:12px;background:#faf7fd;border-radius:14px;padding:13px 15px;cursor:pointer')}>
                <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>Verrouillage automatique</div><div style={sx('font-size:11px;color:#a99fb0;line-height:1.35;margin-top:2px')}>Verrouille le coffre après inactivité</div></div>
                <span style={sx('display:inline-flex;align-items:center;gap:6px;color:#8a7f90;font-size:12.5px;font-weight:600')}>{v.autoLock} <span style={sx(v.lockChevStyle)}>{v.iChev}</span></span>
              </div>
              {v.lockMenuOpen && <F>
                <div onClick={v.onLockClose} style={sx('position:fixed;inset:0;background:rgba(40,30,55,.26);backdrop-filter:blur(6px);z-index:38')}></div>
                <div style={sx('position:absolute;top:calc(100% + 6px);left:0;right:0;background:#fff;border-radius:13px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.42);padding:6px;z-index:41;transform-origin:top;animation:scDrop .15s ease')}>
                  {v.lockOptions.map((o) => (
                    <div key={o.label} style={sx(o.style)} onClick={o.onClick}><span>{o.label}</span>{o.selected && <span style={sx('color:#6b4fb8;font-weight:800')}>✓</span>}</div>
                  ))}
                </div>
              </F>}
            </div>
              {v.secToggles.map((s) => (
                <div key={s.label} style={sx(s.rowStyle)} onClick={s.onClick}>
                  <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>{s.label}</div>{s.hasDesc && <div style={sx('font-size:11px;color:#a99fb0;line-height:1.35;margin-top:2px')}>{s.desc}</div>}</div>
                  {s.soon
                    ? <span style={sx(s.soonBadgeStyle)}>Coming soon</span>
                    : <div style={sx(s.trackStyle)}><div style={sx(s.knobStyle)}></div></div>}
                </div>
              ))}
            </div>
          </div>

          <div>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#b3a8b9;margin:0 2px 10px")}>Préférences</div>
            <div style={sx('display:grid;grid-template-columns:' + (v.mobile ? '1fr' : '1fr 1fr') + ';gap:10px')}>
              <div style={sx('background:#faf7fd;border-radius:14px;padding:13px 15px')}>
                <div style={sx('font-weight:600;font-size:13px;color:#3a3340;margin-bottom:9px')}>Thème</div>
                {/* flex-wrap : quatre thèmes sur deux rangées (la tuile fait la
                    moitié de la grille des Préférences). */}
                <div style={sx('display:flex;flex-wrap:wrap;gap:4px;background:#f1ecf6;border-radius:12px;padding:4px')}>
                  {v.themeSeg.map((o) => (
                    <div key={o.label} style={sx(o.wrapStyle)}>
                      <div style={sx(o.innerStyle)}>
                        <div style={sx(o.labelStyle)} onClick={o.onClick}>
                          <span>{o.label}</span>
                          {o.beta && <span style={sx(o.badgeStyle)}>{o.badge}</span>}
                        </div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
              <div style={sx('display:flex;align-items:center;gap:12px;background:#faf7fd;border-radius:14px;padding:13px 15px;cursor:pointer')}>
                <div style={sx('flex:1')}><div style={sx('font-weight:600;font-size:13px;color:#3a3340')}>Langue</div><div style={sx('font-size:11px;color:#a99fb0')}>Langue de l'interface</div></div>
                <span style={sx('display:inline-flex;align-items:center;gap:6px;color:#8a7f90;font-size:12.5px;font-weight:600')}>Français <span style={sx('display:inline-flex;transform:rotate(90deg);color:#c2b8c8')}>{v.iChev}</span></span>
              </div>
            </div>
          </div>

          <div>
            <div style={sx("font:700 11.5px 'Sora';letter-spacing:.08em;text-transform:uppercase;color:#c0392b;margin:0 2px 10px")}>Zone de danger</div>
            <div style={sx('display:flex;align-items:center;gap:16px;background:#fdf1f1;border:1px solid #f3d0d0;border-radius:14px;padding:16px 18px')}>
              <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:700;font-size:14px;color:#c0392b;margin-bottom:3px')}>Supprimer toutes les données</div><div style={sx('font-size:11.5px;color:#c08087;line-height:1.45')}>Efface mots de passe, codes 2FA, Wi-Fi et notes. Le coffre reste utilisable, les dossiers sont réinitialisés.</div></div>
              <div style={sx('display:flex;align-items:center;gap:8px;padding:9px 16px;border:1.5px solid #e0a3a3;color:#c0392b;background:#fff;border-radius:10px;font-size:12.5px;font-weight:700;cursor:pointer;flex:none')}>{v.iTrash} Tout supprimer…</div>
            </div>
            {/* Suppression du COMPTE (RGPD) — à ne pas confondre avec la vidange
                du coffre ci-dessus : ici, plus rien ne subsiste, pas même
                l'adresse e-mail. */}
            <div style={sx('display:flex;align-items:center;gap:16px;background:#fdf1f1;border:1px solid #f3d0d0;border-radius:14px;padding:16px 18px;margin-top:10px')}>
              <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:700;font-size:14px;color:#c0392b;margin-bottom:3px')}>Supprimer définitivement mon compte</div><div style={sx('font-size:11.5px;color:#c08087;line-height:1.45')}>Efface le compte, le coffre, l'historique, les partages et les appareils. Irréversible : aucune sauvegarde ne pourra les restaurer.</div></div>
              <Hv onClick={v.suppCompte.onOpen} style="display:flex;align-items:center;gap:8px;padding:9px 16px;background:#c0392b;color:#fff;border-radius:10px;font-size:12.5px;font-weight:700;cursor:pointer;flex:none" hover="filter:brightness(1.08)">{v.iTrash} Supprimer mon compte…</Hv>
            </div>
          </div>

        </div>
        </div>
      </div>}

    </div>}

  </div>

  {/* ===================== TOAST « JEU DE DÉMONSTRATION » ===================== */}
  {v.demoToast > 0 && <div style={sx('position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:180;display:flex;align-items:center;gap:11px;background:#6b4fb8;color:#fff;border-radius:13px;padding:13px 18px;border:1px solid #e4dce8;box-shadow:0 18px 44px -14px rgba(80,50,110,.6);font-family:\'Sora\',system-ui,sans-serif;animation:scPop .22s cubic-bezier(.2,.8,.25,1)')}>
    <span style={sx('font-size:17px;display:inline-flex')}>{v.iShieldCheck}</span>
    <span style={sx('font-size:13px;font-weight:600')}>{v.demoToast} entrées factices générées dans le dossier « DEMO ».</span>
  </div>}

  {/* ===================== OVERLAY DÉCONNEXION / PANIQUE ===================== */}
  {v.lockShown && <div style={sx('position:absolute;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);display:flex;align-items:center;justify-content:center;z-index:50;padding:' + v.popPad + ';animation:scFade .18s ease')}>
    {/* width:390px sans max-width débordait à 375 px — sur l'écran même où
        l'on vient de verrouiller son coffre. */}
    <div style={sx('background:#fff;border-radius:22px;padding:32px 36px 18px;text-align:center;width:390px;max-width:100%;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx(v.lockIconWrap)}>{v.lockIcon}</div>
      <div style={sx('font-weight:800;font-size:20px;margin-bottom:8px')}>{v.lockTitle}</div>
      <div style={sx('font-size:13px;color:#7a7184;line-height:1.55;margin-bottom:22px')}>{v.lockText}</div>
      <div onClick={v.onUnlock} style={sx('display:inline-flex;align-items:center;gap:8px;padding:12px 22px;background:#6b4fb8;color:#fff;border-radius:12px;font-size:13px;font-weight:700;cursor:pointer')}>{v.iLock} {v.lockBtn}</div>

      {/* Extender « dernières connexions » : nom, IP, lieu, user-agent, date. */}
      <div style={sx('margin-top:20px;border-top:1px solid #f0eaf2')}>
        <Hv onClick={v.onLockSessToggle} style="display:flex;align-items:center;justify-content:center;gap:7px;padding:10px 8px;border-radius:10px;cursor:pointer;font-size:12px;font-weight:600;color:#9a8fa0" hover="background:#faf7fd;color:#6b4fb8">
          Voir les dernières connexions
          <span style={sx('display:inline-flex;font-size:12px;transition:transform .18s ease;transform:rotate(' + (v.lockSessOpen ? '-90deg' : '90deg') + ')')}>{v.iChev}</span>
        </Hv>
        {v.lockSessOpen && <div className="scl" style={sx('max-height:200px;overflow:auto;text-align:left;margin:2px -10px 0;padding:0 10px')}>
          {v.lockSessLoading && <div style={sx('font-size:12px;color:#a99fb0;padding:12px;text-align:center')}>Chargement des connexions…</div>}
          {v.lockSessEmpty && <div style={sx('font-size:12px;color:#a99fb0;padding:12px;text-align:center')}>Aucune connexion récente.</div>}
          {v.lockSessions.map((s, i) => (
            <div key={i} style={sx('display:flex;gap:10px;align-items:flex-start;padding:9px 4px;' + (i ? 'border-top:1px solid #f6f1f7;' : ''))}>
              <div style={sx('width:28px;height:28px;border-radius:8px;display:grid;place-items:center;font-size:14px;flex:none;margin-top:1px;' + (s.courante ? 'background:#efe7fc;color:#6b4fb8;' : 'background:#f3eef5;color:#a99fb0;'))}>{v.iGlobe}</div>
              <div style={sx('flex:1;min-width:0')}>
                <div style={sx('display:flex;align-items:center;gap:6px')}>
                  <span style={sx('font-size:12.5px;font-weight:700;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{s.nom}</span>
                  {s.courante && <span style={sx('flex:none;font-size:9.5px;font-weight:700;letter-spacing:.04em;background:#efe7fc;color:#6b4fb8;border-radius:999px;padding:2px 7px')}>Cet appareil</span>}
                  {s.multi && <span title={s.nb + ' connexions regroupées'} style={sx('flex:none;font-size:9.5px;font-weight:700;background:#f1ecf6;color:#8a7f90;border-radius:999px;padding:2px 7px')}>× {s.nb}</span>}
                  <span style={sx('flex:none;margin-left:auto;font-size:10.5px;color:#a99fb0')}>{s.date}</span>
                </div>
                <div style={sx('font-size:11px;color:#7a7184;margin-top:2px')}>{s.ip} · {s.lieu}</div>
                {s.ua && <div title={s.ua} style={sx('font-size:10px;color:#b3a8b9;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{s.ua}</div>}
              </div>
            </div>
          ))}
        </div>}
      </div>
    </div>
  </div>}

  {/* « Partager » est désormais un onglet du panneau détail (voir showPartage),
      plus un popup modal. */}

  {/* Bilan d'import (toast) */}
  {v.importBilan && <div style={sx('position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:180;display:flex;align-items:center;gap:11px;background:#2e8f72;color:#fff;border-radius:13px;padding:13px 18px;font-family:\'Sora\',system-ui,sans-serif;animation:scPop .22s cubic-bezier(.2,.8,.25,1)')}>
    <span style={sx('font-size:16px')}>{v.iShieldCheck}</span>
    <span style={sx('font-size:13px;font-weight:600')}>{v.importBilan.crees} fiche(s) importée(s){v.importBilan.doublons ? ' · ' + v.importBilan.doublons + ' doublon(s) ignoré(s)' : ''}</span>
  </div>}

  {/* ===================== CONFIRMATION DE SUPPRESSION ===================== */}
  {v.supprConfirm && <div onClick={v.onSupprCancel} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:135;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.onSupprStop} style={sx('width:430px;max-width:100%;background:#fff;border-radius:18px;border:1px solid #e4dce8;padding:22px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:12px')}>
        <div style={sx('width:36px;height:36px;border-radius:10px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iTrash}</div>
        <div style={sx("font:800 16px 'Sora';color:#2a2431;min-width:0")}>
          {v.supprConfirm.partageDe ? 'Quitter le partage ?' : 'Supprimer « ' + v.supprConfirm.nom + ' » ?'}
        </div>
      </div>

      {v.supprConfirm.partageDe ? <F>
        <div style={sx('background:#fdf4e3;border:1px solid #eeddba;border-radius:12px;padding:12px 14px;font-size:12.5px;color:#8a6d3b;line-height:1.55')}>
          Cette fiche appartient à <b style={sx('color:#6a5427')}>{v.supprConfirm.partageDe}</b>. Vous n'en êtes pas propriétaire : la retirer <b style={sx('color:#6a5427')}>ne la supprime pas de son coffre</b>. Vous quittez simplement le partage et perdez l'accès.
        </div>
        <div style={sx('font-size:11.5px;color:#a99fb0;line-height:1.5;margin-top:10px')}>Pour retrouver l'accès, il faudra que le propriétaire vous repartage la fiche.</div>
      </F> : <F>
        {v.supprConfirm.nbPartages > 0 && <div style={sx('background:#fdf1f1;border:1px solid #f6dedd;border-radius:12px;padding:12px 14px;font-size:12.5px;color:#c0716a;line-height:1.55;margin-bottom:10px')}>
          Cette fiche est partagée avec <b style={sx('color:#a93226')}>{v.supprConfirm.nbPartages} personne(s)</b>, qui <b style={sx('color:#a93226')}>en perdront l'accès</b> immédiatement.
        </div>}
        <div style={sx('font-size:12.5px;color:#6a6070;line-height:1.55')}>
          La fiche part à la corbeille et reste <b style={sx('color:#3a3340')}>restaurable 30 jours</b>{v.supprConfirm.nbPartages > 0 ? ' — la restaurer rendra aussi l’accès aux destinataires' : ''}.
        </div>
      </F>}

      {v.supprErr && <div style={sx('margin-top:12px;background:#fbe4e4;color:#c0392b;border-radius:10px;padding:9px 12px;font-size:12px;font-weight:600')}>{v.supprErr}</div>}
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.onSupprCancel} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        <div onClick={v.onSupprConfirm} style={sx(`padding:9px 18px;background:#c0392b;color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer;${v.supprBusy ? 'opacity:.6;' : ''}`)}>
          {v.supprBusy ? '…' : (v.supprConfirm.partageDe ? 'Quitter le partage' : 'Supprimer')}
        </div>
      </div>
    </div>
  </div>}

  {/* ===================== VERSIONS RESTAURABLES ===================== */}
  {v.versions.open && <div onClick={v.versions.onClose} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:130;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.versions.onStop} style={sx('width:520px;max-width:100%;max-height:80vh;display:flex;flex-direction:column;background:#fff;border-radius:18px;border:1px solid #e4dce8;padding:22px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx("font:800 17px 'Sora';color:#2a2431;margin-bottom:4px")}>Versions de « {v.versions.nom} »</div>
      <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:16px;line-height:1.5')}>Les 20 dernières versions enregistrées, déchiffrées sur votre appareil. Restaurer remplace le contenu actuel — qui devient lui-même une version récupérable.</div>
      {v.versions.etat === 'charge' && <div style={sx('font-size:12.5px;color:#a99fb0;text-align:center;padding:24px')}>Chargement…</div>}
      {v.versions.err && <div style={sx('background:#fbe4e4;color:#c0392b;border-radius:10px;padding:9px 12px;font-size:12px;font-weight:600')}>{v.versions.err}</div>}
      {v.versions.etat === 'ok' && v.versions.rows.length === 0 && <div style={sx('font-size:12.5px;color:#a99fb0;text-align:center;padding:24px')}>Aucune version antérieure : cette fiche n'a pas encore été modifiée.</div>}
      <div className="scl" style={sx('flex:1;min-height:0;overflow:auto;margin:0 -4px;padding:0 4px')}>
        {v.versions.rows.map((r) => (
          <div key={r.key} style={sx('display:flex;align-items:center;gap:11px;background:#faf7fd;border-radius:12px;padding:11px 13px;margin-bottom:7px')}>
            <span style={sx('width:30px;height:30px;border-radius:9px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;flex:none;font-size:14px')}>{v.iRefresh}</span>
            <span style={sx('flex:1;min-width:0')}>
              <span style={sx('display:block;font-size:13px;font-weight:600;color:#3a3340')}>{r.quand}{r.recente ? ' · version précédente' : ''}</span>
              <span style={sx('display:block;font-size:11px;color:#a99fb0;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.apercu}</span>
            </span>
            <Hv onClick={r.onRestore} style="font-size:11.5px;font-weight:600;color:#2e8f72;background:#def3ec;border-radius:9px;padding:6px 11px;cursor:pointer;flex:none" hover="background:#cfe9db">Restaurer</Hv>
          </div>
        ))}
      </div>
      <div style={sx('display:flex;justify-content:flex-end;margin-top:16px')}>
        <div onClick={v.versions.onClose} style={sx('padding:8px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Fermer</div>
      </div>
    </div>
  </div>}

  {/* ===================== PHRASE DE PASSE ===================== */}
  {v.phrase.open && <div onClick={v.phrase.onClose} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:130;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.phrase.onStop} style={sx('width:470px;max-width:100%;background:#fff;border-radius:18px;border:1px solid #e4dce8;padding:22px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx("font:800 17px 'Sora';color:#2a2431;margin-bottom:4px")}>Phrase de passe</div>
      <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:16px;line-height:1.5')}>Mots tirés au hasard sur votre appareil parmi {v.phrase.taille}, avec un générateur cryptographique. Idéale pour le mot de passe maître : longue à casser, facile à retenir.</div>
      <div style={sx("background:#faf7fd;border:1.5px solid #ece5f0;border-radius:12px;padding:15px;font:600 16px 'IBM Plex Mono';color:#3a3340;word-break:break-all;line-height:1.5;text-align:center")}>{v.phrase.valeur}</div>
      <div style={sx('display:flex;align-items:center;gap:8px;margin-top:10px')}>
        <span style={sx(`font-size:11.5px;font-weight:700;color:${v.phrase.niveau[1]}`)}>{v.phrase.niveau[0]}</span>
        <span style={sx('font-size:11.5px;color:#a99fb0')}>· environ {v.phrase.bits} bits d'entropie</span>
      </div>
      <div style={sx('font-size:11px;color:#a99fb0;margin:14px 0 6px')}>Nombre de mots</div>
      <div style={sx('display:flex;gap:4px;background:#f1ecf6;border-radius:10px;padding:4px')}>
        {v.phrase.motsOpts.map((o) => (<div key={o.label} onClick={o.onClick} style={sx(o.style)}>{o.label}</div>))}
      </div>
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.phrase.onClose} style={sx('padding:8px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Fermer</div>
        <div onClick={v.phrase.onRegen} style={sx('padding:8px 16px;background:#f3eefb;color:#6b4fb8;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Regénérer</div>
        <div onClick={v.phrase.onCopy} style={sx('padding:8px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Copier</div>
      </div>
    </div>
  </div>}

  {/* ===================== CORBEILLE ===================== */}
  {v.corbeille.open && <div onClick={v.corbeille.onClose} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:130;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.corbeille.onStop} style={sx('width:540px;max-width:100%;max-height:80vh;display:flex;flex-direction:column;background:#fff;border-radius:18px;border:1px solid #e4dce8;padding:22px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx("font:800 17px 'Sora';color:#2a2431;margin-bottom:4px")}>Corbeille</div>
      <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:16px;line-height:1.5')}>Les fiches supprimées restent ici <b style={sx('color:#6a6070')}>30 jours</b>, puis sont purgées automatiquement. Elles restent chiffrées pendant tout ce temps.</div>
      {v.corbeille.err && <div style={sx('margin-bottom:12px;background:#fbe4e4;color:#c0392b;border-radius:10px;padding:9px 12px;font-size:12px;font-weight:600')}>{v.corbeille.err}</div>}
      <div className="scl" style={sx('flex:1;min-height:0;overflow:auto;margin:0 -4px;padding:0 4px')}>
        {v.corbeille.vide && <div style={sx('font-size:12.5px;color:#a99fb0;text-align:center;padding:26px 10px')}>La corbeille est vide.</div>}
        {v.corbeille.rows.map((r) => (
          <div key={r.key} style={sx('display:flex;align-items:center;gap:11px;background:#faf7fd;border-radius:12px;padding:11px 13px;margin-bottom:7px')}>
            <span style={sx(r.avStyle)}>{r.ini}</span>
            <span style={sx('flex:1;min-width:0')}>
              <span style={sx('display:block;font-size:13.5px;font-weight:600;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.nom}</span>
              <span style={sx('display:block;font-size:11px;color:#a99fb0;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{r.sousTitre ? r.sousTitre + ' · ' : ''}{r.date}</span>
            </span>
            {r.confirming ? (
              <span style={sx('display:flex;align-items:center;gap:7px;flex:none')}>
                <span style={sx('font-size:11.5px;font-weight:600;color:#c0392b')}>Effacer définitivement ?</span>
                <Hv onClick={r.onCancelPurge} style="font-size:11.5px;font-weight:600;color:#6a6070;background:#f3ecf3;border-radius:9px;padding:6px 11px;cursor:pointer" hover="background:#ece3f1">Non</Hv>
                <Hv onClick={r.onPurge} style={`font-size:11.5px;font-weight:700;color:#fff;background:#c0392b;border-radius:9px;padding:6px 11px;cursor:pointer;${r.busy ? 'opacity:.6;' : ''}`} hover="background:#a93226">{r.busy ? '…' : 'Oui'}</Hv>
              </span>
            ) : (
              <span style={sx('display:flex;align-items:center;gap:7px;flex:none')}>
                <Hv onClick={r.onRestore} style={`font-size:11.5px;font-weight:600;color:#2e8f72;background:#def3ec;border-radius:9px;padding:6px 11px;cursor:pointer;${r.busy ? 'opacity:.6;' : ''}`} hover="background:#cfe9db">{r.busy ? 'Restauration…' : 'Restaurer'}</Hv>
                <Hv onClick={r.onAskPurge} title="Effacer définitivement" style="font-size:13px;color:#c0899f;border-radius:9px;padding:6px 8px;cursor:pointer;display:inline-flex" hover="background:#fdf1f1">{v.iTrash}</Hv>
              </span>
            )}
          </div>
        ))}
      </div>
      <div style={sx('display:flex;justify-content:flex-end;margin-top:16px')}>
        <div onClick={v.corbeille.onClose} style={sx('padding:8px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Fermer</div>
      </div>
    </div>
  </div>}

  {/* ===================== POPUP « MODIFIER » (dc-import → CPEditeur) ===================== */}
  {v.editorOpen && Editeur ? <Editeur item={v.editorItem} onSave={v.onNewEditorSave} onClose={v.onNewEditorClose} customCats={v.editorCats} /> : null}

  {/* ===================== RENOMMER L'ESPACE ===================== */}
  {v.renameOpen && <div onClick={v.onRenameClose} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:130;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif")}>
    <div onClick={v.onRenameStop} style={sx('width:360px;max-width:100%;background:#fff;border-radius:18px;border:1px solid #e4dce8;box-shadow:0 30px 70px -24px rgba(40,30,55,.5);padding:22px' + v.popCarte)}>
      <div style={sx("font:800 17px 'Sora';color:#2a2431;margin-bottom:4px")}>Renommer l'espace</div>
      <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:16px')}>Le nom de l'onglet professionnel</div>
      <input value={v.renameDraft} onChange={v.onRenameDraft} placeholder="Nom de l'espace" style={sx('width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #6b4fb8;border-radius:11px;padding:11px 14px;font-size:14px;color:#3a3340;font-family:inherit;outline:none')} />
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px')}>
        <div onClick={v.onRenameClose} style={sx('padding:8px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        <div onClick={v.onRenameSave} style={sx('padding:8px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Enregistrer</div>
      </div>
    </div>
  </div>}

  {/* ===================== DÉPLACER UN DOSSIER (confirmation) ===================== */}
  {v.folderMove.open && <div onClick={v.folderMove.onCancel} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:125;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.folderMove.onStop} style={sx('width:420px;max-width:100%;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx("font:800 18px 'Sora';color:#2a2431;margin-bottom:4px")}>Déplacer le dossier</div>
      <div style={sx('font-size:12.5px;color:#a99fb0;margin-bottom:18px')}>Confirmez le déplacement dans l'arborescence.</div>
      <div style={sx('display:flex;align-items:center;gap:12px;background:#faf7fd;border-radius:14px;padding:13px 15px')}>
        <div style={sx('width:36px;height:36px;border-radius:10px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:17px;flex:none')}>{v.folderMove.srcIcon}</div>
        <div style={sx('flex:1;min-width:0')}><div style={sx('font-size:10.5px;color:#b3a8b9;text-transform:uppercase;letter-spacing:.06em;margin-bottom:3px')}>Source</div><div style={sx('font-weight:700;font-size:14px;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.folderMove.srcName}</div><div style={sx('font-size:11.5px;color:#a99fb0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.folderMove.srcPath}</div></div>
      </div>
      <div style={sx('display:grid;place-items:center;padding:7px 0;color:#a98bde;font-size:16px')}><span style={sx('display:inline-flex;transform:rotate(90deg)')}>{v.iChev}</span></div>
      <div style={sx('display:flex;align-items:center;gap:12px;background:#f4faf6;border:1px solid #cfe9db;border-radius:14px;padding:13px 15px')}>
        <div style={sx('width:36px;height:36px;border-radius:10px;background:#def3ec;color:#2e8f72;display:grid;place-items:center;font-size:17px;flex:none')}>{v.folderMove.dstIcon}</div>
        <div style={sx('flex:1;min-width:0')}><div style={sx('font-size:10.5px;color:#84a896;text-transform:uppercase;letter-spacing:.06em;margin-bottom:3px')}>Destination</div><div style={sx('font-weight:700;font-size:14px;color:#2e8f72;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.folderMove.dstName}</div><div style={sx('font-size:11.5px;color:#84a896;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{v.folderMove.dstPath}</div></div>
      </div>
      <div style={sx('font-size:11.5px;color:#a99fb0;line-height:1.5;margin-top:12px')}>{v.folderMove.note}</div>
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.folderMove.onCancel} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        <div onClick={v.folderMove.onConfirm} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Déplacer</div>
      </div>
    </div>
  </div>}

  {/* ===================== MOT DE PASSE MAÎTRE ===================== */}
  {v.mp.open && <div onClick={v.mp.onClose} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:125;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.mp.onStop} style={sx('width:420px;max-width:100%;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:4px')}><div style={sx('width:36px;height:36px;border-radius:10px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iLock}</div><div style={sx("font:800 18px 'Sora';color:#2a2431")}>Mot de passe maître</div></div>
      <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.5;margin-bottom:18px')}>Il protège l'intégralité du coffre : il n'est jamais stocké, seule une clé dérivée le vérifie.</div>
      <div style={sx('display:flex;flex-direction:column;gap:11px')}>
        <div><div style={sx('font-size:11px;color:#b3a8b9;margin:0 2px 5px')}>Mot de passe actuel</div><Hv tag="input" type={v.mp.type} value={v.mp.cur} onChange={v.mp.onCur} placeholder="••••••••••••" style="width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 14px 'IBM Plex Mono';color:#3a3340;outline:none" focus="border-color:#6b4fb8" /></div>
        <div><div style={sx('display:flex;align-items:center;margin:0 2px 5px')}><span style={sx('font-size:11px;color:#b3a8b9')}>Nouveau mot de passe</span><span style={sx(v.mp.strStyle)}>{v.mp.strLabel}</span></div><Hv tag="input" type={v.mp.type} value={v.mp.nw} onChange={v.mp.onNew} placeholder="12 caractères minimum" style="width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 14px 'IBM Plex Mono';color:#3a3340;outline:none" focus="border-color:#6b4fb8" />
          <div style={sx('height:5px;background:#f0eaf2;border-radius:999px;overflow:hidden;margin-top:7px')}><div style={sx(v.mp.barFill)}></div></div>
        </div>
        <div><div style={sx('font-size:11px;color:#b3a8b9;margin:0 2px 5px')}>Confirmer le nouveau mot de passe</div><Hv tag="input" type={v.mp.type} value={v.mp.conf} onChange={v.mp.onConf} placeholder="••••••••••••" style="width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 14px 'IBM Plex Mono';color:#3a3340;outline:none" focus="border-color:#6b4fb8" /></div>
        <div onClick={v.mp.onToggleShow} style={sx('display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:600;color:#8a7f90;cursor:pointer;user-select:none')}><span style={sx(v.mp.eyeStyle)}>{v.iEye}</span>Afficher les mots de passe</div>
      </div>
      {v.mp.err && <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:11px;padding:10px 13px;font-size:12px;font-weight:600;line-height:1.45;margin-top:13px')}><span style={sx('flex:none')}>⚠</span><div>{v.mp.err}</div></div>}
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.mp.onClose} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        <div onClick={v.mp.onSave} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Modifier le mot de passe</div>
      </div>
    </div>
  </div>}

  {/* ===================== ADRESSE E-MAIL =====================
      L'adresse sert d'identifiant de connexion ET de destinataire des
      partages : la changer déplace l'identité du compte. D'où le mot de passe
      maître exigé ici, et le fait que rien ne bouge avant que le lien envoyé à
      la NOUVELLE adresse ait été ouvert. */}
  {v.courriel.open && <div onClick={v.courriel.onClose} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:125;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.courriel.onStop} style={sx('width:520px;max-width:100%;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:4px')}><div style={sx('width:36px;height:36px;border-radius:10px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iGlobe}</div><div style={sx("font:800 18px 'Sora';color:#2a2431")}>Adresse e-mail</div></div>
      <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.55;margin:6px 0 16px')}>Adresse actuelle : <b style={sx('color:#6a6070')}>{v.courriel.actuelle}</b>. Un lien de confirmation partira vers la nouvelle : votre compte ne changera d’adresse qu’une fois ce lien ouvert.</div>
      {/* Dit AVANT la saisie : sans envoi de courriels, la demande finirait de
          toute façon en erreur côté serveur, après avoir fait taper l'adresse
          et le mot de passe maître pour rien. */}
      {!v.courriel.possible && <div style={sx('display:flex;gap:9px;background:#fdf6ea;border:1px solid #f0dcbe;color:#8a6a2e;border-radius:11px;padding:11px 13px;font-size:12px;line-height:1.5;margin-bottom:16px')}><span style={sx('flex:none')}>⚠</span><div>Ce serveur n’envoie pas de courriels : impossible de prouver que la nouvelle adresse est bien la vôtre, et donc de changer d’adresse. Contactez l’administrateur du service.</div></div>}
      <div style={sx('display:flex;flex-direction:column;gap:13px')}>
        <div><div style={sx('font-size:11px;color:#b3a8b9;margin:0 2px 5px')}>Nouvelle adresse</div><Hv tag="input" type="email" value={v.courriel.nouvelle} onChange={v.courriel.onNouvelle} placeholder="vous@exemple.fr" style="width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font-size:14px;color:#3a3340;outline:none;font-family:inherit" focus="border-color:#6b4fb8" /></div>
        <div><div style={sx('font-size:11px;color:#b3a8b9;margin:0 2px 5px')}>Mot de passe maître</div><Hv tag="input" type={v.courriel.type} value={v.courriel.mdp} onChange={v.courriel.onMdp} placeholder="••••••••••••" style="width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 14px 'IBM Plex Mono';color:#3a3340;outline:none" focus="border-color:#6b4fb8" /></div>
        <div onClick={v.courriel.onToggleShow} style={sx('display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:600;color:#8a7f90;cursor:pointer;user-select:none')}><span style={sx(v.courriel.eyeStyle)}>{v.iEye}</span>Afficher le mot de passe</div>
      </div>
      <div style={sx('font-size:11.5px;color:#a99fb0;line-height:1.55;margin-top:13px')}>Votre mot de passe maître n’est pas transmis : il sert ici à prouver que la demande vient bien de vous, et non du seul porteur de cette session.</div>
      {v.courriel.err && <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:11px;padding:10px 13px;font-size:12px;font-weight:600;line-height:1.45;margin-top:13px')}><span style={sx('flex:none')}>⚠</span><div>{v.courriel.err}</div></div>}
      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.courriel.onClose} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        {/* Envoi gelé : le bouton reste à sa place pour montrer où aboutit le
            parcours, mais il ne porte AUCUN gestionnaire de clic — un simple
            style grisé se contourne au clavier ou à l'inspecteur. */}
        {v.courriel.envoiActif
          ? <div onClick={v.courriel.onEnvoyer} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer' + (v.courriel.busy ? ';opacity:.6' : ''))}>{v.courriel.busy ? 'Envoi…' : 'Envoyer le lien'}</div>
          : <div style={sx('display:flex;align-items:center;gap:8px;padding:9px 18px;background:#f3ecf3;color:#a89fb0;border-radius:10px;font-size:13px;font-weight:700;cursor:default;user-select:none')}>Envoyer le lien <span style={sx(v.courriel.badgeStyle)}>{v.courriel.badge}</span></div>}
      </div>
    </div>
  </div>}

  {/* ===================== SUPPRESSION DU COMPTE =====================
      Irréversible et sans filet : le coffre est chiffré avec un mot de passe
      maître que le serveur n'a jamais eu, donc aucune restauration n'est
      possible, ni ici ni côté hébergeur. D'où les trois preuves demandées. */}
  {v.suppCompte.open && <div onClick={v.suppCompte.onClose} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:140;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.suppCompte.onStop} style={sx('width:440px;max-width:100%;max-height:86vh;overflow:auto;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>

      {v.suppCompte.etape === 'fait'
        ? <F>
            <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:12px')}>
              <div style={sx('width:36px;height:36px;border-radius:10px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iTrash}</div>
              <div style={sx("font:800 18px 'Sora';color:#2a2431")}>Compte supprimé</div>
            </div>
            <div style={sx('font-size:13px;color:#7a7184;line-height:1.6')}>Votre compte et l’intégralité de son contenu ont été effacés. Vous allez être redirigé vers l’écran d’accueil.</div>
          </F>
        : <F>
            <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:4px')}>
              <div style={sx('width:36px;height:36px;border-radius:10px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iTrash}</div>
              <div style={sx("font:800 18px 'Sora';color:#2a2431")}>Supprimer définitivement mon compte</div>
            </div>
            <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.5;margin-bottom:16px')}>{v.suppCompte.email}</div>

            <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:12px;padding:12px 14px;font-size:12px;line-height:1.55')}>
              <span style={sx('flex:none')}>⚠</span>
              <div>Seront effacés : toutes vos fiches, l’historique de leurs versions, la corbeille, vos dossiers, vos partages (émis <b>et</b> reçus), vos appareils et vos préférences. <b>Rien n’est récupérable</b> — vos données sont chiffrées avec un mot de passe maître que le serveur n’a jamais eu.</div>
            </div>
            <div style={sx('font-size:11.5px;color:#8a7f90;line-height:1.55;margin-top:10px')}>Pour en garder une copie, fermez cette fenêtre et lancez d’abord « Sauvegarde chiffrée hors-ligne » dans Sécurité &amp; outils.</div>

            <div style={sx("font:700 10.5px 'Sora';letter-spacing:.06em;text-transform:uppercase;color:#a99fb0;margin:16px 2px 7px")}>Mot de passe maître</div>
            <input type="password" value={v.suppCompte.mdp} onChange={v.suppCompte.onMdp} autoComplete="current-password" placeholder="••••••••••••"
                   style={sx('width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:12px;padding:12px 14px;font-size:14px;color:#3a3340;font-family:inherit;outline:none')} />

            {v.suppCompte.demandeCode && <F>
              <div style={sx("font:700 10.5px 'Sora';letter-spacing:.06em;text-transform:uppercase;color:#a99fb0;margin:14px 2px 7px")}>Code 2FA ou code de secours</div>
              <input type="text" autoComplete="one-time-code" maxLength={9} value={v.suppCompte.code} onChange={v.suppCompte.onCode} placeholder="123 456"
                     style={sx("width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:12px;padding:12px 14px;font:600 16px 'IBM Plex Mono';letter-spacing:.2em;text-align:center;color:#3a3340;outline:none")} />
            </F>}

            <div style={sx("font:700 10.5px 'Sora';letter-spacing:.06em;text-transform:uppercase;color:#a99fb0;margin:14px 2px 7px")}>Recopiez SUPPRIMER pour confirmer</div>
            <input type="text" value={v.suppCompte.phrase} onChange={v.suppCompte.onPhrase} placeholder="SUPPRIMER"
                   style={sx('width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:12px;padding:12px 14px;font-size:14px;font-weight:700;letter-spacing:.08em;color:#3a3340;font-family:inherit;outline:none')} />

            {v.suppCompte.err && <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:11px;padding:10px 13px;font-size:12px;font-weight:600;line-height:1.45;margin-top:13px')}><span style={sx('flex:none')}>⚠</span><div>{v.suppCompte.err}</div></div>}

            <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
              <div onClick={v.suppCompte.onClose} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
              <div onClick={v.suppCompte.onConfirmer} style={sx('padding:9px 18px;background:#c0392b;color:#fff;border-radius:10px;font-size:13px;font-weight:700;' + (v.suppCompte.busy ? 'opacity:.65;cursor:default;' : 'cursor:pointer;'))}>
                {v.suppCompte.busy ? 'Suppression…' : 'Supprimer définitivement'}
              </div>
            </div>
          </F>}
    </div>
  </div>}

  {/* ===================== 2FA DU COMPTE =====================
      Interrupteur « Exiger la 2FA à chaque connexion » : activation réelle
      (secret + QR otpauth → code de vérification → codes de secours) ou
      désactivation (code Authenticator ou code de secours). */}
  {v.tfaPop && <div onClick={v.tfaPop.onClose} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:126;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.tfaPop.onStop} style={sx('width:430px;max-width:100%;max-height:86vh;overflow:auto;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
      <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:4px')}><div style={sx('width:36px;height:36px;border-radius:10px;background:#def3ec;color:#2e8f72;display:grid;place-items:center;font-size:17px;flex:none')}>{v.iShieldCheck}</div><div style={sx("font:800 18px 'Sora';color:#2a2431")}>{v.tfaPop.titre}</div></div>

      {v.tfaPop.etape === 'chargement' && <div style={sx('font-size:12.5px;color:#a99fb0;padding:16px 2px')}>Préparation du secret 2FA…</div>}

      {v.tfaPop.etape === 'secret' && <F>
        <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.5;margin-bottom:16px')}>Scannez ce QR code avec votre application Authenticator (ou saisissez la clé à la main), puis recopiez le code à 6 chiffres qu'elle affiche.</div>
        {v.tfaPop.qrEl && <div style={sx('display:flex;justify-content:center;margin-bottom:14px')}>{v.tfaPop.qrEl}</div>}
        {v.tfaPop.secret && <div onClick={v.tfaPop.onCopierSecret} title="Copier la clé" style={sx("display:flex;align-items:center;gap:9px;background:#faf7fd;border:1px solid #ece5f0;border-radius:11px;padding:10px 13px;font:600 12.5px 'IBM Plex Mono';color:#3a3340;word-break:break-all;cursor:pointer;margin-bottom:14px")}><span style={sx('flex:1;min-width:0')}>{v.tfaPop.secret}</span><span style={sx('flex:none;color:#9a8fa0')}>{v.iCopy}</span></div>}
        <div style={sx('font-size:11px;color:#b3a8b9;margin:0 2px 5px')}>Code de vérification</div>
        <input type="text" inputMode="numeric" maxLength={6} value={v.tfaPop.code || ''} onChange={v.tfaPop.onCode} placeholder="123 456"
               style={sx("width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 18px 'IBM Plex Mono';letter-spacing:.3em;text-align:center;color:#3a3340;outline:none")} />
        {v.tfaPop.err && <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:11px;padding:10px 13px;font-size:12px;font-weight:600;line-height:1.45;margin-top:13px')}><span style={sx('flex:none')}>⚠</span><div>{v.tfaPop.err}</div></div>}
        <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
          <div onClick={v.tfaPop.onClose} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
          <div onClick={v.tfaPop.onConfirmer} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer;' + (v.tfaPop.busy ? 'opacity:.6;' : ''))}>{v.tfaPop.busy ? 'Vérification…' : 'Activer la 2FA'}</div>
        </div>
      </F>}

      {v.tfaPop.etape === 'codes' && <F>
        <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.5;margin-bottom:14px')}>2FA activée. Conservez ces codes de secours hors de ce coffre : chacun ouvre une session <b style={sx('color:#3a3340')}>une seule fois</b>, si vous perdez votre téléphone. Ils ne seront plus jamais affichés.</div>
        <div style={sx("display:grid;grid-template-columns:1fr 1fr;gap:8px;background:#faf7fd;border:1px solid #ece5f0;border-radius:13px;padding:13px")}>
          {(v.tfaPop.codes || []).map((c) => (<div key={c} style={sx("font:600 13.5px 'IBM Plex Mono';letter-spacing:.1em;color:#3a3340;text-align:center")}>{c}</div>))}
        </div>
        <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
          <div onClick={v.tfaPop.onCopierCodes} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Copier les codes</div>
          <div onClick={v.tfaPop.onClose} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>J'ai noté mes codes</div>
        </div>
      </F>}

      {v.tfaPop.etape === 'desactiver' && <F>
        <div style={sx('font-size:12.5px;color:#a99fb0;line-height:1.5;margin-bottom:16px')}>Saisissez le code à 6 chiffres de votre application Authenticator, ou l'un de vos codes de secours. Vos codes de secours actuels seront invalidés.</div>
        <input type="text" maxLength={9} value={v.tfaPop.code || ''} onChange={v.tfaPop.onCode} placeholder="123 456 ou A1B2C3D4"
               style={sx("width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:11px 14px;font:600 16px 'IBM Plex Mono';letter-spacing:.16em;text-align:center;color:#3a3340;outline:none")} />
        {v.tfaPop.err && <div style={sx('display:flex;gap:9px;background:#fdf1f1;border:1px solid #f3d0d0;color:#c0392b;border-radius:11px;padding:10px 13px;font-size:12px;font-weight:600;line-height:1.45;margin-top:13px')}><span style={sx('flex:none')}>⚠</span><div>{v.tfaPop.err}</div></div>}
        <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
          <div onClick={v.tfaPop.onClose} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
          <div onClick={v.tfaPop.onDesactiver} style={sx('padding:9px 18px;background:#c0392b;color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer;' + (v.tfaPop.busy ? 'opacity:.6;' : ''))}>{v.tfaPop.busy ? 'Vérification…' : 'Désactiver'}</div>
        </div>
      </F>}
    </div>
  </div>}

  {/* ===================== GÉRER LES TYPES ===================== */}
  {v.catManagerOpen && <div onClick={v.onCatManagerClose} style={sx("position:fixed;inset:0;background:rgba(40,30,55,.42);backdrop-filter:blur(5px);z-index:120;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif")}>
    <div onClick={v.onCatMenuStop} style={sx('width:430px;max-width:100%;max-height:82vh;overflow:auto;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -24px rgba(40,30,55,.5);padding:22px 22px 20px' + v.popCarte)}>
      <div style={sx('display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:3px')}>
        <div style={sx("font:800 18px 'Sora';color:#2a2431")}>Gérer les types</div>
        <div onClick={v.onCatManagerClose} style={sx('width:30px;height:30px;border-radius:9px;background:#f3ecf3;display:grid;place-items:center;color:#8a7f90;cursor:pointer')}>✕</div>
      </div>
      <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:16px')}>Glissez pour réordonner · les types par défaut ne sont pas supprimables</div>
      <div style={sx('display:flex;flex-direction:column;gap:8px;margin-bottom:14px')}>
        {v.catManagerRows.map((c, i) => (
          <div key={i} draggable={true} onDragStart={c.onDragStart} onDragEnd={c.onDragEnd} onDragOver={c.onOver} onDrop={c.onDrop} style={sx(c.rowStyle)}>
            <span title="Glisser pour réordonner" style={sx('display:inline-grid;grid-template-columns:3px 3px;gap:3px;flex:none')}><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:3px;height:3px;border-radius:50%;background:#c9bcd6')}></span></span>
            <span style={sx(c.tileStyle)}>{c.icon}</span>
            <span style={sx('flex:1;min-width:0;font-weight:600;font-size:13.5px;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>{c.label}</span>
            {/* Zone boutons : exclue du drag de la ligne (dragstart bloqué). */}
            <span draggable={true} onDragStart={(ev) => { if (ev) { ev.preventDefault(); ev.stopPropagation(); } }} style={sx('display:flex;align-items:center;gap:2px;flex:none;cursor:default')}>
              {c.editable && <Hv onClick={c.onEdit} title="Personnaliser (nom, icône, couleur, champs)" style="width:26px;height:26px;border-radius:8px;display:grid;place-items:center;color:#6b4fb8;cursor:pointer;flex:none;font-size:13px" hover="background:#efe7fc">{v.iEdit}</Hv>}
              {c.deletable && <span onClick={c.onDelete} title="Supprimer" style={sx('width:26px;height:26px;border-radius:8px;display:grid;place-items:center;color:#c0899f;cursor:pointer;flex:none;font-size:13px')}>✕</span>}
              {c.notDeletable && <span title="Type par défaut" style={sx('width:26px;height:26px;display:grid;place-items:center;color:#d0c6d8;flex:none')}><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2"><rect x="5" y="11" width="14" height="9" rx="2"></rect><path d="M8 11V8a4 4 0 0 1 8 0v3"></path></svg></span>}
            </span>
          </div>
        ))}
      </div>
      <div style={sx('display:flex;gap:8px')}>
        <Hv tag="input" value={v.catDraft} onChange={v.onCatDraft} placeholder="Nouveau type…" style="flex:1;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:11px;padding:10px 13px;font-size:13px;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
        <div onClick={v.onCatAdd} style={sx('padding:10px 18px;border-radius:11px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;font-size:13px;font-weight:700;cursor:pointer;display:grid;place-items:center')}>Ajouter</div>
      </div>
    </div>
  </div>}

  {/* ===================== PERSONNALISER LE TYPE ===================== */}
  {v.catEdit.open && <div onClick={v.catEdit.onCancel} style={sx("position:fixed;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);z-index:122;display:flex;align-items:center;justify-content:center;padding:" + v.popPad + ";font-family:'Sora',system-ui,sans-serif;animation:scFade .18s ease")}>
    <div onClick={v.catEdit.onStop} style={sx('width:850px;max-width:100%;max-height:86vh;overflow:auto;background:#fff;border-radius:20px;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);padding:24px;animation:scPop .22s cubic-bezier(.2,.8,.25,1)' + v.popCarte)} className="scl">
      <div style={sx('display:flex;align-items:center;gap:13px;margin-bottom:4px')}>
        <div style={sx(v.catEdit.tileStyle)}>{v.catEdit.tileIcon}</div>
        <div style={sx('flex:1;min-width:0')}>
          <div style={sx("font:800 18px 'Sora';color:#2a2431")}>Personnaliser le type</div>
          <Hv tag="input" value={v.catEdit.label} onChange={v.catEdit.onName} placeholder="Nom du type" style="margin-top:5px;width:210px;max-width:100%;box-sizing:border-box;background:#faf7fd;border:1.5px solid #ece5f0;border-radius:9px;padding:6px 10px;font-size:12.5px;font-weight:600;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
        </div>
        <Hv onClick={v.catEdit.onDuplicate} title="Dupliquer ce type (icône, couleur et champs)" style="display:flex;align-items:center;gap:6px;border:1.5px dashed #d9cde6;color:#6b4fb8;border-radius:9px;padding:6px 11px;font-size:12px;font-weight:600;cursor:pointer;flex:none" hover="background:#f7f3fb">⧉ Dupliquer</Hv>
      </div>

      <div style={sx("font:700 10px 'Sora';letter-spacing:.1em;text-transform:uppercase;color:#b3a8b9;margin:18px 2px 9px")}>Icône</div>
      <div style={sx('display:flex;flex-wrap:wrap;gap:8px')}>
        {v.catEdit.icons.map((o, i) => (<div key={i} style={sx(o.style)} onClick={o.onClick}>{o.icon}</div>))}
      </div>

      <div style={sx("font:700 10px 'Sora';letter-spacing:.1em;text-transform:uppercase;color:#b3a8b9;margin:18px 2px 9px")}>Couleur</div>
      <div style={sx('display:flex;flex-wrap:wrap;gap:10px')}>
        {v.catEdit.colors.map((o, i) => (<div key={i} style={sx(o.style)} onClick={o.onClick}><div style={sx(o.dotStyle)}></div></div>))}
      </div>

      {/* Deux colonnes : champs à gauche, aperçu de la fiche à droite, les
          deux sections démarrant au même niveau (aperçu sticky au défilement). */}
      <div style={sx('display:flex;gap:22px;align-items:stretch')}>
      <div style={sx('flex:1;min-width:0')}>
      {v.catEdit.options.length > 0 && <F>
        <div style={sx("font:700 10px 'Sora';letter-spacing:.1em;text-transform:uppercase;color:#b3a8b9;margin:20px 0 9px 2px")}>Options</div>
        <div style={sx('display:flex;flex-direction:column;gap:8px')}>
          {v.catEdit.options.map((o, i) => (
            <div key={i} onClick={o.onToggle} style={sx('display:flex;align-items:center;gap:12px;background:#faf7fd;border:1px solid #f0eaf2;border-radius:12px;padding:12px 14px;cursor:pointer')}>
              <span style={sx('flex:1;min-width:0;font-size:13px;font-weight:600;color:#3a3340')}>{o.label}</span>
              <div style={sx(o.trackStyle)}><div style={sx(o.knobStyle)}></div></div>
            </div>
          ))}
        </div>
      </F>}
      {v.catEdit.hasFields && <F>
      <div style={sx('display:flex;align-items:center;justify-content:space-between;margin:20px 0 9px')}>
        <span style={sx("font:700 10px 'Sora';letter-spacing:.1em;text-transform:uppercase;color:#b3a8b9;margin-left:2px")}>Champs du panneau de détail</span>
        <div onClick={v.catEdit.onAddField} style={sx('display:flex;align-items:center;gap:5px;border:1.5px dashed #d9cde6;color:#6b4fb8;border-radius:9px;padding:5px 11px;font-size:12px;font-weight:600;cursor:pointer')}>{v.iPlus} Ajouter un champ</div>
      </div>
      <div style={sx('display:flex;flex-direction:column;gap:8px')}>
        {v.catEdit.fields.map((f, i) => (
          <div key={i} draggable={true} onDragStart={f.onDragStart} onDragEnd={f.onDragEnd} onDragOver={f.onOver} onDrop={f.onDrop} style={sx(f.rowStyle)}>
            <div style={sx('display:flex;align-items:center;gap:8px')}>
              <span title="Glisser pour réordonner" style={sx('display:inline-grid;grid-template-columns:2.5px 2.5px;gap:3px;flex:none;cursor:grab')}><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span><span style={sx('width:2.5px;height:2.5px;border-radius:50%;background:#c9bcd6')}></span></span>
              <Hv tag="input" value={f.label} onChange={f.onLabel} placeholder="Nom du champ" style="flex:1;min-width:0;box-sizing:border-box;background:#fff;border:1.5px solid #ece5f0;border-radius:9px;padding:8px 11px;font-size:13px;font-weight:600;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
              <select value={f.type} onChange={f.onType} style={sx("background:#fff;border:1.5px solid #ece5f0;border-radius:9px;padding:8px 9px;font:600 12px 'Sora';color:#6a6070;outline:none;cursor:pointer;flex:none")}>
                {f.typeOpts.map((t) => (<option key={t[0]} value={t[0]}>{t[1]}</option>))}
              </select>
              <div title="Largeur dans la fiche" style={sx('display:flex;background:#fff;border:1.5px solid #ece5f0;border-radius:9px;overflow:hidden;flex:none')}>
                {f.widths.map((wo, k) => (<div key={k} onClick={wo.onClick} style={sx(wo.style)}>{wo.label}</div>))}
              </div>
              <span onClick={f.onRemove} title="Retirer" style={sx('width:26px;height:26px;border-radius:8px;display:grid;place-items:center;color:#c0899f;cursor:pointer;flex:none;font-size:13px')}>✕</span>
            </div>
            {f.isListe && <div style={sx('display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px')}>
              {f.optionChips.map((o, k) => (<span key={k} style={sx('display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;padding:4px 9px;border-radius:999px;background:#efe7fc;color:#6b4fb8')}>{o.label}<span onClick={o.onRemove} title="Retirer l'option" style={sx('cursor:pointer;font-size:11px;opacity:.6')}>✕</span></span>))}
              <Hv tag="input" value={f.optDraft} onChange={f.onOptDraft} onKeyDown={f.onOptKey} placeholder="Ajouter une option + Entrée" style="flex:1;min-width:140px;box-sizing:border-box;background:#fff;border:1.5px solid #ece5f0;border-radius:9px;padding:7px 10px;font-size:12px;color:#3a3340;font-family:inherit;outline:none" focus="border-color:#6b4fb8" />
            </div>}
          </div>
        ))}
        {!v.catEdit.fields.length && <div style={sx('font-size:12px;color:#a99fb0;background:#faf7fd;border:1.5px dashed #e4dce8;border-radius:12px;padding:14px;text-align:center')}>Aucun champ personnalisé — la fiche garde sa présentation standard.</div>}
      </div>
      </F>}
      </div>

      <div style={sx('width:320px;flex:none')}>
        <div style={sx('position:sticky;top:0')}>
          <div style={sx('display:flex;align-items:center;min-height:29px;margin:20px 0 9px')}><span style={sx("font:700 10px 'Sora';letter-spacing:.1em;text-transform:uppercase;color:#b3a8b9;margin-left:2px")}>Aperçu de la fiche</span></div>
          <div style={sx('background:#faf7fd;border:1px solid #f0eaf2;border-radius:14px;padding:12px')}>
            <div style={sx('display:flex;align-items:center;gap:7px;margin:0 0 9px')}>
              <div style={sx(v.catEdit.previewChipStyle)}>{v.catEdit.tileIcon}</div>
              <div style={sx("font:600 10px 'Sora';letter-spacing:.13em;color:#b3a8b9;text-transform:uppercase")}>{v.catEdit.label}</div>
            </div>
            {v.catEdit.hasFields ? <F>
              {v.catEdit.preview.length > 0 && <div style={sx('display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px')}>
                {v.catEdit.preview.map((p, i) => (
                  <div key={i} style={sx(p.cellStyle)}>
                    <div style={sx('font-size:10.5px;color:#b3a8b9;margin-bottom:4px')}>{p.label}</div>
                    <div style={sx('font-weight:600;font-size:12.5px;color:#3a3340;' + (p.isMulti ? 'white-space:pre-wrap' : 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis'))}>{p.value}</div>
                  </div>
                ))}
              </div>}
              {!v.catEdit.preview.length && <div style={sx('font-size:12px;color:#a99fb0;text-align:center;padding:12px 6px')}>Ajoutez des champs pour voir l'aperçu.</div>}
            </F> : <F>
              {v.catEdit.key === 'pw' && <F>
                <div style={sx(v.catEdit.optVals.inline ? 'display:flex;gap:7px' : 'display:flex;flex-direction:column;gap:7px')}>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>Nom d'utilisateur</div><div style={sx('font-size:12px;font-weight:600;color:#3a3340;white-space:nowrap;overflow:hidden;text-overflow:ellipsis')}>alex@exemple.fr</div></div>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>Mot de passe</div><div style={sx("font:600 12px 'Space Grotesk';letter-spacing:.14em;color:#3a3340")}>••••••••</div></div>
                </div>
                {v.catEdit.optVals.rotation && <div style={sx('display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px;margin-top:7px')}><div style={sx('width:22px;height:22px;border-radius:7px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:12px;flex:none')}>{v.iRefresh}</div><div style={sx('font-size:11px;font-weight:600;color:#3a3340')}>Rotation automatique</div></div>}
              </F>}
              {v.catEdit.key === 'wifi' && <F>
                {v.catEdit.optVals.qr && <div style={sx('display:flex;align-items:center;gap:10px;background:linear-gradient(135deg,#efe7fc,#fbeef4);border-radius:11px;padding:12px;margin-bottom:7px')}><div style={sx('width:42px;height:42px;border-radius:8px;background:#fff;display:grid;place-items:center;color:#6b4fb8;flex:none;font-size:22px')}>{v.iQr}</div><div style={sx('font-size:11px;color:#7a7184;line-height:1.4')}>QR de connexion automatique</div></div>}
                <div style={sx('display:flex;gap:7px')}>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>SSID</div><div style={sx('font-size:12px;font-weight:600;color:#3a3340')}>MonRéseau</div></div>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>Sécurité</div><div style={sx('font-size:12px;font-weight:600;color:#3a3340')}>WPA2</div></div>
                </div>
              </F>}
              {v.catEdit.key === '2fa' && <div style={sx('background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:11px 12px;text-align:center')}><div style={sx("font:700 9.5px 'Sora';letter-spacing:.12em;color:#b3a8b9;margin-bottom:5px")}>AUTHENTICATOR</div><div style={sx("font:700 22px 'Space Grotesk';color:#6b4fb8;letter-spacing:.08em")}>123 456</div></div>}
              {v.catEdit.key === 'card' && <F>
                <div style={sx('background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px;margin-bottom:7px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>Numéro de carte</div><div style={sx("font:600 12px 'IBM Plex Mono';letter-spacing:.06em;color:#3a3340")}>•••• •••• •••• 4242</div></div>
                <div style={sx('display:flex;gap:7px')}>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>Expiration</div><div style={sx('font-size:12px;font-weight:600;color:#3a3340')}>08 / 28</div></div>
                  <div style={sx('flex:1;min-width:0;background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:8px 10px')}><div style={sx('font-size:9.5px;color:#b3a8b9;margin-bottom:3px')}>CVV</div><div style={sx("font:600 12px 'IBM Plex Mono';letter-spacing:.1em;color:#3a3340")}>•••</div></div>
                </div>
              </F>}
              {v.catEdit.key === 'notes' && <div style={sx('background:#fff;border:1px solid #f0eaf2;border-radius:9px;padding:10px 12px;font-size:11.5px;line-height:1.55;color:#7a7184')}>Texte libre chiffré — vos notes sécurisées s'affichent ici.</div>}
            </F>}
          </div>
          <div style={sx('font-size:11px;color:#a99fb0;line-height:1.5;margin-top:10px')}>{v.catEdit.hasFields ? "Ces champs s'affichent dans la fiche de chaque élément du type. Réglez la largeur de chacun (1/1, 1/2 ou 1/3) et glissez pour réordonner. Types : texte, mot de passe masqué, liste, interrupteur, lien, date, nombre, texte multiligne." : "Ces options s'appliquent à toutes les fiches de ce type. L'aperçu ci-dessus reflète vos réglages en direct."}</div>
        </div>
      </div>
      </div>

      <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
        <div onClick={v.catEdit.onCancel} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
        <div onClick={v.catEdit.onSave} style={sx('padding:9px 18px;background:linear-gradient(120deg,#7c5cff,#b06ad6);color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Enregistrer</div>
      </div>

      {/* Avertissement avant suppression d'un champ renseigné sur des éléments */}
      {v.catEdit.confirmDelete && <div onClick={v.catEdit.confirmDelete.onCancel} style={sx('position:fixed;inset:0;background:rgba(38,34,46,.5);backdrop-filter:blur(4px);z-index:130;display:flex;align-items:center;justify-content:center;padding:' + v.popPad + ';animation:scFade .15s ease')}>
        <div onClick={v.catEdit.onStop} style={sx('width:410px;max-width:100%;background:#fff;border-radius:18px;border:1px solid #e4dce8;box-shadow:0 24px 60px -18px rgba(20,15,30,.55);padding:22px;animation:scPop .2s cubic-bezier(.2,.8,.25,1)' + v.popCarte)}>
          <div style={sx('display:flex;align-items:center;gap:11px;margin-bottom:10px')}>
            <div style={sx('width:38px;height:38px;border-radius:11px;background:#fbe4e4;color:#c0392b;display:grid;place-items:center;flex:none')}><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 9v4M12 17h.01"></path><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"></path></svg></div>
            <div style={sx("font:800 16px 'Sora';color:#2a2431;min-width:0")}>Supprimer le champ « {v.catEdit.confirmDelete.label} » ?</div>
          </div>
          <div style={sx('font-size:12.5px;color:#6a6070;line-height:1.55')}>Ce champ est renseigné sur <b style={sx('color:#c0392b')}>{v.catEdit.confirmDelete.countLabel}</b> de ce type. Ces valeurs seront <b style={sx('color:#3a3340')}>définitivement effacées</b> à l'enregistrement du type.</div>
          <div style={sx('display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px')}>
            <div onClick={v.catEdit.confirmDelete.onCancel} style={sx('padding:9px 16px;background:#f3ecf3;color:#6a6070;border-radius:10px;font-size:13px;font-weight:600;cursor:pointer')}>Annuler</div>
            <div onClick={v.catEdit.confirmDelete.onConfirm} style={sx('padding:9px 18px;background:#c0392b;color:#fff;border-radius:10px;font-size:13px;font-weight:700;cursor:pointer')}>Supprimer le champ</div>
          </div>
        </div>
      </div>}
    </div>
  </div>}

  {/* ===================== MENU « NOUVEL ÉLÉMENT » ===================== */}
  {v.addMenuOpen && <F>
    <div onClick={v.onAddClose} style={sx(v.addOverlayStyle)}></div>
    <div style={sx(v.addCardStyle)}>
      <div style={sx('font-size:10.5px;font-weight:700;letter-spacing:.09em;color:#b3a8b9;padding:6px 12px 8px')}>TYPES GÉNÉRIQUES</div>
      {v.addGenericRows.map((a) => (
        <Hv key={a.name} style={a.rowStyle} onClick={a.onClick} hover={a.soon ? '' : 'background:#f7f3fb'}>
          <div style={sx(a.tileStyle)}>{a.icon}</div>
          <div style={sx('flex:1;min-width:0')}><div style={sx('font-weight:700;font-size:14px;color:#3a3340')}>{a.name}</div><div style={sx('font-size:11.5px;color:#a99fb0')}>{a.desc}</div></div>
          {a.soon && <span style={sx(a.soonBadgeStyle)}>Coming soon</span>}
        </Hv>
      ))}
      <div style={sx('height:1px;background:#f0eaf2;margin:8px 10px')}></div>
      <div style={sx('display:flex;align-items:center;justify-content:space-between;padding:6px 12px 8px')}>
        <span style={sx('font-size:10.5px;font-weight:700;letter-spacing:.09em;color:#b3a8b9')}>TYPES PERSONNALISÉS</span>
        <Hv onClick={v.onAddNewType} title="Créer un type personnalisé" style="width:20px;height:20px;border-radius:6px;display:grid;place-items:center;color:#b3a8b9;cursor:pointer;font-size:15px;line-height:1" hover="background:#efe7fc;color:#6b4fb8">+</Hv>
      </div>
      {v.addCustomRows.map((a) => (
        <Hv key={a.name} style={a.rowStyle} onClick={a.onClick} hover="background:#f7f3fb">
          <div style={sx(a.tileStyle)}>{a.icon}</div>
          <div style={sx('min-width:0')}><div style={sx('font-weight:700;font-size:14px;color:#3a3340')}>{a.name}</div><div style={sx('font-size:11.5px;color:#a99fb0')}>{a.desc}</div></div>
        </Hv>
      ))}
    </div>
  </F>}

  {/* ===================== OVERLAY ÉDITEUR (ajouter / modifier) ===================== */}
  {v.edOpen && <div style={sx('position:absolute;inset:0;background:rgba(40,30,55,.5);backdrop-filter:blur(7px);display:flex;align-items:center;justify-content:center;z-index:60;padding:' + v.popPad + ';animation:scFade .18s ease')}>
    <div style={sx('background:#fff;border-radius:22px;width:648px;max-width:100%;max-height:100%;display:flex;flex-direction:column;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.55);overflow:hidden;animation:scPop .22s cubic-bezier(.2,.8,.25,1)')}>
      <div style={sx('padding:24px 28px 15px;position:relative;flex:none')}>
        <div style={sx("font:800 22px 'Sora';color:#2a2431")}>{v.edTitle}</div>
        {v.edShowSubtitle && <div style={sx('font-size:12.5px;color:#a99fb0;margin-top:3px')}>Toutes les données sont chiffrées localement avant envoi.</div>}
        <div onClick={v.onEditorClose} title="Fermer" style={sx('position:absolute;top:20px;right:22px;width:34px;height:34px;border-radius:10px;background:#f3ecf3;display:grid;place-items:center;color:#8a7f90;font-size:15px;cursor:pointer')}>✕</div>
      </div>
      <div className="scl" style={sx('padding:6px 28px 12px;overflow:auto;flex:1;min-height:0;display:flex;flex-direction:column;gap:16px')}>
        <div style={sx('display:flex;gap:14px')}>
          <div style={sx('flex:1;min-width:0')}>
            <div style={sx(v.edLabelStyle)}>Nom (facultatif)</div>
            <Hv tag="input" value={v.form.name} onChange={v.onName} placeholder={v.edNamePlaceholder} style={v.edInputStyle} focus="border-color:#6b4fb8;background:#fff" />
          </div>
          {v.edIsWifi && <div style={sx('flex:1;min-width:0')}>
            <div style={sx(v.edLabelStyle)}>SSID (nom du réseau) <span style={sx('color:#c0392b')}>*</span></div>
            <Hv tag="input" value={v.form.ssid} onChange={v.onSsid} placeholder="Mon-Réseau" style={v.edInputStyle} focus="border-color:#6b4fb8;background:#fff" />
          </div>}
          {v.edShowDomain && <div style={sx('flex:1;min-width:0')}>
            <div style={sx(v.edLabelStyle)}>{v.edDomainLabel}</div>
            <Hv tag="input" value={v.form.domain} onChange={v.onDomain} placeholder={v.edDomainPlaceholder} style={v.edInputStyle} focus="border-color:#6b4fb8;background:#fff" />
          </div>}
        </div>

        {v.edShowAvatar && <div style={sx('background:#faf7fd;border-radius:16px;padding:15px;display:flex;gap:15px;align-items:center')}>
          <div style={sx(v.avStyle)}>{v.avGlyph}</div>
          <div style={sx('flex:1;min-width:0')}>
            <div style={sx('display:flex;gap:4px;background:#f1ecf6;border-radius:11px;padding:4px')}>
              {v.avModes.map((m) => (<div key={m.label} style={sx(m.style)} onClick={m.onClick}>{m.label}</div>))}
            </div>
            <div style={sx('display:flex;flex-wrap:wrap;gap:9px;margin-top:13px')}>
              {v.swatches.map((c, i) => (<div key={i} style={sx(c.style)} onClick={c.onClick}></div>))}
            </div>
          </div>
        </div>}

        {v.edIsWifi && <F>
          <div>
            <div style={sx(v.edLabelStyle)}>Mot de passe Wi-Fi</div>
            <div style={sx('display:flex;gap:8px;align-items:center')}>
              <Hv tag="input" type={v.wifiPwType} value={v.form.wifiPass} onChange={v.onWifiPass} placeholder="Clé du réseau" style={v.edInputStyle} focus="border-color:#6b4fb8;background:#fff" />
              <div onClick={v.onFormWifiShow} title="Afficher" style={sx('width:44px;height:44px;flex:none;border-radius:12px;background:#faf7fd;border:1.5px solid #ece5f0;display:grid;place-items:center;color:#8a7f90;cursor:pointer')}>{v.iEye}</div>
            </div>
            <div style={sx('display:flex;align-items:center;gap:10px;margin-top:9px')}>
              <div style={sx('flex:1;height:5px;background:#f0eaf2;border-radius:999px;overflow:hidden')}><div style={sx(v.wifiBarFill)}></div></div>
              <span style={sx(v.wifiStrStyle)}>{v.wifiStrLabel}</span>
            </div>
          </div>
          <div style={sx('display:flex;gap:14px;align-items:flex-end')}>
            <div style={sx('flex:1;min-width:0')}>
              <div style={sx(v.edLabelStyle)}>Sécurité</div>
              <select value={v.form.security} onChange={v.onSecurity} style={sx(v.edSelectStyle)}>{v.secOpts.map((o) => (<option key={o} value={o}>{o}</option>))}</select>
            </div>
            <div onClick={v.onFormSsidHidden} style={sx('flex:1;display:flex;align-items:center;justify-content:space-between;background:#faf7fd;border-radius:12px;padding:12px 15px;cursor:pointer')}><span style={sx('font-size:13.5px;font-weight:600;color:#3a3340')}>SSID caché</span><div style={sx(v.edSsidTrack)}><div style={sx(v.edSsidKnob)}></div></div></div>
          </div>
        </F>}

        <div style={sx('display:flex;gap:14px;align-items:flex-start')}>
          <div style={sx('flex:1;min-width:0')}>
            <div style={sx(v.edLabelStyle)}>Dossier</div>
            <select value={v.form.folder} onChange={v.onFolderSel} style={sx(v.edSelectStyle)}><option value="">— Aucun —</option>{v.folderOpts.map((o) => (<option key={o} value={o}>{o}</option>))}</select>
          </div>
          <div style={sx('flex:1;min-width:0;display:flex;flex-direction:column;gap:8px')}>
            <div onClick={v.onFormFav} style={sx('display:flex;align-items:center;justify-content:space-between;background:#faf7fd;border-radius:12px;padding:10px 15px;cursor:pointer')}><span style={sx('font-size:13.5px;font-weight:600;color:#3a3340')}>Favori</span><div style={sx(v.edFavTrack)}><div style={sx(v.edFavKnob)}></div></div></div>
            <div onClick={v.onFormShared} style={sx('display:flex;align-items:center;justify-content:space-between;background:#faf7fd;border-radius:12px;padding:10px 15px;cursor:pointer')}><span style={sx('font-size:13.5px;font-weight:600;color:#3a3340')}>Partagé</span><div style={sx(v.edSharedTrack)}><div style={sx(v.edSharedKnob)}></div></div></div>
          </div>
        </div>

        {v.edIsLogin && <div>
          <div style={sx(v.edLabelStyle)}>Type</div>
          <div style={sx('display:flex;gap:8px')}>
            <select value={v.form.type} onChange={v.onTypeSel} style={sx(v.edSelectStyle)}><option value="">— Aucun —</option>{v.edTypeOpts.map((t) => (<option key={t} value={t}>{t}</option>))}</select>
            <div title="Nouveau type" style={sx('width:44px;height:44px;flex:none;border-radius:12px;background:#faf7fd;border:1.5px solid #ece5f0;display:grid;place-items:center;color:#8a7f90;font-size:18px;cursor:pointer')}>{v.iPlus}</div>
          </div>
        </div>}

        {v.edIsLogin && <F>
          <div style={sx('height:1px;background:#f2edf5')}></div>
          <div>
            <div style={sx('display:flex;align-items:center;justify-content:space-between;margin-bottom:11px')}>
              <div style={sx('display:flex;align-items:center;gap:9px')}><span style={sx(v.edSectionLabel)}>Comptes</span><span style={sx("min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:#efe7fc;color:#6b4fb8;font:700 11px 'Sora';display:grid;place-items:center")}>{v.acctCount}</span></div>
              <div onClick={v.onAddAccount} style={sx('display:flex;align-items:center;gap:5px;border:1.5px dashed #d9cde6;color:#6b4fb8;border-radius:9px;padding:6px 11px;font-size:12px;font-weight:600;cursor:pointer')}>{v.iPlus} Ajouter</div>
            </div>
            <div style={sx('display:flex;flex-direction:column;gap:12px')}>
              {v.acctRows.map((a, i) => (
                <div key={i} style={sx('background:#faf7fd;border:1px solid #f0eaf2;border-radius:14px;padding:14px')}>
                  <div style={sx('display:flex;align-items:center;gap:9px;margin-bottom:11px')}>
                    <span style={sx("font:700 11px 'Sora';letter-spacing:.06em;color:#8a7f96")}>{a.label}</span>
                    {a.principal && <span style={sx("font:700 9px 'Sora';letter-spacing:.05em;color:#6b4fb8;background:#efe7fc;padding:3px 8px;border-radius:6px")}>PRINCIPAL</span>}
                    {a.canRemove && <div onClick={a.remove} title="Retirer" style={sx('margin-left:auto;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;color:#c0716a;cursor:pointer;font-size:14px')}>{v.iTrash}</div>}
                  </div>
                  <div style={sx(v.edLabelStyle)}>Identifiant</div>
                  <Hv tag="input" value={a.user} onChange={a.onUser} placeholder="identifiant@exemple.fr" style={v.edInputStyle + ';background:#fff'} focus="border-color:#6b4fb8" />
                  <div style={sx(v.edLabelStyle + ';margin-top:12px')}>Mot de passe</div>
                  <div style={sx('display:flex;gap:8px;align-items:center')}>
                    <Hv tag="input" type={a.pwType} value={a.password} onChange={a.onPass} placeholder="••••••••" style={v.edInputStyle + ';background:#fff'} focus="border-color:#6b4fb8" />
                    <div onClick={a.toggleShow} title="Afficher" style={sx('width:44px;height:44px;flex:none;border-radius:12px;background:#fff;border:1.5px solid #ece5f0;display:grid;place-items:center;color:#8a7f90;cursor:pointer')}>{v.iEye}</div>
                    <div onClick={a.gen} title="Générer" style={sx('width:44px;height:44px;flex:none;border-radius:12px;background:#efe7fc;border:1.5px solid #e2d4f5;display:grid;place-items:center;color:#6b4fb8;cursor:pointer')}>{v.iRefresh}</div>
                  </div>
                  {a.hasStr && <div style={sx('display:flex;align-items:center;gap:10px;margin-top:9px')}>
                    <div style={sx('flex:1;height:5px;background:#f0eaf2;border-radius:999px;overflow:hidden')}><div style={sx(a.barFill)}></div></div>
                    <span style={sx(a.strStyle)}>{a.strLabel}</span>
                  </div>}
                </div>
              ))}
            </div>
          </div>
        </F>}

        {v.edShowAvatar && <F>
          <div style={sx('height:1px;background:#f2edf5')}></div>
          <div>
            <div style={sx('display:flex;align-items:center;justify-content:space-between;margin-bottom:11px')}>
              <div style={sx('display:flex;align-items:center;gap:9px')}><span style={sx(v.edSectionLabel)}>Codes 2FA (TOTP)</span><span style={sx("min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:#def3ec;color:#2e8f72;font:700 11px 'Sora';display:grid;place-items:center")}>{v.totpCount}</span></div>
              <div onClick={v.onAddTotp} style={sx('display:flex;align-items:center;gap:5px;border:1.5px dashed #bfe0d0;color:#2e8f72;border-radius:9px;padding:6px 11px;font-size:12px;font-weight:600;cursor:pointer')}>{v.iPlus} Ajouter</div>
            </div>
            <div style={sx('display:flex;flex-direction:column;gap:9px')}>
              {v.totpRows.map((t, i) => (
                <div key={i} style={sx('display:flex;gap:8px;align-items:center;background:#faf7fd;border-radius:12px;padding:10px 12px')}>
                  <Hv tag="input" value={t.issuer} onChange={t.onIssuer} placeholder="Émetteur" style={v.edInputStyle + ';background:#fff;flex:1'} focus="border-color:#6b4fb8" />
                  <Hv tag="input" value={t.code} onChange={t.onCode} placeholder="Clé / otpauth" style={v.edInputStyle + ';background:#fff;flex:1'} focus="border-color:#6b4fb8" />
                  <div onClick={t.remove} title="Retirer" style={sx('width:34px;height:34px;flex:none;border-radius:9px;display:grid;place-items:center;color:#c0716a;cursor:pointer;font-size:14px')}>{v.iTrash}</div>
                </div>
              ))}
            </div>
          </div>
        </F>}

        <div>
          <div style={sx(v.edLabelStyle)}>Notes</div>
          <Hv tag="textarea" value={v.form.notes} onChange={v.onNotes} placeholder="Notes chiffrées…" style={v.edInputStyle + ';min-height:70px;resize:vertical'} focus="border-color:#6b4fb8;background:#fff" />
        </div>
      </div>
      <div style={sx('padding:15px 28px 20px;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;flex:none;border-top:1px solid #f2edf5')}>
        <div onClick={v.onEditorClose} style={sx(v.edGhostBtn)}>Annuler</div>
        <div onClick={v.onEditorSubmit} style={sx(v.edPrimaryBtn)}>{v.edSubmit}</div>
      </div>
    </div>
  </div>}

  {/* ===================== OVERLAY IMPORT ===================== */}
  {v.importOpen && <div style={sx('position:absolute;inset:0;background:rgba(38,34,46,.74);backdrop-filter:blur(7px);display:flex;align-items:center;justify-content:center;z-index:55;padding:' + v.popPad + ';animation:scFade .18s ease')}>
    <div style={sx('background:#fff;border-radius:22px;width:900px;max-width:100%;max-height:100%;display:flex;flex-direction:column;border:1px solid #e4dce8;box-shadow:0 30px 70px -20px rgba(20,15,30,.6);overflow:hidden;animation:scPop .22s cubic-bezier(.2,.8,.25,1)')}>
      <div style={sx('padding:26px 30px 16px;position:relative;flex:none')}>
        <div style={sx('font-weight:800;font-size:22px;margin-bottom:5px')}>Importer des mots de passe</div>
        <div style={sx('font-size:13px;color:#a99fb0')}>{v.importStepLabel}</div>
        <div onClick={v.onImportClose} style={sx('position:absolute;top:22px;right:24px;width:34px;height:34px;border-radius:10px;background:#f3ecf3;display:grid;place-items:center;color:#8a7f90;font-size:15px;cursor:pointer')}>✕</div>
      </div>
      <div style={sx('padding:4px 30px 6px;overflow:auto;flex:1;min-height:0')}>
        {v.is1 && <F>
          <div style={sx('font-size:13px;color:#6a6070;line-height:1.5;margin-bottom:18px')}>Choisissez le service d'origine. CléPass adaptera automatiquement les correspondances de colonnes.</div>
          {/* DEUX colonnes et non trois : les intitulés d'export doivent tenir
              sur une seule ligne (« chrome://password-manager/passwords →
              Exporter » réclame 303 px de texte). Sur trois colonnes il aurait
              fallu un popup de ~1260 px, soit la largeur de l'écran. */}
          <div style={sx('display:grid;grid-template-columns:' + (v.mobile ? 'minmax(0,1fr)' : 'minmax(0,1fr) minmax(0,1fr)') + ';gap:12px')}>
            {v.importSources.map((s) => (
              <div key={s.name} style={sx(s.cardStyle)} onClick={s.onClick}>
                <div style={sx(s.tileStyle)}>{s.icon}</div>
                <div style={sx('min-width:0')}><div style={sx('font-weight:700;font-size:14.5px;margin-bottom:3px')}>{s.name}</div><div style={sx('font-size:11.5px;color:#a99fb0;line-height:1.4')}>{s.desc}</div></div>
              </div>
            ))}
          </div>
        </F>}
        {v.is2 && <F>
          <div style={sx('display:flex;align-items:center;gap:13px;background:#faf7fd;border-radius:14px;padding:14px 16px;margin-bottom:16px')}>
            <div style={sx(v.importSelTile)}>{v.importSelIcon}</div>
            <div><div style={sx('font-weight:700;font-size:14.5px')}>{v.importSelName}</div><div style={sx('font-size:11.5px;color:#a99fb0')}>{v.importSelDesc}</div></div>
          </div>
          <label onDrop={v.onImportDrop} onDragOver={v.onImportDragOver} onDragLeave={v.onImportDragLeave} style={sx(v.importDropStyle + 'display:block;cursor:pointer')}>
            <input type="file" accept=".csv,.json,.txt,text/csv,application/json" onChange={v.onImportFile} style={sx('display:none')} />
            <div style={sx('width:52px;height:52px;border-radius:14px;background:#efe7fc;color:#6b4fb8;display:grid;place-items:center;font-size:24px;margin:0 auto 12px')}>{v.iImport}</div>
            <div style={sx('font-weight:700;font-size:14px;margin-bottom:4px')}>Glissez le fichier exporté ici</div>
            <div style={sx('font-size:12px;color:#a99fb0;margin-bottom:14px')}>CSV ou JSON — le fichier est lu dans votre navigateur, rien n'est envoyé en clair</div>
            <div style={sx('display:inline-flex;padding:9px 18px;background:#6b4fb8;color:#fff;border-radius:10px;font-size:12.5px;font-weight:600;cursor:pointer')}>Parcourir…</div>
          </label>
          {v.importErr && <div style={sx('margin-top:12px;background:#fbe4e4;color:#c0392b;border-radius:10px;padding:10px 13px;font-size:12.5px;font-weight:600')}>{v.importErr}</div>}
        </F>}
        {v.is3 && <F>
          <div style={sx('display:flex;align-items:center;gap:10px;background:#eaf6ef;color:#2e8f72;border-radius:12px;padding:12px 15px;margin-bottom:6px;font-size:13px;font-weight:600')}><span style={sx('font-size:16px')}>{v.iShieldCheck}</span>{v.importNbEntrees} entrée(s) détectée(s) · les doublons seront ignorés</div>
          <div style={sx('font-size:11.5px;color:#a99fb0;margin:0 2px 16px')}>{v.importFormat}</div>
          <div style={sx('font-size:11px;color:#a99fb0;text-transform:uppercase;letter-spacing:.05em;margin:0 2px 10px')}>Correspondance des colonnes</div>
          <div style={sx('display:flex;flex-direction:column;gap:8px')}>
            {v.importMap.map((m, i) => (
              <div key={i} style={sx('display:flex;align-items:center;gap:12px;background:#faf7fd;border-radius:12px;padding:11px 15px')}>
                <span style={sx("font-size:12px;color:#8a7f90;flex:1;font-family:'IBM Plex Mono',ui-monospace,monospace")}>{m.from}</span>
                <span style={sx('color:#c2b8c8')}>→</span>
                <span style={sx('font-size:12.5px;font-weight:600;color:#3a3340;flex:1;text-align:right')}>{m.to}</span>
              </div>
            ))}
          </div>
        </F>}
      </div>
      <div style={sx('padding:16px 30px 22px;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;flex:none;border-top:1px solid #f2edf5')}>
        {v.importShowBack && <div onClick={v.onImportBack} style={sx('padding:11px 20px;border:1.5px solid #e4dce8;border-radius:12px;font-size:13px;font-weight:600;color:#6a6070;cursor:pointer')}>Retour</div>}
        <div onClick={v.onImportClose} style={sx('padding:11px 22px;border:1.5px solid #e4dce8;border-radius:12px;font-size:13px;font-weight:600;color:#6a6070;cursor:pointer')}>Annuler</div>
        <div onClick={v.onImportNext} style={sx(v.importNextStyle)}>{v.importNextLabel}</div>
      </div>
    </div>
  </div>}

</div>
</div>
  );
};
})();
